Public Access
- Text elements can scroll in a window at a set speed; clock, countdown and stopwatch can show seconds. Moving pages are sent as instant frames (new Nano command D1) and paced by the estimated flip time. - Countdown to a date and time (smart, days, days + time, with seconds), stopwatch (web UI, HA switch and reset button), image element (fixed or by Home Assistant state), multiplier for HA values, degree sign (char 127) in all fonts and the font converter. - Page format version 2; version 1 pages are converted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
138 lines
4.9 KiB
C++
138 lines
4.9 KiB
C++
#ifndef BROSE9323_H
|
|
#define BROSE9323_H
|
|
|
|
#include <Adafruit_GFX.h>
|
|
|
|
#include "dot_sequence.h"
|
|
|
|
//#define FLIPDOT_PLCC_ADAPTER
|
|
// ESPSERIAL is set per target via build_flags in platformio.ini (-D ESPSERIAL for the ESP32)
|
|
|
|
class BROSE9323 : public Adafruit_GFX
|
|
{
|
|
private:
|
|
uint16_t _flip_time;
|
|
uint16_t _flip_gap = 0; // pause after each pulse in us, lets the coil supply recover
|
|
uint8_t _pulses = 1; // pulses for each dot that changed
|
|
uint8_t _effect = EFFECT_INSTANT;
|
|
uint16_t _effect_time = 1500; // ms, how long an effect takes
|
|
uint8_t _effect_flags = 0; // EFFECT_FLAG_...
|
|
const uint8_t _panel_width;
|
|
const uint8_t _buffer_width;
|
|
const uint16_t _buffer_size;
|
|
uint8_t *_old_buffer = NULL;
|
|
uint8_t *_new_buffer = NULL;
|
|
bool _direct_mode = false;
|
|
|
|
#ifdef ESPSERIAL
|
|
Stream *stream;
|
|
#else
|
|
uint8_t _active_panel = 255;
|
|
uint8_t _active_col = 255;
|
|
uint8_t _active_row = 255;
|
|
bool _active_data;
|
|
// After boot the physical dot state is unknown, so the first display() redraws everything
|
|
bool _force_next = true;
|
|
|
|
// A running effect (display() with an effect other than EFFECT_INSTANT)
|
|
DotSequence _sequence;
|
|
bool _animating = false;
|
|
uint8_t _running_effect = EFFECT_INSTANT; // _effect, or the one chosen for EFFECT_RANDOM
|
|
uint8_t _phase = 0; // EFFECT_FLAP: 0 = to yellow, 1 = the new image
|
|
uint8_t _push_shift = 0; // EFFECT_PUSH: column shift 1..width
|
|
uint16_t _push_pos = 0; // EFFECT_PUSH: dot within the shift
|
|
bool _animate_all = false; // flip every dot, not only the changed ones
|
|
bool _drawing = false; // the buffer changed since the last display(): pause
|
|
uint32_t _step_time = 0; // us per step
|
|
uint32_t _next_step = 0; // micros() of the next step
|
|
|
|
#ifndef FLIPDOT_PLCC_ADAPTER
|
|
const uint8_t ENABLE = 7,
|
|
ADDR_0 = 3,
|
|
ADDR_1 = 5,
|
|
ADDR_2 = 6,
|
|
COL_DATA = 4,
|
|
COL_0 = 8,
|
|
COL_1 = 10,
|
|
COL_2 = 9,
|
|
COL_3 = 11,
|
|
COL_4 = 12,
|
|
ROW_0 = A3,
|
|
ROW_1 = A4,
|
|
ROW_2 = A2,
|
|
ROW_3 = A0,
|
|
ROW_4 = A1,
|
|
ROW_RESET = 13,
|
|
ROW_SET = A5;
|
|
#else
|
|
const uint8_t RELAY = 2,
|
|
ENABLE = 3,
|
|
ADDR_0 = 7,
|
|
ADDR_1 = 6,
|
|
ADDR_2 = 5,
|
|
COL_DATA = 4,
|
|
COL_0 = 12,
|
|
COL_1 = 11,
|
|
COL_2 = 10,
|
|
COL_3 = 9,
|
|
COL_4 = 8,
|
|
ROW_0 = 13, //1 A1 CHECK
|
|
ROW_1 = A0, //2 A2
|
|
ROW_2 = A1, //4 A3
|
|
ROW_3 = A2, //8 13 CHECK
|
|
ROW_4 = A3, //F A0
|
|
ROW_RESET = A4,
|
|
ROW_SET = A5;
|
|
#endif
|
|
|
|
void _selectColumn(uint8_t);
|
|
void _selectPanel(uint8_t);
|
|
void _selectRow(uint8_t);
|
|
void _setData(bool);
|
|
void _strobe(void);
|
|
bool _shown(uint8_t x, uint8_t y) const;
|
|
bool _changed(uint8_t x, uint8_t y) const;
|
|
bool _wanted(uint8_t x, uint8_t y) const;
|
|
void _flipTo(uint8_t x, uint8_t y, bool on, uint8_t pulses);
|
|
void _flipDot(uint8_t x, uint8_t y, uint8_t pulses);
|
|
bool _pushDot(void);
|
|
void _drawAll(bool all);
|
|
void _startEffect(bool all);
|
|
#endif
|
|
public:
|
|
BROSE9323(uint8_t, uint8_t, uint8_t, uint16_t ft = 280);
|
|
#ifdef ESPSERIAL
|
|
void begin(Stream * = &Serial);
|
|
#endif
|
|
void begin(void);
|
|
// Shows the buffer: the changed dots, all with force. instant: without the refresh
|
|
// effect (frames of moving content, e.g. scrolling text). ESP32: sends D or D1.
|
|
void display(bool force = false, bool instant = false);
|
|
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
|
void fillScreen(uint16_t);
|
|
void setDirect(bool);
|
|
void setTiming(uint16_t);
|
|
// Pause after each flip pulse in us
|
|
void setGap(uint16_t);
|
|
// Pulses for each changed dot (a second pulse catches dots that didn't flip). Full
|
|
// redraws use one pulse per dot.
|
|
void setPulses(uint8_t);
|
|
// How display() shows a new frame (RefreshEffect), how long it takes in ms (pushing
|
|
// can take longer: it flips many dots per step) and EFFECT_FLAG_... flags.
|
|
// Effects run in steps from update(), so call that often (every loop).
|
|
void setEffect(uint8_t effect, uint16_t time_ms, uint8_t flags = 0);
|
|
#ifndef ESPSERIAL
|
|
// Runs the next steps of an effect. Returns busy().
|
|
bool update(void);
|
|
// An effect is running (paused while a new frame is being drawn into the buffer)
|
|
bool busy(void) const;
|
|
#endif
|
|
#ifndef ESPSERIAL
|
|
void printBuffer(void);
|
|
#endif
|
|
size_t print(const char *ifsh);
|
|
// State of a dot as of the last display() call (ESP32: shadow copy for the web UI)
|
|
bool shownPixel(int16_t x, int16_t y) const;
|
|
};
|
|
#endif //BROSE9323_H
|