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  if (section < 0 or section >= TelemetrySection::NUM_SECTIONS) {
421  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
422  return;
423  }
424  FwChanIdType pkt = 0;
425  for (pkt = 0; pkt < this->m_numPackets; pkt++) {
426  if (this->m_fillBuffers[pkt].id == id) {
427  this->m_lock.lock();
428  this->m_fillBuffers[pkt].updated = true;
429  this->m_fillBuffers[pkt].latestTime = this->getTime();
430  this->m_lock.unLock();
431 
432  this->m_packetFlags[section][pkt].updateFlag = UpdateFlag::REQUESTED;
433 
434  this->log_ACTIVITY_LO_PacketSent(id);
435  break;
436  }
437  }
438 
439  // couldn't find it
440  if (pkt == this->m_numPackets) {
442  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
443  return;
444  }
445 
446  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
447 }
448 
449 void TlmPacketizer ::ENABLE_SECTION_cmdHandler(FwOpcodeType opCode,
450  U32 cmdSeq,
451  Svc::TelemetrySection section,
452  Fw::Enabled enable) {
453  FW_ASSERT(section.isValid());
454  FW_ASSERT(enable.isValid());
455  if (section < 0 or section >= TelemetrySection::NUM_SECTIONS) {
456  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
457  return;
458  }
459  (void)(this->m_sectionEnabled[section] = enable);
460  this->tlmWrite_SectionEnabled(this->m_sectionEnabled);
461  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
462 }
463 
464 void TlmPacketizer ::ENABLE_GROUP_cmdHandler(FwOpcodeType opCode,
465  U32 cmdSeq,
466  Svc::TelemetrySection section,
467  FwChanIdType tlmGroup,
468  Fw::Enabled enable) {
469  FW_ASSERT(section.isValid());
470  FW_ASSERT(enable.isValid());
471  if (section < 0 or section >= TelemetrySection::NUM_SECTIONS or tlmGroup > MAX_CONFIGURABLE_TLMPACKETIZER_GROUP) {
472  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
473  return;
474  }
475  this->m_groupConfigs[section][tlmGroup].set_enabled(enable);
476  this->tlmWrite_GroupConfigs(this->m_groupConfigs);
477  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
478 }
479 
480 void TlmPacketizer ::FORCE_GROUP_cmdHandler(FwOpcodeType opCode,
481  U32 cmdSeq,
482  Svc::TelemetrySection section,
483  FwChanIdType tlmGroup,
484  Fw::Enabled enable) {
485  FW_ASSERT(section.isValid());
486  FW_ASSERT(enable.isValid());
487  if (section < 0 or section >= TelemetrySection::NUM_SECTIONS or tlmGroup > MAX_CONFIGURABLE_TLMPACKETIZER_GROUP) {
488  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
489  return;
490  }
491  this->m_groupConfigs[section][tlmGroup].set_forceEnabled(enable);
492  this->tlmWrite_GroupConfigs(this->m_groupConfigs);
493  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
494 }
495 
496 void TlmPacketizer ::CONFIGURE_GROUP_RATES_cmdHandler(FwOpcodeType opCode,
497  U32 cmdSeq,
498  Svc::TelemetrySection section,
499  FwChanIdType tlmGroup,
500  Svc::RateLogic rateLogic,
501  U32 minDelta,
502  U32 maxDelta) {
503  FW_ASSERT(section.isValid());
504  FW_ASSERT(rateLogic.isValid());
505  if (section < 0 or section >= TelemetrySection::NUM_SECTIONS or tlmGroup > MAX_CONFIGURABLE_TLMPACKETIZER_GROUP) {
506  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
507  return;
508  }
509  this->configureSectionGroupRate(section, tlmGroup, rateLogic, minDelta, maxDelta);
510  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
511 }
512 
513 void TlmPacketizer::configureSectionGroupRate(
514  const Svc::TelemetrySection& section,
515  FwChanIdType tlmGroup,
516  const Svc::RateLogic& rateLogic,
517  U32 minDelta,
518  U32 maxDelta
519 ) {
520  FW_ASSERT(section.isValid());
521  FW_ASSERT(rateLogic.isValid());
522  // These two asserts are an "if" statement in a command so they will no assert on bad user data
523  FW_ASSERT(section >= 0 and section < TelemetrySection::NUM_SECTIONS);
525 
526  TlmPacketizer_GroupConfig& groupConfig = this->m_groupConfigs[section][tlmGroup];
527  groupConfig.set_rateLogic(rateLogic);
528  groupConfig.set_min(minDelta);
529  groupConfig.set_max(maxDelta);
530  this->tlmWrite_GroupConfigs(this->m_groupConfigs);
531 }
532 
533 FwIndexType TlmPacketizer::sectionGroupToPort(const FwIndexType section, const FwSizeType group) {
534  // Confirm the indices will not overflow the size of the array
535  FW_ASSERT(group < TlmPacketizer_TelemetrySendSection::SIZE, static_cast<FwAssertArgType>(group));
536  FW_ASSERT(section < TlmPacketizer_TelemetrySendPortMap::SIZE, static_cast<FwAssertArgType>(section));
537 
538  const FwIndexType outIndex = TlmPacketizer::TELEMETRY_SEND_PORT_MAP[static_cast<FwSizeType>(section)][group];
539 
540  // Confirm the output port index is within the valid number of telemetry send ports
541  FW_ASSERT(outIndex < TELEMETRY_SEND_PORTS, static_cast<FwAssertArgType>(outIndex));
542  return outIndex;
543 }
544 
545 void TlmPacketizer::missingChannel(FwChanIdType id) {
546  // search to see if missing channel has already been sent
547  for (FwChanIdType slot = 0; slot < TLMPACKETIZER_MAX_MISSING_TLM_CHECK; slot++) {
548  // if it's been checked, return
549  if (this->m_missTlmCheck[slot].checked and (this->m_missTlmCheck[slot].id == id)) {
550  return;
551  } else if (not this->m_missTlmCheck[slot].checked) {
552  this->m_missTlmCheck[slot].checked = true;
553  this->m_missTlmCheck[slot].id = id;
554  this->log_WARNING_LO_NoChan(id);
555  return;
556  }
557  }
558 }
559 
560 Fw::SerializeStatus TlmPacketizer::deserializeParam(const FwPrmIdType base_id,
561  const FwPrmIdType local_id,
562  const Fw::ParamValid prmStat,
563  Fw::SerialBufferBase& buff) {
564  // Autocoder always calls deserializeParam with VALID
565  FW_ASSERT(prmStat == Fw::ParamValid::VALID);
566  switch (local_id) {
568  return buff.deserializeTo(this->m_sectionEnabled);
570  return buff.deserializeTo(this->m_groupConfigs);
571  default:
572  FW_ASSERT(0, static_cast<FwAssertArgType>(local_id));
573  }
575 }
576 
577 Fw::SerializeStatus TlmPacketizer::serializeParam(const FwPrmIdType base_id,
578  const FwPrmIdType local_id,
579  Fw::SerialBufferBase& buff) const {
580  switch (local_id) {
582  return buff.serializeFrom(this->m_sectionEnabled);
584  return buff.serializeFrom(this->m_groupConfigs);
585  default:
586  FW_ASSERT(0, static_cast<FwAssertArgType>(local_id));
587  }
589 }
590 
591 } // 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.
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
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
void log_ACTIVITY_HI_LevelSet(FwChanIdType id) const
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.