Skip to content

Commit

Permalink
Add field precision to master clock
Browse files Browse the repository at this point in the history
  • Loading branch information
ZXGuesser committed May 12, 2024
1 parent 3be411b commit 2cc5518
Show file tree
Hide file tree
Showing 16 changed files with 91 additions and 72 deletions.
2 changes: 0 additions & 2 deletions configure.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;}
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
}
1 change: 1 addition & 0 deletions debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<int,8> GetMagCycleDurations(){ return _magDurations; };

Expand Down
31 changes: 31 additions & 0 deletions masterClock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef _MASTERCLOCK_H_
#define _MASTERCLOCK_H_

#include <cstdint>

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_
5 changes: 2 additions & 3 deletions packet.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include "packet.h"
#include "version.h"
#include "vbit2.h"

using namespace vbit;

Expand Down Expand Up @@ -207,7 +206,7 @@ std::array<uint8_t, PACKETSIZE>* 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;
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "tables.h"
#include <cassert>
#include "ttxpage.h"
#include "masterClock.h"

/**
* Teletext packet.
Expand Down
2 changes: 1 addition & 1 deletion packet830.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
29 changes: 15 additions & 14 deletions packetDebug.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <packetDebug.h>
#include "packetDebug.h"

using namespace vbit;

Expand Down Expand Up @@ -29,25 +29,26 @@ 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);
data.push_back(_debugData.systemClock >> 16);
data.push_back(_debugData.systemClock >> 8);
data.push_back(_debugData.systemClock);

std::array<int, 8> magDurations = _debug->GetMagCycleDurations();
std::array<int, 8> 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);
Expand All @@ -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))
{
Expand All @@ -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;
}
11 changes: 4 additions & 7 deletions packetDebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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);

Expand All @@ -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;
};

Expand Down
13 changes: 7 additions & 6 deletions packetmag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
*/

#include "packetmag.h"
#include "vbit2.h"

using namespace vbit;

Expand All @@ -24,10 +23,11 @@ PacketMag::PacketMag(uint8_t mag, std::list<TTXPageStream>* pageSet, ttx::Config
_magRegion(0),
_specialPagesFlipFlop(false),
_waitingForField(0),
_lastCycle(0),
_cycleDuration(-1)
{
//ctor
_lastCycle = {0,0};

for (int i=0;i<MAXPACKET29TYPES;i++)
{
_headerTemplate = configure->GetHeaderTemplate();
Expand Down Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions packetmag.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -57,6 +56,8 @@ namespace vbit
protected:

private:
enum PacketState {PACKETSTATE_HEADER, PACKETSTATE_FASTEXT, PACKETSTATE_PACKET26, PACKETSTATE_PACKET27, PACKETSTATE_PACKET28, PACKETSTATE_TEXTROW};

std::list<TTXPageStream>* _pageSet; //!< Member variable "_pageSet"
ttx::Configure* _configure;
Debug* _debug;
Expand Down Expand Up @@ -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
};
}

Expand Down
22 changes: 12 additions & 10 deletions service.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/** Service
*/
#include "service.h"
#include "vbit2.h"

using namespace ttx;
using namespace vbit;
Expand Down Expand Up @@ -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;
Expand All @@ -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<vbit::PacketSource*>::const_iterator iterator = _Sources.begin(), end = _Sources.end(); iterator != end; ++iterator)
{
Expand All @@ -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<vbit::PacketSource*>::const_iterator iterator = _Sources.begin(), end = _Sources.end(); iterator != end; ++iterator)
{
Expand Down
11 changes: 6 additions & 5 deletions service.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
#include "pagelist.h"
#include "packetServer.h"
#include "packet.h"
#include <packetsource.h>
#include <packetmag.h>
#include <packet830.h>
#include <packetsubtitle.h>
#include <packetDebug.h>
#include "packetsource.h"
#include "packetmag.h"
#include "packet830.h"
#include "packetsubtitle.h"
#include "packetDebug.h"
#include "masterClock.h"

namespace ttx
{
Expand Down
5 changes: 2 additions & 3 deletions ttxpagestream.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "ttxpagestream.h"
#include "vbit2.h"

TTXPageStream::TTXPageStream() :
_transitionTime(0),
Expand Down Expand Up @@ -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
{
Expand All @@ -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
{
Expand Down
1 change: 1 addition & 0 deletions ttxpagestream.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading

0 comments on commit 2cc5518

Please sign in to comment.