From 5e5c0871db3069958ae072c5a367c4467f261d3e Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Sun, 7 Jun 2015 18:24:20 +0200 Subject: Revert priority setting for mod and UHD threads It is safer to go back to the previous state, given that several users have expressed concerns about reliability. Revert "Set priorities for modulator and UHD threads". This reverts commit c9ea7fb88809d935f3eaeee108415ff5abd17ead. --- src/DabMod.cpp | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src/DabMod.cpp') diff --git a/src/DabMod.cpp b/src/DabMod.cpp index 9f096ab..045138a 100644 --- a/src/DabMod.cpp +++ b/src/DabMod.cpp @@ -768,15 +768,6 @@ int launch_modulator(int argc, char* argv[]) } #endif - // Set thread priority to realtime - const int policy = SCHED_RR; - sched_param sp; - sp.sched_priority = sched_get_priority_min(policy); - int thread_prio_ret = pthread_setschedparam(pthread_self(), policy, &sp); - if (thread_prio_ret != 0) { - etiLog.level(error) << "Could not set priority for Modulator thread:" << thread_prio_ret; - } - while (run_again) { Flowgraph flowgraph; -- cgit v1.2.3 From fed9a724ca91417e84071255890ec26ff797fd4f Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 12 Jun 2015 07:42:22 +0200 Subject: Simplify TIST offset handling, add offset to RC This breaks old configuration files using synchronous=1 --- doc/example.ini | 17 +++----- src/DabMod.cpp | 64 +++++++++--------------------- src/DabModulator.cpp | 4 +- src/DabModulator.h | 2 +- src/EtiReader.cpp | 12 +++--- src/EtiReader.h | 3 +- src/OutputUHD.cpp | 2 +- src/OutputUHD.h | 2 +- src/TimestampDecoder.cpp | 100 +++++++++++++++-------------------------------- src/TimestampDecoder.h | 64 ++++++++++++++++-------------- src/Utils.cpp | 5 +-- 11 files changed, 104 insertions(+), 171 deletions(-) (limited to 'src/DabMod.cpp') 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(new Flowgraph()); shared_ptr 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("delaymanagement.management", ""); + std::string fixedoffset = pt.get("delaymanagement.fixedoffset", ""); + std::string offset_filename = pt.get("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("delaymanagement.management"); - if (delay_mgmt == "fixed") { - modconf.offset_fixed = pt.get("delaymanagement.fixedoffset"); - modconf.use_offset_fixed = true; - } - else if (delay_mgmt == "dynamic") { - modconf.offset_filename = pt.get("delaymanagement.dynamicoffsetfile"); - modconf.use_offset_file = true; - } - else { - throw std::runtime_error("invalid management value"); - } + tist_offset_s = pt.get("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 input(new InputMemory(&m.data)); shared_ptr 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(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 #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"); -- cgit v1.2.3