36 m_vcs[vcInd].vcStructIndex = vcInd;
50 FW_ASSERT(fixedFrameSize > minSize, static_cast<FwAssertArgType>(fixedFrameSize),
51 static_cast<FwAssertArgType>(minSize));
54 FW_ASSERT((spacecraftId & 0xFC00) == 0, static_cast<FwAssertArgType>(spacecraftId));
57 FW_ASSERT((vcId & 0xC0) == 0, static_cast<FwAssertArgType>(vcId));
67 m_fixedFrameSize = fixedFrameSize;
68 m_fecfEnabled = frameErrorControlField;
69 m_spacecraftId = spacecraftId;
75 m_vcs[0].virtualChannelId = vcId;
76 m_vcs[0].pvnMask = pvnMask;
80 m_vcs[vcInd].framesProcessed = 0;
81 m_vcs[vcInd].packetsExtracted = 0;
82 m_vcs[vcInd].vcFrameCount = 0;
85 this->abandonSpanningPacket(m_vcs[vcInd]);
96 FW_ASSERT(m_fixedFrameSize > 0, static_cast<FwAssertArgType>(m_fixedFrameSize));
98 if (data.
getSize() < m_fixedFrameSize) {
107 if (m_fecfEnabled && !this->validateFecf(data)) {
119 if ((vc = this->parseAndValidateHeader(data, packetContext)) ==
nullptr) {
126 if (!vc->spanningPacket.buffer.isValid()) {
127 vc->spanningPacket.context = packetContext;
131 this->extractPackets(*vc, data);
149 void AosDeframer::notifyErrorIfConnected(Ccsds::FrameError error) {
155 void AosDeframer::abandonSpanningPacket(AosDeframerVc& vc) {
156 if (vc.spanningPacket.buffer.isValid()) {
158 vc.spanningPacket.bytesReceived,
159 vc.spanningPacket.buffer.getSize());
163 vc.spanningPacket.bytesReceived = 0;
167 AosDeframer::AosDeframerVc* AosDeframer::getVcStruct(
const U8 vcId) {
169 if (m_vcs[vcInd].virtualChannelId == vcId) {
170 return &m_vcs[vcInd];
188 if (tfvn != static_cast<U8>(
Tfvn::AOS)) {
197 const U16 spacecraftId =
203 if (spacecraftId != m_spacecraftId) {
211 AosDeframerVc* vc = this->getVcStruct(vcId);
226 U32 frameCountMask = 0x00FF
'FFFF; 228 // Extract VC Frame Count Cycle if in use (Section 4.1.2.5.3) 229 if ((header.get_frameCountAndSignaling() & AOSHeaderSubfields::cycleCountFlagMask) != 0) { 230 const U8 rxVcFrameCountCycle = header.get_frameCountAndSignaling() & AOSHeaderSubfields::vcFrameCountCycleMask; 231 // Extend the 24-bit frame count with the 4-bit cycle count 232 rxVcFrameCount |= static_cast<U32>(rxVcFrameCountCycle) << 24; 233 // Add the 4 additional bits to our modulo 234 frameCountMask |= 0x0F00'0000;
238 if (vc->framesProcessed > 0U) {
239 const U32 expectedVcFrameCount = vc->vcFrameCount + 1U;
240 if (rxVcFrameCount != (expectedVcFrameCount & frameCountMask)) {
241 this->log_WARNING_HI_VcFrameCountGap(vcId, rxVcFrameCount, expectedVcFrameCount);
244 this->abandonSpanningPacket(*vc);
249 vc->vcFrameCount = rxVcFrameCount;
250 this->tlmWrite_LatestVcFrameCount(vc->vcFrameCount);
258 bool AosDeframer::validateFecf(
Fw::Buffer& data) {
262 const FwSizeType crcDataLen = m_fixedFrameSize - AOSTrailer::SERIALIZED_SIZE;
272 U16 transmittedCrc = trailer.get_fecf();
273 if (transmittedCrc != computedCrc) {
274 this->log_WARNING_HI_InvalidFecf(transmittedCrc, computedCrc);
276 this->tlmWrite_CrcErrorCount(++m_crcErrorCount);
285 FW_ASSERT(size > 0, static_cast<FwAssertArgType>(size));
291 if (!vc.spanningPacket.buffer.isValid()) {
293 const FwSizeType headerCap = AosDeframerVc::SpanningPacketState::HEADER_BUF_SIZE;
295 const FwSizeType toHeader =
FW_MIN(size, headerCap - vc.spanningPacket.bytesReceived);
297 FW_ASSERT(vc.spanningPacket.bytesReceived < headerCap,
298 static_cast<FwAssertArgType>(vc.spanningPacket.bytesReceived),
299 static_cast<FwAssertArgType>(headerCap));
300 FW_ASSERT(toHeader <= headerCap, static_cast<FwAssertArgType>(toHeader),
301 static_cast<FwAssertArgType>(headerCap));
302 FW_ASSERT(vc.spanningPacket.bytesReceived + toHeader <= headerCap,
303 static_cast<FwAssertArgType>(vc.spanningPacket.bytesReceived),
304 static_cast<FwAssertArgType>(toHeader), static_cast<FwAssertArgType>(headerCap));
305 ::memcpy(vc.spanningPacket.headerBuf + vc.spanningPacket.bytesReceived, data, toHeader);
306 vc.spanningPacket.bytesReceived += toHeader;
311 seekForward += toHeader;
319 const FwSizeType packetSize = sizePacket(vc, vc.spanningPacket.headerBuf, vc.spanningPacket.bytesReceived);
320 if (packetSize == 0) {
325 vc.spanningPacket.buffer = this->allocate_out(0, packetSize);
326 if (vc.spanningPacket.buffer.getSize() < packetSize) {
327 this->log_WARNING_HI_SpanningPacketAllocFailed(vc.virtualChannelId, vc.spanningPacket.context.get_pvn(),
330 const FwSizeType remainingBody = packetSize - vc.spanningPacket.bytesReceived;
331 this->abandonSpanningPacket(vc);
334 const FwSizeType remainingLength = seekForward + remainingBody;
335 if (remainingLength > size) {
338 return remainingLength;
343 FW_ASSERT(vc.spanningPacket.bytesReceived <= AosDeframerVc::SpanningPacketState::HEADER_BUF_SIZE,
344 static_cast<FwAssertArgType>(vc.spanningPacket.bytesReceived),
345 AosDeframerVc::SpanningPacketState::HEADER_BUF_SIZE);
346 ::memcpy(vc.spanningPacket.buffer.getData(), vc.spanningPacket.headerBuf, vc.spanningPacket.bytesReceived);
350 const FwSizeType spaceLeft = vc.spanningPacket.buffer.getSize() - vc.spanningPacket.bytesReceived;
354 FW_ASSERT(vc.spanningPacket.bytesReceived + toBody <= vc.spanningPacket.buffer.getSize(),
355 static_cast<FwAssertArgType>(vc.spanningPacket.bytesReceived), static_cast<FwAssertArgType>(toBody),
357 ::memcpy(vc.spanningPacket.buffer.getData() + vc.spanningPacket.bytesReceived, data, toBody);
358 vc.spanningPacket.bytesReceived += toBody;
359 seekForward += toBody;
363 if (vc.spanningPacket.buffer.getSize() > 0 &&
364 vc.spanningPacket.bytesReceived >= vc.spanningPacket.buffer.getSize()) {
365 this->dataOut_out(0, vc.spanningPacket.buffer, vc.spanningPacket.context);
366 this->tlmWrite_PacketsExtracted(++vc.packetsExtracted);
371 this->abandonSpanningPacket(vc);
377 void AosDeframer::extractPackets(AosDeframerVc& vc,
Fw::Buffer& data) {
379 M_PDUHeader mpduHeader;
385 U16 firstHeaderPointer = mpduHeader.get_firstHeaderPointer();
388 const FwSizeType dataZoneStart = AOSHeader::SERIALIZED_SIZE + M_PDUHeader::SERIALIZED_SIZE;
389 const FwSizeType dataZoneEnd = m_fixedFrameSize - (m_fecfEnabled ? AOSTrailer::SERIALIZED_SIZE : 0);
390 const FwSizeType dataZoneSize = dataZoneEnd - dataZoneStart;
391 U8* dataZone = data.
getData() + dataZoneStart;
396 this->log_ACTIVITY_LO_IdleFrame(vc.virtualChannelId);
402 if (vc.spanningPacket.bytesReceived > 0) {
403 (void)this->appendToSpanningPacket(vc, dataZone, dataZoneSize);
410 if (firstHeaderPointer >= dataZoneSize) {
411 this->log_WARNING_HI_InvalidFhp(vc.virtualChannelId, firstHeaderPointer, dataZoneSize);
414 this->abandonSpanningPacket(vc);
419 if (firstHeaderPointer > 0 && vc.spanningPacket.bytesReceived > 0) {
420 (void)this->appendToSpanningPacket(vc, dataZone, static_cast<FwSizeType>(firstHeaderPointer));
422 this->abandonSpanningPacket(vc);
426 FwSizeType currentOffset = firstHeaderPointer;
433 for (
FwIndexType iter = 0; iter < maxIters && currentOffset < dataZoneSize; iter++) {
435 this->abandonSpanningPacket(vc);
437 U8* packetStart = dataZone + currentOffset;
438 FwSizeType remainingBytes = dataZoneSize - currentOffset;
440 FwSizeType packetSize = this->appendToSpanningPacket(vc, packetStart, remainingBytes);
442 if (packetSize == 0) {
447 currentOffset += packetSize;
452 FW_ASSERT(remainingBytes > 0, static_cast<FwAssertArgType>(remainingBytes));
455 U8 pvn = getPacketVersion(packetStart[0]);
460 if (~vc.pvnMask & (1 << pvn)) {
461 this->log_WARNING_HI_DisabledPvn(vc.virtualChannelId, pvn);
466 vc.spanningPacket.context.set_pvn(pvnEnum);
471 return sizeSppPacket(packetStart, remainingBytes);
474 return sizeEppPacket(packetStart, remainingBytes);
484 SpacePacketHeader header;
494 FwSizeType totalPacketSize = SpacePacketHeader::SERIALIZED_SIZE + header.get_packetDataLength() + 1;
507 return totalPacketSize;
513 FW_ASSERT(payloadSize > 0, static_cast<FwAssertArgType>(payloadSize));
516 U8 firstByte = payloadStart[0];
522 if (protocolId == static_cast<U8>(EppProtocolId::Idle)) {
529 U8 lengthOffset = 1U;
532 if (lengthOfLength >= EppLengthOfLength::Two) {
533 lengthOffset =
static_cast<U8>(lengthOffset + 1U);
537 if (lengthOfLength == EppLengthOfLength::Four) {
538 lengthOffset =
static_cast<U8>(lengthOffset + 2U);
544 const U8 headerLength =
static_cast<U8>(lengthOffset + lengthOfLength);
547 if (payloadSize < headerLength) {
552 U32 packetDataLength = 0;
553 for (
U8 i = 0; i < lengthOfLength; i++) {
554 packetDataLength = (packetDataLength << 8) | payloadStart[lengthOffset + i];
557 totalPacketSize = headerLength + packetDataLength;
559 return totalPacketSize;
562 U8 AosDeframer::getPacketVersion(
U8 firstByte) {
Serialization/Deserialization operation was successful.
static U16 compute(const U8 *buffer, U32 length)
compute CRC16 for a buffer
CCSDS 732.0-B-5: Transfer Frame Version Number mismatch (4.1.2.2.2)
Fully Featured CCSDS Space Packet Protocol.
Advanced Orbiting Systems SDL.
PlatformSizeType FwSizeType
CCSDS 732.0-B-5: Frame length insufficient.
CCSDS 732.0-B-5: Frame Error Control Field CRC mismatch (4.1.6)
Anything equal or higher value is invalid and should not be used.
~AosDeframer()
Destroy AosDeframer object.
The size of the serial representation.
void configure(U32 fixedFrameSize, bool frameErrorControlField, U16 spacecraftId=ComCfg::SpacecraftId, U8 vcId=0, U8 pvnMask=PvnBitfield::SPP_MASK|PvnBitfield::EPP_MASK)
Configure the AosDeframer with mission-specific parameters.
bool isConnected_errorNotify_OutputPort(FwIndexType portNum) const
Auto-generated base for AosDeframer component.
CCSDS 732.0-B-5: Virtual Channel ID mismatch (4.1.2.3)
void log_WARNING_LO_InvalidSpacecraftId(U16 transmitted, U16 configured) const
SerializeStatus
forward declaration for string
ExternalSerializeBufferWithMemberCopy getDeserializer()
bool isConnected_allocate_OutputPort(FwIndexType portNum) const
void tlmWrite_FramesProcessed(U32 arg, Fw::Time _tlmTime=Fw::Time()) const
void log_WARNING_HI_InvalidFrameLength(FwSizeType actual, U32 expected) const
#define FW_MIN(a, b)
MIN macro (deprecated in C++, use std::min)
void deallocate_out(FwIndexType portNum, Fw::Buffer &fwBuffer) const
Invoke output port deallocate.
void log_WARNING_HI_SpanningPacketAbandoned(U8 vcId, ComCfg::Pvn pvn, FwSizeType bytesReceived, FwSizeType bytesExpected) const
CCSDS 732.0-B-5: Spacecraft ID mismatch (4.1.2.2)
Packet Version Numbers are 3 bits with only 2 currently valid values.
bool isConnected_deallocate_OutputPort(FwIndexType portNum) const
void set_vcId(U8 vcId)
Set member vcId.
uint8_t U8
8-bit unsigned integer
void errorNotify_out(FwIndexType portNum, const Svc::Ccsds::FrameError &errorCode) const
Invoke output port errorNotify.
FwSizeType getSize() const
AosDeframer(const char *const compName)
Construct AosDeframer object.
Bare-bones CCSDS Encapsulation Packet Protocol.
PlatformIndexType FwIndexType
SerializeStatus moveDeserToOffset(FwSizeType offset) override
Move deserialization pointer to specified offset.
void log_ACTIVITY_LO_InvalidVcId(U8 transmitted, U8 configured) const
Type used to pass context info between components during framing/deframing.
RateGroupDivider component implementation.
SerializeStatus deserializeTo(U8 &val, Endianness mode=Endianness::BIG) override
Deserialize an 8-bit unsigned integer value.
Per Space Packet Standard, all 1s (11bits) is reserved for Idle Packets.
void dataReturnOut_out(FwIndexType portNum, Fw::Buffer &data, const ComCfg::FrameContext &context) const
Invoke output port dataReturnOut.
PlatformAssertArgType FwAssertArgType
The type of arguments to assert functions.
void log_WARNING_HI_InvalidTfvn(U8 transmitted, U8 expected) const
CCSDS 732.0-B-5: AOS VC frame count discontinuity detected.