F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
TlmPacketizer.cpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title TlmPacketizerImpl.cpp
3 // \author tcanham
4 // \brief cpp file for TlmPacketizer component implementation class
5 //
6 // \copyright
7 // Copyright 2009-2015, by the California Institute of Technology.
8 // ALL RIGHTS RESERVED. United States Government Sponsorship
9 // acknowledged.
10 
11 #include <Fw/Com/ComPacket.hpp>
12 #include <Fw/FPrimeBasicTypes.hpp>
15 #include <cstring>
16 
17 namespace Svc {
18 
19 const TlmPacketizer_TelemetrySendPortMap TlmPacketizer::TELEMETRY_SEND_PORT_MAP = {};
20 
21 static_assert(Svc::TelemetrySection::NUM_SECTIONS >= 1, "At least one telemetry section is required");
22 
23 // ----------------------------------------------------------------------
24 // Construction, initialization, and destruction
25 // ----------------------------------------------------------------------
26 
27 TlmPacketizer ::TlmPacketizer(const char* const compName)
28  : TlmPacketizerComponentBase(compName), m_numPackets(0), m_configured(false), m_numChannels(0) {
29  // Register self as parameter delegate
30  this->registerExternalParameters(this);
31  // clear missing tlm channel check
32  for (FwChanIdType entry = 0; entry < TLMPACKETIZER_MAX_MISSING_TLM_CHECK; entry++) {
33  this->m_missTlmCheck[entry].checked = false;
34  this->m_missTlmCheck[entry].id = 0;
35  }
36 
37  // clear packet buffers
38  for (FwChanIdType buffer = 0; buffer < MAX_PACKETIZER_PACKETS; buffer++) {
39  this->m_fillBuffers[buffer].updated = false;
40  }
41 
43  "NUM_CONFIGURABLE_TLMPACKETIZER_GROUPS MUST BE MAX_CONFIGURABLE_TLMPACKETIZER_GROUP + 1");
44 }
45 
47 
49  const Svc::TlmPacketizerPacket& ignoreList,
50  const FwChanIdType startLevel) {
51  FW_ASSERT(packetList.list);
52  // Ignore list may be nullptr as long as numEntries is 0. Providing an ignore list with numEntries 0 disables
53  // functionality for two reasons:
54  // 1. There are no ignored channels as configured by FPP.
55  // 2. Ignore functionality is intentionally disabled by project where nullptr was intentionally supplied.
56  FW_ASSERT(ignoreList.list || ignoreList.numEntries == 0);
57  FW_ASSERT(packetList.numEntries <= MAX_PACKETIZER_PACKETS, static_cast<FwAssertArgType>(packetList.numEntries));
58 
59  // Reset key data members incase of reentrant calls
60  this->m_numChannels = 0;
61  this->m_channelIndices.clear();
62  this->m_configured = false;
63 
64  // validate packet sizes against maximum com buffer size and populate hash
65  // table
66  FwChanIdType maxLevel = 0;
67  for (FwChanIdType pktEntry = 0; pktEntry < packetList.numEntries; pktEntry++) {
68  // Initial size is packetized telemetry descriptor + size of time tag + sizeof packet ID
69  FwSizeType packetLen =
71  FW_ASSERT(packetList.list[pktEntry]->list, static_cast<FwAssertArgType>(pktEntry));
72  // add up entries for each defined packet
73  for (FwChanIdType tlmEntry = 0; tlmEntry < packetList.list[pktEntry]->numEntries; tlmEntry++) {
74  FwChanIdType id = packetList.list[pktEntry]->list[tlmEntry].id;
75  FwSizeType entryIndex = 0;
76  if (this->m_channelIndices.find(id, entryIndex) != Fw::Success::SUCCESS) {
77  // New channel - allocate a slot and initialize offsets to -1 (not in any packet)
78  entryIndex = this->m_numChannels++;
79  this->m_channels[entryIndex].id = id;
80  this->m_channels[entryIndex].hasValue = false;
81  for (FwChanIdType pktOffsetEntry = 0; pktOffsetEntry < MAX_PACKETIZER_PACKETS; pktOffsetEntry++) {
82  this->m_channels[entryIndex].packetOffset[pktOffsetEntry] = -1;
83  }
84  const Fw::Success insertStatus = this->m_channelIndices.insert(id, entryIndex);
85  FW_ASSERT(insertStatus == Fw::Success::SUCCESS, static_cast<FwAssertArgType>(insertStatus));
86  }
87  // not ignored channel - update entry in place via reference
88  TlmEntry& entry = this->m_channels[entryIndex];
89  entry.ignored = false;
90  entry.channelSize = packetList.list[pktEntry]->list[tlmEntry].size;
91  // the offset into the buffer will be the current packet length
92  // the offset must fit within FwSignedSizeType to allow for negative values
93  FW_ASSERT(packetLen <= static_cast<FwSizeType>(std::numeric_limits<FwSignedSizeType>::max()),
94  static_cast<FwAssertArgType>(packetLen));
95  entry.packetOffset[pktEntry] = static_cast<FwSignedSizeType>(packetLen);
96 
97  packetLen += entry.channelSize;
98 
99  } // end channel in packet
100  FW_ASSERT(packetLen <= FW_COM_BUFFER_MAX_SIZE, static_cast<FwAssertArgType>(packetLen),
101  static_cast<FwAssertArgType>(pktEntry));
102  // clear contents
103  memset(this->m_fillBuffers[pktEntry].buffer.getBuffAddr(), 0, static_cast<size_t>(packetLen));
104  // serialize packet descriptor and packet ID now since it will always be the same
105  Fw::SerializeStatus stat = this->m_fillBuffers[pktEntry].buffer.serializeFrom(
106  static_cast<FwPacketDescriptorType>(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM));
107  FW_ASSERT(Fw::FW_SERIALIZE_OK == stat, stat);
108  stat = this->m_fillBuffers[pktEntry].buffer.serializeFrom(packetList.list[pktEntry]->id);
109  FW_ASSERT(Fw::FW_SERIALIZE_OK == stat, stat);
110  // set packet buffer length
111  stat = this->m_fillBuffers[pktEntry].buffer.setBuffLen(packetLen);
112  FW_ASSERT(Fw::FW_SERIALIZE_OK == stat, stat);
113  // save ID
114  this->m_fillBuffers[pktEntry].id = packetList.list[pktEntry]->id;
115  // save level
116  this->m_fillBuffers[pktEntry].level = packetList.list[pktEntry]->level;
117  // store max level
118  if (packetList.list[pktEntry]->level > maxLevel) {
119  maxLevel = packetList.list[pktEntry]->level;
120  }
121 
122  } // end packet list
123  FW_ASSERT(maxLevel <= MAX_CONFIGURABLE_TLMPACKETIZER_GROUP, static_cast<FwAssertArgType>(maxLevel));
124 
125  // This section adds entries in the map for channels that are intended to be ignored. When the user supplies
126  // a list with no length, this loop is skipped. To turn-off ignoring of channels, the user can provide a null
127  // list with 0 length.
128  for (FwChanIdType channelEntry = 0; channelEntry < ignoreList.numEntries; channelEntry++) {
129  FwChanIdType id = ignoreList.list[channelEntry].id;
130  FwSizeType entryIndex = 0;
131  if (this->m_channelIndices.find(id, entryIndex) != Fw::Success::SUCCESS) {
132  // New channel - allocate a slot and initialize offsets to -1 (not in any packet)
133  entryIndex = this->m_numChannels++;
134  this->m_channels[entryIndex].id = id;
135  this->m_channels[entryIndex].hasValue = false;
136  for (FwChanIdType pktOffsetEntry = 0; pktOffsetEntry < MAX_PACKETIZER_PACKETS; pktOffsetEntry++) {
137  this->m_channels[entryIndex].packetOffset[pktOffsetEntry] = -1;
138  }
139  const Fw::Success insertStatus = this->m_channelIndices.insert(id, entryIndex);
140  FW_ASSERT(insertStatus == Fw::Success::SUCCESS, static_cast<FwAssertArgType>(insertStatus));
141  } else {
142  // Ensure it is a duplicate in the ignore list, not a duplicate of a valid channel
143  FW_ASSERT(this->m_channels[entryIndex].ignored, static_cast<FwAssertArgType>(id));
144  }
145  // is ignored channel - update entry in place via reference
146  TlmEntry& entry = this->m_channels[entryIndex];
147  entry.ignored = true;
148  entry.channelSize = ignoreList.list[channelEntry].size;
149  } // end ignore list
150 
151  // store number of packets
152  this->m_numPackets = packetList.numEntries;
153 
154  // indicate configured
155  this->m_configured = true;
156 }
157 
158 // ----------------------------------------------------------------------
159 // Handler implementations for user-defined typed input ports
160 // ----------------------------------------------------------------------
161 
162 void TlmPacketizer ::TlmRecv_handler(const FwIndexType portNum,
163  FwChanIdType id,
164  Fw::Time& timeTag,
165  Fw::TlmBuffer& val) {
166  FW_ASSERT(this->m_configured);
167  FwSizeType entryIndex = 0;
168 
169  // Search to see if the channel is being tracked
170  if (this->m_channelIndices.find(id, entryIndex) != Fw::Success::SUCCESS) {
171  // channel not part of a packet and not ignored
172  this->missingChannel(id);
173  return;
174  }
175 
176  TlmEntry& entry = this->m_channels[entryIndex];
177 
178  // check to see if the channel is ignored. If so, just return.
179  if (entry.ignored) {
180  return;
181  }
182 
183  // copy telemetry value into active buffers; hasValue written in-place via reference
184  entry.hasValue = true;
185  for (FwChanIdType pkt = 0; pkt < MAX_PACKETIZER_PACKETS; pkt++) {
186  // check if current packet has this channel
187  if (entry.packetOffset[pkt] != -1) {
188  // get destination address
189  this->m_lock.lock();
190  this->m_fillBuffers[pkt].updated = true;
191  this->m_fillBuffers[pkt].latestTime = timeTag;
192  U8* ptr = &this->m_fillBuffers[pkt].buffer.getBuffAddr()[entry.packetOffset[pkt]];
193  // validate before memcpy
194  FW_ASSERT(val.getSize() <= entry.channelSize, static_cast<FwAssertArgType>(val.getSize()),
195  static_cast<FwAssertArgType>(entry.channelSize));
196 
197  (void)memcpy(ptr, val.getBuffAddr(), static_cast<size_t>(val.getSize()));
198  this->m_lock.unLock();
199  }
200  }
201 }
202 
203 void TlmPacketizer ::configureSectionGroupRate_handler(FwIndexType portNum,
204  const Svc::TelemetrySection& section,
205  FwChanIdType tlmGroup,
206  const Svc::RateLogic& rateLogic,
207  U32 minDelta,
208  U32 maxDelta) {
209  this->configureSectionGroupRate(section, tlmGroup, rateLogic, minDelta, maxDelta);
210 }
211 
213 Fw::TlmValid TlmPacketizer ::TlmGet_handler(FwIndexType portNum,
214  FwChanIdType id,
215  Fw::Time& timeTag,
216  Fw::TlmBuffer& val
217 ) {
219  FW_ASSERT(this->m_configured);
220  FwSizeType entryIndex = 0;
221 
222  // Search to see if the channel is being tracked
223  if (this->m_channelIndices.find(id, entryIndex) != Fw::Success::SUCCESS) {
224  // channel not part of a packet and not ignored
225  this->missingChannel(id);
226  val.resetSer();
227  return Fw::TlmValid::INVALID;
228  }
229  const TlmEntry& entry = this->m_channels[entryIndex];
230 
231  // check to see if the channel is ignored. If so, just return, as
232  // we don't store the bytes of ignored channels
233  if (entry.ignored) {
234  val.resetSer();
235  return Fw::TlmValid::INVALID;
236  }
237 
238  if (!entry.hasValue) {
239  // haven't received a value yet for this entry.
240  val.resetSer();
241  return Fw::TlmValid::INVALID;
242  }
243 
244  // make sure we have enough space to store this entry in our buf
245  FW_ASSERT(entry.channelSize <= val.getCapacity(), static_cast<FwAssertArgType>(entry.channelSize),
246  static_cast<FwAssertArgType>(val.getCapacity()));
247 
248  // okay, we have the matching entry.
249  // go over each packet and find the first one which stores this channel
250 
251  for (FwChanIdType pkt = 0; pkt < MAX_PACKETIZER_PACKETS; pkt++) {
252  // check if current packet has this channel
253  if (entry.packetOffset[pkt] != -1) {
254  // okay, it has the channel. copy chan val into the tlm buf
255  this->m_lock.lock();
256  timeTag = this->m_fillBuffers[pkt].latestTime;
257  U8* ptr = &this->m_fillBuffers[pkt].buffer.getBuffAddr()[entry.packetOffset[pkt]];
258  (void)memcpy(val.getBuffAddr(), ptr, static_cast<size_t>(entry.channelSize));
259  // set buf len to the channelSize. keep in mind, this is the MAX serialized size of the channel.
260  // so we may actually be filling val with some junk after the value of the channel.
261  FW_ASSERT(val.setBuffLen(entry.channelSize) == Fw::SerializeStatus::FW_SERIALIZE_OK);
262  this->m_lock.unLock();
263  return Fw::TlmValid::VALID;
264  }
265  }
266 
267  // did not find a packet which stores this channel.
268  // coding error, this was not an ignored channel so it must be in a packet somewhere
269  FW_ASSERT(0, static_cast<FwAssertArgType>(entry.id));
270  // TPP (tim paranoia principle)
271  val.resetSer();
272  return Fw::TlmValid::INVALID;
273 }
274 
275 void TlmPacketizer ::Run_handler(const FwIndexType portNum, U32 context) {
276  FW_ASSERT(this->m_configured);
277 
278  for (FwChanIdType pkt = 0; pkt < this->m_numPackets; pkt++) {
279  // Local flags to track which sections require a packet dispatch
280  bool sectionNeedsSend[TelemetrySection::NUM_SECTIONS] = {false};
281  bool anySectionNeedsSend = false;
282 
283  // Lock only to capture the update status and reset the fill buffer flag.
284  this->m_lock.lock();
285  bool isNewData = this->m_fillBuffers[pkt].updated;
286  FwChanIdType entryGroup = this->m_fillBuffers[pkt].level;
287  this->m_fillBuffers[pkt].updated = false;
288  this->m_lock.unLock();
289 
290  for (FwIndexType section = 0; section < TelemetrySection::NUM_SECTIONS; section++) {
291  PktSendCounters& pktEntryFlags = this->m_packetFlags[static_cast<FwSizeType>(section)][pkt];
292  TlmPacketizer_GroupConfig& entryGroupConfig =
293  this->m_groupConfigs[static_cast<FwSizeType>(section)][entryGroup];
294 
295  // Packet is updated and not REQUESTED (Keep REQUESTED marking to bypass disable checks)
296  if (isNewData && pktEntryFlags.updateFlag != UpdateFlag::REQUESTED) {
297  pktEntryFlags.updateFlag = UpdateFlag::NEW;
298  }
299 
300  /* Base conditions for sending
301  1. Output port is connected
302  2. The packet was requested (Override Checks).
303 
304  If the packet wasn't requested:
305  3. The Section and Group in Section is enabled OR the Group in Section is force enabled
306  4. The rate logic is not SILENCED.
307  5. The packet has data (marked updated in the past or new)
308  */
309  if (!this->isConnected_PktSend_OutputPort(this->sectionGroupToPort(section, entryGroup))) {
310  continue;
311  }
312 
313  if (pktEntryFlags.updateFlag == UpdateFlag::REQUESTED) {
314  sectionNeedsSend[section] = true;
315  } else {
316  if (not((entryGroupConfig.get_enabled() and
317  this->m_sectionEnabled[static_cast<FwSizeType>(section)] == Fw::Enabled::ENABLED) or
318  entryGroupConfig.get_forceEnabled() == Fw::Enabled::ENABLED)) {
319  continue;
320  }
321  if (entryGroupConfig.get_rateLogic() == Svc::RateLogic::SILENCED) {
322  continue;
323  }
324  if (pktEntryFlags.updateFlag == UpdateFlag::NEVER_UPDATED) {
325  continue; // Avoid No Data
326  }
327  }
328 
329  // Update Counter, prevent overflow.
330  if (pktEntryFlags.prevSentCounter < std::numeric_limits<U32>::max()) {
331  pktEntryFlags.prevSentCounter++;
332  }
333 
334  /*
335  1. Packet has been updated
336  2. Group Logic includes checking MIN
337  3. Packet sent counter at MIN
338  */
339  if (pktEntryFlags.updateFlag == UpdateFlag::NEW and
340  entryGroupConfig.get_rateLogic() != Svc::RateLogic::EVERY_MAX and
341  pktEntryFlags.prevSentCounter >= entryGroupConfig.get_min()) {
342  sectionNeedsSend[section] = true;
343  }
344 
345  /*
346  1. Group Logic includes checking MAX
347  2. Packet set counter is at MAX
348  */
349  if (entryGroupConfig.get_rateLogic() != Svc::RateLogic::ON_CHANGE_MIN and
350  pktEntryFlags.prevSentCounter >= entryGroupConfig.get_max()) {
351  sectionNeedsSend[section] = true;
352  }
353 
354  if (sectionNeedsSend[section]) {
355  anySectionNeedsSend = true;
356  }
357  }
358 
359  // Only perform the buffer copy if at least one section needs to send.
360  if (anySectionNeedsSend) {
361  this->m_lock.lock();
362  BufferEntry sendBuffer = this->m_fillBuffers[pkt];
363  this->m_lock.unLock();
364 
365  // serialize time into time offset in packet
367  &sendBuffer.buffer.getBuffAddr()[sizeof(FwPacketDescriptorType) + sizeof(FwTlmPacketizeIdType)],
369  (void)buff.serializeFrom(sendBuffer.latestTime);
370 
371  for (FwIndexType section = 0; section < TelemetrySection::NUM_SECTIONS; section++) {
372  if (sectionNeedsSend[section]) {
373  PktSendCounters& pktEntryFlags = this->m_packetFlags[section][pkt];
374  FwIndexType outIndex = this->sectionGroupToPort(section, entryGroup);
375 
376  this->PktSend_out(outIndex, sendBuffer.buffer, pktEntryFlags.prevSentCounter);
377 
378  pktEntryFlags.prevSentCounter = 0;
379  pktEntryFlags.updateFlag = UpdateFlag::PAST;
380  }
381  }
382  }
383  }
384 }
385 
386 void TlmPacketizer ::controlIn_handler(FwIndexType portNum,
387  const Svc::TelemetrySection& section,
388  const Fw::Enabled& enabled) {
389  // NUM_SECTIONS is an enum constant (not a standalone constant), so isValid() accepts it.
390  // The explicit bounds check prevents an out-of-bounds write to m_sectionEnabled.
391  if (section.isValid() && section < TelemetrySection::NUM_SECTIONS && enabled.isValid()) {
392  (void)(this->m_sectionEnabled[static_cast<FwSizeType>(section)] = enabled);
393  } else {
394  this->log_WARNING_LO_SectionUnconfigurable(section, enabled);
395  }
396 }
397 
398 void TlmPacketizer ::pingIn_handler(const FwIndexType portNum, U32 key) {
399  // return key
400  this->pingOut_out(0, key);
401 }
402 
403 // ----------------------------------------------------------------------
404 // Command handler implementations
405 // ----------------------------------------------------------------------
406 
407 void TlmPacketizer ::SET_LEVEL_cmdHandler(const FwOpcodeType opCode, const U32 cmdSeq, FwChanIdType level) {
410  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
411  return;
412  }
413  for (FwIndexType section = 0; section < TelemetrySection::NUM_SECTIONS; section++) {
414  for (FwChanIdType group = 0; group < NUM_CONFIGURABLE_TLMPACKETIZER_GROUPS; group++) {
415  this->m_groupConfigs[static_cast<FwSizeType>(section)][group].set_enabled(
416  group <= level ? Fw::Enabled::ENABLED : Fw::Enabled::DISABLED);
417  }
418  }
419  this->tlmWrite_GroupConfigs(this->m_groupConfigs);
420  this->log_ACTIVITY_HI_LevelSet(level);
421  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
422 }
423 
424 void TlmPacketizer ::SEND_PKT_cmdHandler(const FwOpcodeType opCode,
425  const U32 cmdSeq,
426  const U32 id,
427  const Svc::TelemetrySection section) {
428  FW_ASSERT(section.isValid());
429  if (section < 0 or section >= TelemetrySection::NUM_SECTIONS) {
430  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
431  return;
432  }
433  FwChanIdType pkt = 0;
434  for (pkt = 0; pkt < this->m_numPackets; pkt++) {
435  if (this->m_fillBuffers[pkt].id == id) {
436  this->m_lock.lock();
437  this->m_fillBuffers[pkt].updated = true;
438  this->m_fillBuffers[pkt].latestTime = this->getTime();
439  this->m_lock.unLock();
440 
441  this->m_packetFlags[section][pkt].updateFlag = UpdateFlag::REQUESTED;
442 
443  this->log_ACTIVITY_LO_PacketSent(id);
444  break;
445  }
446  }
447 
448  // couldn't find it
449  if (pkt == this->m_numPackets) {
451  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
452  return;
453  }
454 
455  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
456 }
457 
458 void TlmPacketizer ::ENABLE_SECTION_cmdHandler(FwOpcodeType opCode,
459  U32 cmdSeq,
460  Svc::TelemetrySection section,
461  Fw::Enabled enable) {
462  FW_ASSERT(section.isValid());
463  FW_ASSERT(enable.isValid());
464  if (section < 0 or section >= TelemetrySection::NUM_SECTIONS) {
465  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
466  return;
467  }
468  (void)(this->m_sectionEnabled[section] = enable);
469  this->tlmWrite_SectionEnabled(this->m_sectionEnabled);
470  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
471 }
472 
473 void TlmPacketizer ::ENABLE_GROUP_cmdHandler(FwOpcodeType opCode,
474  U32 cmdSeq,
475  Svc::TelemetrySection section,
476  FwChanIdType tlmGroup,
477  Fw::Enabled enable) {
478  FW_ASSERT(section.isValid());
479  FW_ASSERT(enable.isValid());
480  if (section < 0 or section >= TelemetrySection::NUM_SECTIONS or tlmGroup > MAX_CONFIGURABLE_TLMPACKETIZER_GROUP) {
481  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
482  return;
483  }
484  this->m_groupConfigs[section][tlmGroup].set_enabled(enable);
485  this->tlmWrite_GroupConfigs(this->m_groupConfigs);
486  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
487 }
488 
489 void TlmPacketizer ::FORCE_GROUP_cmdHandler(FwOpcodeType opCode,
490  U32 cmdSeq,
491  Svc::TelemetrySection section,
492  FwChanIdType tlmGroup,
493  Fw::Enabled enable) {
494  FW_ASSERT(section.isValid());
495  FW_ASSERT(enable.isValid());
496  if (section < 0 or section >= TelemetrySection::NUM_SECTIONS or tlmGroup > MAX_CONFIGURABLE_TLMPACKETIZER_GROUP) {
497  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
498  return;
499  }
500  this->m_groupConfigs[section][tlmGroup].set_forceEnabled(enable);
501  this->tlmWrite_GroupConfigs(this->m_groupConfigs);
502  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
503 }
504 
505 void TlmPacketizer ::CONFIGURE_GROUP_RATES_cmdHandler(FwOpcodeType opCode,
506  U32 cmdSeq,
507  Svc::TelemetrySection section,
508  FwChanIdType tlmGroup,
509  Svc::RateLogic rateLogic,
510  U32 minDelta,
511  U32 maxDelta) {
512  FW_ASSERT(section.isValid());
513  FW_ASSERT(rateLogic.isValid());
514  if (section < 0 or section >= TelemetrySection::NUM_SECTIONS or tlmGroup > MAX_CONFIGURABLE_TLMPACKETIZER_GROUP) {
515  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
516  return;
517  }
518  this->configureSectionGroupRate(section, tlmGroup, rateLogic, minDelta, maxDelta);
519  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
520 }
521 
522 void TlmPacketizer::configureSectionGroupRate(
523  const Svc::TelemetrySection& section,
524  FwChanIdType tlmGroup,
525  const Svc::RateLogic& rateLogic,
526  U32 minDelta,
527  U32 maxDelta
528 ) {
529  FW_ASSERT(section.isValid());
530  FW_ASSERT(rateLogic.isValid());
531  // These two asserts are an "if" statement in a command so they will no assert on bad user data
532  FW_ASSERT(section >= 0 and section < TelemetrySection::NUM_SECTIONS);
534 
535  TlmPacketizer_GroupConfig& groupConfig = this->m_groupConfigs[section][tlmGroup];
536  groupConfig.set_rateLogic(rateLogic);
537  groupConfig.set_min(minDelta);
538  groupConfig.set_max(maxDelta);
539  this->tlmWrite_GroupConfigs(this->m_groupConfigs);
540 }
541 
542 FwIndexType TlmPacketizer::sectionGroupToPort(const FwIndexType section, const FwSizeType group) {
543  // Confirm the indices will not overflow the size of the array
544  FW_ASSERT(group < TlmPacketizer_TelemetrySendSection::SIZE, static_cast<FwAssertArgType>(group));
545  FW_ASSERT(section < TlmPacketizer_TelemetrySendPortMap::SIZE, static_cast<FwAssertArgType>(section));
546 
547  const FwIndexType outIndex = TlmPacketizer::TELEMETRY_SEND_PORT_MAP[static_cast<FwSizeType>(section)][group];
548 
549  // Confirm the output port index is within the valid number of telemetry send ports
550  FW_ASSERT(outIndex < TELEMETRY_SEND_PORTS, static_cast<FwAssertArgType>(outIndex));
551  return outIndex;
552 }
553 
554 void TlmPacketizer::missingChannel(FwChanIdType id) {
555  // search to see if missing channel has already been sent
556  for (FwChanIdType slot = 0; slot < TLMPACKETIZER_MAX_MISSING_TLM_CHECK; slot++) {
557  // if it's been checked, return
558  if (this->m_missTlmCheck[slot].checked and (this->m_missTlmCheck[slot].id == id)) {
559  return;
560  } else if (not this->m_missTlmCheck[slot].checked) {
561  this->m_missTlmCheck[slot].checked = true;
562  this->m_missTlmCheck[slot].id = id;
563  this->log_WARNING_LO_NoChan(id);
564  return;
565  }
566  }
567 }
568 
569 Fw::SerializeStatus TlmPacketizer::deserializeParam(const FwPrmIdType base_id,
570  const FwPrmIdType local_id,
571  const Fw::ParamValid prmStat,
572  Fw::SerialBufferBase& buff) {
573  if ((prmStat == Fw::ParamValid::VALID) || (prmStat == Fw::ParamValid::DEFAULT)) {
574  switch (local_id) {
576  return buff.deserializeTo(this->m_sectionEnabled);
578  return buff.deserializeTo(this->m_groupConfigs);
579  default:
580  FW_ASSERT(0, static_cast<FwAssertArgType>(local_id));
581  }
582  }
584 }
585 
586 Fw::SerializeStatus TlmPacketizer::serializeParam(const FwPrmIdType base_id,
587  const FwPrmIdType local_id,
588  Fw::SerialBufferBase& buff) const {
589  switch (local_id) {
591  return buff.serializeFrom(this->m_sectionEnabled);
593  return buff.serializeFrom(this->m_groupConfigs);
594  default:
595  FW_ASSERT(0, static_cast<FwAssertArgType>(local_id));
596  }
598 }
599 
600 } // end namespace Svc
bool isConnected_PktSend_OutputPort(FwIndexType portNum) const
Serialization/Deserialization operation was successful.
bool isValid() const
Check raw enum value for validity.
U16 FwPacketDescriptorType
The width of packet descriptors when they are serialized by the framework.
TlmPacketizer(const char *const compName)
REQUIRED: Counter, leave as last element.
FwIdType FwOpcodeType
The type of a command opcode.
SerializeStatus serializeFrom(U8 val, Endianness mode=Endianness::BIG) override
Serialize an 8-bit unsigned integer value.
Representing success.
FwSizeType size
serialized size of channel in bytes
PlatformSizeType FwSizeType
FwTlmPacketizeIdType id
packet ID
void tlmWrite_GroupConfigs(const Svc::TlmPacketizer_SectionConfigs &arg, Fw::Time _tlmTime=Fw::Time()) const
Enabled state.
void log_ACTIVITY_HI_LevelSet(FwChanIdType level) const
void log_ACTIVITY_LO_PacketSent(U32 packetId) const
Serializable::SizeType getSize() const override
Get current buffer size.
FwIdType FwPrmIdType
The type of a parameter identifier.
const TlmPacketizerPacket * list[MAX_PACKETIZER_PACKETS]
void log_WARNING_LO_NoChan(FwChanIdType Id) const
static const FwChanIdType MAX_PACKETIZER_PACKETS
Maximum number of packets that the packetizer can handle.
void unLock()
unlock the mutex and assert success
Definition: Mutex.cpp:41
bool isValid() const
Check raw enum value for validity.
PlatformSignedSizeType FwSignedSizeType
void cmdResponse_out(FwOpcodeType opCode, U32 cmdSeq, Fw::CmdResponse response)
Emit command response.
Send on updates after MIN ticks since last send.
virtual SerializeStatus serializeFrom(U8 val, Endianness mode=Endianness::BIG)=0
Serialize an 8-bit unsigned integer value.
Success find(const K &key, V &value) const override
Send every MAX ticks between sends.
const TlmPacketizerChannelEntry * list
pointer to a channel entry
void log_WARNING_LO_PacketNotFound(U32 packetId) const
static const FwChanIdType TLMPACKETIZER_MAX_MISSING_TLM_CHECK
Maximum number of missing channels to track and report.
void tlmWrite_SectionEnabled(const Svc::TlmPacketizer_SectionEnabled &arg, Fw::Time _tlmTime=Fw::Time()) const
Write telemetry channel SectionEnabled.
SerializeStatus
forward declaration for string
No logic applied. Does not send group and freezes counter.
void registerExternalParameters(Fw::ParamExternalDelegate *paramExternalDelegatePtr)
Initialize the external parameter delegate.
virtual SerializeStatus deserializeTo(U8 &val, Endianness mode=Endianness::BIG)=0
Deserialize an 8-bit unsigned integer value.
FwChanIdType id
Id of channel.
FwChanIdType level
packet level - used to select set of packets to send
Data was the wrong format (e.g. wrong packet type)
Enumeration for rate logic types for telemetry groups.
External serialize buffer with no copy semantics.
FwIdType FwChanIdType
The type of a telemetry channel identifier.
U8 * getBuffAddr()
Get buffer address for data filling (non-const version)
Definition: TlmBuffer.cpp:42
void resetSer() override
Reset serialization pointer to beginning of buffer.
Deserialized type ID didn&#39;t match.
Enabled and disabled states.
U16 FwTlmPacketizeIdType
The type of a telemetry packet identifier.
Command successfully executed.
void clear() override
Clear the map.
void setPacketList(const TlmPacketizerPacketList &packetList, const Svc::TlmPacketizerPacket &ignoreList, const FwChanIdType startLevel)
bool isValid() const
Check raw enum value for validity.
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:53
void PktSend_out(FwIndexType portNum, Fw::ComBuffer &data, U32 context) const
Invoke output port PktSend.
void log_WARNING_LO_SectionUnconfigurable(Svc::TelemetrySection section, Fw::Enabled enable) const
Log event SectionUnconfigurable.
void log_WARNING_LO_MaxLevelExceed(FwChanIdType level, FwChanIdType max) const
PlatformIndexType FwIndexType
FwSizeType getCapacity() const
Get buffer capacity.
Definition: TlmBuffer.cpp:30
Command failed validation.
RateGroupDivider component implementation.
Enum representing parameter validity.
SerializeStatus setBuffLen(Serializable::SizeType length) override
Set buffer length manually.
FwChanIdType numEntries
number of channels in packet
void pingOut_out(FwIndexType portNum, U32 key) const
Invoke output port pingOut.
Success insert(const K &key, const V &value) override
#define FW_ASSERT(...)
Definition: Assert.hpp:14
Disabled state.
Success/Failure.
PlatformAssertArgType FwAssertArgType
The type of arguments to assert functions.
void lock()
lock the mutex and assert success
Definition: Mutex.cpp:34
Auto-generated base for TlmPacketizer component.