summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2023-03-04 23:02:48 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2023-03-04 23:02:48 +0100
commit7c6dac7fa29ccd84da890aee7a0b1004dcd93d8b (patch)
treec01bf35a1e0dfe87e3bd13de2f9d695ad2f47ed8 /src
parent8e821c7f8ef72415d84e3f78270c1ae1a85a5304 (diff)
downloaddabmux-7c6dac7fa29ccd84da890aee7a0b1004dcd93d8b.tar.gz
dabmux-7c6dac7fa29ccd84da890aee7a0b1004dcd93d8b.tar.bz2
dabmux-7c6dac7fa29ccd84da890aee7a0b1004dcd93d8b.zip
Align CIF Count and timestamp on startup
Diffstat (limited to 'src')
-rw-r--r--src/DabMultiplexer.cpp73
-rw-r--r--src/DabMultiplexer.h7
2 files changed, 56 insertions, 24 deletions
diff --git a/src/DabMultiplexer.cpp b/src/DabMultiplexer.cpp
index fe7b156..a658262 100644
--- a/src/DabMultiplexer.cpp
+++ b/src/DabMultiplexer.cpp
@@ -99,25 +99,52 @@ void DabMultiplexer::prepare(bool require_tai_clock)
throw MuxInitException();
}
- /* Ensure edi_time and TIST represent current time. Keep
- * a granularity of 24ms, which corresponds to the
- * duration of an ETI frame, to get nicer timestamps.
+ /* At startup, derive edi_time, TIST and CIF count such that there is
+ * a consistency across mux restarts. Ensure edi_time and TIST represent
+ * current time.
+ *
+ * Every 6s, FCT overflows. m_currentFrame overflows at 5000 every 120s.
+ *
+ * Keep a granularity of 24ms, which corresponds to the duration of an ETI
+ * frame, to get nicer timestamps.
*/
using Sec = chrono::seconds;
const auto now = chrono::system_clock::now();
- m_edi_time = chrono::system_clock::to_time_t(chrono::time_point_cast<Sec>(now));
- auto offset = now - chrono::time_point_cast<Sec>(now);
+ const time_t t_now = chrono::system_clock::to_time_t(chrono::time_point_cast<Sec>(now));
+
+ m_edi_time = t_now - (t_now % 6);
+ m_currentFrame = 0;
+ time_t edi_time_at_cif0 = t_now - (t_now % 120);
+ while (edi_time_at_cif0 < m_edi_time) {
+ edi_time_at_cif0 += 6;
+ m_currentFrame += 250;
+ }
+
+ if (edi_time_at_cif0 != m_edi_time) {
+ throw std::logic_error("Invalid startup offset calculation for CIF!");
+ }
+
+ const auto offset = now - chrono::time_point_cast<Sec>(now);
if (offset >= chrono::seconds(1)) {
throw std::logic_error("Invalid startup offset calculation for TIST! " +
to_string(chrono::duration_cast<chrono::milliseconds>(offset).count()) +
" ms");
}
+
+ int64_t offset_ms = chrono::duration_cast<chrono::milliseconds>(offset).count();
+ offset_ms += 1000 * (t_now - m_edi_time);
+
m_timestamp = 0;
- while (offset >= chrono::milliseconds(24)) {
+ while (offset_ms >= 24) {
increment_timestamp();
- offset -= chrono::milliseconds(24);
+ m_currentFrame++;
+ offset_ms -= 24;
}
+ etiLog.log(info, "Startup CIF Count %i with timestamp: %d + %f",
+ m_currentFrame, m_edi_time,
+ (m_timestamp & 0xFFFFFF) / 16384000.0);
+
// Try to load offset once
bool tist_enabled = m_pt.get("general.tist", false);
@@ -415,8 +442,12 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs
//****** Field FSYNC *****//
// See ETS 300 799, 6.2.1.2
- sync ^= 0xffffff;
- etiSync->FSYNC = sync;
+ if ((m_currentFrame & 1) == 0) {
+ etiSync->FSYNC = ETI_FSYNC1;
+ }
+ else {
+ etiSync->FSYNC = ETI_FSYNC1 ^ 0xffffff;
+ }
/**********************************************************************
*********** Section LIDATA of ETI(NI, G703) **********************
@@ -430,8 +461,8 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs
//****** FCT ******//
// Incremente for each frame, overflows at 249
- fc->FCT = currentFrame % 250;
- edi_tagDETI.dlfc = currentFrame % 5000;
+ fc->FCT = m_currentFrame % 250;
+ edi_tagDETI.dlfc = m_currentFrame % 5000;
//****** FICF ******//
// Fast Information Channel Flag, 1 bit, =1 if FIC present
@@ -448,7 +479,7 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs
/* Frame Phase, 3 bit counter, tells the COFDM generator
* when to insert the TII. Is also used by the MNSC.
*/
- fc->FP = edi_tagDETI.fp = currentFrame & 0x7;
+ fc->FP = edi_tagDETI.fp = m_currentFrame & 0x7;
//****** MID ******//
//Mode Identity, 2 bits, 01 ModeI, 10 modeII, 11 ModeIII, 00 ModeIV
@@ -580,9 +611,9 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs
edi_tagDETI.fic_length = FICL * 4;
// Insert all FIBs
- fig_carousel.update(currentFrame);
+ fig_carousel.update(m_currentFrame);
const bool fib3_present = (ensemble->transmission_mode == TransmissionMode_e::TM_III);
- index += fig_carousel.write_fibs(&etiFrame[index], currentFrame % 4, fib3_present);
+ index += fig_carousel.write_fibs(&etiFrame[index], m_currentFrame % 4, fib3_present);
/**********************************************************************
****** Input Data Reading *******************************************
@@ -599,7 +630,7 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs
if (result < 0) {
etiLog.log(info,
"Subchannel %d read failed at ETI frame number: %d",
- subchannel->id, currentFrame);
+ subchannel->id, m_currentFrame);
}
// save pointer to Audio or Data Stream into correct TagESTn for EDI
@@ -661,7 +692,7 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs
output->setMetadata(md_edi_time);
shared_ptr<OutputMetadata> md_dlfc =
- make_shared<OutputMetadataDLFC>(currentFrame % 5000);
+ make_shared<OutputMetadataDLFC>(m_currentFrame % 5000);
output->setMetadata(md_dlfc);
}
}
@@ -726,20 +757,20 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs
/**********************************************************************
*********** Output a small message *********************************
**********************************************************************/
- if (currentFrame % 100 == 0) {
+ if (m_currentFrame % 100 == 0) {
if (enableTist) {
etiLog.log(info, "ETI frame number %i Timestamp: %d + %f",
- currentFrame, edi_time,
+ m_currentFrame, edi_time,
(m_timestamp & 0xFFFFFF) / 16384000.0);
}
else {
etiLog.log(info, "ETI frame number %i Time: %d, no TIST",
- currentFrame, edi_time);
+ m_currentFrame, edi_time);
}
}
#endif
- currentFrame++;
+ m_currentFrame++;
}
void DabMultiplexer::print_info()
@@ -775,7 +806,7 @@ const std::string DabMultiplexer::get_parameter(const std::string& parameter) co
{
stringstream ss;
if (parameter == "frames") {
- ss << currentFrame;
+ ss << m_currentFrame;
}
else if (parameter == "tist_offset") {
ss << m_tist_offset;
diff --git a/src/DabMultiplexer.h b/src/DabMultiplexer.h
index 9d7d19b..3b521ff 100644
--- a/src/DabMultiplexer.h
+++ b/src/DabMultiplexer.h
@@ -50,6 +50,8 @@
#include <memory>
#include <boost/property_tree/ptree.hpp>
+constexpr uint32_t ETI_FSYNC1 = 0x49C5F8;
+
class DabMultiplexer : public RemoteControllable {
public:
DabMultiplexer(boost::property_tree::ptree pt);
@@ -59,7 +61,7 @@ class DabMultiplexer : public RemoteControllable {
void prepare(bool require_tai_clock);
- unsigned long getCurrentFrame() { return currentFrame; }
+ unsigned long getCurrentFrame() { return m_currentFrame; }
void mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs);
@@ -89,8 +91,7 @@ class DabMultiplexer : public RemoteControllable {
edi::configuration_t edi_conf;
std::shared_ptr<edi::Sender> edi_sender;
- uint32_t sync = 0x49C5F8;
- unsigned long currentFrame = 0;
+ unsigned long m_currentFrame = 0;
std::shared_ptr<dabEnsemble> ensemble;