]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - src/pdo.c
fix bug in exit function
[CanFestival-3.git] / src / pdo.c
1 /*
2   This file is part of CanFestival, a library implementing CanOpen
3   Stack.
4
5   Copyright (C): Edouard TISSERANT and Francis DUPIN
6
7   See COPYING file for copyrights details.
8
9   This library is free software; you can redistribute it and/or
10   modify it under the terms of the GNU Lesser General Public
11   License as published by the Free Software Foundation; either
12   version 2.1 of the License, or (at your option) any later version.
13
14   This library is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public
20   License along with this library; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
22   USA
23 */
24 #include "pdo.h"
25 #include "objacces.h"
26 #include "canfestival.h"
27 #include "sysdep.h"
28
29 /*!
30 ** @file   pdo.c
31 ** @author Edouard TISSERANT and Francis DUPIN
32 ** @date   Tue Jun  5 09:32:32 2007
33 **
34 ** @brief
35 **
36 **
37 */
38
39 /*!
40 **
41 **
42 ** @param d
43 ** @param TPDO_com TPDO communication parameters OD entry
44 ** @param TPDO_map TPDO mapping parameters OD entry
45 **
46 ** @return
47 **/
48
49 UNS8
50 buildPDO (CO_Data * d, UNS8 numPdo, Message * pdo)
51 {
52   const indextable *TPDO_com = d->objdict + d->firstIndex->PDO_TRS + numPdo;
53   const indextable *TPDO_map =
54     d->objdict + d->firstIndex->PDO_TRS_MAP + numPdo;
55
56   UNS8 prp_j = 0x00;
57   UNS8 offset = 0x00;
58   const UNS8 *pMappingCount = (UNS8 *) TPDO_map->pSubindex[0].pObject;
59
60   pdo->cob_id = UNS16_LE(*(UNS32*)TPDO_com->pSubindex[1].pObject & 0x7FF);
61   pdo->rtr = NOT_A_REQUEST;
62
63   MSG_WAR (0x3009, "  PDO CobId is : ",
64            *(UNS32 *) TPDO_com->pSubindex[1].pObject);
65   MSG_WAR (0x300D, "  Number of objects mapped : ", *pMappingCount);
66
67   do
68     {
69       UNS8 dataType;            /* Unused */
70       UNS8 tmp[] = { 0, 0, 0, 0, 0, 0, 0, 0 };  /* temporary space to hold bits */
71
72       /* pointer fo the var which holds the mapping parameter of an mapping entry  */
73       UNS32 *pMappingParameter =
74         (UNS32 *) TPDO_map->pSubindex[prp_j + 1].pObject;
75       UNS16 index = (UNS16) ((*pMappingParameter) >> 16);
76       UNS8 Size = (UNS8) (*pMappingParameter & (UNS32) 0x000000FF);     /* Size in bits */
77
78       /* get variable only if Size != 0 and Size is lower than remaining bits in the PDO */
79       if (Size && ((offset + Size) <= 64))
80         {
81           UNS8 ByteSize = 1 + ((Size - 1) >> 3);        /*1->8 => 1 ; 9->16 => 2, ... */
82           UNS8 subIndex =
83             (UNS8) (((*pMappingParameter) >> (UNS8) 8) & (UNS32) 0x000000FF);
84
85           MSG_WAR (0x300F, "  got mapping parameter : ", *pMappingParameter);
86           MSG_WAR (0x3050, "    at index : ", TPDO_map->index);
87           MSG_WAR (0x3051, "    sub-index : ", prp_j + 1);
88
89           if (getODentry (d, index, subIndex, tmp, &ByteSize, &dataType, 0) !=
90               OD_SUCCESSFUL)
91             {
92               MSG_ERR (0x1013,
93                        " Couldn't find mapped variable at index-subindex-size : ",
94                        (UNS16) (*pMappingParameter));
95               return 0xFF;
96             }
97           /* copy bit per bit in little endian */
98           CopyBits (Size, ((UNS8 *) tmp), 0, 0,
99                     (UNS8 *) & pdo->data[offset >> 3], offset % 8, 0);
100
101           offset += Size;
102         }
103       prp_j++;
104     }
105   while (prp_j < *pMappingCount);
106
107   pdo->len = 1 + ((offset - 1) >> 3);
108
109   MSG_WAR (0x3015, "  End scan mapped variable", 0);
110
111   return 0;
112 }
113
114 /*!
115 **
116 **
117 ** @param d
118 ** @param cobId
119 **
120 ** @return
121 **/
122 UNS8
123 sendPDOrequest (CO_Data * d, UNS16 RPDOIndex)
124 {
125   UNS32 *pwCobId;
126   UNS16 offset = d->firstIndex->PDO_RCV;
127   UNS16 lastIndex = d->lastIndex->PDO_RCV;
128
129   /* Sending the request only if the cobid have been found on the PDO
130      receive */
131   /* part dictionary */
132
133   MSG_WAR (0x3930, "sendPDOrequest RPDO Index : ", RPDOIndex);
134
135   if (offset && RPDOIndex >= 0x1400)
136     {
137       offset += RPDOIndex - 0x1400;
138       if (offset <= lastIndex)
139         {
140           /* get the CobId */
141           pwCobId = d->objdict[offset].pSubindex[1].pObject;
142
143           MSG_WAR (0x3930, "sendPDOrequest cobId is : ", *pwCobId);
144           {
145             Message pdo;
146             pdo.cob_id = UNS16_LE(*pwCobId);
147             pdo.rtr = REQUEST;
148             pdo.len = 0;
149             return canSend (d->canHandle, &pdo);
150           }
151         }
152     }
153   MSG_ERR (0x1931, "sendPDOrequest : RPDO Index not found : ", RPDOIndex);
154   return 0xFF;
155 }
156
157
158 /*!
159 **
160 **
161 ** @param d
162 ** @param m
163 **
164 ** @return
165 **/
166 UNS8
167 proceedPDO (CO_Data * d, Message * m)
168 {
169   UNS8 numPdo;
170   UNS8 numMap;                  /* Number of the mapped varable */
171   UNS8 *pMappingCount = NULL;   /* count of mapped objects... */
172   /* pointer to the var which is mapped to a pdo... */
173   /*  void *     pMappedAppObject = NULL;   */
174   /* pointer fo the var which holds the mapping parameter of an
175      mapping entry */
176   UNS32 *pMappingParameter = NULL;
177   UNS8 *pTransmissionType = NULL;       /* pointer to the transmission
178                                            type */
179   UNS32 *pwCobId = NULL;
180   UNS8 Size;
181   UNS8 offset;
182   UNS8 status;
183   UNS32 objDict;
184   UNS16 offsetObjdict;
185   UNS16 lastIndex;
186
187   status = state2;
188
189   MSG_WAR (0x3935, "proceedPDO, cobID : ", (UNS16_LE(m->cob_id) & 0x7ff));
190   offset = 0x00;
191   numPdo = 0;
192   numMap = 0;
193   if ((*m).rtr == NOT_A_REQUEST)
194     {                           /* The PDO received is not a
195                                    request. */
196
197       offsetObjdict = d->firstIndex->PDO_RCV;
198       lastIndex = d->lastIndex->PDO_RCV;
199
200       /* study of all the PDO stored in the dictionary */
201       if (offsetObjdict)
202         while (offsetObjdict <= lastIndex)
203           {
204
205             switch (status)
206               {
207
208               case state2:
209                 /* get CobId of the dictionary correspondant to the received
210                    PDO */
211                 pwCobId =
212                   d->objdict[offsetObjdict].pSubindex[1].pObject;
213                 /* check the CobId coherance */
214                 /*pwCobId is the cobId read in the dictionary at the state 3
215                  */
216                 if (*pwCobId == UNS16_LE(m->cob_id))
217                   {
218                     /* The cobId is recognized */
219                     status = state4;
220                     MSG_WAR (0x3936, "cobId found at index ",
221                              0x1400 + numPdo);
222                     break;
223                   }
224                 else
225                   {
226                     /* cobId received does not match with those write in the
227                        dictionnary */
228                     numPdo++;
229                     offsetObjdict++;
230                     status = state2;
231                     break;
232                   }
233
234               case state4:     /* Get Mapped Objects Number */
235                 /* The cobId of the message received has been found in the
236                    dictionnary. */
237                 offsetObjdict = d->firstIndex->PDO_RCV_MAP;
238                 lastIndex = d->lastIndex->PDO_RCV_MAP;
239                 pMappingCount =
240                   (UNS8 *) (d->objdict + offsetObjdict +
241                             numPdo)->pSubindex[0].pObject;
242                 numMap = 0;
243                 while (numMap < *pMappingCount)
244                   {
245                     UNS8 tmp[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
246                     UNS8 ByteSize;
247                     pMappingParameter =
248                       (UNS32 *) (d->objdict + offsetObjdict +
249                                  numPdo)->pSubindex[numMap + 1].pObject;
250                     if (pMappingParameter == NULL)
251                       {
252                         MSG_ERR (0x1937, "Couldn't get mapping parameter : ",
253                                  numMap + 1);
254                         return 0xFF;
255                       }
256                     /* Get the addresse of the mapped variable. */
257                     /* detail of *pMappingParameter : */
258                     /* The 16 hight bits contains the index, the medium 8 bits
259                        contains the subindex, */
260                     /* and the lower 8 bits contains the size of the mapped
261                        variable. */
262
263                     Size = (UNS8) (*pMappingParameter & (UNS32) 0x000000FF);
264
265                     /* set variable only if Size != 0 and Size is lower than remaining bits in the PDO */
266                     if (Size && ((offset + Size) <= (m->len << 3)))
267                       {
268                         /* copy bit per bit in little endian */
269                         CopyBits (Size, (UNS8 *) & m->data[offset >> 3],
270                                   offset % 8, 0, ((UNS8 *) tmp), 0, 0);
271
272                         ByteSize = 1 + ((Size - 1) >> 3);       /*1->8 => 1 ; 9->16 =>
273                                                                    2, ... */
274
275                         objDict =
276                           setODentry (d, (UNS16) ((*pMappingParameter) >> 16),
277                                       (UNS8) (((*pMappingParameter) >> 8) &
278                                               0xFF), tmp, &ByteSize, 0);
279
280                         if (objDict != OD_SUCCESSFUL)
281                           {
282                             MSG_ERR (0x1938,
283                                      "error accessing to the mapped var : ",
284                                      numMap + 1);
285                             MSG_WAR (0x2939, "         Mapped at index : ",
286                                      (*pMappingParameter) >> 16);
287                             MSG_WAR (0x2940, "                subindex : ",
288                                      ((*pMappingParameter) >> 8) & 0xFF);
289                             return 0xFF;
290                           }
291
292                         MSG_WAR (0x3942,
293                                  "Variable updated with value received by PDO cobid : ",
294                                  UNS16_LE(m->cob_id));
295                         MSG_WAR (0x3943, "         Mapped at index : ",
296                                  (*pMappingParameter) >> 16);
297                         MSG_WAR (0x3944, "                subindex : ",
298                                  ((*pMappingParameter) >> 8) & 0xFF);
299                         /* MSG_WAR(0x3945, "                data : ",*((UNS32*)pMappedAppObject)); */
300                         offset += Size;
301                       }
302                     numMap++;
303                   }             /* end loop while on mapped variables */
304
305                 return 0;
306
307               }                 /* end switch status */
308           }                     /* end while */
309     }                           /* end if Donnees */
310   else if ((*m).rtr == REQUEST)
311     {
312       MSG_WAR (0x3946, "Receive a PDO request cobId : ", UNS16_LE(m->cob_id));
313       status = state1;
314       offsetObjdict = d->firstIndex->PDO_TRS;
315       lastIndex = d->lastIndex->PDO_TRS;
316       if (offsetObjdict)
317         while (offsetObjdict <= lastIndex)
318           {
319             /* study of all PDO stored in the objects dictionary */
320
321             switch (status)
322               {
323
324               case state1:     /* check the CobId */
325                 /* get CobId of the dictionary which match to the received PDO
326                  */
327                 pwCobId =
328                    (d->objdict +
329                              offsetObjdict)->pSubindex[1].pObject;
330                 if (*pwCobId == UNS16_LE(m->cob_id))
331                   {
332                     status = state4;
333                     break;
334                   }
335                 else
336                   {
337                     numPdo++;
338                     offsetObjdict++;
339                   }
340                 status = state1;
341                 break;
342
343
344               case state4:     /* check transmission type */
345                 pTransmissionType =
346                   (UNS8 *) d->objdict[offsetObjdict].pSubindex[2].pObject;
347                 /* If PDO is to be sampled and send on RTR, do it */
348                 if ((*pTransmissionType == TRANS_RTR))
349                   {
350                     status = state5;
351                     break;
352                     /* RTR_SYNC mean data is prepared at SYNC, and transmitted on RTR */
353                   }
354                 else if ((*pTransmissionType == TRANS_RTR_SYNC))
355                   {
356                     if (d->PDO_status[numPdo].
357                         transmit_type_parameter & PDO_RTR_SYNC_READY)
358                       {
359                         /*Data ready, just send */
360                         canSend (d->canHandle,
361                                  &d->PDO_status[numPdo].last_message);
362                         return 0;
363                       }
364                     else
365                       {
366                         /* if SYNC did never occur, force emission with current data */
367                         /* DS301 do not tell what to do in such a case... */
368                         MSG_ERR (0x1947,
369                                  "Not ready RTR_SYNC TPDO send current data : ",
370                                  UNS16_LE(m->cob_id));
371                         status = state5;
372                       }
373                     break;
374                   }
375                 else if ((*pTransmissionType == TRANS_EVENT_PROFILE) ||
376                          (*pTransmissionType == TRANS_EVENT_SPECIFIC))
377                   {
378                     /* Zap all timers and inhibit flag */
379                     d->PDO_status[numPdo].event_timer =
380                       DelAlarm (d->PDO_status[numPdo].event_timer);
381                     d->PDO_status[numPdo].inhibit_timer =
382                       DelAlarm (d->PDO_status[numPdo].inhibit_timer);
383                     d->PDO_status[numPdo].transmit_type_parameter &=
384                       ~PDO_INHIBITED;
385                     /* Call  PDOEventTimerAlarm for this TPDO, this will trigger emission et reset timers */
386                     PDOEventTimerAlarm (d, numPdo);
387                     return 0;
388                   }
389                 else
390                   {
391                     /* The requested PDO is not to send on request. So, does
392                        nothing. */
393                     MSG_WAR (0x2947, "PDO is not to send on request : ",
394                              UNS16_LE(m->cob_id));
395                     return 0xFF;
396                   }
397
398               case state5:     /* build and send requested PDO */
399                 {
400                   Message pdo;
401                   if (buildPDO (d, numPdo, &pdo))
402                     {
403                       MSG_ERR (0x1948, " Couldn't build TPDO n�", numPdo);
404                       return 0xFF;
405                     }
406                   canSend (d->canHandle, &pdo);
407                   return 0;
408                 }
409               }                 /* end switch status */
410           }                     /* end while */
411     }                           /* end if Requete */
412
413   return 0;
414 }
415
416 /*!
417 **
418 **
419 ** @param NbBits
420 ** @param SrcByteIndex
421 ** @param SrcBitIndex
422 ** @param SrcBigEndian
423 ** @param DestByteIndex
424 ** @param DestBitIndex
425 ** @param DestBigEndian
426 **/
427 void
428 CopyBits (UNS8 NbBits, UNS8 * SrcByteIndex, UNS8 SrcBitIndex,
429           UNS8 SrcBigEndian, UNS8 * DestByteIndex, UNS8 DestBitIndex,
430           UNS8 DestBigEndian)
431 {
432   /* This loop copy as many bits that it can each time, crossing */
433   /* successively bytes */
434   // boundaries from LSB to MSB.
435   while (NbBits > 0)
436     {
437       /* Bit missalignement between src and dest */
438       INTEGER8 Vect = DestBitIndex - SrcBitIndex;
439
440       /* We can now get src and align it to dest */
441       UNS8 Aligned =
442         Vect > 0 ? *SrcByteIndex << Vect : *SrcByteIndex >> -Vect;
443
444       /* Compute the nb of bit we will be able to copy */
445       UNS8 BoudaryLimit = (Vect > 0 ? 8 - DestBitIndex : 8 - SrcBitIndex);
446       UNS8 BitsToCopy = BoudaryLimit > NbBits ? NbBits : BoudaryLimit;
447
448       /* Create a mask that will serve in: */
449       UNS8 Mask =
450         ((0xff << (DestBitIndex + BitsToCopy)) |
451          (0xff >> (8 - DestBitIndex)));
452
453       /* - Filtering src */
454       UNS8 Filtered = Aligned & ~Mask;
455
456       /* - and erase bits where we write, preserve where we don't */
457       *DestByteIndex &= Mask;
458
459       /* Then write. */
460       *DestByteIndex |= Filtered;
461
462       /*Compute next time cursors for src */
463       if ((SrcBitIndex += BitsToCopy) > 7)      /* cross boundary ? */
464         {
465           SrcBitIndex = 0;      /* First bit */
466           SrcByteIndex += (SrcBigEndian ? -1 : 1);      /* Next byte */
467         }
468
469
470       /*Compute next time cursors for dest */
471       if ((DestBitIndex += BitsToCopy) > 7)
472         {
473           DestBitIndex = 0;     /* First bit */
474           DestByteIndex += (DestBigEndian ? -1 : 1);    /* Next byte */
475         }
476
477       /*And decrement counter. */
478       NbBits -= BitsToCopy;
479     }
480
481 }
482
483 /*!
484 **
485 **
486 ** @param d
487 **
488 ** @return
489 **/
490
491 UNS8
492 sendPDOevent (CO_Data * d)
493 {
494   /* Calls _sendPDOevent specifying it is not a sync event */
495   return _sendPDOevent (d, 0);
496 }
497
498
499 void
500 PDOEventTimerAlarm (CO_Data * d, UNS32 pdoNum)
501 {
502   /* This is needed to avoid deletion of re-attribuated timer */
503   d->PDO_status[pdoNum].event_timer = TIMER_NONE;
504   /* force emission of PDO by artificially changing last emitted */
505   d->PDO_status[pdoNum].last_message.cob_id = 0;
506   _sendPDOevent (d, 0);         /* not a Sync Event */
507 }
508
509 void
510 PDOInhibitTimerAlarm (CO_Data * d, UNS32 pdoNum)
511 {
512   /* This is needed to avoid deletion of re-attribuated timer */
513   d->PDO_status[pdoNum].inhibit_timer = TIMER_NONE;
514   /* Remove inhibit flag */
515   d->PDO_status[pdoNum].transmit_type_parameter &= ~PDO_INHIBITED;
516   _sendPDOevent (d, 0);         /* not a Sync Event */
517 }
518
519 /*!
520 **
521 **
522 ** @param d
523 ** @param isSyncEvent
524 **
525 ** @return
526 **/
527
528 UNS8
529 _sendPDOevent (CO_Data * d, UNS8 isSyncEvent)
530 {
531   UNS8 pdoNum = 0x00;           /* number of the actual processed pdo-nr. */
532   UNS8 *pTransmissionType = NULL;
533   UNS8 status = state3;
534   UNS16 offsetObjdict = d->firstIndex->PDO_TRS;
535   UNS16 offsetObjdictMap = d->firstIndex->PDO_TRS_MAP;
536   UNS16 lastIndex = d->lastIndex->PDO_TRS;
537
538   /* study all PDO stored in the objects dictionary */
539   if (offsetObjdict)
540     {
541       Message pdo = Message_Initializer;
542       while (offsetObjdict <= lastIndex)
543         {
544           switch (status)
545             {
546             case state3:
547               if (              /*d->objdict[offsetObjdict].bSubCount < 5 || not necessary with objdictedit (always 5) */
548                    /* check if TPDO is not valid */
549                    *(UNS32 *) d->objdict[offsetObjdict].pSubindex[1].
550                    pObject & 0x80000000)
551                 {
552                   MSG_WAR (0x3960, "Not a valid PDO ", 0x1800 + pdoNum);
553                   /*Go next TPDO */
554                   status = state11;
555                   break;
556                 }
557               /* get the PDO transmission type */
558               pTransmissionType =
559                 (UNS8 *) d->objdict[offsetObjdict].pSubindex[2].pObject;
560               MSG_WAR (0x3962, "Reading PDO at index : ", 0x1800 + pdoNum);
561
562               /* check if transmission type is SYNCRONOUS */
563               /* The message is transmited every n SYNC with n=TransmissionType */
564               if (isSyncEvent &&
565                   (*pTransmissionType >= TRANS_SYNC_MIN) &&
566                   (*pTransmissionType <= TRANS_SYNC_MAX) &&
567                   (++d->PDO_status[pdoNum].transmit_type_parameter ==
568                    *pTransmissionType))
569                 {
570                   /*Reset count of SYNC */
571                   d->PDO_status[pdoNum].transmit_type_parameter = 0;
572                   MSG_WAR (0x3964, "  PDO is on SYNCHRO. Trans type : ",
573                            *pTransmissionType);
574                   {
575                     Message msg_init = Message_Initializer;
576                     pdo = msg_init;
577                   }
578                   if (buildPDO (d, pdoNum, &pdo))
579                     {
580                       MSG_ERR (0x1906, " Couldn't build TPDO number : ",
581                                pdoNum);
582                       status = state11;
583                       break;
584                     }
585                   status = state5;
586                   /* If transmission RTR, with data sampled on SYNC */
587                 }
588               else if (isSyncEvent && (*pTransmissionType == TRANS_RTR_SYNC))
589                 {
590                   if (buildPDO
591                       (d, pdoNum, &d->PDO_status[pdoNum].last_message))
592                     {
593                       MSG_ERR (0x1966, " Couldn't build TPDO number : ",
594                                pdoNum);
595                       d->PDO_status[pdoNum].transmit_type_parameter &=
596                         ~PDO_RTR_SYNC_READY;
597                     }
598                   else
599                     {
600                       d->PDO_status[pdoNum].transmit_type_parameter |=
601                         PDO_RTR_SYNC_READY;
602                     }
603                   status = state11;
604                   break;
605                   /* If transmission on Event and not inhibited, check for changes */
606                 }
607               else
608                 if ((isSyncEvent
609                      && (*pTransmissionType == TRANS_SYNC_ACYCLIC))
610                     ||
611                     ((*pTransmissionType == TRANS_EVENT_PROFILE
612                       || *pTransmissionType == TRANS_EVENT_SPECIFIC)
613                      && !(d->PDO_status[pdoNum].
614                           transmit_type_parameter & PDO_INHIBITED)))
615                 {
616                   MSG_WAR (0x3968, "  PDO is on EVENT. Trans type : ",
617                            *pTransmissionType);
618                   {
619                     Message msg_init = Message_Initializer;
620                     pdo = msg_init;
621                   }
622                   if (buildPDO (d, pdoNum, &pdo))
623                     {
624                       MSG_ERR (0x3907, " Couldn't build TPDO number : ",
625                                pdoNum);
626                       status = state11;
627                       break;
628                     }
629
630                   /*Compare new and old PDO */
631                   if (d->PDO_status[pdoNum].last_message.cob_id == pdo.cob_id
632                       && d->PDO_status[pdoNum].last_message.len == pdo.len &&
633 #ifdef UNS64
634                       *(UNS64 *) (&d->PDO_status[pdoNum].last_message.
635                                   data[0]) == *(UNS64 *) (&pdo.data[0])
636 #else /* don't ALLOW_64BIT_OPS */
637                       *(UNS32 *) (&d->PDO_status[pdoNum].last_message.
638                                   data[0]) == *(UNS32 *) (&pdo.data[0])
639                       && *(UNS32 *) (&d->PDO_status[pdoNum].last_message.
640                                      data[4]) == *(UNS32 *) (&pdo.data[4])
641 #endif
642                     )
643                     {
644                       /* No changes -> go to next pdo */
645                       status = state11;
646                     }
647                   else
648                     {
649
650                       UNS16 EventTimerDuration;
651                       UNS16 InhibitTimerDuration;
652
653                       MSG_WAR (0x306A, "Changes TPDO number : ", pdoNum);
654                       /* Changes detected -> transmit message */
655                       EventTimerDuration =
656                         *(UNS16 *) d->objdict[offsetObjdict].pSubindex[5].
657                         pObject;
658                       InhibitTimerDuration =
659                         *(UNS16 *) d->objdict[offsetObjdict].pSubindex[3].
660                         pObject;
661
662                       status = state5;
663
664                       /* Start both event_timer and inhibit_timer */
665                       if (EventTimerDuration)
666                         {
667                           DelAlarm (d->PDO_status[pdoNum].event_timer);
668                           d->PDO_status[pdoNum].event_timer =
669                             SetAlarm (d, pdoNum, &PDOEventTimerAlarm,
670                                       MS_TO_TIMEVAL (EventTimerDuration), 0);
671                         }
672
673                       if (InhibitTimerDuration)
674                         {
675                           DelAlarm (d->PDO_status[pdoNum].inhibit_timer);
676                           d->PDO_status[pdoNum].inhibit_timer =
677                             SetAlarm (d, pdoNum, &PDOInhibitTimerAlarm,
678                                       US_TO_TIMEVAL (InhibitTimerDuration *
679                                                      100), 0);
680                           /* and inhibit TPDO */
681                           d->PDO_status[pdoNum].transmit_type_parameter |=
682                             PDO_INHIBITED;
683                         }
684
685                     }
686                 }
687               else
688                 {
689                   MSG_WAR (0x306C,
690                            "  PDO is not on EVENT or synchro or not at this SYNC. Trans type : ",
691                            *pTransmissionType);
692                   status = state11;
693                 }
694               break;
695             case state5:       /*Send the pdo */
696               /*store_as_last_message */
697               d->PDO_status[pdoNum].last_message = pdo;
698               MSG_WAR (0x396D, "sendPDO cobId :", UNS16_LE(pdo.cob_id));
699               MSG_WAR (0x396E, "     Nb octets  : ", pdo.len);
700
701               canSend (d->canHandle, &pdo);
702               status = state11;
703               break;
704             case state11:      /*Go to next TPDO */
705               pdoNum++;
706               offsetObjdict++;
707               offsetObjdictMap++;
708               MSG_WAR (0x3970, "next pdo index : ", pdoNum);
709               status = state3;
710               break;
711
712             default:
713               MSG_ERR (0x1972, "Unknown state has been reached : %d", status);
714               return 0xFF;
715             }                   /* end switch case */
716
717         }                       /* end while */
718     }
719   return 0;
720 }
721
722 /*!
723 **
724 **
725 ** @param d
726 ** @param OD_entry
727 ** @param bSubindex 
728 ** @return always 0
729 **/
730
731 UNS32
732 TPDO_Communication_Parameter_Callback (CO_Data * d,
733                                        const indextable * OD_entry,
734                                        UNS8 bSubindex)
735 {
736   /* If PDO are actives */
737   if (d->CurrentCommunicationState.csPDO)
738     switch (bSubindex)
739       {
740       case 2:                  /* Changed transmition type */
741       case 3:                  /* Changed inhibit time */
742       case 5:                  /* Changed event time */
743         {
744           const indextable *TPDO_com = d->objdict + d->firstIndex->PDO_TRS;
745           UNS8 numPdo = OD_entry - TPDO_com;    /* number of the actual processed pdo-nr. */
746
747           /* Zap all timers and inhibit flag */
748           d->PDO_status[numPdo].event_timer =
749             DelAlarm (d->PDO_status[numPdo].event_timer);
750           d->PDO_status[numPdo].inhibit_timer =
751             DelAlarm (d->PDO_status[numPdo].inhibit_timer);
752           d->PDO_status[numPdo].transmit_type_parameter = 0;
753           /* Call  PDOEventTimerAlarm for this TPDO, this will trigger emission et reset timers */
754           PDOEventTimerAlarm (d, numPdo);
755           return 0;
756         }
757
758       default:                 /* other subindex are ignored */
759         break;
760       }
761   return 0;
762 }
763
764 void
765 PDOInit (CO_Data * d)
766 {
767   /* For each TPDO mapping parameters */
768   UNS16 pdoIndex = 0x1800;      /* OD index of TDPO */
769
770   UNS16 offsetObjdict = d->firstIndex->PDO_TRS;
771   UNS16 lastIndex = d->lastIndex->PDO_TRS;
772   if (offsetObjdict)
773     while (offsetObjdict <= lastIndex)
774       {
775         /* Assign callbacks to sensible TPDO mapping subindexes */
776         UNS32 errorCode;
777         ODCallback_t *CallbackList;
778         /* Find callback list */
779         scanIndexOD (d, pdoIndex, &errorCode, &CallbackList);
780         if (errorCode == OD_SUCCESSFUL && CallbackList)
781           {
782             /*Assign callbacks to corresponding subindex */
783             /* Transmission type */
784             CallbackList[2] = &TPDO_Communication_Parameter_Callback;
785             /* Inhibit time */
786             CallbackList[3] = &TPDO_Communication_Parameter_Callback;
787             /* Event timer */
788             CallbackList[5] = &TPDO_Communication_Parameter_Callback;
789           }
790         pdoIndex++;
791         offsetObjdict++;
792       }
793
794   /* Trigger a non-sync event */
795   _sendPDOevent (d, 0);
796 }
797
798 void
799 PDOStop (CO_Data * d)
800 {
801   /* For each TPDO mapping parameters */
802   UNS8 pdoNum = 0x00;           /* number of the actual processed pdo-nr. */
803   UNS16 offsetObjdict = d->firstIndex->PDO_TRS;
804   UNS16 lastIndex = d->lastIndex->PDO_TRS;
805   if (offsetObjdict)
806     while (offsetObjdict <= lastIndex)
807       {
808         /* Delete TPDO timers */
809         d->PDO_status[pdoNum].event_timer =
810           DelAlarm (d->PDO_status[pdoNum].event_timer);
811         d->PDO_status[pdoNum].inhibit_timer =
812           DelAlarm (d->PDO_status[pdoNum].inhibit_timer);
813         /* Reset transmit type parameter */
814         d->PDO_status[pdoNum].transmit_type_parameter = 0;
815         d->PDO_status[pdoNum].last_message.cob_id = 0;
816         pdoNum++;
817         offsetObjdict++;
818       }
819 }