diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2017-02-24 10:39:22 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2017-02-24 10:39:22 +0100 |
commit | ebe96d69b44d73875f922a7fc59da02695969b00 (patch) | |
tree | e20362ae9ee188ba4850276042c743892e1d8102 | |
parent | c6ddb4451138005bbf678ee75d6de690a165faa2 (diff) | |
download | dabmod-ebe96d69b44d73875f922a7fc59da02695969b00.tar.gz dabmod-ebe96d69b44d73875f922a7fc59da02695969b00.tar.bz2 dabmod-ebe96d69b44d73875f922a7fc59da02695969b00.zip |
Change phase of TII carriers
This adapts the patch contributed by Piratfm to the next branch
-rw-r--r-- | doc/example.ini | 7 | ||||
-rw-r--r-- | src/DabMod.cpp | 7 | ||||
-rw-r--r-- | src/DabModulator.cpp | 5 | ||||
-rw-r--r-- | src/TII.cpp | 75 | ||||
-rw-r--r-- | src/TII.h | 49 |
5 files changed, 100 insertions, 43 deletions
diff --git a/doc/example.ini b/doc/example.ini index 6887972..bdb3f00 100644 --- a/doc/example.ini +++ b/doc/example.ini @@ -270,4 +270,9 @@ offset=0.002 enable=0 comb=16 pattern=3 - +; There are two variants of TII being used. The old variant that uses the wrong +; phase on the second carrier in each carrier pairs and is therefore not +; conforming to the specification. Modern analysers can decode both variants, +; while others, like the Philips DAB752 and the VAD v2 monitor are known to +; decode only the old non-conforming variant. +old_variant=0 diff --git a/src/DabMod.cpp b/src/DabMod.cpp index 526670d..37db71a 100644 --- a/src/DabMod.cpp +++ b/src/DabMod.cpp @@ -588,9 +588,10 @@ int launch_modulator(int argc, char* argv[]) #endif /* Read TII parameters from config file */ - tiiConfig.enable = pt.get("tii.enable", 0); - tiiConfig.comb = pt.get("tii.comb", 0); - tiiConfig.pattern = pt.get("tii.pattern", 0); + tiiConfig.enable = pt.get("tii.enable", 0); + tiiConfig.comb = pt.get("tii.comb", 0); + tiiConfig.pattern = pt.get("tii.pattern", 0); + tiiConfig.old_variant = pt.get("tii.old_variant", 0); } etiLog.level(info) << "Starting up version " << diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp index 827b73f..678d175 100644 --- a/src/DabModulator.cpp +++ b/src/DabModulator.cpp @@ -187,9 +187,11 @@ int DabModulator::process(Buffer* dataOut) (float)mySpacing * (float)myOutputRate / 2048000.0f, cic_ratio); shared_ptr<TII> tii; + shared_ptr<PhaseReference> tiiRef; try { - tii = make_shared<TII>(myDabMode, myTiiConfig); + tii = make_shared<TII>(myDabMode, myTiiConfig, myEtiSource.getFp()); rcs.enrol(tii.get()); + tiiRef = make_shared<PhaseReference>(mode); } catch (TIIError& e) { etiLog.level(error) << "Could not initialise TII: " << e.what(); @@ -331,6 +333,7 @@ int DabModulator::process(Buffer* dataOut) myFlowgraph->connect(cifNull, cifSig); myFlowgraph->connect(cifDiff, cifSig); if (tii) { + myFlowgraph->connect(tiiRef, tii); myFlowgraph->connect(tii, cifSig); } diff --git a/src/TII.cpp b/src/TII.cpp index 15543d0..6bc3f0d 100644 --- a/src/TII.cpp +++ b/src/TII.cpp @@ -2,7 +2,7 @@ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2015 + Copyright (C) 2017 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -106,22 +106,23 @@ const int pattern_tm1_2_4[][8] = { // {{{ {1,1,1,0,1,0,0,0}, {1,1,1,1,0,0,0,0} }; // }}} -TII::TII(unsigned int dabmode, tii_config_t& tii_config) : - ModInput(), +TII::TII(unsigned int dabmode, tii_config_t& tii_config, unsigned phase) : + ModCodec(), RemoteControllable("tii"), m_dabmode(dabmode), - m_conf(tii_config), - m_insert(true) + m_conf(tii_config) { PDEBUG("TII::TII(%u) @ %p\n", dabmode, this); RC_ADD_PARAMETER(enable, "enable TII [0-1]"); RC_ADD_PARAMETER(comb, "TII comb number [0-23]"); RC_ADD_PARAMETER(pattern, "TII pattern number [0-69]"); + RC_ADD_PARAMETER(old_variant, "select old TII variant for old (buggy) receivers [0-1]"); switch (m_dabmode) { case 1: m_carriers = 1536; + m_insert = (phase & 0x40) ? false : true; if (not(0 <= m_conf.pattern and m_conf.pattern <= 69) ) { throw TIIError("TII::TII pattern not valid!"); @@ -129,6 +130,7 @@ TII::TII(unsigned int dabmode, tii_config_t& tii_config) : break; case 2: m_carriers = 384; + m_insert = (phase & 0x01) ? false : true; if (not(0 <= m_conf.pattern and m_conf.pattern <= 69) ) { throw TIIError("TII::TII pattern not valid!"); @@ -153,8 +155,8 @@ TII::TII(unsigned int dabmode, tii_config_t& tii_config) : throw TIIError("TII::TII comb not valid!"); } - m_dataIn.clear(); - m_dataIn.resize(m_carriers); + m_enabled_carriers.clear(); + m_enabled_carriers.resize(m_carriers); prepare_pattern(); } @@ -169,28 +171,47 @@ const char* TII::name() // Calculate name on demand because comb and pattern are // modifiable through RC std::stringstream ss; - ss << "TII(comb:" << m_conf.comb << ", pattern:" << m_conf.pattern << ")"; + ss << "TII(comb:" << m_conf.comb << + ", pattern:" << m_conf.pattern << + ", variant:" << (m_conf.old_variant ? "old" : "new") << ")"; m_name = ss.str(); return m_name.c_str(); } -int TII::process(Buffer* dataOut) +int TII::process(Buffer* dataIn, Buffer* dataOut) { PDEBUG("TII::process(dataOut: %p)\n", dataOut); + if ( (dataIn == NULL) or + (dataIn->getLength() != m_carriers * sizeof(complexf))) { + throw TIIError("TII::process input size not valid!"); + } + + dataOut->setLength(m_carriers * sizeof(complexf)); + bzero(dataOut->getData(), dataOut->getLength()); if (m_conf.enable and m_insert) { - boost::mutex::scoped_lock lock(m_dataIn_mutex); - dataOut->setData(&m_dataIn[0], m_carriers * sizeof(complexf)); - } - else { - dataOut->setLength(m_carriers * sizeof(complexf)); - bzero(dataOut->getData(), dataOut->getLength()); + boost::mutex::scoped_lock lock(m_enabled_carriers_mutex); + complexf* in = reinterpret_cast<complexf*>(dataIn->getData()); + complexf* out = reinterpret_cast<complexf*>(dataOut->getData()); + + for (size_t i = 0; i < m_enabled_carriers.size(); i+=2) { + //BAD implementation: + // setting exactly the same phase of the signal for lower adjacent + // frequency + if (m_enabled_carriers[i]) { + out[i] = m_conf.old_variant ? in[i+1] : in[i]; + } + + if (m_enabled_carriers[i+1]) { + out[i+1] = in[i+1]; + } + } } - // TODO wrong! Must align with frames containing the right data + // Align with frames containing the right data (when FC.fp is first quarter) m_insert = not m_insert; return 1; @@ -199,23 +220,25 @@ int TII::process(Buffer* dataOut) void TII::enable_carrier(int k) { int ix = m_carriers/2 + k; - if (ix < 0 or ix+1 >= (ssize_t)m_dataIn.size()) { + if (ix < 0 or ix+1 >= (ssize_t)m_enabled_carriers.size()) { throw TIIError("TII::enable_carrier invalid k!"); } - // TODO power of the carrier ? - m_dataIn.at(ix) = 1.0; - m_dataIn.at(ix+1) = 1.0; // TODO verify if +1 is really correct + m_enabled_carriers[ix] = true; + // NULL frequency is never enabled. + if (ix > 1 and (ix-1 != 768)) { + m_enabled_carriers[ix-1] = true; + } } void TII::prepare_pattern() { int comb = m_conf.comb; // Convert from unsigned to signed - boost::mutex::scoped_lock lock(m_dataIn_mutex); + boost::mutex::scoped_lock lock(m_enabled_carriers_mutex); // Clear previous pattern - for (size_t i = 0; i < m_dataIn.size(); i++) { - m_dataIn[i] = 0.0; + for (size_t i = 0; i < m_enabled_carriers.size(); i++) { + m_enabled_carriers[i] = false; } // This could be written more efficiently, but since it is @@ -309,6 +332,9 @@ void TII::set_parameter(const std::string& parameter, const std::string& value) m_conf.comb = new_comb; prepare_pattern(); } + else if (parameter == "old_variant") { + ss >> m_conf.old_variant; + } else { stringstream ss; ss << "Parameter '" << parameter << @@ -330,6 +356,9 @@ const std::string TII::get_parameter(const std::string& parameter) const else if (parameter == "comb") { ss << m_conf.comb; } + else if (parameter == "old_variant") { + ss << (m_conf.old_variant ? 1 : 0); + } else { ss << "Parameter '" << parameter << "' is not exported by controllable " << get_rc_name(); @@ -2,7 +2,7 @@ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2015 + Copyright (C) 2017 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -43,11 +43,33 @@ struct tii_config_t { - tii_config_t() : enable(false), comb(0), pattern(0) {} + tii_config_t() : enable(false), comb(0), pattern(0), old_variant(false) {} bool enable; int comb; int pattern; + + /* EN 300 401 clause 14.8 describes how to generate the TII signal, and + * defines z_{m,0,k}: + * + * z_{m,0,k} = A_{c,p}(k) e^{j \psi_k} + A_{c,p}(k-1) e^{j \psi{k-1}} + * + * What was implemented in the old variant was + * + * z_{m,0,k} = A_{c,p}(k) e^{j \psi_k} + A_{c,p}(k-1) e^{j \psi{k}} + * ^ + * | + * Wrong phase on the second + * carrier of the pair. + * + * Correctly implemented decoders ought to be able to decode such a TII, + * but will not be able to correctly estimate the delay of different + * transmitters. + * + * The option 'old_variant' allows the user to choose between this + * old incorrect implementation and the new conforming one. + */ + bool old_variant; }; class TIIError : public std::runtime_error { @@ -58,13 +80,15 @@ class TIIError : public std::runtime_error { std::runtime_error(msg) {} }; -class TII : public ModInput, public RemoteControllable +class TII : public ModCodec, public RemoteControllable { public: - TII(unsigned int dabmode, tii_config_t& tii_config); + TII(unsigned int dabmode, tii_config_t& tii_config, unsigned phase); virtual ~TII(); + TII(const TII&) = delete; + TII& operator=(const TII&) = delete; - int process(Buffer* dataOut); + int process(Buffer* dataIn, Buffer* dataOut); const char* name(); /******* REMOTE CONTROL ********/ @@ -74,13 +98,12 @@ class TII : public ModInput, public RemoteControllable virtual const std::string get_parameter( const std::string& parameter) const; - protected: - // Fill m_dataIn with the correct carriers for the pattern/comb + // Fill m_enabled_carriers with the correct carriers for the pattern/comb // combination void prepare_pattern(void); - // prerequisites: calling thread must hold m_dataIn mutex + // prerequisites: calling thread must hold m_enabled_carriers mutex void enable_carrier(int k); // Configuration settings @@ -96,14 +119,10 @@ class TII : public ModInput, public RemoteControllable std::string m_name; - // m_dataIn is read by modulator thread, and written + // m_enabled_carriers is read by modulator thread, and written // to by RC thread. - mutable boost::mutex m_dataIn_mutex; - std::vector<std::complex<float> > m_dataIn; - - private: - TII(const TII&); - TII& operator=(const TII&); + mutable boost::mutex m_enabled_carriers_mutex; + std::vector<bool> m_enabled_carriers; }; |