groke6@381: /*
groke6@381: This file is part of CanFestival, a library implementing CanOpen Stack. 
groke6@381: 
groke6@381: Copyright (C): Edouard TISSERANT and Francis DUPIN
groke6@381: 
groke6@381: See COPYING file for copyrights details.
groke6@381: 
groke6@381: This library is free software; you can redistribute it and/or
groke6@381: modify it under the terms of the GNU Lesser General Public
groke6@381: License as published by the Free Software Foundation; either
groke6@381: version 2.1 of the License, or (at your option) any later version.
groke6@381: 
groke6@381: This library is distributed in the hope that it will be useful,
groke6@381: but WITHOUT ANY WARRANTY; without even the implied warranty of
groke6@381: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
groke6@381: Lesser General Public License for more details.
groke6@381: 
groke6@381: You should have received a copy of the GNU Lesser General Public
groke6@381: License along with this library; if not, write to the Free Software
groke6@381: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
groke6@381: */
groke6@381: 
groke6@381: #if defined(WIN32) && !defined(__CYGWIN__)
groke6@381: #include <windows.h>
groke6@381: #include "getopt.h"
groke6@381: void pause(void)
groke6@381: {
groke6@381: 	system("PAUSE");
groke6@381: }
groke6@381: #else
groke6@381: #include <stdio.h>
groke6@381: #include <string.h>
groke6@381: #include <unistd.h>
groke6@381: #include <stdlib.h>
groke6@381: #include <signal.h>
groke6@381: #endif
groke6@381: 
groke6@381: #include "canfestival.h"
groke6@381: //#include <can_driver.h>
groke6@381: //#include <timers_driver.h>
groke6@381: 
groke6@381: #include "Master.h"
groke6@381: #include "SlaveA.h"
groke6@381: #include "SlaveB.h"
groke6@381: #include "TestMasterSlaveLSS.h"
groke6@381: 
groke6@381: s_BOARD SlaveBoardA = {"0", "125K"};
groke6@381: s_BOARD SlaveBoardB = {"1", "125K"};
groke6@381: s_BOARD MasterBoard = {"2", "125K"};
groke6@381: 
groke6@381: #if !defined(WIN32) || defined(__CYGWIN__)
groke6@381: void catch_signal(int sig)
groke6@381: {
groke6@381:   signal(SIGTERM, catch_signal);
groke6@381:   signal(SIGINT, catch_signal);
groke6@381:   eprintf("Got Signal %d\n",sig);
groke6@381: }
groke6@381: #endif
groke6@381: 
greg@454: void help(void)
groke6@381: {
groke6@381:   printf("**************************************************************\n");
groke6@387:   printf("*  TestMasterSlaveLSS                                        *\n");
groke6@387:   printf("*                                                            *\n");
groke6@387:   printf("*  A LSS example for PC. It does implement 3 CanOpen         *\n");
groke6@387:   printf("*  nodes in the same process. A master and 2 slaves. All     *\n");
groke6@381:   printf("*  communicate together, exchanging periodically NMT, SYNC,  *\n");
groke6@381:   printf("*  SDO and PDO. Master configure heartbeat producer time     *\n");
groke6@517:   printf("*  at 1000 ms for the slaves by concise DCF.                 *\n");                                  
groke6@381:   printf("*                                                            *\n");
groke6@381:   printf("*   Usage:                                                   *\n");
groke6@387:   printf("*   ./TestMasterSlaveLSS  [OPTIONS]                          *\n");
groke6@381:   printf("*                                                            *\n");
groke6@381:   printf("*   OPTIONS:                                                 *\n");
groke6@517:   printf("*     -l : Can library [\"libcanfestival_can_virtual.so\"]     *\n");
groke6@387:   printf("*                                                            *\n");
groke6@387:   printf("*    SlaveA:                                                 *\n");
groke6@517:   printf("*     -a : bus name [\"0\"]                                    *\n");
groke6@387:   printf("*     -A : 1M,500K,250K,125K,100K,50K,20K,10K,none(disable)  *\n");
groke6@387:   printf("*                                                            *\n");
groke6@517:   printf("*    SlaveB:                                                 *\n");
groke6@517:   printf("*     -b : bus name [\"1\"]                                    *\n");
groke6@387:   printf("*     -B : 1M,500K,250K,125K,100K,50K,20K,10K,none(disable)  *\n");
groke6@381:   printf("*                                                            *\n");
groke6@381:   printf("*    Master:                                                 *\n");
groke6@517:   printf("*     -m : bus name [\"2\"]                                    *\n");
groke6@381:   printf("*     -M : 1M,500K,250K,125K,100K,50K,20K,10K,none(disable)  *\n");
groke6@381:   printf("*                                                            *\n");
groke6@381:   printf("**************************************************************\n");
groke6@381: }
groke6@381: 
groke6@381: /***************************  INIT  *****************************************/
groke6@381: void InitNodes(CO_Data* d, UNS32 id)
groke6@381: {
groke6@381: 	/****************************** INITIALISATION SLAVE_A *******************************/
groke6@381: 	if(strcmp(SlaveBoardA.baudrate, "none")) {
groke6@381: 		/* Set an invalid nodeID */
groke6@381: 		setNodeId(&TestSlaveA_Data, 0xFF);
groke6@381: 
groke6@381: 		/* init */
groke6@381: 		setState(&TestSlaveA_Data, Initialisation);
groke6@381: 	}
groke6@381: 	
groke6@381: 	/****************************** INITIALISATION SLAVE_B *******************************/
groke6@381: 	if(strcmp(SlaveBoardB.baudrate, "none")) {
groke6@381: 
groke6@381: 		/* Set an invalid nodeID */
groke6@381: 		setNodeId(&TestSlaveB_Data, 0xFF);
groke6@381: 
groke6@381: 		/* init */
groke6@381: 		setState(&TestSlaveB_Data, Initialisation);
groke6@381: 	}
groke6@381: 
groke6@381: 	/****************************** INITIALISATION MASTER *******************************/
groke6@381: 	if(strcmp(MasterBoard.baudrate, "none")){
groke6@381: 		
groke6@381: 		/* Defining the node Id */
groke6@381: 		setNodeId(&TestMaster_Data, 0x01);
groke6@381: 
groke6@381: 		/* init */
groke6@381: 		setState(&TestMaster_Data, Initialisation);		
groke6@381: 	}
groke6@381: }
groke6@381: 
greg@454: /***************************  EXIT  *****************************************/
greg@454: void Exit(CO_Data* d, UNS32 id)
greg@454: {
greg@465: 	if(strcmp(MasterBoard.baudrate, "none")){
greg@454: 	eprintf("Finishing.\n");
greg@454: 	masterSendNMTstateChange (&TestMaster_Data, 0x00, NMT_Stop_Node);
greg@454: 
greg@454: 	eprintf("reset\n");
greg@454: 
greg@454: 	// Stop master
greg@454: 	setState(&TestMaster_Data, Stopped);
greg@465: 	}
greg@454: }
greg@454: 
groke6@381: /****************************************************************************/
groke6@381: /***************************  MAIN  *****************************************/
groke6@381: /****************************************************************************/
groke6@381: int main(int argc,char **argv)
groke6@381: {
groke6@381: 
groke6@381:   int c;
groke6@381:   extern char *optarg;
groke6@381:   char* LibraryPath="../../drivers/can_virtual/libcanfestival_can_virtual.so";
groke6@381: 
groke6@387:   while ((c = getopt(argc, argv, "-m:a:b:M:A:B:l:")) != EOF)
groke6@381:   {
groke6@381:     switch(c)
groke6@381:     {
groke6@387:       case 'a' :
groke6@381:         if (optarg[0] == 0)
groke6@381:         {
groke6@381:           help();
groke6@381:           exit(1);
groke6@381:         }
groke6@381:         SlaveBoardA.busname = optarg;
groke6@381:         break;
groke6@387:       case 'b' :
groke6@387:         if (optarg[0] == 0)
groke6@387:         {
groke6@387:           help();
groke6@387:           exit(1);
groke6@387:         }
groke6@387:         SlaveBoardB.busname = optarg;
groke6@387:         break;
groke6@381:       case 'm' :
groke6@381:         if (optarg[0] == 0)
groke6@381:         {
groke6@381:           help();
groke6@381:           exit(1);
groke6@381:         }
groke6@381:         MasterBoard.busname = optarg;
groke6@381:         break;
groke6@387:       case 'A' :
groke6@381:         if (optarg[0] == 0)
groke6@381:         {
groke6@381:           help();
groke6@381:           exit(1);
groke6@381:         }
groke6@381:         SlaveBoardA.baudrate = optarg;
groke6@381:         break;
groke6@387:       case 'B' :
groke6@387:         if (optarg[0] == 0)
groke6@387:         {
groke6@387:           help();
groke6@387:           exit(1);
groke6@387:         }
groke6@387:         SlaveBoardB.baudrate = optarg;
groke6@387:         break;
groke6@381:       case 'M' :
groke6@381:         if (optarg[0] == 0)
groke6@381:         {
groke6@381:           help();
groke6@381:           exit(1);
groke6@381:         }
groke6@381:         MasterBoard.baudrate = optarg;
groke6@381:         break;
groke6@381:       case 'l' :
groke6@381:         if (optarg[0] == 0)
groke6@381:         {
groke6@381:           help();
groke6@381:           exit(1);
groke6@381:         }
groke6@381:         LibraryPath = optarg;
groke6@381:         break;
groke6@381:       default:
groke6@381:         help();
groke6@381:         exit(1);
groke6@381:     }
groke6@381:   }
groke6@381: 
groke6@381: #if !defined(WIN32) || defined(__CYGWIN__)
groke6@381:   /* install signal handler for manual break */
groke6@381: 	signal(SIGTERM, catch_signal);
groke6@381: 	signal(SIGINT, catch_signal);
greg@454: 	TimerInit();
groke6@381: #endif
groke6@381: 
groke6@381: #ifndef NOT_USE_DYNAMIC_LOADING
groke6@381: 	if (LoadCanDriver(LibraryPath) == NULL)
groke6@381: 	    printf("Unable to load library: %s\n",LibraryPath);
groke6@381: #endif		
groke6@381: 	// Open CAN devices
groke6@381: 
groke6@381: 	if(strcmp(SlaveBoardA.baudrate, "none")){
groke6@381: 		
groke6@381: 		TestSlaveA_Data.heartbeatError = TestSlaveA_heartbeatError;
groke6@381: 		TestSlaveA_Data.initialisation = TestSlaveA_initialisation;
groke6@381: 		TestSlaveA_Data.preOperational = TestSlaveA_preOperational;
groke6@381: 		TestSlaveA_Data.operational = TestSlaveA_operational;
groke6@381: 		TestSlaveA_Data.stopped = TestSlaveA_stopped;
groke6@381: 		TestSlaveA_Data.post_sync = TestSlaveA_post_sync;
groke6@381: 		TestSlaveA_Data.post_TPDO = TestSlaveA_post_TPDO;
groke6@381: 		TestSlaveA_Data.storeODSubIndex = TestSlaveA_storeODSubIndex;
groke6@381: 		TestSlaveA_Data.post_emcy = TestSlaveA_post_emcy;
groke6@517: 		/* in this example the slave doesn't implement NMT_Slave_Communications_Reset_Callback */
groke6@517: 		//TestSlaveA_Data.NMT_Slave_Communications_Reset_Callback = TestSlaveA_NMT_Slave_Communications_Reset_Callback;
groke6@381: 		TestSlaveA_Data.lss_StoreConfiguration = TestSlaveA_StoreConfiguration;
groke6@381: 
groke6@381: 		if(!canOpen(&SlaveBoardA,&TestSlaveA_Data)){
groke6@381: 			eprintf("Cannot open SlaveA Board (%s,%s)\n",SlaveBoardA.busname, SlaveBoardA.baudrate);
groke6@381: 			goto fail_slaveA;
groke6@381: 		}
groke6@381: 	}
groke6@381: 	
groke6@381: 	if(strcmp(SlaveBoardB.baudrate, "none")){
groke6@381: 		
groke6@381: 		TestSlaveB_Data.heartbeatError = TestSlaveB_heartbeatError;
groke6@381: 		TestSlaveB_Data.initialisation = TestSlaveB_initialisation;
groke6@381: 		TestSlaveB_Data.preOperational = TestSlaveB_preOperational;
groke6@381: 		TestSlaveB_Data.operational = TestSlaveB_operational;
groke6@381: 		TestSlaveB_Data.stopped = TestSlaveB_stopped;
groke6@381: 		TestSlaveB_Data.post_sync = TestSlaveB_post_sync;
groke6@381: 		TestSlaveB_Data.post_TPDO = TestSlaveB_post_TPDO;
groke6@381: 		TestSlaveB_Data.storeODSubIndex = TestSlaveB_storeODSubIndex;
groke6@381: 		TestSlaveB_Data.post_emcy = TestSlaveB_post_emcy;
groke6@517: 		TestSlaveB_Data.NMT_Slave_Communications_Reset_Callback = TestSlaveB_NMT_Slave_Communications_Reset_Callback;
groke6@381: 		TestSlaveB_Data.lss_StoreConfiguration = TestSlaveB_StoreConfiguration;
groke6@381: 
groke6@381: 		if(!canOpen(&SlaveBoardB,&TestSlaveB_Data)){
groke6@381: 			eprintf("Cannot open SlaveB Board (%s,%s)\n",SlaveBoardB.busname, SlaveBoardB.baudrate);
groke6@381: 			goto fail_slaveB;
groke6@381: 		}
groke6@381: 	}
groke6@381: 	
groke6@381: 	if(strcmp(MasterBoard.baudrate, "none")){
groke6@381: 		
groke6@381: 		TestMaster_Data.heartbeatError = TestMaster_heartbeatError;
groke6@381: 		TestMaster_Data.initialisation = TestMaster_initialisation;
groke6@381: 		TestMaster_Data.preOperational = TestMaster_preOperational;
groke6@381: 		TestMaster_Data.operational = TestMaster_operational;
groke6@381: 		TestMaster_Data.stopped = TestMaster_stopped;
groke6@381: 		TestMaster_Data.post_sync = TestMaster_post_sync;
groke6@381: 		TestMaster_Data.post_TPDO = TestMaster_post_TPDO;
groke6@381: 		TestMaster_Data.post_emcy = TestMaster_post_emcy;
groke6@381: 		TestMaster_Data.post_SlaveBootup=TestMaster_post_SlaveBootup;
groke6@381: 		
groke6@381: 		if(!canOpen(&MasterBoard,&TestMaster_Data)){
groke6@381: 			eprintf("Cannot open Master Board (%s,%s)\n",MasterBoard.busname, MasterBoard.baudrate);
groke6@381: 			goto fail_master;
groke6@381: 		}
groke6@381: 	}
groke6@381: 
groke6@381: 	// Start timer thread
groke6@381: 	StartTimerLoop(&InitNodes);
groke6@381: 
groke6@381: 	// wait Ctrl-C
groke6@381: 	
groke6@381: 	pause();
groke6@381: 
groke6@381: 	// Stop timer thread
greg@454: 	StopTimerLoop(&Exit);
groke6@381: 	
groke6@381: 	// Close CAN devices (and can threads)
groke6@381: 	if(strcmp(MasterBoard.baudrate, "none")) canClose(&TestMaster_Data);	
groke6@381: fail_master:
groke6@381: 	if(strcmp(SlaveBoardB.baudrate, "none")) canClose(&TestSlaveB_Data);
groke6@381: fail_slaveB:
groke6@381: 	if(strcmp(SlaveBoardA.baudrate, "none")) canClose(&TestSlaveA_Data);
groke6@381: fail_slaveA:
greg@454: 	TimerCleanup();
groke6@381: 	return 0;
groke6@381: }