Merge pull request #2 from Quency-D/dev

Merging changes
This commit is contained in:
Quency-D 2025-08-28 15:36:59 +08:00 committed by GitHub
commit bb63f8165d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
112 changed files with 1873 additions and 271 deletions

View file

@ -21,9 +21,15 @@ public:
virtual void setColor(Color c) = 0;
virtual void setCursor(int x, int y) = 0;
virtual void print(const char* str) = 0;
virtual void printWordWrap(const char* str, int max_width) { print(str); } // fallback to basic print() if no override
virtual void fillRect(int x, int y, int w, int h) = 0;
virtual void drawRect(int x, int y, int w, int h) = 0;
virtual void drawXbm(int x, int y, const uint8_t* bits, int w, int h) = 0;
virtual uint16_t getTextWidth(const char* str) = 0;
virtual void drawTextCentered(int mid_x, int y, const char* str) { // helper method (override to optimise)
int w = getTextWidth(str);
setCursor(mid_x - w/2, y);
print(str);
}
virtual void endFrame() = 0;
};

View file

@ -29,8 +29,8 @@ void GxEPDDisplay::turnOn() {
if (!_init) begin();
#if DISP_BACKLIGHT
digitalWrite(DISP_BACKLIGHT, HIGH);
_isOn = true;
#endif
_isOn = true;
}
void GxEPDDisplay::turnOff() {
@ -47,6 +47,7 @@ void GxEPDDisplay::clear() {
void GxEPDDisplay::startFrame(Color bkg) {
display.fillScreen(GxEPD_WHITE);
display.setTextColor(_curr_color = GxEPD_BLACK);
}
void GxEPDDisplay::setTextSize(int sz) {
@ -67,7 +68,12 @@ void GxEPDDisplay::setTextSize(int sz) {
}
void GxEPDDisplay::setColor(Color c) {
display.setTextColor(GxEPD_BLACK);
// colours need to be inverted for epaper displays
if (c == DARK) {
display.setTextColor(_curr_color = GxEPD_WHITE);
} else {
display.setTextColor(_curr_color = GxEPD_BLACK);
}
}
void GxEPDDisplay::setCursor(int x, int y) {
@ -79,11 +85,11 @@ void GxEPDDisplay::print(const char* str) {
}
void GxEPDDisplay::fillRect(int x, int y, int w, int h) {
display.fillRect(x*SCALE_X, y*SCALE_Y, w*SCALE_X, h*SCALE_Y, GxEPD_BLACK);
display.fillRect(x*SCALE_X, y*SCALE_Y, w*SCALE_X, h*SCALE_Y, _curr_color);
}
void GxEPDDisplay::drawRect(int x, int y, int w, int h) {
display.drawRect(x*SCALE_X, y*SCALE_Y, w*SCALE_X, h*SCALE_Y, GxEPD_BLACK);
display.drawRect(x*SCALE_X, y*SCALE_Y, w*SCALE_X, h*SCALE_Y, _curr_color);
}
void GxEPDDisplay::drawXbm(int x, int y, const uint8_t* bits, int w, int h) {
@ -116,7 +122,7 @@ void GxEPDDisplay::drawXbm(int x, int y, const uint8_t* bits, int w, int h) {
// If the bit is set, draw a block of pixels
if (bitSet) {
// Draw the block as a filled rectangle
display.fillRect(x1, y1, block_w, block_h, GxEPD_BLACK);
display.fillRect(x1, y1, block_w, block_h, _curr_color);
}
}
}
@ -126,7 +132,7 @@ uint16_t GxEPDDisplay::getTextWidth(const char* str) {
int16_t x1, y1;
uint16_t w, h;
display.getTextBounds(str, 0, 0, &x1, &y1, &w, &h);
return w / SCALE_X;
return ceil((w + 1) / SCALE_X);
}
void GxEPDDisplay::endFrame() {

View file

@ -28,6 +28,7 @@ class GxEPDDisplay : public DisplayDriver {
GxEPD2_BW<GxEPD2_150_BN, 200> display;
bool _init = false;
bool _isOn = false;
uint16_t _curr_color;
public:
// there is a margin in y...

View file

@ -0,0 +1,75 @@
#include "MomentaryButton.h"
MomentaryButton::MomentaryButton(int8_t pin, int long_press_millis, bool reverse, bool pulldownup) {
_pin = pin;
_reverse = reverse;
_pull = pulldownup;
down_at = 0;
prev = _reverse ? HIGH : LOW;
cancel = 0;
_long_millis = long_press_millis;
}
void MomentaryButton::begin() {
if (_pin >= 0) {
pinMode(_pin, _pull ? (_reverse ? INPUT_PULLUP : INPUT_PULLDOWN) : INPUT);
}
}
bool MomentaryButton::isPressed() const {
return isPressed(digitalRead(_pin));
}
void MomentaryButton::cancelClick() {
cancel = 1;
}
bool MomentaryButton::isPressed(int level) const {
if (_reverse) {
return level == LOW;
} else {
return level != LOW;
}
}
int MomentaryButton::check(bool repeat_click) {
if (_pin < 0) return BUTTON_EVENT_NONE;
int event = BUTTON_EVENT_NONE;
int btn = digitalRead(_pin);
if (btn != prev) {
if (isPressed(btn)) {
down_at = millis();
} else {
// button UP
if (_long_millis > 0) {
if (down_at > 0 && (unsigned long)(millis() - down_at) < _long_millis) { // only a CLICK if still within the long_press millis
event = BUTTON_EVENT_CLICK;
}
} else {
event = BUTTON_EVENT_CLICK; // any UP results in CLICK event when NOT using long_press feature
}
if (event == BUTTON_EVENT_CLICK && cancel) {
event = BUTTON_EVENT_NONE;
}
down_at = 0;
}
prev = btn;
}
if (!isPressed(btn) && cancel) { // always clear the pending 'cancel' once button is back in UP state
cancel = 0;
}
if (_long_millis > 0 && down_at > 0 && (unsigned long)(millis() - down_at) >= _long_millis) {
event = BUTTON_EVENT_LONG_PRESS;
down_at = 0;
}
if (down_at > 0 && repeat_click) {
unsigned long diff = (unsigned long)(millis() - down_at);
if (diff >= 700) {
event = BUTTON_EVENT_CLICK; // wait 700 millis before repeating the click events
}
}
return event;
}

View file

@ -0,0 +1,25 @@
#pragma once
#include <Arduino.h>
#define BUTTON_EVENT_NONE 0
#define BUTTON_EVENT_CLICK 1
#define BUTTON_EVENT_LONG_PRESS 2
class MomentaryButton {
int8_t _pin;
int8_t prev, cancel;
bool _reverse, _pull;
int _long_millis;
unsigned long down_at;
bool isPressed(int level) const;
public:
MomentaryButton(int8_t pin, int long_press_mills=0, bool reverse=false, bool pulldownup=false);
void begin();
int check(bool repeat_click=false); // returns one of BUTTON_EVENT_*
void cancelClick(); // suppress next BUTTON_EVENT_CLICK (if already in DOWN state)
uint8_t getPin() { return _pin; }
bool isPressed() const;
};

View file

@ -73,6 +73,9 @@ void ST7789Display::clear() {
void ST7789Display::startFrame(Color bkg) {
display.clear();
_color = ST77XX_WHITE;
display.setRGB(_color);
display.setFont(ArialMT_Plain_16);
}
void ST7789Display::setTextSize(int sz) {
@ -92,7 +95,9 @@ void ST7789Display::setColor(Color c) {
switch (c) {
case DisplayDriver::DARK :
_color = ST77XX_BLACK;
display.setColor(OLEDDISPLAY_COLOR::BLACK);
break;
#if 0
case DisplayDriver::LIGHT :
_color = ST77XX_WHITE;
break;
@ -111,8 +116,10 @@ void ST7789Display::setColor(Color c) {
case DisplayDriver::ORANGE :
_color = ST77XX_ORANGE;
break;
#endif
default:
_color = ST77XX_WHITE;
display.setColor(OLEDDISPLAY_COLOR::WHITE);
break;
}
display.setRGB(_color);
@ -127,6 +134,10 @@ void ST7789Display::print(const char* str) {
display.drawString(_x, _y, str);
}
void ST7789Display::printWordWrap(const char* str, int max_width) {
display.drawStringMaxWidth(_x, _y, max_width*SCALE_X, str);
}
void ST7789Display::fillRect(int x, int y, int w, int h) {
display.fillRect(x*SCALE_X + X_OFFSET, y*SCALE_Y + Y_OFFSET, w*SCALE_X, h*SCALE_Y);
}

View file

@ -4,7 +4,7 @@
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <ST7789Spi.h>
#include "ST7789Spi.h"
class ST7789Display : public DisplayDriver {
ST7789Spi display;
@ -30,6 +30,7 @@ public:
void setColor(Color c) override;
void setCursor(int x, int y) override;
void print(const char* str) override;
void printWordWrap(const char* str, int max_width) override;
void fillRect(int x, int y, int w, int h) override;
void drawRect(int x, int y, int w, int h) override;
void drawXbm(int x, int y, const uint8_t* bits, int w, int h) override;

21
src/helpers/ui/UIScreen.h Normal file
View file

@ -0,0 +1,21 @@
#pragma once
#include "DisplayDriver.h"
#define KEY_LEFT 0xB4
#define KEY_UP 0xB5
#define KEY_DOWN 0xB6
#define KEY_RIGHT 0xB7
#define KEY_SELECT 10
#define KEY_ENTER 13
#define KEY_BACK 27 // Esc
class UIScreen {
protected:
UIScreen() { }
public:
virtual int render(DisplayDriver& display) =0; // return value is number of millis until next render
virtual bool handleInput(char c) { return false; }
virtual void poll() { }
};