diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2023-11-21 22:12:14 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2023-11-21 22:12:14 +0100 |
commit | 5fe36a627405b8fc65bdb212a6d505b9a6c8e489 (patch) | |
tree | 8646d654e0467be8603c5ad37fb6cd89656dfd26 /src/DabModulator.cpp | |
parent | 477ac4639a7c7f74f07a6164096fc7de102528ff (diff) | |
parent | f84065c3cc6fff0edb771f85190f7228f4d740b6 (diff) | |
download | dabmod-5fe36a627405b8fc65bdb212a6d505b9a6c8e489.tar.gz dabmod-5fe36a627405b8fc65bdb212a6d505b9a6c8e489.tar.bz2 dabmod-5fe36a627405b8fc65bdb212a6d505b9a6c8e489.zip |
Merge branch 'dexter' into next
Diffstat (limited to 'src/DabModulator.cpp')
-rw-r--r-- | src/DabModulator.cpp | 229 |
1 files changed, 127 insertions, 102 deletions
diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp index aa4f2a8..4a29132 100644 --- a/src/DabModulator.cpp +++ b/src/DabModulator.cpp @@ -3,7 +3,7 @@ Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2019 + Copyright (C) 2023 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -27,53 +27,54 @@ #include <string> #include <memory> +#include <vector> #include "DabModulator.h" #include "PcDebug.h" -#if !defined(BUILD_FOR_EASYDABV3) -# include "QpskSymbolMapper.h" -# include "FrequencyInterleaver.h" -# include "PhaseReference.h" -# include "DifferentialModulator.h" -# include "NullSymbol.h" -# include "CicEqualizer.h" -# include "OfdmGenerator.h" -# include "GainControl.h" -# include "GuardIntervalInserter.h" -# include "Resampler.h" -# include "FIRFilter.h" -# include "MemlessPoly.h" -# include "TII.h" -#endif - -#include "FrameMultiplexer.h" -#include "PrbsGenerator.h" #include "BlockPartitioner.h" -#include "SignalMultiplexer.h" +#include "CicEqualizer.h" #include "ConvEncoder.h" +#include "DifferentialModulator.h" +#include "FIRFilter.h" +#include "FrameMultiplexer.h" +#include "FrequencyInterleaver.h" +#include "GainControl.h" +#include "GuardIntervalInserter.h" +#include "Log.h" +#include "MemlessPoly.h" +#include "NullSymbol.h" +#include "OfdmGenerator.h" +#include "PhaseReference.h" +#include "PrbsGenerator.h" #include "PuncturingEncoder.h" +#include "QpskSymbolMapper.h" +#include "RemoteControl.h" +#include "Resampler.h" +#include "SignalMultiplexer.h" +#include "TII.h" #include "TimeInterleaver.h" #include "TimestampDecoder.h" -#include "RemoteControl.h" -#include "Log.h" using namespace std; DabModulator::DabModulator(EtiSource& etiSource, - mod_settings_t& settings) : + mod_settings_t& settings, + const std::string& format) : ModInput(), RemoteControllable("modulator"), m_settings(settings), - myEtiSource(etiSource), - myFlowgraph() + m_format(format), + m_etiSource(etiSource), + m_flowgraph() { PDEBUG("DabModulator::DabModulator() @ %p\n", this); RC_ADD_PARAMETER(rate, "(Read-only) IQ output samplerate"); + RC_ADD_PARAMETER(num_clipped_samples, "(Read-only) Number of samples clipped in last frame during format conversion"); if (m_settings.dabMode == 0) { - setMode(2); + setMode(1); } else { setMode(m_settings.dabMode); @@ -85,36 +86,36 @@ void DabModulator::setMode(unsigned mode) { switch (mode) { case 1: - myNbSymbols = 76; - myNbCarriers = 1536; - mySpacing = 2048; - myNullSize = 2656; - mySymSize = 2552; - myFicSizeOut = 288; + m_nbSymbols = 76; + m_nbCarriers = 1536; + m_spacing = 2048; + m_nullSize = 2656; + m_symSize = 2552; + m_ficSizeOut = 288; break; case 2: - myNbSymbols = 76; - myNbCarriers = 384; - mySpacing = 512; - myNullSize = 664; - mySymSize = 638; - myFicSizeOut = 288; + m_nbSymbols = 76; + m_nbCarriers = 384; + m_spacing = 512; + m_nullSize = 664; + m_symSize = 638; + m_ficSizeOut = 288; break; case 3: - myNbSymbols = 153; - myNbCarriers = 192; - mySpacing = 256; - myNullSize = 345; - mySymSize = 319; - myFicSizeOut = 384; + m_nbSymbols = 153; + m_nbCarriers = 192; + m_spacing = 256; + m_nullSize = 345; + m_symSize = 319; + m_ficSizeOut = 384; break; case 4: - myNbSymbols = 76; - myNbCarriers = 768; - mySpacing = 1024; - myNullSize = 1328; - mySymSize = 1276; - myFicSizeOut = 288; + m_nbSymbols = 76; + m_nbCarriers = 768; + m_spacing = 1024; + m_nullSize = 1328; + m_symSize = 1276; + m_ficSizeOut = 288; break; default: throw std::runtime_error("DabModulator::setMode invalid mode size"); @@ -128,27 +129,27 @@ int DabModulator::process(Buffer* dataOut) PDEBUG("DabModulator::process(dataOut: %p)\n", dataOut); - if (not myFlowgraph) { + if (not m_flowgraph) { + etiLog.level(debug) << "Setting up DabModulator..."; const unsigned mode = m_settings.dabMode; setMode(mode); - myFlowgraph = make_shared<Flowgraph>(m_settings.showProcessTime); + m_flowgraph = make_shared<Flowgraph>(m_settings.showProcessTime); //////////////////////////////////////////////////////////////// // CIF data initialisation //////////////////////////////////////////////////////////////// auto cifPrbs = make_shared<PrbsGenerator>(864 * 8, 0x110); - auto cifMux = make_shared<FrameMultiplexer>(myEtiSource); + auto cifMux = make_shared<FrameMultiplexer>(m_etiSource); auto cifPart = make_shared<BlockPartitioner>(mode); -#if !defined(BUILD_FOR_EASYDABV3) - auto cifMap = make_shared<QpskSymbolMapper>(myNbCarriers); + auto cifMap = make_shared<QpskSymbolMapper>(m_nbCarriers); auto cifRef = make_shared<PhaseReference>(mode); auto cifFreq = make_shared<FrequencyInterleaver>(mode); - auto cifDiff = make_shared<DifferentialModulator>(myNbCarriers); + auto cifDiff = make_shared<DifferentialModulator>(m_nbCarriers); - auto cifNull = make_shared<NullSymbol>(myNbCarriers); + auto cifNull = make_shared<NullSymbol>(m_nbCarriers); auto cifSig = make_shared<SignalMultiplexer>( - (1 + myNbSymbols) * myNbCarriers * sizeof(complexf)); + (1 + m_nbSymbols) * m_nbCarriers * sizeof(complexf)); // TODO this needs a review bool useCicEq = false; @@ -169,8 +170,8 @@ int DabModulator::process(Buffer* dataOut) shared_ptr<CicEqualizer> cifCicEq; if (useCicEq) { cifCicEq = make_shared<CicEqualizer>( - myNbCarriers, - (float)mySpacing * (float)m_settings.outputRate / 2048000.0f, + m_nbCarriers, + (float)m_spacing * (float)m_settings.outputRate / 2048000.0f, cic_ratio); } @@ -188,9 +189,9 @@ int DabModulator::process(Buffer* dataOut) } auto cifOfdm = make_shared<OfdmGenerator>( - (1 + myNbSymbols), - myNbCarriers, - mySpacing, + (1 + m_nbSymbols), + m_nbCarriers, + m_spacing, m_settings.enableCfr, m_settings.cfrClip, m_settings.cfrErrorClip); @@ -198,7 +199,7 @@ int DabModulator::process(Buffer* dataOut) rcs.enrol(cifOfdm.get()); auto cifGain = make_shared<GainControl>( - mySpacing, + m_spacing, m_settings.gainMode, m_settings.digitalgain, m_settings.normalise, @@ -207,7 +208,7 @@ int DabModulator::process(Buffer* dataOut) rcs.enrol(cifGain.get()); auto cifGuard = make_shared<GuardIntervalInserter>( - myNbSymbols, mySpacing, myNullSize, mySymSize, + m_nbSymbols, m_spacing, m_nullSize, m_symSize, m_settings.ofdmWindowOverlap); rcs.enrol(cifGuard.get()); @@ -229,18 +230,21 @@ int DabModulator::process(Buffer* dataOut) cifRes = make_shared<Resampler>( 2048000, m_settings.outputRate, - mySpacing); + m_spacing); + } + + if (not m_format.empty()) { + m_formatConverter = make_shared<FormatConverter>(m_format); } -#endif - myOutput = make_shared<OutputMemory>(dataOut); + m_output = make_shared<OutputMemory>(dataOut); - myFlowgraph->connect(cifPrbs, cifMux); + m_flowgraph->connect(cifPrbs, cifMux); //////////////////////////////////////////////////////////////// // Processing FIC //////////////////////////////////////////////////////////////// - shared_ptr<FicSource> fic(myEtiSource.getFic()); + shared_ptr<FicSource> fic(m_etiSource.getFic()); //////////////////////////////////////////////////////////////// // Data initialisation //////////////////////////////////////////////////////////////// @@ -272,15 +276,15 @@ int DabModulator::process(Buffer* dataOut) PDEBUG(" Adding tail\n"); ficPunc->append_tail_rule(PuncturingRule(3, 0xcccccc)); - myFlowgraph->connect(fic, ficPrbs); - myFlowgraph->connect(ficPrbs, ficConv); - myFlowgraph->connect(ficConv, ficPunc); - myFlowgraph->connect(ficPunc, cifPart); + m_flowgraph->connect(fic, ficPrbs); + m_flowgraph->connect(ficPrbs, ficConv); + m_flowgraph->connect(ficConv, ficPunc); + m_flowgraph->connect(ficPunc, cifPart); //////////////////////////////////////////////////////////////// // Configuring subchannels //////////////////////////////////////////////////////////////// - for (const auto& subchannel : myEtiSource.getSubchannels()) { + for (const auto& subchannel : m_etiSource.getSubchannels()) { //////////////////////////////////////////////////////////// // Data initialisation @@ -332,59 +336,59 @@ int DabModulator::process(Buffer* dataOut) // Configuring time interleaver auto subchInterleaver = make_shared<TimeInterleaver>(subchSizeOut); - myFlowgraph->connect(subchannel, subchPrbs); - myFlowgraph->connect(subchPrbs, subchConv); - myFlowgraph->connect(subchConv, subchPunc); - myFlowgraph->connect(subchPunc, subchInterleaver); - myFlowgraph->connect(subchInterleaver, cifMux); + m_flowgraph->connect(subchannel, subchPrbs); + m_flowgraph->connect(subchPrbs, subchConv); + m_flowgraph->connect(subchConv, subchPunc); + m_flowgraph->connect(subchPunc, subchInterleaver); + m_flowgraph->connect(subchInterleaver, cifMux); } - myFlowgraph->connect(cifMux, cifPart); -#if defined(BUILD_FOR_EASYDABV3) - myFlowgraph->connect(cifPart, myOutput); -#else - myFlowgraph->connect(cifPart, cifMap); - myFlowgraph->connect(cifMap, cifFreq); - myFlowgraph->connect(cifRef, cifDiff); - myFlowgraph->connect(cifFreq, cifDiff); - myFlowgraph->connect(cifNull, cifSig); - myFlowgraph->connect(cifDiff, cifSig); + m_flowgraph->connect(cifMux, cifPart); + m_flowgraph->connect(cifPart, cifMap); + m_flowgraph->connect(cifMap, cifFreq); + m_flowgraph->connect(cifRef, cifDiff); + m_flowgraph->connect(cifFreq, cifDiff); + m_flowgraph->connect(cifNull, cifSig); + m_flowgraph->connect(cifDiff, cifSig); if (tii) { - myFlowgraph->connect(tiiRef, tii); - myFlowgraph->connect(tii, cifSig); + m_flowgraph->connect(tiiRef, tii); + m_flowgraph->connect(tii, cifSig); } shared_ptr<ModPlugin> prev_plugin = static_pointer_cast<ModPlugin>(cifSig); - const std::list<shared_ptr<ModPlugin> > plugins({ + const std::vector<shared_ptr<ModPlugin> > plugins({ static_pointer_cast<ModPlugin>(cifCicEq), static_pointer_cast<ModPlugin>(cifOfdm), static_pointer_cast<ModPlugin>(cifGain), static_pointer_cast<ModPlugin>(cifGuard), - static_pointer_cast<ModPlugin>(cifFilter), // optional block - static_pointer_cast<ModPlugin>(cifRes), // optional block - static_pointer_cast<ModPlugin>(cifPoly), // optional block - static_pointer_cast<ModPlugin>(myOutput), + // optional blocks + static_pointer_cast<ModPlugin>(cifFilter), + static_pointer_cast<ModPlugin>(cifRes), + static_pointer_cast<ModPlugin>(cifPoly), + static_pointer_cast<ModPlugin>(m_formatConverter), + // mandatory block + static_pointer_cast<ModPlugin>(m_output), }); for (auto& p : plugins) { if (p) { - myFlowgraph->connect(prev_plugin, p); + m_flowgraph->connect(prev_plugin, p); prev_plugin = p; } } -#endif + etiLog.level(debug) << "DabModulator set up."; } //////////////////////////////////////////////////////////////////// // Processing data //////////////////////////////////////////////////////////////////// - return myFlowgraph->run(); + return m_flowgraph->run(); } meta_vec_t DabModulator::process_metadata(const meta_vec_t& metadataIn) { - if (myOutput) { - return myOutput->get_latest_metadata(); + if (m_output) { + return m_output->get_latest_metadata(); } return {}; @@ -396,6 +400,9 @@ void DabModulator::set_parameter(const string& parameter, const string& value) if (parameter == "rate") { throw ParameterError("Parameter 'rate' is read-only"); } + else if (parameter == "num_clipped_samples") { + throw ParameterError("Parameter 'num_clipped_samples' is read-only"); + } else { stringstream ss; ss << "Parameter '" << parameter << @@ -410,6 +417,16 @@ const string DabModulator::get_parameter(const string& parameter) const if (parameter == "rate") { ss << m_settings.outputRate; } + else if (parameter == "num_clipped_samples") { + if (m_formatConverter) { + ss << m_formatConverter->get_num_clipped_samples(); + } + else { + ss << "Parameter '" << parameter << + "' is not available when no format conversion is done."; + throw ParameterError(ss.str()); + } + } else { ss << "Parameter '" << parameter << "' is not exported by controllable " << get_rc_name(); @@ -417,3 +434,11 @@ const string DabModulator::get_parameter(const string& parameter) const } return ss.str(); } + +const json::map_t DabModulator::get_all_values() const +{ + json::map_t map; + map["rate"].v = m_settings.outputRate; + map["num_clipped_samples"].v = m_formatConverter ? m_formatConverter->get_num_clipped_samples() : 0; + return map; +} |