diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/DabMod.cpp | 26 | ||||
| -rw-r--r-- | src/DabModulator.cpp | 4 | ||||
| -rw-r--r-- | src/FormatConverter.cpp | 135 | ||||
| -rw-r--r-- | src/FormatConverter.h | 3 | ||||
| -rw-r--r-- | src/GuardIntervalInserter.cpp | 4 | ||||
| -rw-r--r-- | src/OutputMemory.cpp | 20 | ||||
| -rw-r--r-- | src/OutputMemory.h | 4 | ||||
| -rw-r--r-- | src/output/SDR.cpp | 1 | ||||
| -rw-r--r-- | src/output/SDR.h | 4 | ||||
| -rw-r--r-- | src/output/SDRDevice.h | 4 | ||||
| -rw-r--r-- | src/output/UHD.cpp | 23 | ||||
| -rw-r--r-- | src/output/UHD.h | 3 | 
12 files changed, 129 insertions, 102 deletions
diff --git a/src/DabMod.cpp b/src/DabMod.cpp index 5f8412b..739fef1 100644 --- a/src/DabMod.cpp +++ b/src/DabMod.cpp @@ -72,10 +72,12 @@   * samples can have peaks up to about 48000. The value of 50000   * should guarantee that with a digital gain of 1.0, UHD never clips   * our samples. + * + * This only applies when fixed_point == false.   */  static const float normalise_factor = 50000.0f; -//Empirical normalisation factors used to normalise the samples to amplitude 1. +// Empirical normalisation factors used to normalise the samples to amplitude 1.  static const float normalise_factor_file_fix = 81000.0f;  static const float normalise_factor_file_var = 46000.0f;  static const float normalise_factor_file_max = 46000.0f; @@ -249,16 +251,12 @@ static shared_ptr<ModOutput> prepare_output(mod_settings_t& s)  {      shared_ptr<ModOutput> output; -    if (s.fixedPoint) { -        if (s.useFileOutput) { +    if (s.useFileOutput) { +        if (s.fixedPoint) { +            // Intentionally ignore fileOutputFormat, it is always sc16              output = make_shared<OutputFile>(s.outputName, s.fileOutputShowMetadata);          } -        else { -            throw runtime_error("Fixed point only works with file output"); -        } -    } -    else if (s.useFileOutput) { -        if (s.fileOutputFormat == "complexf") { +        else if (s.fileOutputFormat == "complexf") {              output = make_shared<OutputFile>(s.outputName, s.fileOutputShowMetadata);          }          else if (s.fileOutputFormat == "complexf_normalised") { @@ -294,6 +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;          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()); @@ -304,6 +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");          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()); @@ -313,6 +313,7 @@ static shared_ptr<ModOutput> 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<Output::Dexter>(s.sdr_device_config);          output = make_shared<Output::SDR>(s.sdr_device_config, dexterdevice); @@ -323,6 +324,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");          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); @@ -333,6 +335,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");          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); @@ -443,7 +446,10 @@ int launch_modulator(int argc, char* argv[])      }      std::string output_format; -    if (mod_settings.useFileOutput and +    if (mod_settings.fixedPoint) { +        output_format = "fixedpoint"; +    } +    else if (mod_settings.useFileOutput and              (mod_settings.fileOutputFormat == "s8" or               mod_settings.fileOutputFormat == "u8" or               mod_settings.fileOutputFormat == "s16")) { diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp index d48f1a2..9e9d017 100644 --- a/src/DabModulator.cpp +++ b/src/DabModulator.cpp @@ -258,8 +258,8 @@ int DabModulator::process(Buffer* dataOut)          }          if (not m_format.empty()) { -            if (m_settings.fixedPoint) throw std::runtime_error("fixed point doesn't support format converter"); - +            // This handles both complexf and fixedpoint: +            // Convert from complexfix to interleaved int16_t I/Q              m_formatConverter = make_shared<FormatConverter>(m_format);          } diff --git a/src/FormatConverter.cpp b/src/FormatConverter.cpp index e8e76ed..9e59a4a 100644 --- a/src/FormatConverter.cpp +++ b/src/FormatConverter.cpp @@ -39,6 +39,14 @@ FormatConverter::FormatConverter(const std::string& format) :      m_format(format)  { } +FormatConverter::~FormatConverter() +{ +    etiLog.level(debug) << "FormatConverter: " +        << m_num_clipped_samples.load() << +        " clipped samples"; +} + +  /* Expect the input samples to be in the correct range for the required format */  int FormatConverter::process(Buffer* const dataIn, Buffer* dataOut)  { @@ -47,71 +55,101 @@ 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]; +    bool source_is_complexf = m_format != "fixedpoint"; + +    if (source_is_complexf) { +        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]; +                }              }          } -    } -    else if (m_format == "u8") { -        dataOut->setLength(sizeIn * sizeof(int8_t)); -        uint8_t* out = reinterpret_cast<uint8_t*>(dataOut->getData()); +        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; +                } -        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 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 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 if (m_format == "s8") { -        dataOut->setLength(sizeIn * sizeof(int8_t)); -        int8_t* out = reinterpret_cast<int8_t*>(dataOut->getData()); +    else { +        // Output is always sc16, because that's what UHD accepts + +        using fixed_t = complexfix::value_type; +        size_t sizeIn = dataIn->getLength() / sizeof(fixed_t); +        fixed_t* in = reinterpret_cast<fixed_t*>(dataIn->getData()); + +        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] < INT8_MIN) { -                out[i] = INT8_MIN; +            const auto v = (in[i] * 2).raw_value(); + +            if (v < INT16_MIN) { +                out[i] = INT16_MIN;                  num_clipped_samples++;              } -            else if (in[i] > INT8_MAX) { -                out[i] = INT8_MAX; +            else if (v > INT16_MAX) { +                out[i] = INT16_MAX;                  num_clipped_samples++;              }              else { -                out[i] = in[i]; +                out[i] = (int16_t)v;              }          }      } -    else { -        throw std::runtime_error("FormatConverter: Invalid format " + m_format); -    }      m_num_clipped_samples.store(num_clipped_samples); -      return dataOut->getLength();  } @@ -129,7 +167,10 @@ 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 == "s16") { +    if (format == "fixedpoint") { +        return 4; +    } +    else if (format == "s16") {          return 4;      }      else if (format == "u8") { diff --git a/src/FormatConverter.h b/src/FormatConverter.h index 05511c0..27ca0b1 100644 --- a/src/FormatConverter.h +++ b/src/FormatConverter.h @@ -33,10 +33,8 @@  #endif  #include "ModPlugin.h" -#include <complex>  #include <atomic>  #include <string> -#include <cstdint>  class FormatConverter : public ModCodec  { @@ -45,6 +43,7 @@ class FormatConverter : public ModCodec          // Allowed formats: s8, u8 and s16          FormatConverter(const std::string& format); +        virtual ~FormatConverter();          int process(Buffer* const dataIn, Buffer* dataOut);          const char* name(); diff --git a/src/GuardIntervalInserter.cpp b/src/GuardIntervalInserter.cpp index 0b39de8..4e22367 100644 --- a/src/GuardIntervalInserter.cpp +++ b/src/GuardIntervalInserter.cpp @@ -112,8 +112,6 @@ int do_process(const GuardIntervalInserter::Params& p, Buffer* const dataIn, Buf      PDEBUG("GuardIntervalInserter do_process(dataIn: %p, dataOut: %p)\n",              dataIn, dataOut); -    std::lock_guard<std::mutex> lock(p.windowMutex); -      // Every symbol overlaps over a length of windowOverlap with      // the previous symbol, and with the next symbol. First symbol      // receives no prefix window, because we don't remember the @@ -141,7 +139,7 @@ int do_process(const GuardIntervalInserter::Params& p, Buffer* const dataIn, Buf      // TODO remember the end of the last TF so that we can do some      //      windowing too. - +    std::lock_guard<std::mutex> lock(p.windowMutex);      if (p.windowOverlap) { if constexpr (std::is_same_v<complexf, T>) {          {              // Handle Null symbol separately because it is longer diff --git a/src/OutputMemory.cpp b/src/OutputMemory.cpp index ac8a67b..f673555 100644 --- a/src/OutputMemory.cpp +++ b/src/OutputMemory.cpp @@ -26,20 +26,14 @@  #include "OutputMemory.h"  #include "PcDebug.h" -#include "Log.h" -#include "TimestampDecoder.h" - -#include <stdexcept> -#include <string.h> -#include <math.h> - +#include <cmath>  OutputMemory::OutputMemory(Buffer* dataOut)      : ModOutput()  {      PDEBUG("OutputMemory::OutputMemory(%p) @ %p\n", dataOut, this); -    myDataOut = dataOut; +    m_dataOut = dataOut;  #if OUTPUT_MEM_HISTOGRAM      myMax = 0.0f; @@ -49,7 +43,6 @@ OutputMemory::OutputMemory(Buffer* dataOut)  #endif  } -  OutputMemory::~OutputMemory()  {  #if OUTPUT_MEM_HISTOGRAM @@ -66,13 +59,12 @@ OutputMemory::~OutputMemory()      PDEBUG("OutputMemory::~OutputMemory() @ %p\n", this);  } -  int OutputMemory::process(Buffer* dataIn)  {      PDEBUG("OutputMemory::process(dataIn: %p)\n",              dataIn); -    *myDataOut = *dataIn; +    *m_dataOut = *dataIn;  #if OUTPUT_MEM_HISTOGRAM      const float* in = (const float*)dataIn->getData(); @@ -87,17 +79,17 @@ int OutputMemory::process(Buffer* dataIn)      }  #endif -    return myDataOut->getLength(); +    return m_dataOut->getLength();  }  meta_vec_t OutputMemory::process_metadata(const meta_vec_t& metadataIn)  { -    myMetadata = metadataIn; +    m_metadata = metadataIn;      return {};  }  meta_vec_t OutputMemory::get_latest_metadata()  { -    return myMetadata; +    return m_metadata;  } diff --git a/src/OutputMemory.h b/src/OutputMemory.h index e7252d3..299d31d 100644 --- a/src/OutputMemory.h +++ b/src/OutputMemory.h @@ -62,8 +62,8 @@ public:      meta_vec_t get_latest_metadata(void);  protected: -    Buffer* myDataOut; -    meta_vec_t myMetadata; +    Buffer* m_dataOut; +    meta_vec_t m_metadata;  #if OUTPUT_MEM_HISTOGRAM      // keep track of max value diff --git a/src/output/SDR.cpp b/src/output/SDR.cpp index 594171f..22398c7 100644 --- a/src/output/SDR.cpp +++ b/src/output/SDR.cpp @@ -34,6 +34,7 @@  #include "RemoteControl.h"  #include "Utils.h" +#include <chrono>  #include <cmath>  #include <iostream>  #include <assert.h> diff --git a/src/output/SDR.h b/src/output/SDR.h index 960de0c..86bf295 100644 --- a/src/output/SDR.h +++ b/src/output/SDR.h @@ -34,16 +34,12 @@ DESCRIPTION:  #   include <config.h>  #endif -#include <chrono>  #include "ModPlugin.h" -#include "EtiReader.h"  #include "output/SDRDevice.h"  #include "output/Feedback.h"  namespace Output { -using complexf = std::complex<float>; -  class SDR : public ModOutput, public ModMetadata, public RemoteControllable {      public:          SDR(SDRDeviceConfig& config, std::shared_ptr<SDRDevice> device); diff --git a/src/output/SDRDevice.h b/src/output/SDRDevice.h index 378829c..ec9373d 100644 --- a/src/output/SDRDevice.h +++ b/src/output/SDRDevice.h @@ -38,9 +38,7 @@ DESCRIPTION:  #include <string>  #include <vector>  #include <complex> -#include <variant>  #include <optional> -#include <unordered_map>  #include "TimestampDecoder.h" @@ -59,6 +57,8 @@ struct SDRDeviceConfig {      std::string tx_antenna;      std::string rx_antenna; +    bool fixedPoint = false; +      long masterClockRate = 32768000;      unsigned sampleRate = 2048000;      double frequency = 0.0; diff --git a/src/output/UHD.cpp b/src/output/UHD.cpp index e097692..b30f9e1 100644 --- a/src/output/UHD.cpp +++ b/src/output/UHD.cpp @@ -31,10 +31,7 @@  //#define MDEBUG(fmt, args...) fprintf(LOG, fmt , ## args)  #define MDEBUG(fmt, args...) -#include "PcDebug.h"  #include "Log.h" -#include "RemoteControl.h" -#include "Utils.h"  #include <thread>  #include <iomanip> @@ -52,14 +49,12 @@  # include <uhd/utils/thread_priority.hpp>  #endif - -#include <cmath>  #include <iostream> -#include <assert.h> +#include <cmath> +#include <cassert>  #include <stdexcept> -#include <stdio.h> +#include <cstdio>  #include <time.h> -#include <errno.h>  #include <unistd.h>  #include <pthread.h> @@ -235,7 +230,8 @@ UHD::UHD(SDRDeviceConfig& config) :      m_usrp->set_rx_gain(m_conf.rxgain);      etiLog.log(debug, "OutputUHD:Actual RX Gain: %f", m_usrp->get_rx_gain()); -    const uhd::stream_args_t stream_args("fc32"); //complex floats +    const uhd::stream_args_t stream_args( +            m_conf.fixedPoint ? "sc16" : "fc32");      m_rx_stream = m_usrp->get_rx_stream(stream_args);      m_tx_stream = m_usrp->get_tx_stream(stream_args); @@ -319,8 +315,9 @@ double UHD::get_bandwidth(void) const  void UHD::transmit_frame(struct FrameData&& frame)  {      const double tx_timeout = 20.0; -    const size_t sizeIn = frame.buf.size() / sizeof(complexf); -    const complexf* in_data = reinterpret_cast<const complexf*>(&frame.buf[0]); + +    const size_t sample_size = m_conf.fixedPoint ? (2 * sizeof(int16_t)) : sizeof(complexf); +    const size_t sizeIn = frame.buf.size() / sample_size;      uhd::tx_metadata_t md_tx; @@ -353,9 +350,9 @@ void UHD::transmit_frame(struct FrameData&& frame)                  samps_to_send <= usrp_max_num_samps );          m_require_timestamp_refresh = false; -        //send a single packet +        // send a single packet          size_t num_tx_samps = m_tx_stream->send( -                &in_data[num_acc_samps], +                frame.buf.data() + sample_size * num_acc_samps,                  samps_to_send, md_tx, tx_timeout);          etiLog.log(trace, "UHD,sent %zu of %zu", num_tx_samps, samps_to_send); diff --git a/src/output/UHD.h b/src/output/UHD.h index 9891c7a..c4f1a45 100644 --- a/src/output/UHD.h +++ b/src/output/UHD.h @@ -45,12 +45,9 @@ DESCRIPTION:  #include <atomic>  #include <thread> -#include "Log.h"  #include "output/SDR.h"  #include "output/USRPTime.h"  #include "TimestampDecoder.h" -#include "RemoteControl.h" -#include "ThreadsafeQueue.h"  #include <stdio.h>  #include <sys/types.h>  | 
