diff options
-rw-r--r-- | src/Buffer.h | 1 | ||||
-rw-r--r-- | src/ConfigParser.cpp | 24 | ||||
-rw-r--r-- | src/ConfigParser.h | 8 | ||||
-rw-r--r-- | src/DabMod.cpp | 18 | ||||
-rw-r--r-- | src/DabModulator.cpp | 96 | ||||
-rw-r--r-- | src/FormatConverter.cpp | 142 | ||||
-rw-r--r-- | src/FormatConverter.h | 9 | ||||
-rw-r--r-- | src/GuardIntervalInserter.cpp | 23 | ||||
-rw-r--r-- | src/GuardIntervalInserter.h | 5 | ||||
-rw-r--r-- | src/OfdmGenerator.cpp | 24 |
10 files changed, 213 insertions, 137 deletions
diff --git a/src/Buffer.h b/src/Buffer.h index f6c94e0..bf3b5f4 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -40,6 +40,7 @@ typedef std::complex<float> complexf; using fixed_16 = fpm::fixed<std::int16_t, std::int32_t, 6>; typedef std::complex<fixed_16> complexfix; +typedef std::complex<fpm::fixed_16_16> complexfix_wide; /* Buffer is a container for a byte array, which is memory-aligned * to 32 bytes for SSE performance. diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index a48f7e7..5d9f6f3 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -65,6 +65,27 @@ static GainMode parse_gainmode(const std::string &gainMode_setting) throw std::runtime_error("Configuration error"); } +static FFTEngine parse_fft_engine(const std::string &fft_engine_setting) +{ + string fft_engine_minuscule(fft_engine_setting); + std::transform(fft_engine_minuscule.begin(), fft_engine_minuscule.end(), + fft_engine_minuscule.begin(), ::tolower); + + if (fft_engine_minuscule == "fftw") { + return FFTEngine::FFTW; + } + else if (fft_engine_minuscule == "kiss") { + return FFTEngine::KISS; + } + else if (fft_engine_minuscule == "dexter") { + return FFTEngine::DEXTER; + } + + cerr << "Modulator fft_engine setting '" << fft_engine_setting << + "' not recognised." << endl; + throw std::runtime_error("Configuration error"); +} + static void parse_configfile( const std::string& configuration_file, mod_settings_t& mod_settings) @@ -154,7 +175,8 @@ static void parse_configfile( mod_settings.showProcessTime); // modulator parameters: - mod_settings.fixedPoint = pt.GetInteger("modulator.fixed_point", mod_settings.fixedPoint); + const string fft_engine_setting = pt.Get("modulator.fft_engine", "fftw"); + mod_settings.fftEngine = parse_fft_engine(fft_engine_setting); const string gainMode_setting = pt.Get("modulator.gainmode", "var"); mod_settings.gainMode = parse_gainmode(gainMode_setting); diff --git a/src/ConfigParser.h b/src/ConfigParser.h index f3a2af9..3bacfdd 100644 --- a/src/ConfigParser.h +++ b/src/ConfigParser.h @@ -36,6 +36,12 @@ #include "TII.h" #include "output/SDRDevice.h" +enum class FFTEngine { + FFTW, // floating point in software + KISS, // fixed-point in software + DEXTER // fixed-point in FPGA +}; + struct mod_settings_t { std::string startupCheck; @@ -51,7 +57,7 @@ struct mod_settings_t { bool useLimeOutput = false; bool useBladeRFOutput = false; - bool fixedPoint = false; + FFTEngine fftEngine = FFTEngine::FFTW; size_t outputRate = 2048000; size_t clockRate = 0; diff --git a/src/DabMod.cpp b/src/DabMod.cpp index 4726df9..361e0d4 100644 --- a/src/DabMod.cpp +++ b/src/DabMod.cpp @@ -252,7 +252,7 @@ static shared_ptr<ModOutput> prepare_output(mod_settings_t& s) shared_ptr<ModOutput> output; if (s.useFileOutput) { - if (s.fixedPoint) { + if (s.fftEngine != FFTEngine::FFTW) { // Intentionally ignore fileOutputFormat, it is always sc16 output = make_shared<OutputFile>(s.outputName, s.fileOutputShowMetadata); } @@ -292,7 +292,7 @@ static shared_ptr<ModOutput> prepare_output(mod_settings_t& s) else if (s.useUHDOutput) { s.normalise = 1.0f / normalise_factor; s.sdr_device_config.sampleRate = s.outputRate; - s.sdr_device_config.fixedPoint = s.fixedPoint; + s.sdr_device_config.fixedPoint = (s.fftEngine != FFTEngine::FFTW); auto uhddevice = make_shared<Output::UHD>(s.sdr_device_config); output = make_shared<Output::SDR>(s.sdr_device_config, uhddevice); rcs.enrol((Output::SDR*)output.get()); @@ -303,7 +303,7 @@ static shared_ptr<ModOutput> prepare_output(mod_settings_t& s) /* We normalise the same way as for the UHD output */ s.normalise = 1.0f / normalise_factor; s.sdr_device_config.sampleRate = s.outputRate; - if (s.fixedPoint) throw runtime_error("soapy fixed_point unsupported"); + if (s.fftEngine != FFTEngine::FFTW) throw runtime_error("soapy fixed_point unsupported"); auto soapydevice = make_shared<Output::Soapy>(s.sdr_device_config); output = make_shared<Output::SDR>(s.sdr_device_config, soapydevice); rcs.enrol((Output::SDR*)output.get()); @@ -323,7 +323,7 @@ static shared_ptr<ModOutput> prepare_output(mod_settings_t& s) else if (s.useLimeOutput) { /* We normalise the same way as for the UHD output */ s.normalise = 1.0f / normalise_factor; - if (s.fixedPoint) throw runtime_error("limesdr fixed_point unsupported"); + if (s.fftEngine != FFTEngine::FFTW) throw runtime_error("limesdr fixed_point unsupported"); s.sdr_device_config.sampleRate = s.outputRate; auto limedevice = make_shared<Output::Lime>(s.sdr_device_config); output = make_shared<Output::SDR>(s.sdr_device_config, limedevice); @@ -334,7 +334,7 @@ static shared_ptr<ModOutput> prepare_output(mod_settings_t& s) else if (s.useBladeRFOutput) { /* We normalise specifically for the BladeRF output : range [-2048; 2047] */ s.normalise = 2047.0f / normalise_factor; - if (s.fixedPoint) throw runtime_error("bladerf fixed_point unsupported"); + if (s.fftEngine != FFTEngine::FFTW) throw runtime_error("bladerf fixed_point unsupported"); s.sdr_device_config.sampleRate = s.outputRate; auto bladerfdevice = make_shared<Output::BladeRF>(s.sdr_device_config); output = make_shared<Output::SDR>(s.sdr_device_config, bladerfdevice); @@ -424,7 +424,7 @@ int launch_modulator(int argc, char* argv[]) rcs.enrol(&m); // Neither KISS FFT used for fixedpoint nor the FFT Accelerator used for DEXTER need planning. - if (not (mod_settings.fixedPoint or mod_settings.useDexterOutput)) { + if (mod_settings.fftEngine == FFTEngine::FFTW) { // This is mostly useful on ARM systems where FFTW planning takes some time. If we do it here // it will be done before the modulator starts up etiLog.level(debug) << "Running FFTW planning..."; @@ -446,9 +446,13 @@ int launch_modulator(int argc, char* argv[]) } std::string output_format; - if (mod_settings.fixedPoint) { + if (mod_settings.fftEngine == FFTEngine::KISS) { output_format = ""; //fixed point is native sc16, no converter needed } + else if (mod_settings.fftEngine == FFTEngine::DEXTER) { + output_format = "s16"; // FPGA FFT Engine outputs s32 + } + // else FFTW, i.e. floating point else if (mod_settings.useFileOutput and (mod_settings.fileOutputFormat == "s8" or mod_settings.fileOutputFormat == "u8" or diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp index 5f01725..4cbd0f5 100644 --- a/src/DabModulator.cpp +++ b/src/DabModulator.cpp @@ -142,13 +142,14 @@ int DabModulator::process(Buffer* dataOut) auto cifMux = make_shared<FrameMultiplexer>(m_etiSource); auto cifPart = make_shared<BlockPartitioner>(mode); - auto cifMap = make_shared<QpskSymbolMapper>(m_nbCarriers, m_settings.fixedPoint); - auto cifRef = make_shared<PhaseReference>(mode, m_settings.fixedPoint); - auto cifFreq = make_shared<FrequencyInterleaver>(mode, m_settings.fixedPoint); - auto cifDiff = make_shared<DifferentialModulator>(m_nbCarriers, m_settings.fixedPoint); + const bool fixedPoint = m_settings.fftEngine != FFTEngine::FFTW; + auto cifMap = make_shared<QpskSymbolMapper>(m_nbCarriers, fixedPoint); + auto cifRef = make_shared<PhaseReference>(mode, fixedPoint); + auto cifFreq = make_shared<FrequencyInterleaver>(mode, fixedPoint); + auto cifDiff = make_shared<DifferentialModulator>(m_nbCarriers, fixedPoint); auto cifNull = make_shared<NullSymbol>(m_nbCarriers, - m_settings.fixedPoint ? sizeof(complexfix) : sizeof(complexf)); + fixedPoint ? sizeof(complexfix) : sizeof(complexf)); auto cifSig = make_shared<SignalMultiplexer>(); // TODO this needs a review @@ -178,7 +179,7 @@ int DabModulator::process(Buffer* dataOut) shared_ptr<TII> tii; shared_ptr<PhaseReference> tiiRef; try { - if (m_settings.fixedPoint) { + if (fixedPoint) { etiLog.level(warn) << "TII does not yet support fixed point"; } else { @@ -186,7 +187,7 @@ int DabModulator::process(Buffer* dataOut) m_settings.dabMode, m_settings.tiiConfig); rcs.enrol(tii.get()); - tiiRef = make_shared<PhaseReference>(mode, m_settings.fixedPoint); + tiiRef = make_shared<PhaseReference>(mode, fixedPoint); } } catch (const TIIError& e) { @@ -195,40 +196,43 @@ int DabModulator::process(Buffer* dataOut) shared_ptr<ModPlugin> cifOfdm; - if (m_settings.useDexterOutput) { - cifOfdm = make_shared<OfdmGeneratorDEXTER>( - (1 + m_nbSymbols), - m_nbCarriers, - m_spacing, - m_settings.enableCfr, - m_settings.cfrClip, - m_settings.cfrErrorClip); - } - else if (m_settings.fixedPoint) { - cifOfdm = make_shared<OfdmGeneratorFixed>( - (1 + m_nbSymbols), - m_nbCarriers, - m_spacing, - m_settings.enableCfr, - m_settings.cfrClip, - m_settings.cfrErrorClip); - } - else { - auto ofdm = make_shared<OfdmGeneratorCF32>( - (1 + m_nbSymbols), - m_nbCarriers, - m_spacing, - m_settings.enableCfr, - m_settings.cfrClip, - m_settings.cfrErrorClip); - - rcs.enrol(ofdm.get()); - cifOfdm = ofdm; + switch (m_settings.fftEngine) { + case FFTEngine::FFTW: + { + auto ofdm = make_shared<OfdmGeneratorCF32>( + (1 + m_nbSymbols), + m_nbCarriers, + m_spacing, + m_settings.enableCfr, + m_settings.cfrClip, + m_settings.cfrErrorClip); + rcs.enrol(ofdm.get()); + cifOfdm = ofdm; + } + break; + case FFTEngine::KISS: + cifOfdm = make_shared<OfdmGeneratorFixed>( + (1 + m_nbSymbols), + m_nbCarriers, + m_spacing, + m_settings.enableCfr, + m_settings.cfrClip, + m_settings.cfrErrorClip); + break; + case FFTEngine::DEXTER: + cifOfdm = make_shared<OfdmGeneratorDEXTER>( + (1 + m_nbSymbols), + m_nbCarriers, + m_spacing, + m_settings.enableCfr, + m_settings.cfrClip, + m_settings.cfrErrorClip); + break; } shared_ptr<GainControl> cifGain; - if (not m_settings.fixedPoint) { + if (not fixedPoint) { cifGain = make_shared<GainControl>( m_spacing, m_settings.gainMode, @@ -241,12 +245,12 @@ int DabModulator::process(Buffer* dataOut) auto cifGuard = make_shared<GuardIntervalInserter>( m_nbSymbols, m_spacing, m_nullSize, m_symSize, - m_settings.ofdmWindowOverlap, m_settings.fixedPoint); + m_settings.ofdmWindowOverlap, m_settings.fftEngine); rcs.enrol(cifGuard.get()); shared_ptr<FIRFilter> cifFilter; if (not m_settings.filterTapsFilename.empty()) { - if (m_settings.fixedPoint) throw std::runtime_error("fixed point doesn't support fir filter"); + if (fixedPoint) throw std::runtime_error("fixed point doesn't support fir filter"); cifFilter = make_shared<FIRFilter>(m_settings.filterTapsFilename); rcs.enrol(cifFilter.get()); @@ -254,7 +258,7 @@ int DabModulator::process(Buffer* dataOut) shared_ptr<MemlessPoly> cifPoly; if (not m_settings.polyCoefFilename.empty()) { - if (m_settings.fixedPoint) throw std::runtime_error("fixed point doesn't support predistortion"); + if (fixedPoint) throw std::runtime_error("fixed point doesn't support predistortion"); cifPoly = make_shared<MemlessPoly>(m_settings.polyCoefFilename, m_settings.polyNumThreads); @@ -263,7 +267,7 @@ int DabModulator::process(Buffer* dataOut) shared_ptr<Resampler> cifRes; if (m_settings.outputRate != 2048000) { - if (m_settings.fixedPoint) throw std::runtime_error("fixed point doesn't support resampler"); + if (fixedPoint) throw std::runtime_error("fixed point doesn't support resampler"); cifRes = make_shared<Resampler>( 2048000, @@ -271,11 +275,13 @@ int DabModulator::process(Buffer* dataOut) m_spacing); } - if (not m_format.empty()) { - // This handles both complexf and fixedpoint: - // Convert from complexfix to interleaved int16_t I/Q - m_formatConverter = make_shared<FormatConverter>(m_format); + if (m_settings.fftEngine == FFTEngine::FFTW and not m_format.empty()) { + m_formatConverter = make_shared<FormatConverter>(false, m_format); + } + else if (m_settings.fftEngine == FFTEngine::DEXTER) { + m_formatConverter = make_shared<FormatConverter>(true, m_format); } + // KISS is already in s16 m_output = make_shared<OutputMemory>(dataOut); diff --git a/src/FormatConverter.cpp b/src/FormatConverter.cpp index a52f501..1821442 100644 --- a/src/FormatConverter.cpp +++ b/src/FormatConverter.cpp @@ -34,9 +34,10 @@ #include <stdexcept> #include <assert.h> -FormatConverter::FormatConverter(const std::string& format) : +FormatConverter::FormatConverter(bool input_is_complexfix_wide, const std::string& format_out) : ModCodec(), - m_format(format) + m_input_complexfix_wide(input_is_complexfix_wide), + m_format_out(format_out) { } FormatConverter::~FormatConverter() @@ -55,67 +56,95 @@ int FormatConverter::process(Buffer* const dataIn, Buffer* dataOut) size_t num_clipped_samples = 0; - size_t sizeIn = dataIn->getLength() / sizeof(float); - float* in = reinterpret_cast<float*>(dataIn->getData()); - if (m_format == "s16") { - dataOut->setLength(sizeIn * sizeof(int16_t)); - int16_t* out = reinterpret_cast<int16_t*>(dataOut->getData()); - - for (size_t i = 0; i < sizeIn; i++) { - if (in[i] < INT16_MIN) { - out[i] = INT16_MIN; - num_clipped_samples++; - } - else if (in[i] > INT16_MAX) { - out[i] = INT16_MAX; - num_clipped_samples++; - } - else { - out[i] = in[i]; + if (m_input_complexfix_wide) { + size_t sizeIn = dataIn->getLength() / sizeof(int32_t); + int32_t* in = reinterpret_cast<int32_t*>(dataIn->getData()); + if (m_format_out == "s16") { + dataOut->setLength(sizeIn * sizeof(int16_t)); + int16_t* out = reinterpret_cast<int16_t*>(dataOut->getData()); + + for (size_t i = 0; i < sizeIn; i++) { + if (in[i] < INT16_MIN) { + out[i] = INT16_MIN; + num_clipped_samples++; + } + else if (in[i] > INT16_MAX) { + out[i] = INT16_MAX; + num_clipped_samples++; + } + else { + out[i] = in[i]; + } } } - } - else if (m_format == "u8") { - dataOut->setLength(sizeIn * sizeof(int8_t)); - uint8_t* out = reinterpret_cast<uint8_t*>(dataOut->getData()); - - for (size_t i = 0; i < sizeIn; i++) { - const auto samp = in[i] + 128.0f; - if (samp < 0) { - out[i] = 0; - num_clipped_samples++; - } - else if (samp > UINT8_MAX) { - out[i] = UINT8_MAX; - num_clipped_samples++; - } - else { - out[i] = samp; - } - + else { + throw std::runtime_error("FormatConverter: Invalid fix format " + m_format_out); } } - else if (m_format == "s8") { - dataOut->setLength(sizeIn * sizeof(int8_t)); - int8_t* out = reinterpret_cast<int8_t*>(dataOut->getData()); - - for (size_t i = 0; i < sizeIn; i++) { - if (in[i] < INT8_MIN) { - out[i] = INT8_MIN; - num_clipped_samples++; + else { + size_t sizeIn = dataIn->getLength() / sizeof(float); + float* in = reinterpret_cast<float*>(dataIn->getData()); + + if (m_format_out == "s16") { + dataOut->setLength(sizeIn * sizeof(int16_t)); + int16_t* out = reinterpret_cast<int16_t*>(dataOut->getData()); + + for (size_t i = 0; i < sizeIn; i++) { + if (in[i] < INT16_MIN) { + out[i] = INT16_MIN; + num_clipped_samples++; + } + else if (in[i] > INT16_MAX) { + out[i] = INT16_MAX; + num_clipped_samples++; + } + else { + out[i] = in[i]; + } } - else if (in[i] > INT8_MAX) { - out[i] = INT8_MAX; - num_clipped_samples++; + } + else if (m_format_out == "u8") { + dataOut->setLength(sizeIn * sizeof(int8_t)); + uint8_t* out = reinterpret_cast<uint8_t*>(dataOut->getData()); + + for (size_t i = 0; i < sizeIn; i++) { + const auto samp = in[i] + 128.0f; + if (samp < 0) { + out[i] = 0; + num_clipped_samples++; + } + else if (samp > UINT8_MAX) { + out[i] = UINT8_MAX; + num_clipped_samples++; + } + else { + out[i] = samp; + } + } - else { - out[i] = in[i]; + } + else if (m_format_out == "s8") { + dataOut->setLength(sizeIn * sizeof(int8_t)); + int8_t* out = reinterpret_cast<int8_t*>(dataOut->getData()); + + for (size_t i = 0; i < sizeIn; i++) { + if (in[i] < INT8_MIN) { + out[i] = INT8_MIN; + num_clipped_samples++; + } + else if (in[i] > INT8_MAX) { + out[i] = INT8_MAX; + num_clipped_samples++; + } + else { + out[i] = in[i]; + } } } - } - else { - throw std::runtime_error("FormatConverter: Invalid format " + m_format); + else { + throw std::runtime_error("FormatConverter: Invalid format " + m_format_out); + } } m_num_clipped_samples.store(num_clipped_samples); @@ -136,10 +165,7 @@ size_t FormatConverter::get_num_clipped_samples() const size_t FormatConverter::get_format_size(const std::string& format) { // Returns 2*sizeof(SAMPLE_TYPE) because we have I + Q - if (format == "fixedpoint") { - return 4; - } - else if (format == "s16") { + if (format == "s16") { return 4; } else if (format == "u8") { diff --git a/src/FormatConverter.h b/src/FormatConverter.h index 27ca0b1..1ed2283 100644 --- a/src/FormatConverter.h +++ b/src/FormatConverter.h @@ -41,8 +41,10 @@ class FormatConverter : public ModCodec public: static size_t get_format_size(const std::string& format); - // Allowed formats: s8, u8 and s16 - FormatConverter(const std::string& format); + // floating-point input allows output formats: s8, u8 and s16 + // complexfix_wide input allows output formats: s16 + // complexfix input is already in s16, and needs no converter + FormatConverter(bool input_is_complexfix_wide, const std::string& format_out); virtual ~FormatConverter(); int process(Buffer* const dataIn, Buffer* dataOut); @@ -51,7 +53,8 @@ class FormatConverter : public ModCodec size_t get_num_clipped_samples() const; private: - std::string m_format; + bool m_input_complexfix_wide; + std::string m_format_out; std::atomic<size_t> m_num_clipped_samples = 0; }; diff --git a/src/GuardIntervalInserter.cpp b/src/GuardIntervalInserter.cpp index 4e22367..7061e47 100644 --- a/src/GuardIntervalInserter.cpp +++ b/src/GuardIntervalInserter.cpp @@ -49,10 +49,10 @@ GuardIntervalInserter::GuardIntervalInserter( size_t nullSize, size_t symSize, size_t& windowOverlap, - bool fixedPoint) : + FFTEngine fftEngine) : ModCodec(), RemoteControllable("guardinterval"), - m_fixedPoint(fixedPoint), + m_fftEngine(fftEngine), m_params(nbSymbols, spacing, nullSize, symSize, windowOverlap) { if (nullSize == 0) { @@ -277,15 +277,18 @@ int do_process(const GuardIntervalInserter::Params& p, Buffer* const dataIn, Buf int GuardIntervalInserter::process(Buffer* const dataIn, Buffer* dataOut) { - if (m_fixedPoint) { - if (m_params.windowOverlap) { - throw std::runtime_error("fixed point and ofdm windowing not supported"); - } - return do_process<complexfix>(m_params, dataIn, dataOut); - } - else { - return do_process<complexf>(m_params, dataIn, dataOut); + switch (m_fftEngine) { + case FFTEngine::FFTW: + return do_process<complexf>(m_params, dataIn, dataOut); + case FFTEngine::KISS: + if (m_params.windowOverlap) { + throw std::runtime_error("fixed point and ofdm windowing not supported"); + } + return do_process<complexfix>(m_params, dataIn, dataOut); + case FFTEngine::DEXTER: + return do_process<complexfix_wide>(m_params, dataIn, dataOut); } + throw std::logic_error("Unhandled fftEngine variant"); } void GuardIntervalInserter::set_parameter( diff --git a/src/GuardIntervalInserter.h b/src/GuardIntervalInserter.h index 380142e..8d329ff 100644 --- a/src/GuardIntervalInserter.h +++ b/src/GuardIntervalInserter.h @@ -30,6 +30,7 @@ # include <config.h> #endif +#include "ConfigParser.h" #include "ModPlugin.h" #include "RemoteControl.h" #include <stdint.h> @@ -51,7 +52,7 @@ class GuardIntervalInserter : public ModCodec, public RemoteControllable size_t nullSize, size_t symSize, size_t& windowOverlap, - bool fixedPoint); + FFTEngine fftEngine); virtual ~GuardIntervalInserter() {} @@ -84,7 +85,7 @@ class GuardIntervalInserter : public ModCodec, public RemoteControllable protected: void update_window(size_t new_window_overlap); - bool m_fixedPoint; + FFTEngine m_fftEngine; Params m_params; diff --git a/src/OfdmGenerator.cpp b/src/OfdmGenerator.cpp index 4f6eeb9..11f5bf1 100644 --- a/src/OfdmGenerator.cpp +++ b/src/OfdmGenerator.cpp @@ -633,8 +633,8 @@ OfdmGeneratorDEXTER::OfdmGeneratorDEXTER(size_t nbSymbols, PDEBUG(" myZeroDst: %u\n", myZeroDst); PDEBUG(" myZeroSize: %u\n", myZeroSize); - const size_t nbytes = mySpacing * sizeof(complexfix); - fprintf(stderr, "sizeof(complexfix)=%zu\n", sizeof(complexfix)); + const size_t nbytes_in = mySpacing * sizeof(complexfix); + const size_t nbytes_out = mySpacing * 2 * sizeof(int32_t); #define IIO_ENSURE(expr, err) { \ if (!(expr)) { \ @@ -651,12 +651,12 @@ OfdmGeneratorDEXTER::OfdmGeneratorDEXTER(size_t nbSymbols, iio_channel_enable(m_channel_in); iio_channel_enable(m_channel_out); - m_buf_in = iio_device_create_buffer(m_dev_in, nbytes, false); + m_buf_in = iio_device_create_buffer(m_dev_in, nbytes_in, false); if (!m_buf_in) { throw std::runtime_error("OfdmGeneratorDEXTER could not create in buffer"); } - m_buf_out = iio_device_create_buffer(m_dev_out, nbytes, false); + m_buf_out = iio_device_create_buffer(m_dev_out, nbytes_out, false); if (!m_buf_out) { throw std::runtime_error("OfdmGeneratorDEXTER could not create out buffer"); } @@ -692,13 +692,13 @@ OfdmGeneratorDEXTER::~OfdmGeneratorDEXTER() int OfdmGeneratorDEXTER::process(Buffer* const dataIn, Buffer* dataOut) { - dataOut->setLength(myNbSymbols * mySpacing * sizeof(complexfix)); + dataOut->setLength(myNbSymbols * mySpacing * sizeof(complexfix_wide)); complexfix *in = reinterpret_cast<complexfix*>(dataIn->getData()); - complexfix *out = reinterpret_cast<complexfix*>(dataOut->getData()); + complexfix_wide *out = reinterpret_cast<complexfix_wide*>(dataOut->getData()); size_t sizeIn = dataIn->getLength() / sizeof(complexfix); - size_t sizeOut = dataOut->getLength() / sizeof(complexfix); + size_t sizeOut = dataOut->getLength() / sizeof(complexfix_wide); if (sizeIn != myNbSymbols * myNbCarriers) { PDEBUG("Nb symbols: %zu\n", myNbSymbols); @@ -754,15 +754,19 @@ int OfdmGeneratorDEXTER::process(Buffer* const dataIn, Buffer* dataOut) throw std::runtime_error("OfdmGenerator::process Wrong p_inc"); } + // The FFT Accelerator takes 16-bit I + 16-bit Q, and outputs 32-bit I and 32-bit Q. + // The formatconvert will take care of this const uint8_t *fft_out = (const uint8_t*)iio_buffer_first(m_buf_out, m_channel_out); const uint8_t *fft_out_end = (const uint8_t*)iio_buffer_end(m_buf_out); - if ((fft_out_end - fft_out) != (ssize_t)(mySpacing * sizeof(complexfix))) { + constexpr size_t sizeof_out_iq = sizeof(complexfix_wide); + if ((fft_out_end - fft_out) != (ssize_t)(mySpacing * sizeof_out_iq)) { fprintf(stderr, "FFT_OUT: %p %p %zu %zu\n", - fft_out, fft_out_end, (fft_out_end - fft_out), mySpacing * sizeof(complexfix)); + fft_out, fft_out_end, (fft_out_end - fft_out), + mySpacing * sizeof_out_iq); throw std::runtime_error("OfdmGenerator::process fft_out length invalid!"); } - memcpy(out, fft_out, mySpacing * sizeof(complexfix)); + memcpy(out, fft_out, mySpacing * sizeof_out_iq); in += myNbCarriers; out += mySpacing; |