Files
Flipdot-display/src/esp32/logic/frame_check.cpp
T

120 lines
2.5 KiB
C++
Raw Normal View History

#include "logic/frame_check.h"
#include <string.h>
#include "config.h"
static int hexDigit(char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
return -1;
}
void FrameCheck::reset(uint32_t now)
{
_pending = false;
_checked_any = false;
_replied = false;
_problem = false;
// Switching on sends the whole image anyway
_last_resync = now;
}
bool FrameCheck::due(uint32_t frames_sent, uint32_t now) const
{
// A repair is coming anyway: no need to count the same problem again
if (_pending || _problem)
return false;
if (!_checked_any)
return true;
return frames_sent != _checked_frames && now - _last_check >= FRAME_CHECK_INTERVAL;
}
void FrameCheck::sent(uint16_t expected, uint32_t frames_sent, uint32_t now)
{
_pending = true;
_expected = expected;
_sent_at = now;
_checked_any = true;
_checked_frames = frames_sent;
_last_check = now;
}
void FrameCheck::line(const char *text, uint32_t now)
{
(void)now;
size_t len = strlen(text);
while (len && (text[len - 1] == '\r' || text[len - 1] == ' '))
len--;
if (len == 6 && text[0] == 'C' && text[1] == ' ')
{
int value = 0;
for (int i = 2; i < 6; i++)
{
int d = hexDigit(text[i]);
if (d < 0)
return;
value = value << 4 | d;
}
_replied = true;
if (!_pending)
return; // late answer to a check that already timed out
_pending = false;
if (value == _expected)
_stats.checks++;
else
{
_stats.mismatches++;
_problem = true;
}
return;
}
if (strncmp(text, "ERR", 3) == 0)
{
_replied = true;
_stats.errors++;
size_t n = len < sizeof(_stats.last_error) - 1 ? len : sizeof(_stats.last_error) - 1;
memcpy(_stats.last_error, text, n);
_stats.last_error[n] = '\0';
return;
}
if (len >= 5 && strncmp(text, "READY", 5) == 0)
{
// The Nano restarted while it was on: its image is gone
_replied = true;
_stats.restarts++;
_pending = false;
_problem = true;
}
}
bool FrameCheck::resyncNow(uint32_t now, uint32_t resync_ms)
{
if (_pending && now - _sent_at >= FRAME_CHECK_TIMEOUT)
{
_pending = false;
_stats.no_reply++;
// Only when answers can arrive at all (old Nano firmware, TX not wired: never)
if (_replied)
_problem = true;
}
if (_problem && now - _last_resync >= FRAME_REPAIR_MIN_GAP)
{
_problem = false;
_stats.repairs++;
_last_resync = now;
return true;
}
if (resync_ms && now - _last_resync >= resync_ms)
{
_last_resync = now;
return true;
}
return false;
}