aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2014-09-14 00:08:53 +0200
committerMatthias P. Braendli <matthias.braendli@mpb.li>2014-09-14 00:08:53 +0200
commit685095418bc8fd27dcd0b1d73ad1741114aeda6a (patch)
tree5d959800a98b294cdc08278c8eaf181730190e07
parent0b7bc4a405ea4d6f24fade9420e9919420c64d8e (diff)
downloaddabmod-685095418bc8fd27dcd0b1d73ad1741114aeda6a.tar.gz
dabmod-685095418bc8fd27dcd0b1d73ad1741114aeda6a.tar.bz2
dabmod-685095418bc8fd27dcd0b1d73ad1741114aeda6a.zip
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.
-rw-r--r--src/EtiReader.cpp19
-rw-r--r--src/EtiReader.h9
-rw-r--r--src/InputZeroMQReader.cpp4
-rw-r--r--src/OutputUHD.cpp56
-rw-r--r--src/OutputUHD.h14
-rw-r--r--src/TimestampDecoder.cpp16
-rw-r--r--src/TimestampDecoder.h22
7 files changed, 100 insertions, 40 deletions
diff --git a/src/EtiReader.cpp b/src/EtiReader.cpp
index b61481c..f7376cc 100644
--- a/src/EtiReader.cpp
+++ b/src/EtiReader.cpp
@@ -2,8 +2,10 @@
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty
the Queen in Right of Canada (Communications Research Center Canada)
- Includes modifications for which no copyright is claimed
- 2012, Matthias P. Braendli, matthias.braendli@mpb.li
+ Copyright (C) 2014
+ Matthias P. Braendli, matthias.braendli@mpb.li
+
+ http://opendigitalradio.org
*/
/*
This file is part of ODR-DabMod.
@@ -269,18 +271,17 @@ int EtiReader::process(Buffer* dataIn)
}
break;
default:
- // throw std::runtime_error("Invalid state!");
+ // throw std::runtime_error("Invalid state!");
PDEBUG("Invalid state (%i)!", state);
input_size = 0;
}
}
-
+
// Update timestamps
myTimestampDecoder.updateTimestampEti(eti_fc.FP & 0x3,
- eti_eoh.MNSC,
- getPPSOffset());
+ eti_eoh.MNSC, getPPSOffset(), eti_fc.FCT);
- if (getFCT() % 125 == 0) //every 3 seconds is fine enough
+ if (eti_fc.FCT % 125 == 0) //every 3 seconds is fine enough
{
myTimestampDecoder.updateModulatorOffset();
}
@@ -306,7 +307,3 @@ double EtiReader::getPPSOffset()
return pps;
}
-uint32_t EtiReader::getFCT()
-{
- return eti_fc.FCT;
-}
diff --git a/src/EtiReader.h b/src/EtiReader.h
index be12075..209b208 100644
--- a/src/EtiReader.h
+++ b/src/EtiReader.h
@@ -2,8 +2,10 @@
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty
the Queen in Right of Canada (Communications Research Center Canada)
- Includes modifications for which no copyright is claimed
- 2012, Matthias P. Braendli, matthias.braendli@mpb.li
+ Copyright (C) 2014
+ Matthias P. Braendli, matthias.braendli@mpb.li
+
+ http://opendigitalradio.org
*/
/*
This file is part of ODR-DabMod.
@@ -60,9 +62,6 @@ public:
myTimestampDecoder.calculateTimestamp(ts);
}
- /* Return the frame counter */
- uint32_t getFCT();
-
/* Returns true if we have valid time stamps in the ETI*/
bool sourceContainsTimestamp();
diff --git a/src/InputZeroMQReader.cpp b/src/InputZeroMQReader.cpp
index cf3f7aa..cfb56b2 100644
--- a/src/InputZeroMQReader.cpp
+++ b/src/InputZeroMQReader.cpp
@@ -3,8 +3,10 @@
Her Majesty the Queen in Right of Canada (Communications Research
Center Canada)
- Copyrigth (C) 2013, 2014
+ Copyright (C) 2013, 2014
Matthias P. Braendli, matthias.braendli@mpb.li
+
+ http://opendigitalradio.org
*/
/*
This file is part of ODR-DabMod.
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;
diff --git a/src/OutputUHD.h b/src/OutputUHD.h
index 69e5b20..3a047bf 100644
--- a/src/OutputUHD.h
+++ b/src/OutputUHD.h
@@ -36,6 +36,8 @@ DESCRIPTION:
#ifndef OUTPUT_UHD_H
#define OUTPUT_UHD_H
+#define FAKE_UHD 0
+
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -77,15 +79,14 @@ struct UHDWorkerFrameData {
// Full timestamp
struct frame_timestamp ts;
-
- // Frame counter
- uint32_t fct;
};
enum refclk_lock_loss_behaviour_t { CRASH, IGNORE };
struct UHDWorkerData {
+#if FAKE_UHD == 0
uhd::usrp::multi_usrp::sptr myUsrp;
+#endif
unsigned sampleRate;
// Double buffering between the two threads
@@ -117,7 +118,12 @@ struct UHDWorkerData {
// The common logger
Logger* logger;
-};
+
+ // What transmission mode we're using defines by how
+ // much the FCT should increment for each
+ // transmission frame.
+ int fct_increment;
+};
class UHDWorker {
diff --git a/src/TimestampDecoder.cpp b/src/TimestampDecoder.cpp
index d6c627f..1bb4dd2 100644
--- a/src/TimestampDecoder.cpp
+++ b/src/TimestampDecoder.cpp
@@ -2,8 +2,10 @@
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Her Majesty the
Queen in Right of Canada (Communications Research Center Canada)
- Includes modifications for which no copyright is claimed
- 2012, Matthias P. Braendli, matthias.braendli@mpb.li
+ Copyright (C) 2014
+ Matthias P. Braendli, matthias.braendli@mpb.li
+
+ http://opendigitalradio.org
*/
/*
This file is part of ODR-DabMod.
@@ -45,6 +47,7 @@ void TimestampDecoder::calculateTimestamp(struct frame_timestamp& ts)
ts_queued->timestamp_valid = full_timestamp_received_mnsc;
ts_queued->timestamp_sec = time_secs;
ts_queued->timestamp_pps_offset = time_pps;
+ ts_queued->fct = latestFCT;
ts_queued->timestamp_refresh = offset_changed;
offset_changed = false;
@@ -65,6 +68,7 @@ void TimestampDecoder::calculateTimestamp(struct frame_timestamp& ts)
ts.timestamp_sec = 0;
ts.timestamp_pps_offset = 0;
ts.timestamp_refresh = false;
+ ts.fct = 0;
}
else {
//fprintf(stderr, ". %zu ", queue_timestamps.size());
@@ -179,13 +183,17 @@ void TimestampDecoder::updateTimestampPPS(double pps)
}
time_pps = pps;
-
}
-void TimestampDecoder::updateTimestampEti(int framephase, uint16_t mnsc, double pps)
+void TimestampDecoder::updateTimestampEti(
+ int framephase,
+ uint16_t mnsc,
+ double pps,
+ uint32_t fct)
{
updateTimestampPPS(pps);
pushMNSCData(framephase, mnsc);
+ latestFCT = fct;
}
diff --git a/src/TimestampDecoder.h b/src/TimestampDecoder.h
index 52290ac..0c393e4 100644
--- a/src/TimestampDecoder.h
+++ b/src/TimestampDecoder.h
@@ -2,8 +2,10 @@
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Her Majesty the
Queen in Right of Canada (Communications Research Center Canada)
- Includes modifications for which no copyright is claimed
- 2012, Matthias P. Braendli, matthias.braendli@mpb.li
+ Copyright (C) 2014
+ Matthias P. Braendli, matthias.braendli@mpb.li
+
+ http://opendigitalradio.org
*/
/*
This file is part of ODR-DabMod.
@@ -52,6 +54,9 @@ struct modulator_offset_config
struct frame_timestamp
{
+ // Which frame count does this timestamp apply to
+ uint32_t fct;
+
uint32_t timestamp_sec;
double timestamp_pps_offset;
bool timestamp_valid;
@@ -64,6 +69,7 @@ struct frame_timestamp
this->timestamp_pps_offset = rhs.timestamp_pps_offset;
this->timestamp_valid = rhs.timestamp_valid;
this->timestamp_refresh = rhs.timestamp_refresh;
+ this->fct = rhs.fct;
}
return *this;
@@ -104,7 +110,7 @@ struct frame_timestamp
/* This module decodes MNSC time information */
class TimestampDecoder
{
- public:
+ public:
TimestampDecoder(
struct modulator_offset_config& config,
Logger& logger):
@@ -113,6 +119,7 @@ class TimestampDecoder
inhibit_second_update = 0;
time_pps = 0.0;
time_secs = 0;
+ latestFCT = 0;
enableDecode = false;
full_timestamp_received_mnsc = false;
gmtime_r(0, &temp_time);
@@ -129,7 +136,11 @@ class TimestampDecoder
void calculateTimestamp(struct frame_timestamp& ts);
/* Update timestamp data from data in ETI */
- void updateTimestampEti(int framephase, uint16_t mnsc, double pps);
+ void updateTimestampEti(
+ int framephase,
+ uint16_t mnsc,
+ double pps,
+ uint32_t fct);
/* Update the modulator timestamp offset according to the modconf
*/
@@ -147,7 +158,7 @@ class TimestampDecoder
* the timestamp
*/
void updateTimestampPPS(double pps);
-
+
/* Update the timestamp when a full set of MNSC data is
* known. This function can be called at most every four
* frames when the data is transferred using the MNSC.
@@ -156,6 +167,7 @@ class TimestampDecoder
struct tm temp_time;
uint32_t time_secs;
+ uint32_t latestFCT;
double time_pps;
double timestamp_offset;
int inhibit_second_update;