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  }
142  // is ignored channel - update entry in place via reference
143  TlmEntry& entry = this->m_channels[entryIndex];
144  entry.ignored = true;
145  entry.channelSize = ignoreList.list[channelEntry].size;
146  } // end ignore list
147 
148  // store number of packets
149  this->m_numPackets = packetList.numEntries;
150 
151  // indicate configured
152  this->m_configured = true;
153 }
154 
155 // ----------------------------------------------------------------------
156 // Handler implementations for user-defined typed input ports
157 // ----------------------------------------------------------------------
158 
159 void TlmPacketizer ::TlmRecv_handler(const FwIndexType portNum,
160  FwChanIdType id,
161  Fw::Time& timeTag,
162  Fw::TlmBuffer& val) {
163  FW_ASSERT(this->m_configured);
164  FwSizeType entryIndex = 0;
165 
166  // Search to see if the channel is being tracked
167  if (this->m_channelIndices.find(id, entryIndex) != Fw::Success::SUCCESS) {
168  // channel not part of a packet and not ignored
169  this->missingChannel(id);
170  return;
171  }
172 
173  TlmEntry& entry = this->m_channels[entryIndex];
174 
175  // check to see if the channel is ignored. If so, just return.
176  if (entry.ignored) {
177  return;
178  }
179 
180  // copy telemetry value into active buffers; hasValue written in-place via reference
181  entry.hasValue = true;
182  for (FwChanIdType pkt = 0; pkt < MAX_PACKETIZER_PACKETS; pkt++) {
183  // check if current packet has this channel
184  if (entry.packetOffset[pkt] != -1) {
185  // get destination address
186  this->m_lock.lock();
187  this->m_fillBuffers[pkt].updated = true;
188  this->m_fillBuffers[pkt].latestTime = timeTag;
189  U8* ptr = &this->m_fillBuffers[pkt].buffer.getBuffAddr()[entry.packetOffset[pkt]];
190  (void)memcpy(ptr, val.getBuffAddr(), static_cast<size_t>(val.getSize()));
191  this->m_lock.unLock();
192  }
193  }
194 }
195 
196 void TlmPacketizer ::configureSectionGroupRate_handler(FwIndexType portNum,
197  const Svc::TelemetrySection& section,
198  FwChanIdType tlmGroup,
199  const Svc::RateLogic& rateLogic,
200  U32 minDelta,
201  U32 maxDelta) {
202  this->configureSectionGroupRate(section, tlmGroup, rateLogic, minDelta, maxDelta);
203 }
204 
206 Fw::TlmValid TlmPacketizer ::TlmGet_handler(FwIndexType portNum,
207  FwChanIdType id,
208  Fw::Time& timeTag,
209  Fw::TlmBuffer& val
210 ) {
212  FW_ASSERT(this->m_configured);
213  FwSizeType entryIndex = 0;
214 
215  // Search to see if the channel is being tracked
216  if (this->m_channelIndices.find(id, entryIndex) != Fw::Success::SUCCESS) {
217  // channel not part of a packet and not ignored
218  this->missingChannel(id);
219  val.resetSer();
220  return Fw::TlmValid::INVALID;
221  }
222  const TlmEntry& entry = this->m_channels[entryIndex];
223 
224  // check to see if the channel is ignored. If so, just return, as
225  // we don't store the bytes of ignored channels
226  if (entry.ignored) {
227  val.resetSer();
228  return Fw::TlmValid::INVALID;
229  }
230 
231  if (!entry.hasValue) {
232  // haven't received a value yet for this entry.
233  val.resetSer();
234  return Fw::TlmValid::INVALID;
235  }
236 
237  // make sure we have enough space to store this entry in our buf
238  FW_ASSERT(entry.channelSize <= val.getCapacity(), static_cast<FwAssertArgType>(entry.channelSize),
239  static_cast<FwAssertArgType>(val.getCapacity()));
240 
241  // okay, we have the matching entry.
242  // go over each packet and find the first one which stores this channel
243 
244  for (FwChanIdType pkt = 0; pkt < MAX_PACKETIZER_PACKETS; pkt++) {
245  // check if current packet has this channel
246  if (entry.packetOffset[pkt] != -1) {
247  // okay, it has the channel. copy chan val into the tlm buf
248  this->m_lock.lock();
249  timeTag = this->m_fillBuffers[pkt].latestTime;
250  U8* ptr = &this->m_fillBuffers[pkt].buffer.getBuffAddr()[entry.packetOffset[pkt]];
251  (void)memcpy(val.getBuffAddr(), ptr, static_cast<size_t>(entry.channelSize));
252  // set buf len to the channelSize. keep in mind, this is the MAX serialized size of the channel.
253  // so we may actually be filling val with some junk after the value of the channel.
254  FW_ASSERT(val.setBuffLen(entry.channelSize) == Fw::SerializeStatus::FW_SERIALIZE_OK);
255  this->m_lock.unLock();
256  return Fw::TlmValid::VALID;
257  }
258  }
259 
260  // did not find a packet which stores this channel.
261  // coding error, this was not an ignored channel so it must be in a packet somewhere
262  FW_ASSERT(0, static_cast<FwAssertArgType>(entry.id));
263  // TPP (tim paranoia principle)
264  val.resetSer();
265  return Fw::TlmValid::INVALID;
266 }
267 
268 void TlmPacketizer ::Run_handler(const FwIndexType portNum, U32 context) {
269  FW_ASSERT(this->m_configured);
270 
271  for (FwChanIdType pkt = 0; pkt < this->m_numPackets; pkt++) {
272  // Local flags to track which sections require a packet dispatch
273  bool sectionNeedsSend[TelemetrySection::NUM_SECTIONS] = {false};
274  bool anySectionNeedsSend = false;
275 
276  // Lock only to capture the update status and reset the fill buffer flag.
277  this->m_lock.lock();
278  bool isNewData = this->m_fillBuffers[pkt].updated;
279  FwChanIdType entryGroup = this->m_fillBuffers[pkt].level;
280  this->m_fillBuffers[pkt].updated = false;
281  this->m_lock.unLock();
282 
283  for (FwIndexType section = 0; section < TelemetrySection::NUM_SECTIONS; section++) {
284  PktSendCounters& pktEntryFlags = this->m_packetFlags[static_cast<FwSizeType>(section)][pkt];
285  TlmPacketizer_GroupConfig& entryGroupConfig =
286  this->m_groupConfigs[static_cast<FwSizeType>(section)][entryGroup];
287 
288  // Packet is updated and not REQUESTED (Keep REQUESTED marking to bypass disable checks)
289  if (isNewData && pktEntryFlags.updateFlag != UpdateFlag::REQUESTED) {
290  pktEntryFlags.updateFlag = UpdateFlag::NEW;
291  }
292 
293  /* Base conditions for sending
294  1. Output port is connected
295  2. The packet was requested (Override Checks).
296 
297  If the packet wasn't requested:
298  3. The Section and Group in Section is enabled OR the Group in Section is force enabled
299  4. The rate logic is not SILENCED.
300  5. The packet has data (marked updated in the past or new)
301  */
302  if (!this->isConnected_PktSend_OutputPort(this->sectionGroupToPort(section, entryGroup))) {
303  continue;
304  }
305 
306  if (pktEntryFlags.updateFlag == UpdateFlag::REQUESTED) {
307  sectionNeedsSend[section] = true;
308  } else {
309  if (not((entryGroupConfig.get_enabled() and
310  this->m_sectionEnabled[static_cast<FwSizeType>(section)] == Fw::Enabled::ENABLED) or
311  entryGroupConfig.get_forceEnabled() == Fw::Enabled::ENABLED)) {
312  continue;
313  }
314  if (entryGroupConfig.get_rateLogic() == Svc::RateLogic::SILENCED) {
315  continue;
316  }
317  if (pktEntryFlags.updateFlag == UpdateFlag::NEVER_UPDATED) {
318  continue; // Avoid No Data
319  }
320  }
321 
322  // Update Counter, prevent overflow.
323  if (pktEntryFlags.prevSentCounter < std::numeric_limits<U32>::max()) {
324  pktEntryFlags.prevSentCounter++;
325  }
326 
327  /*
328  1. Packet has been updated
329  2. Group Logic includes checking MIN
330  3. Packet sent counter at MIN
331  */
332  if (pktEntryFlags.updateFlag == UpdateFlag::NEW and
333  entryGroupConfig.get_rateLogic() != Svc::RateLogic::EVERY_MAX and
334  pktEntryFlags.prevSentCounter >= entryGroupConfig.get_min()) {
335  sectionNeedsSend[section] = true;
336  }
337 
338  /*
339  1. Group Logic includes checking MAX
340  2. Packet set counter is at MAX
341  */
342  if (entryGroupConfig.get_rateLogic() != Svc::RateLogic::ON_CHANGE_MIN and
343  pktEntryFlags.prevSentCounter >= entryGroupConfig.get_max()) {
344  sectionNeedsSend[section] = true;
345  }
346 
347  if (sectionNeedsSend[section]) {
348  anySectionNeedsSend = true;
349  }
350  }
351 
352  // Only perform the buffer copy if at least one section needs to send.
353  if (anySectionNeedsSend) {
354  this->m_lock.lock();
355  BufferEntry sendBuffer = this->m_fillBuffers[pkt];
356  this->m_lock.unLock();
357 
358  // serialize time into time offset in packet
360  &sendBuffer.buffer.getBuffAddr()[sizeof(FwPacketDescriptorType) + sizeof(FwTlmPacketizeIdType)],
362  (void)buff.serializeFrom(sendBuffer.latestTime);
363 
364  for (FwIndexType section = 0; section < TelemetrySection::NUM_SECTIONS; section++) {
365  if (sectionNeedsSend[section]) {
366  PktSendCounters& pktEntryFlags = this->m_packetFlags[section][pkt];
367  FwIndexType outIndex = this->sectionGroupToPort(section, entryGroup);
368 
369  this->PktSend_out(outIndex, sendBuffer.buffer, pktEntryFlags.prevSentCounter);
370 
371  pktEntryFlags.prevSentCounter = 0;
372  pktEntryFlags.updateFlag = UpdateFlag::PAST;
373  }
374  }
375  }
376  }
377 }
378 
379 void TlmPacketizer ::controlIn_handler(FwIndexType portNum,
380  const Svc::TelemetrySection& section,
381  const Fw::Enabled& enabled) {
382  FW_ASSERT(section.isValid());
383  FW_ASSERT(enabled.isValid());
384  if (0 <= section && section < TelemetrySection::NUM_SECTIONS) {
385  (void)(this->m_sectionEnabled[static_cast<FwSizeType>(section)] = enabled);
386  } else {
387  this->log_WARNING_LO_SectionUnconfigurable(section, enabled);
388  }
389 }
390 
391 void TlmPacketizer ::pingIn_handler(const FwIndexType portNum, U32 key) {
392  // return key
393  this->pingOut_out(0, key);
394 }
395 
396 // ----------------------------------------------------------------------
397 // Command handler implementations
398 // ----------------------------------------------------------------------
399 
400 void TlmPacketizer ::SET_LEVEL_cmdHandler(const FwOpcodeType opCode, const U32 cmdSeq, FwChanIdType level) {
403  }
404  for (FwIndexType section = 0; section < TelemetrySection::NUM_SECTIONS; section++) {
405  for (FwChanIdType group = 0; group < NUM_CONFIGURABLE_TLMPACKETIZER_GROUPS; group++) {
406  this->m_groupConfigs[static_cast<FwSizeType>(section)][group].set_enabled(
407  group <= level ? Fw::Enabled::ENABLED : Fw::Enabled::DISABLED);
408  }
409  }
410  this->tlmWrite_GroupConfigs(this->m_groupConfigs);
411  this->log_ACTIVITY_HI_LevelSet(level);
412  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
413 }
414 
415 void TlmPacketizer ::SEND_PKT_cmdHandler(const FwOpcodeType opCode,
416  const U32 cmdSeq,
417  const U32 id,
418  const Svc::TelemetrySection section) {
419  FW_ASSERT(section.isValid());
420  FwChanIdType pkt = 0;
421  for (pkt = 0; pkt < this->m_numPackets; pkt++) {
422  if (this->m_fillBuffers[pkt].id == id) {
423  this->m_lock.lock();
424  this->m_fillBuffers[pkt].updated = true;
425  this->m_fillBuffers[pkt].latestTime = this->getTime();
426  this->m_lock.unLock();
427 
428  this->m_packetFlags[section][pkt].updateFlag = UpdateFlag::REQUESTED;
429 
430  this->log_ACTIVITY_LO_PacketSent(id);
431  break;
432  }
433  }
434 
435  // couldn't find it
436  if (pkt == this->m_numPackets) {
438  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
439  return;
440  }
441 
442  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
443 }
444 
445 void TlmPacketizer ::ENABLE_SECTION_cmdHandler(FwOpcodeType opCode,
446  U32 cmdSeq,
447  Svc::TelemetrySection section,
448  Fw::Enabled enable) {
449  FW_ASSERT(section.isValid());
450  FW_ASSERT(enable.isValid());
451  if (section < 0 or section >= TelemetrySection::NUM_SECTIONS) {
452  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
453  return;
454  }
455  (void)(this->m_sectionEnabled[section] = enable);
456  this->tlmWrite_SectionEnabled(this->m_sectionEnabled);
457  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
458 }
459 
460 void TlmPacketizer ::ENABLE_GROUP_cmdHandler(FwOpcodeType opCode,
461  U32 cmdSeq,
462  Svc::TelemetrySection section,
463  FwChanIdType tlmGroup,
464  Fw::Enabled enable) {
465  FW_ASSERT(section.isValid());
466  FW_ASSERT(enable.isValid());
467  if ((0 <= section and section >= TelemetrySection::NUM_SECTIONS) or
469  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
470  return;
471  }
472  this->m_groupConfigs[section][tlmGroup].set_enabled(enable);
473  this->tlmWrite_GroupConfigs(this->m_groupConfigs);
474  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
475 }
476 
477 void TlmPacketizer ::FORCE_GROUP_cmdHandler(FwOpcodeType opCode,
478  U32 cmdSeq,
479  Svc::TelemetrySection section,
480  FwChanIdType tlmGroup,
481  Fw::Enabled enable) {
482  FW_ASSERT(section.isValid());
483  FW_ASSERT(enable.isValid());
484  if (section < 0 or section >= TelemetrySection::NUM_SECTIONS or tlmGroup > MAX_CONFIGURABLE_TLMPACKETIZER_GROUP) {
485  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
486  return;
487  }
488  this->m_groupConfigs[section][tlmGroup].set_forceEnabled(enable);
489  this->tlmWrite_GroupConfigs(this->m_groupConfigs);
490  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
491 }
492 
493 void TlmPacketizer ::CONFIGURE_GROUP_RATES_cmdHandler(FwOpcodeType opCode,
494  U32 cmdSeq,
495  Svc::TelemetrySection section,
496  FwChanIdType tlmGroup,
497  Svc::RateLogic rateLogic,
498  U32 minDelta,
499  U32 maxDelta) {
500  FW_ASSERT(section.isValid());
501  FW_ASSERT(rateLogic.isValid());
502  if (section < 0 or section >= TelemetrySection::NUM_SECTIONS or tlmGroup > MAX_CONFIGURABLE_TLMPACKETIZER_GROUP) {
503  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
504  return;
505  }
506  this->configureSectionGroupRate(section, tlmGroup, rateLogic, minDelta, maxDelta);
507  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
508 }
509 
510 void TlmPacketizer::configureSectionGroupRate(
511  const Svc::TelemetrySection& section,
512  FwChanIdType tlmGroup,
513  const Svc::RateLogic& rateLogic,
514  U32 minDelta,
515  U32 maxDelta
516 ) {
517  FW_ASSERT(section.isValid());
518  FW_ASSERT(rateLogic.isValid());
519  // These two asserts are an "if" statement in a command so they will no assert on bad user data
520  FW_ASSERT(section >= 0 and section < TelemetrySection::NUM_SECTIONS);
522 
523  TlmPacketizer_GroupConfig& groupConfig = this->m_groupConfigs[section][tlmGroup];
524  groupConfig.set_rateLogic(rateLogic);
525  groupConfig.set_min(minDelta);
526  groupConfig.set_max(maxDelta);
527  this->tlmWrite_GroupConfigs(this->m_groupConfigs);
528 }
529 
530 FwIndexType TlmPacketizer::sectionGroupToPort(const FwIndexType section, const FwSizeType group) {
531  // Confirm the indices will not overflow the size of the array
532  FW_ASSERT(group < TlmPacketizer_TelemetrySendSection::SIZE, static_cast<FwAssertArgType>(group));
533  FW_ASSERT(section < TlmPacketizer_TelemetrySendPortMap::SIZE, static_cast<FwAssertArgType>(section));
534 
535  const FwIndexType outIndex = TlmPacketizer::TELEMETRY_SEND_PORT_MAP[static_cast<FwSizeType>(section)][group];
536 
537  // Confirm the output port index is within the valid number of telemetry send ports
538  FW_ASSERT(outIndex < TELEMETRY_SEND_PORTS, static_cast<FwAssertArgType>(outIndex));
539  return outIndex;
540 }
541 
542 void TlmPacketizer::missingChannel(FwChanIdType id) {
543  // search to see if missing channel has already been sent
544  for (FwChanIdType slot = 0; slot < TLMPACKETIZER_MAX_MISSING_TLM_CHECK; slot++) {
545  // if it's been checked, return
546  if (this->m_missTlmCheck[slot].checked and (this->m_missTlmCheck[slot].id == id)) {
547  return;
548  } else if (not this->m_missTlmCheck[slot].checked) {
549  this->m_missTlmCheck[slot].checked = true;
550  this->m_missTlmCheck[slot].id = id;
551  this->log_WARNING_LO_NoChan(id);
552  return;
553  }
554  }
555 }
556 
557 Fw::SerializeStatus TlmPacketizer::deserializeParam(const FwPrmIdType base_id,
558  const FwPrmIdType local_id,
559  const Fw::ParamValid prmStat,
560  Fw::SerialBufferBase& buff) {
561  // Autocoder always calls deserializeParam with VALID
562  FW_ASSERT(prmStat == Fw::ParamValid::VALID);
563  switch (local_id) {
565  return buff.deserializeTo(this->m_sectionEnabled);
567  return buff.deserializeTo(this->m_groupConfigs);
568  default:
569  FW_ASSERT(0, static_cast<FwAssertArgType>(local_id));
570  }
572 }
573 
574 Fw::SerializeStatus TlmPacketizer::serializeParam(const FwPrmIdType base_id,
575  const FwPrmIdType local_id,
576  Fw::SerialBufferBase& buff) const {
577  switch (local_id) {
579  return buff.serializeFrom(this->m_sectionEnabled);
581  return buff.serializeFrom(this->m_groupConfigs);
582  default:
583  FW_ASSERT(0, static_cast<FwAssertArgType>(local_id));
584  }
586 }
587 
588 } // end namespace Svc
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.
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 PktSend_out(FwIndexType portNum, Fw::ComBuffer &data, U32 context)
Invoke output port PktSend.
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
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 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
void log_ACTIVITY_HI_LevelSet(FwChanIdType id) const
Command failed validation.
RateGroupDivider component implementation.
Enum representing parameter validity.
bool isConnected_PktSend_OutputPort(FwIndexType portNum)
SerializeStatus setBuffLen(Serializable::SizeType length) override
Set buffer length manually.
FwChanIdType numEntries
number of channels in packet
Success insert(const K &key, const V &value) override
#define FW_ASSERT(...)
Definition: Assert.hpp:14
Disabled state.
Success/Failure.
void pingOut_out(FwIndexType portNum, U32 key)
Invoke output port pingOut.
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.