From b941958b52616d235d73247dfb54706f8f46a9a7 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Sat, 23 May 2026 01:15:16 +1000 Subject: [PATCH] * trying to get T-Impulse ui-tiny happenin' --- examples/companion_radio/ui-tiny/UITask.cpp | 2 +- src/helpers/ui/SSD1315Display.cpp | 122 ++++++++++++++++++ src/helpers/ui/SSD1315Display.h | 48 +++++++ .../TImpulsePlusBoard.cpp | 4 +- variants/lilygo_t_impulse_plus/platformio.ini | 20 +-- variants/lilygo_t_impulse_plus/target.cpp | 2 +- variants/lilygo_t_impulse_plus/target.h | 2 +- variants/lilygo_t_impulse_plus/variant.h | 11 +- 8 files changed, 193 insertions(+), 18 deletions(-) create mode 100644 src/helpers/ui/SSD1315Display.cpp create mode 100644 src/helpers/ui/SSD1315Display.h diff --git a/examples/companion_radio/ui-tiny/UITask.cpp b/examples/companion_radio/ui-tiny/UITask.cpp index 41702442..d1aa3a11 100644 --- a/examples/companion_radio/ui-tiny/UITask.cpp +++ b/examples/companion_radio/ui-tiny/UITask.cpp @@ -725,7 +725,7 @@ void UITask::loop() { next_batt_chck = millis() + 8000; } #else - if (_display != NULL && _display->isOn() && millis >= next_batt_chck) { + if (_display != NULL && _display->isOn() && millis() >= next_batt_chck) { _cached_batt_mv = getBattMilliVolts(); next_batt_chck = millis() + 8000; } diff --git a/src/helpers/ui/SSD1315Display.cpp b/src/helpers/ui/SSD1315Display.cpp new file mode 100644 index 00000000..95270d06 --- /dev/null +++ b/src/helpers/ui/SSD1315Display.cpp @@ -0,0 +1,122 @@ +#include "SSD1315Display.h" + +#ifndef SCREEN_XOFFSET + #define SCREEN_XOFFSET 0 +#endif + +#ifndef SCREEN_YOFFSET + #define SCREEN_YOFFSET 0 +#endif + +bool SSD1315Display::i2c_probe(TwoWire& wire, uint8_t addr) { + wire.beginTransmission(addr); + uint8_t error = wire.endTransmission(); + return (error == 0); +} + +bool SSD1315Display::begin() { + if (!_isOn) { + if (_peripher_power) _peripher_power->claim(); + _isOn = true; + } + #ifdef DISPLAY_ROTATION + display.setRotation(DISPLAY_ROTATION); + #endif + return display.begin(SSD1306_SWITCHCAPVCC, DISPLAY_ADDRESS, true, false) && i2c_probe(Wire, DISPLAY_ADDRESS); +} + +void SSD1315Display::turnOn() { + if (!_isOn) { + if (_peripher_power) _peripher_power->claim(); + _isOn = true; // set before begin() to prevent double claim + if (_peripher_power) begin(); // re-init display after power was cut + } + display.ssd1306_command(SSD1306_DISPLAYON); +} + +void SSD1315Display::turnOff() { + display.ssd1306_command(SSD1306_DISPLAYOFF); + if (_isOn) { + if (_peripher_power) { +#if PIN_OLED_RESET >= 0 + digitalWrite(PIN_OLED_RESET, LOW); +#endif + _peripher_power->release(); + } + _isOn = false; + } +} + +void SSD1315Display::clear() { + display.clearDisplay(); + display.display(); +} + +void SSD1315Display::startFrame(Color bkg) { + display.clearDisplay(); // TODO: apply 'bkg' + _color = SSD1306_WHITE; + display.setTextColor(_color); + display.setTextSize(1); + display.cp437(true); // Use full 256 char 'Code Page 437' font +} + +void SSD1315Display::setTextSize(int sz) { + display.setTextSize(1); // only small allowed +} + +void SSD1315Display::setColor(Color c) { + _color = (c != 0) ? SSD1306_WHITE : SSD1306_BLACK; + display.setTextColor(_color); +} + +void SSD1315Display::setCursor(int x, int y) { + display.setCursor(x + SCREEN_XOFFSET, y + SCREEN_YOFFSET); +} + +void SSD1315Display::print(const char* str) { + display.print(str); +} + +void SSD1315Display::fillRect(int x, int y, int w, int h) { + display.fillRect(x + SCREEN_XOFFSET, y + SCREEN_YOFFSET, w, h, _color); +} + +void SSD1315Display::drawRect(int x, int y, int w, int h) { + display.drawRect(x + SCREEN_XOFFSET, y + SCREEN_YOFFSET, w, h, _color); +} + +void SSD1315Display::drawXbm(int x, int y, const uint8_t* bits, int w, int h) { + // Width in bytes for bitmap processing + uint16_t widthInBytes = (w + 7) / 8; + + x += SCREEN_XOFFSET; + y += SCREEN_YOFFSET; + // Process the bitmap row by row + for (int by = 0; by < h; by++) { + // Scan across the row bit by bit + for (int bx = 0; bx < w; bx++) { + // Get the current bit using MSB ordering (like GxEPDDisplay) + uint16_t byteOffset = (by * widthInBytes) + (bx / 8); + uint8_t bitMask = 1 << (bx & 7); + bool bitSet = bits[byteOffset] & bitMask; + + // If the bit is set, draw the pixel + if (bitSet) { + display.drawPixel(x + bx, y + by, SSD1306_WHITE); + } + } + } + // wrong bit order: + // display.drawBitmap(x + SCREEN_XOFFSET, y + SCREEN_YOFFSET, bits, w, h, SSD1306_WHITE); +} + +uint16_t SSD1315Display::getTextWidth(const char* str) { + int16_t x1, y1; + uint16_t w, h; + display.getTextBounds(str, 0, 0, &x1, &y1, &w, &h); + return w; +} + +void SSD1315Display::endFrame() { + display.display(); +} diff --git a/src/helpers/ui/SSD1315Display.h b/src/helpers/ui/SSD1315Display.h new file mode 100644 index 00000000..09a7d9c4 --- /dev/null +++ b/src/helpers/ui/SSD1315Display.h @@ -0,0 +1,48 @@ +#pragma once + +#include "DisplayDriver.h" +#include +#include +#define SSD1306_NO_SPLASH +#include +#include + +#ifndef PIN_OLED_RESET + #define PIN_OLED_RESET 21 // Reset pin # (or -1 if sharing Arduino reset pin) +#endif + +#ifndef DISPLAY_ADDRESS + #define DISPLAY_ADDRESS 0x3C +#endif + +class SSD1315Display : public DisplayDriver { + Adafruit_SSD1306 display; + bool _isOn; + uint8_t _color; + RefCountedDigitalPin* _peripher_power; + + bool i2c_probe(TwoWire& wire, uint8_t addr); +public: + SSD1315Display(RefCountedDigitalPin* peripher_power=NULL) : DisplayDriver(64, 32), + display(128, 64, &Wire, PIN_OLED_RESET), + _peripher_power(peripher_power) + { + _isOn = false; + } + bool begin(); + + bool isOn() override { return _isOn; } + void turnOn() override; + void turnOff() override; + void clear() override; + void startFrame(Color bkg = DARK) override; + void setTextSize(int sz) override; + void setColor(Color c) override; + void setCursor(int x, int y) override; + void print(const char* str) 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; + uint16_t getTextWidth(const char* str) override; + void endFrame() override; +}; diff --git a/variants/lilygo_t_impulse_plus/TImpulsePlusBoard.cpp b/variants/lilygo_t_impulse_plus/TImpulsePlusBoard.cpp index df5b7e28..2c7b6a6d 100644 --- a/variants/lilygo_t_impulse_plus/TImpulsePlusBoard.cpp +++ b/variants/lilygo_t_impulse_plus/TImpulsePlusBoard.cpp @@ -29,8 +29,8 @@ void TImpulsePlusBoard::begin() { // configure user button pinMode(TTP223_KEY, INPUT_PULLDOWN); - #if defined(PIN_WIRE_SDA) && defined(PIN_WIRE_SCL) - Wire.setPins(PIN_WIRE_SDA, PIN_WIRE_SCL); + #if defined(SCREEN_SDA) && defined(SCREEN_SCL) + Wire.setPins(SCREEN_SDA, SCREEN_SCL); #endif Wire.begin(); diff --git a/variants/lilygo_t_impulse_plus/platformio.ini b/variants/lilygo_t_impulse_plus/platformio.ini index 0ed5b9a4..01617e59 100644 --- a/variants/lilygo_t_impulse_plus/platformio.ini +++ b/variants/lilygo_t_impulse_plus/platformio.ini @@ -12,20 +12,22 @@ build_flags = ${nrf52_base.build_flags} -D SX126X_CURRENT_LIMIT=140 -D SX126X_RX_BOOSTED_GAIN=1 -D PIN_USER_BTN=-1 - ; -D PIN_USER_BTN=TTP223_KEY ; leave button disabled until screen implemented - ; -D USER_BTN_PRESSED=HIGH + -D PIN_USER_BTN=TTP223_KEY + -D USER_BTN_PRESSED=HIGH -D PIN_WIRE_SDA=SCREEN_SDA -D PIN_WIRE_SCL=SCREEN_SCL - -D ENV_PIN_SDA=IIC_SDA_2 ; firmware hangs without this - -D ENV_PIN_SCL=IIC_SCL_2 ; firmware hangs without this + -D SCREEN_XOFFSET=32 + -D SCREEN_YOFFSET=32 + -D ENV_PIN_SDA=IIC_SDA_1 ; firmware hangs without this + -D ENV_PIN_SCL=IIC_SCL_1 ; firmware hangs without this build_src_filter = ${nrf52_base.build_src_filter} + +<../variants/lilygo_t_impulse_plus> - + + + + lib_deps= ${nrf52_base.lib_deps} ${sensor_base.lib_deps} - adafruit/Adafruit SSD1306 @ ^2.5.13 + adafruit/Adafruit SSD1306 @ ^2.5.14 adafruit/Adafruit GFX Library @ ^1.12.1 [env:LilyGo_T_Impulse_Plus_repeater] @@ -49,8 +51,8 @@ extends = LilyGo_T_Impulse_Plus build_flags = ${LilyGo_T_Impulse_Plus.build_flags} -I src/helpers/ui - -I examples/companion_radio/ui-new - -D DISPLAY_CLASS=SSD1306Display + -I examples/companion_radio/ui-tiny + -D DISPLAY_CLASS=SSD1315Display -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 -D QSPIFLASH=1 @@ -62,7 +64,7 @@ build_flags = build_src_filter = ${LilyGo_T_Impulse_Plus.build_src_filter} + +<../examples/companion_radio/*.cpp> - +<../examples/companion_radio/ui-new/*.cpp> + +<../examples/companion_radio/ui-tiny/*.cpp> lib_deps = ${LilyGo_T_Impulse_Plus.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/lilygo_t_impulse_plus/target.cpp b/variants/lilygo_t_impulse_plus/target.cpp index 87b3dbfe..eabbf21e 100644 --- a/variants/lilygo_t_impulse_plus/target.cpp +++ b/variants/lilygo_t_impulse_plus/target.cpp @@ -21,7 +21,7 @@ EnvironmentSensorManager sensors = EnvironmentSensorManager(); #ifdef DISPLAY_CLASS DISPLAY_CLASS display; - MomentaryButton user_btn(PIN_USER_BTN, 1000, true); + MomentaryButton user_btn(PIN_USER_BTN, 1000, false, true); #endif bool radio_init() { diff --git a/variants/lilygo_t_impulse_plus/target.h b/variants/lilygo_t_impulse_plus/target.h index ff168fbe..54fd2c15 100644 --- a/variants/lilygo_t_impulse_plus/target.h +++ b/variants/lilygo_t_impulse_plus/target.h @@ -9,7 +9,7 @@ #include #include #ifdef DISPLAY_CLASS - #include + #include #include #endif diff --git a/variants/lilygo_t_impulse_plus/variant.h b/variants/lilygo_t_impulse_plus/variant.h index 403e9195..72c5fc98 100644 --- a/variants/lilygo_t_impulse_plus/variant.h +++ b/variants/lilygo_t_impulse_plus/variant.h @@ -94,6 +94,9 @@ extern "C" #define GPS_BAUD_RATE 38400 #define PIN_GPS_EN_ACTIVE LOW +// vibrate +#define VIBRATION_MOTOR_DATA _PINNUM(0, 22) + // Battery #define BATTERY_MEASUREMENT_CONTROL _PINNUM(0, 25) #define BATTERY_ADC_DATA _PINNUM(0, 5) @@ -186,11 +189,11 @@ static const uint8_t SCK = PIN_SPI_SCK ; */ #define WIRE_INTERFACES_COUNT 2 -#define PIN_WIRE_SDA (26) -#define PIN_WIRE_SCL (27) +#define PIN_WIRE_SDA _PINNUM(0, 20) +#define PIN_WIRE_SCL _PINNUM(0, 15) -#define PIN_WIRE1_SDA (26) -#define PIN_WIRE1_SCL (27) +#define PIN_WIRE1_SDA _PINNUM(1, 8) +#define PIN_WIRE1_SCL _PINNUM(0, 11) // ZD25WQ32CEIGR SPI #define ZD25WQ32C_CS _PINNUM(0, 12)