Public Access
Fix shifted pictures: non-blocking Nano drawing, frame check, refresh settings
The Nano's periodic full redraw blocked for ~0.8 s. A frame that arrived meanwhile overflowed its 64-byte serial buffer; lost bytes in a bitmap shift the rest of the image (picture moved up), and diff frames never repaired it. - Nano: all drawing (frames, effects, the dot refresh) runs from update() in ~1 ms slices; the refresh pauses while a frame is received or shown - New commands: C (reply with the image checksum) and I (refresh minutes, EEPROM) - ESP32: NanoMonitor asks for the checksum after frames and sends the whole image again on a mismatch, missing answer or Nano restart; counts ERR replies. Periodic whole-image resync. - Settings: "Dot refresh" and "Image resync" intervals (settings v5, v4 records are migrated) - System tab: loop timing, free memory, frame check counts - test_driver: the real driver against a simulated panel Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
58a7cb03c2
commit
090c2bf8ae
45 files changed
+1265
-157
No files matched your search
+35
-15
@@ -71,7 +71,6 @@ void CommandParser::feed(char c)
|
||||
return;
|
||||
}
|
||||
_line[_line_len++] = c;
|
||||
_frame_ended = false;
|
||||
|
||||
// Bitmap header complete: draw the pixel data as it arrives
|
||||
if (_line_len == BITMAP_HEADER_LEN && isBitmapCommand(_line[0]))
|
||||
@@ -82,11 +81,6 @@ void CommandParser::feed(char c)
|
||||
}
|
||||
}
|
||||
|
||||
bool CommandParser::frameEnded() const
|
||||
{
|
||||
return _frame_ended;
|
||||
}
|
||||
|
||||
// Run one complete command line (without the '\n')
|
||||
void CommandParser::_runLine()
|
||||
{
|
||||
@@ -102,6 +96,10 @@ void CommandParser::_runLine()
|
||||
// Complete bitmap headers are handled in feed()
|
||||
_error(F("Incomplete bitmap header"));
|
||||
break;
|
||||
case 'c':
|
||||
case 'C':
|
||||
_checksum();
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
_effect();
|
||||
@@ -110,21 +108,18 @@ void CommandParser::_runLine()
|
||||
case 'G':
|
||||
_gap();
|
||||
break;
|
||||
case 'i':
|
||||
case 'I':
|
||||
_refreshInterval();
|
||||
break;
|
||||
case 'n':
|
||||
case 'N':
|
||||
_pulses();
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
// D1: a frame of moving content, shown without the effect. More frames follow
|
||||
// soon, so the periodic full redraw waits until the serial line is idle.
|
||||
if (_line[1] == '1')
|
||||
_display.display(false, true);
|
||||
else
|
||||
{
|
||||
_display.display();
|
||||
_frame_ended = true;
|
||||
}
|
||||
// D1: a frame of moving content, shown without the effect
|
||||
_display.display(false, _line[1] == '1');
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
@@ -320,3 +315,28 @@ void CommandParser::_effect()
|
||||
_display.setEffect(effect, t, flags);
|
||||
saveEffect(effect, t, flags);
|
||||
}
|
||||
|
||||
// C: replies "C xxxx", the bufferCrc() of the image received so far as 4 hex digits. The
|
||||
// ESP32 sends it after a frame and compares it with what it sent.
|
||||
void CommandParser::_checksum()
|
||||
{
|
||||
uint16_t crc = _display.crc();
|
||||
char text[7] = "C ";
|
||||
for (uint8_t i = 0; i < 4; i++)
|
||||
text[2 + i] = "0123456789ABCDEF"[(crc >> (12 - 4 * i)) & 0xF];
|
||||
text[6] = '\0';
|
||||
_reply.println(text);
|
||||
}
|
||||
|
||||
// Immm (mmm = decimal minutes between full redraws, 0 = never, up to 1440), stored in EEPROM
|
||||
void CommandParser::_refreshInterval()
|
||||
{
|
||||
long m = atol(_line + 1);
|
||||
if (_line_len < 2 || m < 0 || m > REFRESH_MINUTES_MAX)
|
||||
{
|
||||
_error(F("Refresh interval out of range (0-1440 min)"));
|
||||
return;
|
||||
}
|
||||
_refresh_minutes = m;
|
||||
saveRefreshMinutes(m);
|
||||
}
|
||||
Reference in new issue
Block a user