From 933021ed44e6c1bd2cf1dee91fc033c145c061af Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Tue, 29 Oct 2024 22:55:41 +0100 Subject: Change to 16-bit fixed point --- Makefile.am | 2 +- src/Buffer.h | 4 +- src/DabMod.cpp | 3 +- src/DabModulator.cpp | 15 ++++-- src/FormatConverter.cpp | 121 ++++++++++++++++++------------------------------ src/OfdmGenerator.cpp | 30 ++++++------ src/PhaseReference.cpp | 4 +- 7 files changed, 79 insertions(+), 100 deletions(-) diff --git a/Makefile.am b/Makefile.am index 47d6f43..87d553a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -35,7 +35,7 @@ endif bin_PROGRAMS = odr-dabmod -KISS_FLAGS=-DFIXED_POINT=32 +KISS_FLAGS=-DFIXED_POINT=16 odr_dabmod_CFLAGS = -Wall -Isrc -Ilib -Ikiss \ $(GITVERSION_FLAGS) $(KISS_FLAGS) odr_dabmod_CXXFLAGS = -Wall -Isrc -Ilib -Ikiss \ diff --git a/src/Buffer.h b/src/Buffer.h index 711b804..f6c94e0 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -37,7 +37,9 @@ #include "fpm/fixed.hpp" typedef std::complex complexf; -typedef std::complex complexfix; + +using fixed_16 = fpm::fixed; +typedef std::complex complexfix; /* Buffer is a container for a byte array, which is memory-aligned * to 32 bytes for SSE performance. diff --git a/src/DabMod.cpp b/src/DabMod.cpp index b745271..4726df9 100644 --- a/src/DabMod.cpp +++ b/src/DabMod.cpp @@ -313,7 +313,6 @@ static shared_ptr prepare_output(mod_settings_t& s) else if (s.useDexterOutput) { /* We normalise specifically range [-32768; 32767] */ s.normalise = 32767.0f / normalise_factor; - if (s.fixedPoint) throw runtime_error("dexter fixed_point unsupported"); s.sdr_device_config.sampleRate = s.outputRate; auto dexterdevice = make_shared(s.sdr_device_config); output = make_shared(s.sdr_device_config, dexterdevice); @@ -448,7 +447,7 @@ int launch_modulator(int argc, char* argv[]) std::string output_format; if (mod_settings.fixedPoint) { - output_format = "fixedpoint"; + output_format = ""; //fixed point is native sc16, no converter needed } else if (mod_settings.useFileOutput and (mod_settings.fileOutputFormat == "s8" or diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp index 757b01f..5f01725 100644 --- a/src/DabModulator.cpp +++ b/src/DabModulator.cpp @@ -178,11 +178,16 @@ int DabModulator::process(Buffer* dataOut) shared_ptr tii; shared_ptr tiiRef; try { - tii = make_shared( - m_settings.dabMode, - m_settings.tiiConfig); - rcs.enrol(tii.get()); - tiiRef = make_shared(mode, m_settings.fixedPoint); + if (m_settings.fixedPoint) { + etiLog.level(warn) << "TII does not yet support fixed point"; + } + else { + tii = make_shared( + m_settings.dabMode, + m_settings.tiiConfig); + rcs.enrol(tii.get()); + tiiRef = make_shared(mode, m_settings.fixedPoint); + } } catch (const TIIError& e) { etiLog.level(error) << "Could not initialise TII: " << e.what(); diff --git a/src/FormatConverter.cpp b/src/FormatConverter.cpp index 9e59a4a..a52f501 100644 --- a/src/FormatConverter.cpp +++ b/src/FormatConverter.cpp @@ -55,99 +55,68 @@ int FormatConverter::process(Buffer* const dataIn, Buffer* dataOut) size_t num_clipped_samples = 0; - bool source_is_complexf = m_format != "fixedpoint"; - - if (source_is_complexf) { - size_t sizeIn = dataIn->getLength() / sizeof(float); - float* in = reinterpret_cast(dataIn->getData()); - - if (m_format == "s16") { - dataOut->setLength(sizeIn * sizeof(int16_t)); - int16_t* out = reinterpret_cast(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(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; - } + size_t sizeIn = dataIn->getLength() / sizeof(float); + float* in = reinterpret_cast(dataIn->getData()); + + if (m_format == "s16") { + dataOut->setLength(sizeIn * sizeof(int16_t)); + int16_t* out = reinterpret_cast(dataOut->getData()); + for (size_t i = 0; i < sizeIn; i++) { + if (in[i] < INT16_MIN) { + out[i] = INT16_MIN; + num_clipped_samples++; } - } - else if (m_format == "s8") { - dataOut->setLength(sizeIn * sizeof(int8_t)); - int8_t* out = reinterpret_cast(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 if (in[i] > INT16_MAX) { + out[i] = INT16_MAX; + num_clipped_samples++; + } + else { + out[i] = in[i]; } } - else { - throw std::runtime_error("FormatConverter: Invalid format " + m_format); - } - } - else { - // Output is always sc16, because that's what UHD accepts + else if (m_format == "u8") { + dataOut->setLength(sizeIn * sizeof(int8_t)); + uint8_t* out = reinterpret_cast(dataOut->getData()); - using fixed_t = complexfix::value_type; - size_t sizeIn = dataIn->getLength() / sizeof(fixed_t); - fixed_t* in = reinterpret_cast(dataIn->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; + } - dataOut->setLength(sizeIn * sizeof(int16_t)); - int16_t* out = reinterpret_cast(dataOut->getData()); + } + } + else if (m_format == "s8") { + dataOut->setLength(sizeIn * sizeof(int8_t)); + int8_t* out = reinterpret_cast(dataOut->getData()); for (size_t i = 0; i < sizeIn; i++) { - const auto v = (in[i] * 2).raw_value(); - - if (v < INT16_MIN) { - out[i] = INT16_MIN; + if (in[i] < INT8_MIN) { + out[i] = INT8_MIN; num_clipped_samples++; } - else if (v > INT16_MAX) { - out[i] = INT16_MAX; + else if (in[i] > INT8_MAX) { + out[i] = INT8_MAX; num_clipped_samples++; } else { - out[i] = (int16_t)v; + out[i] = in[i]; } } } + else { + throw std::runtime_error("FormatConverter: Invalid format " + m_format); + } m_num_clipped_samples.store(num_clipped_samples); return dataOut->getLength(); diff --git a/src/OfdmGenerator.cpp b/src/OfdmGenerator.cpp index 62a0ee5..4f6eeb9 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 int N = mySpacing; // The size of the FFT - const size_t nbytes = N * sizeof(complexfix); + const size_t nbytes = mySpacing * sizeof(complexfix); + fprintf(stderr, "sizeof(complexfix)=%zu\n", sizeof(complexfix)); #define IIO_ENSURE(expr, err) { \ if (!(expr)) { \ @@ -721,17 +721,6 @@ int OfdmGeneratorDEXTER::process(Buffer* const dataIn, Buffer* dataOut) throw std::runtime_error("OfdmGenerator::process incorrect iio buffer size!"); } - ptrdiff_t p_inc = iio_buffer_step(m_buf_out); - if (p_inc != 1) { - throw std::runtime_error("OfdmGenerator::process Wrong p_inc"); - } - - 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))) != 0) { - throw std::runtime_error("OfdmGenerator::process fft_out length invalid!"); - } - complexfix *fft_in = reinterpret_cast(iio_buffer_start(m_buf_in)); fft_in[0] = static_cast(0); @@ -758,6 +747,21 @@ int OfdmGeneratorDEXTER::process(Buffer* const dataIn, Buffer* dataOut) throw std::runtime_error("OfdmGenerator::process error refilling IIO buffer!"); } + fprintf(stderr, "IIO refill %zd\n", nbytes_rx); + + ptrdiff_t p_inc = iio_buffer_step(m_buf_out); + if (p_inc != 1) { + throw std::runtime_error("OfdmGenerator::process Wrong p_inc"); + } + + 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))) { + fprintf(stderr, "FFT_OUT: %p %p %zu %zu\n", + fft_out, fft_out_end, (fft_out_end - fft_out), mySpacing * sizeof(complexfix)); + throw std::runtime_error("OfdmGenerator::process fft_out length invalid!"); + } + memcpy(out, fft_out, mySpacing * sizeof(complexfix)); in += myNbCarriers; diff --git a/src/PhaseReference.cpp b/src/PhaseReference.cpp index d7b89bf..e2fb9a9 100644 --- a/src/PhaseReference.cpp +++ b/src/PhaseReference.cpp @@ -137,8 +137,8 @@ complexf PhaseRefGen::convert(uint8_t data) { template <> complexfix PhaseRefGen::convert(uint8_t data) { - constexpr auto one = fpm::fixed_16_16{1}; - constexpr auto zero = fpm::fixed_16_16{0}; + constexpr auto one = fixed_16{1}; + constexpr auto zero = fixed_16{0}; const complexfix value[] = { complexfix(one, zero), -- cgit v1.2.3