GCC Code Coverage Report


Directory: ./
File: Svc/Ccsds/TcDeframer/TcDeframer.cpp
Date: 2026-09-03 21:13:48
Exec Total Coverage
Lines: 56 59 94.9%
Functions: 6 6 100.0%
Branches: 46 53 86.8%

Line Branch Exec Source
1 // ======================================================================
2 // \title TcDeframer.cpp
3 // \author thomas-bc
4 // \brief cpp file for TcDeframer component implementation class
5 // ======================================================================
6
7 #include "Svc/Ccsds/TcDeframer/TcDeframer.hpp"
8 #include "Svc/Ccsds/Types/FppConstantsAc.hpp"
9 #include "Svc/Ccsds/Types/TCHeaderSerializableAc.hpp"
10 #include "Svc/Ccsds/Types/TCTrailerSerializableAc.hpp"
11 #include "Svc/Ccsds/Utils/CRC16.hpp"
12 #include "config/FpConfig.hpp"
13
14 namespace Svc {
15 namespace Ccsds {
16
17 // ----------------------------------------------------------------------
18 // Component construction and destruction
19 // ----------------------------------------------------------------------
20
21 6 TcDeframer ::TcDeframer(const char* const compName)
22 6 : TcDeframerComponentBase(compName), m_spacecraftId(ComCfg::SpacecraftId) {}
23
24 12 TcDeframer ::~TcDeframer() {}
25
26 5 void TcDeframer::configure(U16 vcId, U16 spacecraftId, bool acceptAllVcid) {
27 5 this->m_vcId = vcId;
28 5 this->m_spacecraftId = spacecraftId;
29 5 this->m_acceptAllVcid = acceptAllVcid;
30 5 }
31 // ----------------------------------------------------------------------
32 // Handler implementations for user-defined typed input ports
33 // ----------------------------------------------------------------------
34
35 5 void TcDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) {
36 // CCSDS TC Format:
37 // 5 octets - TC Primary Header
38 // Up to 1019 octets - Data Field (including optional 2 octets frame error control field)
39
40 // Note: F Prime uses Type-BD
41 // CCSDS TC Primary Header:
42 // 2b - 00 - TF Version Number
43 // 1b - 0/1 - Bypass Flag (0 = Type-A FARM checks enabled, 1 = Type-B FARM checks bypassed)
44 // 1b - 0/1 - Control Command Flag (0 = Type-D data, 1 = Type-C control command)
45 // 2b - 00 - Reserved Spare (set to 00)
46 // 10b- XX - Spacecraft ID
47 // 6b - XX - Virtual Channel ID
48 // 10b- XX - Frame Length
49 // 8b - XX - Frame Sequence Number (unused for Type-B frames)
50
51 // CCSDS TC Trailer:
52 // 16b - Frame Error Control Field (FECF): CRC16
53
2/3
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
5 if (data.getSize() <= TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE) {
54 // Incoming buffer is not long enough to contain a valid frame (header+trailer)
55 this->log_WARNING_LO_InvalidPacket();
56 this->dataReturnOut_out(0, data, context);
57 return;
58 }
59
60
1/1
✓ Branch 2 taken 5 times.
5 TCHeader header;
61
2/2
✓ Branch 2 taken 5 times.
✓ Branch 8 taken 5 times.
5 Fw::SerializeStatus status = data.getDeserializer().deserializeTo(header);
62 5 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
63 // TC protocol defines the Frame Length as number of bytes minus 1, so we add 1 back to get length in bytes
64 5 U16 total_frame_length = static_cast<U16>((header.get_vcIdAndLength() & TCSubfields::FrameLengthMask) + 1);
65 5 U8 vc_id = static_cast<U8>((header.get_vcIdAndLength() & TCSubfields::VcIdMask) >> TCSubfields::VcIdOffset);
66 5 U16 spacecraft_id = header.get_flagsAndScId() & TCSubfields::SpacecraftIdMask;
67
68
2/2
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 4 times.
5 if (spacecraft_id != this->m_spacecraftId) {
69
1/1
✓ Branch 9 taken 1 times.
1 this->log_WARNING_LO_InvalidSpacecraftId(spacecraft_id, this->m_spacecraftId);
70
2/2
✓ Branch 5 taken 1 times.
✓ Branch 8 taken 1 times.
1 this->errorNotifyHelper(Ccsds::FrameError::TC_INVALID_SCID);
71
1/1
✓ Branch 5 taken 1 times.
1 this->dataReturnOut_out(0, data, context); // drop the frame
72 1 return;
73 }
74 // check that deserialized frame_length is at least large enough to hold header and trailer, and
75 // that it is not larger than the actual data available in the buffer
76
6/7
✓ Branch 4 taken 4 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 3 times.
4 if ((data.getSize() < static_cast<Fw::Buffer::SizeType>(total_frame_length)) or
77 (total_frame_length < TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE)) {
78
1/1
✓ Branch 4 taken 1 times.
1 FwSizeType maxDataAvailable = static_cast<FwSizeType>(data.getSize());
79
1/1
✓ Branch 5 taken 1 times.
1 this->log_WARNING_HI_InvalidFrameLength(total_frame_length, maxDataAvailable);
80
2/2
✓ Branch 5 taken 1 times.
✓ Branch 8 taken 1 times.
1 this->errorNotifyHelper(Ccsds::FrameError::TC_INVALID_LENGTH);
81
1/1
✓ Branch 5 taken 1 times.
1 this->dataReturnOut_out(0, data, context); // drop the frame
82 1 return;
83 }
84
4/6
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
3 if (not this->m_acceptAllVcid && vc_id != this->m_vcId) {
85
1/1
✓ Branch 9 taken 1 times.
1 this->log_ACTIVITY_LO_InvalidVcId(vc_id, this->m_vcId);
86
2/2
✓ Branch 5 taken 1 times.
✓ Branch 8 taken 1 times.
1 this->errorNotifyHelper(Ccsds::FrameError::TC_INVALID_VCID);
87
1/1
✓ Branch 5 taken 1 times.
1 this->dataReturnOut_out(0, data, context); // drop the frame
88 1 return;
89 }
90 // Note: F Prime uses TC Type-BD frames for now, so the FARM checks are not ran
91 // This means there is no sequence count checks at the TC level (there are at the Space Packet level)
92
93 // -------------------------------------------------
94 // CRC Check
95 // -------------------------------------------------
96 // Compute CRC over the entire frame buffer minus the FECF trailer
97
2/2
✓ Branch 4 taken 2 times.
✓ Branch 7 taken 2 times.
2 U16 computed_crc = Ccsds::Utils::CRC16::compute(data.getData(), total_frame_length - TCTrailer::SERIALIZED_SIZE);
98
1/1
✓ Branch 2 taken 2 times.
2 TCTrailer trailer;
99
1/1
✓ Branch 2 taken 2 times.
2 auto deserializer = data.getDeserializer();
100
1/1
✓ Branch 2 taken 2 times.
2 status = deserializer.moveDeserToOffset(total_frame_length - TCTrailer::SERIALIZED_SIZE);
101 2 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
102
1/1
✓ Branch 2 taken 2 times.
2 status = deserializer.deserializeTo(trailer);
103 2 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
104
105 2 U16 transmitted_crc = trailer.get_fecf();
106
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (transmitted_crc != computed_crc) {
107
1/1
✓ Branch 5 taken 1 times.
1 this->log_WARNING_HI_InvalidCrc(computed_crc, transmitted_crc);
108
2/2
✓ Branch 5 taken 1 times.
✓ Branch 8 taken 1 times.
1 this->errorNotifyHelper(Ccsds::FrameError::TC_INVALID_CRC);
109
1/1
✓ Branch 5 taken 1 times.
1 this->dataReturnOut_out(0, data, context); // drop the frame
110 1 return;
111 }
112
113 // Point to the start of the data field and set appropriate size
114
1/1
✓ Branch 4 taken 1 times.
1 data.advance(TCHeader::SERIALIZED_SIZE);
115 // Shrink size to that of the encapsulated data field ( header | data | trailer )
116
1/1
✓ Branch 4 taken 1 times.
1 data.setSize(total_frame_length - TCHeader::SERIALIZED_SIZE - TCTrailer::SERIALIZED_SIZE);
117
118
1/1
✓ Branch 5 taken 1 times.
1 this->dataOut_out(0, data, context);
119 7 }
120
121 1 void TcDeframer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) {
122 1 this->dataReturnOut_out(0, fwBuffer, context);
123 1 }
124
125 4 void TcDeframer::errorNotifyHelper(Ccsds::FrameError error) {
126
1/2
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
4 if (this->isConnected_errorNotify_OutputPort(0)) {
127 4 this->errorNotify_out(0, error);
128 }
129 4 }
130
131 } // namespace Ccsds
132 } // namespace Svc
133