examples/win32test/main.c
author etisserant
Wed, 04 Apr 2007 13:04:31 +0200
changeset 145 e747d2e26af0
child 149 fe50ada8020b
permissions -rw-r--r--
Win32 Native support and dynamicaly loaded CAN drivers for Linux, Cygwin and Win32.
/**************************************************************************
CanFestival3 win32 port example

This sample demonstrates CanFestival usage with Win32

Program implements master node. It starts CANOpen slave node, modifies OD, 
performs SDO reads and prints some slave node information.

Usage:

    win32test <node_id>

  where node_id is node ID in decimal format

You should have CanFestival-3.dll CAN-uVCCM.dll in the search path to run this sample.
Code will work with non-UNICODE CanFestival-3.dll CAN-uVCCM.dll libraries.

Sample can work on other platdorms as well.

Copyright (C) 2007  Leonid Tochinski (ltochinski AT chattenassociates DOT com)
***************************************************************************/

#include <stdio.h>
#include <stdlib.h> 
#include "win32test.h"
#include "canfestival.h"

#ifdef WIN32
#define sleep_proc(ms) Sleep(ms)
#define uptime_ms_proc() GetTickCount()
#else
#include <time.h> 
#define sleep_proc(ms)
#define uptime_ms_proc (1000*(time()%86400))  // TOD
#endif

/* required canfestival callbacks. */
void win32test_SDOtimeoutError(UNS8 line)
  {
  }
  
void win32test_heartbeatError(UNS8 node_id)
  {
  }

void win32test_initialisation(void)
  {
  }

void win32test_preOperational(void)
  {
  }

void win32test_operational(void)
  {
  }

void win32test_stopped(void)
  {
  }

void win32test_post_sync(void)
  {
  }

void win32test_post_TPDO(void)
  {
  }

static CAN_HANDLE g_MasterCanHandle = NULL;

UNS8 win32test_canSend(Message *m)
  {
  if (g_MasterCanHandle != NULL)
     return canSend(g_MasterCanHandle, m);
  return 1;
  }

UNS8 GetChangeStateResults(UNS8 node_id, UNS8 expected_state, unsigned long timeout_ms)
   {
   unsigned long start_time = 0;
   
   // reset nodes state
   win32test_Data.NMTable[node_id] = Unknown_state;

   // request node state
   masterRequestNodeState(&win32test_Data, node_id);
   
   start_time = uptime_ms_proc();
   while(uptime_ms_proc() - start_time < timeout_ms)
      {
      if (getNodeState(&win32test_Data, node_id) == expected_state)
         return 0;
      sleep_proc(1);   
      }
   return 0xFF;
   }

UNS8 ReadSDO(UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, void* data, UNS8* size)
   {
   UNS32 abortCode = 0;
   UNS8 res = SDO_UPLOAD_IN_PROGRESS;
   // Read SDO
   UNS8 err = readNetworkDict (&win32test_Data, nodeId, index, subIndex, dataType);
   if (err)
      return 0xFF;
   for(;;)
      {
      res = getReadResultNetworkDict (&win32test_Data, nodeId, data, size, &abortCode);
      if (res != SDO_UPLOAD_IN_PROGRESS)
         break;   
      sleep_proc(1);
      continue;
      }
   closeSDOtransfer(&win32test_Data, nodeId, SDO_CLIENT);
   if (res == SDO_FINISHED)
      return 0;
   return 0xFF;   
   }

int main(int argc, char *argv[])
  {
   UNS8 node_id = 0;
   s_BOARD MasterBoard = {"1", "125K"};
   char* dll_file_name;

   /* process command line arguments */
   if (argc < 2)
      {
      printf("USAGE: win32test node_id [dll_file_name]\n");
      return 1;
      }

   node_id = atoi(argv[1]);
   if (node_id < 2 || node_id > 127)
      {
      printf("ERROR: node_id shoule be >=2 and <= 127\n");
      return 1;
      }

      if (argc > 2)
		dll_file_name = argv[2];
	  else
		dll_file_name = "can_uvccm_win32.dll";

   // load can driver
   if (!LoadCanDriver(dll_file_name))
      {
      printf("ERROR: could not load diver %s\n", dll_file_name);
      return 1;
      }
   
   g_MasterCanHandle = canOpen(&MasterBoard,&win32test_Data);
   
   if (g_MasterCanHandle)
      {
      /* Defining the node Id */
      setNodeId(&win32test_Data, 0x01);

      /* init */
      setState(&win32test_Data, Initialisation);

      /****************************** START *******************************/
      /* Put the master in operational mode */
      setState(&win32test_Data, Operational);

      /* Ask slave node to go in operational mode */
      masterSendNMTstateChange (&win32test_Data, 0, NMT_Start_Node);

      printf("\nStarting node %d (%xh) ...\n",(int)node_id,(int)node_id);
      
      /* wait untill mode will switch to operational state*/
      if (GetChangeStateResults(node_id, Operational, 3000) != 0xFF)
         {
         /* modify Client SDO 1 Parameter */
         UNS32 COB_ID_Client_to_Server_Transmit_SDO = 0x600 + node_id;
         UNS32 COB_ID_Server_to_Client_Receive_SDO  = 0x580 + node_id;
         UNS32 Node_ID_of_the_SDO_Server = node_id;
         UNS8 ExpectedSize = sizeof (UNS32);

         if (OD_SUCCESSFUL ==  setODentry(&win32test_Data, 0x1280, 1, &COB_ID_Client_to_Server_Transmit_SDO, &ExpectedSize, RW) 
              && OD_SUCCESSFUL ==  setODentry(&win32test_Data, 0x1280, 2, &COB_ID_Server_to_Client_Receive_SDO, &ExpectedSize, RW) 
              && OD_SUCCESSFUL ==  setODentry(&win32test_Data, 0x1280, 3, &Node_ID_of_the_SDO_Server, &ExpectedSize, RW))
            {
            UNS32 dev_type = 0;
            char device_name[64]="";
            char hw_ver[64]="";
            char sw_ver[64]="";   
            UNS32 vendor_id = 0;            
            UNS32 prod_code = 0;
            UNS32 ser_num = 0;
            UNS8 size;
            UNS8 res;

            printf("\nnode_id: %d (%xh) info\n",(int)node_id,(int)node_id);
            printf("********************************************\n");

            size = sizeof (dev_type);
            res = ReadSDO(node_id, 0x1000, 0, uint32, &dev_type, &size);
            printf("device type: %d\n",dev_type & 0xFFFF);
           
            size = sizeof (device_name);
            res = ReadSDO(node_id, 0x1008, 0, visible_string, device_name, &size);
            printf("device name: %s\n",device_name);

            size = sizeof (hw_ver);
            res = ReadSDO(node_id, 0x1009, 0, visible_string, hw_ver, &size);
            printf("HW version: %s\n",hw_ver);

            size = sizeof (sw_ver);
            res = ReadSDO(node_id, 0x100A, 0, visible_string, sw_ver, &size);
            printf("SW version: %s\n",sw_ver);            
            
            size = sizeof (vendor_id);
            res = ReadSDO(node_id, 0x1018, 1, uint32, &vendor_id, &size);
            printf("vendor id: %d\n",vendor_id);

            size = sizeof (prod_code);
            res = ReadSDO(node_id, 0x1018, 2, uint32, &prod_code, &size);
            printf("product code: %d\n",prod_code);

            size = sizeof (ser_num);
            res = ReadSDO(node_id, 0x1018, 4, uint32, &ser_num, &size);
            printf("serial number: %d\n",ser_num);
            
            printf("********************************************\n");
            } 
         else
            {
            printf("ERROR: Object dictionary access failed\n");
            }
         }
      else
         {
         printf("ERROR: node_id %d (%xh) is not responding\n",(int)node_id,(int)node_id);
         }
         
      masterSendNMTstateChange (&win32test_Data, 0x02, NMT_Stop_Node);

      setState(&win32test_Data, Stopped);
      
      canClose(g_MasterCanHandle);
      }
   return 0;
  }