#pragma once #include // Checks that the Nano shows what was sent. The Nano has no acknowledgement and drops // bytes when its serial buffer overflows; a lost byte in a bitmap shifts the rest of the // image (the dots after it land too early). After a frame the ESP32 asks for the checksum // of the Nano's image (C command, bufferCrc() in lib/BROSE9323) and compares it with its // own copy. A wrong checksum, a missing answer or a restarted Nano (READY) makes it send // the whole image again (repair). Besides that the whole image is sent again every // resync interval, which also fixes what the check can't see. // // Pure logic (tested in test/test_esp32); nano_link/nano_monitor does the serial part. struct FrameCheckStats { uint32_t checks = 0; // answers that matched uint32_t mismatches = 0; // answers that didn't uint32_t no_reply = 0; // checks without an answer in FRAME_CHECK_TIMEOUT uint32_t errors = 0; // ERR: lines from the Nano uint32_t restarts = 0; // READY while it was on: the Nano restarted (power dip?) uint32_t repairs = 0; // whole image sent again because of one of the above char last_error[48] = ""; }; class FrameCheck { public: // The Nano was switched on or off: forget the check in progress void reset(uint32_t now); // A check (C) should be sent now: a frame was sent since the last one (frames_sent // changed), none is waiting for its answer and the last one is FRAME_CHECK_INTERVAL ago bool due(uint32_t frames_sent, uint32_t now) const; // The C was sent; expected: the checksum of the ESP32's copy void sent(uint16_t expected, uint32_t frames_sent, uint32_t now); // One line from the Nano (without the '\n') void line(const char *text, uint32_t now); // Call each loop(). True: send the whole image now (repair, or every resync_ms; 0 = no // periodic resync) bool resyncNow(uint32_t now, uint32_t resync_ms); const FrameCheckStats &stats() const { return _stats; } private: FrameCheckStats _stats; bool _pending = false; uint16_t _expected = 0; uint32_t _sent_at = 0; bool _checked_any = false; // since reset() uint32_t _checked_frames = 0; uint32_t _last_check = 0; bool _replied = false; // the Nano answered since reset(): its TX is wired bool _problem = false; // repair at the next chance uint32_t _last_resync = 0; };