kopia lustrzana https://github.com/OpenRTX/OpenRTX
Implementation of M17 frame encoder
rodzic
82dd0a63f1
commit
35c1f062c6
|
@ -43,6 +43,7 @@ openrtx_src = ['openrtx/src/core/state.c',
|
|||
'openrtx/src/protocols/M17/M17Callsign.cpp',
|
||||
'openrtx/src/protocols/M17/M17Modulator.cpp',
|
||||
'openrtx/src/protocols/M17/M17Demodulator.cpp',
|
||||
'openrtx/src/protocols/M17/M17FrameEncoder.cpp',
|
||||
'openrtx/src/protocols/M17/M17FrameDecoder.cpp',
|
||||
'openrtx/src/protocols/M17/M17Transmitter.cpp',
|
||||
'openrtx/src/protocols/M17/M17LinkSetupFrame.cpp']
|
||||
|
|
|
@ -33,6 +33,7 @@ using call_t = std::array< uint8_t, 6 >; // Data type for encoded callsign
|
|||
using meta_t = std::array< uint8_t, 14 >; // Data type for LSF metadata field
|
||||
using payload_t = std::array< uint8_t, 16 >; // Data type for frame payload field
|
||||
using lich_t = std::array< uint8_t, 12 >; // Data type for Golay(24,12) encoded LICH data
|
||||
using frame_t = std::array< uint8_t, 48 >; // Data type for a full M17 data frame, including sync word
|
||||
|
||||
static constexpr std::array<uint8_t, 2> LSF_SYNC_WORD = {0x55, 0xF7}; // LSF sync word
|
||||
static constexpr std::array<uint8_t, 2> STREAM_SYNC_WORD = {0xFF, 0x5D}; // Stream data sync word
|
||||
|
|
|
@ -69,7 +69,7 @@ public:
|
|||
* @param frame: byte array containg frame data.
|
||||
* @return the type of frame recognized.
|
||||
*/
|
||||
M17FrameType decodeFrame(const std::array< uint8_t, 48 >& frame);
|
||||
M17FrameType decodeFrame(const frame_t& frame);
|
||||
|
||||
/**
|
||||
* Get the latest Link Setup Frame decoded. Check of the validity of the
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2022 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Niccolò Izzo IU2KIN *
|
||||
* Frederik Saraci IU2NRO *
|
||||
* Silvano Seva IU2KWO *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/> *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef M17FRAMEENCODER_H
|
||||
#define M17FRAMEENCODER_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error This header is C++ only!
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include "M17ConvolutionalEncoder.h"
|
||||
#include "M17LinkSetupFrame.h"
|
||||
#include "M17StreamFrame.h"
|
||||
|
||||
/**
|
||||
* M17 frame encoder.
|
||||
*/
|
||||
class M17FrameEncoder
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
M17FrameEncoder();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~M17FrameEncoder();
|
||||
|
||||
/**
|
||||
* Clear the internal data structures, reset the counter for frame sequence
|
||||
* number in stream data frames and reset the counter for LICH segment
|
||||
* sequence.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* Encode a Link Setup Frame into a frame ready for transmission, prepended
|
||||
* with the corresponding sync word. Link Setup data is also copied to an
|
||||
* internal data structure and used to generate the LICH segments to be
|
||||
* placed in each stream frame.
|
||||
*
|
||||
* @param lsf: Link Setup Frame to be encoded.
|
||||
* @param output: destination buffer for the encoded data.
|
||||
*/
|
||||
void encodeLsf(M17LinkSetupFrame& lsf, frame_t& output);
|
||||
|
||||
/**
|
||||
* Prepare and encode a stream data frame into a frame ready for
|
||||
* transmission, prepended with the corresponding sync word. The frame
|
||||
* sequence number is incremented by one on each function call and cleared
|
||||
* when the reset() function is called. The LICH segment field is filled
|
||||
* with data obtained from the latest Link Setup Frame encoded.
|
||||
*
|
||||
* @param payload: payload data.
|
||||
* @param output: destination buffer for the encoded data.
|
||||
* @param isLast: if true, current frame is marked as the last one to be
|
||||
* transmitted.
|
||||
* @return the frame sequence number.
|
||||
*/
|
||||
uint16_t encodeStreamFrame(const payload_t& payload, frame_t& output,
|
||||
const bool isLast = false);
|
||||
private:
|
||||
|
||||
M17ConvolutionalEncoder encoder; ///< Convolutional encoder.
|
||||
std::array< lich_t, 6 > lichSegments; ///< Encoded LSF chunks for LICH generation.
|
||||
uint8_t currentLich; ///< Index of current LSF chunk.
|
||||
uint16_t streamFrameNumber; ///< Current frame number.
|
||||
};
|
||||
|
||||
#endif /* M17FRAMEENCODER_H */
|
|
@ -38,7 +38,7 @@ void M17FrameDecoder::reset()
|
|||
streamFrame.clear();
|
||||
}
|
||||
|
||||
M17FrameType M17FrameDecoder::decodeFrame(const std::array< uint8_t, 48 >& frame)
|
||||
M17FrameType M17FrameDecoder::decodeFrame(const frame_t& frame)
|
||||
{
|
||||
std::array< uint8_t, 2 > syncWord;
|
||||
std::array< uint8_t, 46 > data;
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2022 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Niccolò Izzo IU2KIN *
|
||||
* Frederik Saraci IU2NRO *
|
||||
* Silvano Seva IU2KWO *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/> *
|
||||
***************************************************************************/
|
||||
|
||||
#include <M17/M17CodePuncturing.h>
|
||||
#include <M17/M17Decorrelator.h>
|
||||
#include <M17/M17Interleaver.h>
|
||||
#include <M17/M17FrameEncoder.h>
|
||||
|
||||
M17FrameEncoder::M17FrameEncoder() : currentLich(0), streamFrameNumber(0)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
M17FrameEncoder::~M17FrameEncoder()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void M17FrameEncoder::reset()
|
||||
{
|
||||
// Clear counters
|
||||
currentLich = 0;
|
||||
streamFrameNumber = 0;
|
||||
|
||||
// Clear all the LICH segments
|
||||
for(auto& segment : lichSegments)
|
||||
{
|
||||
segment.fill(0x00);
|
||||
}
|
||||
}
|
||||
|
||||
void M17FrameEncoder::encodeLsf(M17LinkSetupFrame& lsf, frame_t& output)
|
||||
{
|
||||
// Ensure the LSF to be encoded has a valid CRC field
|
||||
lsf.updateCrc();
|
||||
|
||||
// Generate the Golay(24,12) LICH segments
|
||||
for(size_t i = 0; i < lichSegments.size(); i++)
|
||||
{
|
||||
lichSegments[i] = lsf.generateLichSegment(i);
|
||||
}
|
||||
|
||||
// Encode the LSF, then puncture and decorrelate its data
|
||||
std::array<uint8_t, 61> encoded;
|
||||
encoder.reset();
|
||||
encoder.encode(lsf.getData(), encoded.data(), sizeof(M17LinkSetupFrame));
|
||||
encoded[60] = encoder.flush();
|
||||
|
||||
std::array<uint8_t, 46> punctured;
|
||||
puncture(encoded, punctured, LSF_PUNCTURE);
|
||||
interleave(punctured);
|
||||
decorrelate(punctured);
|
||||
|
||||
// Copy data to output buffer, prepended with sync word.
|
||||
auto it = std::copy(LSF_SYNC_WORD.begin(), LSF_SYNC_WORD.end(),
|
||||
output.begin());
|
||||
std::copy(punctured.begin(), punctured.end(), it);
|
||||
}
|
||||
|
||||
uint16_t M17FrameEncoder::encodeStreamFrame(const payload_t& payload,
|
||||
frame_t& output, const bool isLast)
|
||||
{
|
||||
M17StreamFrame streamFrame;
|
||||
|
||||
streamFrame.setFrameNumber(streamFrameNumber);
|
||||
streamFrameNumber = (streamFrameNumber + 1) & 0x07FF;
|
||||
if(isLast) streamFrame.lastFrame();
|
||||
std::copy(payload.begin(), payload.end(), streamFrame.payload().begin());
|
||||
|
||||
// Encode frame
|
||||
std::array<uint8_t, 37> encoded;
|
||||
encoder.reset();
|
||||
encoder.encode(streamFrame.getData(), encoded.data(), sizeof(M17StreamFrame));
|
||||
encoded[36] = encoder.flush();
|
||||
|
||||
std::array<uint8_t, 34> punctured;
|
||||
puncture(encoded, punctured, DATA_PUNCTURE);
|
||||
|
||||
// Add LICH segment to coded data
|
||||
std::array<uint8_t, 46> frame;
|
||||
auto it = std::copy(lichSegments[currentLich].begin(),
|
||||
lichSegments[currentLich].end(),
|
||||
frame.begin());
|
||||
std::copy(punctured.begin(), punctured.end(), it);
|
||||
|
||||
// Increment LICH counter after copy
|
||||
currentLich = (currentLich + 1) % lichSegments.size();
|
||||
|
||||
interleave(frame);
|
||||
decorrelate(frame);
|
||||
|
||||
// Copy data to output buffer, prepended with sync word.
|
||||
auto oIt = std::copy(STREAM_SYNC_WORD.begin(), STREAM_SYNC_WORD.end(),
|
||||
output.begin());
|
||||
std::copy(frame.begin(), frame.end(), oIt);
|
||||
|
||||
return streamFrame.getFrameNumber();
|
||||
}
|
Ładowanie…
Reference in New Issue