diff options
-rw-r--r-- | doc/example.ini | 1 | ||||
-rw-r--r-- | src/DabMod.cpp | 2 | ||||
-rw-r--r-- | src/EtiReader.cpp | 39 | ||||
-rw-r--r-- | src/EtiReader.h | 16 | ||||
-rw-r--r-- | src/Flowgraph.cpp | 53 | ||||
-rw-r--r-- | src/TimestampDecoder.cpp | 12 | ||||
-rw-r--r-- | src/TimestampDecoder.h | 17 |
7 files changed, 94 insertions, 46 deletions
diff --git a/doc/example.ini b/doc/example.ini index a0cd110..3dd8505 100644 --- a/doc/example.ini +++ b/doc/example.ini @@ -60,6 +60,7 @@ loop=0 ; before it timeouts ;edi_max_delay=240 ; No support yet for multicast, should work with and without PFT +; This EDI implementation does not support EDI Packet Resend ; When recieving data using ZeroMQ, the source is the URI to be used ;transport=zeromq diff --git a/src/DabMod.cpp b/src/DabMod.cpp index ac7842f..44951d7 100644 --- a/src/DabMod.cpp +++ b/src/DabMod.cpp @@ -699,7 +699,7 @@ int launch_modulator(int argc, char* argv[]) } - EdiReader ediReader; + EdiReader ediReader(tist_offset_s, tist_delay_stages); EdiDecoder::ETIDecoder ediInput(ediReader); if (edi_max_delay_ms > 0.0f) { // setMaxDelay wants number of AF packets, which correspond to 24ms ETI frames diff --git a/src/EtiReader.cpp b/src/EtiReader.cpp index a1053c6..f0a1793 100644 --- a/src/EtiReader.cpp +++ b/src/EtiReader.cpp @@ -304,6 +304,13 @@ uint32_t EtiReader::getPPSOffset() return timestamp; } +EdiReader::EdiReader( + double& tist_offset_s, + unsigned tist_delay_stages) : + m_timestamp_decoder(tist_offset_s, tist_delay_stages) +{ + rcs.enrol(&m_timestamp_decoder); +} unsigned EdiReader::getMode() { @@ -339,6 +346,19 @@ const std::vector<std::shared_ptr<SubchannelSource> > EdiReader::getSubchannels( return sources; } +bool EdiReader::sourceContainsTimestamp() +{ + if (not (m_frameReady and m_fc_valid)) { + throw std::runtime_error("Trying to get timestamp before it is ready"); + } + + return m_fc.tsta != 0xFFFFFF; +} + +void EdiReader::calculateTimestamp(struct frame_timestamp& ts) +{ +} + bool EdiReader::isFrameReady() { return m_frameReady; @@ -493,13 +513,20 @@ void EdiReader::assemble() // Accept zero subchannels, because of an edge-case that can happen // during reconfiguration. See ETS 300 799 Clause 5.3.3 - // TODO check time validity + if (m_utco == 0 and m_seconds == 0) { + // We don't support relative-only timestamps + m_fc.tsta = 0xFFFFFF; // disable TSTA + } + + /* According to Annex F + * EDI = UTC + UTCO + * We need UTC = EDI - UTCO + */ + auto utc_ts = m_seconds - m_utco; + + m_timestamp_decoder.updateTimestampEdi( + utc_ts, m_fc.tsta, m_fc.fct()); - /* TODO timestamp - myTimestampDecoder.updateTimestampEti( - eti_fc.FP & 0x3, - eti_eoh.MNSC, getPPSOffset(), eti_fc.FCT); - */ m_frameReady = true; } diff --git a/src/EtiReader.h b/src/EtiReader.h index 1b75025..5231365 100644 --- a/src/EtiReader.h +++ b/src/EtiReader.h @@ -122,11 +122,14 @@ private: class EdiReader : public EtiSource, public EdiDecoder::DataCollector { public: + EdiReader( + double& tist_offset_s, + unsigned tist_delay_stages); + virtual unsigned getMode(); virtual unsigned getFp(); - virtual bool sourceContainsTimestamp() { return false; } - virtual void calculateTimestamp(struct frame_timestamp& ts) - { /* TODO */ } + virtual bool sourceContainsTimestamp(); + virtual void calculateTimestamp(struct frame_timestamp& ts); virtual const std::vector<std::shared_ptr<SubchannelSource> > getSubchannels() const; virtual bool isFrameReady(void); @@ -181,10 +184,13 @@ private: uint16_t m_rfu = 0xffff; std::map<uint8_t, std::shared_ptr<SubchannelSource> > m_sources; + + TimestampDecoder m_timestamp_decoder; }; -/* The EDI input does not use the inputs defined in InputReader.h, as they were designed - * for ETI. It uses the EdiUdpInput which in turn uses a threaded receiver. +/* The EDI input does not use the inputs defined in InputReader.h, as they were + * designed for ETI. It uses the EdiUdpInput which in turn uses a threaded + * receiver. */ class EdiUdpInput { diff --git a/src/Flowgraph.cpp b/src/Flowgraph.cpp index 0eb1c60..ae75808 100644 --- a/src/Flowgraph.cpp +++ b/src/Flowgraph.cpp @@ -111,32 +111,6 @@ void Node::removeInputBuffer(Buffer::sptr& buffer) } } -Edge::Edge(shared_ptr<Node>& srcNode, shared_ptr<Node>& dstNode) : - mySrcNode(srcNode), - myDstNode(dstNode) -{ - PDEBUG("Edge::Edge(srcNode(%s): %p, dstNode(%s): %p) @ %p\n", - srcNode->plugin()->name(), srcNode.get(), - dstNode->plugin()->name(), dstNode.get(), - this); - - myBuffer = make_shared<Buffer>(); - srcNode->addOutputBuffer(myBuffer); - dstNode->addInputBuffer(myBuffer); -} - - -Edge::~Edge() -{ - PDEBUG("Edge::~Edge() @ %p\n", this); - - if (myBuffer) { - mySrcNode->removeOutputBuffer(myBuffer); - myDstNode->removeInputBuffer(myBuffer); - } -} - - int Node::process() { PDEBUG("Node::process()\n"); @@ -178,12 +152,37 @@ int Node::process() return ret; } +Edge::Edge(shared_ptr<Node>& srcNode, shared_ptr<Node>& dstNode) : + mySrcNode(srcNode), + myDstNode(dstNode) +{ + PDEBUG("Edge::Edge(srcNode(%s): %p, dstNode(%s): %p) @ %p\n", + srcNode->plugin()->name(), srcNode.get(), + dstNode->plugin()->name(), dstNode.get(), + this); + + myBuffer = make_shared<Buffer>(); + srcNode->addOutputBuffer(myBuffer); + dstNode->addInputBuffer(myBuffer); +} + + +Edge::~Edge() +{ + PDEBUG("Edge::~Edge() @ %p\n", this); + + if (myBuffer) { + mySrcNode->removeOutputBuffer(myBuffer); + myDstNode->removeInputBuffer(myBuffer); + } +} + + Flowgraph::Flowgraph() : myProcessTime(0) { PDEBUG("Flowgraph::Flowgraph() @ %p\n", this); - } diff --git a/src/TimestampDecoder.cpp b/src/TimestampDecoder.cpp index 5f93407..42d53ab 100644 --- a/src/TimestampDecoder.cpp +++ b/src/TimestampDecoder.cpp @@ -2,7 +2,7 @@ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2014, 2015 + Copyright (C) 2017 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -197,6 +197,16 @@ void TimestampDecoder::updateTimestampEti( latestFCT = fct; } +void TimestampDecoder::updateTimestampEdi( + uint32_t seconds_utc, + uint32_t pps, // In units of 1/16384000 s + int32_t fct) +{ + updateTimestampPPS(pps); + time_secs = seconds_utc; + latestFCT = fct; +} + void TimestampDecoder::set_parameter( const std::string& parameter, const std::string& value) diff --git a/src/TimestampDecoder.h b/src/TimestampDecoder.h index 29e12c2..a822ee5 100644 --- a/src/TimestampDecoder.h +++ b/src/TimestampDecoder.h @@ -2,7 +2,7 @@ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2014, 2015 + Copyright (C) 2017 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -24,8 +24,7 @@ along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef TIMESTAMP_DECODER_H -#define TIMESTAMP_DECODER_H +#pragma once #include <queue> #include <memory> @@ -97,7 +96,8 @@ struct frame_timestamp } }; -/* This module decodes MNSC time information */ +/* This module decodes MNSC time information from an ETI source and + * EDI time information*/ class TimestampDecoder : public RemoteControllable { public: @@ -135,13 +135,19 @@ class TimestampDecoder : public RemoteControllable /* Calculate the timestamp for the current frame. */ void calculateTimestamp(struct frame_timestamp& ts); - /* Update timestamp data from data in ETI */ + /* Update timestamp data from ETI */ void updateTimestampEti( int framephase, uint16_t mnsc, uint32_t pps, // In units of 1/16384000 s int32_t fct); + /* Update timestamp data from EDI */ + void updateTimestampEdi( + uint32_t seconds_utc, + uint32_t pps, // In units of 1/16384000 s + int32_t fct); + /*********** REMOTE CONTROL ***************/ /* Base function to set parameters. */ @@ -199,5 +205,4 @@ class TimestampDecoder : public RemoteControllable }; -#endif |