Files
mpsk_rx_gui/Source/Transmitter.cpp
T
2022-06-24 08:55:03 +00:00

208 lines
4.4 KiB
C++

#include "Transmitter.hpp"
Transmitter::Transmitter(void)
: Thread("Transmitter")
, m_formatter()
, m_symbolizer()
, m_symbolMapper()
, m_bufferSize(0)
, m_samplerate(192000)
, m_symbolrate(48000)
, m_numBitPerSymbol(2)
, m_carrierFreq(48000)
, m_txBuf(0, 2)
, m_symCount(0)
, m_pCoeffRCF(0)
, m_upsampleFactor(1)
, m_buffer_data_in(BUFFERSIZE_DATA)
, m_buffer_symbol_in(BUFFERSIZE_DATA+64)
, m_buffer_symbol_out(BUFFERSIZE_SYMBOL)
{
SymMapInit(&m_symbolMapper, m_numBitPerSymbol, MAP_MODE_QAM);
m_duc.init(m_carrierFreq/m_samplerate, 0);
paramChanged();
// Setup Buffers
bufferResize(2048);
// Formatter
m_formatter.buffer_in_add(&m_buffer_data_in);
m_formatter.buffer_out_add(&m_buffer_symbol_in);
m_formatter.prepare();
// Symbolizer
m_symbolizer.buffer_in_add(&m_buffer_symbol_in);
m_symbolizer.buffer_out_add(&m_buffer_symbol_out);
m_symbolizer.prepare();
}
Transmitter::~Transmitter(void)
{
stopThread(1000);
if (m_pCoeffRCF)
delete m_pCoeffRCF;
m_pCoeffRCF = nullptr;
SymMapFree(&m_symbolMapper);
}
// Thread
void Transmitter::run()
{
uint64_t data = 0;
while(!threadShouldExit())
{
// Create Data
while(m_buffer_data_in.free())
{
m_buffer_data_in.write((uint8_t*)&data, sizeof(data));
data++;
}
// Format
m_formatter.process();
// Symbolize
m_symbolizer.process();
// Transmit symbols
transmit();
}
}
// Transmit symbols
void Transmitter::transmit()
{
while(m_buffer_symbol_out.len())
{
symbol_t symbol;
m_buffer_symbol_out.read(&symbol, 1);
m_bufferSym[m_symCount++] = toComplexScalar(SymMapMap(&m_symbolMapper, symbol));
if (m_symCount >= m_bufferSize/m_upsampleFactor)
{
uint32_t symCountRcf = m_firUp.process(m_bufferSymRcf, m_bufferSym, m_symCount);
m_duc.mixComplexRealV(m_bufferRF, m_bufferSymRcf, ComplexScalar(m_kRcf/4, m_kRcf/4), symCountRcf);
m_txBuf.write(m_bufferRF, symCountRcf);
m_symCount = 0;
}
}
}
void Transmitter::paramChanged()
{
uint32_t n_mf;
const ScopedLock sl (m_lock);
m_symbolizer.setNumBitsPerSymbol(m_numBitPerSymbol);
SymMapReinit(&m_symbolMapper, m_numBitPerSymbol, MAP_MODE_QAM);
m_upsampleFactor = (uint32_t)(m_samplerate/m_symbolrate + 0.5);
n_mf = (uint32_t)(TRANSMITTER_RCF_OVERSAMPLING*m_upsampleFactor) + 1;
if (m_pCoeffRCF)
{
delete m_pCoeffRCF;
}
m_pCoeffRCF = new radio_float_t[n_mf];
m_kRcf = CalcFirSRRC(m_pCoeffRCF, (radio_float_t)m_samplerate, (radio_float_t)2.0/m_symbolrate, TRANSMITTER_RCF_ROLLOFF, n_mf);
m_firUp.init(m_upsampleFactor, m_pCoeffRCF, n_mf);
m_duc.init(m_carrierFreq/m_samplerate, 0);
symbol_t sync_syms[4]; // 4 Corners
sync_syms[0] = SymMapDemap(&m_symbolMapper, toCpx(ComplexScalar(+1,+1)));
sync_syms[1] = SymMapDemap(&m_symbolMapper, toCpx(ComplexScalar(-1,+1)));
sync_syms[2] = SymMapDemap(&m_symbolMapper, toCpx(ComplexScalar(-1,-1)));
sync_syms[3] = SymMapDemap(&m_symbolMapper, toCpx(ComplexScalar(+1,-1)));
}
void Transmitter::bufferResize(uint32_t size)
{
stopThread(10000);
m_bufferSize = size;
m_txBuf.resize(size, 8);
m_bufferRF.resize(size);
m_bufferSym.resize(size);
m_bufferSymRcf.resize(size);
m_symCount = 0;
startThread(0);
}
void Transmitter::reset()
{
}
void Transmitter::setBuffersize(uint32_t size)
{
bufferResize(size);
paramChanged();
}
void Transmitter::setSamplerate(radio_float_t samplerate_hz)
{
m_samplerate = samplerate_hz;
m_carrierFreq = samplerate_hz/4;
m_symbolrate = samplerate_hz/4;
paramChanged();
}
void Transmitter::setCarrierFrequency(radio_float_t frequency_hz)
{
const ScopedLock sl (m_lock);
m_carrierFreq = frequency_hz;
m_duc.init(m_carrierFreq/m_samplerate, 0);
}
radio_float_t Transmitter::getCarrierFrequency()
{
return m_carrierFreq;
}
void Transmitter::setSymbolRate(radio_float_t symbolrate_bit_per_sec)
{
m_symbolrate = symbolrate_bit_per_sec;
paramChanged();
}
radio_float_t Transmitter::getSymbolRate()
{
return m_symbolrate;
}
void Transmitter::setNumBitPerSymbol(uint32_t numBitPerSymbol)
{
m_numBitPerSymbol = numBitPerSymbol;
if (m_numBitPerSymbol > 16)
m_numBitPerSymbol = 16;
paramChanged();
}
void Transmitter::getData(float *pRF, uint32_t len)
{
uint32_t res;
if (len != m_bufferSize)
{
memset(pRF, 0, len*sizeof(float));
return;
}
res = m_txBuf.read(pRF);
if (!res)
memset(pRF, 0, len*sizeof(float));
}