Files

112 lines
2.8 KiB
C++
Raw Permalink Normal View History

// 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;
};