Skip to content

Commit fb1edfb

Browse files
committed
builds (?)
1 parent d671a93 commit fb1edfb

File tree

10 files changed

+967
-6
lines changed

10 files changed

+967
-6
lines changed

FprimeZephyrReference/Components/PayloadHandler/PayloadHandler.cpp

Lines changed: 298 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,29 @@
44
// \brief cpp file for PayloadHandler component implementation class
55
// ======================================================================
66
#include "Os/File.hpp"
7+
#include "Fw/Types/Assert.hpp"
8+
#include "Fw/Types/BasicTypes.hpp"
79
#include "FprimeZephyrReference/Components/PayloadHandler/PayloadHandler.hpp"
10+
#include <cstring>
811

912
namespace Components {
1013

1114
// ----------------------------------------------------------------------
1215
// Component construction and destruction
1316
// ----------------------------------------------------------------------
1417

15-
PayloadHandler ::PayloadHandler(const char* const compName) : PayloadHandlerComponentBase(compName) {}
16-
PayloadHandler ::~PayloadHandler() {}
18+
PayloadHandler ::PayloadHandler(const char* const compName)
19+
: PayloadHandlerComponentBase(compName),
20+
m_protocolBufferSize(0),
21+
m_imageBufferUsed(0) {
22+
// Initialize protocol buffer to zero
23+
memset(m_protocolBuffer, 0, PROTOCOL_BUFFER_SIZE);
24+
}
25+
26+
PayloadHandler ::~PayloadHandler() {
27+
// Clean up any allocated image buffer
28+
deallocateImageBuffer();
29+
}
1730

1831

1932
// ----------------------------------------------------------------------
@@ -25,7 +38,63 @@ void PayloadHandler ::in_port_handler(FwIndexType portNum, Fw::Buffer& buffer, c
2538

2639
this->log_ACTIVITY_LO_UartReceived();
2740

28-
41+
// Check if we received data successfully
42+
if (status != Drv::ByteStreamStatus::OP_OK) {
43+
// TODO - log error event?
44+
return;
45+
}
46+
47+
// Check if buffer is valid
48+
if (!buffer.isValid()) {
49+
return;
50+
}
51+
52+
// Get the data from the incoming buffer
53+
const U8* data = buffer.getData();
54+
const U32 dataSize = static_cast<U32>(buffer.getSize());
55+
56+
// Unclear if this works as intended if data flow is interrupted
57+
58+
if (m_receiving && m_imageBuffer.isValid()) {
59+
// Currently receiving image data - accumulate into large buffer
60+
// Check for end marker before accumulating
61+
I32 endMarkerPos = findImageEndMarker(data, dataSize);
62+
63+
if (endMarkerPos >= 0) {
64+
// Found end marker - accumulate data up to marker
65+
U32 finalDataSize = static_cast<U32>(endMarkerPos);
66+
if (finalDataSize > 0) {
67+
if (!accumulateImageData(data, finalDataSize)) {
68+
// Overflow
69+
this->log_WARNING_HI_ImageDataOverflow();
70+
deallocateImageBuffer();
71+
m_receiving = false;
72+
return;
73+
}
74+
}
75+
76+
// Image is complete
77+
processCompleteImage();
78+
} else {
79+
// No end marker yet - accumulate all data
80+
if (!accumulateImageData(data, dataSize)) {
81+
// Image buffer overflow
82+
this->log_WARNING_HI_ImageDataOverflow();
83+
deallocateImageBuffer();
84+
m_receiving = false;
85+
}
86+
}
87+
} else {
88+
// Not receiving image - accumulate protocol data
89+
if (!accumulateProtocolData(data, dataSize)) {
90+
// Protocol buffer overflow - clear and retry
91+
clearProtocolBuffer();
92+
accumulateProtocolData(data, dataSize);
93+
}
94+
95+
// Process protocol buffer to detect image headers/commands
96+
processProtocolBuffer();
97+
}
2998
}
3099

31100
// ----------------------------------------------------------------------
@@ -60,4 +129,230 @@ void PayloadHandler ::SEND_COMMAND_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, c
60129
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
61130
}
62131

132+
// ----------------------------------------------------------------------
133+
// Helper method implementations
134+
// ----------------------------------------------------------------------
135+
136+
bool PayloadHandler ::accumulateProtocolData(const U8* data, U32 size) {
137+
// Check if we have space for the new data
138+
if (m_protocolBufferSize + size > PROTOCOL_BUFFER_SIZE) {
139+
return false;
140+
}
141+
142+
// Copy data into protocol buffer
143+
memcpy(&m_protocolBuffer[m_protocolBufferSize], data, size);
144+
m_protocolBufferSize += size;
145+
146+
return true;
147+
}
148+
149+
void PayloadHandler ::processProtocolBuffer() {
150+
// Process newline-terminated commands/headers
151+
// Looking for "<IMG_START>" to begin image reception
152+
153+
while (m_protocolBufferSize > 0) {
154+
// Look for newline character
155+
bool foundNewline = false;
156+
U32 lineEndIndex = 0;
157+
158+
for (U32 i = 0; i < m_protocolBufferSize; ++i) {
159+
if (m_protocolBuffer[i] == '\n' || m_protocolBuffer[i] == '\r') {
160+
foundNewline = true;
161+
lineEndIndex = i;
162+
break;
163+
}
164+
}
165+
166+
if (foundNewline) {
167+
U32 lineLength = lineEndIndex;
168+
169+
// Skip carriage return if present (handle \r\n)
170+
// needed?
171+
if (lineEndIndex + 1 < m_protocolBufferSize &&
172+
m_protocolBuffer[lineEndIndex] == '\r' &&
173+
m_protocolBuffer[lineEndIndex + 1] == '\n') {
174+
lineEndIndex++;
175+
}
176+
177+
// Check if this is the image start command
178+
if (isImageStartCommand(m_protocolBuffer, lineLength)) {
179+
// Allocate buffer for image data
180+
if (allocateImageBuffer()) {
181+
m_receiving = true;
182+
m_bytes_received = 0;
183+
184+
// Generate filename
185+
char filename[64];
186+
snprintf(filename, sizeof(filename), "/mnt/data/img_%03d.jpg", m_data_file_count++);
187+
m_currentFilename = filename;
188+
189+
this->log_ACTIVITY_LO_ImageHeaderReceived();
190+
191+
// Remove the IMG_START line from buffer
192+
U32 remainingSize = m_protocolBufferSize - (lineEndIndex + 1);
193+
if (remainingSize > 0) {
194+
memmove(m_protocolBuffer,
195+
&m_protocolBuffer[lineEndIndex + 1],
196+
remainingSize);
197+
}
198+
m_protocolBufferSize = remainingSize;
199+
200+
// Any remaining data in protocol buffer is image data, so we transfer it to the image buffer immediately
201+
if (m_protocolBufferSize > 0) {
202+
if (!accumulateImageData(m_protocolBuffer, m_protocolBufferSize)) {
203+
this->log_WARNING_HI_ImageDataOverflow();
204+
deallocateImageBuffer();
205+
m_receiving = false;
206+
}
207+
clearProtocolBuffer(); // Clear now that data is moved
208+
}
209+
210+
// Exit loop - we're now in image receiving mode
211+
break;
212+
} else {
213+
// Buffer allocation failed
214+
this->log_WARNING_HI_BufferAllocationFailed(IMAGE_BUFFER_SIZE);
215+
}
216+
} else {
217+
// Log other commands/data for debugging
218+
for (U32 i = 0; i < lineLength && i < 16; ++i) {
219+
this->log_ACTIVITY_LO_ByteReceived(m_protocolBuffer[i]);
220+
}
221+
222+
// Remove processed line from buffer
223+
U32 remainingSize = m_protocolBufferSize - (lineEndIndex + 1);
224+
if (remainingSize > 0) {
225+
memmove(m_protocolBuffer,
226+
&m_protocolBuffer[lineEndIndex + 1],
227+
remainingSize);
228+
}
229+
m_protocolBufferSize = remainingSize;
230+
}
231+
} else {
232+
break;
233+
}
234+
}
235+
}
236+
237+
void PayloadHandler ::clearProtocolBuffer() {
238+
m_protocolBufferSize = 0;
239+
memset(m_protocolBuffer, 0, PROTOCOL_BUFFER_SIZE);
240+
}
241+
242+
bool PayloadHandler ::allocateImageBuffer() {
243+
// Request buffer from BufferManager
244+
m_imageBuffer = this->allocate_out(0, IMAGE_BUFFER_SIZE);
245+
246+
// Check if allocation succeeded
247+
if (!m_imageBuffer.isValid() || m_imageBuffer.getSize() < IMAGE_BUFFER_SIZE) {
248+
this->log_WARNING_HI_BufferAllocationFailed(IMAGE_BUFFER_SIZE);
249+
deallocateImageBuffer();
250+
return false;
251+
}
252+
253+
m_imageBufferUsed = 0;
254+
return true;
255+
}
256+
257+
void PayloadHandler ::deallocateImageBuffer() {
258+
if (m_imageBuffer.isValid()) {
259+
this->deallocate_out(0, m_imageBuffer);
260+
m_imageBuffer = Fw::Buffer(); // Reset to invalid buffer
261+
}
262+
m_imageBufferUsed = 0;
263+
}
264+
265+
bool PayloadHandler ::accumulateImageData(const U8* data, U32 size) {
266+
FW_ASSERT(m_imageBuffer.isValid());
267+
268+
// Check if we have space
269+
if (m_imageBufferUsed + size > m_imageBuffer.getSize()) {
270+
return false;
271+
}
272+
273+
// Copy data into image buffer
274+
memcpy(&m_imageBuffer.getData()[m_imageBufferUsed], data, size);
275+
m_imageBufferUsed += size;
276+
m_bytes_received += size;
277+
278+
return true;
279+
}
280+
281+
void PayloadHandler ::processCompleteImage() {
282+
FW_ASSERT(m_imageBuffer.isValid());
283+
284+
// Write image to file
285+
Os::File::Status status = m_file.open(m_currentFilename.c_str(), Os::File::OPEN_WRITE);
286+
287+
if (status == Os::File::OP_OK) {
288+
// Os::File::write expects FwSizeType& for size parameter
289+
FwSizeType sizeToWrite = static_cast<FwSizeType>(m_imageBufferUsed);
290+
status = m_file.write(m_imageBuffer.getData(), sizeToWrite, Os::File::WaitType::NO_WAIT);
291+
m_file.close();
292+
293+
if (status == Os::File::OP_OK) {
294+
// Success! sizeToWrite now contains actual bytes written
295+
Fw::LogStringArg pathArg(m_currentFilename.c_str());
296+
this->log_ACTIVITY_HI_DataReceived(m_imageBufferUsed, pathArg);
297+
} else {
298+
// TODO - log write error
299+
}
300+
} else {
301+
// TODO - log open error
302+
}
303+
304+
// Clean up
305+
deallocateImageBuffer();
306+
m_receiving = false;
307+
m_bytes_received = 0;
308+
}
309+
310+
I32 PayloadHandler ::findImageEndMarker(const U8* data, U32 size) {
311+
// Looking for "\n<IMG_END>" or "<IMG_END>"
312+
const char* marker = "<IMG_END>";
313+
const U32 markerLen = 9; // strlen("<IMG_END>")
314+
315+
if (size < markerLen) {
316+
return -1;
317+
}
318+
319+
// Search for the marker
320+
for (U32 i = 0; i <= size - markerLen; ++i) {
321+
bool found = true;
322+
for (U32 j = 0; j < markerLen; ++j) {
323+
if (data[i + j] != static_cast<U8>(marker[j])) {
324+
found = false;
325+
break;
326+
}
327+
}
328+
if (found) {
329+
// Found marker at position i
330+
// If preceded by newline, back up to before newline
331+
if (i > 0 && data[i - 1] == '\n') {
332+
return static_cast<I32>(i - 1);
333+
}
334+
return static_cast<I32>(i);
335+
}
336+
}
337+
338+
return -1; // Not found
339+
}
340+
341+
bool PayloadHandler ::isImageStartCommand(const U8* line, U32 length) {
342+
const char* command = "<IMG_START>";
343+
const U32 cmdLen = 11; // strlen("<IMG_START>")
344+
345+
if (length != cmdLen) {
346+
return false;
347+
}
348+
349+
for (U32 i = 0; i < cmdLen; ++i) {
350+
if (line[i] != static_cast<U8>(command[i])) {
351+
return false;
352+
}
353+
}
354+
355+
return true;
356+
}
357+
63358
} // namespace Components

FprimeZephyrReference/Components/PayloadHandler/PayloadHandler.fpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,19 @@ module Components {
1919

2020
event UartReceived() severity activity low format "Received UART data"
2121

22+
event BufferAllocationFailed(buffer_size: U32) severity warning high format "Failed to allocate buffer of size {}"
23+
24+
event ImageDataOverflow() severity warning high format "Image data overflow - buffer full"
25+
2226
output port out_port: Drv.ByteStreamSend
2327

24-
sync input port in_port: Drv.ByteStreamData
28+
sync input port in_port: Drv.ByteStreamData
29+
30+
@ Port for allocating buffers for image data
31+
output port allocate: Fw.BufferGet
32+
33+
@ Port for deallocating buffers
34+
output port deallocate: Fw.BufferSend
2535

2636
##############################################################################
2737
#### Uncomment the following examples to start customizing your component ####
@@ -73,4 +83,4 @@ module Components {
7383
param set port prmSetOut
7484

7585
}
76-
}
86+
}

0 commit comments

Comments
 (0)