mirror of
https://github.com/SatDump/SatDump
synced 2026-08-13 17:47:30 -04:00
210 lines
No EOL
8.6 KiB
C++
210 lines
No EOL
8.6 KiB
C++
#include "demuxer.h"
|
|
#include "mpdu.h"
|
|
#include <cstring>
|
|
#include <vector>
|
|
|
|
#define HEADER_LENGTH 6
|
|
|
|
namespace ccsds
|
|
{
|
|
namespace ccsds_tm
|
|
{
|
|
Demuxer::Demuxer(int mpdu_data_size, bool hasInsertZone, int insertZoneSize, int mpdu_insert_zone, bool secondaryHeaderExtendsPkt)
|
|
: MPDU_DATA_SIZE(mpdu_data_size), HAS_INSERT_ZONE(hasInsertZone), INSERT_ZONE_SIZE(insertZoneSize), MPDU_INSERT_ZONE(mpdu_insert_zone),
|
|
SECONDARY_HEADER_EXTENDS_PKT(secondaryHeaderExtendsPkt)
|
|
{
|
|
// Init variables
|
|
currentCCSDSPacket.header.packet_length = 0;
|
|
currentPacketPayloadLength = 0;
|
|
remainingPacketLength = 0;
|
|
totalPacketLength = 0;
|
|
inHeader = false;
|
|
inHeaderBuffer = 0;
|
|
abortPacket();
|
|
}
|
|
|
|
// Fill header and packet lengths
|
|
void Demuxer::readPacket(uint8_t *h)
|
|
{
|
|
workingOnPacket = true;
|
|
currentCCSDSPacket.header = parseCCSDSHeader(h);
|
|
currentPacketPayloadLength = currentCCSDSPacket.header.packet_length + 1 + (SECONDARY_HEADER_EXTENDS_PKT ? (currentCCSDSPacket.header.secondary_header_flag ? 8 : 0) : 0);
|
|
totalPacketLength = currentPacketPayloadLength + HEADER_LENGTH;
|
|
remainingPacketLength = currentPacketPayloadLength;
|
|
}
|
|
|
|
// Clear everything and push into packet buffer
|
|
void Demuxer::pushPacket()
|
|
{
|
|
ccsdsBuffer.push_back(currentCCSDSPacket);
|
|
currentCCSDSPacket.payload.clear();
|
|
currentCCSDSPacket.header.packet_length = 0;
|
|
currentPacketPayloadLength = 0;
|
|
remainingPacketLength = 0;
|
|
workingOnPacket = false;
|
|
}
|
|
|
|
// Push data into the packet
|
|
void Demuxer::pushPayload(uint8_t *data, int length)
|
|
{
|
|
for (int i = 0; i < length; i++)
|
|
currentCCSDSPacket.payload.push_back(data[i]);
|
|
|
|
remainingPacketLength -= length;
|
|
}
|
|
|
|
// ABORT!
|
|
void Demuxer::abortPacket()
|
|
{
|
|
workingOnPacket = false;
|
|
currentCCSDSPacket.payload.clear();
|
|
currentCCSDSPacket.header.packet_length = 0;
|
|
currentPacketPayloadLength = 0;
|
|
remainingPacketLength = 0;
|
|
};
|
|
|
|
std::vector<CCSDSPacket> Demuxer::work(uint8_t *cadu)
|
|
{
|
|
ccsdsBuffer.clear(); // Clear buffer from previous run
|
|
|
|
MPDU mpdu = parseMPDU(cadu, HAS_INSERT_ZONE, INSERT_ZONE_SIZE, MPDU_INSERT_ZONE); // Parse M-PDU Header
|
|
|
|
// Sanity check, if the first header point points outside the data payload
|
|
if (mpdu.first_header_pointer < 2047 && mpdu.first_header_pointer >= MPDU_DATA_SIZE)
|
|
{
|
|
return ccsdsBuffer;
|
|
}
|
|
|
|
// This is idle
|
|
if (mpdu.first_header_pointer == 2046)
|
|
{
|
|
return ccsdsBuffer;
|
|
}
|
|
|
|
// If we're in a header or so,
|
|
// we may need to read with an offset
|
|
int offset = 0;
|
|
|
|
// We're parsing a header!
|
|
if (inHeader)
|
|
{
|
|
inHeader = false;
|
|
|
|
// Copy the remaining data into our header
|
|
std::memcpy(&headerBuffer[inHeaderBuffer], &mpdu.data[0], 6 - inHeaderBuffer);
|
|
offset = 6 - inHeaderBuffer;
|
|
inHeaderBuffer += 6 - inHeaderBuffer;
|
|
|
|
// Parse it
|
|
readPacket(headerBuffer);
|
|
}
|
|
|
|
// Are we working on a packet right now? Still got stuff to write? Then do it!
|
|
if (remainingPacketLength > 0 && workingOnPacket)
|
|
{
|
|
// If there's a header, it takes priority
|
|
if (mpdu.first_header_pointer < 2047)
|
|
{
|
|
// Finish filling up that packet
|
|
int toWrite = (remainingPacketLength + offset) > mpdu.first_header_pointer + 1 ? (mpdu.first_header_pointer + 1) - offset : remainingPacketLength;
|
|
pushPayload(&mpdu.data[offset], toWrite);
|
|
remainingPacketLength = 0;
|
|
}
|
|
else
|
|
{
|
|
// Write what we have
|
|
int toWrite = (remainingPacketLength + offset) > MPDU_DATA_SIZE - offset ? MPDU_DATA_SIZE - offset : remainingPacketLength;
|
|
pushPayload(&mpdu.data[offset], toWrite);
|
|
}
|
|
}
|
|
|
|
// Are we done writing a packet? Push it
|
|
if (remainingPacketLength == 0 && workingOnPacket)
|
|
{
|
|
pushPacket();
|
|
}
|
|
|
|
// Is there a new header here?
|
|
if (mpdu.first_header_pointer < 2047)
|
|
{
|
|
// The full header fits
|
|
if (mpdu.first_header_pointer + HEADER_LENGTH < MPDU_DATA_SIZE)
|
|
{
|
|
// Parse it
|
|
readPacket(&mpdu.data[mpdu.first_header_pointer]);
|
|
|
|
// Compute possible secondary headers in that packet
|
|
bool hasSecondHeader = MPDU_DATA_SIZE > mpdu.first_header_pointer + totalPacketLength;
|
|
|
|
// A second header can fit, so search for it!
|
|
if (hasSecondHeader)
|
|
{
|
|
// Write first packet
|
|
if (mpdu.first_header_pointer + totalPacketLength < MPDU_DATA_SIZE)
|
|
{
|
|
pushPayload(&mpdu.data[mpdu.first_header_pointer + 6], currentPacketPayloadLength);
|
|
pushPacket();
|
|
}
|
|
else
|
|
{
|
|
abortPacket();
|
|
}
|
|
|
|
// Compute next possible header
|
|
int nextHeaderPointer = mpdu.first_header_pointer + totalPacketLength;
|
|
|
|
while (nextHeaderPointer < MPDU_DATA_SIZE)
|
|
{
|
|
// The header fits!
|
|
if (nextHeaderPointer + HEADER_LENGTH < MPDU_DATA_SIZE)
|
|
{
|
|
readPacket(&mpdu.data[nextHeaderPointer]);
|
|
|
|
int toWrite = remainingPacketLength > (MPDU_DATA_SIZE - (nextHeaderPointer + 6)) ? (MPDU_DATA_SIZE - (nextHeaderPointer + 6)) : remainingPacketLength;
|
|
pushPayload(&mpdu.data[nextHeaderPointer + 6], toWrite);
|
|
}
|
|
// Only part of the header fits. At least 1 byte has to be there or it'll be in the next frame
|
|
else if (nextHeaderPointer < MPDU_DATA_SIZE)
|
|
{
|
|
inHeader = true;
|
|
inHeaderBuffer = 0;
|
|
std::memcpy(headerBuffer, &mpdu.data[nextHeaderPointer], MPDU_DATA_SIZE - nextHeaderPointer);
|
|
inHeaderBuffer += MPDU_DATA_SIZE - nextHeaderPointer;
|
|
break;
|
|
}
|
|
|
|
// That packet is done? Write it
|
|
if (remainingPacketLength == 0 && workingOnPacket)
|
|
{
|
|
pushPacket();
|
|
}
|
|
|
|
// Update to next pointer
|
|
nextHeaderPointer = nextHeaderPointer + totalPacketLength;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Sanity check
|
|
if (workingOnPacket)
|
|
{
|
|
// Fill that packet
|
|
int toWrite = remainingPacketLength > (MPDU_DATA_SIZE - (mpdu.first_header_pointer + 6)) ? (MPDU_DATA_SIZE - (mpdu.first_header_pointer + 6)) : remainingPacketLength;
|
|
pushPayload(&mpdu.data[mpdu.first_header_pointer + 6], toWrite);
|
|
}
|
|
}
|
|
}
|
|
else if (mpdu.first_header_pointer < MPDU_DATA_SIZE)
|
|
{
|
|
// The header doesn't fit, so fill what we have
|
|
inHeader = true;
|
|
inHeaderBuffer = 0;
|
|
std::memcpy(headerBuffer, &mpdu.data[mpdu.first_header_pointer], MPDU_DATA_SIZE - mpdu.first_header_pointer);
|
|
inHeaderBuffer += MPDU_DATA_SIZE - mpdu.first_header_pointer;
|
|
}
|
|
}
|
|
|
|
return ccsdsBuffer;
|
|
} // namespace libccsds
|
|
} // namespace ccsds_tm
|
|
} // namespace ccsds
|