com_manager.c
Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright (c) 2014-2021 Inertial Sense, Inc. - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #include "com_manager.h"
14 #include <string.h>
15 #include <stdlib.h>
16 
17 
18 // enable filtering of duplicate packets
19 #define ENABLE_FILTER_DUPLICATE_PACKETS 1
20 
21 // whether the first character or all characters are checked in duplicate packets
22 #define ENABLE_FILTER_DUPLICATE_PACKETS_MATCH_ALL_CHARACTERS 0
23 
24 #define PARSE_DOUBLE(str) strtod(str, 0)
25 #define PARSE_FLOAT(str) strtof(str, 0)
26 
27 #define MIN_REQUEST_PERIOD_MS 1 // (ms) 1 KHz
28 #define MAX_REQUEST_PERIOD_MS 100000 // (ms)
29 #define MSG_PERIOD_SEND_ONCE -1
30 #define MSG_PERIOD_DISABLED 0
31 
33 
35 (
36  com_manager_t* cmInstance,
37  int numHandles,
38  int maxEnsuredPackets,
39  int stepPeriodMilliseconds,
40  int retryCount,
41  pfnComManagerRead readFnc,
42  pfnComManagerSend sendFnc,
44  pfnComManagerPostRead pstRxFnc,
45  pfnComManagerPostAck pstAckFnc,
46  pfnComManagerDisableBroadcasts disableBcastFnc,
47  com_manager_init_t *buffers,
48  com_manager_port_t *cmPorts
49 );
50 // int processAsciiRxPacket(com_manager_t* cmInstance, int pHandle, unsigned char* start, int count);
51 // void parseAsciiPacket(com_manager_t* cmInstance, int pHandle, unsigned char* buf, int count);
52 int processBinaryRxPacket(com_manager_t* cmInstance, int pHandle, packet_t *pkt);
53 void enableBroadcastMsg(com_manager_t* cmInstance, broadcast_msg_t *msg, int periodMultiple);
54 void disableBroadcastMsg(com_manager_t* cmInstance, broadcast_msg_t *msg);
55 void disableDidBroadcast(com_manager_t* cmInstance, int pHandle, p_data_disable_t *disable);
56 int sendPacket(com_manager_t* cmInstance, int pHandle, packet_t *dPkt, uint8_t additionalPktFlags);
57 int sendDataPacket(com_manager_t* cmInstance, int pHandle, pkt_info_t *msg);
58 void sendAck(com_manager_t* cmInstance, int pHandle, packet_t *pkt, unsigned char pid_ack);
59 int findAsciiMessage(const void * a, const void * b);
60 
61 // Packet processing
62 // com manager only...
63 int encodeBinaryPacket(com_manager_t* cmInstance, int pHandle, buffer_t *pkt, packet_t *dPkt, uint8_t additionalPktFlags);
64 // 1 if valid
65 int asciiMessageCompare(const void* elem1, const void* elem2);
66 
67 // Packet Retry
68 void stepPacketRetry(com_manager_t* cmInstance);
69 packet_t* registerPacketRetry(com_manager_t* cmInstance, int pHandle, uint8_t pid, unsigned char data[], unsigned int dataSize);
70 void updatePacketRetryData(com_manager_t* cmInstance, packet_t *pkt);
71 void updatePacketRetryAck(com_manager_t* cmInstance, packet_t *pkt);
72 
75 
76 CMHANDLE comManagerGetGlobal(void) { return &g_cm; }
77 
79 (
80  int numHandles,
81  int maxEnsuredPackets,
82  int stepPeriodMilliseconds,
83  int retryCount,
84  pfnComManagerRead readFnc,
85  pfnComManagerSend sendFnc,
87  pfnComManagerPostRead pstRxFnc,
88  pfnComManagerPostAck pstAckFnc,
89  pfnComManagerDisableBroadcasts disableBcastFnc,
90  com_manager_init_t *buffers,
91  com_manager_port_t *cmPorts
92 )
93 {
95  &g_cm,
96  numHandles,
97  maxEnsuredPackets,
98  stepPeriodMilliseconds,
99  retryCount,
100  readFnc,
101  sendFnc,
102  txFreeFnc,
103  pstRxFnc,
104  pstAckFnc,
105  disableBcastFnc,
106  buffers,
107  cmPorts);
108 }
109 
111 (
112  CMHANDLE cmHandle,
113  int numHandles,
114  int maxEnsuredPackets,
115  int stepPeriodMilliseconds,
116  int retryCount,
117  pfnComManagerRead readFnc,
118  pfnComManagerSend sendFnc,
120  pfnComManagerPostRead pstRxFnc,
121  pfnComManagerPostAck pstAckFnc,
122  pfnComManagerDisableBroadcasts disableBcastFnc,
123  com_manager_init_t *buffers,
124  com_manager_port_t *cmPorts
125 )
126 {
127  int result = 0;
128 
129  com_manager_t* cmInstance = (com_manager_t*)cmHandle;
130  if (cmInstance != 0)
131  {
132  memset(cmInstance, 0, sizeof(com_manager_t));
134  cmInstance,
135  numHandles,
136  maxEnsuredPackets,
137  stepPeriodMilliseconds,
138  retryCount,
139  readFnc,
140  sendFnc,
141  txFreeFnc,
142  pstRxFnc,
143  pstAckFnc,
144  disableBcastFnc,
145  buffers,
146  cmPorts);
147  }
148  return result;
149 }
150 
152 (
153  com_manager_t* cmInstance,
154  int numHandles,
155  int maxEnsuredPackets,
156  int stepPeriodMilliseconds,
157  int retryCount,
158  pfnComManagerRead readFnc,
159  pfnComManagerSend sendFnc,
161  pfnComManagerPostRead pstRxFnc,
162  pfnComManagerPostAck pstAckFnc,
163  pfnComManagerDisableBroadcasts disableBcastFnc,
164  com_manager_init_t *buffers,
165  com_manager_port_t *cmPorts
166 )
167 {
168  int32_t i;
169 
170  if (numHandles <= 0)
171  {
172  return -1;
173  }
174  numHandles = _CLAMP(numHandles, 1, 1024);
175 
176  // assign new variables
177  cmInstance->maxEnsuredPackets = maxEnsuredPackets;
178  cmInstance->readCallback = readFnc;
179  cmInstance->sendPacketCallback = sendFnc;
180  cmInstance->txFreeCallback = txFreeFnc;
181  cmInstance->pstRxFnc = pstRxFnc;
182  cmInstance->pstAckFnc = pstAckFnc;
183  cmInstance->disableBcastFnc = disableBcastFnc;
184  cmInstance->numHandles = numHandles;
185  cmInstance->stepPeriodMilliseconds = stepPeriodMilliseconds;
186  cmInstance->ensureRetryCount = retryCount;
187  cmInstance->cmMsgHandlerAscii = NULL;
188  cmInstance->cmMsgHandlerUblox = NULL;
189  cmInstance->cmMsgHandlerRtcm3 = NULL;
190 
191  if (buffers == NULL)
192  {
193  return -1;
194  }
195 
196  // Buffer: message broadcasts
198  {
199  return -1;
200  }
201  cmInstance->broadcastMessages = (broadcast_msg_t*)buffers->broadcastMsg;
202  memset(cmInstance->broadcastMessages, 0, buffers->broadcastMsgSize);
203 
204  // Port specific info
205  cmInstance->ports = cmPorts;
206  for (i = 0; i < numHandles; i++)
207  { // Initialize IScomm instance, for serial reads / writes
208  com_manager_port_t *port = &(cmInstance->ports[i]);
209  is_comm_init(&(port->comm), port->comm_buffer, MEMBERSIZE(com_manager_port_t, comm_buffer));
210 
211  // Port status
212  memset(&(port->status), 0, MEMBERSIZE(com_manager_port_t,status));
213 
214 #if ENABLE_PACKET_CONTINUATION
215  // Packet data continuation
216  memset(&(port->con), 0, MEMBERSIZE(com_manager_port_t,con));
217 #endif
218  }
219 
220  // Buffer: ensured packets
221  if (cmInstance->maxEnsuredPackets > 0)
222  {
224  {
225  return -1;
226  }
227  cmInstance->ensuredPackets = (ensured_pkt_t*)buffers->ensuredPackets;
228  memset(cmInstance->ensuredPackets, 0, buffers->ensuredPacketsSize);
229  for (i = 0; i < cmInstance->maxEnsuredPackets; i++)
230  {
231  cmInstance->ensuredPackets[i].counter = -2; // indicates no retries are enabled
232  cmInstance->ensuredPackets[i].pkt.body.ptr = cmInstance->ensuredPackets[i].pktBody;
233  }
234  }
235 
236  return 0;
237 }
238 
239 int asciiMessageCompare(const void* elem1, const void* elem2)
240 {
241  asciiMessageMap_t* e1 = (asciiMessageMap_t*)elem1;
242  asciiMessageMap_t* e2 = (asciiMessageMap_t*)elem2;
243 
244  return memcmp(e1->messageId, e2->messageId, 4);
245 }
246 
247 void comManagerRegister(uint32_t dataId, pfnComManagerPreSend txFnc, pfnComManagerPostRead pstRxFnc, const void* txDataPtr, void* rxDataPtr, int dataSize, uint8_t pktFlags)
248 {
249  comManagerRegisterInstance(&g_cm, dataId, txFnc, pstRxFnc, txDataPtr, rxDataPtr, dataSize, pktFlags);
250 }
251 
252 void comManagerRegisterInstance(CMHANDLE cmInstance_, uint32_t dataId, pfnComManagerPreSend txFnc, pfnComManagerPostRead pstRxFnc, const void* txDataPtr, void* rxDataPtr, int dataSize, uint8_t pktFlags)
253 {
254  com_manager_t* cmInstance = (com_manager_t*)cmInstance_;
255 
256  // Validate ID and data pointer
257  if (dataId >= DID_COUNT)
258  {
259  return;
260  }
261 
262  // Function called to update struct before data is sent
263  cmInstance->regData[dataId].preTxFnc = txFnc;
264 
265  // Function called after data is received and struct is updated
266  cmInstance->regData[dataId].pstRxFnc = pstRxFnc;
267 
268  // Pointer to data struct for Tx
269  cmInstance->regData[dataId].dataSet.txPtr = (unsigned char*)txDataPtr;
270 
271  // Pointer to data struct for Rx
272  cmInstance->regData[dataId].dataSet.rxPtr = (unsigned char*)rxDataPtr;
273 
274  // Size of data struct
275  cmInstance->regData[dataId].dataSet.size = dataSize;
276 
277  // Packet flags
278  cmInstance->regData[dataId].pktFlags = pktFlags;
279 }
280 
281 void comManagerStep(void)
282 {
285 }
286 
288 {
289  com_manager_t* cmInstance = (com_manager_t*)cmInstance_;
290  comManagerStepRxInstance(cmInstance);
291  comManagerStepTxInstance(cmInstance);
292 }
293 
294 // pfnISCommRead
295 // static int commRead(int pHandle, uint8_t *buffer, int numberOfBytes)
296 // {
297 //
298 // }
299 
301 {
302  com_manager_t* cmInstance = (com_manager_t*)cmInstance_;
303  int32_t pHandle;
304 
305  if (!cmInstance->readCallback)
306  {
307  return;
308  }
309 
310 
311  for (pHandle = 0; pHandle < cmInstance->numHandles; pHandle++)
312  {
313  com_manager_port_t *port = &(cmInstance->ports[pHandle]);
314  is_comm_instance_t *comm = &(port->comm);
315  protocol_type_t ptype;
316 
317 #if 0 // Read one byte (simple method)
318  uint8_t c;
319 
320  // Read from serial buffer until empty
321  while (cmInstance->readCallback(cmInstance, pHandle, &c, 1))
322  {
323  if ((ptype = is_comm_parse_byte(comm, c)) != _PTYPE_NONE)
324  {
325 
326 #else // Read a set of bytes (fast method)
327 
328  // Get available size of comm buffer
329  int n = is_comm_free(comm);
330 
331  // Read data directly into comm buffer
332  if ((n = cmInstance->readCallback(cmInstance, pHandle, comm->buf.tail, n)))
333  {
334  // Update comm buffer tail pointer
335  comm->buf.tail += n;
336 
337  // Search comm buffer for valid packets
338  while ((ptype = is_comm_parse(comm)) != _PTYPE_NONE)
339  {
340 #endif
341  uint8_t error = 0;
342  uint8_t *dataPtr = comm->dataPtr + comm->dataHdr.offset;
343  uint32_t dataSize = comm->dataHdr.size;
344 
345  switch (ptype)
346  {
347  case _PTYPE_PARSE_ERROR:
348  error = 1;
349  break;
350 
353  error = (uint8_t)processBinaryRxPacket(cmInstance, pHandle, &(comm->pkt));
354  break;
355 
356  case _PTYPE_UBLOX:
357  if (cmInstance->cmMsgHandlerUblox)
358  {
359  error = (uint8_t)cmInstance->cmMsgHandlerUblox(cmInstance, pHandle, dataPtr, dataSize);
360  }
361  break;
362 
363  case _PTYPE_RTCM3:
364  if (cmInstance->cmMsgHandlerRtcm3)
365  {
366  error = (uint8_t)cmInstance->cmMsgHandlerRtcm3(cmInstance, pHandle, dataPtr, dataSize);
367  }
368  break;
369 
370  case _PTYPE_ASCII_NMEA:
371  if (cmInstance->cmMsgHandlerAscii)
372  {
373  error = (uint8_t)cmInstance->cmMsgHandlerAscii(cmInstance, pHandle, dataPtr, dataSize);
374  }
375  break;
376 
377  default:
378  break;
379  }
380 
381  if (error)
382  { // Error parsing packet
383  port->status.readCounter += 32;
384  port->status.rxError = (uint32_t)-1;
386  }
387  }
388  }
389 
390  if ((port->status.flags & CM_PKT_FLAGS_RX_VALID_DATA) && port->status.readCounter > 128)
391  { // communication problem, clear communication received bit
393  }
394  }
395 }
396 
398 {
399  com_manager_t* cmInstance = (com_manager_t*)cmInstance_;
401 }
402 
404 {
406 }
407 
409 {
410  com_manager_t* cmInstance = cmInstance_;
411 
412  // Send data (if necessary)
413  for (broadcast_msg_t* bcPtr = cmInstance->broadcastMessages, *ptrEnd = (cmInstance->broadcastMessages + MAX_NUM_BCAST_MSGS); bcPtr < ptrEnd; bcPtr++)
414  {
415  // If send buffer does not have space, exit out
416  if (cmInstance->txFreeCallback && (bcPtr->pkt.txData.size > (uint32_t)cmInstance->txFreeCallback(cmInstance, bcPtr->pHandle)))
417  {
418  break;
419  }
420  // Send once and remove from message queue
421  else if (bcPtr->period == MSG_PERIOD_SEND_ONCE)
422  {
423  sendDataPacket(cmInstance, bcPtr->pHandle, &(bcPtr->pkt));
424  disableBroadcastMsg(cmInstance, bcPtr);
425  }
426  // Broadcast messages
427  else if (bcPtr->period > 0)
428  {
429  // Check if counter has expired
430  if (++bcPtr->counter >= bcPtr->period)
431  {
432  bcPtr->counter = 0; // reset counter
433 
434  // Prep data if callback exists
435  unsigned int id = bcPtr->dataHdr.id;
436  int sendData = 1;
437  if (id<DID_COUNT && cmInstance->regData[id].preTxFnc)
438  {
439  sendData = cmInstance->regData[id].preTxFnc(cmInstance, bcPtr->pHandle);
440  }
441  if (sendData)
442  {
443  sendDataPacket(cmInstance, bcPtr->pHandle, &(bcPtr->pkt));
444  }
445  }
446  }
447  }
448 
449  // Resend data (if necessary)
450  stepPacketRetry(cmInstance);
451 }
452 
454  pfnComManagerAsapMsg handlerRmc,
455  pfnComManagerGenMsgHandler handlerAscii,
456  pfnComManagerGenMsgHandler handlerUblox,
457  pfnComManagerGenMsgHandler handlerRtcm3)
458 {
459  comManagerSetCallbacksInstance(&g_cm, handlerRmc, handlerAscii, handlerUblox, handlerRtcm3);
460 }
461 
463  pfnComManagerAsapMsg handlerRmc,
464  pfnComManagerGenMsgHandler handlerAscii,
465  pfnComManagerGenMsgHandler handlerUblox,
466  pfnComManagerGenMsgHandler handlerRtcm3)
467 {
468  if (cmInstance != 0)
469  {
470  ((com_manager_t*)cmInstance)->cmMsgHandlerRmc = handlerRmc;
471  ((com_manager_t*)cmInstance)->cmMsgHandlerAscii = handlerAscii;
472  ((com_manager_t*)cmInstance)->cmMsgHandlerUblox = handlerUblox;
473  ((com_manager_t*)cmInstance)->cmMsgHandlerRtcm3 = handlerRtcm3;
474  }
475 }
476 
477 void comManagerAssignUserPointer(CMHANDLE cmInstance, void* userPointer)
478 {
479  ((com_manager_t*)cmInstance)->userPointer = userPointer;
480 }
481 
483 {
484  return ((com_manager_t*)cmInstance)->userPointer;
485 }
486 
488 {
489  return comManagerGetStatusInstance(&g_cm, pHandle);
490 }
491 
493 {
494  com_manager_t *cm = (com_manager_t*)cmInstance;
495 
496  if(cm->numHandles <= 0 || pHandle < 0 || pHandle >= cm->numHandles)
497  {
498  return NULL;
499  }
500 
501  return &(cm->ports[pHandle].status);
502 }
503 
516 void comManagerGetData(int pHandle, uint32_t dataId, int offset, int size, int periodMultiple)
517 {
518  comManagerGetDataInstance(&g_cm, pHandle, dataId, offset, size, periodMultiple);
519 }
520 
521 void comManagerGetDataInstance(CMHANDLE cmInstance, int pHandle, uint32_t dataId, int offset, int size, int periodMultiple)
522 {
523  p_data_get_t request;
524  bufPtr_t data;
525 
526  // Create and Send request packet
527  request.id = dataId;
528  request.offset = offset;
529  request.size = size;
530  request.bc_period_multiple = periodMultiple;
531 
532  data.ptr = (uint8_t*)&request;
533  data.size = sizeof(request);
534  comManagerSendInstance(cmInstance, pHandle, PID_GET_DATA, 0, &data, 0);
535 
536  // comManagerSendEnsured(pHandle, PID_GET_DATA, (unsigned char*)&request, sizeof(request));
537 }
538 
539 void comManagerGetDataRmc(int pHandle, uint64_t rmcBits, uint32_t rmcOptions)
540 {
541  comManagerGetDataRmcInstance(&g_cm, pHandle, rmcBits, rmcOptions);
542 }
543 
544 void comManagerGetDataRmcInstance(CMHANDLE cmInstance, int pHandle, uint64_t rmcBits, uint32_t rmcOptions)
545 {
546  rmc_t rmc;
547  rmc.bits = rmcBits;
548  rmc.options = rmcOptions;
549 
550  comManagerSendDataInstance(cmInstance, pHandle, DID_RMC, &rmc, sizeof(rmc_t), 0);
551 }
552 
553 int comManagerSendData(int pHandle, uint32_t dataId, void *dataPtr, int dataSize, int dataOffset)
554 {
555  return comManagerSendDataInstance(&g_cm, pHandle, dataId, dataPtr, dataSize, dataOffset);
556 }
557 
558 int comManagerSendDataInstance(CMHANDLE cmInstance, int pHandle, uint32_t dataId, void* dataPtr, int dataSize, int dataOffset)
559 {
560  p_data_hdr_t hdr;
561  bufPtr_t bodyHdr, data;
562 
563  // Data Header
564  hdr.id = dataId;
565  hdr.size = dataSize;
566  hdr.offset = dataOffset;
567 
568  // Packet Body
569  bodyHdr.ptr = (uint8_t*)&hdr;
570  bodyHdr.size = sizeof(hdr);
571  data.ptr = (uint8_t*)dataPtr;
572  data.size = dataSize;
573 
574  return comManagerSendInstance(cmInstance, pHandle, PID_SET_DATA, &bodyHdr, &data, 0);
575 }
576 
577 int comManagerSendDataNoAck(int pHandle, uint32_t dataId, void *dataPtr, int dataSize, int dataOffset)
578 {
579  return comManagerSendDataNoAckInstance(&g_cm, pHandle, dataId, dataPtr, dataSize, dataOffset);
580 }
581 
582 int comManagerSendDataNoAckInstance(CMHANDLE cmInstance, int pHandle, uint32_t dataId, void* dataPtr, int dataSize, int dataOffset)
583 {
584  p_data_hdr_t hdr;
585  bufPtr_t bodyHdr, data;
586 
587  // Data Header
588  hdr.id = dataId;
589  hdr.size = dataSize;
590  hdr.offset = dataOffset;
591 
592  // Packet Body
593  bodyHdr.ptr = (uint8_t*)&hdr;
594  bodyHdr.size = sizeof(hdr);
595  data.ptr = (uint8_t*)dataPtr;
596  data.size = dataSize;
597 
598  return comManagerSendInstance((com_manager_t*)cmInstance, pHandle, PID_DATA, &bodyHdr, &data, 0);
599 }
600 
601 int comManagerSendRawData(int pHandle, uint32_t dataId, void *dataPtr, int dataSize, int dataOffset)
602 {
603  return comManagerSendRawDataInstance(&g_cm, pHandle, dataId, dataPtr, dataSize, dataOffset);
604 }
605 
606 int comManagerSendRawDataInstance(CMHANDLE cmInstance, int pHandle, uint32_t dataId, void* dataPtr, int dataSize, int dataOffset)
607 {
608  p_data_hdr_t hdr;
609  bufPtr_t bodyHdr, data;
610 
611  // Data Header
612  hdr.id = dataId;
613  hdr.size = dataSize;
614  hdr.offset = dataOffset;
615 
616  // Packet Body
617  bodyHdr.ptr = (uint8_t*)&hdr;
618  bodyHdr.size = sizeof(hdr);
619  data.ptr = (uint8_t*)dataPtr;
620  data.size = dataSize;
621 
622  return comManagerSendInstance((com_manager_t*)cmInstance, pHandle, PID_SET_DATA, &bodyHdr, &data, CM_PKT_FLAGS_RAW_DATA_NO_SWAP);
623 }
624 
625 int comManagerDisableData(int pHandle, uint32_t dataId)
626 {
627  return comManagerDisableDataInstance(&g_cm, pHandle, dataId);
628 }
629 
630 int comManagerDisableDataInstance(CMHANDLE cmInstance, int pHandle, uint32_t dataId)
631 {
632  bufPtr_t data;
633  data.ptr = (uint8_t*)&dataId;
634  data.size = 4;
635 
636  return comManagerSendInstance(cmInstance, pHandle, PID_STOP_DID_BROADCAST, 0, &data, 0);
637 }
638 
639 int comManagerSend(int pHandle, uint8_t pktInfo, bufPtr_t *bodyHdr, bufPtr_t *txData, uint8_t pFlags)
640 {
641  return comManagerSendInstance(&g_cm, pHandle, pktInfo, bodyHdr, txData, pFlags);
642 }
643 
644 int comManagerSendInstance(CMHANDLE cmInstance, int pHandle, uint8_t pktInfo, bufPtr_t* bodyHdr, bufPtr_t* txData, uint8_t pktFlags)
645 {
646  pkt_info_t pkt = { 0 };
647 
648  // Create Packet String (start to end byte)
650  pkt.hdr.pid = pktInfo;
651  pkt.hdr.flags = pktFlags;
652 
653  if (bodyHdr)
654  {
655  pkt.bodyHdr = *bodyHdr;
656  }
657  if (txData)
658  {
659  pkt.txData = *txData;
660  }
661 
662  return sendDataPacket(cmInstance, pHandle, &pkt);
663 }
664 
665 int comManagerSendEnsured(int pHandle, uint8_t pktInfo, unsigned char* data, unsigned int dataSize)
666 {
667  return comManagerSendEnsuredInstance(&g_cm, pHandle, pktInfo, data, dataSize);
668 }
669 
670 int comManagerSendEnsuredInstance(CMHANDLE cmInstance, int pHandle, uint8_t pktInfo, unsigned char *data, unsigned int dataSize)
671 {
672  packet_t *pkt;
673 
674  // Change retry "Ensured" packets to so that we encode packets first (including pkt counter)
675  // and then ensure they are delivered. Include packet checksum in ACK/NACK to validate delivery.
676  // Then, if all the ensured slots are occupied because of bad comm, either allow
677  // to clear ensured packets or just block until they are delivered. We must
678  // ensure NACKs are used to clear blocking ensured packets.
679 
680  // Create Packet String (start to end byte)
681  if ((pkt = registerPacketRetry((com_manager_t*)cmInstance, pHandle, pktInfo, data, dataSize)) == 0)
682  {
683  return -1;
684  }
685 
686  return sendPacket((com_manager_t*)cmInstance, pHandle, pkt, 0);
687 }
688 
689 int findAsciiMessage(const void * a, const void * b)
690 {
691  unsigned char* a1 = (unsigned char*)a;
693 
694  return memcmp(a1, a2->messageId, 4);
695 }
696 
702 int processBinaryRxPacket(com_manager_t* cmInstance, int pHandle, packet_t *pkt)
703 {
704  p_data_t *data = (p_data_t*)(pkt->body.ptr);
705  p_data_hdr_t *dataHdr;
706  registered_data_t *regd = NULL;
707  uint8_t pid = (uint8_t)(pkt->hdr.pid);
708 
709  com_manager_port_t *port = &(cmInstance->ports[pHandle]);
710  port->status.flags |= CM_PKT_FLAGS_RX_VALID_DATA; // communication received
711  port->status.readCounter = 0;
712 
713  // Packet read success
714  port->status.rxPktCount++;
715 
716  switch (pid)
717  {
718  default: // Data ID Unknown
719  return -1;
720 
721  case PID_SET_DATA:
722  case PID_DATA:
723  dataHdr = &(data->hdr);
724 
725  // Validate Data
726  if (dataHdr->id < DID_COUNT)
727  {
728  regd = &(cmInstance->regData[dataHdr->id]);
729 
730  // Validate and constrain Rx data size to fit within local data struct
731  if (regd->dataSet.size && (dataHdr->offset + dataHdr->size) > regd->dataSet.size)
732  {
733  // trim the size down so it fits
734  int size = (int)(regd->dataSet.size - dataHdr->offset);
735  if (size < 4)
736  {
737  // we are completely out of bounds, we cannot process this message at all
738  // the minimum data struct size is 4 bytes
739  return -1;
740  }
741 
742  // Update Rx data size
743  dataHdr->size = _MIN(dataHdr->size, (uint8_t)size);
744  }
745  }
746 
747 #if ENABLE_PACKET_CONTINUATION
748 
749  // Consolidate datasets that were broken-up across multiple packets
750  p_data_t* con = &cmInstance->ports[pHandle].con;
751  if (additionalDataAvailable || (con->hdr.size != 0 && con->hdr.id == dataHdr->id))
752  {
753  // New dataset
754  if (con->hdr.id == 0 || con->hdr.size == 0 || con->hdr.id != dataHdr->id || con->hdr.size > dataHdr->offset)
755  {
756  // Reset data consolidation
757  con->hdr.id = dataHdr->id;
758  con->hdr.offset = dataHdr->offset;
759  con->hdr.size = 0;
760  }
761 
762  // Ensure data will fit in buffer
763  if ((con->hdr.size + dataHdr->size) < sizeof(con->buf))
764  {
765  // Add data to buffer
766  memcpy(con->buf + con->hdr.size, data->buf, dataHdr->size);
767  con->hdr.size += dataHdr->size;
768  }
769  else
770  {
771  // buffer overflow
772  }
773 
774  // Wait for end of data
775  if (additionalDataAvailable)
776  {
777  return 0;
778  }
779 
780  // Use consolidated data
781  data = con;
782  }
783 
784 #else
785 
786 // unsigned char additionalDataAvailable // function parameter removed
787 // (void)additionalDataAvailable;
788 
789 #endif
790 
791  if (regd)
792  {
793  // Write to data structure if it was registered
794  if (regd->dataSet.rxPtr)
795  {
796  copyDataPToStructP(regd->dataSet.rxPtr, data, regd->dataSet.size);
797  }
798 
799  // Call data specific callback after data has been written to
800  if (regd->pstRxFnc)
801  {
802  regd->pstRxFnc(cmInstance, pHandle, data);
803  }
804  }
805 
806  // Call general/global callback
807  if (cmInstance->pstRxFnc)
808  {
809  cmInstance->pstRxFnc(cmInstance, pHandle, data);
810  }
811 
812  // Remove retry from linked list if necessary
813  updatePacketRetryData(cmInstance, pkt);
814 
815 #if ENABLE_PACKET_CONTINUATION
816 
817  // Clear dataset consolidation
818  con->hdr.id = con->hdr.size = con->hdr.offset = 0;
819 
820 #endif
821 
822  // Reply w/ ACK for PID_SET_DATA
823  if (pid == PID_SET_DATA)
824  {
825  sendAck(cmInstance, pHandle, pkt, PID_ACK);
826  }
827  break;
828 
829  case PID_GET_DATA:
830  if (comManagerGetDataRequestInstance(cmInstance, pHandle, (p_data_get_t *)(data)))
831  {
832  sendAck(cmInstance, pHandle, pkt, PID_NACK);
833  }
834  break;
835 
837  comManagerDisableBroadcastsInstance(cmInstance, -1);
838 
839  // Call disable broadcasts callback if exists
840  if (cmInstance->disableBcastFnc)
841  {
842  cmInstance->disableBcastFnc(cmInstance, -1);
843  }
844  sendAck(cmInstance, pHandle, pkt, PID_ACK);
845  break;
846 
848  comManagerDisableBroadcastsInstance(cmInstance, pHandle);
849 
850  // Call disable broadcasts callback if exists
851  if (cmInstance->disableBcastFnc)
852  {
853  cmInstance->disableBcastFnc(cmInstance, pHandle);
854  }
855  sendAck(cmInstance, pHandle, pkt, PID_ACK);
856  break;
857 
859  disableDidBroadcast(cmInstance, pHandle, (p_data_disable_t *)(data));
860  break;
861 
862  case PID_NACK:
863  case PID_ACK:
864  // Remove retry from linked list if necessary
865  updatePacketRetryAck(cmInstance, pkt);
866 
867  // Call general ack callback
868  if (cmInstance->pstAckFnc)
869  {
870  cmInstance->pstAckFnc(cmInstance, pHandle, (p_ack_t*)(pkt->body.ptr), pid);
871  }
872  break;
873  }
874 
875  return 0;
876 }
877 
879 {
880  return comManagerGetRegisteredDataInfoInstance(&g_cm, dataId);
881 }
882 
884 {
885  if (dataId < DID_COUNT)
886  {
887  com_manager_t* cmInstance = (com_manager_t*)_cmInstance;
888  return &cmInstance->regData[dataId].dataSet;
889  }
890 
891  return 0;
892 }
893 
894 // 0 on success. -1 on failure.
896 {
897  return comManagerGetDataRequestInstance(&g_cm, pHandle, req);
898 }
899 
900 int comManagerGetDataRequestInstance(CMHANDLE _cmInstance, int pHandle, p_data_get_t* req)
901 {
902  com_manager_t* cmInstance = (com_manager_t*)_cmInstance;
903  broadcast_msg_t* msg = 0;
904 
905  // Validate the request
906  if (req->id >= DID_COUNT)
907  {
908  // invalid data id
909  return -1;
910  }
911  // Call RealtimeMessageController (RMC) handler
912  else if (cmInstance->cmMsgHandlerRmc && (cmInstance->cmMsgHandlerRmc(cmInstance, pHandle, req) == 0))
913  {
914  // Don't allow comManager broadcasts for messages handled by RealtimeMessageController.
915  return 0;
916  }
917  // if size is 0 and offset is 0, set size to full data struct size
918  else if (req->size == 0 && req->offset == 0 && req->id < DID_COUNT)
919  {
920  req->size = cmInstance->regData[req->id].dataSet.size;
921  }
922 
923  // Copy reference to source data
924  bufTxRxPtr_t* dataSetPtr = &cmInstance->regData[req->id].dataSet;
925 
926  // Abort if no data pointer is registered or offset + size is out of bounds
927  if (dataSetPtr->txPtr == 0 || dataSetPtr->size == 0)
928  {
929  return -1;
930  }
931  else if (req->offset + req->size > dataSetPtr->size)
932  {
933  req->offset = 0;
934  req->size = dataSetPtr->size;
935  }
936 
937  // Search for matching message (i.e. matches pHandle, id, size, and offset)...
938  for (broadcast_msg_t* bcPtr = cmInstance->broadcastMessages, *ptrEnd = (cmInstance->broadcastMessages + MAX_NUM_BCAST_MSGS); bcPtr < ptrEnd; bcPtr++)
939  {
940  if (bcPtr->pHandle == pHandle && bcPtr->dataHdr.id == req->id && bcPtr->dataHdr.size == req->size && bcPtr->dataHdr.offset == req->offset)
941  {
942  msg = bcPtr;
943  break;
944  }
945  }
946 
947  // otherwise use the first available (period=0) message.
948  if (msg == 0)
949  {
950  for (broadcast_msg_t* bcPtr = cmInstance->broadcastMessages, *ptrEnd = (cmInstance->broadcastMessages + MAX_NUM_BCAST_MSGS); bcPtr < ptrEnd; bcPtr++)
951  {
952  if (bcPtr->period <= MSG_PERIOD_DISABLED)
953  {
954  msg = bcPtr;
955  break;
956  }
957  }
958 
959  if (msg == 0)
960  {
961  // use last slot, force overwrite
962  msg = cmInstance->broadcastMessages + MAX_NUM_BCAST_MSGS - 1;
963  }
964  }
965 
966  // Port handle
967  msg->pHandle = pHandle;
968 
969  // Packet parameters
971  msg->pkt.hdr.pid = PID_DATA;
972 
973  // Data Header
974  msg->dataHdr.id = req->id;
975  msg->dataHdr.size = req->size;
976  msg->dataHdr.offset = req->offset;
977  msg->pkt.hdr.flags = cmInstance->regData[req->id].pktFlags;
978  msg->pkt.bodyHdr.ptr = (uint8_t *)&msg->dataHdr;
979  msg->pkt.bodyHdr.size = sizeof(msg->dataHdr);
980  msg->pkt.txData.size = req->size;
981  msg->pkt.txData.ptr = cmInstance->regData[req->id].dataSet.txPtr + req->offset;
982 
983  // Prep data if callback exists
984  int sendData = 1;
985  if (cmInstance->regData[req->id].preTxFnc)
986  {
987  sendData = cmInstance->regData[req->id].preTxFnc(cmInstance, pHandle);
988  }
989 // sendData
990 
991  // Constrain request broadcast period if necessary
992  if (req->bc_period_multiple != 0)
993  {
995  }
996 
997  // Send data
998  if (req->bc_period_multiple > 0)
999  {
1000  // *** Request Broadcast ***
1001  // Send data immediately if possible
1002  if (cmInstance->txFreeCallback == 0 || msg->pkt.txData.size <= (uint32_t)cmInstance->txFreeCallback(cmInstance, pHandle))
1003  {
1004  if (sendData)
1005  {
1006  sendDataPacket(cmInstance, pHandle, &(msg->pkt));
1007  }
1008  }
1009 
1010  // Enable broadcast message
1011  enableBroadcastMsg(cmInstance, msg, req->bc_period_multiple);
1012  }
1013  else
1014  {
1015  // *** Request Single ***
1016  // Send data immediately if possible
1017  if (cmInstance->txFreeCallback == 0 || msg->pkt.txData.size <= (uint32_t)cmInstance->txFreeCallback(cmInstance, pHandle))
1018  {
1019  if (sendData)
1020  {
1021  sendDataPacket(cmInstance, pHandle, &(msg->pkt));
1022  }
1023  disableBroadcastMsg(cmInstance, msg);
1024  }
1025  else
1026  {
1027  // Won't fit in queue, so send it later
1028  enableBroadcastMsg(cmInstance, msg, req->bc_period_multiple);
1029  }
1030  }
1031 
1032  return 0;
1033 }
1034 
1035 void enableBroadcastMsg(com_manager_t* cmInstance, broadcast_msg_t* msg, int periodMultiple)
1036 {
1037  // Update broadcast period
1038  if (periodMultiple > 0)
1039  {
1040  msg->period = periodMultiple / cmInstance->stepPeriodMilliseconds;
1041  }
1042  else
1043  {
1045  }
1046  msg->counter = -1; // Keeps broadcast from sending for at least one period
1047 }
1048 
1050 {
1051  (void)cmInstance;
1052 
1053  // Remove item from linked list
1054  msg->period = MSG_PERIOD_DISABLED;
1055 }
1056 
1058 {
1059  comManagerDisableBroadcastsInstance(&g_cm, pHandle);
1060 }
1061 
1062 void comManagerDisableBroadcastsInstance(CMHANDLE cmInstance_, int pHandle)
1063 {
1064  com_manager_t* cmInstance = (com_manager_t*)cmInstance_;
1065  for (broadcast_msg_t* bcPtr = cmInstance->broadcastMessages, *ptrEnd = (cmInstance->broadcastMessages + MAX_NUM_BCAST_MSGS); bcPtr < ptrEnd; bcPtr++)
1066  {
1067  if (pHandle < 0 || bcPtr->pHandle == pHandle)
1068  {
1069  bcPtr->period = MSG_PERIOD_DISABLED;
1070  }
1071  }
1072 }
1073 
1074 void disableDidBroadcast(com_manager_t* cmInstance, int pHandle, p_data_disable_t* disable)
1075 {
1076  for (broadcast_msg_t* bcPtr = cmInstance->broadcastMessages, *ptrEnd = (cmInstance->broadcastMessages + MAX_NUM_BCAST_MSGS); bcPtr < ptrEnd; bcPtr++)
1077  {
1078  if ((pHandle < 0 || pHandle == bcPtr->pHandle) && bcPtr->dataHdr.id == disable->id)
1079  {
1080  bcPtr->period = MSG_PERIOD_DISABLED;
1081  }
1082  }
1083 
1084  // Call global broadcast handler to disable message control
1085  if (cmInstance->cmMsgHandlerRmc)
1086  {
1087  p_data_get_t req;
1088  req.id = disable->id;
1089  req.size = 0;
1090  req.offset = 0;
1091  req.bc_period_multiple = 0;
1092  cmInstance->cmMsgHandlerRmc(cmInstance, pHandle, &req);
1093  }
1094 }
1095 
1103 int sendPacket(com_manager_t* cmInstance, int pHandle, packet_t *dPkt, uint8_t additionalPktFlags)
1104 {
1105  buffer_t buffer;
1106 
1107  if (encodeBinaryPacket(cmInstance, pHandle, &buffer, dPkt, additionalPktFlags))
1108  {
1109  return -1;
1110  }
1111 
1112  // Send Packet
1113  else if (cmInstance->sendPacketCallback)
1114  {
1115  cmInstance->sendPacketCallback(cmInstance, pHandle, buffer.buf, buffer.size);
1116  }
1117 
1118  return 0;
1119 }
1120 
1121 // Consolidate this with sendPacket() so that we break up packets into multiples that fit our buffer size.
1122 int sendDataPacket(com_manager_t* cmInstance, int pHandle, pkt_info_t* msg)
1123 {
1124  pfnComManagerSend sendCallback = cmInstance->sendPacketCallback;
1125  if (sendCallback == 0)
1126  {
1127  return -1;
1128  }
1129 
1130  buffer_t bufToSend;
1131  packet_t pkt;
1132  pkt.hdr = msg->hdr;
1133 
1134  switch (pkt.hdr.pid)
1135  {
1136  // Large data support - breaks data up into separate packets for Tx
1137  case PID_DATA:
1138  case PID_SET_DATA:
1139  {
1140  // Setup packet and encoding state
1141  buffer_t bufToEncode;
1142  p_data_hdr_t hdr = *(p_data_hdr_t*)msg->bodyHdr.ptr;
1143  p_data_hdr_t* hdrToSend = (p_data_hdr_t*)bufToEncode.buf;
1144  uint32_t size = hdr.size;
1145  uint32_t offset = 0;
1146  uint32_t id = hdr.id;
1147  pkt.body.ptr = bufToEncode.buf;
1148 
1149 #if ENABLE_PACKET_CONTINUATION
1150 
1151  while (size > 0)
1152  {
1153 
1154 #endif
1155 
1156  // Assign data header values
1157  hdrToSend->size = _MIN(size, MAX_P_DATA_BODY_SIZE);
1158  hdrToSend->offset = hdr.offset + offset;
1159  hdrToSend->id = id;
1160 
1161  // copy the data to send to bufToEncode, skipping the data header - since we had to create that data header, we now have to append the actual data
1162  memcpy(bufToEncode.buf + sizeof(p_data_hdr_t), msg->txData.ptr + offset, hdrToSend->size);
1163 
1164  // reduce size by the amount sent - if packet continuation is off, this must become 0 otherwise we fail
1165  size -= hdrToSend->size;
1166 
1167 #if ENABLE_PACKET_CONTINUATION
1168 
1169  // increment offset for the next packet
1170  offset += hdrToSend->size;
1171 
1172 #else
1173 
1174  if (size > 0)
1175  {
1176  // data was too large to fit in one packet, fail
1177  return -1;
1178  }
1179 
1180 #endif
1181 
1182  // Set data body size
1183  pkt.body.size = sizeof(p_data_hdr_t) + hdrToSend->size;
1184 
1185  // Encode the packet, handling special characters, etc.
1186  if (encodeBinaryPacket(cmInstance, pHandle, &bufToSend, &pkt, CM_PKT_FLAGS_MORE_DATA_AVAILABLE * (size != 0)))
1187  {
1188  return -1;
1189  }
1190 
1191  // Send the packet using the specified callback
1192  sendCallback(cmInstance, pHandle, bufToSend.buf, bufToSend.size);
1193 
1194 #if ENABLE_PACKET_CONTINUATION
1195 
1196  }
1197 
1198 #endif
1199 
1200  } break;
1201 
1202  // Single packet commands/data sets. No data header, just body.
1203  default:
1204  {
1205  // Assign packet pointer and encode data as is
1206  pkt.body = msg->txData;
1207  if (encodeBinaryPacket(cmInstance, pHandle, &bufToSend, &pkt, 0))
1208  {
1209  return -1;
1210  }
1211 
1212  // Send the packet using the specified callback
1213  sendCallback(cmInstance, pHandle, bufToSend.buf, bufToSend.size);
1214  } break;
1215  }
1216 
1217  return 0;
1218 }
1219 
1220 void sendAck(com_manager_t* cmInstance, int pHandle, packet_t *pkt, unsigned char pid_ack)
1221 {
1222  int ackSize;
1223  bufPtr_t data;
1224 
1225  // Create and Send request packet
1226  p_ack_t ack = { 0 };
1227  ack.hdr.pktInfo = pkt->hdr.pid;
1228  ack.hdr.pktCounter = pkt->hdr.counter;
1229  ackSize = sizeof(p_ack_hdr_t);
1230 
1231  // Set ack body
1232  switch (pkt->hdr.pid)
1233  {
1234  case PID_SET_DATA:
1235 // memcpy(ack.body.buf, (p_data_hdr_t*)(pkt->body.ptr), sizeof(p_data_hdr_t));
1236  ack.body.dataHdr = *((p_data_hdr_t*)(pkt->body.ptr));
1237  ackSize += sizeof(p_data_hdr_t);
1238  break;
1239  }
1240 
1241  data.ptr = (unsigned char*)&ack;
1242  data.size = ackSize;
1243 
1244  comManagerSendInstance(cmInstance, pHandle, (uint8_t)pid_ack, 0, &data, 0);
1245 }
1246 
1248 // Packet Composition
1250 
1270 int encodeBinaryPacket(com_manager_t* cmInstance, int pHandle, buffer_t *pkt, packet_t *dPkt, uint8_t additionalPktFlags)
1271 {
1272  com_manager_port_t *port = &(cmInstance->ports[pHandle]);
1273 
1274  void* srcBuffer = dPkt->body.ptr;
1275  int srcBufferLength = dPkt->body.size;
1276  void* encodedPacket = pkt->buf;
1277  int encodedPacketLength = PKT_BUF_SIZE - 1;
1278  packet_hdr_t* hdr = &dPkt->hdr;
1279  hdr->counter = (uint8_t)(port->comm.txPktCount++);
1280 
1281  pkt->size = is_encode_binary_packet(srcBuffer, srcBufferLength, hdr, additionalPktFlags | port->status.flags, encodedPacket, encodedPacketLength);
1282  return (-1 * ((int)pkt->size < 8));
1283 }
1284 
1285 
1287 // Packet Retry
1289 
1295 {
1296  int32_t i;
1297  ensured_pkt_t* ePkt;
1298 
1299  for (i = 0; i < cmInstance->maxEnsuredPackets; i++)
1300  {
1301  ePkt = &(cmInstance->ensuredPackets[i]);
1302 
1303  // No more retries in list
1304  if (ePkt->counter == -2)
1305  {
1306  return;
1307  }
1308 
1309  // Check that retry is enabled
1310  if (ePkt->counter >= 0)
1311  {
1312  // Check if counter has expired
1313  if (--(ePkt->counter) == 0)
1314  {
1315  // Reset counter
1316  ePkt->counter = cmInstance->ensureRetryCount;
1317 
1318  // Reset packet
1319  sendPacket(cmInstance, ePkt->pHandle, &(ePkt->pkt), 0);
1320  }
1321  }
1322  }
1323 }
1324 
1336 packet_t* registerPacketRetry(com_manager_t* cmInstance, int pHandle, uint8_t pid, unsigned char data[], unsigned int dataSize)
1337 {
1338  int32_t i;
1339  ensured_pkt_t *ePkt = 0;
1340  unsigned char searching = 1;
1341 
1342  #if ENABLE_FILTER_DUPLICATE_PACKETS
1343 
1344  #if ENABLE_FILTER_DUPLICATE_PACKETS_MATCH_ALL_CHARACTERS
1345 
1346  int32_t j;
1347 
1348  #endif
1349 
1350  // Filter out redundant retries (replace same type packets and pHandle with latest)
1351  p_data_get_t *getData1, *getData2;
1352 
1353  // Validate Data Size
1354  if (dataSize > MAX_P_DATA_BODY_SIZE)
1355  {
1356  return 0;
1357  }
1358 
1359  // Check for existing retry
1360  for (i = 0; searching && i < cmInstance->maxEnsuredPackets; i++)
1361  {
1362  ePkt = &(cmInstance->ensuredPackets[i]);
1363 
1364  // No more retries to search over. Abort and look for first disabled slot.
1365  if (ePkt->counter == -2)
1366  {
1367  break;
1368  }
1369 
1370  // Found enabled retry w/ matching packet ID and data size
1371  if (ePkt->counter >= 0 &&
1372  ePkt->pkt.hdr.pid == pid &&
1373  ePkt->pkt.body.size == dataSize &&
1374  ePkt->pHandle == pHandle)
1375  {
1376  switch (pid)
1377  {
1378  case PID_GET_DATA:
1379  getData1 = (p_data_get_t*)data;
1380  getData2 = (p_data_get_t*)ePkt->pktBody;
1381 
1382  // Match: all Get Data parameters
1383  if (getData1->id == getData2->id &&
1384  getData1->size == getData2->size &&
1385  getData1->offset == getData2->offset)
1386  searching = 0;
1387  break;
1388 
1390  searching = 0;
1391  break;
1392 
1393  default:
1394 
1395 #if !ENABLE_FILTER_DUPLICATE_PACKETS_MATCH_ALL_CHARACTERS
1396 
1397  // Match: first character
1398  if (ePkt->pkt.body.ptr[0] == data[0])
1399  {
1400  searching = 0;
1401  }
1402 
1403 #else
1404 
1405  // Match: All character
1406  for (j = 0; j < dataSize; j++)
1407  {
1408  if (ePkt->pkt.body.ptr[j] == data[j])
1409  {
1410  searching = 0;
1411  break;
1412  }
1413  }
1414 
1415 #endif
1416 
1417  break;
1418  }
1419  }
1420  }
1421 
1422  #endif
1423 
1424  // Find Empty Slot - either first available or tail if all used.
1425  for (i = 0; searching && i < cmInstance->maxEnsuredPackets; i++)
1426  {
1427  ePkt = &(cmInstance->ensuredPackets[i]);
1428 
1429  // Found empty slot
1430  if (ePkt->counter < 0)
1431  {
1432  searching = 0;
1433  break;
1434  }
1435  }
1436 
1437  // All slots enabled, so take the oldest (one after last used)
1438  if (searching && cmInstance->ensuredPackets != 0)
1439  {
1440  if (++cmInstance->lastEnsuredPacketIndex >= cmInstance->maxEnsuredPackets)
1441  {
1442  cmInstance->lastEnsuredPacketIndex = 0;
1443  }
1444  ePkt = &(cmInstance->ensuredPackets[cmInstance->lastEnsuredPacketIndex]);
1445  }
1446  else
1447  {
1448  cmInstance->lastEnsuredPacketIndex = i;
1449  }
1450  if (ePkt == 0)
1451  {
1452  return 0;
1453  }
1454 
1455  // Backup packet contents for retry if not already registered
1456  ePkt->counter = cmInstance->ensureRetryCount;
1457  memcpy(ePkt->pktBody, data, dataSize);
1458 
1459  // Update ePkt pkt header and body info
1460  ePkt->pkt.hdr.startByte = PSC_START_BYTE;
1461  ePkt->pkt.hdr.pid = pid;
1462  ePkt->pkt.body.ptr = ePkt->pktBody; // point to ePkt buffer "pktBody"
1463  ePkt->pkt.body.size = dataSize;
1464  ePkt->pHandle = pHandle;
1465 
1466  return &(ePkt->pkt);
1467 }
1468 
1477 {
1478  int32_t i;
1479  ensured_pkt_t *ePkt;
1480 
1481  // Search for retries that match packet received. If found, removed it from the retry list.
1482  for (i = 0; i < cmInstance->maxEnsuredPackets; i++)
1483  {
1484  ePkt = &(cmInstance->ensuredPackets[i]);
1485 
1486  if (ePkt->counter == -2)
1487  {
1488  // No more retries to search for
1489  return;
1490  }
1491 
1492  if (ePkt->counter < 0)
1493  {
1494  // This retry is disabled. Skip it.
1495  continue;
1496  }
1497 
1498  // Found packet response expected. Remove from retry list.
1499  if (ePkt->pktBody[0] == pkt->body.ptr[0])
1500  {
1501  // Indicate disabled retry
1502  ePkt->counter = -1;
1503  }
1504  }
1505 
1506  // Update last retry indicator
1507  for (i = cmInstance->maxEnsuredPackets - 1; i >= 0; i--)
1508  {
1509  // Current is enabled so stop
1510  if (cmInstance->ensuredPackets[i].counter >= 0)
1511  {
1512  break;
1513  }
1514 
1515  // Indicate no more retries in list
1516  cmInstance->ensuredPackets[i].counter = -2;
1517  }
1518 }
1519 
1521 {
1522  int32_t i;
1523  ensured_pkt_t *ePkt;
1524  p_ack_t *ack;
1525  uint8_t ackInfo;
1526 
1527  ack = (p_ack_t*)(pkt->body.ptr);
1528  ackInfo = (uint8_t)(ack->hdr.pktInfo);
1529 
1530  // Search for retries that match packet received. If found, removed it from the retry list.
1531  for (i = 0; i < cmInstance->maxEnsuredPackets; i++)
1532  {
1533  ePkt = &(cmInstance->ensuredPackets[i]);
1534 
1535  if (ePkt->counter == -2)
1536  {
1537  // No more retries to search for
1538  return;
1539  }
1540 
1541  if (ePkt->counter == -1)
1542  {
1543  // This retry is disabled. Skip it.
1544  continue;
1545  }
1546 
1547  // Check packet info matches
1548  if (ack->hdr.pktInfo == ePkt->pkt.hdr.pid)
1549  {
1550  p_data_hdr_t *dHdr, *eHdr;
1551 
1552  switch (ackInfo)
1553  {
1554  default:
1555  // Custom/Specific Packets
1556  case PID_STOP_BROADCASTS_ALL_PORTS: // No body ID available
1557  ePkt->counter = -1; // indicate disabled retry
1558  break;
1559 
1560  case PID_SET_DATA:
1561  dHdr = &(ack->body.dataHdr);
1562  eHdr = (p_data_hdr_t*)(ePkt->pktBody);
1563 
1564  if (dHdr->id == eHdr->id &&
1565  dHdr->size == eHdr->size &&
1566  dHdr->offset == eHdr->offset)
1567  {
1568  ePkt->counter = -1; // indicate disabled retry
1569  }
1570  break;
1571  }
1572  }
1573  }
1574 
1575  // Update last retry indicator
1576  for (i = cmInstance->maxEnsuredPackets - 1; i >= 0; i--)
1577  {
1578  // Current is enabled so stop
1579  if (cmInstance->ensuredPackets[i].counter >= 0)
1580  {
1581  break;
1582  }
1583  cmInstance->ensuredPackets[i].counter = -2; // Indicate no more retries in list
1584  }
1585 }
1586 
1587 int comManagerValidateBaudRate(unsigned int baudRate)
1588 {
1589  // Valid baudrates for InertialSense hardware
1590  for (size_t i = 0; i < _ARRAY_ELEMENT_COUNT(g_validBaudRates); i++)
1591  {
1592  if (g_validBaudRates[i] == baudRate)
1593  {
1594  return 0;
1595  }
1596  }
1597  return -1;
1598 }
1599 
int comManagerDisableData(int pHandle, uint32_t dataId)
Definition: com_manager.c:625
#define _MIN(a, b)
Definition: ISConstants.h:298
registered_data_t regData[DID_COUNT]
Definition: com_manager.h:212
int comManagerSendDataNoAck(int pHandle, uint32_t dataId, void *dataPtr, int dataSize, int dataOffset)
Definition: com_manager.c:577
bufPtr_t body
Definition: ISComm.h:361
packet_t pkt
Definition: com_manager.h:64
ensured_pkt_t * ensuredPackets
Definition: com_manager.h:218
int comManagerSendDataInstance(CMHANDLE cmInstance, int pHandle, uint32_t dataId, void *dataPtr, int dataSize, int dataOffset)
Definition: com_manager.c:558
uint32_t options
Definition: data_sets.h:1152
int(* pfnComManagerSendBufferAvailableBytes)(CMHANDLE cmHandle, int pHandle)
Definition: com_manager.h:129
int comManagerSendRawData(int pHandle, uint32_t dataId, void *dataPtr, int dataSize, int dataOffset)
Definition: com_manager.c:601
packet_hdr_t hdr
Definition: ISComm.h:367
void comManagerSetCallbacksInstance(CMHANDLE cmInstance, pfnComManagerAsapMsg handlerRmc, pfnComManagerGenMsgHandler handlerAscii, pfnComManagerGenMsgHandler handlerUblox, pfnComManagerGenMsgHandler handlerRtcm3)
Definition: com_manager.c:462
uint8_t startByte
Definition: ISComm.h:320
void comManagerStepRxInstance(CMHANDLE cmInstance_)
Definition: com_manager.c:300
int asciiMessageCompare(const void *elem1, const void *elem2)
Definition: com_manager.c:239
uint8_t * txPtr
Definition: ISComm.h:216
pfnComManagerGenMsgHandler cmMsgHandlerUblox
Definition: com_manager.h:246
int processBinaryRxPacket(com_manager_t *cmInstance, int pHandle, packet_t *pkt)
Process binary packet content:
Definition: com_manager.c:702
pfnComManagerAsapMsg cmMsgHandlerRmc
Definition: com_manager.h:240
broadcast_msg_t * broadcastMessages
Definition: com_manager.h:220
com_manager_status_t * comManagerGetStatus(int pHandle)
Definition: com_manager.c:487
int comManagerValidateBaudRate(unsigned int baudRate)
Definition: com_manager.c:1587
int32_t counter
Definition: com_manager.h:51
#define MSG_PERIOD_DISABLED
Definition: com_manager.c:30
bufTxRxPtr_t * comManagerGetRegisteredDataInfo(uint32_t dataId)
Definition: com_manager.c:878
ensured_pkt_t * ensuredPackets
Definition: com_manager.h:105
void(* pfnComManagerPostRead)(CMHANDLE cmHandle, int pHandle, p_data_t *dataRead)
Definition: com_manager.h:132
#define PID_STOP_BROADCASTS_ALL_PORTS
Definition: ISComm.h:186
pfnComManagerPostRead pstRxFnc
Definition: com_manager.h:203
pfnComManagerSendBufferAvailableBytes txFreeCallback
Definition: com_manager.h:200
uint32_t id
Definition: ISComm.h:376
void comManagerGetDataRmcInstance(CMHANDLE cmInstance, int pHandle, uint64_t rmcBits, uint32_t rmcOptions)
Definition: com_manager.c:544
uint32_t size
Definition: ISComm.h:379
uint8_t buf[PKT_BUF_SIZE]
Definition: ISComm.h:199
bufTxRxPtr_t * comManagerGetRegisteredDataInfoInstance(CMHANDLE _cmInstance, uint32_t dataId)
Definition: com_manager.c:883
void comManagerDisableBroadcasts(int pHandle)
Definition: com_manager.c:1057
pfnComManagerPostRead pstRxFnc
Definition: com_manager.h:165
void updatePacketRetryData(com_manager_t *cmInstance, packet_t *pkt)
Update packet retry. If the specific data requested or acknowledge is received, the retry list is upd...
Definition: com_manager.c:1476
static int sendData(is_comm_instance_t *instance, uint32_t dataId, uint32_t offset, uint32_t size, void *data, uint32_t pid)
Definition: ISComm.c:610
uint32_t communicationErrorCount
Definition: com_manager.h:89
uint8_t comm_buffer[PKT_BUF_SIZE]
Definition: com_manager.h:177
void stepPacketRetry(com_manager_t *cmInstance)
stepPacketRetry - Resend the ensured packets after the ENSURE_RETRY_COUNT period if the expected resp...
Definition: com_manager.c:1294
int(* pfnComManagerAsapMsg)(CMHANDLE cmHandle, int pHandle, p_data_get_t *req)
Definition: com_manager.h:153
uint32_t size
Definition: ISComm.h:209
broadcast_msg_t * broadcastMsg
Definition: com_manager.h:102
uint64_t bits
Definition: data_sets.h:1359
#define MSG_PERIOD_SEND_ONCE
Definition: com_manager.c:29
if(udd_ctrl_interrupt())
Definition: usbhs_device.c:688
void disableDidBroadcast(com_manager_t *cmInstance, int pHandle, p_data_disable_t *disable)
Definition: com_manager.c:1074
void comManagerRegisterInstance(CMHANDLE cmInstance_, uint32_t dataId, pfnComManagerPreSend txFnc, pfnComManagerPostRead pstRxFnc, const void *txDataPtr, void *rxDataPtr, int dataSize, uint8_t pktFlags)
Definition: com_manager.c:252
int32_t pHandle
Definition: com_manager.h:57
int comManagerSendInstance(CMHANDLE cmInstance, int pHandle, uint8_t pktInfo, bufPtr_t *bodyHdr, bufPtr_t *txData, uint8_t pktFlags)
Definition: com_manager.c:644
void sendAck(com_manager_t *cmInstance, int pHandle, packet_t *pkt, unsigned char pid_ack)
Definition: com_manager.c:1220
#define PKT_BUF_SIZE
Definition: ISComm.h:98
#define DID_COUNT
Definition: data_sets.h:138
packet_hdr_t hdr
Definition: ISComm.h:358
uint8_t pktBody[PKT_BUF_SIZE]
Definition: com_manager.h:67
#define DID_RMC
Definition: data_sets.h:43
protocol_type_t is_comm_parse_byte(is_comm_instance_t *instance, uint8_t byte)
Definition: ISComm.c:499
#define NULL
Definition: nm_bsp.h:52
void(* pfnComManagerDisableBroadcasts)(CMHANDLE cmHandle, int pHandle)
Definition: com_manager.h:138
pfnComManagerRead readCallback
Definition: com_manager.h:194
com_manager_status_t * comManagerGetStatusInstance(CMHANDLE cmInstance, int pHandle)
Definition: com_manager.c:492
void comManagerDisableBroadcastsInstance(CMHANDLE cmInstance_, int pHandle)
Definition: com_manager.c:1062
int comManagerGetDataRequestInstance(CMHANDLE _cmInstance, int pHandle, p_data_get_t *req)
Definition: com_manager.c:900
char copyDataPToStructP(void *sptr, const p_data_t *data, const unsigned int maxsize)
Definition: ISComm.c:975
#define MIN_REQUEST_PERIOD_MS
Definition: com_manager.c:27
p_data_hdr_t dataHdr
Definition: com_manager.h:48
void updatePacketRetryAck(com_manager_t *cmInstance, packet_t *pkt)
Definition: com_manager.c:1520
bufPtr_t bodyHdr
Definition: ISComm.h:368
uint32_t pktInfo
Definition: ISComm.h:425
pfnComManagerPreSend preTxFnc
Definition: com_manager.h:162
int comManagerGetDataRequest(int pHandle, p_data_get_t *req)
Definition: com_manager.c:895
#define PID_SET_DATA
Definition: ISComm.h:185
bufPtr_t txData
Definition: ISComm.h:369
unsigned char messageId[4]
Definition: ISComm.h:301
void comManagerStep(void)
Definition: com_manager.c:281
uint32_t offset
Definition: ISComm.h:405
uint32_t pktCounter
Definition: ISComm.h:428
p_ack_hdr_t hdr
Definition: ISComm.h:435
com_manager_port_t * ports
Definition: com_manager.h:215
int comManagerInitInstance(CMHANDLE cmHandle, int numHandles, int maxEnsuredPackets, int stepPeriodMilliseconds, int retryCount, pfnComManagerRead readFnc, pfnComManagerSend sendFnc, pfnComManagerSendBufferAvailableBytes txFreeFnc, pfnComManagerPostRead pstRxFnc, pfnComManagerPostAck pstAckFnc, pfnComManagerDisableBroadcasts disableBcastFnc, com_manager_init_t *buffers, com_manager_port_t *cmPorts)
Definition: com_manager.c:111
#define COM_MANAGER_BUF_SIZE_BCAST_MSG(max_num_bcast_msgs)
Definition: com_manager.h:115
#define MEMBERSIZE(type, member)
Definition: ISConstants.h:334
#define _LIMIT2(x, xmin, xmax)
Definition: ISConstants.h:314
p_data_hdr_t dataHdr
Definition: ISComm.h:441
is_comm_buffer_t buf
Definition: ISComm.h:489
packet_t * registerPacketRetry(com_manager_t *cmInstance, int pHandle, uint8_t pid, unsigned char data[], unsigned int dataSize)
registerPacketRetry - Saves data and packet header info to a retry list that will be resent if the co...
Definition: com_manager.c:1336
#define PID_STOP_BROADCASTS_CURRENT_PORT
Definition: ISComm.h:188
int sendPacket(com_manager_t *cmInstance, int pHandle, packet_t *dPkt, uint8_t additionalPktFlags)
Encode and send out serial port the referenced packet structure.
Definition: com_manager.c:1103
int is_encode_binary_packet(void *srcBuffer, unsigned int srcBufferLength, packet_hdr_t *hdr, uint8_t additionalPktFlags, void *encodedPacket, int encodedPacketLength)
Definition: ISComm.c:791
#define MAX_P_DATA_BODY_SIZE
Definition: ISComm.h:108
int sendDataPacket(com_manager_t *cmInstance, int pHandle, pkt_info_t *msg)
Definition: com_manager.c:1122
int32_t maxEnsuredPackets
Definition: com_manager.h:228
int comManagerSendEnsured(int pHandle, uint8_t pktInfo, unsigned char *data, unsigned int dataSize)
Definition: com_manager.c:665
int is_comm_free(is_comm_instance_t *instance)
Definition: ISComm.c:462
uint32_t size
Definition: ISComm.h:222
union p_ack_t::@43 body
#define MAX_REQUEST_PERIOD_MS
Definition: com_manager.c:28
int comManagerSendRawDataInstance(CMHANDLE cmInstance, int pHandle, uint32_t dataId, void *dataPtr, int dataSize, int dataOffset)
Definition: com_manager.c:606
int initComManagerInstanceInternal(com_manager_t *cmInstance, int numHandles, int maxEnsuredPackets, int stepPeriodMilliseconds, int retryCount, pfnComManagerRead readFnc, pfnComManagerSend sendFnc, pfnComManagerSendBufferAvailableBytes txFreeFnc, pfnComManagerPostRead pstRxFnc, pfnComManagerPostAck pstAckFnc, pfnComManagerDisableBroadcasts disableBcastFnc, com_manager_init_t *buffers, com_manager_port_t *cmPorts)
Definition: com_manager.c:152
#define PID_GET_DATA
Definition: ISComm.h:183
int(* pfnComManagerGenMsgHandler)(CMHANDLE cmHandle, int pHandle, const unsigned char *msg, int msgSize)
Definition: com_manager.h:147
void comManagerGetDataInstance(CMHANDLE cmInstance, int pHandle, uint32_t dataId, int offset, int size, int periodMultiple)
Definition: com_manager.c:521
uint32_t id
Definition: ISComm.h:418
uint8_t * rxPtr
Definition: ISComm.h:219
void * CMHANDLE
Definition: com_manager.h:119
uint32_t broadcastMsgSize
Definition: com_manager.h:103
#define PID_NACK
Definition: ISComm.h:182
#define PID_ACK
Definition: ISComm.h:181
is_comm_instance_t comm
Definition: com_manager.h:174
const unsigned int g_validBaudRates[IS_BAUDRATE_COUNT]
Definition: ISComm.c:84
pfnComManagerSend sendPacketCallback
Definition: com_manager.h:197
int(* pfnComManagerSend)(CMHANDLE cmHandle, int pHandle, unsigned char *buffer, int numberOfBytes)
Definition: com_manager.h:126
int findAsciiMessage(const void *a, const void *b)
Definition: com_manager.c:689
int(* pfnComManagerPreSend)(CMHANDLE cmHandle, int pHandle)
Definition: com_manager.h:141
p_data_hdr_t hdr
Definition: ISComm.h:389
uint8_t * tail
Definition: ISComm.h:460
void comManagerStepTxInstance(CMHANDLE cmInstance_)
Definition: com_manager.c:397
#define _CLAMP(v, minV, maxV)
Definition: ISConstants.h:302
uint32_t id
Definition: ISComm.h:399
USBInterfaceDescriptor data
pkt_info_t pkt
Definition: com_manager.h:45
int(* pfnComManagerRead)(CMHANDLE cmHandle, int pHandle, uint8_t *buffer, int numberOfBytes)
Definition: com_manager.h:123
int32_t ensureRetryCount
Definition: com_manager.h:234
com_manager_status_t status
Definition: com_manager.h:180
uint8_t pid
Definition: ISComm.h:323
int comManagerSendDataNoAckInstance(CMHANDLE cmInstance, int pHandle, uint32_t dataId, void *dataPtr, int dataSize, int dataOffset)
Definition: com_manager.c:582
int32_t lastEnsuredPacketIndex
Definition: com_manager.h:222
void comManagerAssignUserPointer(CMHANDLE cmInstance, void *userPointer)
Definition: com_manager.c:477
void is_comm_init(is_comm_instance_t *instance, uint8_t *buffer, int bufferSize)
Definition: ISComm.c:185
uint32_t size
Definition: ISComm.h:196
void stepComManagerSendMessagesInstance(CMHANDLE cmInstance)
Definition: com_manager.c:408
int encodeBinaryPacket(com_manager_t *cmInstance, int pHandle, buffer_t *pkt, packet_t *dPkt, uint8_t additionalPktFlags)
Adds data to a packet: adds start, info, data length, data, checksum, and stop bytes. All data is communicated in the endianess of the sender, each packet has a bit that determines big or little endian. Process for Creating Tx Packet: 1.) Add to packet.
Definition: com_manager.c:1270
pfnComManagerGenMsgHandler cmMsgHandlerAscii
Definition: com_manager.h:243
uint32_t txPktCount
Definition: ISComm.h:495
#define COM_MANAGER_BUF_SIZE_ENSURED_PKTS(max_num_ensured_pkts)
Definition: com_manager.h:116
#define MAX_NUM_BCAST_MSGS
Definition: com_manager.h:112
pfnComManagerGenMsgHandler cmMsgHandlerRtcm3
Definition: com_manager.h:249
void disableBroadcastMsg(com_manager_t *cmInstance, broadcast_msg_t *msg)
Definition: com_manager.c:1049
p_data_hdr_t dataHdr
Definition: ISComm.h:507
#define PID_DATA
Definition: ISComm.h:184
void comManagerSetCallbacks(pfnComManagerAsapMsg handlerRmc, pfnComManagerGenMsgHandler handlerAscii, pfnComManagerGenMsgHandler handlerUblox, pfnComManagerGenMsgHandler handlerRtcm3)
Definition: com_manager.c:453
void comManagerGetDataRmc(int pHandle, uint64_t rmcBits, uint32_t rmcOptions)
Definition: com_manager.c:539
int comManagerSend(int pHandle, uint8_t pktInfo, bufPtr_t *bodyHdr, bufPtr_t *txData, uint8_t pFlags)
Definition: com_manager.c:639
void stepComManagerSendMessages(void)
Definition: com_manager.c:403
int32_t period
Definition: com_manager.h:54
void * comManagerGetUserPointer(CMHANDLE cmInstance)
Definition: com_manager.c:482
pfnComManagerPostAck pstAckFnc
Definition: com_manager.h:206
int comManagerSendData(int pHandle, uint32_t dataId, void *dataPtr, int dataSize, int dataOffset)
Definition: com_manager.c:553
int comManagerDisableDataInstance(CMHANDLE cmInstance, int pHandle, uint32_t dataId)
Definition: com_manager.c:630
protocol_type_t
Definition: ISComm.h:75
uint8_t * ptr
Definition: ISComm.h:206
void enableBroadcastMsg(com_manager_t *cmInstance, broadcast_msg_t *msg, int periodMultiple)
Definition: com_manager.c:1035
#define PID_STOP_DID_BROADCAST
Definition: ISComm.h:187
protocol_type_t is_comm_parse(is_comm_instance_t *instance)
Definition: ISComm.c:514
void comManagerGetData(int pHandle, uint32_t dataId, int offset, int size, int periodMultiple)
Request data This function requests the specified data w/ offset and length for partial reads...
Definition: com_manager.c:516
uint8_t buf[MAX_DATASET_SIZE]
Definition: ISComm.h:392
int comManagerInit(int numHandles, int maxEnsuredPackets, int stepPeriodMilliseconds, int retryCount, pfnComManagerRead readFnc, pfnComManagerSend sendFnc, pfnComManagerSendBufferAvailableBytes txFreeFnc, pfnComManagerPostRead pstRxFnc, pfnComManagerPostAck pstAckFnc, pfnComManagerDisableBroadcasts disableBcastFnc, com_manager_init_t *buffers, com_manager_port_t *cmPorts)
Definition: com_manager.c:79
packet_t pkt
Definition: ISComm.h:522
#define _ARRAY_ELEMENT_COUNT(a)
Definition: ISConstants.h:326
int32_t stepPeriodMilliseconds
Definition: com_manager.h:231
uint8_t flags
Definition: ISComm.h:335
int32_t numHandles
Definition: com_manager.h:225
uint32_t bc_period_multiple
Definition: ISComm.h:411
bufTxRxPtr_t dataSet
Definition: com_manager.h:159
uint32_t offset
Definition: ISComm.h:382
pfnComManagerDisableBroadcasts disableBcastFnc
Definition: com_manager.h:209
void comManagerRegister(uint32_t dataId, pfnComManagerPreSend txFnc, pfnComManagerPostRead pstRxFnc, const void *txDataPtr, void *rxDataPtr, int dataSize, uint8_t pktFlags)
Definition: com_manager.c:247
uint8_t counter
Definition: ISComm.h:326
uint32_t size
Definition: ISComm.h:402
uint32_t ensuredPacketsSize
Definition: com_manager.h:106
void(* pfnComManagerPostAck)(CMHANDLE cmHandle, int pHandle, p_ack_t *ack, unsigned char packetIdentifier)
Definition: com_manager.h:135
void comManagerStepInstance(CMHANDLE cmInstance_)
Definition: com_manager.c:287
static com_manager_t g_cm
Definition: com_manager.c:32
int comManagerSendEnsuredInstance(CMHANDLE cmInstance, int pHandle, uint8_t pktInfo, unsigned char *data, unsigned int dataSize)
Definition: com_manager.c:670
CMHANDLE comManagerGetGlobal(void)
Definition: com_manager.c:76
uint8_t * dataPtr
Definition: ISComm.h:510


inertial_sense_ros
Author(s):
autogenerated on Sun Feb 28 2021 03:17:57