examples/AppliMaster_HCS12/appli.c
changeset 93 16c8ceea8f18
parent 92 0d84d95790d9
child 94 bdf4c86be6b2
equal deleted inserted replaced
92:0d84d95790d9 93:16c8ceea8f18
     1 /*
       
     2 This file is part of CanFestival, a library implementing CanOpen Stack. 
       
     3 
       
     4 Copyright (C): Edouard TISSERANT and Francis DUPIN
       
     5 
       
     6 See COPYING file for copyrights details.
       
     7 
       
     8 This library is free software; you can redistribute it and/or
       
     9 modify it under the terms of the GNU Lesser General Public
       
    10 License as published by the Free Software Foundation; either
       
    11 version 2.1 of the License, or (at your option) any later version.
       
    12 
       
    13 This library is distributed in the hope that it will be useful,
       
    14 but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    16 Lesser General Public License for more details.
       
    17 
       
    18 You should have received a copy of the GNU Lesser General Public
       
    19 License along with this library; if not, write to the Free Software
       
    20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    21 */
       
    22 
       
    23 #include <stddef.h> /* for NULL */
       
    24 
       
    25 #include <asm-m68hc12/portsaccess.h>
       
    26 #include <asm-m68hc12/ports_def.h>
       
    27 #include <asm-m68hc12/ports.h>
       
    28 #include  <interrupt.h>
       
    29 
       
    30 #include <applicfg.h>
       
    31 #include <candriver.h>
       
    32 #include <timerhw.h>
       
    33 
       
    34 #include "def.h"
       
    35 #include "can.h"
       
    36 #include "objdictdef.h"
       
    37 #include "objacces.h"
       
    38 #include "canOpenDriver.h"
       
    39 #include "sdo.h"
       
    40 #include "pdo.h"
       
    41 #include "init.h"
       
    42 #include "timer.h"
       
    43 #include "lifegrd.h"
       
    44 #include "sync.h"
       
    45 
       
    46 #include "nmtMaster.h"
       
    47 
       
    48 // For prototype of exit();
       
    49 #define exit _exit
       
    50 
       
    51 
       
    52 
       
    53 
       
    54 // HCS12 configuration
       
    55 // -----------------------------------------------------
       
    56 
       
    57 enum E_CanBaudrate 
       
    58 {
       
    59    CAN_BAUDRATE_250K,
       
    60    CAN_BAUDRATE_500K,
       
    61    CAN_BAUDRATE_1M,
       
    62    CAN_BAUDRATE_OLD_VALUE
       
    63 };
       
    64 
       
    65 const canBusTime CAN_Baudrates[] =
       
    66 {
       
    67    {
       
    68       1,  /* clksrc: Use the bus clock : 16 MHz, the freq. of the quartz's board        */
       
    69       3,  /* brp :  chose btw 0 and 63 (6 bits).  freq time quantum = 16MHz / (brp + 1) */
       
    70       0,  /* sjw : chose btw 0 and 3 (2 bits). Sync on (sjw + 1 ) time quantum          */
       
    71       0,  /* samp : chose btw 0 and 3 (2 bits) (samp + 1 ) samples per bit              */
       
    72       1,  /* tseg2 : chose btw 0 and 7 (3 bits) Segment 2 width = (tseg2 + 1)  tq       */
       
    73      12,  /* tseg1 : chose btw 0 and 15 (4 bits) Segment 1 width = (tseg1 + 1)  tq      */
       
    74 
       
    75       /*
       
    76       With these values, 
       
    77       - The width of the bit time is 16 time quantum :
       
    78           - 1 tq for the SYNC segment (could not be modified)
       
    79           - 13 tq for the TIME 1 segment (tseg1 = 12)
       
    80           - 2 tq for the TIME 2 segment (tseg2 = 1)
       
    81       - Because the bus clock of the MSCAN is 16 MHZ, and the 
       
    82         freq of the time quantum is 4 MHZ (brp = 3+1), and  there are 16 tq in the bit time,
       
    83         so the freq of the bit time is 250 kHz.
       
    84       */
       
    85    },
       
    86 
       
    87    {
       
    88       1,  /* clksrc: Use the bus clock : 16 MHz, the freq. of the quartz's board        */
       
    89       1,  /* brp :  chose btw 0 and 63 (6 bits).  freq time quantum = 16MHz / (brp + 1) */
       
    90       0,  /* sjw : chose btw 0 and 3 (2 bits). Sync on (sjw + 1 ) time quantum          */
       
    91       0,  /* samp : chose btw 0 and 3 (2 bits) (samp + 1 ) samples per bit              */
       
    92       1,  /* tseg2 : chose btw 0 and 7 (3 bits) Segment 2 width = (tseg2 + 1)  tq       */
       
    93      12,  /* tseg1 : chose btw 0 and 15 (4 bits) Segment 1 width = (tseg1 + 1)  tq      */
       
    94 
       
    95       /*
       
    96       With these values, 
       
    97       - The width of the bit time is 16 time quantum :
       
    98           - 1 tq for the SYNC segment (could not be modified)
       
    99           - 13 tq for the TIME 1 segment (tseg1 = 12)
       
   100           - 2 tq for the TIME 2 segment (tseg2 = 1)
       
   101       - Because the bus clock of the MSCAN is 16 MHZ, and the 
       
   102         freq of the time quantum is 8 MHZ (brp = 1+1), and  there are 16 tq in the bit time,
       
   103         so the freq of the bit time is 500 kHz.
       
   104       */
       
   105     },
       
   106 
       
   107 	{
       
   108       1,  /* clksrc: Use the bus clock : 16 MHz, the freq. of the quartz's board        */
       
   109       1,  /* brp :  chose btw 0 and 63 (6 bits).  freq time quantum = 16MHz / (brp + 1) */
       
   110       0,  /* sjw : chose btw 0 and 3 (2 bits). Sync on (sjw + 1 ) time quantum          */
       
   111       0,  /* samp : chose btw 0 and 3 (2 bits) (samp + 1 ) samples per bit              */
       
   112       1,  /* tseg2 : chose btw 0 and 7 (3 bits) Segment 2 width = (tseg2 + 1)  tq       */
       
   113       4,  /* tseg1 : chose btw 0 and 15 (4 bits) Segment 1 width = (tseg1 + 1)  tq      */
       
   114 
       
   115       /*
       
   116       With these values, 
       
   117       - The width of the bit time is 16 time quantum :
       
   118           - 1 tq for the SYNC segment (could not be modified)
       
   119           - 5 tq for the TIME 1 segment (tseg1 = 4)
       
   120           - 2 tq for the TIME 2 segment (tseg2 = 1)
       
   121       - Because the bus clock of the MSCAN is 16 MHZ, and the 
       
   122         freq of the time quantum is 8 MHZ (brp = 1+1), and  there are 8 tq in the bit time,
       
   123         so the freq of the bit time is 1 MHz.
       
   124       */
       
   125     },
       
   126 
       
   127 	{
       
   128       1,  /* clksrc: Use the bus clock : 16 MHz, the freq. of the quartz's board        */
       
   129       0,  /* brp :  chose btw 0 and 63 (6 bits).  freq time quantum = 16MHz / (brp + 1) */
       
   130       1,  /* sjw : chose btw 0 and 3 (2 bits). Sync on (sjw + 1 ) time quantum          */
       
   131       1,  /* samp : chose btw 0 and 3 (2 bits) (samp + 1 ) samples per bit              */
       
   132       4,  /* tseg2 : chose btw 0 and 7 (3 bits) Segment 2 width = (tseg2 + 1)  tq       */
       
   133       9,  /* tseg1 : chose btw 0 and 15 (4 bits) Segment 1 width = (tseg1 + 1)  tq      */
       
   134 
       
   135       /*
       
   136       With these values, 
       
   137       - The width of the bit time is 16 time quantum :
       
   138           - 1 tq for the SYNC segment (could not be modified)
       
   139           - 10 tq for the TIME 1 segment (tseg1 = 9)
       
   140           - 5 tq for the TIME 2 segment (tseg2 = 4)
       
   141       - Because the bus clock of the MSCAN is 16 MHZ, and the 
       
   142         freq of the time quantum is 16 MHZ (brp = 0), and  there are 16 tq in the bit time,
       
   143         so the freq of the bit time is 1 MHz.
       
   144       */
       
   145     }
       
   146 };
       
   147 
       
   148 
       
   149 
       
   150 // Required definition variables
       
   151 // -----------------------------
       
   152 // The variables that you should define for debugging.
       
   153 // They are used by the macro MSG_ERR and MSG_WAR in applicfg.h
       
   154 // if the node is a slave, they can be mapped in the object dictionnary.
       
   155 
       
   156 UNS8 printMsgErrToConsole = 1;
       
   157 UNS8 printMsgWarToConsole = 1;
       
   158 
       
   159 // The variables mapped in the object dictionnary
       
   160 // ----------------------------------------------
       
   161 extern UNS32 canopenErrNB_node5;   // Mapped at index 0x6000, subindex 0x0
       
   162 extern UNS32 canopenErrVAL_node5;  // Mapped at index 0x6001, subindex 0x0
       
   163 extern UNS8 second;		   // Mapped at index 0x6002, subindex 0x1
       
   164 extern UNS8 minutes;		   // Mapped at index 0x6002, subindex 0x2
       
   165 extern UNS8 hour;		   // Mapped at index 0x6002, subindex 0x3
       
   166 extern UNS8 day;		   // Mapped at index 0x6002, subindex 0x4
       
   167 extern UNS32 canopenErrNB;	   // Mapped at index 0x6003, subindex 0x1
       
   168 extern UNS32 canopenErrVAL;	   // Mapped at index 0x6003, subindex 0x2
       
   169 
       
   170 /*************************User's variables declaration**************************/
       
   171 UNS8 connectedNode[128];
       
   172 volatile UNS8 sec = 0; // To count the time every second
       
   173 UNS8 softCount = 0;
       
   174 
       
   175 /* The variable to map in a PDO is defined at index and subIndex. Its length is size bytes */
       
   176 typedef struct mappedVar 
       
   177 {
       
   178   UNS32 index;
       
   179   UNS8  subIndex;
       
   180   UNS8  size; // in byte
       
   181 } s_mappedVar;
       
   182 
       
   183 typedef struct heartbeatConsumer
       
   184 {
       
   185   UNS8 nodeProducer;
       
   186   UNS16 time_ms;
       
   187 } s_heartbeatConsumer;
       
   188 
       
   189 /**************************prototypes*****************************************/
       
   190 /* You *must* have these 2 functions in your code*/
       
   191 void heartbeatError(UNS8 heartbeatID );
       
   192 void SD0timeoutError(UNS8 bus_id, UNS8 line);
       
   193 
       
   194 void waitMessage (void );
       
   195 void heartBeat (void );
       
   196 void transmitSync (void);
       
   197 e_nodeState stateNode (UNS8 node);
       
   198 void configure_master_SDO (UNS32 index, UNS8 serverNode);
       
   199 UNS8 waitingWriteToSlaveDict ( UNS8 slaveNode, UNS8 error);
       
   200 UNS8 waitingReadToSlaveDict (UNS8 slaveNode, void * data, UNS8 * size, UNS8 error);
       
   201 UNS8 configure_client_SDO (UNS8 slaveNode, UNS8 clientNode);
       
   202 void masterMappingPDO (UNS32 indexPDO, UNS32 cobId, 
       
   203 		      s_mappedVar *tabMappedVar, UNS8 nbVar);
       
   204 void slaveMappingPDO (UNS8 slaveNode, UNS32 indexPDO, UNS32 cobId, 
       
   205 		     s_mappedVar *tabMappedVar, UNS8 nbVar);
       
   206 void masterHeartbeatConsumer (s_heartbeatConsumer 
       
   207 			     *tabHeartbeatConsumer, UNS8 nbHeartbeats);
       
   208 void masterHeartbeatProducer (UNS16 time);
       
   209 void slaveHeartbeatConsumer (UNS8 slaveNode, s_heartbeatConsumer 
       
   210 			    *tabHeartbeatConsumer, UNS8 nbHeartbeats);
       
   211 void slaveHeartbeatProducer (UNS8 slaveNode, UNS16 time);
       
   212 void masterPDOTransmissionMode (UNS32 indexPDO,  UNS8 transType);
       
   213 void slavePDOTransmissionMode (UNS8 slaveNode, UNS32 indexPDO,  UNS8 transType);
       
   214 void masterSYNCPeriod (UNS32 SYNCPeriod);
       
   215 int main (void);
       
   216 
       
   217 // Interruption timer 3. (The timer 4 is used by CanOpen)
       
   218 void __attribute__((interrupt)) timer3Hdl (void);
       
   219 void incDate (void);
       
   220 void initLeds (void);
       
   221 void initCanHCS12 (void);
       
   222 void initTimerClk (void);
       
   223 
       
   224 
       
   225 /*****************************************************************************/
       
   226 void heartbeatError(UNS8 heartbeatID)
       
   227 {
       
   228   // MSG_ERR should send the values canopenErrNB and canopenErrVAL on event in a PDO,
       
   229   // But we do not have mapped the variables in a PDO, so it sends nothing.
       
   230   // See the note at the end of END CONFIGURING THE NETWORK.
       
   231   MSG_WAR(0x2F00, "HeartBeat, no response from node : ", heartbeatID);
       
   232 }
       
   233 
       
   234 /*****************************************************************************/
       
   235 void SD0timeoutError (UNS8 bus_id, UNS8 line)
       
   236 {
       
   237   // Informations on what occurs are in transfers[bus_id][line]....
       
   238   // See scanSDOtimeout() in sdo.c
       
   239 }
       
   240 
       
   241 //------------------------------------------------------------------------------
       
   242 /************************** FUNCTIONS TO CONFIGURE THE NETWORK******************/
       
   243 
       
   244 //------------------------------------------------------------------------------
       
   245 /* Node mode result after NodeGuard query */
       
   246 e_nodeState stateNode(UNS8 node) 
       
   247 {
       
   248   e_nodeState state = getNodeState(0, node);
       
   249   switch (state) {
       
   250   case Unknown_state: 
       
   251     MSG_WAR(0x3F05, "Not connected (Does not have sent its status) node :", node);
       
   252     break;
       
   253   case Operational: 
       
   254     MSG_WAR(0x3F06, "Ok, in operational mode, node : ", node);
       
   255     break;
       
   256   case Pre_operational: 
       
   257     MSG_WAR(0x3F07, "OK in pre-operational mode, node : ", node);
       
   258     break;
       
   259   default:
       
   260     MSG_WAR(0x3F08, "OK connected but in curious mode, node : ", node);
       
   261   }
       
   262   return state;
       
   263 }
       
   264 
       
   265 //------------------------------------------------------------------------------
       
   266 /* The master is writing in its dictionnary to configure the SDO parameters 
       
   267 to communicate with server_node
       
   268 */
       
   269 void configure_master_SDO(UNS32 index, UNS8 serverNode)
       
   270 {
       
   271   UNS32 data32;
       
   272   UNS8  data8;
       
   273   UNS8 sizeData = 4 ; // in bytes
       
   274 
       
   275   /* At subindex 1, the cobId of the Can message from the client.
       
   276   It is always defined inside the server dictionnary as 0x600 + server_node.
       
   277   So, we have no choice here ! */
       
   278   data32 = 0x600 + serverNode;
       
   279   setODentry(index, 1, &data32, sizeData, 0);
       
   280 
       
   281   {
       
   282     // Test
       
   283     UNS32  *pbData;
       
   284     UNS8 length;
       
   285     UNS32 returnValue;
       
   286     UNS8 dataType;
       
   287     // Relecture
       
   288     MSG_WAR(0x1000, "Reading index : ", index);
       
   289     MSG_WAR(0x1000, "     subindex : ", 1);
       
   290     returnValue = getODentry(index, 1, (void * *)&pbData, (UNS8 *)&length, &dataType, 0);
       
   291     MSG_WAR(0x1000, "          val : ", *pbData);
       
   292   }
       
   293 
       
   294 
       
   295   /* At subindex 2, the cobId of the Can message from the server to the client.
       
   296   It is always defined inside the server dictionnary as 0x580 + client_node.
       
   297   So, we have no choice here ! */
       
   298   data32 = 0x580 + serverNode;
       
   299   setODentry(index, 2, &data32, sizeData, 0);
       
   300 
       
   301   /* At subindex 3, the node of the server */
       
   302   data8 = serverNode;
       
   303   sizeData = 1;
       
   304   setODentry(index, 3, &data8, sizeData, 0);
       
   305 
       
   306   {
       
   307     UNS8  *pbData;
       
   308     UNS8 length;
       
   309     UNS32 returnValue;
       
   310     UNS8 dataType;
       
   311     // Relecture
       
   312     MSG_WAR(0x1000, "Reading  index : ", index);
       
   313     MSG_WAR(0x1000, "      subindex : ", 3);
       
   314     returnValue = getODentry(index, 1, (void * *)&pbData, (UNS8 *)&length, &dataType, 0);
       
   315     MSG_WAR(0x1000, "           val : ", *pbData);
       
   316   }
       
   317 }
       
   318 
       
   319 //------------------------------------------------------------------------------
       
   320 /*
       
   321  */
       
   322 UNS8 waitingWriteToSlaveDict(UNS8 slaveNode, UNS8 error)
       
   323 {
       
   324    UNS8 err;
       
   325   UNS32 abortCode;
       
   326   MSG_WAR(0x3F21, "Sending SDO to write in dictionnary of node : ", slaveNode);
       
   327   if (error) {
       
   328     MSG_ERR(0x1F22, "Unable to send the SDO to node ", slaveNode);
       
   329     return -1;
       
   330   }
       
   331   /* Waiting until the slave has responded */
       
   332   while (getWriteResultNetworkDict (0, slaveNode, &abortCode) == SDO_DOWNLOAD_IN_PROGRESS) {
       
   333     // Check if some SDO response are missing
       
   334     scanSDOtimeout();
       
   335   }
       
   336 
       
   337   err = getWriteResultNetworkDict (0, slaveNode, &abortCode);
       
   338   if (err == SDO_FINISHED) {
       
   339     MSG_WAR(0x3F22, "SDO download finished to Node : ", slaveNode);
       
   340     // Release the line. Don't forget !!!
       
   341     closeSDOtransfer(0, slaveNode, SDO_CLIENT);
       
   342     return 0;
       
   343   }
       
   344 
       
   345   if (err == SDO_ABORTED_RCV) {
       
   346     MSG_WAR(0x2F20, "Received SDO abort from node : ", slaveNode);
       
   347   }
       
   348 
       
   349   if (err == SDO_ABORTED_INTERNAL) {
       
   350     MSG_WAR(0x2F20, "Internal SDO abort for node : ", slaveNode);
       
   351   }
       
   352   // Looking for the line transfert number to read the index, subindex and releasing the line.
       
   353   {
       
   354     UNS8 line;
       
   355     err = getSDOlineOnUse(0, slaveNode, SDO_CLIENT, &line);
       
   356     if (err) {
       
   357       MSG_WAR(0x2F21, "No line found for node : ", slaveNode);
       
   358       exit(-1);
       
   359     }
       
   360     MSG_WAR (0x2F22, "while writing at his index : ", transfers[0][line].index);
       
   361     MSG_WAR (0x2F23, "                  subIndex : ", transfers[0][line].subIndex);
       
   362     //Releasing the line.
       
   363     closeSDOtransfer(0, slaveNode, SDO_CLIENT);
       
   364     exit(-1);
       
   365   }
       
   366  return 0;
       
   367 }
       
   368 
       
   369 //------------------------------------------------------------------------------
       
   370 /*
       
   371  */
       
   372 UNS8 waitingReadToSlaveDict(UNS8 slaveNode, void * data, UNS8 * size, UNS8 error)
       
   373 {
       
   374   UNS8 err;
       
   375   UNS32 abortCode;
       
   376   MSG_WAR(0x3F2A, "Sending SDO to read in dictionnary of node : ", slaveNode);
       
   377   if (error) {
       
   378     MSG_ERR(0x1F2B, "Unable to send the SDO to node ", slaveNode);
       
   379     return -1;
       
   380   }
       
   381   /* Waiting until the slave has responded */
       
   382   while (getReadResultNetworkDict (0, slaveNode, data, size, &abortCode) == SDO_UPLOAD_IN_PROGRESS) {
       
   383     // Check if some SDO response are missing
       
   384     scanSDOtimeout();
       
   385   }
       
   386   err = getReadResultNetworkDict (0, slaveNode, data, size, &abortCode);
       
   387   if (err == SDO_FINISHED) {
       
   388     MSG_WAR(0x3F2C, "SDO upload finished to Node : ", slaveNode);
       
   389     // Release the line. Don't forget !!!
       
   390     closeSDOtransfer(0, slaveNode, SDO_CLIENT);
       
   391     return 0;
       
   392   }
       
   393   if (err == SDO_ABORTED_RCV) {
       
   394     MSG_WAR(0x2F2D, "Received SDO abort from node : ", slaveNode);
       
   395   }
       
   396 
       
   397   if (err == SDO_ABORTED_INTERNAL) {
       
   398     MSG_WAR(0x2F2E, "Internal SDO abort for node : ", slaveNode);
       
   399   }
       
   400   // Looking for the line transfert number to read the index, subindex and releasing the line.
       
   401   {
       
   402     UNS8 line;
       
   403     err = getSDOlineOnUse(0, slaveNode, SDO_CLIENT, &line);
       
   404     if (err) {
       
   405       MSG_WAR(0x2F2F, "No line found for node : ", slaveNode);
       
   406       exit(-1);
       
   407     }
       
   408     MSG_WAR (0x2F30, "while writing at his index : ", transfers[0][line].index);
       
   409     MSG_WAR (0x2F31, "                  subIndex : ", transfers[0][line].subIndex);
       
   410     //Releasing the line.
       
   411     closeSDOtransfer(0, slaveNode, SDO_CLIENT);
       
   412     exit(-1);
       
   413   }    
       
   414 
       
   415  return 0;
       
   416 }
       
   417 
       
   418 //------------------------------------------------------------------------------
       
   419 /* The master is writing in the slave dictionnary to configure the SDO parameters
       
   420 Remember that the slave is the server, and the master is the client.
       
   421  */
       
   422 UNS8 configure_client_SDO(UNS8 slaveNode, UNS8 clientNode)
       
   423 {
       
   424   UNS8 data;
       
   425   UNS8 NbDataToWrite = 1 ; // in bytes
       
   426   UNS8 err = 0;
       
   427   MSG_WAR(0x3F20, "Configuring SDO by writing in dictionnary Node ", slaveNode);
       
   428   /* It is only to put at subindex 3 the serverNode. It is optionnal.
       
   429      In the slave dictionary, only one SDO server is defined, at index 
       
   430      0x1200 */
       
   431   data = clientNode;
       
   432   err = writeNetworkDict(0, slaveNode, 0x1200, 3, NbDataToWrite, 0, &data); 
       
   433   waitingWriteToSlaveDict(slaveNode, err);
       
   434  
       
   435   return 0;
       
   436 }		
       
   437   
       
   438 //------------------------------------------------------------------------------
       
   439 /*
       
   440  */
       
   441 
       
   442 void masterMappingPDO(UNS32 indexPDO, UNS32 cobId, 
       
   443 		      s_mappedVar *tabMappedVar, UNS8 nbVar)
       
   444 {
       
   445   UNS32 *pbData;
       
   446   UNS32 data32; 
       
   447   UNS8 i;
       
   448   UNS8 size = 0;
       
   449   UNS8 dataType;
       
   450 
       
   451   if ((indexPDO >= 0x1400) && (indexPDO <= 0x15FF))
       
   452     MSG_WAR(0x3F30, "Configuring MASTER for PDO receive, COBID : ", cobId);
       
   453 
       
   454   if ((indexPDO >= 0x1800) && (indexPDO <= 0x19FF))
       
   455     MSG_WAR(0x3F31, "Configuring MASTER for PDO transmit, COBID : ", cobId);
       
   456 
       
   457   /* At indexPDO, subindex 1, defining the cobId of the PDO */
       
   458   setODentry(indexPDO, 1, &cobId, 4, 0);
       
   459   /* The mapping ... */
       
   460   /* ----------------*/
       
   461   /* At subindex 0, the number of variables in the PDO */
       
   462   setODentry(indexPDO + 0x200, 0, &nbVar, 1, 0);
       
   463   getODentry(indexPDO + 0x200, 0, (void * *)&pbData, &size, &dataType, 0);
       
   464   /* At each subindex 1 .. nbVar, The index,subindex and size of the variable to map in 
       
   465      the PDO. The first variable after the COBID is defined at subindex 1, ... 
       
   466      The data to write is the concatenation on 32 bits of (msb ... lsb) : 
       
   467      index(16b),subIndex(8b),sizeVariable(8b)
       
   468 */
       
   469   for (i = 0 ; i < nbVar ; i++) {
       
   470     data32 = ((tabMappedVar + i)->index << 16) |
       
   471       (((tabMappedVar + i)->subIndex & 0xFF) << 8) |
       
   472       ((tabMappedVar + i)->size & 0xFF);
       
   473     // Write dictionary
       
   474     setODentry(indexPDO + 0x200, i + 1, &data32, 4, 0);
       
   475 
       
   476 #   ifdef MORE_COMMENTS
       
   477     printf("Mapped variable defined  at index 0x%X, subIndex 0x%X, %d bits\n", 
       
   478 	   (tabMappedVar + i)->index, (tabMappedVar + i)->subIndex, 8 * (tabMappedVar + i)->size);
       
   479     // Only to verify.
       
   480     // Read dictionnary
       
   481     getODentry(indexPDO + 0x200, i + 1, (void * *)&pbData, &size, &dataType, 0);
       
   482     printf("Writen à  index 0x%X, subIndex 0x%X, %d bits : 0x%08X\n", 
       
   483 	   indexPDO + 0x200, i + 1, 8 * size, *pbData);
       
   484 #   endif
       
   485     
       
   486   }
       
   487 }
       
   488 
       
   489 //------------------------------------------------------------------------------
       
   490 /*
       
   491  */
       
   492 
       
   493 void slaveMappingPDO(UNS8 slaveNode, UNS32 indexPDO, UNS32 cobId, 
       
   494 		     s_mappedVar *tabMappedVar, UNS8 nbVar)
       
   495 {
       
   496   UNS32 data32; 
       
   497   UNS8 i;
       
   498   UNS8 err;
       
   499   UNS8 nbBytes = 1;
       
   500   if ((indexPDO >= 0x1400) && (indexPDO <= 0x15FF))
       
   501     MSG_WAR(0x3F32, "Configuring slave for PDO receive, COBID : ", cobId);
       
   502 
       
   503   if ((indexPDO >= 0x1800) && (indexPDO <= 0x19FF))
       
   504     MSG_WAR(0x3F33, "Configuring slave for PDO transmit, COBID : ", cobId);
       
   505 
       
   506   /* At indexPDO, subindex 1, defining the cobId of the PDO */
       
   507   err = writeNetworkDict(0, slaveNode, indexPDO, 1, 4, 0, &cobId); 
       
   508   waitingWriteToSlaveDict(slaveNode, err);
       
   509 
       
   510   /* The mapping ... */
       
   511   /* ----------------*/
       
   512   /* At subindex 0, the number of variables in the PDO */
       
   513   err = writeNetworkDict(0, slaveNode, indexPDO + 0x200, 0, nbBytes, 0, &nbVar); 
       
   514   waitingWriteToSlaveDict(slaveNode, err);
       
   515 
       
   516   /* At each subindex 1 .. nbVar, The index,subindex and size of the variable to map in 
       
   517      the PDO. The first variable after the COBID is defined at subindex 1, ... 
       
   518      The data to write is the concatenation on 32 bits of (msb ... lsb) : 
       
   519      index(16b),subIndex(8b),sizeVariable(8b)
       
   520 */
       
   521   for (i = 0 ; i < nbVar ; i++) {
       
   522     data32 = ((tabMappedVar + i)->index << 16) |
       
   523       (((tabMappedVar + i)->subIndex & 0xFF) << 8) |
       
   524       ((tabMappedVar + i)->size & 0xFF);
       
   525 
       
   526     // Write dictionary
       
   527     err = writeNetworkDict(0, slaveNode, indexPDO + 0x200, i + 1, 4, 0, &data32); 
       
   528     waitingWriteToSlaveDict(slaveNode, err);
       
   529 
       
   530 #   ifdef MORE_COMMENTS
       
   531     printf("Mapped variable defined  at index 0x%X, subIndex 0x%X, %d bits\n", 
       
   532 	   (tabMappedVar + i)->index, (tabMappedVar + i)->subIndex, 8 * (tabMappedVar + i)->size);
       
   533 
       
   534     printf("At node 0x%X Writen at  index 0x%X, subIndex 0x%X, %d bits : 0x%08X\n", 
       
   535 	   slaveNode, indexPDO + 0x200, i + 1, 32, data32);
       
   536 #   endif
       
   537     
       
   538   }
       
   539 }
       
   540 
       
   541 //------------------------------------------------------------------------------
       
   542 /*
       
   543  */
       
   544 void masterHeartbeatConsumer(s_heartbeatConsumer 
       
   545 			     *tabHeartbeatConsumer, UNS8 nbHeartbeats)
       
   546 {
       
   547   UNS32 data;
       
   548   UNS8 i;
       
   549   UNS8 nbHB = nbHeartbeats;
       
   550 
       
   551   MSG_WAR(0x3F40, "Configuring heartbeats consumers for master", 0);
       
   552   /* At index 1016, subindex 0 : the nb of consumers (ie nb of nodes of which are expecting heartbeats) */
       
   553   setODentry(0x1016, 0, & nbHB, 1, 0);
       
   554   
       
   555   /* At Index 1016, subindex 1, ... : 32 bit values : msb ... lsb :
       
   556      00 - node_consumer (8b) - time_ms (16b)
       
   557      Put 0 to ignore the entry.
       
   558   */
       
   559   for (i = 0 ; i < nbHeartbeats ; i++) {
       
   560     data = (((tabHeartbeatConsumer + i)->nodeProducer & 0xFF)<< 16) | ((tabHeartbeatConsumer + i)->time_ms & 0xFFFF);
       
   561     setODentry(0x1016, i + 1, & data, 4, 0);
       
   562   }
       
   563 }
       
   564 
       
   565 //------------------------------------------------------------------------------
       
   566 /*
       
   567  */
       
   568 
       
   569 void masterHeartbeatProducer(UNS16 time)
       
   570 {
       
   571   UNS16 hbTime = time;
       
   572   MSG_WAR(0x3F45, "Configuring heartbeat producer for master", 0);
       
   573   /* At index 1017, subindex 0, defining the time to send the heartbeat. Put 0 to never send heartbeat */
       
   574   setODentry(0x1017, 0, &hbTime, 2, 0);
       
   575 }
       
   576 
       
   577 //------------------------------------------------------------------------------
       
   578 /*
       
   579  */
       
   580 void slaveHeartbeatConsumer(UNS8 slaveNode, s_heartbeatConsumer 
       
   581 			    *tabHeartbeatConsumer, UNS8 nbHeartbeats)
       
   582 {
       
   583   UNS32 data;
       
   584   UNS8 err;
       
   585   UNS8 i;
       
   586   
       
   587   MSG_WAR(0x3F46, "Configuring heartbeats consumers for node  : ", slaveNode);
       
   588   
       
   589   /* At Index 1016, subindex 1, ... : 32 bit values : msb ... lsb :
       
   590      00 - node_consumer (8b) - time_ms (16b)
       
   591      Put 0 to ignore the entry.
       
   592   */
       
   593   for (i = 0 ; i < nbHeartbeats ; i++) {
       
   594     data = (((tabHeartbeatConsumer + i)->nodeProducer & 0xFF)<< 16) | 
       
   595       ((tabHeartbeatConsumer + i)->time_ms & 0xFFFF);
       
   596     err = writeNetworkDict(0, slaveNode, 0x1016, i + 1, 4, 0, &data); 
       
   597     waitingWriteToSlaveDict(slaveNode, err);
       
   598   }
       
   599 }
       
   600 
       
   601 //------------------------------------------------------------------------------
       
   602 /*
       
   603  */
       
   604 
       
   605 void slaveHeartbeatProducer(UNS8 slaveNode, UNS16 time)
       
   606 {
       
   607   UNS8 err;
       
   608   MSG_WAR(0x3F47, "Configuring heartbeat producer for node  : ", slaveNode);
       
   609   /* At index 1017, subindex 0, defining the time to send the heartbeat. Put 0 to never send heartbeat */
       
   610 
       
   611   err = writeNetworkDict(0, slaveNode, 0x1017, 0, 2, 0, &time); 
       
   612   waitingWriteToSlaveDict(slaveNode, err);
       
   613 }
       
   614 
       
   615 //------------------------------------------------------------------------------
       
   616 /*
       
   617  */
       
   618 
       
   619 void masterPDOTransmissionMode(UNS32 indexPDO,  UNS8 transType)
       
   620 {
       
   621   MSG_WAR(0x3F48, "Configuring transmission from master, indexPDO : ", indexPDO);
       
   622  
       
   623   /* At subindex 2, the transmission type */
       
   624   setODentry(indexPDO, 2, &transType, 1, 0);
       
   625 }
       
   626 
       
   627 
       
   628 //------------------------------------------------------------------------------
       
   629 /*
       
   630  */
       
   631 
       
   632 void slavePDOTransmissionMode(UNS8 slaveNode, UNS32 indexPDO,  UNS8 transType)
       
   633 {
       
   634   UNS8 err;
       
   635   MSG_WAR(0x3F41, "Configuring transmission mode for node : ", slaveNode);
       
   636   MSG_WAR(0x3F42, "                              indexPDO : ", indexPDO);
       
   637 
       
   638   err = writeNetworkDict(0, slaveNode, indexPDO, 2, 1, 0, &transType); 
       
   639   waitingWriteToSlaveDict(slaveNode, err);
       
   640 }
       
   641 
       
   642 //------------------------------------------------------------------------------
       
   643 /*
       
   644  */
       
   645 
       
   646 void masterSYNCPeriod(UNS32 SYNCPeriod)
       
   647 {
       
   648  UNS32 cobId = 0x40000080;
       
   649  MSG_WAR(0x3F49, "Configuring master to send SYNC every ... micro-seconds :", SYNCPeriod);
       
   650  /* At index 0x1006, subindex 0 : the period in ms */
       
   651  setODentry(0x1006, 0, &SYNCPeriod , 4, 0);
       
   652  /* At index 0x1005, subindex 0 : Device generate SYNC signal with CobId 0x80 */
       
   653  setODentry(0x1005, 0, &cobId, 4, 0);
       
   654 }
       
   655 
       
   656 //------------------------------------------------------------------------------
       
   657 
       
   658 
       
   659 //Initialisation of the port B for the leds.
       
   660 void initLeds(void)
       
   661 {
       
   662   // Port B is output
       
   663   IO_PORTS_8(DDRB)= 0XFF;
       
   664   // RAZ
       
   665   IO_PORTS_8(PORTB) = 0xFF;
       
   666 }
       
   667 
       
   668 //------------------------------------------------------------------------------
       
   669 
       
   670 
       
   671 
       
   672 void initCanHCS12 (void)
       
   673 {  
       
   674   //Init the HCS12 microcontroler for CanOpen 
       
   675   initHCS12();
       
   676    // Init the HCS12  CAN driver
       
   677   const canBusInit bi0 = {
       
   678     0,    /* no low power                 */ 
       
   679     0,    /* no time stamp                */
       
   680     1,    /* enable MSCAN                 */
       
   681     0,    /* clock source : oscillator (In fact, it is not used)   */
       
   682     0,    /* no loop back                 */
       
   683     0,    /* no listen only               */
       
   684     0,    /* no low pass filter for wk up */
       
   685 	CAN_Baudrates[CAN_BAUDRATE_250K],
       
   686     {
       
   687       0x00,    /* Filter on 16 bits. See Motorola Block Guide V02.14 fig 4-3 */
       
   688       0x00, 0xFF, /* filter 0 hight accept all msg      */
       
   689       0x00, 0xFF, /* filter 0 low accept all msg        */
       
   690       0x00, 0xFF, /* filter 1 hight filter all of  msg  */
       
   691       0x00, 0xFF, /* filter 1 low filter all of  msg    */
       
   692       0x00, 0xFF, /* filter 2 hight filter most of  msg */
       
   693       0x00, 0xFF, /* filter 2 low filter most of  msg   */
       
   694       0x00, 0xFF, /* filter 3 hight filter most of  msg */
       
   695       0x00, 0xFF, /* filter 3 low filter most of  msg   */
       
   696     }
       
   697   };   
       
   698 
       
   699   canInit(CANOPEN_LINE_NUMBER_USED, bi0);  //initialize filters...
       
   700   unlock(); // Allow interruptions
       
   701 }
       
   702 
       
   703 /*********************************************************************/
       
   704 // For Second timer
       
   705 void incDate(void)
       
   706 {
       
   707   if (sec == 59) 
       
   708     sec = 0;
       
   709   else
       
   710     sec++;
       
   711 
       
   712   // Toggle the led 4 every seconds
       
   713   IO_PORTS_8(PORTB) ^= 0x10;
       
   714 
       
   715 }
       
   716 
       
   717 // Init the time for the second counter
       
   718 void initTimerClk(void)
       
   719 {
       
   720 
       
   721   lock();   // Inhibe les interruptions
       
   722 
       
   723   // Configuration du Channel 3
       
   724   IO_PORTS_8(TIOS) |= 0x08;     // Canal 3 en sortie
       
   725   IO_PORTS_8(TCTL2) &= ~(0xC0); // Canal 3 déconnecté du pin de sortie
       
   726   IO_PORTS_8(TIE) |= 0x08;      // Autorise interruption Canal 3
       
   727   IO_PORTS_8(TSCR1) |= 0x80;    // Mise en route du timer
       
   728   unlock(); // Autorise les interruptions
       
   729 }
       
   730 
       
   731 
       
   732 /*********************************************************************/
       
   733 void __attribute__((interrupt)) timer3Hdl(void)
       
   734 {
       
   735   //IO_PORTS_8(PORTB) ^= 0x10;
       
   736   //IO_PORTS_8(PORTB) &= ~0x20;
       
   737   IO_PORTS_8(TFLG1) = 0x08; // RAZ du flag interruption timer 3
       
   738   // Calcul evt suivant. Clock 8 MHz -> 8000 evt de 1 ms!! Doit tenir sur 16 bits
       
   739   // Attention, ça change si on utilise la pll
       
   740   // Lorsque le timer atteindra la valeur de TC3 (16 bits), l'interruption timer3Hdl sera déclenchée
       
   741   // Si on utilise la PLL à 24 MHZ, alors la vitesse du bus est multipliée par 3.
       
   742 
       
   743 /*   Assume that our board uses a 16 MHz quartz */
       
   744 /*   Without pre-division, 8000 counts takes 1 ms. */
       
   745 /*   We are using a pre-divisor of 32. (register TSCR2) See in CanOpenDriverHC12/timerhw.c  */
       
   746 /*   So 1000 counts takes 4 ms. */
       
   747 /*   We must have a soft counter of 250 to count a second. */
       
   748   
       
   749 /*
       
   750   We check in an interrupt handler if a message is arrived.
       
   751 */
       
   752   receiveMsgHandler(0);
       
   753 
       
   754   IO_PORTS_16(TC3H) += (1000); // IT every 4000 count.
       
   755   softCount++;
       
   756   if (softCount == 250) {
       
   757     softCount = 0;
       
   758     incDate();
       
   759   }
       
   760 }
       
   761 
       
   762 
       
   763 
       
   764 
       
   765 /*****************************************************************************/
       
   766 
       
   767 
       
   768 
       
   769 /********************************* MAIN ***************************************/
       
   770 
       
   771  
       
   772 int main()
       
   773 {
       
   774 
       
   775   UNS8 second_last;
       
   776   UNS8 minutes_last;
       
   777   UNS8 sendingResetError = 0;
       
   778   UNS8 ok, i;
       
   779 
       
   780   /* initialisation du bus Can */
       
   781   initCanHCS12();  
       
   782  
       
   783   /* arrays initialisation, etc */
       
   784   initCANopenMain();     
       
   785       
       
   786   /* arrays initialisation, etc */
       
   787   initCANopenMaster();  
       
   788 
       
   789 /* Defining the node Id */
       
   790   setNodeId(0x01);
       
   791   MSG_WAR(0x3F50, "My node ID is : ", getNodeId()); 
       
   792 
       
   793   /* Put the master in operational mode */
       
   794   setState(Operational);
       
   795 
       
   796  /* Init the table of connected nodes */
       
   797   for (i = 0 ; i < 128 ; i++)
       
   798     connectedNode[i] = 0;
       
   799 
       
   800   /* Initialisation */
       
   801   initLeds();
       
   802   initTimer( );
       
   803   initTimerClk();
       
   804     
       
   805 
       
   806 
       
   807   /******************** CONFIGURING THE NETWORK **************************/
       
   808   
       
   809   /* Which nodes are connected ? */
       
   810   /* Sending a request Node guard to node 5 and 6 */
       
   811   MSG_WAR(0x3F04, "Sending a node guard to node : ", 5);
       
   812   masterReadNodeState(0, 0x05);
       
   813 
       
   814   /* Sending a message to the node 6, only as example */
       
   815   MSG_WAR(0x3F04, "Sending a node guard to node : ", 6);
       
   816   masterReadNodeState(0, 0x06);
       
   817   /* Waiting for a second the response */
       
   818   sec = 0;
       
   819   while (sec < 2) {};
       
   820 
       
   821   /* Whose node have answered ? */
       
   822   connectedNode[5] = stateNode(5);
       
   823   if (connectedNode[5] != Unknown_state) {
       
   824     MSG_WAR(0x3F06, "Node 5 connected. Its state is : ", connectedNode[5]);
       
   825   }
       
   826   else {
       
   827     MSG_WAR(0x3F07, "Node 5 NOT connected ", connectedNode[5]);
       
   828   }
       
   829 
       
   830   connectedNode[6] = stateNode(6);
       
   831   if (connectedNode[6] != Unknown_state) {
       
   832     MSG_WAR(0x3F08, "Node 6 connected. Its state is : ", connectedNode[6]);
       
   833   }
       
   834   else {
       
   835     MSG_WAR(0x3F09, "Node 6 NOT connected ", connectedNode[6]);
       
   836   }
       
   837 
       
   838   /* Configure the SDO master to communicate with node 5 and node 6 */
       
   839   configure_master_SDO(0x1280, 0x05);
       
   840   /* Configure the SDO of node 5 */
       
   841   /* getNodeId() returns my node Id */
       
   842   configure_client_SDO(0x05, getNodeId());
       
   843 
       
   844   /* Mapping of the PDO 
       
   845      Chose some COBID in (hexa) 181-1FF, 201-27F, 281-2FF, 301-37F, 
       
   846      381-3FF, 401-47F, 481-4FF, 501-57F,
       
   847      without other restriction.
       
   848      (Of course, you must not define 2 PDO transmit with the same cobId !!)
       
   849   */
       
   850  
       
   851   /*
       
   852      *** PDO node 1 <-- node 5 ***
       
   853      *** cobId 0x181 *************
       
   854      MASTER (node 1)
       
   855      Mapped to variables (node1) [index-subindex-size_bits]: 
       
   856        day    [0x6002 - 0x04 - 8]
       
   857        hour   [0x6002 - 0x03 - 8]
       
   858        second [0x6002 - 0x01 - 8]
       
   859 
       
   860      SLAVE (node 5)
       
   861      Mapped to variables (node5) [index-subindex-size_bits]: 
       
   862        day    [0x2000 - 0x04 - 8]
       
   863        hour   [0x2000 - 0x03 - 8]
       
   864        second [0x2000 - 0x01 - 8]
       
   865 */
       
   866 
       
   867   /* Configuring the first PDO receive, defined at index 0x1400 and 0x1600 */
       
   868   {
       
   869     s_mappedVar tabMappedVar[8] = { {0x6002,4,8}, {0x6002,3,8}, {0x6002,1,8}, };
       
   870     masterMappingPDO(0x1400, 0x181, tabMappedVar, 3);
       
   871   }
       
   872 
       
   873   /* Configuring the first PDO transmit, defined at index 0x1800 and 0x1A00 */
       
   874   {
       
   875     s_mappedVar tabMappedVar[8] = { {0x2000,4,8}, {0x2000,3,8}, {0x2000,1,8}, };
       
   876     slaveMappingPDO(0x05, 0x1800, 0x181, tabMappedVar, 3);
       
   877   }
       
   878    /*
       
   879      *** PDO node 1 <-- node 5 ***
       
   880      *** cobId 0x182 *************
       
   881      MASTER (node 1)
       
   882      Mapped to variables (node1) [index-subindex-size_bits]: 
       
   883        minute    [0x6002 - 0x02 - 8]
       
   884 
       
   885      SLAVE (node 5)
       
   886      Mapped to variables (node5) [index-subindex-size_bits]: 
       
   887        minute    [0x2000 - 0x02 - 8]
       
   888    */
       
   889 
       
   890   /* Configuring PDO receive, defined at index 0x1400 and 0x1600 */
       
   891   {
       
   892     s_mappedVar tabMappedVar[8] = { {0x6002,2,8} };
       
   893     masterMappingPDO(0x1401, 0x182, tabMappedVar, 1);
       
   894   }
       
   895 
       
   896   /* Configuring PDO transmit, defined at index 0x1800 and 0x1A00 */
       
   897   {
       
   898     s_mappedVar tabMappedVar[8] = { {0x2000,2,8} };
       
   899     slaveMappingPDO(0x05, 0x1801, 0x182, tabMappedVar, 1);
       
   900   }
       
   901 
       
   902 
       
   903   /*
       
   904      *** PDO node 1 <-- node 5 ***
       
   905      *** cobId 0x183 *************
       
   906      Error management :  By this way, The node can send by PDO an error
       
   907      MASTER (node 1)
       
   908      Mapped to variables (node1) [index-subindex-size_bits]: 
       
   909        canopenErrNb_node5     [0x6000 - 0x00 - 32]
       
   910        canopenErrVal_node5    [0x6001 - 0x00 - 32] 
       
   911 
       
   912      SLAVE (node 5)
       
   913      Mapped to variables (node5) [index-subindex-size_bytes]: 
       
   914        canopenErrNb     [0x6000 - 0x00 - 32]
       
   915        canopenErrVal    [0x6001 - 0x00 - 32]  
       
   916   */
       
   917 
       
   918   /* Configuring  PDO receive, defined at index 0x1402 and 0x1602 */
       
   919   {
       
   920     s_mappedVar tabMappedVar[8] = { {0x6000,0,32}, {0x6001, 0, 32}};
       
   921     masterMappingPDO(0x1402, 0x183, tabMappedVar, 2);
       
   922   }
       
   923 
       
   924   /* Configuring PDO transmit, defined at index 0x1802 and 0x1A02 */
       
   925   {
       
   926     s_mappedVar tabMappedVar[8] = { {0x6000,0,32}, {0x6001, 0, 32}};
       
   927     slaveMappingPDO(0x05, 0x1802, 0x183, tabMappedVar, 2);
       
   928   }
       
   929  
       
   930   /*
       
   931      *** PDO node 1 --> node 5 ***
       
   932      *** cobId 0x184 *************
       
   933      Error management :  To reset the error
       
   934      MASTER (node 1)
       
   935      Mapped to variables (node1) [index-subindex-size_bits]: 
       
   936        canopenErrNb_node5     [0x6000 - 0x00 - 32]
       
   937        canopenErrVal_node5    [0x6001 - 0x00 - 32] 
       
   938 
       
   939      SLAVE (node 5)
       
   940      Mapped to variables (node5) [index-subindex-size_bytes]: 
       
   941        canopenErrNb     [0x6000 - 0x00 - 32]
       
   942        canopenErrVal    [0x6001 - 0x00 - 32]  
       
   943   */
       
   944 
       
   945   /* Configuring  PDO transmit, defined at index 0x1803 and 0x1103 */
       
   946   {
       
   947     s_mappedVar tabMappedVar[8] = { {0x6000,0,32}, {0x6001, 0, 32}};
       
   948     masterMappingPDO(0x1801, 0x184, tabMappedVar, 2);
       
   949   }
       
   950 
       
   951   /* Configuring PDO transmit, defined at index 0x1403 and 0x1603 */
       
   952   {
       
   953     s_mappedVar tabMappedVar[8] = { {0x6000,0,32}, {0x6001, 0, 32}};
       
   954     slaveMappingPDO(0x05, 0x1400, 0x184, tabMappedVar, 2);
       
   955   }
       
   956 
       
   957   /* Configuring the node 5 heartbeat */
       
   958   /* Check every 3000 ms if it have received a heartbeat from node 1 */
       
   959   {
       
   960     UNS8 nbHeartbeatsToReceive = 1;
       
   961     s_heartbeatConsumer tabHeartbeatConsumer[10] = {{1, 0xBB8}};
       
   962     slaveHeartbeatConsumer(0x05, tabHeartbeatConsumer, nbHeartbeatsToReceive);
       
   963   }
       
   964   /* Sending every 1000 ms an heartbeat */
       
   965   slaveHeartbeatProducer(0x05, 0x3E8);
       
   966 
       
   967   /* Configuring the master heartbeat */
       
   968   /* Check every 3000 ms if it have received a heartbeat from node 5 */
       
   969     {
       
   970     UNS8 nbHeartbeatsToReceive = 1;
       
   971     s_heartbeatConsumer tabHeartbeatConsumer[10] = {{5, 0xBB8}};
       
   972     masterHeartbeatConsumer(tabHeartbeatConsumer, nbHeartbeatsToReceive);
       
   973   }
       
   974 
       
   975     /* Sending every 1000 ms an heartbeat */
       
   976     masterHeartbeatProducer(0x3E8);
       
   977 
       
   978 
       
   979     
       
   980     /* Configuring the transmission mode of the PDO */
       
   981     slavePDOTransmissionMode(0x05, 0x1800,  TRANS_EVERY_N_SYNC (1));
       
   982     slavePDOTransmissionMode(0x05, 0x1801,  TRANS_EVENT);
       
   983     slavePDOTransmissionMode(0x05, 0x1802,  TRANS_EVENT);
       
   984     masterPDOTransmissionMode(0x1801,  TRANS_EVENT);
       
   985 
       
   986 
       
   987     /* Configuring the master to send a SYNC message every 1 s */
       
   988     /* Note than any other node can send the SYNC instead of the master */
       
   989     masterSYNCPeriod(1000000); 
       
   990 
       
   991     {
       
   992       // Reading the period of heartbeat which has been written in node 5 dictionary
       
   993       UNS8 node = 5;
       
   994       UNS16 index = 0x1017;
       
   995       UNS8 subindex = 0;
       
   996       //UNS8 notused = 0;
       
   997       UNS16 hb = 0;
       
   998       UNS8  size_data = 0;
       
   999       UNS8 error;
       
  1000       MSG_WAR(0x3F50, "Reading dictionary noeud 5, 1017/0", 0);
       
  1001       error = readNetworkDict(0, node, index, subindex, 0);
       
  1002       //error = readNetworkDict(0, node, index, subindex, &notused);
       
  1003       if (error) {
       
  1004 	MSG_ERR(0x1F50, "!!! ERROR reading dictionary noeud 5, 1017/0", 0);
       
  1005 	exit (-1);
       
  1006       }
       
  1007       /* Waiting until the server has responded */
       
  1008       error = waitingReadToSlaveDict(node,  (UNS16 *)&hb,  &size_data, error);
       
  1009       MSG_WAR(0x1F51, "Read dictionary of node 5, index/subindex 1017/0 value = ", hb);
       
  1010       MSG_WAR(0x1F51, "         size of data (bytes) = ", size_data);
       
  1011     }
       
  1012 
       
  1013     /* Put the node 5 in operational mode 
       
  1014        The mode is changed according to the slave state machine mode :
       
  1015          initialisation  ---> pre-operational (Automatic transition)
       
  1016          pre-operational <--> operational
       
  1017          pre-operational <--> stopped
       
  1018          pre-operational, operational, stopped -> initialisation
       
  1019        NMT_Start_Node           // Put the node in operational mode       
       
  1020        NMT_Stop_Node		// Put the node in stopped mode    
       
  1021        NMT_Enter_PreOperational // Put the node in pre_operational mode
       
  1022        NMT_Reset_Node		// Put the node in initialization mode 
       
  1023        NMT_Reset_Comunication	// Put the node in initialization mode 
       
  1024     */
       
  1025     masterSendNMTstateChange(0, 0x05, NMT_Start_Node);
       
  1026 
       
  1027     // Note
       
  1028     //-----
       
  1029     // We do not have mapped the variable canopenErrNB and canopenErrVAL.
       
  1030     // We should have done that !
       
  1031     // the macro MSG_ERR try to send the PDO(s) which contains these two variables.
       
  1032     // While the PDO will not be found, if you are printing the warnings in file pdo.c,
       
  1033     // it will print "0X393B Unable to send variable on event :  not mapped in a PDO to send on event" for  
       
  1034     // example when you enter the function heartbeatError. 
       
  1035 
       
  1036    /******************** END CONFIGURING THE NETWORK **********************/
       
  1037     
       
  1038     
       
  1039     
       
  1040     /* Init the errors values that may send the node 5 */
       
  1041     canopenErrNB_node5 = 0;
       
  1042     canopenErrVAL_node5 = 0;
       
  1043 
       
  1044     /***********/
       
  1045     /* Running */
       
  1046     /***********/
       
  1047 
       
  1048   /* SDO test with node 5 */
       
  1049   /* This code may takes too much room in memory if you are also debugging the file sdo.c */
       
  1050   {
       
  1051     // Reading string
       
  1052     UNS8 dataW[20];
       
  1053     UNS8 dataR[20];
       
  1054     UNS8 size;
       
  1055     UNS8 err;
       
  1056     MSG_WAR(0x3F05, "Test SDO", 0);
       
  1057 
       
  1058     MSG_WAR(0x3F10, "Writing to node 5 at 0x6002-0 ...", 0);
       
  1059     strcpy(dataW, "Au Revoir");
       
  1060     MSG_WAR(0x3F10, dataW, 0);
       
  1061     size = 20;
       
  1062     err = writeNetworkDict(0, 5, 0x6002, 0, 10, visible_string, dataW);
       
  1063     err = waitingWriteToSlaveDict(5, err);
       
  1064   
       
  1065     err = readNetworkDict(0, 5, 0x6002, 0, visible_string);
       
  1066     err = waitingReadToSlaveDict(5, dataR, &size, err);
       
  1067     MSG_WAR(0x3F08, "Read from node 5 at 0x6002-0" , 0);
       
  1068     MSG_WAR(0x3F08, dataR, 0);
       
  1069     
       
  1070     MSG_WAR(0x3F08, "node 5. Hardware version. (default = compil. date) ...", 0);
       
  1071     err = readNetworkDict(0, 5, 0x1009, 0, visible_string);
       
  1072  
       
  1073     err = waitingReadToSlaveDict(5, dataR, &size, err);
       
  1074     MSG_WAR(0x3F08, dataR, 0);
       
  1075 
       
  1076     MSG_WAR(0x3F08, "node 5. Software version. (default = compil. time) ...", 0);
       
  1077     err = readNetworkDict(0, 5, 0x100A, 0, visible_string);
       
  1078     err = waitingReadToSlaveDict(5, dataR, &size, err);
       
  1079     MSG_WAR(0x3F08, dataR, 0);
       
  1080   }
       
  1081 
       
  1082   // Node identity ?
       
  1083   {
       
  1084     UNS8 *data;
       
  1085     UNS8 size;
       
  1086     UNS8 dataType;
       
  1087     // Manufacturer Device name (default = empty string)
       
  1088     getODentry(0x1008, 0x0, (void **)&data, &size, &dataType, 0);
       
  1089     MSG_WAR(0x3F09, data, 0);
       
  1090     // Manufacturer Hardware version. (default = compilation. date)
       
  1091     getODentry(0x1009, 0x0, (void **)&data, &size, &dataType, 0);
       
  1092     MSG_WAR(0x3F09, data, 0);
       
  1093     // Manufacturer Software version. (default = compilation. time)
       
  1094     getODentry(0x100A, 0x0, (void **)&data, &size, &dataType, 0);
       
  1095     MSG_WAR(0x3F09, data, 0);
       
  1096   }
       
  1097     
       
  1098   while(1) { 
       
  1099     // To transmit the SYNC if it is time to do.
       
  1100     computeSYNC();
       
  1101 
       
  1102     // Testing if heartsbeat have been received, and send a heartbeat if it is time.
       
  1103      heartbeatMGR();
       
  1104 
       
  1105      // Messages received ?
       
  1106      // The function is called in void __attribute__((interrupt)) timer3Hdl (void)
       
  1107      //receiveMsgHandler(0);
       
  1108 
       
  1109  if (minutes != minutes_last) {
       
  1110 	MSG_WAR(0x3F80, "Minutes changed :", minutes);
       
  1111 	minutes_last = minutes;
       
  1112       }
       
  1113 
       
  1114       if (second != second_last) {
       
  1115 	MSG_WAR(0x3F81, "Seconds : ", second);
       
  1116 	second_last = second;
       
  1117 
       
  1118 	if (canopenErrNB_node5) {
       
  1119 	  MSG_WAR(0x3F82, "Received an error from node 5, NB : ", canopenErrNB_node5);
       
  1120 	  MSG_WAR(0x3F83, "                            VALUE : ", canopenErrVAL_node5);
       
  1121 	  // Reseting the error
       
  1122 	  canopenErrNB_node5 = 0;
       
  1123 	  canopenErrVAL_node5 = 0;
       
  1124 	  sendingResetError = 1;
       
  1125 	}
       
  1126        
       
  1127 	if ((second == 00) && sendingResetError) {
       
  1128 	  MSG_WAR(0x3F84, 
       
  1129 		 "Sending to node 5 a PDO envent to reset the error NB and VAL : ",0);
       
  1130 	  sendPDOevent(0, &canopenErrNB_node5);
       
  1131 	  sendingResetError = 0; 
       
  1132 	}
       
  1133       
       
  1134       
       
  1135       }	// end if (second != second_last)
       
  1136 
       
  1137       
       
  1138   } // end while
       
  1139       
       
  1140  
       
  1141   return (0); 
       
  1142 }
       
  1143