Skip to content

Commit

Permalink
add format type to debug datacast packet data, add page counts
Browse files Browse the repository at this point in the history
  • Loading branch information
ZXGuesser committed May 14, 2024
1 parent a8cfbf0 commit 9b8ca9a
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 59 deletions.
12 changes: 11 additions & 1 deletion debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Debug::Debug() :
{
//ctor
_magDurations.fill(-1);
_magSizes.fill(0);
}

Debug::~Debug()
Expand All @@ -26,6 +27,15 @@ 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 / 50) + " seconds, " + std::to_string(duration % 50) + " fields");
Log(logDEBUG, "[Debug::SetMagCycleDuration] Magazine " + std::to_string(mag) + " cycle duration: " + std::to_string(duration / 50) + " seconds, " + std::to_string(duration % 50) + " fields");
}
}

void Debug::SetMagazineSize(int mag, int size)
{
if (mag >= 0 && mag < 8)
{
_magSizes[mag] = (size<255)?size:255; // clamp erroneous sizes to 255
Log(logDEBUG, "[Debug::SetMagazineSize] Magazine " + std::to_string(mag) + " size: " + std::to_string(size) + " pages");
}
}
3 changes: 3 additions & 0 deletions debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,15 @@ namespace vbit
LogLevels GetDebugLevel(){ return _debugLevel; };
void SetMagCycleDuration(int mag, int duration);
std::array<int,8> GetMagCycleDurations(){ return _magDurations; };
void SetMagazineSize(int mag, int size);
std::array<int,8> GetMagSizes(){ return _magSizes; };

protected:

private:
LogLevels _debugLevel;
std::array<int, 8> _magDurations;
std::array<int, 8> _magSizes;
};
}

Expand Down
3 changes: 2 additions & 1 deletion masterClock.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define _MASTERCLOCK_H_

#include <cstdint>
#include <ctime>

namespace vbit
{
Expand All @@ -22,7 +23,7 @@ namespace vbit
timeStruct GetMasterClock(){ return _masterClock; }

private:
MasterClock(){ _masterClock = {0, 0}; }; // initialise master clock to unix epoch, it will be set when run() starts generating packets
MasterClock(){ _masterClock = {time(NULL)-1, 0}; }; // initialise master clock to system time - 1
static MasterClock *instance;
timeStruct _masterClock;
};
Expand Down
4 changes: 2 additions & 2 deletions packet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,13 +540,13 @@ int Packet::IDLA(uint8_t datachannel, uint8_t flags, uint8_t ial, uint32_t spa,
if (flags & IDLA_DL)
_packet[DLoffset]++;

if ((uint8_t)(_packet[p]) == 0xff || (uint8_t)(_packet[p]) == 0x00)
if ((_packet[p] == _packet[p-1]) && ((uint8_t)(_packet[p]) == 0xff || (uint8_t)(_packet[p]) == 0x00))
{
sameCount++;

if ((uint8_t)(_packet[p]) == (uint8_t)(_packet[p-1]))
{
if (sameCount > 7 && p < 42)
if (sameCount >= 7 && p < 42)
{
sameCount = 0;
_packet[++p] = 0xaa; // add a dummy byte
Expand Down
154 changes: 121 additions & 33 deletions packetDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ using namespace vbit;
PacketDebug::PacketDebug(ttx::Configure* configure, Debug* debug) :
_configure(configure),
_debug(debug),
_debugPacketCI(0) // continuity counter for debug datacast packets
_debugPacketCI(0), // continuity counter for debug datacast packets
_startupTime(time(NULL)),
_masterClockSeconds(0),
_masterClockFields(0),
_systemClock(0),
_debugType(FORMAT1),
_clockFlags(CFLAGRESYNC),
_magFlags(0)
{
//ctor

Expand All @@ -21,37 +28,86 @@ PacketDebug::~PacketDebug()

Packet* PacketDebug::GetPacket(Packet* p)
{
// crude packets for timing measurement and monitoring
std::vector<uint8_t> data;
/* Generate simple datacast packets for timing measurement and magazine monitoring.
The user data payload for each format type is padded to a fixed 26 bytes long.
The first byte of each packet payload indicates the format type.
*/

// Debug packet header
data.assign(_debugData.header, _debugData.header + sizeof(_debugData.header)); // "VBIT"
data.push_back(_debugData.ver); // debug data version number
std::vector<uint8_t> data;
int mag;

// current internal master clock
data.push_back(_debugData.masterClockSeconds >> 24);
data.push_back(_debugData.masterClockSeconds >> 16);
data.push_back(_debugData.masterClockSeconds >> 8);
data.push_back(_debugData.masterClockSeconds);
data.push_back(_debugType); // format type in this packet

// current field count
data.push_back(_debugData.masterClockFields);
// all types start with the current master clock
data.push_back(_masterClockSeconds >> 24);
data.push_back(_masterClockSeconds >> 16);
data.push_back(_masterClockSeconds >> 8);
data.push_back(_masterClockSeconds);
data.push_back(_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);
// 6 of 26 bytes used

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] / 50 > 255)
data.push_back(255); // clamp to 255 seconds
else
data.push_back(magDurations[i] / 50); // truncate to whole seconds
switch(_debugType)
{
default:
case NONE: // this should never get sent
{
break;
}
case FORMAT1: // packet type 1, system time
{
_debugType = FORMAT2; // cycle to format 2 on next packet

data.push_back(VBIT2_DEBUG_VERSION); // Debug stream format version

// clock flags
data.push_back(_clockFlags);
_clockFlags = 0; // clear flags

// current system clock
data.push_back(_systemClock >> 24);
data.push_back(_systemClock >> 16);
data.push_back(_systemClock >> 8);
data.push_back(_systemClock);

// vbit2 startup timestamp
data.push_back(_startupTime >> 24);
data.push_back(_startupTime >> 16);
data.push_back(_startupTime >> 8);
data.push_back(_startupTime);

// 16 of 26 bytes used

break;
}
case FORMAT2: // packet type 2, magazine data
{
_debugType = FORMAT1; // cycle to format 1 on next packet

// magazine flags
data.push_back(_magFlags);
_magFlags = 0; // clear flags

for (mag=0; mag<8; mag++){
data.push_back(_magDurations[mag]);
}
// these 8 bytes may result in a dummy byte!

for (mag=0; mag<8; mag++){
data.push_back(_magSizes[mag]);
}
// these 8 bytes may result in a dummy byte!

// 22 of 26 bytes used

break;
}
}

p->IDLA(_datachannel, Packet::IDLA_DL, 6, _servicePacketAddress, 0, _debugPacketCI++, data);
data.insert(data.end(), 26 - data.size(), 0); // pad payload data to 26 bytes long (leave three bytes available in packet for dummies)

// generate format A datacast packet with explicit data length, and implicit continuity indicator
p->IDLA(_datachannel, Packet::IDLA_DL, 6, _servicePacketAddress, 0, _debugPacketCI++, data);

return p;
}
Expand All @@ -61,23 +117,55 @@ bool PacketDebug::IsReady(bool force)
(void)force; // silence error about unused parameter
bool result=false;

if (_debug->GetDebugLevel()) // TODO have specific configuration for datacast debugging packet
if (GetEvent(EVENT_FIELD))
{
if (GetEvent(EVENT_FIELD))
ClearEvent(EVENT_FIELD);

if (_debugType > FORMAT1) // we are in the middle of sending debug data already
{
ClearEvent(EVENT_FIELD);

result = true;
}
else
{
// update magazine data
int mag;
std::array<int, 8> magDurations = _debug->GetMagCycleDurations(); // get magazine durations in number of fields
for (mag=0; mag<8; mag++){
if(magDurations[mag] < 0 || magDurations[mag] / 50 > 255)
magDurations[mag] = 255; // clamp to 255 seconds
else
magDurations[mag] = magDurations[mag] / 50; // truncate to whole seconds

if (_magDurations[mag] != magDurations[mag])
{
_magFlags |= MFLAGDURATION; // mag durations have changed!
_magDurations[mag] = magDurations[mag]; // update our internal variable
}
}

std::array<int, 8> magSizes = _debug->GetMagSizes(); // get number of pages in each magazine
for (mag=0; mag<8; mag++){
if (_magSizes[mag] != magSizes[mag])
{
_magFlags |= MFLAGPAGES; // mag sizes have changed!
_magSizes[mag] = magSizes[mag]; // update our internal variable
}
}

if (_clockFlags || _magFlags || force) // generate packets if any of the content has changed (or we are forcing output to use this as datacast filler)
result = true;
}
}

return result;
}

void PacketDebug::TimeAndField(MasterClock::timeStruct masterClock, time_t systemClock)
void PacketDebug::TimeAndField(MasterClock::timeStruct masterClock, time_t systemClock, bool resync)
{
// update the clocks in _debugData struct - called once per field by Service::_updateEvents()
_debugData.masterClockSeconds = masterClock.seconds;
_debugData.masterClockFields = masterClock.fields;
_debugData.systemClock = systemClock;
_masterClockSeconds = masterClock.seconds;
_masterClockFields = masterClock.fields;
_systemClock = systemClock;
if (resync)
_clockFlags |= CFLAGRESYNC; // set flag
}
28 changes: 17 additions & 11 deletions packetDebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include "configure.h"
#include "debug.h"

#define VBIT2_DEBUG_VERSION 0x01 // Debug API version
#define VBIT2_DEBUG_VERSION 0x01 // Debug packet version

namespace vbit
{
Expand All @@ -23,7 +23,7 @@ namespace vbit
// overrides
Packet* GetPacket(Packet* p) override;

void TimeAndField(MasterClock::timeStruct masterClock, time_t systemClock);
void TimeAndField(MasterClock::timeStruct masterClock, time_t systemClock, bool resync);

bool IsReady(bool force=false);

Expand All @@ -37,16 +37,22 @@ namespace vbit
uint32_t _servicePacketAddress;
uint8_t _debugPacketCI; // continuity indicator for databroadcast stream

struct debugData
{
char header[4] = {'V','B','I','T'};
uint8_t ver = VBIT2_DEBUG_VERSION;
time_t masterClockSeconds = 0;
uint8_t masterClockFields = 0;
time_t systemClock = 0;
};
const time_t _startupTime;
time_t _masterClockSeconds;
uint8_t _masterClockFields;
time_t _systemClock;

struct debugData _debugData;
std::array<uint8_t, 8> _magDurations;
std::array<uint8_t, 8> _magSizes;

enum DebugTypes {NONE, FORMAT1, FORMAT2};
DebugTypes _debugType;

enum ClockFlags {CFLAGRESYNC = 1};
uint8_t _clockFlags;

enum MagFlags {MFLAGDURATION=1, MFLAGPAGES=2};
uint8_t _magFlags;
};
}

Expand Down
7 changes: 7 additions & 0 deletions pagelist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,19 @@ int PageList::ReadDirectory(std::string filepath)
}
closedir(dp);

for (int mag=0;mag<8;mag++)
{
_debug->SetMagazineSize(mag, _pageList[mag].size());
}

return 0;
}

void PageList::AddPage(TTXPageStream* page)
{
int mag=(page->GetPageNumber() >> 16) & 0x7;
_pageList[mag].push_back(*page);
_debug->SetMagazineSize(mag, _pageList[mag].size());
}

void PageList::CheckForPacket29OrCustomHeader(TTXPageStream* page)
Expand Down Expand Up @@ -420,6 +426,7 @@ void PageList::DeleteOldPages()

// page has been removed from lists
_pageList[mag].remove(*p--);
_debug->SetMagazineSize(mag, _pageList[mag].size());

if (_iterMag == mag)
{
Expand Down
21 changes: 10 additions & 11 deletions service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,11 @@ int Service::run()
// Send ONLY one packet per loop
_updateEvents();

if (_packetDebug->IsReady()) // Special case for debug. Ensures it can have the first line of field
// Special case for debug. Ensures it can have the first line of field
if (_packetDebug->IsReady(_debug->GetDebugLevel() >= Debug::LogLevels::logDEBUG)) // force if log level DEBUG
{
if (_packetDebug->GetPacket(pkt) != nullptr)
{
_packetOutput(pkt);
}
else
{
_packetOutput(filler);
}
_packetDebug->GetPacket(pkt);
_packetOutput(pkt);
}
else if (_subtitle->IsReady()) // Special case for subtitles. Subtitles always go if there is one waiting
{
Expand Down Expand Up @@ -153,7 +148,7 @@ int Service::run()
return 99; // can't return but this keeps the compiler happy
} // worker

#define FORWARDSBUFFER 1
#define FORWARDSBUFFER 1 // how far into the future vbit2 should run before rate limiting in seconds

void Service::_updateEvents()
{
Expand All @@ -180,7 +175,7 @@ void Service::_updateEvents()

masterClock.fields = _fieldCounter;

_packetDebug->TimeAndField(masterClock, now); // update the clocks in debugPacket.
_packetDebug->TimeAndField(masterClock, now, false); // update the clocks in debugPacket.

if (_fieldCounter == 0)
{
Expand All @@ -193,6 +188,8 @@ void Service::_updateEvents()

for (int i=0;i<8;i++)
_magList[i]->InvalidateCycleTimestamp(); // reset magazine cycle duration calculations

_packetDebug->TimeAndField(masterClock, now, true); // update the clocks in debugPacket.
}

if (masterClock.seconds%15==0) // TODO: how often do we want to trigger sending special packets?
Expand All @@ -205,6 +202,8 @@ void Service::_updateEvents()
}
}



mc->SetMasterClock(masterClock); // update the master clock singleton

// New field, so set the FIELD event in all the sources.
Expand Down

0 comments on commit 9b8ca9a

Please sign in to comment.