aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/example.ini17
-rw-r--r--src/DabMod.cpp64
-rw-r--r--src/DabModulator.cpp4
-rw-r--r--src/DabModulator.h2
-rw-r--r--src/EtiReader.cpp12
-rw-r--r--src/EtiReader.h3
-rw-r--r--src/OutputUHD.cpp2
-rw-r--r--src/OutputUHD.h2
-rw-r--r--src/TimestampDecoder.cpp100
-rw-r--r--src/TimestampDecoder.h64
-rw-r--r--src/Utils.cpp5
11 files changed, 104 insertions, 171 deletions
diff --git a/doc/example.ini b/doc/example.ini
index d7f0a4f..322bbe9 100644
--- a/doc/example.ini
+++ b/doc/example.ini
@@ -221,16 +221,11 @@ synchronous=0
; Whether to mute the TX when incoming frames have no timestamp
mutenotimestamps=0
-; Choose between fixed and dynamic offset definition
-; fixed defines an offset in this file that cannot be changed while
-; the modulator runs.
-;
-; dynamic reads the offset from a file, and if the value changes,
-; the chain does a re-sync.
-management=dynamic
+; This iffset is added to the TIST, and the sum defines the
+; TX time of the transmission frame. It can by changed at runtime
+; through the remote control.
+offset=0.002
-fixedoffset=0.002
+; The previous static vs dynamic offset distinction, and reading the
+; modulatoroffset from a file has been removed.
-; The file should contain a single floating point value, written
-; in ASCII (it's human-readable, not binary)
-dynamicoffsetfile=modulator_offset
diff --git a/src/DabMod.cpp b/src/DabMod.cpp
index 045138a..1fc7e3c 100644
--- a/src/DabMod.cpp
+++ b/src/DabMod.cpp
@@ -157,10 +157,8 @@ int launch_modulator(int argc, char* argv[])
modulator_data m;
// To handle the timestamp offset of the modulator
- struct modulator_offset_config modconf;
- modconf.use_offset_file = false;
- modconf.use_offset_fixed = false;
- modconf.delay_calculation_pipeline_stages = 0;
+ unsigned tist_delay_stages = 0;
+ double tist_offset_s = 0.0;
shared_ptr<Flowgraph> flowgraph(new Flowgraph());
shared_ptr<FormatConverter> format_converter;
@@ -238,25 +236,7 @@ int launch_modulator(int argc, char* argv[])
loop = true;
break;
case 'o':
- if (modconf.use_offset_file)
- {
- fprintf(stderr, "Options -o and -O are mutually exclusive\n");
- throw std::invalid_argument("Invalid command line options");
- }
- modconf.use_offset_fixed = true;
- modconf.offset_fixed = strtod(optarg, NULL);
-#if defined(HAVE_OUTPUT_UHD)
- outputuhd_conf.enableSync = true;
-#endif
- break;
- case 'O':
- if (modconf.use_offset_fixed)
- {
- fprintf(stderr, "Options -o and -O are mutually exclusive\n");
- throw std::invalid_argument("Invalid command line options");
- }
- modconf.use_offset_file = true;
- modconf.offset_filename = std::string(optarg);
+ tist_offset_s = strtod(optarg, NULL);
#if defined(HAVE_OUTPUT_UHD)
outputuhd_conf.enableSync = true;
#endif
@@ -578,23 +558,20 @@ int launch_modulator(int argc, char* argv[])
#if defined(HAVE_OUTPUT_UHD)
outputuhd_conf.enableSync = (pt.get("delaymanagement.synchronous", 0) == 1);
if (outputuhd_conf.enableSync) {
+ std::string delay_mgmt = pt.get<std::string>("delaymanagement.management", "");
+ std::string fixedoffset = pt.get<std::string>("delaymanagement.fixedoffset", "");
+ std::string offset_filename = pt.get<std::string>("delaymanagement.dynamicoffsetfile", "");
+
+ if (not(delay_mgmt.empty() and fixedoffset.empty() and offset_filename.empty())) {
+ std::cerr << "Warning: you are using the old config syntax for the offset management.\n";
+ std::cerr << " Please see the example.ini configuration for the new settings.\n";
+ }
+
try {
- std::string delay_mgmt = pt.get<std::string>("delaymanagement.management");
- if (delay_mgmt == "fixed") {
- modconf.offset_fixed = pt.get<double>("delaymanagement.fixedoffset");
- modconf.use_offset_fixed = true;
- }
- else if (delay_mgmt == "dynamic") {
- modconf.offset_filename = pt.get<std::string>("delaymanagement.dynamicoffsetfile");
- modconf.use_offset_file = true;
- }
- else {
- throw std::runtime_error("invalid management value");
- }
+ tist_offset_s = pt.get<double>("delaymanagement.offset");
}
catch (std::exception &e) {
- std::cerr << "Error: " << e.what() << "\n";
- std::cerr << " Synchronised transmission enabled, but delay management specification is incomplete.\n";
+ std::cerr << "Error: delaymanagement: synchronous is enabled, but no offset defined!\n";
throw std::runtime_error("Configuration error");
}
}
@@ -611,16 +588,10 @@ int launch_modulator(int argc, char* argv[])
etiLog.level(info) << "Starting up";
- if (!(modconf.use_offset_file || modconf.use_offset_fixed)) {
- etiLog.level(debug) << "No Modulator offset defined, setting to 0";
- modconf.use_offset_fixed = true;
- modconf.offset_fixed = 0;
- }
-
// When using the FIRFilter, increase the modulator offset pipelining delay
// by the correct amount
if (filterTapsFilename != "") {
- modconf.delay_calculation_pipeline_stages += FIRFILTER_PIPELINE_DELAY;
+ tist_delay_stages += FIRFILTER_PIPELINE_DELAY;
}
// Setting ETI input filename
@@ -777,8 +748,9 @@ int launch_modulator(int argc, char* argv[])
shared_ptr<InputMemory> input(new InputMemory(&m.data));
shared_ptr<DabModulator> modulator(
- new DabModulator(modconf, &rcs, outputRate, clockRate,
- dabMode, gainMode, digitalgain, normalise, filterTapsFilename));
+ new DabModulator(tist_offset_s, tist_delay_stages, &rcs,
+ 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 4769502..35ef7cb 100644
--- a/src/DabModulator.cpp
+++ b/src/DabModulator.cpp
@@ -55,7 +55,7 @@
using namespace boost;
DabModulator::DabModulator(
- struct modulator_offset_config& modconf,
+ double tist_offset_s, unsigned tist_delay_stages,
RemoteControllers* rcs,
unsigned outputRate, unsigned clockRate,
unsigned dabMode, GainMode gainMode,
@@ -69,7 +69,7 @@ DabModulator::DabModulator(
myGainMode(gainMode),
myDigGain(digGain),
myNormalise(normalise),
- myEtiReader(EtiReader(modconf)),
+ myEtiReader(EtiReader(tist_offset_s, tist_delay_stages, rcs)),
myFlowgraph(NULL),
myFilterTapsFilename(filterTapsFilename),
myRCs(rcs)
diff --git a/src/DabModulator.h b/src/DabModulator.h
index 5337f8c..1a9e477 100644
--- a/src/DabModulator.h
+++ b/src/DabModulator.h
@@ -49,7 +49,7 @@ class DabModulator : public ModCodec
{
public:
DabModulator(
- struct modulator_offset_config& modconf,
+ double tist_offset_s, unsigned tist_delay_stages,
RemoteControllers* rcs,
unsigned outputRate = 2048000, unsigned clockRate = 0,
unsigned dabMode = 0, GainMode gainMode = GAIN_VAR,
diff --git a/src/EtiReader.cpp b/src/EtiReader.cpp
index 100fbdb..2f088d5 100644
--- a/src/EtiReader.cpp
+++ b/src/EtiReader.cpp
@@ -51,13 +51,16 @@ enum ETI_READER_STATE {
};
-EtiReader::EtiReader(struct modulator_offset_config& modconf) :
+EtiReader::EtiReader(double tist_offset_s, unsigned tist_delay_stages,
+ RemoteControllers* rcs) :
state(EtiReaderStateSync),
myFicSource(NULL),
- myTimestampDecoder(modconf)
+ myTimestampDecoder(tist_offset_s, tist_delay_stages)
{
PDEBUG("EtiReader::EtiReader()\n");
+ myTimestampDecoder.enrol_at(*rcs);
+
myCurrentFrame = 0;
eti_fc_valid = false;
}
@@ -284,11 +287,6 @@ int EtiReader::process(const Buffer* dataIn)
myTimestampDecoder.updateTimestampEti(eti_fc.FP & 0x3,
eti_eoh.MNSC, getPPSOffset(), eti_fc.FCT);
- if (eti_fc.FCT % 125 == 0) //every 3 seconds is fine enough
- {
- myTimestampDecoder.updateModulatorOffset();
- }
-
return dataIn->getLength() - input_size;
}
diff --git a/src/EtiReader.h b/src/EtiReader.h
index 58a1976..e3b8b0e 100644
--- a/src/EtiReader.h
+++ b/src/EtiReader.h
@@ -47,7 +47,8 @@
class EtiReader
{
public:
- EtiReader(struct modulator_offset_config& modconf);
+ EtiReader(double tist_offset_s, unsigned tist_delay_stages,
+ RemoteControllers* rcs);
virtual ~EtiReader();
EtiReader(const EtiReader&);
EtiReader& operator=(const EtiReader&);
diff --git a/src/OutputUHD.cpp b/src/OutputUHD.cpp
index 24d206f..72d4976 100644
--- a/src/OutputUHD.cpp
+++ b/src/OutputUHD.cpp
@@ -2,7 +2,7 @@
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Her Majesty the
Queen in Right of Canada (Communications Research Center Canada)
- Copyright (C) 2014
+ Copyright (C) 2014, 2015
Matthias P. Braendli, matthias.braendli@mpb.li
http://opendigitalradio.org
diff --git a/src/OutputUHD.h b/src/OutputUHD.h
index 44dd0ff..bf5b27d 100644
--- a/src/OutputUHD.h
+++ b/src/OutputUHD.h
@@ -2,7 +2,7 @@
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Her Majesty the
Queen in Right of Canada (Communications Research Center Canada)
- Copyright (C) 2014
+ Copyright (C) 2014, 2015
Matthias P. Braendli, matthias.braendli@mpb.li
http://opendigitalradio.org
diff --git a/src/TimestampDecoder.cpp b/src/TimestampDecoder.cpp
index c833e7a..b03ecbb 100644
--- a/src/TimestampDecoder.cpp
+++ b/src/TimestampDecoder.cpp
@@ -2,7 +2,7 @@
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Her Majesty the
Queen in Right of Canada (Communications Research Center Canada)
- Copyright (C) 2014
+ Copyright (C) 2014, 2015
Matthias P. Braendli, matthias.braendli@mpb.li
http://opendigitalradio.org
@@ -62,8 +62,8 @@ void TimestampDecoder::calculateTimestamp(struct frame_timestamp& ts)
*
* Therefore, use <= and not < for comparison
*/
- if (queue_timestamps.size() <= modconfig.delay_calculation_pipeline_stages) {
- //fprintf(stderr, "* %zu %u ", queue_timestamps.size(), modconfig.delay_calculation_pipeline_stages);
+ if (queue_timestamps.size() <= m_tist_delay_stages) {
+ //fprintf(stderr, "* %zu %u ", queue_timestamps.size(), m_tist_delay_stages);
/* Return invalid timestamp until the queue is full */
ts.timestamp_valid = false;
ts.timestamp_sec = 0;
@@ -93,9 +93,9 @@ void TimestampDecoder::calculateTimestamp(struct frame_timestamp& ts)
MDEBUG("Timestamp queue size %zu, delay_calc %u\n",
queue_timestamps.size(),
- modconfig.delay_calculation_pipeline_stages);
+ m_tist_delay_stages);
- if (queue_timestamps.size() > modconfig.delay_calculation_pipeline_stages) {
+ if (queue_timestamps.size() > m_tist_delay_stages) {
etiLog.level(error) << "Error: Timestamp queue is too large : size " <<
queue_timestamps.size() << "! This should not happen !";
}
@@ -198,77 +198,41 @@ void TimestampDecoder::updateTimestampEti(
latestFCT = fct;
}
-
-bool TimestampDecoder::updateModulatorOffset()
+void TimestampDecoder::set_parameter(
+ const std::string& parameter,
+ const std::string& value)
{
using namespace std;
- using boost::lexical_cast;
- using boost::bad_lexical_cast;
-
- if (modconfig.use_offset_fixed)
- {
- timestamp_offset = modconfig.offset_fixed;
- return true;
- }
- else if (modconfig.use_offset_file)
- {
- bool r = false;
- double newoffset;
- std::string filedata;
- ifstream filestream;
+ stringstream ss(value);
+ ss.exceptions ( stringstream::failbit | stringstream::badbit );
- try
- {
- filestream.open(modconfig.offset_filename.c_str());
- if (!filestream.eof())
- {
- getline(filestream, filedata);
- try
- {
- newoffset = lexical_cast<double>(filedata);
- r = true;
- }
- catch (bad_lexical_cast& e)
- {
- etiLog.level(error) <<
- "Error parsing timestamp offset from file '" <<
- modconfig.offset_filename << "'";
- r = false;
- }
- }
- else
- {
- etiLog.level(error) <<
- "Error reading from timestamp offset file: eof reached\n";
- r = false;
- }
- filestream.close();
- }
- catch (exception& e)
- {
- etiLog.level(error) << "Error opening timestamp offset file\n";
- r = false;
- }
-
-
- if (r)
- {
- if (timestamp_offset != newoffset)
- {
- timestamp_offset = newoffset;
- etiLog.level(info) <<
- "TimestampDecoder::updateTimestampOffset: new offset is " <<
- timestamp_offset;
- offset_changed = true;
- }
+ if (parameter == "offset") {
+ ss >> timestamp_offset;
+ offset_changed = true;
+ }
+ else {
+ stringstream ss;
+ ss << "Parameter '" << parameter
+ << "' is not exported by controllable " << get_rc_name();
+ throw ParameterError(ss.str());
+ }
+}
- }
+const std::string TimestampDecoder::get_parameter(
+ const std::string& parameter) const
+{
+ using namespace std;
- return r;
+ stringstream ss;
+ if (parameter == "offset") {
+ ss << timestamp_offset;
}
else {
- return false;
+ ss << "Parameter '" << parameter <<
+ "' is not exported by controllable " << get_rc_name();
+ throw ParameterError(ss.str());
}
+ return ss.str();
}
diff --git a/src/TimestampDecoder.h b/src/TimestampDecoder.h
index 82753d1..1b805ca 100644
--- a/src/TimestampDecoder.h
+++ b/src/TimestampDecoder.h
@@ -2,7 +2,7 @@
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Her Majesty the
Queen in Right of Canada (Communications Research Center Canada)
- Copyright (C) 2014
+ Copyright (C) 2014, 2015
Matthias P. Braendli, matthias.braendli@mpb.li
http://opendigitalradio.org
@@ -34,23 +34,7 @@
#include <stdio.h>
#include "Eti.h"
#include "Log.h"
-
-struct modulator_offset_config
-{
- bool use_offset_fixed;
- double offset_fixed;
- /* These two fields are used when the modulator is run with a fixed offset */
-
- bool use_offset_file;
- std::string offset_filename;
- /* These two fields are used when the modulator reads the offset from a file */
-
- unsigned delay_calculation_pipeline_stages;
- /* Specifies by how many stages the timestamp must be delayed.
- * (e.g. The FIRFilter is pipelined, therefore we must increase
- * delay_calculation_pipeline_stages by one if the filter is used
- */
-};
+#include "RemoteControl.h"
struct frame_timestamp
{
@@ -109,13 +93,24 @@ struct frame_timestamp
};
/* This module decodes MNSC time information */
-class TimestampDecoder
+class TimestampDecoder : public RemoteControllable
{
public:
TimestampDecoder(
- struct modulator_offset_config& config) :
- modconfig(config)
+ /* The modulator adds this offset to the TIST to define time of
+ * frame transmission
+ */
+ double offset_s,
+
+ /* Specifies by how many stages the timestamp must be delayed.
+ * (e.g. The FIRFilter is pipelined, therefore we must increase
+ * tist_delay_stages by one if the filter is used
+ */
+ unsigned tist_delay_stages) :
+ RemoteControllable("tist")
{
+ timestamp_offset = offset_s;
+ m_tist_delay_stages = tist_delay_stages;
inhibit_second_update = 0;
time_pps = 0.0;
time_secs = 0;
@@ -125,10 +120,10 @@ class TimestampDecoder
gmtime_r(0, &temp_time);
offset_changed = false;
+ RC_ADD_PARAMETER(offset, "TIST offset [s]");
+
etiLog.level(info) << "Setting up timestamp decoder with " <<
- (modconfig.use_offset_fixed ? "fixed" :
- (modconfig.use_offset_file ? "dynamic" : "none")) <<
- " offset";
+ timestamp_offset << " offset";
};
@@ -142,9 +137,21 @@ class TimestampDecoder
double pps,
int32_t fct);
- /* Update the modulator timestamp offset according to the modconf
+ /*********** REMOTE CONTROL ***************/
+ /* virtual void enrol_at(BaseRemoteController& controller)
+ * is inherited
*/
- bool updateModulatorOffset();
+
+ /* Base function to set parameters. */
+ virtual void set_parameter(const std::string& parameter,
+ const std::string& value);
+
+ /* Getting a parameter always returns a string. */
+ virtual const std::string get_parameter(
+ const std::string& parameter) const;
+
+ const char* name() { return "TS"; }
+
protected:
/* Push a new MNSC field into the decoder */
@@ -167,12 +174,10 @@ class TimestampDecoder
int32_t latestFCT;
double time_pps;
double timestamp_offset;
+ unsigned m_tist_delay_stages;
int inhibit_second_update;
bool offset_changed;
- /* configuration for the offset management */
- struct modulator_offset_config& modconfig;
-
/* When the type or identifier don't match, the decoder must
* be disabled
*/
@@ -191,3 +196,4 @@ class TimestampDecoder
};
#endif
+
diff --git a/src/Utils.cpp b/src/Utils.cpp
index 8b97602..6c9b0fc 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -49,7 +49,6 @@ void printUsage(char* progName)
" (-f filename | -u uhddevice -F frequency) "
" [-G txgain]"
" [-o offset]"
- " [-O offsetfile]"
" [-T filter_taps_file]"
" [-a gain]"
" [-c clockrate]"
@@ -66,9 +65,7 @@ void printUsage(char* progName)
fprintf(out, "-F frequency: Set the transmit frequency when using UHD output. (mandatory option when using UHD)\n");
fprintf(out, "-G txgain: Set the transmit gain for the UHD driver (default: 0)\n");
fprintf(out, "-o: (UHD only) Set the timestamp offset added to the timestamp in the ETI. The offset is a double.\n");
- fprintf(out, "-O: (UHD only) Set the file containing the timestamp offset added to the timestamp in the ETI.\n"
- "The file is read every six seconds, and must contain a double value.\n");
- fprintf(out, " Specifying either -o or -O has two implications: It enables synchronous transmission,\n"
+ fprintf(out, " Specifying this option has two implications: It enables synchronous transmission,\n"
" requiring an external REFCLK and PPS signal and frames that do not contain a valid timestamp\n"
" get muted.\n\n");
fprintf(out, "-T taps_file: Enable filtering before the output, using the specified file containing the filter taps.\n");