From 8736f6160aeafe7a177cb6143fea80157e174e52 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Sun, 6 Oct 2024 19:47:19 +0200 Subject: Implement fixed-point symbols, FFT and file output --- src/PhaseReference.cpp | 135 ++++++++++++++++++++++++++++--------------------- 1 file changed, 76 insertions(+), 59 deletions(-) (limited to 'src/PhaseReference.cpp') diff --git a/src/PhaseReference.cpp b/src/PhaseReference.cpp index 568e15e..d7b89bf 100644 --- a/src/PhaseReference.cpp +++ b/src/PhaseReference.cpp @@ -29,12 +29,10 @@ #include -using complexf = std::complex; - /* ETSI EN 300 401 Table 43 (Clause 14.3.2) * Contains h_{i,k} values */ -const uint8_t PhaseReference::d_h[4][32] = { +static const uint8_t d_h[4][32] = { /* h0 */ { 0, 2, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 2, 2, 1, 1, 0, 2, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 2, 2, 1, 1 }, /* h1 */ { 0, 3, 2, 3, 0, 1, 3, 0, 2, 1, 2, 3, 2, 3, 3, 0, @@ -54,41 +52,80 @@ const uint8_t PhaseReference::d_h[4][32] = { * Tables 44 to 47 describe the frequency interleaving done in * FrequencyInterleaver. */ -PhaseReference::PhaseReference(unsigned int dabmode) : +PhaseReference::PhaseReference(unsigned int dabmode, bool fixedPoint) : ModInput(), - d_dabmode(dabmode) + d_dabmode(dabmode), + d_fixedPoint(fixedPoint) { PDEBUG("PhaseReference::PhaseReference(%u) @ %p\n", dabmode, this); switch (d_dabmode) { case 1: d_carriers = 1536; - d_num = 2048; break; case 2: d_carriers = 384; - d_num = 512; break; case 3: d_carriers = 192; - d_num = 256; break; case 4: d_dabmode = 0; case 0: d_carriers = 768; - d_num = 1024; break; default: throw std::runtime_error( "PhaseReference::PhaseReference DAB mode not valid!"); } - d_dataIn.resize(d_carriers); - fillData(); + + if (d_fixedPoint) { + d_phaseRefFixed.fillData(d_dabmode, d_carriers); + } + else { + d_phaseRefCF32.fillData(d_dabmode, d_carriers); + } } -complexf convert(uint8_t data) { +static const int table[][48][2] = { + { // Mode 0/4 + // Positive part + { 0, 0 }, { 3, 1 }, { 2, 0 }, { 1, 2 }, { 0, 0 }, { 3, 1 }, + { 2, 2 }, { 1, 2 }, { 0, 2 }, { 3, 1 }, { 2, 3 }, { 1, 0 }, + // Negative part + { 0, 0 }, { 1, 1 }, { 2, 1 }, { 3, 2 }, { 0, 2 }, { 1, 2 }, + { 2, 0 }, { 3, 3 }, { 0, 3 }, { 1, 1 }, { 2, 3 }, { 3, 2 }, + }, + { // Mode 1 + // Positive part + { 0, 3 }, { 3, 1 }, { 2, 1 }, { 1, 1 }, { 0, 2 }, { 3, 2 }, + { 2, 1 }, { 1, 0 }, { 0, 2 }, { 3, 2 }, { 2, 3 }, { 1, 3 }, + { 0, 0 }, { 3, 2 }, { 2, 1 }, { 1, 3 }, { 0, 3 }, { 3, 3 }, + { 2, 3 }, { 1, 0 }, { 0, 3 }, { 3, 0 }, { 2, 1 }, { 1, 1 }, + // Negative part + { 0, 1 }, { 1, 2 }, { 2, 0 }, { 3, 1 }, { 0, 3 }, { 1, 2 }, + { 2, 2 }, { 3, 3 }, { 0, 2 }, { 1, 1 }, { 2, 2 }, { 3, 3 }, + { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 3 }, { 0, 2 }, { 1, 2 }, + { 2, 2 }, { 3, 1 }, { 0, 1 }, { 1, 3 }, { 2, 1 }, { 3, 2 }, + }, + { // Mode 2 + // Positive part + { 2, 0 }, { 1, 2 }, { 0, 2 }, { 3, 1 }, { 2, 0 }, { 1, 3 }, + // Negative part + { 0, 2 }, { 1, 3 }, { 2, 2 }, { 3, 2 }, { 0, 1 }, { 1, 2 }, + }, + { // Mode 3 + // Positive part + { 3, 2 }, { 2, 2 }, { 1, 2 }, + // Negative part + { 0, 2 }, { 1, 3 }, { 2, 0 }, + }, +}; + + +template <> +complexf PhaseRefGen::convert(uint8_t data) { const complexf value[] = { complexf(1, 0), complexf(0, 1), @@ -98,62 +135,37 @@ complexf convert(uint8_t data) { return value[data % 4]; } +template <> +complexfix PhaseRefGen::convert(uint8_t data) { + constexpr auto one = fpm::fixed_16_16{1}; + constexpr auto zero = fpm::fixed_16_16{0}; -void PhaseReference::fillData() -{ - const int table[][48][2] = { - { // Mode 0/4 - // Positive part - { 0, 0 }, { 3, 1 }, { 2, 0 }, { 1, 2 }, { 0, 0 }, { 3, 1 }, - { 2, 2 }, { 1, 2 }, { 0, 2 }, { 3, 1 }, { 2, 3 }, { 1, 0 }, - // Negative part - { 0, 0 }, { 1, 1 }, { 2, 1 }, { 3, 2 }, { 0, 2 }, { 1, 2 }, - { 2, 0 }, { 3, 3 }, { 0, 3 }, { 1, 1 }, { 2, 3 }, { 3, 2 }, - }, - { // Mode 1 - // Positive part - { 0, 3 }, { 3, 1 }, { 2, 1 }, { 1, 1 }, { 0, 2 }, { 3, 2 }, - { 2, 1 }, { 1, 0 }, { 0, 2 }, { 3, 2 }, { 2, 3 }, { 1, 3 }, - { 0, 0 }, { 3, 2 }, { 2, 1 }, { 1, 3 }, { 0, 3 }, { 3, 3 }, - { 2, 3 }, { 1, 0 }, { 0, 3 }, { 3, 0 }, { 2, 1 }, { 1, 1 }, - // Negative part - { 0, 1 }, { 1, 2 }, { 2, 0 }, { 3, 1 }, { 0, 3 }, { 1, 2 }, - { 2, 2 }, { 3, 3 }, { 0, 2 }, { 1, 1 }, { 2, 2 }, { 3, 3 }, - { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 3 }, { 0, 2 }, { 1, 2 }, - { 2, 2 }, { 3, 1 }, { 0, 1 }, { 1, 3 }, { 2, 1 }, { 3, 2 }, - }, - { // Mode 2 - // Positive part - { 2, 0 }, { 1, 2 }, { 0, 2 }, { 3, 1 }, { 2, 0 }, { 1, 3 }, - // Negative part - { 0, 2 }, { 1, 3 }, { 2, 2 }, { 3, 2 }, { 0, 1 }, { 1, 2 }, - }, - { // Mode 3 - // Positive part - { 3, 2 }, { 2, 2 }, { 1, 2 }, - // Negative part - { 0, 2 }, { 1, 3 }, { 2, 0 }, - }, + const complexfix value[] = { + complexfix(one, zero), + complexfix(zero, one), + complexfix(-one, zero), + complexfix(zero, -one), }; + return value[data % 4]; +} - if (d_dabmode > 3) { - throw std::runtime_error( - "PhaseReference::fillData invalid DAB mode!"); - } - - if (d_dataIn.size() != d_carriers) { +template +void PhaseRefGen::fillData(unsigned int dabmode, size_t carriers) +{ + dataIn.resize(carriers); + if (dataIn.size() != carriers) { throw std::runtime_error( - "PhaseReference::fillData d_dataIn has incorrect size!"); + "PhaseReference::fillData dataIn has incorrect size!"); } for (size_t index = 0, offset = 0; - index < d_dataIn.size(); + index < dataIn.size(); ++offset) { for (size_t k = 0; k < 32; ++k) { - d_dataIn[index++] = convert( - d_h[ table[d_dabmode][offset][0] ][k] + - table[d_dabmode][offset][1] ); + dataIn[index++] = convert( + d_h[ table[dabmode][offset][0] ][k] + + table[dabmode][offset][1] ); } } } @@ -163,7 +175,12 @@ int PhaseReference::process(Buffer* dataOut) { PDEBUG("PhaseReference::process(dataOut: %p)\n", dataOut); - dataOut->setData(&d_dataIn[0], d_carriers * sizeof(complexf)); + if (d_fixedPoint) { + dataOut->setData(&d_phaseRefFixed.dataIn[0], d_carriers * sizeof(complexfix)); + } + else { + dataOut->setData(&d_phaseRefCF32.dataIn[0], d_carriers * sizeof(complexf)); + } return 1; } -- cgit v1.2.3 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(-) (limited to 'src/PhaseReference.cpp') 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 From 7452ff0fd85da423a5be1fdc3873106160c6ccae Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Tue, 5 Nov 2024 16:45:35 +0100 Subject: Debug DEXTER FFT Acccelerator --- src/DabModulator.cpp | 4 + src/DifferentialModulator.cpp | 2 +- src/Flowgraph.cpp | 10 +- src/FrequencyInterleaver.cpp | 8 +- src/GuardIntervalInserter.cpp | 210 ++++++++++++++++++++++-------------------- src/OfdmGenerator.cpp | 16 ++-- src/PhaseReference.cpp | 4 +- src/SignalMultiplexer.cpp | 8 +- 8 files changed, 132 insertions(+), 130 deletions(-) (limited to 'src/PhaseReference.cpp') diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp index 4cbd0f5..39c1d4a 100644 --- a/src/DabModulator.cpp +++ b/src/DabModulator.cpp @@ -220,6 +220,7 @@ int DabModulator::process(Buffer* dataOut) m_settings.cfrErrorClip); break; case FFTEngine::DEXTER: +#if defined(HAVE_DEXTER) cifOfdm = make_shared( (1 + m_nbSymbols), m_nbCarriers, @@ -227,6 +228,9 @@ int DabModulator::process(Buffer* dataOut) m_settings.enableCfr, m_settings.cfrClip, m_settings.cfrErrorClip); +#else + throw std::runtime_error("Cannot use DEXTER fft engine without --enable-dexter"); +#endif break; } diff --git a/src/DifferentialModulator.cpp b/src/DifferentialModulator.cpp index cfebf65..21b4c3e 100644 --- a/src/DifferentialModulator.cpp +++ b/src/DifferentialModulator.cpp @@ -43,7 +43,7 @@ DifferentialModulator::~DifferentialModulator() template -void do_process(size_t carriers, std::vector dataIn, Buffer* dataOut) +void do_process(size_t carriers, const std::vector& dataIn, Buffer* dataOut) { size_t phaseSize = dataIn[0]->getLength() / sizeof(T); size_t dataSize = dataIn[1]->getLength() / sizeof(T); diff --git a/src/Flowgraph.cpp b/src/Flowgraph.cpp index 3d4cdcc..339e326 100644 --- a/src/Flowgraph.cpp +++ b/src/Flowgraph.cpp @@ -27,12 +27,10 @@ #include "Flowgraph.h" #include "PcDebug.h" #include "Log.h" -#include #include #include #include #include -#include #include #include @@ -254,15 +252,15 @@ Flowgraph::~Flowgraph() char node_time_sz[1024] = {}; for (const auto &node : nodes) { - snprintf(node_time_sz, 1023, " %30s: %10lu us (%2.2f %%)\n", + snprintf(node_time_sz, 1023, " %30s: %10lld us (%2.2f %%)\n", node->plugin()->name(), - node->processTime(), + (long long)node->processTime(), node->processTime() * 100.0 / myProcessTime); ss << node_time_sz; } - snprintf(node_time_sz, 1023, " %30s: %10lu us (100.00 %%)\n", "total", - myProcessTime); + snprintf(node_time_sz, 1023, " %30s: %10lld us (100.00 %%)\n", "total", + (long long)myProcessTime); ss << node_time_sz; etiLog.level(debug) << ss.str(); diff --git a/src/FrequencyInterleaver.cpp b/src/FrequencyInterleaver.cpp index 856e8d0..6f36dcb 100644 --- a/src/FrequencyInterleaver.cpp +++ b/src/FrequencyInterleaver.cpp @@ -61,7 +61,7 @@ FrequencyInterleaver::FrequencyInterleaver(size_t mode, bool fixedPoint) : beta = 255; break; default: - PDEBUG("Carriers: %zu\n", (d_carriers >> 1) << 1); + PDEBUG("Carriers: %zu\n", (m_carriers >> 1) << 1); throw std::runtime_error("FrequencyInterleaver: invalid dab mode"); } @@ -79,10 +79,10 @@ FrequencyInterleaver::FrequencyInterleaver(size_t mode, bool fixedPoint) : && perm <= (num - (num - m_carriers) / 2) && perm != (num / 2)) { PDEBUG("i: %4zu, R: %4zu, d: %4zu, n: %4zu, k: %5zi, index: %zu\n", - j, perm, perm, index - d_indexes, perm - num / 2, + j, perm, perm, index - m_indices, perm - num / 2, perm > num / 2 ? perm - (1 + (num / 2)) - : perm + (d_carriers - (num / 2))); + : perm + (m_carriers - (num / 2))); *(index++) = perm > num / 2 ? perm - (1 + (num / 2)) : perm + (m_carriers - (num / 2)); } @@ -114,7 +114,7 @@ void do_process(Buffer* const dataIn, Buffer* dataOut, } for (size_t i = 0; i < sizeIn;) { -// memset(out, 0, d_carriers * sizeof(T)); +// memset(out, 0, m_carriers * sizeof(T)); for (size_t j = 0; j < carriers; i += 4, j += 4) { out[indices[j]] = in[i]; out[indices[j + 1]] = in[i + 1]; diff --git a/src/GuardIntervalInserter.cpp b/src/GuardIntervalInserter.cpp index 7061e47..26d4fd1 100644 --- a/src/GuardIntervalInserter.cpp +++ b/src/GuardIntervalInserter.cpp @@ -140,118 +140,123 @@ int do_process(const GuardIntervalInserter::Params& p, Buffer* const dataIn, Buf // windowing too. std::lock_guard lock(p.windowMutex); - if (p.windowOverlap) { if constexpr (std::is_same_v) { - { - // Handle Null symbol separately because it is longer - const size_t prefixlength = p.nullSize - p.spacing; - - // end = spacing - memcpy(out, &in[p.spacing - prefixlength], - prefixlength * sizeof(T)); - - memcpy(&out[prefixlength], in, (p.spacing - p.windowOverlap) * sizeof(T)); - - // The remaining part of the symbol must have half of the window applied, - // sloping down from 1 to 0.5 - for (size_t i = 0; i < p.windowOverlap; i++) { - const size_t out_ix = prefixlength + p.spacing - p.windowOverlap + i; - const size_t in_ix = p.spacing - p.windowOverlap + i; - out[out_ix] = in[in_ix] * p.window[2*p.windowOverlap - (i+1)]; - } - - // Suffix is taken from the beginning of the symbol, and sees the other - // half of the window applied. - for (size_t i = 0; i < p.windowOverlap; i++) { - const size_t out_ix = prefixlength + p.spacing + i; - out[out_ix] = in[i] * p.window[p.windowOverlap - (i+1)]; - } + if (p.windowOverlap) { + if constexpr (std::is_same_v) { + { + // Handle Null symbol separately because it is longer + const size_t prefixlength = p.nullSize - p.spacing; + + // end = spacing + memcpy(out, &in[p.spacing - prefixlength], + prefixlength * sizeof(T)); + + memcpy(&out[prefixlength], in, (p.spacing - p.windowOverlap) * sizeof(T)); + + // The remaining part of the symbol must have half of the window applied, + // sloping down from 1 to 0.5 + for (size_t i = 0; i < p.windowOverlap; i++) { + const size_t out_ix = prefixlength + p.spacing - p.windowOverlap + i; + const size_t in_ix = p.spacing - p.windowOverlap + i; + out[out_ix] = in[in_ix] * p.window[2*p.windowOverlap - (i+1)]; + } - in += p.spacing; - out += p.nullSize; - // out is now pointing to the proper end of symbol. There are - // windowOverlap samples ahead that were already written. - } + // Suffix is taken from the beginning of the symbol, and sees the other + // half of the window applied. + for (size_t i = 0; i < p.windowOverlap; i++) { + const size_t out_ix = prefixlength + p.spacing + i; + out[out_ix] = in[i] * p.window[p.windowOverlap - (i+1)]; + } - // Data symbols - for (size_t sym_ix = 0; sym_ix < p.nbSymbols; sym_ix++) { - /* _ix variables are indices into in[], _ox variables are - * indices for out[] */ - const ssize_t start_rise_ox = -p.windowOverlap; - const size_t start_rise_ix = 2 * p.spacing - p.symSize - p.windowOverlap; - /* - const size_t start_real_symbol_ox = 0; - const size_t start_real_symbol_ix = 2 * p.spacing - p.symSize; - */ - const ssize_t end_rise_ox = p.windowOverlap; - const size_t end_rise_ix = 2 * p.spacing - p.symSize + p.windowOverlap; - const ssize_t end_cyclic_prefix_ox = p.symSize - p.spacing; - /* end_cyclic_prefix_ix = end of symbol - const size_t begin_fall_ox = p.symSize - p.windowOverlap; - const size_t begin_fall_ix = p.spacing - p.windowOverlap; - const size_t end_real_symbol_ox = p.symSize; - end_real_symbol_ix = end of symbol - const size_t end_fall_ox = p.symSize + p.windowOverlap; - const size_t end_fall_ix = p.spacing + p.windowOverlap; - */ - - ssize_t ox = start_rise_ox; - size_t ix = start_rise_ix; - - for (size_t i = 0; ix < end_rise_ix; i++) { - out[ox] += in[ix] * p.window.at(i); - ix++; - ox++; - } - assert(ox == end_rise_ox); - - const size_t remaining_prefix_length = end_cyclic_prefix_ox - end_rise_ox; - memcpy( &out[ox], &in[ix], - remaining_prefix_length * sizeof(T)); - ox += remaining_prefix_length; - assert(ox == end_cyclic_prefix_ox); - ix = 0; - - const bool last_symbol = (sym_ix + 1 >= p.nbSymbols); - if (last_symbol) { - // No windowing at all at end - memcpy(&out[ox], &in[ix], p.spacing * sizeof(T)); - ox += p.spacing; + in += p.spacing; + out += p.nullSize; + // out is now pointing to the proper end of symbol. There are + // windowOverlap samples ahead that were already written. } - else { - // Copy the middle part of the symbol, p.windowOverlap samples - // short of the end. - memcpy( &out[ox], - &in[ix], - (p.spacing - p.windowOverlap) * sizeof(T)); - ox += p.spacing - p.windowOverlap; - ix += p.spacing - p.windowOverlap; - assert(ox == (ssize_t)(p.symSize - p.windowOverlap)); - - // Apply window from 1 to 0.5 for the end of the symbol - for (size_t i = 0; ox < (ssize_t)p.symSize; i++) { - out[ox] = in[ix] * p.window[2*p.windowOverlap - (i+1)]; - ox++; + + // Data symbols + for (size_t sym_ix = 0; sym_ix < p.nbSymbols; sym_ix++) { + /* _ix variables are indices into in[], _ox variables are + * indices for out[] */ + const ssize_t start_rise_ox = -p.windowOverlap; + const size_t start_rise_ix = 2 * p.spacing - p.symSize - p.windowOverlap; + /* + const size_t start_real_symbol_ox = 0; + const size_t start_real_symbol_ix = 2 * p.spacing - p.symSize; + */ + const ssize_t end_rise_ox = p.windowOverlap; + const size_t end_rise_ix = 2 * p.spacing - p.symSize + p.windowOverlap; + const ssize_t end_cyclic_prefix_ox = p.symSize - p.spacing; + /* end_cyclic_prefix_ix = end of symbol + const size_t begin_fall_ox = p.symSize - p.windowOverlap; + const size_t begin_fall_ix = p.spacing - p.windowOverlap; + const size_t end_real_symbol_ox = p.symSize; + end_real_symbol_ix = end of symbol + const size_t end_fall_ox = p.symSize + p.windowOverlap; + const size_t end_fall_ix = p.spacing + p.windowOverlap; + */ + + ssize_t ox = start_rise_ox; + size_t ix = start_rise_ix; + + for (size_t i = 0; ix < end_rise_ix; i++) { + out[ox] += in[ix] * p.window.at(i); ix++; + ox++; } - assert(ix == p.spacing); + assert(ox == end_rise_ox); + const size_t remaining_prefix_length = end_cyclic_prefix_ox - end_rise_ox; + memcpy( &out[ox], &in[ix], + remaining_prefix_length * sizeof(T)); + ox += remaining_prefix_length; + assert(ox == end_cyclic_prefix_ox); ix = 0; - // Cyclic suffix, with window from 0.5 to 0 - for (size_t i = 0; ox < (ssize_t)(p.symSize + p.windowOverlap); i++) { - out[ox] = in[ix] * p.window[p.windowOverlap - (i+1)]; - ox++; - ix++; + + const bool last_symbol = (sym_ix + 1 >= p.nbSymbols); + if (last_symbol) { + // No windowing at all at end + memcpy(&out[ox], &in[ix], p.spacing * sizeof(T)); + ox += p.spacing; + } + else { + // Copy the middle part of the symbol, p.windowOverlap samples + // short of the end. + memcpy( &out[ox], + &in[ix], + (p.spacing - p.windowOverlap) * sizeof(T)); + ox += p.spacing - p.windowOverlap; + ix += p.spacing - p.windowOverlap; + assert(ox == (ssize_t)(p.symSize - p.windowOverlap)); + + // Apply window from 1 to 0.5 for the end of the symbol + for (size_t i = 0; ox < (ssize_t)p.symSize; i++) { + out[ox] = in[ix] * p.window[2*p.windowOverlap - (i+1)]; + ox++; + ix++; + } + assert(ix == p.spacing); + + ix = 0; + // Cyclic suffix, with window from 0.5 to 0 + for (size_t i = 0; ox < (ssize_t)(p.symSize + p.windowOverlap); i++) { + out[ox] = in[ix] * p.window[p.windowOverlap - (i+1)]; + ox++; + ix++; + } + + assert(ix == p.windowOverlap); } - assert(ix == p.windowOverlap); + out += p.symSize; + in += p.spacing; + // out is now pointing to the proper end of symbol. There are + // windowOverlap samples ahead that were already written. } - - out += p.symSize; - in += p.spacing; - // out is now pointing to the proper end of symbol. There are - // windowOverlap samples ahead that were already written. } - } } + else { + throw std::runtime_error("fixed-point doesn't support window overlap"); + } + } else { // Handle Null symbol separately because it is longer // end - (nullSize - spacing) = 2 * spacing - nullSize @@ -272,7 +277,8 @@ int do_process(const GuardIntervalInserter::Params& p, Buffer* const dataIn, Buf } } - return sizeIn; + const auto sizeOut = dataOut->getLength(); + return sizeOut; } int GuardIntervalInserter::process(Buffer* const dataIn, Buffer* dataOut) diff --git a/src/OfdmGenerator.cpp b/src/OfdmGenerator.cpp index cfdf31d..32b5f76 100644 --- a/src/OfdmGenerator.cpp +++ b/src/OfdmGenerator.cpp @@ -219,7 +219,6 @@ int OfdmGeneratorCF32::process(Buffer* const dataIn, Buffer* dataOut) memcpy(&myFftIn[myNegDst], &in[myNegSrc], myNegSize * sizeof(FFTW_TYPE)); - if (myCfr) { reference.resize(mySpacing); memcpy(reinterpret_cast(reference.data()), @@ -228,7 +227,6 @@ int OfdmGeneratorCF32::process(Buffer* const dataIn, Buffer* dataOut) fftwf_execute(myFftPlan); // IFFT from myFftIn to myFftOut - if (myCfr) { complexf *symbol = reinterpret_cast(myFftOut); myPaprBeforeCFR.process_block(symbol, mySpacing); @@ -634,7 +632,7 @@ OfdmGeneratorDEXTER::OfdmGeneratorDEXTER(size_t nbSymbols, PDEBUG(" myZeroSize: %u\n", myZeroSize); const size_t nbytes_in = mySpacing * sizeof(complexfix); - const size_t nbytes_out = mySpacing * 2 * sizeof(int32_t); + const size_t nbytes_out = mySpacing * sizeof(complexfix_wide); #define IIO_ENSURE(expr, err) { \ if (!(expr)) { \ @@ -721,14 +719,14 @@ int OfdmGeneratorDEXTER::process(Buffer* const dataIn, Buffer* dataOut) throw std::runtime_error("OfdmGenerator::process incorrect iio buffer size!"); } - complexfix *fft_in = reinterpret_cast(iio_buffer_start(m_buf_in)); + for (size_t i = 0; i < myNbSymbols; i++) { + complexfix *fft_in = reinterpret_cast(iio_buffer_start(m_buf_in)); - fft_in[0] = static_cast(0); - for (size_t i = 0; i < myZeroSize; i++) { - fft_in[myZeroDst + i] = static_cast(0); - } + fft_in[0] = static_cast(0); + for (size_t i = 0; i < myZeroSize; i++) { + fft_in[myZeroDst + i] = static_cast(0); + } - for (size_t i = 0; i < myNbSymbols; i++) { /* For TM I this is: * ZeroDst=769 ZeroSize=511 * PosSrc=0 PosDst=1 PosSize=768 diff --git a/src/PhaseReference.cpp b/src/PhaseReference.cpp index e2fb9a9..71dec87 100644 --- a/src/PhaseReference.cpp +++ b/src/PhaseReference.cpp @@ -176,10 +176,10 @@ int PhaseReference::process(Buffer* dataOut) PDEBUG("PhaseReference::process(dataOut: %p)\n", dataOut); if (d_fixedPoint) { - dataOut->setData(&d_phaseRefFixed.dataIn[0], d_carriers * sizeof(complexfix)); + dataOut->setData(d_phaseRefFixed.dataIn.data(), d_carriers * sizeof(complexfix)); } else { - dataOut->setData(&d_phaseRefCF32.dataIn[0], d_carriers * sizeof(complexf)); + dataOut->setData(d_phaseRefCF32.dataIn.data(), d_carriers * sizeof(complexf)); } return 1; diff --git a/src/SignalMultiplexer.cpp b/src/SignalMultiplexer.cpp index 8ecbe78..d4955d0 100644 --- a/src/SignalMultiplexer.cpp +++ b/src/SignalMultiplexer.cpp @@ -22,24 +22,20 @@ #include "SignalMultiplexer.h" #include "PcDebug.h" -#include -#include +#include #include -#include SignalMultiplexer::SignalMultiplexer() : ModMux() { - PDEBUG("SignalMultiplexer::SignalMultiplexer(%zu) @ %p\n", framesize, this); - + PDEBUG("SignalMultiplexer::SignalMultiplexer() @ %p\n", this); } SignalMultiplexer::~SignalMultiplexer() { PDEBUG("SignalMultiplexer::~SignalMultiplexer() @ %p\n", this); - } -- cgit v1.2.3