2 This file is part of CanFestival, a library implementing CanOpen Stack.
4 Copyright (C): Edouard TISSERANT and Francis DUPIN
6 See COPYING file for copyrights details.
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.
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.
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
24 #include "canfestival.h"
26 /****************************************************************************/
27 UNS8 sendPDO(CO_Data* d, s_PDO pdo, UNS8 req)
30 if( d->nodeState == Operational ) {
33 /* Message copy for sending */
34 m.cob_id.w = pdo.cobId & 0x7FF; /* Because the cobId is 11 bytes length */
35 if ( req == NOT_A_REQUEST ) {
37 m.rtr = NOT_A_REQUEST;
39 /* memcpy(&m.data, &pdo.data, m.len); */
40 /* This Memcpy depends on packing structure. Avoid */
41 for (i = 0 ; i < pdo.len ; i++)
42 m.data[i] = pdo.data[i];
49 MSG_WAR(0x3901, "sendPDO cobId :", m.cob_id.w);
50 MSG_WAR(0x3902, " Nb octets : ", m.len);
51 for (i = 0 ; i < m.len ; i++) {
52 MSG_WAR(0x3903," data : ", m.data[i]);
55 return canSend(d->canHandle,&m);
60 /***************************************************************************/
61 UNS8 PDOmGR(CO_Data* d, UNS32 cobId) /* PDO Manager */
67 MSG_WAR(0x3905, "PDOmGR",0);
69 /* if PDO is waiting for transmission,
70 preparation of the message to send */
72 pdo.len = d->process_var.count;
73 /* memcpy(&(pdo.data), &(process_var.data), pdo.len); */
74 /* Ce memcpy devrait ĂȘtre portable */
75 for ( i = 0 ; i < pdo.len ; i++)
76 pdo.data[i] = d->process_var.data[i];
78 res = sendPDO(d, pdo, NOT_A_REQUEST);
84 /*********************************************************************/
85 /* TODO : implement bit mapping */
86 /*********************************************************************/
88 UNS8 buildPDO(CO_Data* d, UNS16 index)
89 { /* DO NOT USE MSG_ERR because the macro may send a PDO -> infinite loop if it fails. */
93 UNS8 * pMappingCount = NULL; /* count of mapped objects... */
94 /* pointer to the var which is mapped to a pdo */
95 /* void * pMappedAppObject = NULL; */
96 /* pointer fo the var which holds the mapping parameter of an mapping entry */
97 UNS32 * pMappingParameter = NULL;
103 UNS16 offsetObjdictPrm;
108 ind = index - 0x1800;
110 MSG_WAR(0x3910,"Prepare PDO to send index :", index);
112 /* only operational state allows PDO transmission */
113 if( d->nodeState != Operational ) {
114 MSG_WAR(0x2911, "Unable to send the PDO (node not in OPERATIONAL mode). Node : ", index);
117 offsetObjdictPrm = d->firstIndex->PDO_TRS;
118 offsetObjdict = d->firstIndex->PDO_TRS_MAP;
120 if (offsetObjdictPrm && offsetObjdict)
122 /* get mapped objects number to transmit with this PDO */
123 pMappingCount = (d->objdict + offsetObjdict + ind)->pSubindex[0].pObject;
124 MSG_WAR(0x3912, "Nb maped objects : ",* pMappingCount);
125 MSG_WAR(0x3913, " at index : ", 0x1A00 + ind);
126 while (subInd < *pMappingCount) { /* Loop on mapped variables */
127 /* get mapping parameters */
128 pMappingParameter = (d->objdict + offsetObjdict + ind)->pSubindex[subInd + 1].pObject;
129 MSG_WAR(0x3914, "Get the mapping at index : ", (UNS16)0x1A00 + ind);
130 MSG_WAR(0x3915, " subIndex : ", subInd + 1);
131 MSG_WAR(0x3916, " value : ", *(UNS32 *)pMappingParameter);
132 /* Get the mapped variable */
133 Size = ((UNS8)(((*pMappingParameter) & 0xFF) >> 3));
134 objDict = getODentry(d, (UNS16)((*pMappingParameter) >> 16),
135 (UNS8)(((*pMappingParameter) >> 8 ) & 0x000000FF),
136 (void *)&d->process_var.data[offset], &Size, &dataType, 0 );
138 if (objDict != OD_SUCCESSFUL) {
139 MSG_WAR(0x2919, "error accessing to the mapped var : ", subInd + 1);
140 MSG_WAR(0x2920, " Mapped at index : ", (*pMappingParameter) >> 16);
141 MSG_WAR(0x2921, " subindex : ", ((*pMappingParameter) >> 8 ) & 0xFF);
146 d->process_var.count = offset;
148 }/* end Loop on mapped variables */
153 /**************************************************************************/
154 UNS8 sendPDOrequest( CO_Data* d, UNS32 cobId )
161 MSG_WAR(0x3930, "sendPDOrequest ",0);
162 /* Sending the request only if the cobid have been found on the PDO receive */
163 /* part dictionary */
164 offset = d->firstIndex->PDO_RCV;
165 lastIndex = d->lastIndex->PDO_RCV;
167 while (offset <= lastIndex) {
169 pwCobId = d->objdict[offset].pSubindex[1].pObject;
171 if ( *pwCobId == cobId ) {
173 pdo.cobId = *pwCobId;
175 err = sendPDO(d, pdo, REQUEST);
180 MSG_WAR(0x1931, "sendPDOrequest : COBID not found : ", cobId);
186 /***********************************************************************/
187 UNS8 proceedPDO(CO_Data* d, Message *m)
190 UNS8 numMap; /* Number of the mapped varable */
192 UNS8 * pMappingCount = NULL; /* count of mapped objects... */
193 /* pointer to the var which is mapped to a pdo... */
194 /* void * pMappedAppObject = NULL; */
195 /* pointer fo the var which holds the mapping parameter of an mapping entry */
196 UNS32 * pMappingParameter = NULL;
197 UNS8 * pTransmissionType = NULL; /* pointer to the transmission type */
198 UNS32 * pwCobId = NULL;
210 MSG_WAR(0x3935, "proceedPDO, cobID : ", ((*m).cob_id.w & 0x7ff));
214 if((*m).rtr == NOT_A_REQUEST ) { /* The PDO received is not a request. */
215 offsetObjdict = d->firstIndex->PDO_RCV;
216 lastIndex = d->lastIndex->PDO_RCV;
218 /* study of all the PDO stored in the dictionary */
220 while (offsetObjdict <= lastIndex) {
224 case state1: /* data are stored in process_var array */
225 /* memcpy(&(process_var.data), &m->data, (*m).len); */
226 /* Ce memcpy devrait ĂȘtre portable. */
227 for ( i = 0 ; i < m->len ; i++)
228 d->process_var.data[i] = m->data[i];
229 d->process_var.count = (*m).len;
235 /* get CobId of the dictionary correspondant to the received PDO */
236 pwCobId = d->objdict[offsetObjdict].pSubindex[1].pObject;
237 /* check the CobId coherance */
238 /*pwCobId is the cobId read in the dictionary at the state 3 */
239 if ( *pwCobId == (*m).cob_id.w ){
240 /* The cobId is recognized */
242 MSG_WAR(0x3936, "cobId found at index ", 0x1400 + numPdo);
246 /* cobId received does not match with those write in the dictionnary */
253 case state4: /* get mapped objects number */
254 /* The cobId of the message received has been found in the dictionnary. */
255 offsetObjdict = d->firstIndex->PDO_RCV_MAP;
256 lastIndex = d->lastIndex->PDO_RCV_MAP;
257 pMappingCount = (d->objdict + offsetObjdict + numPdo)->pSubindex[0].pObject;
259 while (numMap < *pMappingCount) {
260 UNS8 tmp[]= {0,0,0,0,0,0,0,0};
262 pMappingParameter = (d->objdict + offsetObjdict + numPdo)->pSubindex[numMap + 1].pObject;
263 if (pMappingParameter == NULL) {
264 MSG_ERR(0x1937, "Couldn't get mapping parameter : ", numMap + 1);
267 /* Get the addresse of the mapped variable. */
268 /* detail of *pMappingParameter : */
269 /* The 16 hight bits contains the index, the medium 8 bits contains the subindex, */
270 /* and the lower 8 bits contains the size of the mapped variable. */
272 Size = (UNS8)(*pMappingParameter);
274 /* copy bit per bit in little endian */
275 CopyBits(Size, (UNS8*)&d->process_var.data[offset>>3], offset%8, 0, ((UNS8*)tmp), 0, 0);
277 ByteSize = 1 + ((Size - 1) >> 3); /*1->8 => 1 ; 9->16 => 2, ... */
279 objDict = setODentry(d, (UNS16)((*pMappingParameter) >> 16),
280 (UNS8)(((*pMappingParameter) >> 8 ) & 0xFF),
283 if(objDict != OD_SUCCESSFUL) {
284 MSG_ERR(0x1938, "error accessing to the mapped var : ", numMap + 1);
285 MSG_WAR(0x2939, " Mapped at index : ", (*pMappingParameter) >> 16);
286 MSG_WAR(0x2940, " subindex : ", ((*pMappingParameter) >> 8 ) & 0xFF);
290 MSG_WAR(0x3942, "Variable updated with value received by PDO cobid : ", m->cob_id.w);
291 MSG_WAR(0x3943, " Mapped at index : ", (*pMappingParameter) >> 16);
292 MSG_WAR(0x3944, " subindex : ", ((*pMappingParameter) >> 8 ) & 0xFF);
293 /* MSG_WAR(0x3945, " data : ",*((UNS32 *)pMappedAppObject)); */
296 } /* end loop while on mapped variables */
302 }/* end switch status */
304 }/* end if Donnees */
307 else if ((*m).rtr == REQUEST ){
308 MSG_WAR(0x3946, "Receive a PDO request cobId : ", m->cob_id.w);
310 offsetObjdict = d->firstIndex->PDO_TRS;
311 lastIndex = d->lastIndex->PDO_TRS;
312 if(offsetObjdict) while( offsetObjdict <= lastIndex ){
313 /* study of all PDO stored in the objects dictionary */
317 case state1: /* check the CobId */
318 /* get CobId of the dictionary which match to the received PDO */
319 pwCobId = (d->objdict + offsetObjdict)->pSubindex[1].pObject;
320 if ( *pwCobId == (*m).cob_id.w ) {
332 case state4: /* check transmission type (after request?) */
333 pTransmissionType = d->objdict[offsetObjdict].pSubindex[2].pObject;
334 if ( (*pTransmissionType == TRANS_RTR) || (*pTransmissionType == TRANS_RTR_SYNC ) || (*pTransmissionType == TRANS_EVENT) ) {
339 /* The requested PDO is not to send on request. So, does nothing. */
340 MSG_WAR(0x2947, "PDO is not to send on request : ", m->cob_id.w);
344 case state5: /* get mapped objects number */
345 offsetObjdict = d->firstIndex->PDO_TRS_MAP;
346 lastIndex = d->lastIndex->PDO_TRS_MAP;
347 pMappingCount = (d->objdict + offsetObjdict + numPdo)->pSubindex[0].pObject;
349 while (numMap < *pMappingCount) {
350 pMappingParameter = (d->objdict + offsetObjdict + numPdo)->pSubindex[numMap + 1].pObject;
351 /* Get the mapped variable */
352 Size = ((UNS8)(((*pMappingParameter) & 0xFF) >> 3));
353 objDict = getODentry( d, (UNS16)((*pMappingParameter) >> (UNS8)16),
354 (UNS8)(( (*pMappingParameter) >> (UNS8)8 ) & 0xFF),
355 (void *)&d->process_var.data[offset], &Size, &dataType, 0 );
356 if (objDict != OD_SUCCESSFUL) {
357 MSG_ERR(0x1948, "error accessing to the mapped var : ", numMap + 1);
358 MSG_WAR(0x2949, " Mapped at index : ", (*pMappingParameter) >> 16);
359 MSG_WAR(0x2950, " subindex : ", ((*pMappingParameter) >> 8 ) & 0xFF);
362 offset += (UNS8) (((*pMappingParameter) & 0xFF) >> 3);
363 d->process_var.count = offset;
367 PDOmGR( d, *pwCobId ); /* Transmit the PDO */
370 }/* end switch status */
372 }/* end if Requete */
378 void CopyBits(UNS8 NbBits, UNS8* SrcByteIndex, UNS8 SrcBitIndex, UNS8 SrcBigEndian, UNS8* DestByteIndex, UNS8 DestBitIndex, UNS8 DestBigEndian)
380 //This loop copy as many bits that it can each time, crossing successively bytes
381 // boundaries from LSB to MSB.
384 // Bit missalignement between src and dest
385 INTEGER8 Vect = DestBitIndex - SrcBitIndex;
387 // We can now get src and align it to dest
388 UNS8 Aligned = Vect>0 ? *SrcByteIndex << Vect : *SrcByteIndex >> -Vect;
390 // Compute the nb of bit we will be able to copy
391 UNS8 BoudaryLimit = (Vect>0 ? 8 - DestBitIndex : 8 - SrcBitIndex );
392 UNS8 BitsToCopy = BoudaryLimit > NbBits ? NbBits : BoudaryLimit;
394 // Create a mask that will serve in:
395 UNS8 Mask = ((0xff << (DestBitIndex + BitsToCopy)) | (0xff >> (8 - DestBitIndex)));
398 UNS8 Filtered = Aligned & ~Mask;
400 // - and erase bits where we write, preserve where we don't
401 *DestByteIndex &= Mask;
404 *DestByteIndex |= Filtered ;
406 //Compute next time cursors for src
407 if((SrcBitIndex += BitsToCopy)>7) // cross boundary ?
409 SrcBitIndex = 0; // First bit
410 SrcByteIndex += (SrcBigEndian ? -1 : 1); // Next byte
413 //Compute next time cursors for dest
414 if((DestBitIndex += BitsToCopy)>7)
416 DestBitIndex = 0; // First bit
417 DestByteIndex += (DestBigEndian ? -1 : 1);// Next byte
420 //And decrement counter.
421 NbBits -= BitsToCopy;
428 /*********************************************************************/
429 /* TODO : reimplement this using CallBacks */
430 /*********************************************************************/
432 UNS8 sendPDOevent( CO_Data* d, void * variable )
433 { /* DO NOT USE MSG_ERR because the macro may send a PDO -> infinite loop if it fails. */
438 UNS8 * pMappingCount = NULL;
439 UNS32 * pMappingParameter = NULL;
440 void * pMappedAppObject = NULL;
441 UNS8 * pTransmissionType = NULL; /* pointer to the transmission type */
442 UNS32 * pwCobId = NULL;
447 UNS16 offsetObjdictPrm;
456 /* look for the index and subindex where the variable is mapped */
457 /* Then, send the pdo which contains the variable. */
459 MSG_WAR (0x3960, "sendPDOevent", 0);
460 offsetObjdictPrm = d->firstIndex->PDO_TRS;
462 offsetObjdict = d->firstIndex->PDO_TRS_MAP;
463 lastIndex = d->lastIndex->PDO_TRS_MAP;
465 if (offsetObjdictPrm && offsetObjdict)
466 /* Loop on PDO Transmit */
467 while(offsetObjdict <= lastIndex){
468 /* Check the transmission mode */
469 pTransmissionType = d->objdict[offsetObjdictPrm].pSubindex[2].pObject;
470 if (*pTransmissionType != TRANS_EVENT) {
476 pMappingCount = d->objdict[offsetObjdict].pSubindex[0].pObject;
477 numMap = 1; /* mapped variable */
478 while (numMap <= *pMappingCount) {
479 pMappingParameter = d->objdict[offsetObjdict].pSubindex[numMap].pObject;
480 /* Get the variable */
481 objDict = getODentry( d,
482 (UNS16)((*pMappingParameter) >> 16),
483 (UNS8)(( (*pMappingParameter) >> (UNS8)8 ) & (UNS32)0x000000FF),
484 (void * *)&pMappedAppObject, pSize, &dataType, 0 );
485 if( objDict != OD_SUCCESSFUL ) {
486 MSG_WAR(0x2961, "Error in dict. at index : ",
487 (*pMappingParameter) >> (UNS8)16);
489 MSG_WAR(0x2962, " subindex : ",
490 ((*pMappingParameter) >> (UNS8)8 ) & (UNS32)0x000000FF);
493 if (pMappedAppObject == variable) { // Variable found !
494 MSG_WAR(0x3963, "Variable to send found at index : ",
495 (*pMappingParameter) >> 16);
496 MSG_WAR(0x3964, " subIndex : ",
497 ((*pMappingParameter) >> 8 ) & 0x000000FF);
498 buildPDO(d, 0x1800 + ind);
500 pwCobId = d->objdict[offsetObjdictPrm].pSubindex[1].pObject;
501 PDOmGR( d, *pwCobId ); /* Send the PDO */
505 } /* End loop on mapped variable */
509 } /* End loop while on PDO */
511 MSG_WAR(0x2965, "Variable not found in a PDO to send on event", 0);