F´ Flight Software - C/C++ Documentation  devel
A framework for building embedded system applications to NASA flight quality standards.
GroundInterface.cpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title GroundInterface.cpp
3 // \author lestarch
4 // \brief cpp file for GroundInterface component implementation class
5 // ======================================================================
6 
7 #include <Fw/Com/ComPacket.hpp>
9 #include <FpConfig.hpp>
10 #include <cstring>
11 
12 namespace Svc {
13 
15  const TOKEN_TYPE GroundInterfaceComponentImpl::START_WORD = static_cast<TOKEN_TYPE>(0xdeadbeef);
16  const U32 GroundInterfaceComponentImpl::END_WORD = static_cast<U32>(0xcafecafe);
17 
18  // ----------------------------------------------------------------------
19  // Construction, initialization, and destruction
20  // ----------------------------------------------------------------------
21 
24  const char *const compName
25  ) : GroundInterfaceComponentBase(compName),
26  m_ext_buffer(m_buffer, GND_BUFFER_SIZE),
27  m_data_size(0),
28  m_in_ring(m_in_buffer, GND_BUFFER_SIZE)
29  {
30 
31  }
32 
34  init(
35  const NATIVE_INT_TYPE instance
36  )
37  {
39  }
40 
43  {
44 
45  }
46 
47  // ----------------------------------------------------------------------
48  // Handler implementations for user-defined typed input ports
49  // ----------------------------------------------------------------------
50 
51  void GroundInterfaceComponentImpl ::
52  downlinkPort_handler(
53  const NATIVE_INT_TYPE portNum,
54  Fw::ComBuffer &data,
55  U32 context
56  )
57  {
59  frame_send(data.getBuffAddr(), data.getBuffLength());
60  }
61 
62  void GroundInterfaceComponentImpl ::
63  fileDownlinkBufferSendIn_handler(
64  const NATIVE_INT_TYPE portNum,
65  Fw::Buffer &fwBuffer
66  )
67  {
68  FW_ASSERT(fwBuffer.getSize() <= MAX_DATA_SIZE);
69  frame_send(fwBuffer.getData(), fwBuffer.getSize(), Fw::ComPacket::FW_PACKET_FILE);
70  fileDownlinkBufferSendOut_out(0, fwBuffer);
71  }
72 
73  void GroundInterfaceComponentImpl ::
74  readCallback_handler(
75  const NATIVE_INT_TYPE portNum,
76  Fw::Buffer &buffer
77  )
78  {
79  processBuffer(buffer);
80  }
81 
82  void GroundInterfaceComponentImpl ::
83  schedIn_handler(
84  const NATIVE_INT_TYPE portNum,
85  NATIVE_UINT_TYPE context
86  )
87  {
88  // TODO: replace with a call to a buffer manager
89  Fw::Buffer buffer = m_ext_buffer;
90  // Call read poll if it is hooked up
92  readPoll_out(0, buffer);
93  processBuffer(buffer);
94  }
95  }
96 
97  void GroundInterfaceComponentImpl::frame_send(U8 *data, TOKEN_TYPE size, TOKEN_TYPE packet_type) {
98  // TODO: replace with a call to a buffer manager
99  Fw::Buffer buffer = m_ext_buffer;
100  Fw::SerializeBufferBase& buffer_wrapper = buffer.getSerializeRepr();
101  buffer_wrapper.resetSer();
102  // True size is supplied size plus sizeof(TOKEN_TYPE) if a packet_type other than "UNKNOWN" was supplied.
103  // This is because if not UNKNOWN, the packet_type is serialized too. Otherwise it is assumed the PACKET_TYPE is
104  // already the first token in the UNKNOWN typed buffer.
105  U32 true_size = (packet_type != Fw::ComPacket::FW_PACKET_UNKNOWN) ? size + sizeof(TOKEN_TYPE) : size;
106  U32 total_size = sizeof(TOKEN_TYPE) + sizeof(TOKEN_TYPE) + true_size + sizeof(U32);
107  // Serialize data
108  FW_ASSERT(GND_BUFFER_SIZE >= total_size, GND_BUFFER_SIZE, total_size);
109  buffer_wrapper.serialize(START_WORD);
110  buffer_wrapper.serialize(static_cast<TOKEN_TYPE>(true_size));
111  // Explicitly set the packet type, if it didn't come with the data already
112  if (packet_type != Fw::ComPacket::FW_PACKET_UNKNOWN) {
113  buffer_wrapper.serialize(packet_type);
114  }
115  buffer_wrapper.serialize(data, size, true);
116  buffer_wrapper.serialize(static_cast<TOKEN_TYPE>(END_WORD));
117 
118  // Setup for sending by truncating unused data
119  buffer.setSize(buffer_wrapper.getBuffLength());
120  FW_ASSERT(buffer.getSize() == total_size, buffer.getSize(), total_size);
121  write_out(0, buffer);
122  }
123 
124  void GroundInterfaceComponentImpl ::
125  routeComData()
126  {
127  // Read the packet type from the data buffer
129 
130  //read packet descriptor in size agnostic way
131  U8 packet_descriptor_size = sizeof(FwPacketDescriptorType);
132  U8 packet_type_bytes[sizeof(FwPacketDescriptorType)];
133  Fw::SerializeStatus stat = m_in_ring.peek(packet_type_bytes, packet_descriptor_size, HEADER_SIZE);
134  //m_in_ring.peek(packet_type, HEADER_SIZE); // this way is only valid for 4byte packet descriptors
135  if(stat == Fw::FW_SERIALIZE_OK)
136  {
137  // unpack Big Endian encoded bytes
138  packet_type = 0;
139  for(int i = 0; i < packet_descriptor_size; i++)
140  {
141  packet_type <<= 8;
142  packet_type |= packet_type_bytes[i];
143  }
144  }
145 
146  // Process variable type
147  switch (packet_type) {
149  Fw::ComBuffer com;
150  m_in_ring.peek(com.getBuffAddr(), m_data_size, HEADER_SIZE);
151  // Reset com buffer for sending out data
152  com.setBuffLen(m_data_size);
153  uplinkPort_out(0, com, 0);
154  break;
155  }
157  // If file uplink is possible, handle files. Otherwise ignore.
160  Fw::Buffer buffer = fileUplinkBufferGet_out(0, m_data_size);
161  m_in_ring.peek(buffer.getData(), m_data_size - sizeof(packet_type), HEADER_SIZE + sizeof(packet_type));
162  buffer.setSize(m_data_size - sizeof(packet_type));
163  fileUplinkBufferSendOut_out(0, buffer);
164  }
165  break;
166  }
167  default:
168  return;
169  }
170  }
171 
172  void GroundInterfaceComponentImpl ::
173  processRing()
174  {
175  // Header items for the packet
176  TOKEN_TYPE start;
177  U32 checksum; //TODO: make this run a CRC32
178  // Inner-loop, process ring buffer looking for at least the header
179  while (m_in_ring.get_allocated_size() >= HEADER_SIZE) {
180  m_data_size = 0;
181  // Peek into the header and read out values
182  Fw::SerializeStatus status = m_in_ring.peek(start, 0);
183  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
184  status = m_in_ring.peek(m_data_size, sizeof(TOKEN_TYPE));
185  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
186  // Check the header for correctness
187  if (start != START_WORD || m_data_size >= MAX_DATA_SIZE) {
188  m_in_ring.rotate(1);
189  continue;
190  }
191  // Check for enough data to deserialize everything otherwise break and wait for more.
192  else if (m_in_ring.get_allocated_size() < (HEADER_SIZE + m_data_size + sizeof(END_WORD))) {
193  break;
194  }
195  // Continue with the data portion and checksum
196  m_in_ring.peek(checksum, HEADER_SIZE + m_data_size);
197  // Check checksum
198  if (checksum == END_WORD) {
199  routeComData();
200  m_in_ring.rotate(HEADER_SIZE + m_data_size + sizeof(U32));
201  }
202  // Failed checksum, keep looking for valid message
203  else {
204  m_in_ring.rotate(1);
205  }
206  }
207  }
208 
209  void GroundInterfaceComponentImpl ::
210  processBuffer(Fw::Buffer& buffer)
211  {
212  NATIVE_UINT_TYPE buffer_offset = 0;
213  while (buffer_offset < buffer.getSize()) {
214  NATIVE_UINT_TYPE ser_size = (buffer.getSize() >= m_in_ring.get_free_size()) ?
215  m_in_ring.get_free_size() : static_cast<NATIVE_UINT_TYPE>(buffer.getSize());
216  m_in_ring.serialize(buffer.getData() + buffer_offset, ser_size);
217  buffer_offset = buffer_offset + ser_size;
218  processRing();
219  }
220  }
221 } // end namespace Svc
#define FW_ASSERT(...)
Definition: Assert.hpp:14
PlatformIntType NATIVE_INT_TYPE
Definition: BasicTypes.h:51
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:26
PlatformUIntType NATIVE_UINT_TYPE
Definition: BasicTypes.h:52
U32 FwPacketDescriptorType
Definition: FpConfig.h:53
C++-compatible configuration header for fprime configuration.
#define HEADER_SIZE
#define TOKEN_TYPE
#define GND_BUFFER_SIZE
U8 * getData() const
Definition: Buffer.cpp:68
U32 getSize() const
Definition: Buffer.cpp:72
void setSize(U32 size)
Definition: Buffer.cpp:87
SerializeBufferBase & getSerializeRepr()
Definition: Buffer.cpp:107
U8 * getBuffAddr()
gets buffer address for data filling
Definition: ComBuffer.cpp:40
void init()
Object initializer.
Definition: ObjBase.cpp:27
SerializeStatus setBuffLen(NATIVE_UINT_TYPE length)
sets buffer length manually after filling with data
void resetSer()
reset to beginning of buffer to reuse for serialization
SerializeStatus serialize(U8 val)
serialize 8-bit unsigned int
NATIVE_UINT_TYPE getBuffLength() const
returns current buffer size
Auto-generated base for GroundInterface component.
bool isConnected_fileDownlinkBufferSendOut_OutputPort(NATIVE_INT_TYPE portNum)
void fileDownlinkBufferSendOut_out(NATIVE_INT_TYPE portNum, Fw::Buffer &fwBuffer)
Invoke output port fileDownlinkBufferSendOut.
void write_out(NATIVE_INT_TYPE portNum, Fw::Buffer &fwBuffer)
Invoke output port write.
Fw::Buffer fileUplinkBufferGet_out(NATIVE_INT_TYPE portNum, U32 size)
Invoke output port fileUplinkBufferGet.
void readPoll_out(NATIVE_INT_TYPE portNum, Fw::Buffer &fwBuffer)
Invoke output port readPoll.
void fileUplinkBufferSendOut_out(NATIVE_INT_TYPE portNum, Fw::Buffer &fwBuffer)
Invoke output port fileUplinkBufferSendOut.
bool isConnected_readPoll_OutputPort(NATIVE_INT_TYPE portNum)
bool isConnected_fileUplinkBufferGet_OutputPort(NATIVE_INT_TYPE portNum)
void uplinkPort_out(NATIVE_INT_TYPE portNum, Fw::ComBuffer &data, U32 context)
Invoke output port uplinkPort.
GroundInterfaceComponentImpl(const char *const compName)
static const TOKEN_TYPE START_WORD
Fw::SerializeStatus serialize(const U8 *const buffer, const NATIVE_UINT_TYPE size)
NATIVE_UINT_TYPE get_free_size() const
NATIVE_UINT_TYPE get_allocated_size() const
Fw::SerializeStatus peek(char &value, NATIVE_UINT_TYPE offset=0) const
Fw::SerializeStatus rotate(NATIVE_UINT_TYPE amount)
SerializeStatus
forward declaration for string
@ FW_SERIALIZE_OK
Serialization/Deserialization operation was successful.