leonid@255: /*
leonid@255: This file is part of CanFestival, a library implementing CanOpen Stack.
leonid@255: 
leonid@255: CanFestival Copyright (C): Edouard TISSERANT and Francis DUPIN
leonid@255: CanFestival Win32 port Copyright (C) 2007 Leonid Tochinski, ChattenAssociates, Inc.
leonid@255: 
leonid@255: See COPYING file for copyrights details.
leonid@255: 
leonid@255: This library is free software; you can redistribute it and/or
leonid@255: modify it under the terms of the GNU Lesser General Public
leonid@255: License as published by the Free Software Foundation; either
leonid@255: version 2.1 of the License, or (at your option) any later version.
leonid@255: 
leonid@255: This library is distributed in the hope that it will be useful,
leonid@255: but WITHOUT ANY WARRANTY; without even the implied warranty of
leonid@255: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
leonid@255: Lesser General Public License for more details.
leonid@255: 
leonid@255: You should have received a copy of the GNU Lesser General Public
leonid@255: License along with this library; if not, write to the Free Software
leonid@255: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
leonid@255: */
leonid@255: 
etisserant@145: /**************************************************************************
etisserant@145: CanFestival3 win32 port example
etisserant@145: 
etisserant@145: This sample demonstrates CanFestival usage with Win32
etisserant@145: 
etisserant@145: Program implements master node. It starts CANOpen slave node, modifies OD, 
etisserant@145: performs SDO reads and prints some slave node information.
etisserant@145: 
etisserant@145: Usage:
etisserant@145: 
leonid@256:    win32test <node_id> [can driver dll filename [baud rate]]
leonid@256: 
leonid@256:  where node_id is node_id in decimal format
leonid@256: 
leonid@256: If driver is not specified, CAN-uVCCM.dll will be used by default.
leonid@256: If baudrate is not specified, 125K will be used by default.
leonid@256: You should have CanFestival-3.dll can driver dll in the search path to run this sample.
etisserant@145: 
etisserant@145: Sample can work on other platdorms as well.
etisserant@145: ***************************************************************************/
etisserant@145: 
etisserant@145: #include <stdio.h>
etisserant@145: #include <stdlib.h> 
etisserant@145: #include "win32test.h"
etisserant@145: #include "canfestival.h"
etisserant@145: 
etisserant@145: #ifdef WIN32
etisserant@145: #define sleep_proc(ms) Sleep(ms)
etisserant@145: #define uptime_ms_proc() GetTickCount()
etisserant@145: #else
etisserant@145: #include <time.h> 
etisserant@145: #define sleep_proc(ms)
etisserant@145: #define uptime_ms_proc (1000*(time()%86400))  // TOD
etisserant@145: #endif
etisserant@145: 
etisserant@145: UNS8 GetChangeStateResults(UNS8 node_id, UNS8 expected_state, unsigned long timeout_ms)
etisserant@145:    {
etisserant@145:    unsigned long start_time = 0;
etisserant@145:    
etisserant@145:    // reset nodes state
etisserant@145:    win32test_Data.NMTable[node_id] = Unknown_state;
etisserant@145: 
etisserant@145:    // request node state
etisserant@145:    masterRequestNodeState(&win32test_Data, node_id);
etisserant@145:    
etisserant@145:    start_time = uptime_ms_proc();
etisserant@145:    while(uptime_ms_proc() - start_time < timeout_ms)
etisserant@145:       {
etisserant@145:       if (getNodeState(&win32test_Data, node_id) == expected_state)
etisserant@145:          return 0;
etisserant@145:       sleep_proc(1);   
etisserant@145:       }
etisserant@145:    return 0xFF;
etisserant@145:    }
etisserant@145: 
etisserant@145: UNS8 ReadSDO(UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, void* data, UNS8* size)
etisserant@145:    {
etisserant@145:    UNS32 abortCode = 0;
etisserant@145:    UNS8 res = SDO_UPLOAD_IN_PROGRESS;
etisserant@145:    // Read SDO
etisserant@145:    UNS8 err = readNetworkDict (&win32test_Data, nodeId, index, subIndex, dataType);
etisserant@145:    if (err)
etisserant@145:       return 0xFF;
etisserant@145:    for(;;)
etisserant@145:       {
etisserant@145:       res = getReadResultNetworkDict (&win32test_Data, nodeId, data, size, &abortCode);
etisserant@145:       if (res != SDO_UPLOAD_IN_PROGRESS)
etisserant@145:          break;   
etisserant@145:       sleep_proc(1);
etisserant@145:       continue;
etisserant@145:       }
etisserant@145:    closeSDOtransfer(&win32test_Data, nodeId, SDO_CLIENT);
etisserant@145:    if (res == SDO_FINISHED)
etisserant@145:       return 0;
etisserant@145:    return 0xFF;   
etisserant@145:    }
etisserant@145: 
etisserant@145: int main(int argc, char *argv[])
etisserant@145:   {
etisserant@145:    UNS8 node_id = 0;
etisserant@145:    s_BOARD MasterBoard = {"1", "125K"};
etisserant@145:    char* dll_file_name;
etisserant@145: 
etisserant@145:    /* process command line arguments */
etisserant@145:    if (argc < 2)
etisserant@145:       {
leonid@256:       printf("USAGE: win32test <node_id> [can driver dll filename [baud rate]]\n");
etisserant@145:       return 1;
etisserant@145:       }
etisserant@145: 
etisserant@145:    node_id = atoi(argv[1]);
etisserant@145:    if (node_id < 2 || node_id > 127)
etisserant@145:       {
etisserant@145:       printf("ERROR: node_id shoule be >=2 and <= 127\n");
etisserant@145:       return 1;
etisserant@145:       }
etisserant@145: 
leonid@256:    if (argc > 2)
leonid@256:       dll_file_name = argv[2];
leonid@256:    else
leonid@256:       dll_file_name = "can_uvccm_win32.dll";
leonid@256: 
leonid@256:    if (argc > 3)
leonid@256:       MasterBoard.baudrate = argv[3];
etisserant@145: 
etisserant@145:    // load can driver
etisserant@145:    if (!LoadCanDriver(dll_file_name))
etisserant@145:       {
etisserant@145:       printf("ERROR: could not load diver %s\n", dll_file_name);
etisserant@145:       return 1;
etisserant@145:       }
etisserant@145:    
etisserant@149:    if (canOpen(&MasterBoard,&win32test_Data))
etisserant@145:       {
etisserant@145:       /* Defining the node Id */
etisserant@145:       setNodeId(&win32test_Data, 0x01);
etisserant@145: 
etisserant@145:       /* init */
etisserant@145:       setState(&win32test_Data, Initialisation);
etisserant@145: 
etisserant@145:       /****************************** START *******************************/
etisserant@145:       /* Put the master in operational mode */
etisserant@145:       setState(&win32test_Data, Operational);
etisserant@145: 
etisserant@145:       /* Ask slave node to go in operational mode */
etisserant@145:       masterSendNMTstateChange (&win32test_Data, 0, NMT_Start_Node);
etisserant@145: 
etisserant@145:       printf("\nStarting node %d (%xh) ...\n",(int)node_id,(int)node_id);
etisserant@145:       
etisserant@145:       /* wait untill mode will switch to operational state*/
etisserant@145:       if (GetChangeStateResults(node_id, Operational, 3000) != 0xFF)
etisserant@145:          {
etisserant@145:          /* modify Client SDO 1 Parameter */
etisserant@145:          UNS32 COB_ID_Client_to_Server_Transmit_SDO = 0x600 + node_id;
etisserant@145:          UNS32 COB_ID_Server_to_Client_Receive_SDO  = 0x580 + node_id;
etisserant@145:          UNS32 Node_ID_of_the_SDO_Server = node_id;
etisserant@145:          UNS8 ExpectedSize = sizeof (UNS32);
etisserant@145: 
etisserant@175:          if (OD_SUCCESSFUL ==  writeLocalDict(&win32test_Data, 0x1280, 1, &COB_ID_Client_to_Server_Transmit_SDO, &ExpectedSize, RW) 
etisserant@175:               && OD_SUCCESSFUL ==  writeLocalDict(&win32test_Data, 0x1280, 2, &COB_ID_Server_to_Client_Receive_SDO, &ExpectedSize, RW) 
etisserant@175:               && OD_SUCCESSFUL ==  writeLocalDict(&win32test_Data, 0x1280, 3, &Node_ID_of_the_SDO_Server, &ExpectedSize, RW))
etisserant@145:             {
etisserant@145:             UNS32 dev_type = 0;
etisserant@145:             char device_name[64]="";
etisserant@145:             char hw_ver[64]="";
etisserant@145:             char sw_ver[64]="";   
etisserant@145:             UNS32 vendor_id = 0;            
etisserant@145:             UNS32 prod_code = 0;
etisserant@145:             UNS32 ser_num = 0;
etisserant@145:             UNS8 size;
etisserant@145:             UNS8 res;
etisserant@145: 
etisserant@145:             printf("\nnode_id: %d (%xh) info\n",(int)node_id,(int)node_id);
etisserant@145:             printf("********************************************\n");
etisserant@145: 
etisserant@145:             size = sizeof (dev_type);
etisserant@145:             res = ReadSDO(node_id, 0x1000, 0, uint32, &dev_type, &size);
etisserant@145:             printf("device type: %d\n",dev_type & 0xFFFF);
etisserant@145:            
etisserant@145:             size = sizeof (device_name);
etisserant@145:             res = ReadSDO(node_id, 0x1008, 0, visible_string, device_name, &size);
etisserant@145:             printf("device name: %s\n",device_name);
etisserant@145: 
etisserant@145:             size = sizeof (hw_ver);
etisserant@145:             res = ReadSDO(node_id, 0x1009, 0, visible_string, hw_ver, &size);
etisserant@145:             printf("HW version: %s\n",hw_ver);
etisserant@145: 
etisserant@145:             size = sizeof (sw_ver);
etisserant@145:             res = ReadSDO(node_id, 0x100A, 0, visible_string, sw_ver, &size);
etisserant@145:             printf("SW version: %s\n",sw_ver);            
etisserant@145:             
etisserant@145:             size = sizeof (vendor_id);
etisserant@145:             res = ReadSDO(node_id, 0x1018, 1, uint32, &vendor_id, &size);
etisserant@145:             printf("vendor id: %d\n",vendor_id);
etisserant@145: 
etisserant@145:             size = sizeof (prod_code);
etisserant@145:             res = ReadSDO(node_id, 0x1018, 2, uint32, &prod_code, &size);
etisserant@145:             printf("product code: %d\n",prod_code);
etisserant@145: 
etisserant@145:             size = sizeof (ser_num);
etisserant@145:             res = ReadSDO(node_id, 0x1018, 4, uint32, &ser_num, &size);
etisserant@145:             printf("serial number: %d\n",ser_num);
etisserant@145:             
etisserant@145:             printf("********************************************\n");
etisserant@145:             } 
etisserant@145:          else
etisserant@145:             {
etisserant@145:             printf("ERROR: Object dictionary access failed\n");
etisserant@145:             }
etisserant@145:          }
etisserant@145:       else
etisserant@145:          {
etisserant@145:          printf("ERROR: node_id %d (%xh) is not responding\n",(int)node_id,(int)node_id);
etisserant@145:          }
etisserant@145:          
etisserant@145:       masterSendNMTstateChange (&win32test_Data, 0x02, NMT_Stop_Node);
etisserant@145: 
etisserant@145:       setState(&win32test_Data, Stopped);
etisserant@145:       
etisserant@149:       canClose(&win32test_Data);
etisserant@145:       }
etisserant@145:    return 0;
etisserant@145:   }
etisserant@145:   
etisserant@145: