2 This file is part of CanFestival, a library implementing CanOpen
5 Copyright (C): Edouard TISSERANT and Francis DUPIN
7 See COPYING file for copyrights details.
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.
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.
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
26 #include "canfestival.h"
30 ** @author Edouard TISSERANT and Francis DUPIN
31 ** @date Tue Jun 5 09:32:32 2007
37 UNS8 sendPDO(CO_Data* d, s_PDO pdo, UNS8 req)
40 if( d->nodeState == Operational ) {
43 /*! Message copy for sending */
44 m.cob_id.w = pdo.cobId & 0x7FF; /*! Because the cobId is 11 bytes
46 if ( req == NOT_A_REQUEST ) {
48 m.rtr = NOT_A_REQUEST;
50 /*! memcpy(&m.data, &pdo.data, m.len); */
51 /*! This Memcpy depends on packing structure. Avoid */
52 for (i = 0 ; i < pdo.len ; i++)
53 m.data[i] = pdo.data[i];
60 MSG_WAR(0x3901, "sendPDO cobId :", m.cob_id.w);
61 MSG_WAR(0x3902, " Nb octets : ", m.len);
62 for (i = 0 ; i < m.len ; i++) {
63 MSG_WAR(0x3903," data : ", m.data[i]);
66 return canSend(d->canHandle,&m);
79 UNS8 PDOmGR(CO_Data* d, UNS32 cobId)
85 MSG_WAR(0x3905, "PDOmGR",0);
87 /*! if PDO is waiting for transmission,
88 preparation of the message to send */
90 pdo.len = d->process_var.count;
91 /*! memcpy(&(pdo.data), &(process_var.data), pdo.len); */
92 /* Ce memcpy devrait tre portable */
93 for ( i = 0 ; i < pdo.len ; i++)
94 pdo.data[i] = d->process_var.data[i];
96 res = sendPDO(d, pdo, NOT_A_REQUEST);
102 /*********************************************************************/
103 /* TODO : implement bit mapping */
104 /*********************************************************************/
106 UNS8 buildPDO(CO_Data* d, UNS16 index)
107 { /* DO NOT USE MSG_ERR because the macro may send a PDO -> infinite loop if it fails. */
111 UNS8 * pMappingCount = NULL; /* count of mapped objects... */
112 /* pointer to the var which is mapped to a pdo */
113 /* void * pMappedAppObject = NULL; */
114 /* pointer fo the var which holds the mapping parameter of an mapping entry */
116 UNS32 * pMappingParameter = NULL;
122 UNS16 offsetObjdictPrm;
127 ind = index - 0x1800;
129 MSG_WAR(0x3910,"Prepare PDO to send index :", index);
131 /*! only operational state allows PDO transmission */
132 if( d->nodeState != Operational ) {
133 MSG_WAR(0x2911, "Unable to send the PDO (node not in OPERATIONAL mode). Node : ", index);
136 offsetObjdictPrm = d->firstIndex->PDO_TRS;
137 offsetObjdict = d->firstIndex->PDO_TRS_MAP;
139 if (offsetObjdictPrm && offsetObjdict)
141 /*! get mapped objects number to transmit with this PDO */
142 pMappingCount = (d->objdict + offsetObjdict + ind)->pSubindex[0].pObject;
143 MSG_WAR(0x3912, "Nb maped objects : ",* pMappingCount);
144 MSG_WAR(0x3913, " at index : ", 0x1A00 + ind);
145 while (subInd < *pMappingCount) { /*! Loop on mapped variables */
146 /*! get mapping parameters */
147 pMappingParameter = (d->objdict + offsetObjdict + ind)->pSubindex[subInd + 1].pObject;
148 MSG_WAR(0x3914, "Get the mapping at index : ", (UNS16)0x1A00 + ind);
149 MSG_WAR(0x3915, " subIndex : ", subInd + 1);
150 MSG_WAR(0x3916, " value : ", *(UNS32 *)pMappingParameter);
151 /*! Get the mapped variable */
152 Size = ((UNS8)(((*pMappingParameter) & 0xFF) >> 3));
153 objDict = getODentry(d, (UNS16)((*pMappingParameter) >> 16),
154 (UNS8)(((*pMappingParameter) >> 8 ) & 0x000000FF),
155 (void *)&d->process_var.data[offset], &Size, &dataType, 0 );
157 if (objDict != OD_SUCCESSFUL) {
158 MSG_WAR(0x2919, "error accessing to the mapped var : ", subInd + 1);
159 MSG_WAR(0x2920, " Mapped at index : ", (*pMappingParameter) >> 16);
160 MSG_WAR(0x2921, " subindex : ", ((*pMappingParameter) >> 8 ) & 0xFF);
165 d->process_var.count = offset;
167 }/*! end Loop on mapped variables */
181 UNS8 sendPDOrequest( CO_Data* d, UNS32 cobId )
188 MSG_WAR(0x3930, "sendPDOrequest ",0);
189 /*! Sending the request only if the cobid have been found on the PDO
191 /*! part dictionary */
192 offset = d->firstIndex->PDO_RCV;
193 lastIndex = d->lastIndex->PDO_RCV;
195 while (offset <= lastIndex) {
197 pwCobId = d->objdict[offset].pSubindex[1].pObject;
199 if ( *pwCobId == cobId ) {
201 pdo.cobId = *pwCobId;
203 err = sendPDO(d, pdo, REQUEST);
208 MSG_WAR(0x1931, "sendPDOrequest : COBID not found : ", cobId);
221 UNS8 proceedPDO(CO_Data* d, Message *m)
224 UNS8 numMap; /*! Number of the mapped varable */
226 UNS8 * pMappingCount = NULL; /*! count of mapped objects... */
227 /*! pointer to the var which is mapped to a pdo... */
228 /*! void * pMappedAppObject = NULL; */
229 /*! pointer fo the var which holds the mapping parameter of an
231 UNS32 * pMappingParameter = NULL;
232 UNS8 * pTransmissionType = NULL; /*! pointer to the transmission
234 UNS32 * pwCobId = NULL;
244 MSG_WAR(0x3935, "proceedPDO, cobID : ", ((*m).cob_id.w & 0x7ff));
248 if((*m).rtr == NOT_A_REQUEST ) { /*! The PDO received is not a
250 offsetObjdict = d->firstIndex->PDO_RCV;
251 lastIndex = d->lastIndex->PDO_RCV;
253 /*! study of all the PDO stored in the dictionary */
255 while (offsetObjdict <= lastIndex) {
259 case state1:/*! data are stored in process_var array */
260 /*! memcpy(&(process_var.data), &m->data, (*m).len); */
261 /*! Ce memcpy devrait etre portable */
262 for ( i = 0 ; i < m->len ; i++)
263 d->process_var.data[i] = m->data[i];
264 d->process_var.count = (*m).len;
270 /*! get CobId of the dictionary correspondant to the received
272 pwCobId = d->objdict[offsetObjdict].pSubindex[1].pObject;
273 /*! check the CobId coherance */
274 /*!pwCobId is the cobId read in the dictionary at the state 3
276 if ( *pwCobId == (*m).cob_id.w ){
277 /*! The cobId is recognized */
279 MSG_WAR(0x3936, "cobId found at index ", 0x1400 + numPdo);
283 /*! cobId received does not match with those write in the
291 case state4:/*! Get Mapped Objects Number */
292 /*! The cobId of the message received has been found in the
294 offsetObjdict = d->firstIndex->PDO_RCV_MAP;
295 lastIndex = d->lastIndex->PDO_RCV_MAP;
296 pMappingCount = (d->objdict + offsetObjdict + numPdo)->pSubindex[0].pObject;
298 while (numMap < *pMappingCount) {
299 UNS8 tmp[]= {0,0,0,0,0,0,0,0};
301 pMappingParameter = (d->objdict + offsetObjdict + numPdo)->pSubindex[numMap + 1].pObject;
302 if (pMappingParameter == NULL) {
303 MSG_ERR(0x1937, "Couldn't get mapping parameter : ", numMap + 1);
306 /*! Get the addresse of the mapped variable. */
307 /*! detail of *pMappingParameter : */
308 /*! The 16 hight bits contains the index, the medium 8 bits
309 contains the subindex, */
310 /*! and the lower 8 bits contains the size of the mapped
313 Size = (UNS8)(*pMappingParameter);
315 /*! copy bit per bit in little endian */
316 CopyBits(Size, (UNS8*)&d->process_var.data[offset>>3], offset%8, 0, ((UNS8*)tmp), 0, 0);
318 ByteSize = 1 + ((Size - 1) >> 3); /*1->8 => 1 ; 9->16 =>
321 objDict = setODentry(d, (UNS16)((*pMappingParameter) >> 16),
322 (UNS8)(((*pMappingParameter) >> 8 ) & 0xFF),
325 if(objDict != OD_SUCCESSFUL) {
326 MSG_ERR(0x1938, "error accessing to the mapped var : ", numMap + 1);
327 MSG_WAR(0x2939, " Mapped at index : ", (*pMappingParameter) >> 16);
328 MSG_WAR(0x2940, " subindex : ", ((*pMappingParameter) >> 8 ) & 0xFF);
332 MSG_WAR(0x3942, "Variable updated with value received by PDO cobid : ", m->cob_id.w);
333 MSG_WAR(0x3943, " Mapped at index : ", (*pMappingParameter) >> 16);
334 MSG_WAR(0x3944, " subindex : ", ((*pMappingParameter) >> 8 ) & 0xFF);
335 /*! MSG_WAR(0x3945, " data : ",*((UNS32*)pMappedAppObject)); */
338 } /*! end loop while on mapped variables */
344 }/*! end switch status*/
346 }/*! end if Donnees */
347 else if ((*m).rtr == REQUEST ){
348 MSG_WAR(0x3946, "Receive a PDO request cobId : ", m->cob_id.w);
350 offsetObjdict = d->firstIndex->PDO_TRS;
351 lastIndex = d->lastIndex->PDO_TRS;
352 if(offsetObjdict) while( offsetObjdict <= lastIndex ){
353 /*! study of all PDO stored in the objects dictionary */
357 case state1:/*! check the CobId */
358 /*! get CobId of the dictionary which match to the received PDO
360 pwCobId = (d->objdict + offsetObjdict)->pSubindex[1].pObject;
361 if ( *pwCobId == (*m).cob_id.w ) {
373 case state4:/*! check transmission type (after request?) */
374 pTransmissionType = d->objdict[offsetObjdict].pSubindex[2].pObject;
375 if ( (*pTransmissionType == TRANS_RTR) || (*pTransmissionType == TRANS_RTR_SYNC ) || (*pTransmissionType == TRANS_EVENT) ) {
380 /*! The requested PDO is not to send on request. So, does
382 MSG_WAR(0x2947, "PDO is not to send on request : ", m->cob_id.w);
386 case state5:/*! get mapped objects number */
387 offsetObjdict = d->firstIndex->PDO_TRS_MAP;
388 lastIndex = d->lastIndex->PDO_TRS_MAP;
389 pMappingCount = (d->objdict + offsetObjdict + numPdo)->pSubindex[0].pObject;
391 while (numMap < *pMappingCount) {
392 pMappingParameter = (d->objdict + offsetObjdict + numPdo)->pSubindex[numMap + 1].pObject;
393 /*! Get the mapped variable */
394 Size = ((UNS8)(((*pMappingParameter) & 0xFF) >> 3));
395 objDict = getODentry( d, (UNS16)((*pMappingParameter) >> (UNS8)16),
396 (UNS8)(( (*pMappingParameter) >> (UNS8)8 ) & 0xFF),
397 (void *)&d->process_var.data[offset], &Size, &dataType, 0 );
398 if (objDict != OD_SUCCESSFUL) {
399 MSG_ERR(0x1948, "error accessing to the mapped var : ", numMap + 1);
400 MSG_WAR(0x2949, " Mapped at index : ", (*pMappingParameter) >> 16);
401 MSG_WAR(0x2950, " subindex : ", ((*pMappingParameter) >> 8 ) & 0xFF);
404 offset += (UNS8) (((*pMappingParameter) & 0xFF) >> 3);
405 d->process_var.count = offset;
409 PDOmGR( d, *pwCobId ); /*! Transmit the PDO */
412 }/*! end switch status */
414 }/*! end if Requete */
423 ** @param SrcByteIndex
424 ** @param SrcBitIndex
425 ** @param SrcBigEndian
426 ** @param DestByteIndex
427 ** @param DestBitIndex
428 ** @param DestBigEndian
430 void CopyBits(UNS8 NbBits, UNS8* SrcByteIndex, UNS8 SrcBitIndex, UNS8 SrcBigEndian, UNS8* DestByteIndex, UNS8 DestBitIndex, UNS8 DestBigEndian)
432 /*! This loop copy as many bits that it can each time, crossing*/
433 /*! successively bytes*/
434 // boundaries from LSB to MSB.
437 /*! Bit missalignement between src and dest*/
438 INTEGER8 Vect = DestBitIndex - SrcBitIndex;
440 /*! We can now get src and align it to dest*/
441 UNS8 Aligned = Vect>0 ? *SrcByteIndex << Vect : *SrcByteIndex >> -Vect;
443 /*! Compute the nb of bit we will be able to copy*/
444 UNS8 BoudaryLimit = (Vect>0 ? 8 - DestBitIndex : 8 - SrcBitIndex );
445 UNS8 BitsToCopy = BoudaryLimit > NbBits ? NbBits : BoudaryLimit;
447 /*! Create a mask that will serve in:*/
448 UNS8 Mask = ((0xff << (DestBitIndex + BitsToCopy)) | (0xff >> (8 - DestBitIndex)));
450 /*! - Filtering src*/
451 UNS8 Filtered = Aligned & ~Mask;
453 /*! - and erase bits where we write, preserve where we don't*/
454 *DestByteIndex &= Mask;
457 *DestByteIndex |= Filtered ;
459 /*!Compute next time cursors for src*/
460 if((SrcBitIndex += BitsToCopy)>7)/*! cross boundary ?*/
462 SrcBitIndex = 0;/*! First bit*/
463 SrcByteIndex += (SrcBigEndian ? -1 : 1);/*! Next byte*/
467 /*!Compute next time cursors for dest*/
468 if((DestBitIndex += BitsToCopy)>7)
470 DestBitIndex = 0;/*! First bit*/
471 DestByteIndex += (DestBigEndian ? -1 : 1);/*! Next byte*/
474 /*!And decrement counter.*/
475 NbBits -= BitsToCopy;
482 /*********************************************************************/
483 /* TODO : reimplement this using CallBacks
485 /*********************************************************************/
495 UNS8 sendPDOevent( CO_Data* d, void * variable )
496 { /*! DO NOT USE MSG_ERR because the macro may send a PDO -> infinite
502 UNS8 * pMappingCount = NULL;
503 UNS32 * pMappingParameter = NULL;
504 void * pMappedAppObject = NULL;
505 UNS8 * pTransmissionType = NULL; /*! pointer to the transmission
507 UNS32 * pwCobId = NULL;
512 UNS16 offsetObjdictPrm;
522 /*! look for the index and subindex where the variable is mapped */
523 /*! Then, send the pdo which contains the variable. */
525 MSG_WAR (0x3960, "sendPDOevent", 0);
526 offsetObjdictPrm = d->firstIndex->PDO_TRS;
528 offsetObjdict = d->firstIndex->PDO_TRS_MAP;
529 lastIndex = d->lastIndex->PDO_TRS_MAP;
531 if (offsetObjdictPrm && offsetObjdict)
532 /*! Loop on PDO Transmit */
533 while(offsetObjdict <= lastIndex){
534 /*! Check the transmission mode */
535 pTransmissionType = d->objdict[offsetObjdictPrm].pSubindex[2].pObject;
536 if (*pTransmissionType != TRANS_EVENT) {
542 pMappingCount = d->objdict[offsetObjdict].pSubindex[0].pObject;
543 numMap = 1; /*! mapped variable */
544 while (numMap <= *pMappingCount) {
545 pMappingParameter = d->objdict[offsetObjdict].pSubindex[numMap].pObject;
546 /*! Get the variable */
547 objDict = getODentry( d,
548 (UNS16)((*pMappingParameter) >> 16),
549 (UNS8)(( (*pMappingParameter) >> (UNS8)8 ) & (UNS32)0x000000FF),
550 (void * *)&pMappedAppObject, pSize, &dataType, 0 );
551 if( objDict != OD_SUCCESSFUL ) {
552 MSG_WAR(0x2961, "Error in dict. at index : ",
553 (*pMappingParameter) >> (UNS8)16);
555 MSG_WAR(0x2962, " subindex : ",
556 ((*pMappingParameter) >> (UNS8)8 ) & (UNS32)0x000000FF);
559 if (pMappedAppObject == variable) { // Variable found !
560 MSG_WAR(0x3963, "Variable to send found at index : ",
561 (*pMappingParameter) >> 16);
562 MSG_WAR(0x3964, " subIndex : ",
563 ((*pMappingParameter) >> 8 ) & 0x000000FF);
564 buildPDO(d, 0x1800 + ind);
566 pwCobId = d->objdict[offsetObjdictPrm].pSubindex[1].pObject;
567 PDOmGR( d, *pwCobId ); /*! Send the PDO */
571 } /*! End loop on mapped variable */
575 } /*! End loop while on PDO */
577 MSG_WAR(0x2965, "Variable not found in a PDO to send on event", 0);