/*************************************************************************** * 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 * ***************************************************************************/ #include #include #include #include using namespace M17; 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 encoded; encoder.reset(); encoder.encode(lsf.getData(), encoded.data(), sizeof(M17LinkSetupFrame)); encoded[60] = encoder.flush(); std::array 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 encoded; encoder.reset(); encoder.encode(streamFrame.getData(), encoded.data(), sizeof(M17StreamFrame)); encoded[36] = encoder.flush(); std::array punctured; puncture(encoded, punctured, DATA_PUNCTURE); // Add LICH segment to coded data std::array 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(); }