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
@@ -0,0 +1,112 @@
|
||||
// Just enough Arduino and Adafruit GFX to run the real BROSE9323 driver (Nano build) on
|
||||
// the PC, with a simulated panel: test/test_driver. The panel decodes the pin levels at
|
||||
// each strobe (ENABLE low) into the dot that flips, like the Brose panel electronics.
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#define A0 14
|
||||
#define A1 15
|
||||
#define A2 16
|
||||
#define A3 17
|
||||
#define A4 18
|
||||
#define A5 19
|
||||
#define OUTPUT 1
|
||||
|
||||
// Every micros() call takes a microsecond, so loops that wait for the time end
|
||||
inline uint32_t fake_micros = 0;
|
||||
inline uint32_t micros() { return ++fake_micros; }
|
||||
inline uint32_t millis() { return fake_micros / 1000; }
|
||||
inline void delayMicroseconds(unsigned int us) { fake_micros += us; }
|
||||
inline void pinMode(uint8_t, uint8_t) {}
|
||||
|
||||
struct FakePanel
|
||||
{
|
||||
static const int W = 84, H = 19, PANEL_W = 28;
|
||||
bool dot[W][H] = {};
|
||||
int flips[W][H] = {}; // strobes per dot
|
||||
int strobes = 0;
|
||||
bool pins[20] = {};
|
||||
|
||||
void clearCounts()
|
||||
{
|
||||
memset(flips, 0, sizeof(flips));
|
||||
strobes = 0;
|
||||
}
|
||||
void write(uint8_t pin, bool level)
|
||||
{
|
||||
pins[pin] = level;
|
||||
if (pin == 7 && !level) // ENABLE low: flip the addressed dot
|
||||
strobe();
|
||||
}
|
||||
void strobe()
|
||||
{
|
||||
int panel = pins[3] | pins[5] << 1 | pins[6] << 2;
|
||||
int col_code = pins[8] | pins[10] << 1 | pins[9] << 2 | pins[11] << 3 | pins[12] << 4;
|
||||
int row_code = pins[A3] | pins[A4] << 1 | pins[A2] << 2 | pins[A0] << 3 | pins[A1] << 4;
|
||||
int col = -1, row = -1;
|
||||
for (int c = 0; c < PANEL_W; c++)
|
||||
if (c + 1 + c / 7 == col_code)
|
||||
col = c;
|
||||
for (int r = 0; r < H; r++)
|
||||
if (r + r / 7 == row_code)
|
||||
row = r;
|
||||
if (col < 0 || row < 0 || panel > 2)
|
||||
{
|
||||
fprintf(stderr, "bad address: panel %d col code %d row code %d\n", panel, col_code, row_code);
|
||||
abort();
|
||||
}
|
||||
int x = panel * PANEL_W + col;
|
||||
dot[x][row] = !pins[4]; // COL_DATA low sets the dot (yellow)
|
||||
flips[x][row]++;
|
||||
strobes++;
|
||||
}
|
||||
};
|
||||
|
||||
inline FakePanel panel;
|
||||
inline void digitalWrite(uint8_t pin, int level) { panel.write(pin, level != 0); }
|
||||
|
||||
struct FakeSerialOut
|
||||
{
|
||||
void write(char) {}
|
||||
void println() {}
|
||||
};
|
||||
inline FakeSerialOut Serial;
|
||||
|
||||
// Only what BROSE9323::print() uses
|
||||
class String
|
||||
{
|
||||
public:
|
||||
String(const char *s) : _s(s) {}
|
||||
void replace(const char *from, const char *to)
|
||||
{
|
||||
size_t pos = 0, n = strlen(from);
|
||||
while ((pos = _s.find(from, pos)) != std::string::npos)
|
||||
{
|
||||
_s.replace(pos, n, to);
|
||||
pos += strlen(to);
|
||||
}
|
||||
}
|
||||
const char *c_str() const { return _s.c_str(); }
|
||||
|
||||
private:
|
||||
std::string _s;
|
||||
};
|
||||
|
||||
class Adafruit_GFX
|
||||
{
|
||||
public:
|
||||
Adafruit_GFX(int16_t w, int16_t h) : _width(w), _height(h) {}
|
||||
virtual ~Adafruit_GFX() {}
|
||||
virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0;
|
||||
int16_t width() const { return _width; }
|
||||
int16_t height() const { return _height; }
|
||||
size_t print(const char *s) { return strlen(s); }
|
||||
|
||||
protected:
|
||||
int16_t _width, _height;
|
||||
};
|
||||
Reference in new issue
Block a user