From 1d833b718845b97a5b1d90f33b547b1772bc0708 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Sun, 7 Jan 2018 08:49:29 +0100 Subject: Add new flowgraph path for metadata --- src/BlockPartitioner.cpp | 45 ++++++++++++++++++++++++------ src/BlockPartitioner.h | 21 ++++++++------ src/DabModulator.cpp | 13 +++++++-- src/DabModulator.h | 9 ++++-- src/EtiReader.cpp | 7 +++-- src/FicSource.cpp | 24 +++++++++++++++- src/FicSource.h | 11 ++++++-- src/Flowgraph.cpp | 68 ++++++++++++++++++++++++++++++++++++++++------ src/Flowgraph.h | 14 +++++++--- src/ModPlugin.h | 17 ++++++++++++ src/OutputFile.cpp | 56 ++++++++++++++++++++++++++++---------- src/OutputFile.h | 22 +++++++++++---- src/OutputMemory.cpp | 14 +++++++++- src/OutputMemory.h | 16 ++++++++--- src/TimestampDecoder.cpp | 48 ++++++++++++++++++++++++++++++-- src/TimestampDecoder.h | 71 ++++++++++++++++-------------------------------- 16 files changed, 341 insertions(+), 115 deletions(-) diff --git a/src/BlockPartitioner.cpp b/src/BlockPartitioner.cpp index 9e9f80b..54405d9 100644 --- a/src/BlockPartitioner.cpp +++ b/src/BlockPartitioner.cpp @@ -1,6 +1,11 @@ /* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) + + Copyright (C) 2018 + Matthias P. Braendli, matthias.braendli@mpb.li + + http://opendigitalradio.org */ /* This file is part of ODR-DabMod. @@ -21,6 +26,8 @@ #include "BlockPartitioner.h" #include "PcDebug.h" +#include "Log.h" +#include "TimestampDecoder.h" #include #include @@ -31,6 +38,7 @@ BlockPartitioner::BlockPartitioner(unsigned mode, unsigned phase) : ModMux(), + ModMetadata(), d_mode(mode) { PDEBUG("BlockPartitioner::BlockPartitioner(%i)\n", mode); @@ -68,17 +76,11 @@ BlockPartitioner::BlockPartitioner(unsigned mode, unsigned phase) : d_cifNb = 0; // For Synchronisation purpose, count nb of CIF to drop d_cifPhase = phase % d_cifCount; + d_metaPhase = phase % d_cifCount; d_cifSize = 864 * 8; } -BlockPartitioner::~BlockPartitioner() -{ - PDEBUG("BlockPartitioner::~BlockPartitioner()\n"); - -} - - // dataIn[0] -> FIC // dataIn[1] -> CIF int BlockPartitioner::process(std::vector dataIn, Buffer* dataOut) @@ -124,10 +126,10 @@ int BlockPartitioner::process(std::vector dataIn, Buffer* dataOut) uint8_t* out = reinterpret_cast(dataOut->getData()); // Copy FIC data - PDEBUG("Writting FIC %zu bytes to %zu\n", d_ficSize, d_cifNb * d_ficSize); + PDEBUG("Writing FIC %zu bytes to %zu\n", d_ficSize, d_cifNb * d_ficSize); memcpy(out + (d_cifNb * d_ficSize), fic, d_ficSize); // Copy CIF data - PDEBUG("Writting CIF %u bytes to %zu\n", 864 * 8, + PDEBUG("Writing CIF %u bytes to %zu\n", 864 * 8, (d_cifCount * d_ficSize) + (d_cifNb * 864 * 8)); memcpy(out + (d_cifCount * d_ficSize) + (d_cifNb * 864 * 8), cif, 864 * 8); @@ -137,3 +139,28 @@ int BlockPartitioner::process(std::vector dataIn, Buffer* dataOut) return d_cifNb == 0; } + +meta_vec_t BlockPartitioner::process_metadata(const meta_vec_t& metadataIn) +{ + // Synchronize CIF phase + if (d_metaPhase != 0) { + if (++d_metaPhase == d_cifCount) { + d_metaPhase = 0; + } + // Drop this metadata + return {}; + } + + if (d_cifNb == 1) { + d_meta.clear(); + } + + std::copy(metadataIn.begin(), metadataIn.end(), std::back_inserter(d_meta)); + + if (d_cifNb == 0) { + return d_meta; + } + else { + return {}; + } +} diff --git a/src/BlockPartitioner.h b/src/BlockPartitioner.h index 90cffa3..a4656a1 100644 --- a/src/BlockPartitioner.h +++ b/src/BlockPartitioner.h @@ -1,6 +1,11 @@ /* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) + + Copyright (C) 2018 + Matthias P. Braendli, matthias.braendli@mpb.li + + http://opendigitalradio.org */ /* This file is part of ODR-DabMod. @@ -25,32 +30,32 @@ # include #endif - #include "ModPlugin.h" #include +#include -#include - - -class BlockPartitioner : public ModMux +class BlockPartitioner : public ModMux, public ModMetadata { public: BlockPartitioner(unsigned mode, unsigned phase); - virtual ~BlockPartitioner(); - BlockPartitioner(const BlockPartitioner&); - BlockPartitioner& operator=(const BlockPartitioner&); int process(std::vector dataIn, Buffer* dataOut); const char* name() { return "BlockPartitioner"; } + // The implementation assumes process_metadata is always called after process + virtual meta_vec_t process_metadata(const meta_vec_t& metadataIn); + protected: int d_mode; size_t d_ficSize; size_t d_cifCount; size_t d_cifNb; size_t d_cifPhase; + size_t d_metaPhase; size_t d_cifSize; size_t d_outputFramesize; size_t d_outputFramecount; + + meta_vec_t d_meta; }; diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp index 0818f4f..f1ea071 100644 --- a/src/DabModulator.cpp +++ b/src/DabModulator.cpp @@ -3,7 +3,7 @@ Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2017 + Copyright (C) 2018 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -218,7 +218,7 @@ int DabModulator::process(Buffer* dataOut) rcs.enrol(cifPoly.get()); } - auto myOutput = make_shared(dataOut); + myOutput = make_shared(dataOut); shared_ptr cifRes; if (m_settings.outputRate != 2048000) { @@ -392,3 +392,12 @@ int DabModulator::process(Buffer* dataOut) return myFlowgraph->run(); } +meta_vec_t DabModulator::process_metadata(const meta_vec_t& metadataIn) +{ + if (myOutput) { + return myOutput->get_latest_metadata(); + } + + return {}; +} + diff --git a/src/DabModulator.h b/src/DabModulator.h index 6878853..e806c92 100644 --- a/src/DabModulator.h +++ b/src/DabModulator.h @@ -3,7 +3,7 @@ Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2017 + Copyright (C) 2018 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -46,7 +46,7 @@ #include "TII.h" -class DabModulator : public ModInput +class DabModulator : public ModInput, public ModMetadata { public: DabModulator(EtiSource& etiSource, @@ -55,6 +55,9 @@ public: int process(Buffer* dataOut); const char* name() { return "DabModulator"; } + virtual meta_vec_t process_metadata( + const meta_vec_t& metadataIn); + /* Required to get the timestamp */ EtiSource* getEtiSource() { return &myEtiSource; } @@ -73,5 +76,7 @@ protected: size_t mySymSize; size_t myFicSizeOut; size_t myFicSizeIn; + + std::shared_ptr myOutput; }; diff --git a/src/EtiReader.cpp b/src/EtiReader.cpp index d84ed1f..dc5df84 100644 --- a/src/EtiReader.cpp +++ b/src/EtiReader.cpp @@ -281,6 +281,8 @@ int EtiReader::loadEtiData(const Buffer& dataIn) myTimestampDecoder.updateTimestampEti(eti_fc.FP & 0x3, eti_eoh.MNSC, getPPSOffset(), eti_fc.FCT); + myFicSource->loadTimestamp(myTimestampDecoder.getTimestamp()); + return dataIn.getLength() - input_size; } @@ -533,8 +535,9 @@ void EdiReader::assemble() const std::time_t posix_timestamp_1_jan_2000 = 946684800; auto utc_ts = posix_timestamp_1_jan_2000 + m_seconds - m_utco; - m_timestamp_decoder.updateTimestampEdi( - utc_ts, m_fc.tsta, m_fc.fct()); + m_timestamp_decoder.updateTimestampEdi(utc_ts, m_fc.tsta, m_fc.fct(), m_fc.fp); + + myFicSource->loadTimestamp(m_timestamp_decoder.getTimestamp()); m_frameReady = true; } diff --git a/src/FicSource.cpp b/src/FicSource.cpp index 04197db..2b95085 100644 --- a/src/FicSource.cpp +++ b/src/FicSource.cpp @@ -2,7 +2,7 @@ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2018 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -26,6 +26,8 @@ #include "FicSource.h" #include "PcDebug.h" +#include "Log.h" +#include "TimestampDecoder.h" #include #include @@ -92,3 +94,23 @@ int FicSource::process(Buffer* outputData) return outputData->getLength(); } +void FicSource::loadTimestamp(const std::shared_ptr& ts) +{ + d_ts = ts; +} + + +meta_vec_t FicSource::process_metadata(const meta_vec_t& metadataIn) +{ + if (not d_ts) { + return {}; + } + + using namespace std; + meta_vec_t md_vec; + flowgraph_metadata meta; + meta.ts = d_ts; + md_vec.push_back(meta); + return md_vec; +} + diff --git a/src/FicSource.h b/src/FicSource.h index 77ac741..93c1a7f 100644 --- a/src/FicSource.h +++ b/src/FicSource.h @@ -36,7 +36,7 @@ #include #include -class FicSource : public ModInput +class FicSource : public ModInput, public ModMetadata { public: FicSource(unsigned ficf, unsigned mid); @@ -45,12 +45,17 @@ public: const std::vector& get_rules(); void loadFicData(const Buffer& fic); - int process(Buffer* outputData); - const char* name() { return "FicSource"; } + int process(Buffer* outputData) override; + const char* name() override { return "FicSource"; } + + void loadTimestamp(const std::shared_ptr& ts); + virtual meta_vec_t process_metadata( + const meta_vec_t& metadataIn) override; private: size_t d_framesize; Buffer d_buffer; + std::shared_ptr d_ts; std::vector d_puncturing_rules; }; diff --git a/src/Flowgraph.cpp b/src/Flowgraph.cpp index 465ef41..0b80a8c 100644 --- a/src/Flowgraph.cpp +++ b/src/Flowgraph.cpp @@ -26,6 +26,8 @@ #include "Flowgraph.h" #include "PcDebug.h" +#include "Log.h" +#include "TimestampDecoder.h" #include #include #include @@ -57,9 +59,10 @@ Node::~Node() assert(myOutputBuffers.size() == 0); } -void Node::addOutputBuffer(Buffer::sptr& buffer) +void Node::addOutputBuffer(Buffer::sptr& buffer, Metadata_vec_sptr& md) { myOutputBuffers.push_back(buffer); + myOutputMetadata.push_back(md); #if DEBUG std::string fname = string(myPlugin->name()) + "-" + to_string(myDebugFiles.size()) + @@ -71,7 +74,7 @@ void Node::addOutputBuffer(Buffer::sptr& buffer) #endif } -void Node::removeOutputBuffer(Buffer::sptr& buffer) +void Node::removeOutputBuffer(Buffer::sptr& buffer, Metadata_vec_sptr& md) { auto it = std::find( myOutputBuffers.begin(), @@ -89,14 +92,23 @@ void Node::removeOutputBuffer(Buffer::sptr& buffer) #endif myOutputBuffers.erase(it); } + + auto mdit = std::find( + myOutputMetadata.begin(), + myOutputMetadata.end(), + md); + if (mdit != myOutputMetadata.end()) { + myOutputMetadata.erase(mdit); + } } -void Node::addInputBuffer(Buffer::sptr& buffer) +void Node::addInputBuffer(Buffer::sptr& buffer, Metadata_vec_sptr& md) { myInputBuffers.push_back(buffer); + myInputMetadata.push_back(md); } -void Node::removeInputBuffer(Buffer::sptr& buffer) +void Node::removeInputBuffer(Buffer::sptr& buffer, Metadata_vec_sptr& md) { auto it = std::find( myInputBuffers.begin(), @@ -105,6 +117,14 @@ void Node::removeInputBuffer(Buffer::sptr& buffer) if (it != myInputBuffers.end()) { myInputBuffers.erase(it); } + + auto mdit = std::find( + myInputMetadata.begin(), + myInputMetadata.end(), + md); + if (mdit != myInputMetadata.end()) { + myInputMetadata.erase(mdit); + } } int Node::process() @@ -127,6 +147,36 @@ int Node::process() } int ret = myPlugin->process(inBuffers, outBuffers); + + // Collect all incoming metadata into a single vector + meta_vec_t all_input_mds; + for (auto& md_vec_sp : myInputMetadata) { + if (md_vec_sp) { + copy(md_vec_sp->begin(), md_vec_sp->end(), + back_inserter(all_input_mds)); + } + } + + auto mod_meta = dynamic_pointer_cast(myPlugin); + if (mod_meta) { + auto outputMetadata = mod_meta->process_metadata(all_input_mds); + // Distribute the result metadata to all outputs + for (auto& out_md : myOutputMetadata) { + out_md->clear(); + std::move(outputMetadata.begin(), outputMetadata.end(), + std::back_inserter(*out_md)); + } + } + else { + // Propagate the unmodified input metadata to all outputs + for (auto& out_md : myOutputMetadata) { + out_md->clear(); + std::move(all_input_mds.begin(), all_input_mds.end(), + std::back_inserter(*out_md)); + } + } + + #if DEBUG assert(myDebugFiles.size() == myOutputBuffers.size()); @@ -158,8 +208,10 @@ Edge::Edge(shared_ptr& srcNode, shared_ptr& dstNode) : this); myBuffer = make_shared(); - srcNode->addOutputBuffer(myBuffer); - dstNode->addInputBuffer(myBuffer); + myMetadata = make_shared >(); + + srcNode->addOutputBuffer(myBuffer, myMetadata); + dstNode->addInputBuffer(myBuffer, myMetadata); } @@ -168,8 +220,8 @@ Edge::~Edge() PDEBUG("Edge::~Edge() @ %p\n", this); if (myBuffer) { - mySrcNode->removeOutputBuffer(myBuffer); - myDstNode->removeInputBuffer(myBuffer); + mySrcNode->removeOutputBuffer(myBuffer, myMetadata); + myDstNode->removeInputBuffer(myBuffer, myMetadata); } } diff --git a/src/Flowgraph.h b/src/Flowgraph.h index ebb7314..2742824 100644 --- a/src/Flowgraph.h +++ b/src/Flowgraph.h @@ -39,6 +39,8 @@ #include #include +using Metadata_vec_sptr = std::shared_ptr >; + class Node { public: @@ -55,15 +57,18 @@ public: myProcessTime += processTime; } - void addOutputBuffer(Buffer::sptr& buffer); - void removeOutputBuffer(Buffer::sptr& buffer); + void addOutputBuffer(Buffer::sptr& buffer, Metadata_vec_sptr& md); + void removeOutputBuffer(Buffer::sptr& buffer, Metadata_vec_sptr& md); - void addInputBuffer(Buffer::sptr& buffer); - void removeInputBuffer(Buffer::sptr& buffer); + void addInputBuffer(Buffer::sptr& buffer, Metadata_vec_sptr& md); + void removeInputBuffer(Buffer::sptr& buffer, Metadata_vec_sptr& md); protected: std::list myInputBuffers; std::list myOutputBuffers; + std::list myInputMetadata; + std::list myOutputMetadata; + #if DEBUG std::list myDebugFiles; #endif @@ -85,6 +90,7 @@ protected: std::shared_ptr mySrcNode; std::shared_ptr myDstNode; std::shared_ptr myBuffer; + std::shared_ptr > myMetadata; }; diff --git a/src/ModPlugin.h b/src/ModPlugin.h index d3aa780..3c3e8b3 100644 --- a/src/ModPlugin.h +++ b/src/ModPlugin.h @@ -119,3 +119,20 @@ public: std::vector dataOut); virtual int process(Buffer* dataIn) = 0; }; + +struct frame_timestamp; +struct flowgraph_metadata { + std::shared_ptr ts; +}; + + +using meta_vec_t = std::vector; + +/* Some ModPlugins also support metadata */ +class ModMetadata { + public: + // Receives metadata from all inputs, and process them, and output + // a sequence of metadata. + virtual meta_vec_t process_metadata(const meta_vec_t& metadataIn) = 0; +}; + diff --git a/src/OutputFile.cpp b/src/OutputFile.cpp index 23d5523..3bb45c4 100644 --- a/src/OutputFile.cpp +++ b/src/OutputFile.cpp @@ -2,7 +2,7 @@ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2018 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -26,47 +26,73 @@ #include "OutputFile.h" #include "PcDebug.h" +#include "Log.h" +#include "TimestampDecoder.h" #include #include #include +using namespace std; + OutputFile::OutputFile(std::string filename) : ModOutput(), + ModMetadata(), myFilename(filename) { PDEBUG("OutputFile::OutputFile(filename: %s) @ %p\n", filename.c_str(), this); - myFile = fopen(filename.c_str(), "w"); - if (myFile == NULL) { + FILE* fd = fopen(filename.c_str(), "w"); + if (fd == nullptr) { perror(filename.c_str()); throw std::runtime_error( "OutputFile::OutputFile() unable to open file!"); } -} - - -OutputFile::~OutputFile() -{ - PDEBUG("OutputFile::~OutputFile() @ %p\n", this); - - if (myFile != NULL) { - fclose(myFile); - } + myFile.reset(fd); } int OutputFile::process(Buffer* dataIn) { PDEBUG("OutputFile::process(%p)\n", dataIn); - assert(dataIn != NULL); + assert(dataIn != nullptr); - if (fwrite(dataIn->getData(), dataIn->getLength(), 1, myFile) == 0) { + if (fwrite(dataIn->getData(), dataIn->getLength(), 1, myFile.get()) == 0) { throw std::runtime_error( "OutputFile::process() unable to write to file!"); } return dataIn->getLength(); } + +meta_vec_t OutputFile::process_metadata(const meta_vec_t& metadataIn) +{ + stringstream ss; + + if (metadataIn.empty()) { + etiLog.level(debug) << "OutputFile: no mdIn"; + } + + for (const auto& md : metadataIn) { + if (md.ts) { + ss << "FCT=" << md.ts->fct << + " FP=" << (int)md.ts->fp; + if (md.ts->timestamp_valid) { + ss << " ts=" << md.ts->timestamp_sec << + "+" << md.ts->timestamp_pps << ", "; + } + else { + ss << " no ts"; + } + } + else { + ss << "void, "; + } + } + + etiLog.level(debug) << "Output File got metadata: " << ss.str(); + + return {}; +} diff --git a/src/OutputFile.h b/src/OutputFile.h index 7121ef3..2b92369 100644 --- a/src/OutputFile.h +++ b/src/OutputFile.h @@ -2,7 +2,7 @@ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2018 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -36,19 +36,29 @@ #include #include #include +#include +struct FILEDeleter { + void operator()(FILE* fd) { + if (fd) { + fclose(fd); + } + } +}; -class OutputFile : public ModOutput +class OutputFile : public ModOutput, public ModMetadata { public: OutputFile(std::string filename); - virtual ~OutputFile(); - virtual int process(Buffer* dataIn); - const char* name() { return "OutputFile"; } + virtual int process(Buffer* dataIn) override; + const char* name() override { return "OutputFile"; } + + virtual meta_vec_t process_metadata( + const meta_vec_t& metadataIn) override; protected: std::string myFilename; - FILE* myFile; + std::unique_ptr myFile; }; diff --git a/src/OutputMemory.cpp b/src/OutputMemory.cpp index 6e2fd49..5f24095 100644 --- a/src/OutputMemory.cpp +++ b/src/OutputMemory.cpp @@ -2,7 +2,7 @@ Copyright (C) 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2018 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -26,6 +26,7 @@ #include "OutputMemory.h" #include "PcDebug.h" +#include "Log.h" #include #include @@ -94,3 +95,14 @@ int OutputMemory::process(Buffer* dataIn) return myDataOut->getLength(); } +meta_vec_t OutputMemory::process_metadata(const meta_vec_t& metadataIn) +{ + myMetadata = metadataIn; + return {}; +} + +meta_vec_t OutputMemory::get_latest_metadata() +{ + return myMetadata; +} + diff --git a/src/OutputMemory.h b/src/OutputMemory.h index 715cb2d..f0a5fbb 100644 --- a/src/OutputMemory.h +++ b/src/OutputMemory.h @@ -2,7 +2,7 @@ Copyright (C) 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2018 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -46,18 +46,26 @@ #include "ModPlugin.h" -class OutputMemory : public ModOutput +class OutputMemory : public ModOutput, public ModMetadata { public: OutputMemory(Buffer* dataOut); virtual ~OutputMemory(); - virtual int process(Buffer* dataIn); - const char* name() { return "OutputMemory"; } + OutputMemory(OutputMemory& other) = delete; + OutputMemory& operator=(OutputMemory& other) = delete; + + virtual int process(Buffer* dataIn) override; + const char* name() override { return "OutputMemory"; } + virtual meta_vec_t process_metadata( + const meta_vec_t& metadataIn) override; + + meta_vec_t get_latest_metadata(void); void setOutput(Buffer* dataOut); protected: Buffer* myDataOut; + meta_vec_t myMetadata; #if OUTPUT_MEM_HISTOGRAM // keep track of max value diff --git a/src/TimestampDecoder.cpp b/src/TimestampDecoder.cpp index 26deb60..6cf2875 100644 --- a/src/TimestampDecoder.cpp +++ b/src/TimestampDecoder.cpp @@ -37,6 +37,22 @@ //#define MDEBUG(fmt, args...) fprintf (LOG, "*****" fmt , ## args) #define MDEBUG(fmt, args...) PDEBUG(fmt, ## args) +TimestampDecoder::TimestampDecoder(double& offset_s, unsigned tist_delay_stages) : + RemoteControllable("tist"), + timestamp_offset(offset_s), + m_tist_delay_stages(tist_delay_stages) +{ + // Properly initialise temp_time + memset(&temp_time, 0, sizeof(temp_time)); + const time_t timep = 0; + gmtime_r(&timep, &temp_time); + + RC_ADD_PARAMETER(offset, "TIST offset [s]"); + RC_ADD_PARAMETER(timestamp, "FCT and timestamp [s]"); + + etiLog.level(info) << "Setting up timestamp decoder with " << + timestamp_offset << " offset"; +} void TimestampDecoder::calculateTimestamp(frame_timestamp& ts) { @@ -48,6 +64,7 @@ void TimestampDecoder::calculateTimestamp(frame_timestamp& ts) ts_queued->timestamp_sec = time_secs; ts_queued->timestamp_pps = time_pps; ts_queued->fct = latestFCT; + ts_queued->fp = latestFP; ts_queued->timestamp_refresh = offset_changed; offset_changed = false; @@ -102,7 +119,29 @@ void TimestampDecoder::calculateTimestamp(frame_timestamp& ts) //ts.print("calc2 "); } -void TimestampDecoder::pushMNSCData(int framephase, uint16_t mnsc) +std::shared_ptr TimestampDecoder::getTimestamp() +{ + std::shared_ptr ts = + std::make_shared(); + + /* Push new timestamp into queue */ + ts->timestamp_valid = full_timestamp_received; + ts->timestamp_sec = time_secs; + ts->timestamp_pps = time_pps; + ts->fct = latestFCT; + ts->fp = latestFP; + + ts->timestamp_refresh = offset_changed; + offset_changed = false; + + MDEBUG("time_secs=%d, time_pps=%f\n", time_secs, + (double)time_pps / 16384000.0); + *ts += timestamp_offset; + + return ts; +} + +void TimestampDecoder::pushMNSCData(uint8_t framephase, uint16_t mnsc) { struct eti_MNSC_TIME_0 *mnsc0; struct eti_MNSC_TIME_1 *mnsc1; @@ -190,7 +229,7 @@ void TimestampDecoder::updateTimestampPPS(uint32_t pps) } void TimestampDecoder::updateTimestampEti( - int framephase, + uint8_t framephase, uint16_t mnsc, uint32_t pps, // In units of 1/16384000 s int32_t fct) @@ -198,16 +237,19 @@ void TimestampDecoder::updateTimestampEti( updateTimestampPPS(pps); pushMNSCData(framephase, mnsc); latestFCT = fct; + latestFP = framephase; } void TimestampDecoder::updateTimestampEdi( uint32_t seconds_utc, uint32_t pps, // In units of 1/16384000 s - int32_t fct) + int32_t fct, + uint8_t framephase) { time_secs = seconds_utc; time_pps = pps; latestFCT = fct; + latestFP = framephase; full_timestamp_received = true; } diff --git a/src/TimestampDecoder.h b/src/TimestampDecoder.h index 943b241..4bbf5cc 100644 --- a/src/TimestampDecoder.h +++ b/src/TimestampDecoder.h @@ -40,6 +40,7 @@ struct frame_timestamp { // Which frame count does this timestamp apply to int32_t fct; + uint8_t fp; // Frame Phase uint32_t timestamp_sec; uint32_t timestamp_pps; // In units of 1/16384000 s @@ -56,6 +57,7 @@ struct frame_timestamp this->timestamp_valid = rhs.timestamp_valid; this->timestamp_refresh = rhs.timestamp_refresh; this->fct = rhs.fct; + this->fp = rhs.fp; } return *this; @@ -103,49 +105,23 @@ struct frame_timestamp class TimestampDecoder : public RemoteControllable { public: - TimestampDecoder( - /* The modulator adds this offset to the TIST to define time of - * frame transmission - */ - double& offset_s, - - /* Specifies by how many stages the timestamp must be delayed. - * (e.g. The FIRFilter is pipelined, therefore we must increase - * tist_delay_stages by one if the filter is used - */ - unsigned tist_delay_stages) : - RemoteControllable("tist"), - timestamp_offset(offset_s) - { - m_tist_delay_stages = tist_delay_stages; - inhibit_second_update = 0; - time_pps = 0.0; - time_secs = 0; - latestFCT = 0; - enableDecode = false; - full_timestamp_received = false; - - // Properly initialise temp_time - memset(&temp_time, 0, sizeof(temp_time)); - const time_t timep = 0; - gmtime_r(&timep, &temp_time); - - offset_changed = false; - - RC_ADD_PARAMETER(offset, "TIST offset [s]"); - RC_ADD_PARAMETER(timestamp, "FCT and timestamp [s]"); - - etiLog.level(info) << "Setting up timestamp decoder with " << - timestamp_offset << " offset"; - - }; + /* offset_s: The modulator adds this offset to the TIST to define time of + * frame transmission + * + * tist_delay_stages: Specifies by how many stages the timestamp must + * be delayed. (e.g. The FIRFilter is pipelined, therefore we must + * increase tist_delay_stages by one if the filter is used + */ + TimestampDecoder(double& offset_s, unsigned tist_delay_stages); /* Calculate the timestamp for the current frame. */ void calculateTimestamp(frame_timestamp& ts); + std::shared_ptr getTimestamp(void); + /* Update timestamp data from ETI */ void updateTimestampEti( - int framephase, + uint8_t framephase, uint16_t mnsc, uint32_t pps, // In units of 1/16384000 s int32_t fct); @@ -154,7 +130,8 @@ class TimestampDecoder : public RemoteControllable void updateTimestampEdi( uint32_t seconds_utc, uint32_t pps, // In units of 1/16384000 s - int32_t fct); + int32_t fct, + uint8_t framephase); /*********** REMOTE CONTROL ***************/ @@ -171,7 +148,7 @@ class TimestampDecoder : public RemoteControllable protected: /* Push a new MNSC field into the decoder */ - void pushMNSCData(int framephase, uint16_t mnsc); + void pushMNSCData(uint8_t framephase, uint16_t mnsc); /* Each frame contains the TIST field with the PPS offset. * For each frame, this function must be called to update @@ -191,21 +168,22 @@ class TimestampDecoder : public RemoteControllable void updateTimestampSeconds(uint32_t secs); struct tm temp_time; - uint32_t time_secs; - int32_t latestFCT; - uint32_t time_pps; + uint32_t time_secs = 0; + int32_t latestFCT = 0; + uint32_t latestFP = 0; + uint32_t time_pps = 0; double& timestamp_offset; unsigned m_tist_delay_stages; - int inhibit_second_update; - bool offset_changed; + int inhibit_second_update = 0; + bool offset_changed = false; /* When the type or identifier don't match, the decoder must * be disabled */ - bool enableDecode; + bool enableDecode = false; /* Disable timstamps until full time has been received */ - bool full_timestamp_received; + bool full_timestamp_received = false; /* when pipelining, we must shift the calculated timestamps * through this queue. Otherwise, it would not be possible to @@ -213,6 +191,5 @@ class TimestampDecoder : public RemoteControllable * FIRFilter (1 stage pipeline) */ std::queue > queue_timestamps; - }; -- cgit v1.2.3