aboutsummaryrefslogtreecommitdiffstats
path: root/src/OutputUHD.h
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2017-08-30 19:06:51 +0200
committerMatthias P. Braendli <matthias.braendli@mpb.li>2017-08-30 19:06:51 +0200
commit65afcb59dd63e22e8c7877228e21ed321a49312b (patch)
tree4a7ce46c7f96459bddf9e0b45305195e49be28be /src/OutputUHD.h
parent728a120df27d5f27a477f1faae0059a5fcab150c (diff)
downloaddabmod-65afcb59dd63e22e8c7877228e21ed321a49312b.tar.gz
dabmod-65afcb59dd63e22e8c7877228e21ed321a49312b.tar.bz2
dabmod-65afcb59dd63e22e8c7877228e21ed321a49312b.zip
Rework UHD output and add underrun and frame counters to RC
This makes it easier for users to monitor underruns if parsing the syslog is not possible.
Diffstat (limited to 'src/OutputUHD.h')
-rw-r--r--src/OutputUHD.h160
1 files changed, 62 insertions, 98 deletions
diff --git a/src/OutputUHD.h b/src/OutputUHD.h
index c966c7e..f1ae09c 100644
--- a/src/OutputUHD.h
+++ b/src/OutputUHD.h
@@ -12,8 +12,8 @@ DESCRIPTION:
library. This version is multi-threaded. A separate thread sends the data to
the device.
- Data between the modulator and the UHD thread is exchanged by swapping
- buffers at a synchronisation barrier.
+ Data between the modulator and the UHD thread are exchanged through a
+ threadsafe queue.
*/
/*
@@ -49,6 +49,7 @@ DESCRIPTION:
#include <chrono>
#include <memory>
#include <string>
+#include <atomic>
#include "Log.h"
#include "ModPlugin.h"
@@ -61,8 +62,8 @@ DESCRIPTION:
#include <stdio.h>
#include <sys/types.h>
-#define MDEBUG(fmt, args...) fprintf (LOG, fmt , ## args)
-//#define MDEBUG(fmt, args...)
+//#define MDEBUG(fmt, args...) fprintf(LOG, fmt , ## args)
+#define MDEBUG(fmt, args...)
// If the timestamp is further in the future than
// 100 seconds, abort
@@ -87,93 +88,6 @@ struct UHDWorkerFrameData {
enum refclk_lock_loss_behaviour_t { CRASH, IGNORE };
-struct UHDWorkerData {
- bool running;
-
- uhd::usrp::multi_usrp::sptr myUsrp;
- unsigned sampleRate;
-
- bool sourceContainsTimestamp;
-
- // When working with timestamps, mute the frames that
- // do not have a timestamp
- bool muteNoTimestamps;
-
- ThreadsafeQueue<UHDWorkerFrameData> frames;
-
- // If we want to verify loss of refclk
- bool check_refclk_loss;
-
- // If we want to check for the gps_timelock sensor
- bool check_gpsfix;
-
- bool gpsdo_is_ettus; // Set to false in case the ODR LEA-M8F board is used
-
- // muting set by remote control
- bool muting;
-
- // What to do when the reference clock PLL loses lock
- refclk_lock_loss_behaviour_t refclk_lock_loss_behaviour;
-};
-
-
-class UHDWorker {
- public:
- UHDWorker(struct UHDWorkerData *uhdworkerdata) {
- uwd = uhdworkerdata;
- }
-
- void start(struct UHDWorkerData *uhdworkerdata) {
- uwd->running = true;
- uhd_thread = boost::thread(&UHDWorker::process_errhandler, this);
- async_rx_thread = boost::thread(
- &UHDWorker::print_async_metadata, this);
- }
-
- void stop() {
- if (uwd) {
- uwd->running = false;
- }
- uhd_thread.interrupt();
- uhd_thread.join();
- async_rx_thread.join();
- }
-
- ~UHDWorker() {
- stop();
- }
-
- UHDWorker(const UHDWorker& other) = delete;
- UHDWorker& operator=(const UHDWorker& other) = delete;
-
- private:
- // Asynchronous message statistics
- int num_underflows;
- int num_late_packets;
-
- uhd::tx_metadata_t md;
- bool last_tx_time_initialised;
- uint32_t last_tx_second;
- uint32_t last_tx_pps;
-
- // Used to print statistics once a second
- std::chrono::steady_clock::time_point last_print_time;
-
- void print_async_metadata(void);
-
- void handle_frame(const struct UHDWorkerFrameData *frame);
- void tx_frame(const struct UHDWorkerFrameData *frame, bool ts_update);
-
- struct UHDWorkerData *uwd;
- boost::thread uhd_thread;
- boost::thread async_rx_thread;
-
- uhd::tx_streamer::sptr myTxStream;
-
- void process();
- void process_errhandler();
-};
-
/* This structure is used as initial configuration for OutputUHD.
* It must also contain all remote-controllable settings, otherwise
* they will get lost on a modulator restart. */
@@ -191,6 +105,9 @@ struct OutputUHDConfig {
double txgain = 0.0;
double rxgain = 0.0;
bool enableSync = false;
+
+ // When working with timestamps, mute the frames that
+ // do not have a timestamp
bool muteNoTimestamps = false;
unsigned dabMode = 0;
unsigned maxGPSHoldoverTime = 0;
@@ -221,6 +138,9 @@ struct OutputUHDConfig {
class OutputUHD: public ModOutput, public RemoteControllable {
public:
OutputUHD(OutputUHDConfig& config);
+ OutputUHD(const OutputUHD& other) = delete;
+ OutputUHD operator=(const OutputUHD& other) = delete;
+ ~OutputUHD();
int process(Buffer* dataIn);
@@ -239,14 +159,12 @@ class OutputUHD: public ModOutput, public RemoteControllable {
const std::string& parameter) const;
protected:
- EtiSource *myEtiSource;
+ EtiSource *myEtiSource = nullptr;
OutputUHDConfig& myConf;
uhd::usrp::multi_usrp::sptr myUsrp;
std::shared_ptr<boost::barrier> mySyncBarrier;
- bool first_run;
- bool gps_fix_verified;
- struct UHDWorkerData uwd;
- UHDWorker worker;
+ bool first_run = true;
+ bool gps_fix_verified = false;
OutputUHDFeedback uhdFeedback;
private:
@@ -258,10 +176,10 @@ class OutputUHD: public ModOutput, public RemoteControllable {
// The remote-controllable static delay is in the OutputUHDConfig
int myTFDurationMs; // TF duration in milliseconds
std::vector<complexf> myDelayBuf;
- size_t lastLen;
+ size_t lastLen = 0;
// GPS Fix check variables
- int num_checks_without_gps_fix;
+ int num_checks_without_gps_fix = 1;
struct timespec first_gps_fix_check;
struct timespec last_gps_fix_check;
struct timespec time_last_frame;
@@ -275,6 +193,52 @@ class OutputUHD: public ModOutput, public RemoteControllable {
// Interval for checking the GPS at runtime
static constexpr double gps_fix_check_interval = 10.0; // seconds
+ // Asynchronous message statistics
+ size_t num_underflows = 0;
+ size_t num_late_packets = 0;
+ size_t num_underflows_previous = 0;
+ size_t num_late_packets_previous = 0;
+
+ size_t num_frames_modulated = 0;
+
+ uhd::tx_metadata_t md;
+ bool last_tx_time_initialised = false;
+ uint32_t last_tx_second = 0;
+ uint32_t last_tx_pps = 0;
+
+ // Used to print statistics once a second
+ std::chrono::steady_clock::time_point last_print_time;
+
+ bool sourceContainsTimestamp = false;
+
+ ThreadsafeQueue<UHDWorkerFrameData> frames;
+
+ // Returns true if we want to verify loss of refclk
+ bool refclk_loss_needs_check(void) const;
+ bool suppress_refclk_loss_check = false;
+
+ // Returns true if we want to check for the gps_timelock sensor
+ bool gpsfix_needs_check(void) const;
+
+ // Return true if the gpsdo is from ettus, false if it is the ODR
+ // LEA-M8F board is used
+ bool gpsdo_is_ettus(void) const;
+
+ std::atomic<bool> running;
+ boost::thread uhd_thread;
+ boost::thread async_rx_thread;
+ void stop_threads(void);
+
+ uhd::tx_streamer::sptr myTxStream;
+
+ // The worker thread decouples the modulator from UHD
+ void workerthread();
+ void handle_frame(const struct UHDWorkerFrameData *frame);
+ void tx_frame(const struct UHDWorkerFrameData *frame, bool ts_update);
+
+ // Poll asynchronous metadata from UHD
+ void print_async_thread(void);
+
void check_gps();
void set_usrp_time();