etisserant@0: /*
etisserant@0: This file is part of CanFestival, a library implementing CanOpen Stack. 
etisserant@0: 
etisserant@0: Copyright (C): Edouard TISSERANT and Francis DUPIN
etisserant@0: 
etisserant@0: See COPYING file for copyrights details.
etisserant@0: 
etisserant@0: This library is free software; you can redistribute it and/or
etisserant@0: modify it under the terms of the GNU Lesser General Public
etisserant@0: License as published by the Free Software Foundation; either
etisserant@0: version 2.1 of the License, or (at your option) any later version.
etisserant@0: 
etisserant@0: This library is distributed in the hope that it will be useful,
etisserant@0: but WITHOUT ANY WARRANTY; without even the implied warranty of
etisserant@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
etisserant@0: Lesser General Public License for more details.
etisserant@0: 
etisserant@0: You should have received a copy of the GNU Lesser General Public
etisserant@0: License along with this library; if not, write to the Free Software
etisserant@0: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
etisserant@0: */
etisserant@0: 
etisserant@145: #if defined(WIN32) && !defined(__CYGWIN__)
etisserant@145: #include <windows.h>
etisserant@145: #include "getopt.h"
etisserant@145: void pause(void)
etisserant@145: {
etisserant@145: 	system("PAUSE");
etisserant@145: }
etisserant@145: #else
etisserant@0: #include <stdio.h>
etisserant@0: #include <string.h>
etisserant@169: #include <unistd.h>
etisserant@0: #include <stdlib.h>
etisserant@0: #include <signal.h>
etisserant@145: #endif
etisserant@0: 
etisserant@156: #include "canfestival.h"
etisserant@156: //#include <can_driver.h>
etisserant@156: //#include <timers_driver.h>
etisserant@0: 
etisserant@0: #include "Master.h"
etisserant@0: #include "Slave.h"
etisserant@0: #include "TestMasterSlave.h"
etisserant@0: 
etisserant@0: UNS32 OnMasterMap1Update(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex)
etisserant@0: {
greg@466: 	eprintf("OnMasterMap1Update:%d\n", MasterMap1);
lbessard@31: 	return 0;
etisserant@0: }
etisserant@0: 
greg@179: s_BOARD SlaveBoard = {"0", "125K"};
greg@179: s_BOARD MasterBoard = {"1", "125K"};
etisserant@145: 
etisserant@145: #if !defined(WIN32) || defined(__CYGWIN__)
etisserant@0: void catch_signal(int sig)
etisserant@0: {
etisserant@0:   signal(SIGTERM, catch_signal);
etisserant@0:   signal(SIGINT, catch_signal);
etisserant@32:   eprintf("Got Signal %d\n",sig);
etisserant@32: }
etisserant@145: #endif
etisserant@0: 
greg@454: void help(void)
etisserant@0: {
etisserant@0:   printf("**************************************************************\n");
etisserant@0:   printf("*  TestMasterSlave                                           *\n");
etisserant@0:   printf("*                                                            *\n");
etisserant@0:   printf("*  A simple example for PC. It does implement 2 CanOpen      *\n");
etisserant@0:   printf("*  nodes in the same process. A master and a slave. Both     *\n");
etisserant@36:   printf("*  communicate together, exchanging periodically NMT, SYNC,  *\n");
greg@179:   printf("*  SDO and PDO. Master configure heartbeat producer time     *\n");
greg@179:   printf("*  at 1000 ms for slave node-id 0x02 by concise DCF.         *\n");                                  
etisserant@36:   printf("*                                                            *\n");
etisserant@36:   printf("*   Usage:                                                   *\n");
etisserant@36:   printf("*   ./TestMasterSlave  [OPTIONS]                             *\n");
etisserant@36:   printf("*                                                            *\n");
etisserant@36:   printf("*   OPTIONS:                                                 *\n");
etisserant@145:   printf("*     -l : Can library [\"libcanfestival_can_virtual.so\"]     *\n");
etisserant@145:   printf("*                                                            *\n");
etisserant@36:   printf("*    Slave:                                                  *\n");
etisserant@36:   printf("*     -s : bus name [\"0\"]                                    *\n");
etisserant@36:   printf("*     -S : 1M,500K,250K,125K,100K,50K,20K,10K,none(disable)  *\n");
etisserant@36:   printf("*                                                            *\n");
etisserant@36:   printf("*    Master:                                                 *\n");
etisserant@36:   printf("*     -m : bus name [\"1\"]                                    *\n");
etisserant@36:   printf("*     -M : 1M,500K,250K,125K,100K,50K,20K,10K,none(disable)  *\n");
etisserant@0:   printf("*                                                            *\n");
etisserant@0:   printf("**************************************************************\n");
etisserant@0: }
etisserant@0: 
etisserant@36: /***************************  INIT  *****************************************/
etisserant@36: void InitNodes(CO_Data* d, UNS32 id)
etisserant@36: {
etisserant@36: 	/****************************** INITIALISATION SLAVE *******************************/
greg@179: 	if(strcmp(SlaveBoard.baudrate, "none")) {
etisserant@36: 		setNodeId(&TestSlave_Data, 0x02);
etisserant@343: 
etisserant@36: 		/* init */
etisserant@36: 		setState(&TestSlave_Data, Initialisation);
etisserant@36: 	}
etisserant@36: 
etisserant@36: 	/****************************** INITIALISATION MASTER *******************************/
greg@179: 	if(strcmp(MasterBoard.baudrate, "none")){
etisserant@36:  		RegisterSetODentryCallBack(&TestMaster_Data, 0x2000, 0, &OnMasterMap1Update);
greg@179: 		
etisserant@36: 		/* Defining the node Id */
etisserant@36: 		setNodeId(&TestMaster_Data, 0x01);
etisserant@36: 
etisserant@36: 		/* init */
etisserant@36: 		setState(&TestMaster_Data, Initialisation);
greg@179: 			
etisserant@36: 	}
etisserant@36: }
etisserant@36: 
greg@454: /***************************  EXIT  *****************************************/
greg@454: void Exit(CO_Data* d, UNS32 id)
greg@454: {
greg@465: 	if(strcmp(MasterBoard.baudrate, "none")){
greg@465: 		
greg@465: 		masterSendNMTstateChange(&TestMaster_Data, 0x02, NMT_Reset_Node);    
greg@454:     
greg@465:     	//Stop master
greg@465: 		setState(&TestMaster_Data, Stopped);
greg@465: 	}
greg@454: }
greg@454: 
etisserant@0: /****************************************************************************/
etisserant@0: /***************************  MAIN  *****************************************/
etisserant@0: /****************************************************************************/
etisserant@0: int main(int argc,char **argv)
etisserant@0: {
etisserant@0: 
etisserant@191:   int c;
etisserant@0:   extern char *optarg;
etisserant@343:   char* LibraryPath="../../drivers/can_virtual/libcanfestival_can_virtual.so";
etisserant@145: 
etisserant@145:   while ((c = getopt(argc, argv, "-m:s:M:S:l:")) != EOF)
etisserant@0:   {
etisserant@0:     switch(c)
etisserant@0:     {
etisserant@0:       case 's' :
etisserant@0:         if (optarg[0] == 0)
etisserant@0:         {
etisserant@0:           help();
etisserant@0:           exit(1);
etisserant@0:         }
etisserant@0:         SlaveBoard.busname = optarg;
etisserant@0:         break;
etisserant@0:       case 'm' :
etisserant@0:         if (optarg[0] == 0)
etisserant@0:         {
etisserant@0:           help();
etisserant@0:           exit(1);
etisserant@0:         }
etisserant@0:         MasterBoard.busname = optarg;
etisserant@0:         break;
etisserant@36:       case 'S' :
etisserant@36:         if (optarg[0] == 0)
etisserant@36:         {
etisserant@36:           help();
etisserant@36:           exit(1);
etisserant@36:         }
etisserant@145:         SlaveBoard.baudrate = optarg;
etisserant@36:         break;
etisserant@36:       case 'M' :
etisserant@36:         if (optarg[0] == 0)
etisserant@36:         {
etisserant@36:           help();
etisserant@36:           exit(1);
etisserant@36:         }
etisserant@145:         MasterBoard.baudrate = optarg;
etisserant@145:         break;
etisserant@145:       case 'l' :
etisserant@145:         if (optarg[0] == 0)
etisserant@145:         {
etisserant@145:           help();
etisserant@145:           exit(1);
etisserant@145:         }
etisserant@145:         LibraryPath = optarg;
etisserant@36:         break;
etisserant@0:       default:
etisserant@0:         help();
etisserant@0:         exit(1);
etisserant@0:     }
etisserant@0:   }
etisserant@0: 
etisserant@145: #if !defined(WIN32) || defined(__CYGWIN__)
etisserant@145:   /* install signal handler for manual break */
etisserant@0: 	signal(SIGTERM, catch_signal);
etisserant@0: 	signal(SIGINT, catch_signal);
greg@454: 	TimerInit();
etisserant@145: #endif
etisserant@145: 
etisserant@145: #ifndef NOT_USE_DYNAMIC_LOADING
etisserant@331: 	if (LoadCanDriver(LibraryPath) == NULL)
etisserant@331: 	    printf("Unable to load library: %s\n",LibraryPath);
etisserant@145: #endif		
etisserant@0: 	// Open CAN devices
greg@179: 
greg@179: 	if(strcmp(SlaveBoard.baudrate, "none")){
etisserant@149: 		
etisserant@149: 		TestSlave_Data.heartbeatError = TestSlave_heartbeatError;
etisserant@149: 		TestSlave_Data.initialisation = TestSlave_initialisation;
etisserant@149: 		TestSlave_Data.preOperational = TestSlave_preOperational;
etisserant@149: 		TestSlave_Data.operational = TestSlave_operational;
etisserant@149: 		TestSlave_Data.stopped = TestSlave_stopped;
etisserant@149: 		TestSlave_Data.post_sync = TestSlave_post_sync;
etisserant@149: 		TestSlave_Data.post_TPDO = TestSlave_post_TPDO;
luis@284: 		TestSlave_Data.storeODSubIndex = TestSlave_storeODSubIndex;
luis@284: 		TestSlave_Data.post_emcy = TestSlave_post_emcy;
etisserant@149: 
etisserant@149: 		if(!canOpen(&SlaveBoard,&TestSlave_Data)){
etisserant@145: 			eprintf("Cannot open Slave Board (%s,%s)\n",SlaveBoard.busname, SlaveBoard.baudrate);
etisserant@145: 			goto fail_slave;
etisserant@145: 		}
etisserant@145: 	}
greg@179: 	if(strcmp(MasterBoard.baudrate, "none")){
etisserant@149: 		
etisserant@149: 		TestMaster_Data.heartbeatError = TestMaster_heartbeatError;
etisserant@149: 		TestMaster_Data.initialisation = TestMaster_initialisation;
etisserant@149: 		TestMaster_Data.preOperational = TestMaster_preOperational;
etisserant@149: 		TestMaster_Data.operational = TestMaster_operational;
etisserant@149: 		TestMaster_Data.stopped = TestMaster_stopped;
etisserant@149: 		TestMaster_Data.post_sync = TestMaster_post_sync;
etisserant@149: 		TestMaster_Data.post_TPDO = TestMaster_post_TPDO;
luis@284: 		TestMaster_Data.post_emcy = TestMaster_post_emcy;
etisserant@343: 		TestMaster_Data.post_SlaveBootup=TestMaster_post_SlaveBootup;
etisserant@149: 		
etisserant@149: 		if(!canOpen(&MasterBoard,&TestMaster_Data)){
greg@179: 			eprintf("Cannot open Master Board (%s,%s)\n",MasterBoard.busname, MasterBoard.baudrate);
etisserant@145: 			goto fail_master;
etisserant@145: 		}
etisserant@145: 	}
etisserant@194: 
etisserant@32: 	// Start timer thread
etisserant@32: 	StartTimerLoop(&InitNodes);
etisserant@32: 
etisserant@32: 	// wait Ctrl-C
etisserant@32: 	pause();
etisserant@262: 
etisserant@32: 	// Stop timer thread
greg@454: 	StopTimerLoop(&Exit);
etisserant@32: 	
etisserant@32: 	// Close CAN devices (and can threads)
greg@454: 	if(strcmp(MasterBoard.baudrate, "none")) canClose(&TestMaster_Data);	
greg@454: fail_master:
greg@179: 	if(strcmp(SlaveBoard.baudrate, "none")) canClose(&TestSlave_Data);
etisserant@36: fail_slave:
greg@454: 	TimerCleanup();
greg@179: 	return 0;
greg@179: }