#include "logic/frame_check.h" #include #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; }