From 685095418bc8fd27dcd0b1d73ad1741114aeda6a Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Sun, 14 Sep 2014 00:08:53 +0200 Subject: SFN: carry FCT along with timestamps This is the first step to fix issue #6. The goal is to enable the OutputUHD to check for FCT consistency. Once it can do that, it will also be able to reset the UHD streamer if necessary. --- src/OutputUHD.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 10 deletions(-) (limited to 'src/OutputUHD.cpp') diff --git a/src/OutputUHD.cpp b/src/OutputUHD.cpp index b44cd3f..927d2e6 100644 --- a/src/OutputUHD.cpp +++ b/src/OutputUHD.cpp @@ -58,6 +58,9 @@ OutputUHD::OutputUHD( { myMuting = 0; // is remote-controllable +#if FAKE_UHD + MDEBUG("OutputUHD:Using fake UHD output"); +#else std::stringstream device; device << myConf.device; @@ -198,6 +201,7 @@ OutputUHD::OutputUHD( // preparing output thread worker data uwd.myUsrp = myUsrp; +#endif uwd.frame0.ts.timestamp_valid = false; uwd.frame1.ts.timestamp_valid = false; @@ -257,7 +261,15 @@ int OutputUHD::process(Buffer* dataIn, Buffer* dataOut) myEtiReader->calculateTimestamp(ts); uwd.frame0.ts = ts; - uwd.frame0.fct = myEtiReader->getFCT(); + + switch (myEtiReader->getMode()) { + case 1: uwd.fct_increment = 4; break; + case 2: + case 3: uwd.fct_increment = 1; break; + case 4: uwd.fct_increment = 2; break; + default: break; + } + activebuffer = 1; @@ -287,13 +299,11 @@ int OutputUHD::process(Buffer* dataIn, Buffer* dataOut) memcpy(uwd.frame0.buf, dataIn->getData(), uwd.bufsize); uwd.frame0.ts = ts; - uwd.frame0.fct = myEtiReader->getFCT(); } else if (activebuffer == 1) { memcpy(uwd.frame1.buf, dataIn->getData(), uwd.bufsize); uwd.frame1.ts = ts; - uwd.frame1.fct = myEtiReader->getFCT(); } activebuffer = (activebuffer + 1) % 2; @@ -322,9 +332,13 @@ void UHDWorker::process() // Transmit timeout const double timeout = 0.2; +#if FAKE_UHD == 0 uhd::stream_args_t stream_args("fc32"); //complex floats uhd::tx_streamer::sptr myTxStream = uwd->myUsrp->get_tx_stream(stream_args); size_t usrp_max_num_samps = myTxStream->get_max_num_samps(); +#else + size_t usrp_max_num_samps = 2048; // arbitrarily chosen +#endif const complexf* in; @@ -362,6 +376,19 @@ void UHDWorker::process() sizeIn = uwd->bufsize / sizeof(complexf); +#if FAKE_UHD + if (expected_next_fct != -1) { + if (expected_next_fct != frame->ts.fct) { + uwd->logger->level(warn) << + "OutputUHD: Incorrect expect fct " << frame->ts.fct; + + // TODO here we should disrupt the UHD streamer so that + // it resyncs to the correct timestamps + } + } + + expected_next_fct = (frame->ts.fct + uwd->fct_increment) % 250; +#else // Check for ref_lock if (uwd->check_refclk_loss) { @@ -392,7 +419,7 @@ void UHDWorker::process() * MNSC. We sleep through the frame. */ uwd->logger->level(info) << - "OutputUHD: Throwing sample " << frame->fct << + "OutputUHD: Throwing sample " << frame->ts.fct << " away: incomplete timestamp " << tx_second << " + " << pps_offset; usleep(20000); //TODO should this be TM-dependant ? @@ -408,7 +435,7 @@ void UHDWorker::process() "OutputUHD: Timestamp in the past! offset: " << md.time_spec.get_real_secs() - usrp_time << " (" << usrp_time << ")" - " frame " << frame->fct << + " frame " << frame->ts.fct << ", tx_second " << tx_second << ", pps " << pps_offset; goto loopend; //skip the frame @@ -433,7 +460,7 @@ void UHDWorker::process() "OutputUHD (usrp time: %f): frame %d;" " tx_second %zu; pps %.9f\n", usrp_time, - frame->fct, tx_second, pps_offset); + frame->ts.fct, tx_second, pps_offset); } } @@ -444,20 +471,21 @@ void UHDWorker::process() if (uwd->muting) { uwd->logger->log(info, "OutputUHD: Muting sample %d requested\n", - frame->fct); + frame->ts.fct); } else { uwd->logger->log(info, "OutputUHD: Muting sample %d : no timestamp\n", - frame->fct); + frame->ts.fct); } usleep(20000); goto loopend; } } +#endif PDEBUG("UHDWorker::process:max_num_samps: %zu.\n", - myTxStream->get_max_num_samps()); + usrp_max_num_samps); while (running && !uwd->muting && (num_acc_samps < sizeIn)) { size_t samps_to_send = std::min(sizeIn - num_acc_samps, usrp_max_num_samps); @@ -467,10 +495,16 @@ void UHDWorker::process() md.end_of_burst = (frame->ts.timestamp_refresh && (samps_to_send <= usrp_max_num_samps)); +#if FAKE_UHD + // This is probably very approximate + usleep( (1000000 / uwd->sampleRate) * samps_to_send); + size_t num_tx_samps = samps_to_send; +#else //send a single packet size_t num_tx_samps = myTxStream->send( &in[num_acc_samps], samps_to_send, md, timeout); +#endif num_acc_samps += num_tx_samps; @@ -515,6 +549,7 @@ void UHDWorker::process() #endif } +#if FAKE_UHD == 0 uhd::async_metadata_t async_md; if (uwd->myUsrp->get_device()->recv_async_msg(async_md, 0)) { const char* uhd_async_message = ""; @@ -545,11 +580,12 @@ void UHDWorker::process() if (failure) { uwd->logger->level(alert) << "Near frame " << - frame->fct << ": Received Async UHD Message '" << + frame->ts.fct << ": Received Async UHD Message '" << uhd_async_message << "'"; } } +#endif /* bool got_async_burst_ack = false; -- cgit v1.2.3 From 11295eabfdb514b43918b8ac45945d36f81f4bd7 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 26 Sep 2014 11:23:53 +0200 Subject: Interrupt UHD when FCT value is not contiguous --- src/EtiReader.cpp | 6 ++++-- src/OutputUHD.cpp | 35 ++++++++++++++++------------------- src/TimestampDecoder.cpp | 20 ++++++++++++++------ 3 files changed, 34 insertions(+), 27 deletions(-) (limited to 'src/OutputUHD.cpp') diff --git a/src/EtiReader.cpp b/src/EtiReader.cpp index f7376cc..fe54f55 100644 --- a/src/EtiReader.cpp +++ b/src/EtiReader.cpp @@ -297,11 +297,13 @@ bool EtiReader::sourceContainsTimestamp() double EtiReader::getPPSOffset() { - if (!sourceContainsTimestamp()) + if (!sourceContainsTimestamp()) { + //fprintf(stderr, "****** SOURCE NO TS\n"); return 0.0; + } uint32_t timestamp = ntohl(eti_tist.TIST) & 0xFFFFFF; - //fprintf(stderr, "TIST 0x%x\n", timestamp); + //fprintf(stderr, "****** TIST 0x%x\n", timestamp); double pps = timestamp / 16384000.0; // seconds return pps; diff --git a/src/OutputUHD.cpp b/src/OutputUHD.cpp index 927d2e6..3d8eea6 100644 --- a/src/OutputUHD.cpp +++ b/src/OutputUHD.cpp @@ -346,7 +346,10 @@ void UHDWorker::process() md.start_of_burst = false; md.end_of_burst = false; + int expected_next_fct = -1; + while (running) { + bool fct_discontinuity = false; md.has_time_spec = false; md.time_spec = uhd::time_spec_t(0.0); num_acc_samps = 0; @@ -376,19 +379,20 @@ void UHDWorker::process() sizeIn = uwd->bufsize / sizeof(complexf); -#if FAKE_UHD + /* Verify that the FCT value is correct. If we miss one transmission + * frame we must interrupt UHD and resync to the timestamps + */ if (expected_next_fct != -1) { - if (expected_next_fct != frame->ts.fct) { + if (expected_next_fct != (int)frame->ts.fct) { uwd->logger->level(warn) << "OutputUHD: Incorrect expect fct " << frame->ts.fct; - // TODO here we should disrupt the UHD streamer so that - // it resyncs to the correct timestamps + fct_discontinuity = true; } } expected_next_fct = (frame->ts.fct + uwd->fct_increment) % 250; -#else + // Check for ref_lock if (uwd->check_refclk_loss) { @@ -482,7 +486,6 @@ void UHDWorker::process() goto loopend; } } -#endif PDEBUG("UHDWorker::process:max_num_samps: %zu.\n", usrp_max_num_samps); @@ -492,8 +495,13 @@ void UHDWorker::process() //ensure the the last packet has EOB set if the timestamps has been //refreshed and need to be reconsidered. - md.end_of_burst = (frame->ts.timestamp_refresh && - (samps_to_send <= usrp_max_num_samps)); + //Also, if we saw that the FCT did not increment as expected, which + //could be due to a lost incoming packet. + md.end_of_burst = ( + uwd->sourceContainsTimestamp && + (frame->ts.timestamp_refresh || fct_discontinuity) && + samps_to_send <= usrp_max_num_samps ); + #if FAKE_UHD // This is probably very approximate @@ -586,17 +594,6 @@ void UHDWorker::process() } } #endif - - /* - bool got_async_burst_ack = false; - //loop through all messages for the ACK packet (may have underflow messages in queue) - while (not got_async_burst_ack and uwd->myUsrp->get_device()->recv_async_msg(async_md, 0.2)){ - got_async_burst_ack = (async_md.event_code == uhd::async_metadata_t::EVENT_CODE_BURST_ACK); - } - //std::cerr << (got_async_burst_ack? "success" : "fail") << std::endl; - // */ - - } last_pps = pps_offset; diff --git a/src/TimestampDecoder.cpp b/src/TimestampDecoder.cpp index 1bb4dd2..96c84c0 100644 --- a/src/TimestampDecoder.cpp +++ b/src/TimestampDecoder.cpp @@ -35,7 +35,7 @@ #include "Eti.h" #include "Log.h" -//#define MDEBUG(fmt, args...) fprintf (LOG, fmt , ## args) +//#define MDEBUG(fmt, args...) fprintf (LOG, "*****" fmt , ## args) #define MDEBUG(fmt, args...) PDEBUG(fmt, ## args) @@ -52,6 +52,7 @@ void TimestampDecoder::calculateTimestamp(struct frame_timestamp& ts) ts_queued->timestamp_refresh = offset_changed; offset_changed = false; + MDEBUG("time_secs=%d, time_pps=%f\n", time_secs, time_pps); *ts_queued += timestamp_offset; queue_timestamps.push(ts_queued); @@ -90,7 +91,7 @@ void TimestampDecoder::calculateTimestamp(struct frame_timestamp& ts) delete ts_queued; } - PDEBUG("Timestamp queue size %zu, delay_calc %u\n", + MDEBUG("Timestamp queue size %zu, delay_calc %u\n", queue_timestamps.size(), modconfig.delay_calculation_pipeline_stages); @@ -157,13 +158,14 @@ void TimestampDecoder::pushMNSCData(int framephase, uint16_t mnsc) void TimestampDecoder::updateTimestampSeconds(uint32_t secs) { - MDEBUG("TimestampDecoder::updateTimestampSeconds(%d)\n", secs); if (inhibit_second_update > 0) { + MDEBUG("TimestampDecoder::updateTimestampSeconds(%d) inhibit\n", secs); inhibit_second_update--; } else { + MDEBUG("TimestampDecoder::updateTimestampSeconds(%d) apply\n", secs); time_secs = secs; } } @@ -229,13 +231,16 @@ bool TimestampDecoder::updateModulatorOffset() } catch (bad_lexical_cast& e) { - myLogger.level(error) << "Error parsing timestamp offset from file '" << modconfig.offset_filename << "'"; + myLogger.level(error) << + "Error parsing timestamp offset from file '" << + modconfig.offset_filename << "'"; r = false; } } else { - myLogger.level(error) << "Error reading from timestamp offset file: eof reached\n"; + myLogger.level(error) << + "Error reading from timestamp offset file: eof reached\n"; r = false; } filestream.close(); @@ -252,7 +257,9 @@ bool TimestampDecoder::updateModulatorOffset() if (timestamp_offset != newoffset) { timestamp_offset = newoffset; - myLogger.level(info) << "TimestampDecoder::updateTimestampOffset: new offset is " << timestamp_offset; + myLogger.level(info) << + "TimestampDecoder::updateTimestampOffset: new offset is " << + timestamp_offset; offset_changed = true; } @@ -264,3 +271,4 @@ bool TimestampDecoder::updateModulatorOffset() return false; } } + -- cgit v1.2.3 From 2ba0bcee8b4b3c0ace3d70bae07d8d5d3152da95 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 14 Nov 2014 14:44:09 +0100 Subject: Remove Makefile.am UHD check --- configure.ac | 2 -- src/Makefile.am | 8 +------- src/OutputUHD.cpp | 4 ++++ src/OutputUHD.h | 3 +++ 4 files changed, 8 insertions(+), 9 deletions(-) (limited to 'src/OutputUHD.cpp') diff --git a/configure.ac b/configure.ac index 7f7ad0a..005b1fc 100644 --- a/configure.ac +++ b/configure.ac @@ -129,8 +129,6 @@ AS_IF([test "x$enable_output_uhd" = "xyes"], [AC_DEFINE(HAVE_OUTPUT_UHD, [1], [Define if UHD output is enabled]) , AC_CHECK_LIB([uhd], [main], [], [AC_MSG_ERROR([library uhd is missing])])]) -AM_CONDITIONAL([HAVE_OUTPUT_UHD_TEST], [test "x$enable_output_uhd" = "xyes"]) - AX_BOOST_BASE([1.41.0], [], AC_MSG_ERROR([BOOST 1.41 or later is required])) AC_CHECK_LIB([boost_system], [main], [], [AC_MSG_ERROR([library boost_system is missing])]) AC_CHECK_LIB([boost_thread], [main], [], [AC_MSG_ERROR([library boost_thread is missing])]) diff --git a/src/Makefile.am b/src/Makefile.am index 635a3d8..922ce52 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,12 +22,6 @@ else GITVERSION_FLAGS = endif -if HAVE_OUTPUT_UHD_TEST -UHD_SOURCES = OutputUHD.cpp OutputUHD.h -else -UHD_SOURCES = -endif - if HAVE_SSE SIMD_CFLAGS = -msse -msse2 else @@ -92,7 +86,7 @@ odr_dabmod_SOURCES = DabMod.cpp \ OutputMemory.cpp OutputMemory.h \ OutputZeroMQ.cpp OutputZeroMQ.h \ TimestampDecoder.h TimestampDecoder.cpp \ - $(UHD_SOURCES) \ + OutputUHD.cpp OutputUHD.h \ ModOutput.cpp ModOutput.h \ InputMemory.cpp InputMemory.h \ InputFileReader.cpp InputZeroMQReader.cpp InputReader.h \ diff --git a/src/OutputUHD.cpp b/src/OutputUHD.cpp index 3d8eea6..8063e75 100644 --- a/src/OutputUHD.cpp +++ b/src/OutputUHD.cpp @@ -25,6 +25,9 @@ */ #include "OutputUHD.h" + +#ifdef HAVE_OUTPUT_UHD + #include "PcDebug.h" #include "Log.h" #include "RemoteControl.h" @@ -652,3 +655,4 @@ const string OutputUHD::get_parameter(const string& parameter) const return ss.str(); } +#endif // HAVE_OUTPUT_UHD diff --git a/src/OutputUHD.h b/src/OutputUHD.h index ef9740d..a2ffb7d 100644 --- a/src/OutputUHD.h +++ b/src/OutputUHD.h @@ -42,6 +42,8 @@ DESCRIPTION: # include #endif +#ifdef HAVE_OUTPUT_UHD + #include #include #include @@ -230,6 +232,7 @@ class OutputUHD: public ModOutput, public RemoteControllable { size_t lastLen; }; +#endif // HAVE_OUTPUT_UHD #endif // OUTPUT_UHD_H -- cgit v1.2.3