aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Buffer.h1
-rw-r--r--src/ConfigParser.cpp24
-rw-r--r--src/ConfigParser.h8
-rw-r--r--src/DabMod.cpp18
-rw-r--r--src/DabModulator.cpp96
-rw-r--r--src/FormatConverter.cpp142
-rw-r--r--src/FormatConverter.h9
-rw-r--r--src/GuardIntervalInserter.cpp23
-rw-r--r--src/GuardIntervalInserter.h5
-rw-r--r--src/OfdmGenerator.cpp24
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;