GCC Code Coverage Report


Directory: Svc/FrameAccumulator/
File: FrameDetector/CcsdsTcFrameDetector.cpp
Date: 2026-09-03 21:17:59
Exec Total Coverage
Lines: 44 46 95.7%
Functions: 1 1 100.0%
Branches: 28 30 93.3%

Line Branch Exec Source
1 // ======================================================================
2 // \title CcsdsTcFrameDetector.hpp
3 // \author thomas-bc
4 // \brief hpp file for fprime frame detector definitions
5 // ======================================================================
6
7 #include "Svc/FrameAccumulator/FrameDetector/CcsdsTcFrameDetector.hpp"
8 #include <cstdio>
9 #include "Svc/Ccsds/Types/FppConstantsAc.hpp"
10 #include "Svc/Ccsds/Types/TCHeaderSerializableAc.hpp"
11 #include "Svc/Ccsds/Types/TCTrailerSerializableAc.hpp"
12 #include "Svc/Ccsds/Utils/CRC16.hpp"
13 #include "Utils/Hash/Hash.hpp"
14 #include "config/FppConstantsAc.hpp"
15
16 namespace Svc {
17 namespace FrameDetectors {
18
19 1008 FrameDetector::Status CcsdsTcFrameDetector::detect(const Types::CircularBuffer& data, FwSizeType& size_out) const {
20
3/3
✓ Branch 2 taken 1008 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1007 times.
1008 if (data.get_allocated_size() < Ccsds::TCHeader::SERIALIZED_SIZE + Ccsds::TCTrailer::SERIALIZED_SIZE) {
21 1 size_out = Ccsds::TCHeader::SERIALIZED_SIZE + Ccsds::TCTrailer::SERIALIZED_SIZE;
22 1 return Status::MORE_DATA_NEEDED;
23 }
24
25 // ---------------- Frame Header ----------------
26 // Copy CircularBuffer data into linear buffer, for serialization into FrameHeader object
27 1007 U8 header_data[Ccsds::TCHeader::SERIALIZED_SIZE];
28
1/1
✓ Branch 2 taken 1007 times.
1007 Fw::SerializeStatus status = data.peek(header_data, Ccsds::TCHeader::SERIALIZED_SIZE, 0);
29
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1007 times.
1007 if (status != Fw::FW_SERIALIZE_OK) {
30 return Status::NO_FRAME_DETECTED;
31 }
32
1/1
✓ Branch 2 taken 1007 times.
1007 Fw::ExternalSerializeBuffer header_ser_buffer(header_data, Ccsds::TCHeader::SERIALIZED_SIZE);
33
1/1
✓ Branch 2 taken 1007 times.
1007 status = header_ser_buffer.setBuffLen(Ccsds::TCHeader::SERIALIZED_SIZE);
34 1007 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast<FwAssertArgType>(status));
35 // Attempt to deserialize data into the FrameHeader object
36
1/1
✓ Branch 2 taken 1007 times.
1007 Ccsds::TCHeader header;
37
1/1
✓ Branch 2 taken 1007 times.
1007 status = header.deserializeFrom(header_ser_buffer);
38 1007 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
39
40
2/2
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1006 times.
1007 if (header.get_flagsAndScId() != this->m_expectedFlagsAndScIdToken) {
41 // If the flags and SC ID do not match the expected token, we don't have a valid frame
42 1 return Status::NO_FRAME_DETECTED;
43 }
44 // TC protocol defines the Frame Length as number of bytes minus 1, so we add 1 back to get length in bytes
45 const FwSizeType expected_frame_length =
46 1006 static_cast<FwSizeType>((header.get_vcIdAndLength() & Ccsds::TCSubfields::FrameLengthMask) + 1);
47
48 // If the full frame is not yet available, report that more data is needed
49
3/3
✓ Branch 2 taken 1006 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1005 times.
1006 if (data.get_allocated_size() < expected_frame_length) {
50 1 size_out = expected_frame_length;
51 1 return Status::MORE_DATA_NEEDED;
52 }
53 // Validate minimum frame size BEFORE computing data_to_crc_length.
54 // If expected_frame_length < TRAILER_SIZE the subtraction below would underflow to a
55 // near-maximum value, causing the CRC loop to read far beyond the valid frame data.
56
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1003 times.
1005 if (expected_frame_length < Ccsds::TCHeader::SERIALIZED_SIZE + Ccsds::TCTrailer::SERIALIZED_SIZE) {
57 2 return Status::NO_FRAME_DETECTED;
58 }
59 // Safe: the guard above guarantees expected_frame_length >= TRAILER_SIZE, so this
60 // subtraction cannot underflow. Type is FwSizeType (not U16) to avoid silent truncation
61 // if expected_frame_length ever exceeds 65535.
62 1003 const FwSizeType data_to_crc_length = expected_frame_length - Ccsds::TCTrailer::SERIALIZED_SIZE;
63
64 // ---------------- Frame Trailer ----------------
65 // Compute CRC on the received data
66 1003 Ccsds::Utils::CRC16 crc;
67
2/2
✓ Branch 0 taken 15035 times.
✓ Branch 1 taken 1003 times.
16038 for (FwSizeType i = 0; i < data_to_crc_length; ++i) {
68 15035 U8 byte = 0;
69
1/1
✓ Branch 2 taken 15035 times.
15035 status = data.peek(byte, i);
70 15035 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
71
1/1
✓ Branch 1 taken 15035 times.
15035 crc.update(byte);
72 }
73 1003 U16 computed_fecf = crc.finalize();
74 // Retrieve CRC field from the trailer
75 1003 U8 trailer_data[Ccsds::TCTrailer::SERIALIZED_SIZE];
76
1/1
✓ Branch 2 taken 1003 times.
1003 status = data.peek(trailer_data, Ccsds::TCTrailer::SERIALIZED_SIZE, data_to_crc_length);
77
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1003 times.
1003 if (status != Fw::FW_SERIALIZE_OK) {
78 return Status::NO_FRAME_DETECTED;
79 }
80
1/1
✓ Branch 2 taken 1003 times.
1003 Fw::ExternalSerializeBuffer trailer_ser_buffer(trailer_data, Ccsds::TCTrailer::SERIALIZED_SIZE);
81
1/1
✓ Branch 2 taken 1003 times.
1003 status = trailer_ser_buffer.setBuffLen(Ccsds::TCTrailer::SERIALIZED_SIZE);
82 1003 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast<FwAssertArgType>(status));
83 // Attempt to deserialize data into the FrameTrailer object
84
1/1
✓ Branch 2 taken 1003 times.
1003 Ccsds::TCTrailer trailer;
85
1/1
✓ Branch 2 taken 1003 times.
1003 status = trailer.deserializeFrom(trailer_ser_buffer);
86 1003 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
87 1003 U16 transmitted_fecf = trailer.get_fecf();
88
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1002 times.
1003 if (transmitted_fecf != computed_fecf) {
89 // If the computed CRC does not match the transmitted CRC, we don't have a valid frame
90 1 return Status::NO_FRAME_DETECTED;
91 }
92 // At this point, we have validated the header and CRC - we report a valid frame detected
93 1002 size_out = expected_frame_length;
94 1002 return Status::FRAME_DETECTED;
95 1007 }
96
97 } // namespace FrameDetectors
98 } // namespace Svc
99