diff --git a/configure.h b/configure.h index ab3c52e..e108fcf 100644 --- a/configure.h +++ b/configure.h @@ -59,7 +59,6 @@ class Configure bool GetCommandPortEnabled(){return _commandPortEnabled;} uint16_t GetLinesPerField(){return _linesPerField;} bool GetReverseFlag(){return _reverseBits;} - int GetDebugLevel(){return _debugLevel;} int GetMagazinePriority(uint8_t mag){return _magazinePriority[mag];} OutputFormat GetOutputFormat(){return _OutputFormat;} @@ -98,7 +97,6 @@ class Configure uint8_t _subtitleRepeats; /// Number of times a subtitle repeats (typically 1 or 2). bool _commandPortEnabled; bool _reverseBits; - int _debugLevel; OutputFormat _OutputFormat; uint16_t _PID; diff --git a/debug.cpp b/debug.cpp index 8aadc2f..2ce0d34 100644 --- a/debug.cpp +++ b/debug.cpp @@ -26,6 +26,6 @@ void Debug::SetMagCycleDuration(int mag, int duration) if (mag >= 0 && mag < 8) { _magDurations[mag] = duration; - Log(logDEBUG, "magazine " + std::to_string(mag) + " cycle duration: " + std::to_string(duration) + " seconds"); + Log(logDEBUG, "Magazine " + std::to_string(mag) + " cycle duration: " + std::to_string(duration / 50) + " seconds, " + std::to_string(duration % 50) + " fields"); } } diff --git a/debug.h b/debug.h index c36204e..36c68a1 100644 --- a/debug.h +++ b/debug.h @@ -27,6 +27,7 @@ namespace vbit void Log(LogLevels level, std::string str); void SetDebugLevel(LogLevels level){ _debugLevel = level; }; + LogLevels GetDebugLevel(){ return _debugLevel; }; void SetMagCycleDuration(int mag, int duration); std::array GetMagCycleDurations(){ return _magDurations; }; diff --git a/masterClock.h b/masterClock.h new file mode 100644 index 0000000..f528861 --- /dev/null +++ b/masterClock.h @@ -0,0 +1,31 @@ +#ifndef _MASTERCLOCK_H_ +#define _MASTERCLOCK_H_ + +#include + +namespace vbit +{ + class MasterClock { + public: + struct timeStruct { + time_t seconds; + uint8_t fields; + }; + + static MasterClock *Instance(){ + if (!instance) + instance = new MasterClock; + return instance; + } + + void SetMasterClock(timeStruct t){ _masterClock = t; } + timeStruct GetMasterClock(){ return _masterClock; } + + private: + MasterClock(){ _masterClock = {0, 0}; }; // initialise master clock to unix epoch, it will be set when run() starts generating packets + static MasterClock *instance; + timeStruct _masterClock; + }; +} + +#endif // _MASTERCLOCK_H_ diff --git a/packet.cpp b/packet.cpp index 11ff5a0..a43e00b 100644 --- a/packet.cpp +++ b/packet.cpp @@ -1,6 +1,5 @@ #include "packet.h" #include "version.h" -#include "vbit2.h" using namespace vbit; @@ -207,7 +206,7 @@ std::array* Packet::tx() { // get master clock singleton vbit::MasterClock *mc = mc->Instance(); - time_t t = mc->GetMasterClock(); + time_t t = mc->GetMasterClock().seconds; // Get local time struct tm * timeinfo; @@ -328,7 +327,7 @@ void Packet::Header(uint8_t mag, uint8_t page, uint16_t subcode, uint16_t contro // get master clock singleton vbit::MasterClock *mc = mc->Instance(); - time_t t = mc->GetMasterClock(); + time_t t = mc->GetMasterClock().seconds; // Get local time struct tm * timeinfo; diff --git a/packet.h b/packet.h index 3c22549..d8e7567 100644 --- a/packet.h +++ b/packet.h @@ -12,6 +12,7 @@ #include "tables.h" #include #include "ttxpage.h" +#include "masterClock.h" /** * Teletext packet. diff --git a/packet830.cpp b/packet830.cpp index d89dcc8..a631656 100644 --- a/packet830.cpp +++ b/packet830.cpp @@ -21,7 +21,7 @@ Packet830::~Packet830() Packet* Packet830::GetPacket(Packet* p) { vbit::MasterClock *mc = mc->Instance(); - time_t timeRaw = mc->GetMasterClock(); + time_t timeRaw = mc->GetMasterClock().seconds; time_t timeLocal; struct tm *tmLocal; struct tm *tmGMT; diff --git a/packetDebug.cpp b/packetDebug.cpp index 1f562d2..e3f3756 100644 --- a/packetDebug.cpp +++ b/packetDebug.cpp @@ -1,4 +1,4 @@ -#include +#include "packetDebug.h" using namespace vbit; @@ -29,13 +29,13 @@ Packet* PacketDebug::GetPacket(Packet* p) data.push_back(_debugData.ver); // debug data version number // current internal master clock - data.push_back(_debugData.masterClock >> 24); - data.push_back(_debugData.masterClock >> 16); - data.push_back(_debugData.masterClock >> 8); - data.push_back(_debugData.masterClock); + data.push_back(_debugData.masterClockSeconds >> 24); + data.push_back(_debugData.masterClockSeconds >> 16); + data.push_back(_debugData.masterClockSeconds >> 8); + data.push_back(_debugData.masterClockSeconds); // current field count - data.push_back(_debugData.fieldCount); + data.push_back(_debugData.masterClockFields); // current system clock data.push_back(_debugData.systemClock >> 24); @@ -43,11 +43,12 @@ Packet* PacketDebug::GetPacket(Packet* p) data.push_back(_debugData.systemClock >> 8); data.push_back(_debugData.systemClock); - std::array magDurations = _debug->GetMagCycleDurations(); + std::array magDurations = _debug->GetMagCycleDurations(); // get magazine durations in number of fields for (int i=0; i<8; i++){ - if(magDurations[i] < 0 || magDurations[i] > 255) - magDurations[i] = 255; // clamp range 0-255 - data.push_back(magDurations[i]); + if(magDurations[i] < 0 || magDurations[i] / 50 > 255) + data.push_back(255); // clamp to 255 seconds + else + data.push_back(magDurations[i] / 50); // truncate to whole seconds } p->IDLA(_datachannel, Packet::IDLA_DL, 6, _servicePacketAddress, 0, _debugPacketCI++, data); @@ -60,7 +61,7 @@ bool PacketDebug::IsReady(bool force) (void)force; // silence error about unused parameter bool result=false; - if (_configure->GetDebugLevel()) + if (_debug->GetDebugLevel()) // TODO have specific configuration for datacast debugging packet { if (GetEvent(EVENT_FIELD)) { @@ -73,10 +74,10 @@ bool PacketDebug::IsReady(bool force) return result; } -void PacketDebug::TimeAndField(time_t masterClock, uint8_t fieldCount, time_t systemClock) +void PacketDebug::TimeAndField(MasterClock::timeStruct masterClock, time_t systemClock) { // update the clocks in _debugData struct - called once per field by Service::_updateEvents() - _debugData.masterClock = masterClock; - _debugData.fieldCount = fieldCount; + _debugData.masterClockSeconds = masterClock.seconds; + _debugData.masterClockFields = masterClock.fields; _debugData.systemClock = systemClock; } diff --git a/packetDebug.h b/packetDebug.h index 3daaf62..9c9df27 100644 --- a/packetDebug.h +++ b/packetDebug.h @@ -8,10 +8,7 @@ #include "configure.h" #include "debug.h" -#define VBIT2_DEBUG_VERSION 0x00 // Debug API version - -#define MAXMESSAGEBUFFER 30 // maximum number of debug messages to queue before discarding -#define BUFFERRECOVER 20 // size buffer must shrink to before allowing new messages to be queued after an overrun +#define VBIT2_DEBUG_VERSION 0x01 // Debug API version namespace vbit { @@ -26,7 +23,7 @@ namespace vbit // overrides Packet* GetPacket(Packet* p) override; - void TimeAndField(time_t masterClock, uint8_t fieldCount, time_t systemClock); + void TimeAndField(MasterClock::timeStruct masterClock, time_t systemClock); bool IsReady(bool force=false); @@ -44,8 +41,8 @@ namespace vbit { char header[4] = {'V','B','I','T'}; uint8_t ver = VBIT2_DEBUG_VERSION; - time_t masterClock = 0; - uint8_t fieldCount = 0; + time_t masterClockSeconds = 0; + uint8_t masterClockFields = 0; time_t systemClock = 0; }; diff --git a/packetmag.cpp b/packetmag.cpp index c4937fa..241c864 100644 --- a/packetmag.cpp +++ b/packetmag.cpp @@ -2,7 +2,6 @@ */ #include "packetmag.h" -#include "vbit2.h" using namespace vbit; @@ -24,10 +23,11 @@ PacketMag::PacketMag(uint8_t mag, std::list* pageSet, ttx::Config _magRegion(0), _specialPagesFlipFlop(false), _waitingForField(0), - _lastCycle(0), _cycleDuration(-1) { //ctor + _lastCycle = {0,0}; + for (int i=0;iGetHeaderTemplate(); @@ -158,10 +158,11 @@ Packet* PacketMag::GetPacket(Packet* p) { // reached the end of a magazine cycle // get master clock singleton - vbit::MasterClock *mc = mc->Instance(); - time_t t = mc->GetMasterClock(); - if (_lastCycle){ // wait for real timestamps - _cycleDuration = difftime(t, _lastCycle); // truncates double to int + MasterClock *mc = mc->Instance(); + MasterClock::timeStruct t = mc->GetMasterClock(); + if (_lastCycle.seconds){ // wait for real timestamps + int diffSeconds = difftime(t.seconds, _lastCycle.seconds); // truncates double to int + _cycleDuration = ((diffSeconds * 50) - _lastCycle.fields) + t.fields; _debug->SetMagCycleDuration(_magNumber, _cycleDuration); } _lastCycle = t; // update timestamp diff --git a/packetmag.h b/packetmag.h index bb26629..90ea100 100644 --- a/packetmag.h +++ b/packetmag.h @@ -10,13 +10,12 @@ #include "updatedpages.h" #include "configure.h" #include "debug.h" +#include "masterClock.h" #define MAXPACKET29TYPES 3 namespace vbit { - enum PacketState {PACKETSTATE_HEADER, PACKETSTATE_FASTEXT, PACKETSTATE_PACKET26, PACKETSTATE_PACKET27, PACKETSTATE_PACKET28, PACKETSTATE_TEXTROW}; - class PacketMag : public PacketSource { public: @@ -57,6 +56,8 @@ namespace vbit protected: private: + enum PacketState {PACKETSTATE_HEADER, PACKETSTATE_FASTEXT, PACKETSTATE_PACKET26, PACKETSTATE_PACKET27, PACKETSTATE_PACKET28, PACKETSTATE_TEXTROW}; + std::list* _pageSet; //!< Member variable "_pageSet" ttx::Configure* _configure; Debug* _debug; @@ -91,8 +92,8 @@ namespace vbit bool _specialPagesFlipFlop; // toggle to alternate between special pages and normal pages int _waitingForField; - time_t _lastCycle; - int _cycleDuration; + MasterClock::timeStruct _lastCycle; + int _cycleDuration; // magazine cycle time in fields }; } diff --git a/service.cpp b/service.cpp index 9e03d83..a41c858 100644 --- a/service.cpp +++ b/service.cpp @@ -1,7 +1,6 @@ /** Service */ #include "service.h" -#include "vbit2.h" using namespace ttx; using namespace vbit; @@ -159,7 +158,7 @@ int Service::run() void Service::_updateEvents() { vbit::MasterClock *mc = mc->Instance(); - time_t masterClock = mc->GetMasterClock(); + vbit::MasterClock::timeStruct masterClock = mc->GetMasterClock(); // Step the counters _lineCounter = (_lineCounter + 1) % _linesPerField; @@ -171,29 +170,29 @@ void Service::_updateEvents() time_t now; time(&now); - if (masterClock > now + FORWARDSBUFFER) // allow vbit2 to run into the future before limiting packet rate + if (masterClock.seconds > now + FORWARDSBUFFER) // allow vbit2 to run into the future before limiting packet rate std::this_thread::sleep_for(std::chrono::milliseconds(40)); // back off for ≈2 fields to limit output to (less than) 50 fields per second if (_fieldCounter == 0) { - masterClock++; // step the master clock before updating debug packet + masterClock.seconds++; // step the master clock before updating debug packet } - _packetDebug->TimeAndField(masterClock, _fieldCounter, now); // update the clocks in debugPacket. + masterClock.fields = _fieldCounter; + + _packetDebug->TimeAndField(masterClock, now); // update the clocks in debugPacket. if (_fieldCounter == 0) { // if internal master clock is behind real time, or too far ahead, resynchronise it. - if (masterClock < now || masterClock > now + FORWARDSBUFFER + 1) + if (masterClock.seconds < now || masterClock.seconds > now + FORWARDSBUFFER + 1) { - masterClock = now; + masterClock.seconds = now; _debug->Log(Debug::LogLevels::logWARN,"[Service::_updateEvents] Resynchronising master clock"); } - mc->SetMasterClock(masterClock); // update the master clock singleton - - if (masterClock%15==0) // TODO: how often do we want to trigger sending special packets? + if (masterClock.seconds%15==0) // TODO: how often do we want to trigger sending special packets? { for (std::list::const_iterator iterator = _Sources.begin(), end = _Sources.end(); iterator != end; ++iterator) { @@ -202,6 +201,9 @@ void Service::_updateEvents() } } } + + mc->SetMasterClock(masterClock); // update the master clock singleton + // New field, so set the FIELD event in all the sources. for (std::list::const_iterator iterator = _Sources.begin(), end = _Sources.end(); iterator != end; ++iterator) { diff --git a/service.h b/service.h index 4c45e93..748e21f 100644 --- a/service.h +++ b/service.h @@ -12,11 +12,12 @@ #include "pagelist.h" #include "packetServer.h" #include "packet.h" -#include -#include -#include -#include -#include +#include "packetsource.h" +#include "packetmag.h" +#include "packet830.h" +#include "packetsubtitle.h" +#include "packetDebug.h" +#include "masterClock.h" namespace ttx { diff --git a/ttxpagestream.cpp b/ttxpagestream.cpp index 29c913c..71cb898 100644 --- a/ttxpagestream.cpp +++ b/ttxpagestream.cpp @@ -1,5 +1,4 @@ #include "ttxpagestream.h" -#include "vbit2.h" TTXPageStream::TTXPageStream() : _transitionTime(0), @@ -101,7 +100,7 @@ void TTXPageStream::SetTransitionTime(int cycleTime) if (GetCycleTimeMode() == 'T') { vbit::MasterClock *mc = mc->Instance(); - _transitionTime = mc->GetMasterClock() + cycleTime; + _transitionTime = mc->GetMasterClock().seconds + cycleTime; } else { @@ -115,7 +114,7 @@ bool TTXPageStream::Expired(bool StepCycles) if (GetCycleTimeMode() == 'T') { vbit::MasterClock *mc = mc->Instance(); - return _transitionTime <= mc->GetMasterClock(); + return _transitionTime <= mc->GetMasterClock().seconds; } else { diff --git a/ttxpagestream.h b/ttxpagestream.h index 8622f78..10466a2 100644 --- a/ttxpagestream.h +++ b/ttxpagestream.h @@ -5,6 +5,7 @@ #include "ttxpage.h" #include "packet.h" +#include "masterClock.h" /** @brief Extends TTXPage to allow Service to iterate through this page. * It adds iterators to the page and also timing control if it is a carousel. diff --git a/vbit2.h b/vbit2.h index 8582e90..9d7f9c3 100644 --- a/vbit2.h +++ b/vbit2.h @@ -10,6 +10,7 @@ #include "filemonitor.h" #include "command.h" #include "packetServer.h" +#include "masterClock.h" #ifdef WIN32 #include "fcntl.h" @@ -17,22 +18,7 @@ namespace vbit { - class MasterClock { - public: - static MasterClock *Instance(){ - if (!instance) - instance = new MasterClock; - return instance; - } - - void SetMasterClock(time_t t){_masterClock = t;} - time_t GetMasterClock(){return _masterClock;} - - private: - MasterClock(){_masterClock = 0;}; // initialise master clock to unix epoch, it will be set when run() starts generating packets - static MasterClock *instance; - time_t _masterClock; - }; + } #endif