F´ Flight Software - C/C++ Documentation  devel
A framework for building embedded system applications to NASA flight quality standards.
TlmChan.cpp
Go to the documentation of this file.
1 
12 #include <FpConfig.hpp>
13 #include <Fw/Com/ComBuffer.hpp>
14 #include <Fw/Types/Assert.hpp>
15 #include <Svc/TlmChan/TlmChan.hpp>
16 
17 namespace Svc {
18 
19 TlmChan::TlmChan(const char* name) : TlmChanComponentBase(name), m_activeBuffer(0) {
20  // clear slot pointers
21  for (NATIVE_UINT_TYPE entry = 0; entry < TLMCHAN_NUM_TLM_HASH_SLOTS; entry++) {
22  this->m_tlmEntries[0].slots[entry] = nullptr;
23  this->m_tlmEntries[1].slots[entry] = nullptr;
24  }
25  // clear buckets
26  for (NATIVE_UINT_TYPE entry = 0; entry < TLMCHAN_HASH_BUCKETS; entry++) {
27  this->m_tlmEntries[0].buckets[entry].used = false;
28  this->m_tlmEntries[0].buckets[entry].updated = false;
29  this->m_tlmEntries[0].buckets[entry].bucketNo = entry;
30  this->m_tlmEntries[0].buckets[entry].next = nullptr;
31  this->m_tlmEntries[0].buckets[entry].id = 0;
32  this->m_tlmEntries[1].buckets[entry].used = false;
33  this->m_tlmEntries[1].buckets[entry].updated = false;
34  this->m_tlmEntries[1].buckets[entry].bucketNo = entry;
35  this->m_tlmEntries[1].buckets[entry].next = nullptr;
36  this->m_tlmEntries[1].buckets[entry].id = 0;
37  }
38  // clear free index
39  this->m_tlmEntries[0].free = 0;
40  this->m_tlmEntries[1].free = 0;
41 }
42 
44 
45 void TlmChan::init(NATIVE_INT_TYPE queueDepth,
46  NATIVE_INT_TYPE instance
47 ) {
48  TlmChanComponentBase::init(queueDepth, instance);
49 }
50 
52  return (id % TLMCHAN_HASH_MOD_VALUE) % TLMCHAN_NUM_TLM_HASH_SLOTS;
53 }
54 
55 void TlmChan::pingIn_handler(const NATIVE_INT_TYPE portNum, U32 key) {
56  // return key
57  this->pingOut_out(0, key);
58 }
59 
60 void TlmChan::TlmGet_handler(NATIVE_INT_TYPE portNum, FwChanIdType id, Fw::Time& timeTag, Fw::TlmBuffer& val) {
61  // Compute index for entry
62 
63  NATIVE_UINT_TYPE index = this->doHash(id);
64 
65  // Search to see if channel has been stored
66  TlmEntry* entryToUse = this->m_tlmEntries[this->m_activeBuffer].slots[index];
67  for (NATIVE_UINT_TYPE bucket = 0; bucket < TLMCHAN_HASH_BUCKETS; bucket++) {
68  if (entryToUse) { // If bucket exists, check id
69  if (entryToUse->id == id) {
70  break;
71  } else { // otherwise go to next bucket
72  entryToUse = entryToUse->next;
73  }
74  } else { // no buckets left to search
75  break;
76  }
77  }
78 
79  if (entryToUse) {
80  val = entryToUse->buffer;
81  timeTag = entryToUse->lastUpdate;
82  } else { // requested entry may not be written yet; empty buffer
83  val.resetSer();
84  }
85 }
86 
87 void TlmChan::TlmRecv_handler(NATIVE_INT_TYPE portNum, FwChanIdType id, Fw::Time& timeTag, Fw::TlmBuffer& val) {
88  // Compute index for entry
89 
90  NATIVE_UINT_TYPE index = this->doHash(id);
91  TlmEntry* entryToUse = nullptr;
92  TlmEntry* prevEntry = nullptr;
93 
94  // Search to see if channel has already been stored or a bucket needs to be added
95  if (this->m_tlmEntries[this->m_activeBuffer].slots[index]) {
96  entryToUse = this->m_tlmEntries[this->m_activeBuffer].slots[index];
97  for (NATIVE_UINT_TYPE bucket = 0; bucket < TLMCHAN_HASH_BUCKETS; bucket++) {
98  if (entryToUse) {
99  if (entryToUse->id == id) { // found the matching entry
100  break;
101  } else { // try next entry
102  prevEntry = entryToUse;
103  entryToUse = entryToUse->next;
104  }
105  } else {
106  // Make sure that we haven't run out of buckets
107  FW_ASSERT(this->m_tlmEntries[this->m_activeBuffer].free < TLMCHAN_HASH_BUCKETS);
108  // add new bucket from free list
109  entryToUse =
110  &this->m_tlmEntries[this->m_activeBuffer].buckets[this->m_tlmEntries[this->m_activeBuffer].free++];
111  FW_ASSERT(prevEntry);
112  prevEntry->next = entryToUse;
113  // clear next pointer
114  entryToUse->next = nullptr;
115  break;
116  }
117  }
118  } else {
119  // Make sure that we haven't run out of buckets
120  FW_ASSERT(this->m_tlmEntries[this->m_activeBuffer].free < TLMCHAN_HASH_BUCKETS);
121  // create new entry at slot head
122  this->m_tlmEntries[this->m_activeBuffer].slots[index] =
123  &this->m_tlmEntries[this->m_activeBuffer].buckets[this->m_tlmEntries[this->m_activeBuffer].free++];
124  entryToUse = this->m_tlmEntries[this->m_activeBuffer].slots[index];
125  entryToUse->next = nullptr;
126  }
127 
128  // copy into entry
129  FW_ASSERT(entryToUse);
130  entryToUse->used = true;
131  entryToUse->id = id;
132  entryToUse->updated = true;
133  entryToUse->lastUpdate = timeTag;
134  entryToUse->buffer = val;
135 }
136 
137 void TlmChan::Run_handler(NATIVE_INT_TYPE portNum, NATIVE_UINT_TYPE context) {
138  // Only write packets if connected
139  if (not this->isConnected_PktSend_OutputPort(0)) {
140  return;
141  }
142 
143  // lock mutex long enough to modify active telemetry buffer
144  // so the data can be read without worrying about updates
145  this->lock();
146  this->m_activeBuffer = 1 - this->m_activeBuffer;
147  // set activeBuffer to not updated
148  for (U32 entry = 0; entry < TLMCHAN_HASH_BUCKETS; entry++) {
149  this->m_tlmEntries[this->m_activeBuffer].buckets[entry].updated = false;
150  }
151  this->unLock();
152 
153  // go through each entry and send a packet if it has been updated
154  Fw::TlmPacket pkt;
155  pkt.resetPktSer();
156 
157  for (U32 entry = 0; entry < TLMCHAN_HASH_BUCKETS; entry++) {
158  TlmEntry* p_entry = &this->m_tlmEntries[1 - this->m_activeBuffer].buckets[entry];
159  if ((p_entry->updated) && (p_entry->used)) {
160  Fw::SerializeStatus stat = pkt.addValue(p_entry->id, p_entry->lastUpdate, p_entry->buffer);
161 
162  // check to see if this packet is full, if so, send it
163  if (Fw::FW_SERIALIZE_NO_ROOM_LEFT == stat) {
164  this->PktSend_out(0, pkt.getBuffer(), 0);
165  // reset packet for more entries
166  pkt.resetPktSer();
167  // add entry to new packet
168  stat = pkt.addValue(p_entry->id, p_entry->lastUpdate, p_entry->buffer);
169  // if this doesn't work, that means packet isn't big enough for
170  // even one channel, so assert
171  FW_ASSERT(Fw::FW_SERIALIZE_OK == stat, static_cast<NATIVE_INT_TYPE>(stat));
172  } else if (Fw::FW_SERIALIZE_OK == stat) {
173  // if there was still room, do nothing move on to the next channel in the packet
174  } else // any other status is an assert, since it shouldn't happen
175  {
176  FW_ASSERT(0, static_cast<NATIVE_INT_TYPE>(stat));
177  }
178  // flag as updated
179  p_entry->updated = false;
180  } // end if entry was updated
181  } // end for each entry
182 
183  // send remnant entries
184  if (pkt.getNumEntries() > 0) {
185  this->PktSend_out(0, pkt.getBuffer(), 0);
186  }
187 } // end run handler
188 
189 } // namespace Svc
#define FW_ASSERT(...)
Definition: Assert.hpp:14
PlatformIntType NATIVE_INT_TYPE
Definition: BasicTypes.h:51
PlatformUIntType NATIVE_UINT_TYPE
Definition: BasicTypes.h:52
U32 FwChanIdType
Definition: FpConfig.h:59
C++-compatible configuration header for fprime configuration.
Component that stores telemetry channel values.
void init()
Object initializer.
Definition: ObjBase.cpp:27
void resetSer()
reset to beginning of buffer to reuse for serialization
Definition: Time.hpp:9
NATIVE_UINT_TYPE getNumEntries()
get the number of packets added via addValue()
Definition: TlmPacket.cpp:52
SerializeStatus resetPktSer()
Reset serialization of values. This should be done when starting to accumulate a new set of values.
Definition: TlmPacket.cpp:21
Fw::ComBuffer & getBuffer()
get buffer to send to the ground
Definition: TlmPacket.cpp:56
SerializeStatus addValue(FwChanIdType id, Time &timeTag, TlmBuffer &buffer)
Add telemetry value to buffer.
Definition: TlmPacket.cpp:64
Auto-generated base for TlmChan component.
bool isConnected_PktSend_OutputPort(NATIVE_INT_TYPE portNum)
virtual void unLock()
Unlock the guarded mutex.
void pingOut_out(NATIVE_INT_TYPE portNum, U32 key)
Invoke output port pingOut.
void PktSend_out(NATIVE_INT_TYPE portNum, Fw::ComBuffer &data, U32 context)
Invoke output port PktSend.
virtual void lock()
Lock the guarded mutex.
virtual NATIVE_UINT_TYPE doHash(FwChanIdType id)
Definition: TlmChan.cpp:51
virtual ~TlmChan()
Definition: TlmChan.cpp:43
TlmChan(const char *compName)
Definition: TlmChan.cpp:19
SerializeStatus
forward declaration for string
@ FW_SERIALIZE_OK
Serialization/Deserialization operation was successful.
@ FW_SERIALIZE_NO_ROOM_LEFT
No room left in the buffer to serialize data.