Reorganized code for M17 transmission: removed M17Transmitter class, use M17FrameEncoder to assemble LSF and data frames, modified API of M17Modulator class.
This commit is contained in:
parent
48cd81ee7c
commit
a22aceb576
|
|
@ -57,7 +57,6 @@ openrtx_src = ['openrtx/src/core/state.c',
|
||||||
'openrtx/src/protocols/M17/M17Demodulator.cpp',
|
'openrtx/src/protocols/M17/M17Demodulator.cpp',
|
||||||
'openrtx/src/protocols/M17/M17FrameEncoder.cpp',
|
'openrtx/src/protocols/M17/M17FrameEncoder.cpp',
|
||||||
'openrtx/src/protocols/M17/M17FrameDecoder.cpp',
|
'openrtx/src/protocols/M17/M17FrameDecoder.cpp',
|
||||||
'openrtx/src/protocols/M17/M17Transmitter.cpp',
|
|
||||||
'openrtx/src/protocols/M17/M17LinkSetupFrame.cpp']
|
'openrtx/src/protocols/M17/M17LinkSetupFrame.cpp']
|
||||||
|
|
||||||
openrtx_inc = ['openrtx/include',
|
openrtx_inc = ['openrtx/include',
|
||||||
|
|
|
||||||
|
|
@ -62,31 +62,32 @@ public:
|
||||||
*/
|
*/
|
||||||
void terminate();
|
void terminate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start baseband transmission and send an 80ms preamble.
|
||||||
|
*/
|
||||||
|
void start();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate and transmit the baseband signal obtained by 4FSK modulation of
|
* Generate and transmit the baseband signal obtained by 4FSK modulation of
|
||||||
* a given block of data. When called for the first time, this function
|
* a given block of data.
|
||||||
* starts baseband transmission.
|
|
||||||
*
|
*
|
||||||
* @param sync: synchronisation word to be prepended to data block.
|
* @param frame: M17 frame to be sent.
|
||||||
* @param data: data block to be transmitted.
|
|
||||||
* @param isLast: flag signalling that current block is the last one being
|
* @param isLast: flag signalling that current block is the last one being
|
||||||
* transmitted.
|
* transmitted.
|
||||||
*/
|
*/
|
||||||
void send(const std::array< uint8_t, 2 >& sync,
|
void send(const frame_t& frame, const bool isLast);
|
||||||
const std::array< uint8_t, 46 >& data,
|
|
||||||
const bool isLast = false);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate baseband stream from symbol stream.
|
* Generate baseband stream from symbol stream.
|
||||||
*/
|
*/
|
||||||
void generateBaseband();
|
void symbolsToBaseband();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emit the baseband stream towards the output stage, platform dependent.
|
* Emit the baseband stream towards the output stage, platform dependent.
|
||||||
*/
|
*/
|
||||||
void emitBaseband();
|
void sendBaseband();
|
||||||
|
|
||||||
static constexpr size_t M17_TX_SAMPLE_RATE = 48000;
|
static constexpr size_t M17_TX_SAMPLE_RATE = 48000;
|
||||||
static constexpr size_t M17_SAMPLES_PER_SYMBOL = M17_TX_SAMPLE_RATE / M17_SYMBOL_RATE;
|
static constexpr size_t M17_SAMPLES_PER_SYMBOL = M17_TX_SAMPLE_RATE / M17_SYMBOL_RATE;
|
||||||
|
|
@ -100,7 +101,7 @@ private:
|
||||||
static constexpr float M17_RRC_OFFSET = 0.0f;
|
static constexpr float M17_RRC_OFFSET = 0.0f;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::array< int16_t, M17_FRAME_SYMBOLS > symbols;
|
std::array< int8_t, M17_FRAME_SYMBOLS > symbols;
|
||||||
std::unique_ptr< int16_t[] > baseband_buffer; ///< Buffer for baseband audio handling.
|
std::unique_ptr< int16_t[] > baseband_buffer; ///< Buffer for baseband audio handling.
|
||||||
stream_sample_t *idleBuffer; ///< Half baseband buffer, free for processing.
|
stream_sample_t *idleBuffer; ///< Half baseband buffer, free for processing.
|
||||||
streamId outStream; ///< Baseband output stream ID.
|
streamId outStream; ///< Baseband output stream ID.
|
||||||
|
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
* Copyright (C) 2021 - 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 M17TRANSMITTER_H
|
|
||||||
#define M17TRANSMITTER_H
|
|
||||||
|
|
||||||
#ifndef __cplusplus
|
|
||||||
#error This header is C++ only!
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <array>
|
|
||||||
#include "M17ConvolutionalEncoder.hpp"
|
|
||||||
#include "M17LinkSetupFrame.hpp"
|
|
||||||
#include "M17StreamFrame.hpp"
|
|
||||||
#include "M17Modulator.hpp"
|
|
||||||
|
|
||||||
namespace M17
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* M17 transmitter.
|
|
||||||
*/
|
|
||||||
class M17Transmitter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param modulator: reference to M17 4FSK modulator driver.
|
|
||||||
*/
|
|
||||||
M17Transmitter(M17Modulator& modulator);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor.
|
|
||||||
*/
|
|
||||||
~M17Transmitter();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start a new data stream with broadcast destination callsign.
|
|
||||||
*
|
|
||||||
* @param src: source callsign.
|
|
||||||
*/
|
|
||||||
void start(const std::string& src);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start a new data stream with given destination callsign. If destination
|
|
||||||
* callsing is empty, the stream falls back to broadcast transmission.
|
|
||||||
*
|
|
||||||
* @param src: source callsign.
|
|
||||||
* @param dst: destination callsign.
|
|
||||||
*/
|
|
||||||
void start(const std::string& src, const std::string& dst);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a block of data.
|
|
||||||
*
|
|
||||||
* @param payload: payload data.
|
|
||||||
* @param isLast: if true, current frame is marked as the last one to be
|
|
||||||
* transmitted.
|
|
||||||
*/
|
|
||||||
void send(const payload_t& payload, const bool isLast = false);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
M17ConvolutionalEncoder encoder; ///< Convolutional encoder.
|
|
||||||
M17LinkSetupFrame lsf; ///< Link Setup Frame handler.
|
|
||||||
M17StreamFrame dataFrame; ///< Data frame Handler.
|
|
||||||
M17Modulator& modulator; ///< 4FSK modulator.
|
|
||||||
std::array< lich_t, 6 > lichSegments; ///< Encoded LSF chunks for LICH generation.
|
|
||||||
uint8_t currentLich; ///< Index of current LSF chunk.
|
|
||||||
uint16_t frameNumber; ///< Current frame number.
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* M17 */
|
|
||||||
|
|
||||||
#endif /* M17TRANSMITTER_H */
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
#define OPMODE_M17_H
|
#define OPMODE_M17_H
|
||||||
|
|
||||||
#include <M17/M17FrameDecoder.hpp>
|
#include <M17/M17FrameDecoder.hpp>
|
||||||
#include <M17/M17Transmitter.hpp>
|
#include <M17/M17FrameEncoder.hpp>
|
||||||
#include <M17/M17Demodulator.hpp>
|
#include <M17/M17Demodulator.hpp>
|
||||||
#include <M17/M17Modulator.hpp>
|
#include <M17/M17Modulator.hpp>
|
||||||
#include "OpMode.hpp"
|
#include "OpMode.hpp"
|
||||||
|
|
@ -126,8 +126,8 @@ private:
|
||||||
bool locked; ///< Demodulator locked on data stream.
|
bool locked; ///< Demodulator locked on data stream.
|
||||||
M17::M17Modulator modulator; ///< M17 modulator.
|
M17::M17Modulator modulator; ///< M17 modulator.
|
||||||
M17::M17Demodulator demodulator; ///< M17 demodulator.
|
M17::M17Demodulator demodulator; ///< M17 demodulator.
|
||||||
M17::M17Transmitter m17Tx; ///< M17 transmission manager.
|
|
||||||
M17::M17FrameDecoder decoder; ///< M17 frame decoder
|
M17::M17FrameDecoder decoder; ///< M17 frame decoder
|
||||||
|
M17::M17FrameEncoder encoder; ///< M17 frame encoder
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* OPMODE_M17_H */
|
#endif /* OPMODE_M17_H */
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,7 @@ void M17Modulator::init()
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Allocate a chunk of memory to contain two complete buffers for baseband
|
* Allocate a chunk of memory to contain two complete buffers for baseband
|
||||||
* audio. Split this chunk in two separate blocks for double buffering using
|
* audio.
|
||||||
* placement new.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
baseband_buffer = std::make_unique< int16_t[] >(2 * M17_FRAME_SAMPLES);
|
baseband_buffer = std::make_unique< int16_t[] >(2 * M17_FRAME_SAMPLES);
|
||||||
|
|
@ -72,30 +71,55 @@ void M17Modulator::terminate()
|
||||||
baseband_buffer.reset();
|
baseband_buffer.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void M17Modulator::send(const std::array< uint8_t, 2 >& sync,
|
void M17::M17Modulator::start()
|
||||||
const std::array< uint8_t, 46 >& data,
|
|
||||||
const bool isLast)
|
|
||||||
{
|
{
|
||||||
auto sync1 = byteToSymbols(sync[0]);
|
if(txRunning) return;
|
||||||
auto sync2 = byteToSymbols(sync[1]);
|
|
||||||
|
|
||||||
auto it = std::copy(sync1.begin(), sync1.end(), symbols.begin());
|
txRunning = true;
|
||||||
it = std::copy(sync2.begin(), sync2.end(), it);
|
stopTx = false;
|
||||||
|
|
||||||
for(size_t i = 0; i < data.size(); i++)
|
// Fill symbol buffer with preamble, made of alternated +3 and -3 symbols
|
||||||
|
for(size_t i = 0; i < symbols.size(); i += 2)
|
||||||
{
|
{
|
||||||
auto sym = byteToSymbols(data[i]);
|
symbols[i] = +3;
|
||||||
|
symbols[i + 1] = -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate baseband signal and then start transmission
|
||||||
|
symbolsToBaseband();
|
||||||
|
#ifndef PLATFORM_LINUX
|
||||||
|
outStream = outputStream_start(SINK_RTX, PRIO_TX, baseband_buffer.get(),
|
||||||
|
2*M17_FRAME_SAMPLES, BUF_CIRC_DOUBLE,
|
||||||
|
M17_TX_SAMPLE_RATE);
|
||||||
|
idleBuffer = outputStream_getIdleBuffer(outStream);
|
||||||
|
#else
|
||||||
|
sendBaseband();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Repeat baseband generation and transmission, this makes the preamble to
|
||||||
|
// be long 80ms (two frames)
|
||||||
|
symbolsToBaseband();
|
||||||
|
sendBaseband();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void M17Modulator::send(const frame_t& frame, const bool isLast)
|
||||||
|
{
|
||||||
|
auto it = symbols.begin();
|
||||||
|
for(size_t i = 0; i < frame.size(); i++)
|
||||||
|
{
|
||||||
|
auto sym = byteToSymbols(frame[i]);
|
||||||
it = std::copy(sym.begin(), sym.end(), it);
|
it = std::copy(sym.begin(), sym.end(), it);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If last frame, signal stop of transmission
|
// If last frame, signal stop of transmission
|
||||||
if(isLast) stopTx = true;
|
if(isLast) stopTx = true;
|
||||||
|
|
||||||
generateBaseband();
|
symbolsToBaseband();
|
||||||
emitBaseband();
|
sendBaseband();
|
||||||
}
|
}
|
||||||
|
|
||||||
void M17Modulator::generateBaseband()
|
void M17Modulator::symbolsToBaseband()
|
||||||
{
|
{
|
||||||
memset(idleBuffer, 0x00, M17_FRAME_SAMPLES * sizeof(stream_sample_t));
|
memset(idleBuffer, 0x00, M17_FRAME_SAMPLES * sizeof(stream_sample_t));
|
||||||
|
|
||||||
|
|
@ -110,33 +134,20 @@ void M17Modulator::generateBaseband()
|
||||||
elem = M17::rrc_48k(elem * M17_RRC_GAIN) - M17_RRC_OFFSET;
|
elem = M17::rrc_48k(elem * M17_RRC_GAIN) - M17_RRC_OFFSET;
|
||||||
idleBuffer[i] = static_cast< int16_t >(elem);
|
idleBuffer[i] = static_cast< int16_t >(elem);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef PLATFORM_LINUX
|
|
||||||
void M17Modulator::emitBaseband()
|
|
||||||
{
|
|
||||||
#if defined(PLATFORM_MD3x0) || defined(PLATFORM_MDUV3x0)
|
#if defined(PLATFORM_MD3x0) || defined(PLATFORM_MDUV3x0)
|
||||||
dsp_pwmCompensate(&pwmFilterState, idleBuffer, M17_FRAME_SAMPLES);
|
dsp_pwmCompensate(&pwmFilterState, idleBuffer, M17_FRAME_SAMPLES);
|
||||||
dsp_invertPhase(idleBuffer, M17_FRAME_SAMPLES);
|
dsp_invertPhase(idleBuffer, M17_FRAME_SAMPLES);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if(txRunning == false)
|
#ifndef PLATFORM_LINUX
|
||||||
{
|
void M17Modulator::sendBaseband()
|
||||||
// First run, start transmission
|
{
|
||||||
outStream = outputStream_start(SINK_RTX,
|
if(txRunning == false) return;
|
||||||
PRIO_TX,
|
|
||||||
baseband_buffer.get(),
|
// Transmission is ongoing, syncronise with stream end before proceeding
|
||||||
2*M17_FRAME_SAMPLES,
|
outputStream_sync(outStream, true);
|
||||||
BUF_CIRC_DOUBLE,
|
|
||||||
M17_TX_SAMPLE_RATE);
|
|
||||||
txRunning = true;
|
|
||||||
stopTx = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Transmission is ongoing, syncronise with stream end before proceeding
|
|
||||||
outputStream_sync(outStream, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if transmission stop is requested, if so stop the output stream
|
// Check if transmission stop is requested, if so stop the output stream
|
||||||
// and wait until its effective termination.
|
// and wait until its effective termination.
|
||||||
|
|
@ -157,7 +168,7 @@ void M17Modulator::emitBaseband()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void M17Modulator::emitBaseband()
|
void M17Modulator::sendBaseband()
|
||||||
{
|
{
|
||||||
FILE *outfile = fopen("/tmp/m17_output.raw", "ab");
|
FILE *outfile = fopen("/tmp/m17_output.raw", "ab");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
* Copyright (C) 2021 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.hpp>
|
|
||||||
#include <M17/M17Decorrelator.hpp>
|
|
||||||
#include <M17/M17Interleaver.hpp>
|
|
||||||
#include <M17/M17Transmitter.hpp>
|
|
||||||
|
|
||||||
using namespace M17;
|
|
||||||
|
|
||||||
M17Transmitter::M17Transmitter(M17Modulator& modulator) : modulator(modulator),
|
|
||||||
currentLich(0), frameNumber(0)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
M17Transmitter::~M17Transmitter()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void M17Transmitter::start(const std::string& src)
|
|
||||||
{
|
|
||||||
// Just call start() with an empty string for destination callsign.
|
|
||||||
std::string empty;
|
|
||||||
start(src, empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
void M17Transmitter::start(const std::string& src, const std::string& dst)
|
|
||||||
{
|
|
||||||
// Reset LICH and frame counters
|
|
||||||
currentLich = 0;
|
|
||||||
frameNumber = 0;
|
|
||||||
|
|
||||||
// Fill the Link Setup Frame
|
|
||||||
lsf.clear();
|
|
||||||
lsf.setSource(src);
|
|
||||||
if(!dst.empty()) lsf.setDestination(dst);
|
|
||||||
|
|
||||||
streamType_t type;
|
|
||||||
type.fields.stream = 1; // Stream
|
|
||||||
type.fields.dataType = 2; // Voice data
|
|
||||||
type.fields.CAN = 0; // Channel access number
|
|
||||||
|
|
||||||
lsf.setType(type);
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Send preamble
|
|
||||||
std::array<uint8_t, 2> preamble_sync;
|
|
||||||
std::array<uint8_t, 46> preamble_bytes;
|
|
||||||
preamble_sync.fill(0x77);
|
|
||||||
preamble_bytes.fill(0x77);
|
|
||||||
modulator.send(preamble_sync, preamble_bytes);
|
|
||||||
|
|
||||||
// Send LSF
|
|
||||||
modulator.send(LSF_SYNC_WORD, punctured);
|
|
||||||
}
|
|
||||||
|
|
||||||
void M17Transmitter::send(const payload_t& payload, const bool isLast)
|
|
||||||
{
|
|
||||||
dataFrame.clear();
|
|
||||||
dataFrame.setFrameNumber(frameNumber);
|
|
||||||
frameNumber = (frameNumber + 1) & 0x07FF;
|
|
||||||
if(isLast) dataFrame.lastFrame();
|
|
||||||
std::copy(payload.begin(), payload.end(), dataFrame.payload().begin());
|
|
||||||
|
|
||||||
// Encode frame
|
|
||||||
std::array<uint8_t, 37> encoded;
|
|
||||||
encoder.reset();
|
|
||||||
encoder.encode(dataFrame.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 and send
|
|
||||||
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);
|
|
||||||
|
|
||||||
modulator.send(STREAM_SYNC_WORD, frame, isLast);
|
|
||||||
}
|
|
||||||
|
|
@ -29,8 +29,7 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace M17;
|
using namespace M17;
|
||||||
|
|
||||||
OpMode_M17::OpMode_M17() : startRx(false), startTx(false), locked(false),
|
OpMode_M17::OpMode_M17() : startRx(false), startTx(false), locked(false)
|
||||||
m17Tx(modulator)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -190,18 +189,37 @@ void OpMode_M17::rxState(rtxStatus_t *const status)
|
||||||
|
|
||||||
void OpMode_M17::txState(rtxStatus_t *const status)
|
void OpMode_M17::txState(rtxStatus_t *const status)
|
||||||
{
|
{
|
||||||
|
frame_t m17Frame;
|
||||||
|
|
||||||
if(startTx)
|
if(startTx)
|
||||||
{
|
{
|
||||||
|
startTx = false;
|
||||||
|
|
||||||
|
std::string src(status->source_address);
|
||||||
|
std::string dst(status->destination_address);
|
||||||
|
M17LinkSetupFrame lsf;
|
||||||
|
|
||||||
|
lsf.clear();
|
||||||
|
lsf.setSource(src);
|
||||||
|
if(!dst.empty()) lsf.setDestination(dst);
|
||||||
|
|
||||||
|
streamType_t type;
|
||||||
|
type.fields.stream = 1; // Stream
|
||||||
|
type.fields.dataType = 2; // Voice data
|
||||||
|
type.fields.CAN = 0; // Channel access number
|
||||||
|
|
||||||
|
lsf.setType(type);
|
||||||
|
lsf.updateCrc();
|
||||||
|
|
||||||
|
encoder.reset();
|
||||||
|
encoder.encodeLsf(lsf, m17Frame);
|
||||||
|
|
||||||
audio_enableMic();
|
audio_enableMic();
|
||||||
codec_startEncode(SOURCE_MIC);
|
codec_startEncode(SOURCE_MIC);
|
||||||
|
|
||||||
radio_enableTx();
|
radio_enableTx();
|
||||||
|
|
||||||
std::string source_address(status->source_address);
|
modulator.start();
|
||||||
std::string destination_address(status->destination_address);
|
modulator.send(m17Frame, false);
|
||||||
m17Tx.start(source_address, destination_address);
|
|
||||||
|
|
||||||
startTx = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
payload_t dataFrame;
|
payload_t dataFrame;
|
||||||
|
|
@ -218,5 +236,6 @@ void OpMode_M17::txState(rtxStatus_t *const status)
|
||||||
status->opStatus = OFF;
|
status->opStatus = OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
m17Tx.send(dataFrame, lastFrame);
|
encoder.encodeStreamFrame(dataFrame, m17Frame, lastFrame);
|
||||||
|
modulator.send(m17Frame, lastFrame);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue