#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)); }