From 827f61c82c4739ddc45bf925b55c73cf6dcf307a Mon Sep 17 00:00:00 2001 From: "Matthias (think)" Date: Wed, 18 Jul 2012 15:03:46 +0200 Subject: dabmod: made OutputUHD usable without REFCLK and 1PPS (Single transmitter) --- src/DabMod.cpp | 12 ++++++--- src/OutputUHD.cpp | 80 +++++++++++++++++++++++++++++-------------------------- src/OutputUHD.h | 3 ++- 3 files changed, 53 insertions(+), 42 deletions(-) diff --git a/src/DabMod.cpp b/src/DabMod.cpp index f9bc3c9..24dfe4f 100644 --- a/src/DabMod.cpp +++ b/src/DabMod.cpp @@ -95,8 +95,11 @@ void printUsage(char* progName, FILE* out = stderr) 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. The file is read every six seconds, and must contain a double value.\n"); - fprintf(out, " Specifying either -o or -O make DABMOD mute frames that do not contain a valid timestamp.\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" + " 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"); fprintf(out, "-a gain: Apply digital amplitude gain.\n"); fprintf(out, "-c rate: Set the DAC clock rate and enable Cic Equalisation.\n"); @@ -147,6 +150,7 @@ int main(int argc, char* argv[]) double uhdFrequency = 0.0; int uhdTxGain = 0; bool uhd_mute_no_timestamps = false; + bool uhd_enable_sync = false; FILE* inputFile = NULL; uint32_t sync = 0; @@ -218,6 +222,7 @@ int main(int argc, char* argv[]) } modconf.use_offset_fixed = true; modconf.offset_fixed = strtod(optarg, NULL); + uhd_enable_sync = true; break; case 'O': if (modconf.use_offset_fixed) @@ -227,6 +232,7 @@ int main(int argc, char* argv[]) } modconf.use_offset_file = true; modconf.offset_filename = optarg; + uhd_enable_sync = true; break; case 'm': dabMode = strtol(optarg, NULL, 0); @@ -333,7 +339,7 @@ int main(int argc, char* argv[]) else if (useUHDOutput) { fprintf(stderr, "Using UHD output\n"); amplitude /= 32000.0f; - output = new OutputUHD(outputDevice, outputRate, uhdFrequency, uhdTxGain, uhd_mute_no_timestamps); + output = new OutputUHD(outputDevice, outputRate, uhdFrequency, uhdTxGain, uhd_enable_sync, uhd_mute_no_timestamps); } flowgraph = new Flowgraph(); diff --git a/src/OutputUHD.cpp b/src/OutputUHD.cpp index 9e14a4f..f7825e3 100644 --- a/src/OutputUHD.cpp +++ b/src/OutputUHD.cpp @@ -38,9 +38,10 @@ typedef std::complex complexf; OutputUHD::OutputUHD(char* device, unsigned sampleRate, - double frequency, int txgain, bool muteNoTimestamps) : + double frequency, int txgain, bool enableSync, bool muteNoTimestamps) : ModOutput(ModFormat(1), ModFormat(0)), mySampleRate(sampleRate), myTxGain(txgain), + enable_sync(enableSync), myFrequency(frequency), mute_no_timestamps(muteNoTimestamps) { MDEBUG("OutputUHD::OutputUHD(device: %s) @ %p\n", @@ -57,12 +58,14 @@ OutputUHD::OutputUHD(char* device, unsigned sampleRate, myUsrp = uhd::usrp::multi_usrp::make(myDevice); MDEBUG("OutputUHD:Using device: %s...\n", myUsrp->get_pp_string().c_str()); - MDEBUG("OutputUHD:Setting REFCLK and PPS input...\n"); - uhd::clock_config_t clock_config; - clock_config.ref_source = uhd::clock_config_t::REF_SMA; - clock_config.pps_source = uhd::clock_config_t::PPS_SMA; - clock_config.pps_polarity = uhd::clock_config_t::PPS_POS; - myUsrp->set_clock_config(clock_config, uhd::usrp::multi_usrp::ALL_MBOARDS); + if (enable_sync) { + MDEBUG("OutputUHD:Setting REFCLK and PPS input...\n"); + uhd::clock_config_t clock_config; + clock_config.ref_source = uhd::clock_config_t::REF_SMA; + clock_config.pps_source = uhd::clock_config_t::PPS_SMA; + clock_config.pps_polarity = uhd::clock_config_t::PPS_POS; + myUsrp->set_clock_config(clock_config, uhd::usrp::multi_usrp::ALL_MBOARDS); + } std::cerr << "UHD clock source is " << myUsrp->get_clock_source(0) << std::endl; @@ -84,39 +87,40 @@ OutputUHD::OutputUHD(char* device, unsigned sampleRate, MDEBUG("OutputUHD:Actual TX Gain: %f ...\n", myUsrp->get_tx_gain()); - /* handling time for synchronisation: wait until the next full - * second, and set the USRP time at next PPS */ - struct timespec now; - time_t seconds; - if (clock_gettime(CLOCK_REALTIME, &now)) { - fprintf(stderr, "errno: %d\n", errno); - perror("OutputUHD:Error: could not get time: "); - } - else { - seconds = now.tv_sec; - - MDEBUG("OutputUHD:sec+1: %ld ; now: %ld ...\n", seconds+1, now.tv_sec); - while (seconds + 1 > now.tv_sec) { - usleep(1); - if (clock_gettime(CLOCK_REALTIME, &now)) { - fprintf(stderr, "errno: %d\n", errno); - perror("OutputUHD:Error: could not get time: "); - break; + if (enable_sync) { + /* handling time for synchronisation: wait until the next full + * second, and set the USRP time at next PPS */ + struct timespec now; + time_t seconds; + if (clock_gettime(CLOCK_REALTIME, &now)) { + fprintf(stderr, "errno: %d\n", errno); + perror("OutputUHD:Error: could not get time: "); + } + else { + seconds = now.tv_sec; + + MDEBUG("OutputUHD:sec+1: %ld ; now: %ld ...\n", seconds+1, now.tv_sec); + while (seconds + 1 > now.tv_sec) { + usleep(1); + if (clock_gettime(CLOCK_REALTIME, &now)) { + fprintf(stderr, "errno: %d\n", errno); + perror("OutputUHD:Error: could not get time: "); + break; + } } + MDEBUG("OutputUHD:sec+1: %ld ; now: %ld ...\n", seconds+1, now.tv_sec); + /* We are now shortly after the second change. */ + + usleep(200000); // 200ms, we want the PPS to be later + myUsrp->set_time_unknown_pps(uhd::time_spec_t(seconds + 2)); + fprintf(stderr, "OutputUHD: Setting USRP time next pps to %f\n", + uhd::time_spec_t(seconds + 2).get_real_secs()); } - MDEBUG("OutputUHD:sec+1: %ld ; now: %ld ...\n", seconds+1, now.tv_sec); - /* We are now shortly after the second change. */ - -#warning "TODO usleep for USRP time setting !" - //usleep(200000); // 200ms, we want the PPS to be later - myUsrp->set_time_unknown_pps(uhd::time_spec_t(seconds + 2)); - fprintf(stderr, "OutputUHD: Setting USRP time next pps to %f\n", - uhd::time_spec_t(seconds + 2).get_real_secs()); - } - usleep(1e6); - fprintf(stderr, "OutputUHD: USRP time %f\n", - myUsrp->get_time_now().get_real_secs()); + usleep(1e6); + fprintf(stderr, "OutputUHD: USRP time %f\n", + myUsrp->get_time_now().get_real_secs()); + } // preparing output thread worker data @@ -166,7 +170,7 @@ int OutputUHD::process(Buffer* dataIn, Buffer* dataOut) uwd.frame0.buf = malloc(uwd.bufsize); uwd.frame1.buf = malloc(uwd.bufsize); - uwd.sourceContainsTimestamp = myEtiReader->sourceContainsTimestamp(); + uwd.sourceContainsTimestamp = enable_sync && myEtiReader->sourceContainsTimestamp(); // The worker begins by transmitting buf0 memcpy(uwd.frame0.buf, dataIn->getData(), uwd.bufsize); diff --git a/src/OutputUHD.h b/src/OutputUHD.h index eea594f..953675d 100644 --- a/src/OutputUHD.h +++ b/src/OutputUHD.h @@ -135,7 +135,7 @@ class UHDWorker { class OutputUHD: public ModOutput { public: OutputUHD(char* device, unsigned sampleRate, double frequency, int txgain, - bool muteNoTimestamps); + bool enableSync, bool muteNoTimestamps); ~OutputUHD(); int process(Buffer* dataIn, Buffer* dataOut); @@ -159,6 +159,7 @@ class OutputUHD: public ModOutput { struct UHDWorkerData uwd; int activebuffer; bool mute_no_timestamps; + bool enable_sync; size_t lastLen; }; -- cgit v1.2.3