aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/example.ini5
-rw-r--r--src/DabMod.cpp12
-rw-r--r--src/DabModulator.cpp13
-rw-r--r--src/DabModulator.h8
-rw-r--r--src/TII.cpp94
-rw-r--r--src/TII.h47
6 files changed, 143 insertions, 36 deletions
diff --git a/doc/example.ini b/doc/example.ini
index d99a966..d59223d 100644
--- a/doc/example.ini
+++ b/doc/example.ini
@@ -232,6 +232,7 @@ offset=0.002
[tii]
; (experimental)
; If these options are set, TII transmission is enabled.
-comb = 16
-pattern = 3
+enable=0
+comb=16
+pattern=3
diff --git a/src/DabMod.cpp b/src/DabMod.cpp
index 618e0fe..01125b2 100644
--- a/src/DabMod.cpp
+++ b/src/DabMod.cpp
@@ -132,8 +132,7 @@ int launch_modulator(int argc, char* argv[])
float normalise = 1.0f;
GainMode gainMode = GAIN_VAR;
- int tiiPattern = 0;
- int tiiComb = 0;
+ tii_config_t tiiConfig;
/* UHD requires the input I and Q samples to be in the interval
* [-1.0,1.0], otherwise they get truncated, which creates very
@@ -582,8 +581,9 @@ int launch_modulator(int argc, char* argv[])
#endif
/* Read TII parameters from config file */
- tiiComb = pt.get("tii.comb", 0);
- tiiPattern = 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);
}
if (rcs.get_no_controllers() == 0) {
@@ -755,8 +755,8 @@ int launch_modulator(int argc, char* argv[])
shared_ptr<InputMemory> input(new InputMemory(&m.data));
shared_ptr<DabModulator> modulator(
new DabModulator(tist_offset_s, tist_delay_stages, &rcs,
- outputRate, clockRate, dabMode, gainMode, digitalgain,
- normalise, filterTapsFilename, tiiComb, tiiPattern));
+ tiiConfig, outputRate, clockRate, dabMode, gainMode,
+ digitalgain, normalise, filterTapsFilename));
flowgraph.connect(input, modulator);
if (format_converter) {
diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp
index dbc6827..9d4647e 100644
--- a/src/DabModulator.cpp
+++ b/src/DabModulator.cpp
@@ -58,11 +58,11 @@ using namespace boost;
DabModulator::DabModulator(
double tist_offset_s, unsigned tist_delay_stages,
RemoteControllers* rcs,
+ const tii_config_t& tiiConfig,
unsigned outputRate, unsigned clockRate,
unsigned dabMode, GainMode gainMode,
float digGain, float normalise,
- std::string filterTapsFilename,
- int tiiComb, int tiiPattern
+ std::string filterTapsFilename
) :
ModCodec(ModFormat(1), ModFormat(0)),
myOutputRate(outputRate),
@@ -74,8 +74,7 @@ DabModulator::DabModulator(
myEtiReader(EtiReader(tist_offset_s, tist_delay_stages, rcs)),
myFlowgraph(NULL),
myFilterTapsFilename(filterTapsFilename),
- myTiiComb(tiiComb),
- myTiiPattern(tiiPattern),
+ myTiiConfig(tiiConfig),
myRCs(rcs)
{
PDEBUG("DabModulator::DabModulator(%u, %u, %u, %u) @ %p\n",
@@ -198,10 +197,8 @@ int DabModulator::process(Buffer* const dataIn, Buffer* dataOut)
(float)mySpacing * (float)myOutputRate / 2048000.0f,
cic_ratio));
- shared_ptr<TII> tii;
- if (myTiiComb != 0) {
- tii = make_shared<TII>(myDabMode, myTiiPattern, myTiiComb);
- }
+ shared_ptr<TII> tii = make_shared<TII>(myDabMode, myTiiConfig);
+ tii->enrol_at(*myRCs);
shared_ptr<OfdmGenerator> cifOfdm(
new OfdmGenerator((1 + myNbSymbols), myNbCarriers, mySpacing));
diff --git a/src/DabModulator.h b/src/DabModulator.h
index 48cdd42..cee066a 100644
--- a/src/DabModulator.h
+++ b/src/DabModulator.h
@@ -43,6 +43,7 @@
#include "OutputMemory.h"
#include "RemoteControl.h"
#include "Log.h"
+#include "TII.h"
class DabModulator : public ModCodec
@@ -51,11 +52,11 @@ public:
DabModulator(
double tist_offset_s, unsigned tist_delay_stages,
RemoteControllers* rcs,
+ const tii_config_t& tiiConfig,
unsigned outputRate = 2048000, unsigned clockRate = 0,
unsigned dabMode = 0, GainMode gainMode = GAIN_VAR,
float digGain = 1.0, float normalise = 1.0,
- std::string filterTapsFilename = "",
- int tiiComb = 0, int tiiPattern = 0);
+ std::string filterTapsFilename = "");
DabModulator(const DabModulator& copy);
virtual ~DabModulator();
@@ -78,8 +79,7 @@ protected:
Flowgraph* myFlowgraph;
OutputMemory* myOutput;
std::string myFilterTapsFilename;
- int myTiiComb;
- int myTiiPattern;
+ tii_config_t myTiiConfig;
RemoteControllers* myRCs;
size_t myNbSymbols;
diff --git a/src/TII.cpp b/src/TII.cpp
index 5c85302..6d969a5 100644
--- a/src/TII.cpp
+++ b/src/TII.cpp
@@ -106,19 +106,20 @@ 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, unsigned int comb, unsigned int pattern) :
+TII::TII(unsigned int dabmode, const tii_config_t& tii_config) :
ModCodec(ModFormat(0), ModFormat(0)),
+ RemoteControllable("tii"),
m_dabmode(dabmode),
- m_comb(comb),
- m_pattern(pattern),
+ m_enable(tii_config.enable),
+ m_comb(tii_config.comb),
+ m_pattern(tii_config.pattern),
m_insert(true)
{
PDEBUG("TII::TII(%u) @ %p\n", dabmode, this);
- std::stringstream ss;
- ss << "TII(comb:" << m_comb << ", pattern:" << m_pattern << ")";
- m_name = ss.str();
+ 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]");
switch (m_dabmode) {
case 1:
@@ -152,7 +153,7 @@ TII::TII(unsigned int dabmode, unsigned int comb, unsigned int pattern) :
throw std::runtime_error(ss_exception.str());
}
- if (not(0 < m_comb and m_comb <= 23) ) {
+ if (not(0 <= m_comb and m_comb <= 23) ) {
throw std::runtime_error(
"TII::TII comb not valid!");
}
@@ -170,6 +171,17 @@ TII::~TII()
PDEBUG("TII::~TII() @ %p\n", this);
}
+const char* TII::name()
+{
+ // Calculate name on demand because comb and pattern are
+ // modifiable through RC
+ std::stringstream ss;
+ ss << "TII(comb:" << m_comb << ", pattern:" << m_pattern << ")";
+ m_name = ss.str();
+
+ return m_name.c_str();
+}
+
int TII::process(Buffer* const dataIn, Buffer* dataOut)
{
@@ -181,7 +193,8 @@ int TII::process(Buffer* const dataIn, Buffer* dataOut)
"TII::process input size not valid!");
}
- if (m_insert) {
+ if (m_enable and m_insert) {
+ boost::mutex::scoped_lock lock(m_dataIn_mutex);
dataOut->setData(&m_dataIn[0], m_carriers * sizeof(complexf));
}
else {
@@ -211,6 +224,13 @@ void TII::enable_carrier(int k) {
void TII::prepare_pattern() {
int comb = m_comb; // Convert from unsigned to signed
+ boost::mutex::scoped_lock lock(m_dataIn_mutex);
+
+ // Clear previous pattern
+ for (size_t i = 0; i < m_dataIn.size(); i++) {
+ m_dataIn[i] = 0.0;
+ }
+
// This could be written more efficiently, but since it is
// not performance-critial, it makes sense to write it
// in the same way as the specification in
@@ -273,10 +293,66 @@ void TII::prepare_pattern() {
throw std::runtime_error(
"TII::TII DAB mode not valid!");
}
+}
+
+void TII::set_parameter(const std::string& parameter, const std::string& value)
+{
+ using namespace std;
+ stringstream ss(value);
+ ss.exceptions ( stringstream::failbit | stringstream::badbit );
+ if (parameter == "enable") {
+ ss >> m_enable;
+ }
+ else if (parameter == "pattern") {
+ int new_pattern;
+ ss >> new_pattern;
+ if ( (m_dabmode == 1 or m_dabmode == 2) and
+ not(0 <= new_pattern and new_pattern <= 69) ) {
+ throw std::runtime_error(
+ "TII pattern not valid!");
+ }
+ m_pattern = new_pattern;
+ prepare_pattern();
+ }
+ else if (parameter == "comb") {
+ int new_comb;
+ ss >> new_comb;
+ if (not(0 <= new_comb and new_comb <= 23) ) {
+ throw std::runtime_error(
+ "TII comb not valid!");
+ }
+ m_comb = new_comb;
+ prepare_pattern();
+ }
+ else {
+ stringstream ss;
+ ss << "Parameter '" << parameter << "' is not exported by controllable " << get_rc_name();
+ throw ParameterError(ss.str());
+ }
+}
+const std::string TII::get_parameter(const std::string& parameter) const
+{
+ using namespace std;
+ stringstream ss;
+ if (parameter == "enable") {
+ ss << (m_enable ? 1 : 0);
+ }
+ else if (parameter == "pattern") {
+ ss << m_pattern;
+ }
+ else if (parameter == "comb") {
+ ss << m_comb;
+ }
+ else {
+ ss << "Parameter '" << parameter << "' is not exported by controllable " << get_rc_name();
+ throw ParameterError(ss.str());
+ }
+ return ss.str();
}
+
#ifdef TII_TEST
int main(int argc, char** argv)
{
diff --git a/src/TII.h b/src/TII.h
index 44f37ce..b241bed 100644
--- a/src/TII.h
+++ b/src/TII.h
@@ -6,6 +6,8 @@
Matthias P. Braendli, matthias.braendli@mpb.li
http://opendigitalradio.org
+
+ TII generation according to ETSI EN 300 401 Clause 14.8
*/
/*
This file is part of ODR-DabMod.
@@ -32,36 +34,67 @@
#endif
#include "ModCodec.h"
+#include "RemoteControl.h"
+#include <boost/thread.hpp>
#include <sys/types.h>
#include <complex>
#include <vector>
#include <string>
-class TII : public ModCodec
+struct tii_config_t
+{
+ tii_config_t() : enable(false), comb(0), pattern(0) {}
+
+ bool enable;
+ int comb;
+ int pattern;
+};
+
+class TII : public ModCodec, public RemoteControllable
{
public:
- TII(unsigned int dabmode, unsigned int comb, unsigned int pattern);
+ TII(unsigned int dabmode, const tii_config_t& tii_config);
virtual ~TII();
int process(Buffer* const dataIn, Buffer* dataOut);
- const char* name() { return m_name.c_str(); };
+ const char* name();
+
+ /******* REMOTE CONTROL ********/
+ virtual void set_parameter(const std::string& parameter,
+ const std::string& value);
+
+ virtual const std::string get_parameter(
+ const std::string& parameter) const;
+
protected:
+ // Fill m_dataIn with the correct carriers for the pattern/comb
+ // combination
+ void prepare_pattern(void);
+
+ // prerequisites: calling thread must hold m_dataIn mutex
+ void enable_carrier(int k);
+
+ // Configuration settings
unsigned int m_dabmode;
+
+ // Remote-controllable settings
+ bool m_enable;
unsigned int m_comb;
unsigned int m_pattern;
+ // Internal flag when to insert TII
bool m_insert;
size_t m_carriers;
std::string m_name;
- std::vector<std::complex<float> > m_dataIn;
- void prepare_pattern(void);
-
- void enable_carrier(int k);
+ // m_dataIn 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&);