etisserant@166: /* etisserant@166: This file is part of CanFestival, a library implementing CanOpen Stack. etisserant@166: etisserant@166: Copyright (C): Edouard TISSERANT and Francis DUPIN etisserant@166: etisserant@166: See COPYING file for copyrights details. etisserant@166: etisserant@166: This library is free software; you can redistribute it and/or etisserant@166: modify it under the terms of the GNU Lesser General Public etisserant@166: License as published by the Free Software Foundation; either etisserant@166: version 2.1 of the License, or (at your option) any later version. etisserant@166: etisserant@166: This library is distributed in the hope that it will be useful, etisserant@166: but WITHOUT ANY WARRANTY; without even the implied warranty of etisserant@166: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU etisserant@166: Lesser General Public License for more details. etisserant@166: etisserant@166: You should have received a copy of the GNU Lesser General Public etisserant@166: License along with this library; if not, write to the Free Software etisserant@166: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA etisserant@166: */ etisserant@166: etisserant@166: #if defined(WIN32) && !defined(__CYGWIN__) etisserant@166: #include etisserant@166: #include "getopt.h" etisserant@166: void pause(void) etisserant@166: { etisserant@166: system("PAUSE"); etisserant@166: } etisserant@166: #else etisserant@166: #include etisserant@166: #include etisserant@166: #include etisserant@166: #include etisserant@166: #endif etisserant@166: etisserant@166: #include "canfestival.h" etisserant@166: #include "TestMasterMicroMod.h" etisserant@166: #include "TestMaster.h" etisserant@166: UNS8 slavenodeid; etisserant@166: etisserant@166: etisserant@166: /*****************************************************************************/ etisserant@166: void TestMaster_heartbeatError(UNS8 heartbeatID) etisserant@166: { etisserant@166: eprintf("TestMaster_heartbeatError %d\n", heartbeatID); etisserant@166: } etisserant@166: etisserant@166: /*****************************************************************************/ etisserant@166: void TestMaster_SDOtimeoutError (UNS8 line) etisserant@166: { etisserant@166: eprintf("TestMaster_SDOtimeoutError %d\n", line); etisserant@166: } etisserant@166: etisserant@166: /******************************************************** etisserant@166: * ConfigureSlaveNode is responsible to etisserant@166: * - setup master RPDO 1 to receive TPDO 1 from id 0x40 etisserant@166: * - setup master TPDO 1 to send RPDO 1 to id 0x40 etisserant@166: ********************************************************/ etisserant@166: void TestMaster_initialisation() etisserant@166: { etisserant@166: UNS32 PDO1_COBID = 0x0180 + slavenodeid; etisserant@166: UNS32 PDO2_COBID = 0x0200 + slavenodeid; etisserant@166: UNS8 size = sizeof(UNS32); etisserant@166: etisserant@166: eprintf("TestMaster_initialisation\n"); etisserant@166: etisserant@166: /***************************************** etisserant@166: * Define RPDOs to match slave ID=0x40 TPDOs* etisserant@166: *****************************************/ etisserant@166: setODentry( &TestMaster_Data, /*CO_Data* d*/ etisserant@166: 0x1400, /*UNS16 index*/ etisserant@166: 0x01, /*UNS8 subind*/ etisserant@166: &PDO1_COBID, /*void * pSourceData,*/ etisserant@166: &size, /* UNS8 * pExpectedSize*/ etisserant@166: RW); /* UNS8 checkAccess */ etisserant@166: etisserant@166: etisserant@166: /***************************************** etisserant@166: * Define TPDOs to match slave ID=0x40 RPDOs* etisserant@166: *****************************************/ etisserant@166: setODentry( &TestMaster_Data, /*CO_Data* d*/ etisserant@166: 0x1800, /*UNS16 index*/ etisserant@166: 0x01, /*UNS8 subind*/ etisserant@166: &PDO2_COBID, /*void * pSourceData,*/ etisserant@166: &size, /* UNS8 * pExpectedSize*/ etisserant@166: RW); /* UNS8 checkAccess */ etisserant@166: } etisserant@166: etisserant@166: /******************************************************** etisserant@166: * ConfigureSlaveNode is responsible to etisserant@166: * - setup slave TPDO 1 transmit time etisserant@166: * - setup slave TPDO 2 transmit time etisserant@166: * - setup slave Heartbeat Producer time etisserant@166: * - switch to operational mode etisserant@166: * - send NMT to slave etisserant@166: ******************************************************** etisserant@166: * This an example of : etisserant@166: * Network Dictionary Access (SDO) with Callback etisserant@166: * Slave node state change request (NMT) etisserant@166: ******************************************************** etisserant@166: * This is called first by TestMaster_preOperational etisserant@166: * then it called again each time a SDO exchange is etisserant@166: * finished. etisserant@166: ********************************************************/ etisserant@166: static void ConfigureSlaveNode(CO_Data* d, UNS8 nodeId) etisserant@166: { etisserant@166: // Step counts number of times ConfigureSlaveNode is called etisserant@166: static step = 1; etisserant@166: etisserant@166: UNS8 Transmission_Type = 0x01; etisserant@166: UNS16 Heartbeat_Producer_Time = 0x03E8; etisserant@166: UNS32 abortCode; etisserant@166: UNS8 res; etisserant@166: eprintf("Master : ConfigureSlaveNode %2.2x\n", nodeId); etisserant@166: switch(step++){ etisserant@166: case 1: /*First step : setup Slave's TPDO 1 to be transmitted on SYNC*/ etisserant@166: eprintf("Master : set slave %2.2x TPDO 1 transmit type\n", nodeId); etisserant@166: res = writeNetworkDictCallBack (d, /*CO_Data* d*/ etisserant@166: /**TestSlave_Data.bDeviceNodeId, UNS8 nodeId*/ etisserant@166: nodeId, /*UNS8 nodeId*/ etisserant@166: 0x1800, /*UNS16 index*/ etisserant@166: 0x02, /*UNS8 subindex*/ etisserant@166: 1, /*UNS8 count*/ etisserant@166: 0, /*UNS8 dataType*/ etisserant@166: &Transmission_Type,/*void *data*/ etisserant@166: ConfigureSlaveNode); /*SDOCallback_t Callback*/ etisserant@166: break; etisserant@166: etisserant@166: etisserant@166: case 2: /*Second step*/ etisserant@166: if(getWriteResultNetworkDict (d, slavenodeid, &abortCode) != SDO_FINISHED) etisserant@166: eprintf("Master : Couldn't set slave %2.2x TPDO 1 transmit type. AbortCode :%4.4x \n", nodeId, abortCode); etisserant@166: etisserant@166: /* Finalise last SDO transfer with this node */ etisserant@166: closeSDOtransfer(&TestMaster_Data, etisserant@166: /**TestSlave_Data.bDeviceNodeId, UNS8 nodeId*/ etisserant@166: slavenodeid, /*UNS8 nodeId*/ etisserant@166: SDO_CLIENT); etisserant@166: etisserant@166: eprintf("Master : set slave %2.2x RPDO 1 receive type\n", nodeId); etisserant@166: res = writeNetworkDictCallBack (d, /*CO_Data* d*/ etisserant@166: /**TestSlave_Data.bDeviceNodeId, UNS8 nodeId*/ etisserant@166: slavenodeid, /*UNS8 nodeId*/ etisserant@166: 0x1400, /*UNS16 index*/ etisserant@166: 0x02, /*UNS8 subindex*/ etisserant@166: 1, /*UNS8 count*/ etisserant@166: 0, /*UNS8 dataType*/ etisserant@166: &Transmission_Type,/*void *data*/ etisserant@166: ConfigureSlaveNode); /*SDOCallback_t Callback*/ etisserant@166: break; etisserant@166: etisserant@166: case 3: /*Second step*/ etisserant@166: if(getWriteResultNetworkDict (d, slavenodeid, &abortCode) != SDO_FINISHED) etisserant@166: eprintf("Master : Couldn't set slave %2.2x RPDO 1 transmit type. AbortCode :%4.4x \n", nodeId, abortCode); etisserant@166: etisserant@166: /* Finalise last SDO transfer with this node */ etisserant@166: closeSDOtransfer(&TestMaster_Data, etisserant@166: /**TestSlave_Data.bDeviceNodeId, UNS8 nodeId*/ etisserant@166: slavenodeid, /*UNS8 nodeId*/ etisserant@166: SDO_CLIENT); etisserant@166: etisserant@166: eprintf("Master : set slave %2.2x heartbeat producer time \n", nodeId); etisserant@166: res = writeNetworkDictCallBack (d, /*CO_Data* d*/ etisserant@166: /**TestSlave_Data.bDeviceNodeId, UNS8 nodeId*/ etisserant@166: slavenodeid, /*UNS8 nodeId*/ etisserant@166: 0x1017, /*UNS16 index*/ etisserant@166: 0x00, /*UNS8 subindex*/ etisserant@166: 2, /*UNS8 count*/ etisserant@166: 0, /*UNS8 dataType*/ etisserant@166: &Heartbeat_Producer_Time,/*void *data*/ etisserant@166: ConfigureSlaveNode); /*SDOCallback_t Callback*/ etisserant@166: break; etisserant@166: etisserant@166: case 4: /*Second step*/ etisserant@166: etisserant@166: if(getWriteResultNetworkDict (d, slavenodeid, &abortCode) != SDO_FINISHED) etisserant@166: eprintf("Master : Couldn't set slave %2.2x Heartbeat_Producer_Time. AbortCode :%4.4x \n", nodeId, abortCode); etisserant@166: etisserant@166: /* Finalise last SDO transfer with this node */ etisserant@166: closeSDOtransfer(&TestMaster_Data, etisserant@166: /**TestSlave_Data.bDeviceNodeId, UNS8 nodeId*/ etisserant@166: slavenodeid, /*UNS8 nodeId*/ etisserant@166: SDO_CLIENT); etisserant@166: etisserant@166: /* Put the master in operational mode */ etisserant@166: setState(d, Operational); etisserant@166: etisserant@166: /* Ask slave node to go in operational mode */ etisserant@166: masterSendNMTstateChange (d, slavenodeid, NMT_Start_Node); etisserant@166: } etisserant@166: etisserant@166: } etisserant@166: etisserant@166: void TestMaster_preOperational() etisserant@166: { etisserant@166: etisserant@166: eprintf("TestMaster_preOperational\n"); etisserant@166: ConfigureSlaveNode(&TestMaster_Data, slavenodeid); etisserant@166: etisserant@166: } etisserant@166: etisserant@166: void TestMaster_operational() etisserant@166: { etisserant@166: eprintf("TestMaster_operational\n"); etisserant@166: } etisserant@166: etisserant@166: void TestMaster_stopped() etisserant@166: { etisserant@166: eprintf("TestMaster_stopped\n"); etisserant@166: } etisserant@166: etisserant@166: void TestMaster_post_sync() etisserant@166: { etisserant@166: DO++; etisserant@166: eprintf("MicroMod Digital Out: %2.2x In: %2.2d\n",DO,DI); etisserant@166: } etisserant@166: etisserant@166: void TestMaster_post_TPDO() etisserant@166: { etisserant@166: // eprintf("TestMaster_post_TPDO\n"); etisserant@166: } etisserant@166: etisserant@166: //s_BOARD SlaveBoard = {"0", "500K"}; etisserant@166: s_BOARD MasterBoard = {"32", "125K"}; etisserant@166: etisserant@166: #if !defined(WIN32) || defined(__CYGWIN__) etisserant@166: void catch_signal(int sig) etisserant@166: { etisserant@166: signal(SIGTERM, catch_signal); etisserant@166: signal(SIGINT, catch_signal); etisserant@166: etisserant@166: eprintf("Got Signal %d\n",sig); etisserant@166: } etisserant@166: #endif etisserant@166: etisserant@166: void help() etisserant@166: { etisserant@166: printf("**************************************************************\n"); etisserant@166: printf("* TestMasterMicroMod *\n"); etisserant@166: printf("* *\n"); etisserant@166: printf("* A simple example for PC. *\n"); etisserant@166: printf("* A CanOpen master that control a MicroMod module: *\n"); etisserant@166: printf("* - setup module TPDO 1 transmit type (ignored ???) *\n"); etisserant@166: printf("* - setup module RPDO 1 transmit type (ignored ???) *\n"); etisserant@166: printf("* - setup module hearbeatbeat period *\n"); etisserant@166: printf("* - set state to operational *\n"); etisserant@166: printf("* - send periodic SYNC (ignored ???) *\n"); etisserant@166: printf("* - send periodic RPDO 1 to Micromod (digital output) *\n"); etisserant@166: printf("* - listen Micromod's TPDO 1 (digital input) *\n"); etisserant@166: printf("* *\n"); etisserant@166: printf("* Usage: *\n"); etisserant@166: printf("* ./TestMasterMicroMod [OPTIONS] *\n"); etisserant@166: printf("* *\n"); etisserant@166: printf("* OPTIONS: *\n"); etisserant@166: printf("* -l : Can library [\"libcanfestival_can_virtual.so\"] *\n"); etisserant@166: printf("* *\n"); etisserant@166: printf("* Slave: *\n"); etisserant@166: printf("* -i : Slave Node id format [0x01 , 0x7F] *\n"); etisserant@166: printf("* *\n"); etisserant@166: printf("* Master: *\n"); etisserant@166: printf("* -m : bus name [\"1\"] *\n"); etisserant@166: printf("* -M : 1M,500K,250K,125K,100K,50K,20K,10K,none(disable) *\n"); etisserant@166: printf("* *\n"); etisserant@166: printf("**************************************************************\n"); etisserant@166: } etisserant@166: etisserant@166: /*************************** INIT *****************************************/ etisserant@166: void InitNodes(CO_Data* d, UNS32 id) etisserant@166: { etisserant@166: /****************************** INITIALISATION MASTER *******************************/ etisserant@166: if(MasterBoard.baudrate){ etisserant@166: /* Defining the node Id */ etisserant@166: setNodeId(&TestMaster_Data, 0x01); etisserant@166: etisserant@166: /* init */ etisserant@166: setState(&TestMaster_Data, Initialisation); etisserant@166: } etisserant@166: } etisserant@166: etisserant@166: /****************************************************************************/ etisserant@166: /*************************** MAIN *****************************************/ etisserant@166: /****************************************************************************/ etisserant@166: int main(int argc,char **argv) etisserant@166: { etisserant@166: etisserant@166: char c; etisserant@166: extern char *optarg; etisserant@166: char* LibraryPath="libcanfestival_can_virtual.so"; etisserant@166: char *snodeid; etisserant@166: while ((c = getopt(argc, argv, "-m:s:M:S:l:i:")) != EOF) etisserant@166: { etisserant@166: switch(c) etisserant@166: { etisserant@166: case 'm' : etisserant@166: if (optarg[0] == 0) etisserant@166: { etisserant@166: help(); etisserant@166: exit(1); etisserant@166: } etisserant@166: MasterBoard.busname = optarg; etisserant@166: break; etisserant@166: case 'M' : etisserant@166: if (optarg[0] == 0) etisserant@166: { etisserant@166: help(); etisserant@166: exit(1); etisserant@166: } etisserant@166: MasterBoard.baudrate = optarg; etisserant@166: break; etisserant@166: case 'l' : etisserant@166: if (optarg[0] == 0) etisserant@166: { etisserant@166: help(); etisserant@166: exit(1); etisserant@166: } etisserant@166: LibraryPath = optarg; etisserant@166: break; etisserant@166: case 'i' : etisserant@166: if (optarg[0] == 0) etisserant@166: { etisserant@166: help(); etisserant@166: exit(1); etisserant@166: } etisserant@166: snodeid = optarg; etisserant@166: sscanf(snodeid,"%x",&slavenodeid); etisserant@166: break; etisserant@166: default: etisserant@166: help(); etisserant@166: exit(1); etisserant@166: } etisserant@166: } etisserant@166: etisserant@166: #if !defined(WIN32) || defined(__CYGWIN__) etisserant@166: /* install signal handler for manual break */ etisserant@166: signal(SIGTERM, catch_signal); etisserant@166: signal(SIGINT, catch_signal); etisserant@166: #endif etisserant@166: etisserant@166: #ifndef NOT_USE_DYNAMIC_LOADING etisserant@166: LoadCanDriver(LibraryPath); etisserant@166: #endif etisserant@166: etisserant@166: if(MasterBoard.baudrate){ etisserant@166: etisserant@166: TestMaster_Data.heartbeatError = TestMaster_heartbeatError; etisserant@166: TestMaster_Data.SDOtimeoutError = TestMaster_SDOtimeoutError; etisserant@166: TestMaster_Data.initialisation = TestMaster_initialisation; etisserant@166: TestMaster_Data.preOperational = TestMaster_preOperational; etisserant@166: TestMaster_Data.operational = TestMaster_operational; etisserant@166: TestMaster_Data.stopped = TestMaster_stopped; etisserant@166: TestMaster_Data.post_sync = TestMaster_post_sync; etisserant@166: TestMaster_Data.post_TPDO = TestMaster_post_TPDO; etisserant@166: etisserant@166: if(!canOpen(&MasterBoard,&TestMaster_Data)){ etisserant@166: eprintf("Cannot open Master Board\n"); etisserant@166: goto fail_master; etisserant@166: } etisserant@166: } etisserant@166: etisserant@166: // Start timer thread etisserant@166: StartTimerLoop(&InitNodes); etisserant@166: etisserant@166: // wait Ctrl-C etisserant@166: pause(); etisserant@166: eprintf("Finishing.\n"); etisserant@166: etisserant@166: // Reset the slave node for next use (will stop emitting heartbeat) etisserant@166: masterSendNMTstateChange (&TestMaster_Data, slavenodeid, NMT_Reset_Node); etisserant@166: etisserant@166: // Stop master etisserant@166: setState(&TestMaster_Data, Stopped); etisserant@166: etisserant@166: // Stop timer thread etisserant@166: StopTimerLoop(); etisserant@166: etisserant@166: fail_master: etisserant@166: if(MasterBoard.baudrate) canClose(&TestMaster_Data); etisserant@166: etisserant@166: return 0; etisserant@166: } etisserant@166: etisserant@166: