summaryrefslogtreecommitdiffstats
path: root/src
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 /src
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.
Diffstat (limited to 'src')
-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;