diff options
| author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2017-08-30 19:08:45 +0200 | 
|---|---|---|
| committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2017-08-30 19:08:45 +0200 | 
| commit | f5939de02ada69d2ff4ca28bddc9241dcc5c356c (patch) | |
| tree | 355ff207201e02930aeba6fd03393908363ba0ca /src | |
| parent | d3d5de2dac2defc41cd9ea13825914a70c976eb5 (diff) | |
| parent | 65afcb59dd63e22e8c7877228e21ed321a49312b (diff) | |
| download | dabmod-f5939de02ada69d2ff4ca28bddc9241dcc5c356c.tar.gz dabmod-f5939de02ada69d2ff4ca28bddc9241dcc5c356c.tar.bz2 dabmod-f5939de02ada69d2ff4ca28bddc9241dcc5c356c.zip | |
Merge branch 'next' into next_memless
Diffstat (limited to 'src')
| -rw-r--r-- | src/OutputUHD.cpp | 243 | ||||
| -rw-r--r-- | src/OutputUHD.h | 160 | ||||
| -rw-r--r-- | src/TimestampDecoder.h | 1 | 
3 files changed, 196 insertions, 208 deletions
| diff --git a/src/OutputUHD.cpp b/src/OutputUHD.cpp index c2f985b..10e605f 100644 --- a/src/OutputUHD.cpp +++ b/src/OutputUHD.cpp @@ -49,7 +49,7 @@  using namespace std; -// Maximum number of frames that can wait in uwd.frames +// Maximum number of frames that can wait in frames  static const size_t FRAMES_MAX_SIZE = 8;  typedef std::complex<float> complexf; @@ -158,16 +158,13 @@ OutputUHD::OutputUHD(      myConf(config),      // Since we don't know the buffer size, we cannot initialise      // the buffers at object initialisation. -    first_run(true), -    gps_fix_verified(false), -    worker(&uwd), -    myDelayBuf(0) +    myDelayBuf(0), +    running(false)  {      myConf.muting = true;     // is remote-controllable, and reset by the GPS fix check      myConf.staticDelayUs = 0; // is remote-controllable      // Variables needed for GPS fix check -    num_checks_without_gps_fix = 1;      first_gps_fix_check.tv_sec = 0;      last_gps_fix_check.tv_sec = 0;      time_last_frame.tv_sec = 0; @@ -196,25 +193,29 @@ OutputUHD::OutputUHD(      /* register the parameters that can be remote controlled */      RC_ADD_PARAMETER(txgain, "UHD analog daughterboard TX gain");      RC_ADD_PARAMETER(rxgain, "UHD analog daughterboard RX gain for DPD feedback"); -    RC_ADD_PARAMETER(freq,   "UHD transmission frequency"); +    RC_ADD_PARAMETER(freq, "UHD transmission frequency");      RC_ADD_PARAMETER(muting, "Mute the output by stopping the transmitter");      RC_ADD_PARAMETER(staticdelay, "Set static delay (uS) between 0 and 96000"); +    RC_ADD_PARAMETER(underruns, "Read-only counter of number of underruns"); +    RC_ADD_PARAMETER(latepackets, "Read-only counter of number of late packets"); +    RC_ADD_PARAMETER(frames, "Read-only counter of number of frames modulated");      uhd::msg::register_handler(uhd_msg_handler);      uhd::set_thread_priority_safe(); -    //create a usrp device -    MDEBUG("OutputUHD:Creating the usrp device with: %s...\n", +    etiLog.log(info, "OutputUHD:Creating the usrp device with: %s...",              device.str().c_str());      myUsrp = uhd::usrp::multi_usrp::make(device.str()); -    MDEBUG("OutputUHD:Using device: %s...\n", myUsrp->get_pp_string().c_str()); +    etiLog.log(info, "OutputUHD:Using device: %s...", +            myUsrp->get_pp_string().c_str());      if (myConf.masterClockRate != 0.0) {          double master_clk_rate = myUsrp->get_master_clock_rate(); -        MDEBUG("OutputUHD:Checking master clock rate: %f...\n", master_clk_rate); +        etiLog.log(debug, "OutputUHD:Checking master clock rate: %f...", +                master_clk_rate);          if (fabs(master_clk_rate - myConf.masterClockRate) >                  (myConf.masterClockRate * 1e-6)) { @@ -237,20 +238,16 @@ OutputUHD::OutputUHD(                  uhd::usrp::multi_usrp::ALL_MBOARDS);      } -    std::cerr << "UHD clock source is " << -        myUsrp->get_clock_source(0) << std::endl; +    etiLog.level(debug) << "UHD clock source is " << myUsrp->get_clock_source(0); -    std::cerr << "UHD time source is " << -        myUsrp->get_time_source(0) << std::endl; +    etiLog.level(debug) << "UHD time source is " << myUsrp->get_time_source(0); -    //set the tx sample rate -    MDEBUG("OutputUHD:Setting rate to %d...\n", myConf.sampleRate);      myUsrp->set_tx_rate(myConf.sampleRate); -    MDEBUG("OutputUHD:Actual TX Rate: %f sps...\n", myUsrp->get_tx_rate()); +    etiLog.log(debug, "OutputUHD:Set rate to %d. Actual TX Rate: %f sps...", +            myConf.sampleRate, myUsrp->get_tx_rate());      if (fabs(myUsrp->get_tx_rate() / myConf.sampleRate) >               myConf.sampleRate * 1e-6) { -        MDEBUG("OutputUHD: Cannot set sample\n");          throw std::runtime_error("Cannot set USRP sample rate. Aborted.");      } @@ -264,52 +261,71 @@ OutputUHD::OutputUHD(          "OutputUHD:Actual RX frequency: " << myUsrp->get_tx_freq();      myUsrp->set_tx_gain(myConf.txgain); -    MDEBUG("OutputUHD:Actual TX Gain: %f ...\n", myUsrp->get_tx_gain()); +    etiLog.log(debug, "OutputUHD:Actual TX Gain: %f", myUsrp->get_tx_gain()); -    MDEBUG("OutputUHD:Mute on missing timestamps: %s ...\n", +    etiLog.log(debug, "OutputUHD:Mute on missing timestamps: %s",              myConf.muteNoTimestamps ? "enabled" : "disabled");      // preparing output thread worker data -    uwd.myUsrp = myUsrp; +    sourceContainsTimestamp = false; -    uwd.sampleRate = myConf.sampleRate; -    uwd.sourceContainsTimestamp = false; -    uwd.muteNoTimestamps = myConf.muteNoTimestamps; -    uwd.refclk_lock_loss_behaviour = myConf.refclk_lock_loss_behaviour; -    uwd.gpsdo_is_ettus = false; +    SetDelayBuffer(myConf.dabMode); + +    myUsrp->set_rx_rate(myConf.sampleRate); +    etiLog.log(debug, "OutputUHD:Actual RX Rate: %f sps.", myUsrp->get_rx_rate()); + +    myUsrp->set_rx_antenna("RX2"); +    etiLog.log(debug, "OutputUHD:Set RX Antenna: %s", +            myUsrp->get_rx_antenna().c_str()); + +    myUsrp->set_rx_gain(myConf.rxgain); +    etiLog.log(debug, "OutputUHD:Actual RX Gain: %f", myUsrp->get_rx_gain()); + +    uhdFeedback.setup(myUsrp, myConf.dpdFeedbackServerPort, myConf.sampleRate); + +    MDEBUG("OutputUHD:UHD ready.\n"); +} + +bool OutputUHD::refclk_loss_needs_check() const +{ +    if (suppress_refclk_loss_check) { +        return false; +    } +    return myConf.refclk_src != "internal"; +} +bool OutputUHD::gpsfix_needs_check() const +{      if (myConf.refclk_src == "internal") { -        uwd.check_refclk_loss = false; -        uwd.check_gpsfix = false; +        return false;      }      else if (myConf.refclk_src == "gpsdo") { -        uwd.check_refclk_loss = true; -        uwd.check_gpsfix = (myConf.maxGPSHoldoverTime != 0); +        return (myConf.maxGPSHoldoverTime != 0);      }      else if (myConf.refclk_src == "gpsdo-ettus") { -        uwd.check_refclk_loss = true; -        uwd.check_gpsfix = (myConf.maxGPSHoldoverTime != 0); -        uwd.gpsdo_is_ettus = true; +        return (myConf.maxGPSHoldoverTime != 0);      }      else { -        uwd.check_refclk_loss = true; -        uwd.check_gpsfix = false; +        return false;      } +} -    SetDelayBuffer(myConf.dabMode); - -    myUsrp->set_rx_rate(myConf.sampleRate); -    MDEBUG("OutputUHD:Actual RX Rate: %f sps...\n", myUsrp->get_rx_rate()); - -    myUsrp->set_rx_antenna("RX2"); -    MDEBUG("OutputUHD:Set RX Antenna: %s ...\n", myUsrp->get_rx_antenna().c_str()); - -    myUsrp->set_rx_gain(myConf.rxgain); -    MDEBUG("OutputUHD:Actual RX Gain: %f ...\n", myUsrp->get_rx_gain()); +bool OutputUHD::gpsdo_is_ettus() const +{ +    return (myConf.refclk_src == "gpsdo-ettus"); +} -    uhdFeedback.setup(myUsrp, myConf.dpdFeedbackServerPort, myConf.sampleRate); +OutputUHD::~OutputUHD() +{ +    stop_threads(); +} -    MDEBUG("OutputUHD:UHD ready.\n"); +void OutputUHD::stop_threads() +{ +    running.store(false); +    uhd_thread.interrupt(); +    uhd_thread.join(); +    async_rx_thread.join();  } @@ -346,10 +362,8 @@ void OutputUHD::SetDelayBuffer(unsigned int dabMode)  int OutputUHD::process(Buffer* dataIn)  { -    uwd.muting = myConf.muting; -      if (not gps_fix_verified) { -        if (uwd.check_gpsfix) { +        if (gpsfix_needs_check()) {              initial_gps_check();              if (num_checks_without_gps_fix == 0) { @@ -374,7 +388,10 @@ int OutputUHD::process(Buffer* dataIn)                  SetDelayBuffer(myEtiSource->getMode());              } -            worker.start(&uwd); +            running.store(true); +            uhd_thread = boost::thread(&OutputUHD::workerthread, this); +            async_rx_thread = boost::thread( +                    &OutputUHD::print_async_thread, this);              lastLen = dataIn->getLength();              first_run = false; @@ -389,16 +406,15 @@ int OutputUHD::process(Buffer* dataIn)              throw std::runtime_error("Non-constant input length!");          } -        uwd.sourceContainsTimestamp = myConf.enableSync && +        sourceContainsTimestamp = myConf.enableSync and              myEtiSource->sourceContainsTimestamp(); - -        if (uwd.check_gpsfix) { +        if (gpsfix_needs_check()) {              try {                  check_gps();              }              catch (std::runtime_error& e) { -                uwd.running = false; +                running.store(false);                  etiLog.level(error) << e.what();              }          } @@ -429,12 +445,13 @@ int OutputUHD::process(Buffer* dataIn)          myEtiSource->calculateTimestamp(frame.ts); -        if (!uwd.running) { -            worker.stop(); +        if (not running.load()) { +            uhd_thread.interrupt(); +            uhd_thread.join(); +            async_rx_thread.join();              first_run = true; -            etiLog.level(error) << -                "OutputUHD: Error, UHD worker failed"; +            etiLog.level(error) << "OutputUHD: Error, UHD worker failed";              throw std::runtime_error("UHD worker failed");          } @@ -445,7 +462,7 @@ int OutputUHD::process(Buffer* dataIn)          else {              uhdFeedback.set_tx_frame(frame.buf, frame.ts); -            size_t num_frames = uwd.frames.push_wait_if_full(frame, +            size_t num_frames = frames.push_wait_if_full(frame,                      FRAMES_MAX_SIZE);              etiLog.log(trace, "UHD,push %zu", num_frames);          } @@ -457,7 +474,7 @@ int OutputUHD::process(Buffer* dataIn)  void OutputUHD::set_usrp_time()  { -    if (myConf.enableSync && (myConf.pps_src == "none")) { +    if (myConf.enableSync and (myConf.pps_src == "none")) {          etiLog.level(warn) <<              "OutputUHD: WARNING:"              " you are using synchronous transmission without PPS input!"; @@ -574,7 +591,7 @@ void OutputUHD::check_gps()      // Divide interval by two because we alternate between      // launch and check -    if (uwd.check_gpsfix and +    if (gpsfix_needs_check() and              last_gps_fix_check.tv_sec + gps_fix_check_interval/2.0 <              time_now.tv_sec) {          last_gps_fix_check = time_now; @@ -615,7 +632,7 @@ void OutputUHD::check_gps()          else {              // Checking the sensor here takes too much              // time, it has to be done in a separate thread. -            if (uwd.gpsdo_is_ettus) { +            if (gpsdo_is_ettus()) {                  gps_fix_pt = boost::packaged_task<bool>(                          boost::bind(check_gps_locked, myUsrp) );              } @@ -630,9 +647,7 @@ void OutputUHD::check_gps()      }  } -//============================ UHD Worker ======================== - -void UHDWorker::process_errhandler() +void OutputUHD::workerthread()  {      // Set thread priority to realtime      if (int ret = set_realtime_prio(1)) { @@ -641,17 +656,10 @@ void UHDWorker::process_errhandler()      set_thread_name("uhdworker"); -    process(); -    uwd->running = false; -    etiLog.level(warn) << "UHD worker terminated"; -} - -void UHDWorker::process() -{      last_tx_time_initialised = false;      uhd::stream_args_t stream_args("fc32"); //complex floats -    myTxStream = uwd->myUsrp->get_tx_stream(stream_args); +    myTxStream = myUsrp->get_tx_stream(stream_args);      md.start_of_burst = false;      md.end_of_burst   = false; @@ -659,21 +667,22 @@ void UHDWorker::process()      num_underflows   = 0;      num_late_packets = 0; -    int last_num_underflows = 0; +    size_t last_num_underflows = 0;      size_t pop_prebuffering = FRAMES_MAX_SIZE; -    while (uwd->running) { +    while (running.load()) {          md.has_time_spec  = false;          md.time_spec      = uhd::time_spec_t(0.0);          struct UHDWorkerFrameData frame;          etiLog.log(trace, "UHD,wait"); -        uwd->frames.wait_and_pop(frame, pop_prebuffering); +        frames.wait_and_pop(frame, pop_prebuffering);          etiLog.log(trace, "UHD,pop");          handle_frame(&frame); +        num_frames_modulated++; -        /* Ensure we fill uwd->frames after every underrun and +        /* Ensure we fill frames after every underrun and           * at startup to reduce underrun likelihood. */          if (last_num_underflows < num_underflows) {              pop_prebuffering = FRAMES_MAX_SIZE; @@ -683,38 +692,38 @@ void UHDWorker::process()          }          last_num_underflows = num_underflows;      } +    running.store(false); +    etiLog.level(warn) << "UHD worker terminated";  } -void UHDWorker::handle_frame(const struct UHDWorkerFrameData *frame) +void OutputUHD::handle_frame(const struct UHDWorkerFrameData *frame)  {      // Transmit timeout      static const double tx_timeout = 20.0;      // Check for ref_lock -    if (uwd->check_refclk_loss) { +    if (refclk_loss_needs_check()) {          try { -            // TODO: Is this check specific to the B100 and USRP2 ? -            if (! uwd->myUsrp->get_mboard_sensor("ref_locked", 0).to_bool()) { +            if (not myUsrp->get_mboard_sensor("ref_locked", 0).to_bool()) {                  etiLog.log(alert,                          "OutputUHD: External reference clock lock lost !"); -                if (uwd->refclk_lock_loss_behaviour == CRASH) { +                if (myConf.refclk_lock_loss_behaviour == CRASH) {                      throw std::runtime_error(                              "OutputUHD: External reference clock lock lost.");                  }              }          }          catch (uhd::lookup_error &e) { -            uwd->check_refclk_loss = false; -            etiLog.log(warn, -                    "OutputUHD: This USRP does not have mboard sensor for ext clock loss." -                    " Check disabled."); +            suppress_refclk_loss_check = true; +            etiLog.log(warn, "OutputUHD: This USRP does not have mboard " +                    "sensor for ext clock loss. Check disabled.");          }      } -    double usrp_time = uwd->myUsrp->get_time_now().get_real_secs(); +    double usrp_time = myUsrp->get_time_now().get_real_secs();      bool timestamp_discontinuity = false; -    if (uwd->sourceContainsTimestamp) { +    if (sourceContainsTimestamp) {          // Tx time from MNSC and TIST          uint32_t tx_second = frame->ts.timestamp_sec;          uint32_t tx_pps    = frame->ts.timestamp_pps; @@ -734,7 +743,7 @@ void UHDWorker::handle_frame(const struct UHDWorkerFrameData *frame)          if (last_tx_time_initialised) {              const size_t sizeIn = frame->buf.size() / sizeof(complexf);              uint64_t increment = (uint64_t)sizeIn * 16384000ul / -                                 (uint64_t)uwd->sampleRate; +                                 (uint64_t)myConf.sampleRate;                                    // samps  * ticks/s  / (samps/s)                                    // (samps * ticks * s) / (s * samps)                                    // ticks @@ -793,11 +802,10 @@ void UHDWorker::handle_frame(const struct UHDWorkerFrameData *frame)              throw std::runtime_error("Timestamp error. Aborted.");          }      } -    else { // !uwd->sourceContainsTimestamp -        if (uwd->muting || uwd->muteNoTimestamps) { -            /* There was some error decoding the timestamp -            */ -            if (uwd->muting) { +    else { // !sourceContainsTimestamp +        if (myConf.muting or myConf.muteNoTimestamps) { +            /* There was some error decoding the timestamp */ +            if (myConf.muting) {                  etiLog.log(info,                          "OutputUHD: Muting sample %d requested\n",                          frame->ts.fct); @@ -815,7 +823,7 @@ void UHDWorker::handle_frame(const struct UHDWorkerFrameData *frame)      tx_frame(frame, timestamp_discontinuity);  } -void UHDWorker::tx_frame(const struct UHDWorkerFrameData *frame, bool ts_update) +void OutputUHD::tx_frame(const struct UHDWorkerFrameData *frame, bool ts_update)  {      const double tx_timeout = 20.0;      const size_t sizeIn = frame->buf.size() / sizeof(complexf); @@ -823,7 +831,7 @@ void UHDWorker::tx_frame(const struct UHDWorkerFrameData *frame, bool ts_update)      size_t usrp_max_num_samps = myTxStream->get_max_num_samps();      size_t num_acc_samps = 0; //number of accumulated samples -    while (uwd->running && !uwd->muting && (num_acc_samps < sizeIn)) { +    while (running.load() and (not myConf.muting) and (num_acc_samps < sizeIn)) {          size_t samps_to_send = std::min(sizeIn - num_acc_samps, usrp_max_num_samps);          uhd::tx_metadata_t md_tx = md; @@ -831,8 +839,8 @@ void UHDWorker::tx_frame(const struct UHDWorkerFrameData *frame, bool ts_update)          //ensure the the last packet has EOB set if the timestamps has been          //refreshed and need to be reconsidered.          md_tx.end_of_burst = ( -                uwd->sourceContainsTimestamp && -                (frame->ts.timestamp_refresh or ts_update) && +                sourceContainsTimestamp and +                (frame->ts.timestamp_refresh or ts_update) and                  samps_to_send <= usrp_max_num_samps ); @@ -845,21 +853,21 @@ void UHDWorker::tx_frame(const struct UHDWorkerFrameData *frame, bool ts_update)          num_acc_samps += num_tx_samps;          md_tx.time_spec = md.time_spec + -            uhd::time_spec_t(0, num_tx_samps/uwd->sampleRate); +            uhd::time_spec_t(0, num_tx_samps/myConf.sampleRate);          if (num_tx_samps == 0) {              etiLog.log(warn, -                    "UHDWorker::process() unable to write to device, skipping frame!\n"); +                    "OutputUHD::workerthread() unable to write to device, skipping frame!\n");              break;          }      }  } -void UHDWorker::print_async_metadata() +void OutputUHD::print_async_thread()  { -    while (uwd->running) { +    while (running.load()) {          uhd::async_metadata_t async_md; -        if (uwd->myUsrp->get_device()->recv_async_msg(async_md, 1)) { +        if (myUsrp->get_device()->recv_async_msg(async_md, 1)) {              const char* uhd_async_message = "";              bool failure = false;              switch (async_md.event_code) { @@ -903,17 +911,19 @@ void UHDWorker::print_async_metadata()          auto time_now = std::chrono::steady_clock::now();          if (last_print_time + std::chrono::seconds(1) < time_now) {              const double usrp_time = -                uwd->myUsrp->get_time_now().get_real_secs(); +                myUsrp->get_time_now().get_real_secs(); -            if (num_underflows or num_late_packets) { +            if ( (num_underflows > num_underflows_previous) or +                 (num_late_packets > num_late_packets_previous)) {                  etiLog.log(info,                          "OutputUHD status (usrp time: %f): "                          "%d underruns and %d late packets since last status.\n",                          usrp_time,                          num_underflows, num_late_packets);              } -            num_underflows = 0; -            num_late_packets = 0; + +            num_underflows_previous = num_underflows; +            num_late_packets_previous = num_late_packets;              last_print_time = time_now;          } @@ -923,7 +933,6 @@ void UHDWorker::print_async_metadata()  // =======================================  // Remote Control for UHD  // ======================================= -  void OutputUHD::set_parameter(const string& parameter, const string& value)  {      stringstream ss(value); @@ -964,6 +973,11 @@ void OutputUHD::set_parameter(const string& parameter, const string& value)                  myConf.staticDelayUs = newStaticDelayUs;          }      } +    else if (parameter == "underruns" or +            parameter == "latepackets" or +            parameter == "frames") { +        throw ParameterError("Parameter " + parameter + " is read-only."); +    }      else {          stringstream ss;          ss << "Parameter '" << parameter @@ -990,6 +1004,15 @@ const string OutputUHD::get_parameter(const string& parameter) const      else if (parameter == "staticdelay") {          ss << myConf.staticDelayUs;      } +    else if (parameter == "underruns") { +        ss << num_underflows; +    } +    else if (parameter == "latepackets") { +        ss << num_late_packets; +    } +    else if (parameter == "frames") { +        ss << num_frames_modulated; +    }      else {          ss << "Parameter '" << parameter <<              "' is not exported by controllable " << get_rc_name(); 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(); diff --git a/src/TimestampDecoder.h b/src/TimestampDecoder.h index 171dba7..c835430 100644 --- a/src/TimestampDecoder.h +++ b/src/TimestampDecoder.h @@ -122,6 +122,7 @@ class TimestampDecoder : public RemoteControllable              latestFCT = 0;              enableDecode = false;              full_timestamp_received = false; +            bzero(&temp_time, sizeof(temp_time));              gmtime_r(0, &temp_time);              offset_changed = false; | 
