Replace USE_PIN_TFT bit-bang software SPI (~8-10 fps) with LovyanGFX
hardware FSPI (SPI2_HOST, 40 MHz, DMA) matching Meshtastic's architecture.
Files:
- variants/rak_tap_v2/LGFXDisplay.{h,cpp}: new DisplayDriver via LovyanGFX
- variants/rak_tap_v2/target.{h,cpp}: SPI.begin() in radio_init() for FSPI
- platformio.ini: DISPLAY_CLASS=LGFXDisplay, LGFX_INVERT_COLOR, LovyanGFX dep
- src/ui-touch/UITask.cpp: RAK path includes LGFXDisplay + 320x40 LVGL buffer
- NOTICE: LovyanGFX dependency
Signed-off-by: Ethan-chen1234-zy <ethan.chen@rakwireless.com>
139 lines
4.3 KiB
C++
139 lines
4.3 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
||
#if defined(RAK_WISMESH_TAP_V2)
|
||
|
||
#include "LGFXDisplay.h"
|
||
#include <Arduino.h>
|
||
|
||
#ifndef LGFX_INVERT_COLOR
|
||
#define LGFX_INVERT_COLOR true // default: black bg (ST7789 INVON)
|
||
#endif
|
||
|
||
LGFXDisplay::LGFXDisplay(RefCountedDigitalPin* peripher_power)
|
||
: DisplayDriver(240, 320),
|
||
_periph_power(peripher_power)
|
||
{
|
||
_isOn = false;
|
||
_color = 0xFFFF;
|
||
|
||
// ---- SPI bus config ----
|
||
{
|
||
auto cfg = _bus.config();
|
||
cfg.spi_host = SPI2_HOST; // FSPI, already begun by SPI.begin() in radio_init()
|
||
cfg.spi_mode = 0;
|
||
cfg.freq_write = 20000000; // 20 MHz — conservative for this PCB
|
||
cfg.freq_read = 16000000;
|
||
cfg.spi_3wire = false;
|
||
cfg.use_lock = true;
|
||
cfg.dma_channel = SPI_DMA_CH_AUTO;
|
||
cfg.pin_sclk = PIN_TFT_SCL; // 13
|
||
cfg.pin_mosi = PIN_TFT_SDA; // 11
|
||
cfg.pin_miso = -1;
|
||
cfg.pin_dc = PIN_TFT_DC; // 42
|
||
_bus.config(cfg);
|
||
_panel.setBus(&_bus);
|
||
}
|
||
|
||
// ---- ST7789 panel config ----
|
||
{
|
||
auto cfg = _panel.config();
|
||
cfg.pin_cs = PIN_TFT_CS; // 12
|
||
cfg.pin_rst = PIN_TFT_RST; // -1
|
||
cfg.pin_busy = -1;
|
||
cfg.panel_width = 240;
|
||
cfg.panel_height = 320;
|
||
cfg.offset_x = 0;
|
||
cfg.offset_y = 0;
|
||
cfg.offset_rotation = 0;
|
||
cfg.readable = false;
|
||
cfg.invert = LGFX_INVERT_COLOR; // configurable via -D LGFX_INVERT_COLOR in platformio.ini
|
||
cfg.rgb_order = false;
|
||
cfg.dlen_16bit = false;
|
||
cfg.bus_shared = true;
|
||
_panel.config(cfg);
|
||
}
|
||
|
||
// ---- Backlight ----
|
||
{
|
||
auto cfg = _light.config();
|
||
cfg.pin_bl = PIN_TFT_LEDA_CTL; // 41
|
||
cfg.invert = false;
|
||
cfg.freq = 44000;
|
||
cfg.pwm_channel = 7;
|
||
_light.config(cfg);
|
||
_panel.setLight(&_light);
|
||
}
|
||
|
||
_lcd.setPanel(&_panel);
|
||
}
|
||
|
||
bool LGFXDisplay::begin() {
|
||
if (_isOn) return true;
|
||
if (_periph_power) _periph_power->claim();
|
||
|
||
_lcd.init();
|
||
_lcd.setSwapBytes(true); // LVGL pixels are LE; ST7789 needs BE
|
||
_lcd.setRotation(1); // landscape 320×240
|
||
_lcd.setBrightness(255);
|
||
_lcd.fillScreen(0x0000);
|
||
setLogicalSize(_lcd.width(), _lcd.height());
|
||
|
||
_isOn = true;
|
||
Serial.printf("[TFT] LGFXDisplay %dx%d rotation=1\n", _lcd.width(), _lcd.height());
|
||
return true;
|
||
}
|
||
|
||
void LGFXDisplay::turnOn() {
|
||
if (_isOn) return;
|
||
if (_periph_power) _periph_power->claim();
|
||
_lcd.setBrightness(255);
|
||
_isOn = true;
|
||
}
|
||
void LGFXDisplay::turnOff() {
|
||
if (!_isOn) return;
|
||
_lcd.setBrightness(0);
|
||
_isOn = false;
|
||
if (_periph_power) _periph_power->release();
|
||
}
|
||
void LGFXDisplay::clear() { _lcd.fillScreen(0x0000); }
|
||
void LGFXDisplay::startFrame(Color) { _lcd.fillScreen(0x0000); }
|
||
void LGFXDisplay::setTextSize(int sz) { _lcd.setTextSize(sz); }
|
||
|
||
static inline uint16_t _c16(DisplayDriver::Color c) {
|
||
switch (c) {
|
||
case DisplayDriver::DARK: return 0x0000;
|
||
case DisplayDriver::LIGHT: return 0xFFFF;
|
||
case DisplayDriver::RED: return 0xF800;
|
||
case DisplayDriver::GREEN: return 0x07E0;
|
||
case DisplayDriver::BLUE: return 0x001F;
|
||
case DisplayDriver::YELLOW: return 0xFFE0;
|
||
case DisplayDriver::ORANGE: return 0xFD20;
|
||
default: return 0xFFFF;
|
||
}
|
||
}
|
||
void LGFXDisplay::setColor(Color c) {
|
||
_color = _c16(c);
|
||
_lcd.setTextColor(_color);
|
||
}
|
||
void LGFXDisplay::setCursor(int x, int y) { _lcd.setCursor(x, y); }
|
||
void LGFXDisplay::print(const char* s) { _lcd.print(s); }
|
||
void LGFXDisplay::fillRect(int x,int y,int w,int h) { _lcd.fillRect(x,y,w,h,_color); }
|
||
void LGFXDisplay::drawRect(int x,int y,int w,int h) { _lcd.drawRect(x,y,w,h,_color); }
|
||
void LGFXDisplay::drawXbm(int x,int y,const uint8_t* b,int w,int h) { _lcd.drawXBitmap(x,y,b,w,h,_color); }
|
||
uint16_t LGFXDisplay::getTextWidth(const char* s) { return _lcd.textWidth(s); }
|
||
void LGFXDisplay::endFrame() {}
|
||
|
||
void LGFXDisplay::writePixelsRGB565(int x, int y, int w, int h, const uint16_t* pixels) {
|
||
if (!_isOn || !pixels || w <= 0 || h <= 0) return;
|
||
_lcd.startWrite();
|
||
_lcd.setAddrWindow(x, y, w, h);
|
||
_lcd.writePixels(const_cast<uint16_t*>(pixels), (uint32_t)(w * h));
|
||
_lcd.endWrite();
|
||
}
|
||
|
||
void LGFXDisplay::setDisplayRotation(uint8_t) {
|
||
_lcd.setRotation(1);
|
||
setLogicalSize(_lcd.width(), _lcd.height());
|
||
}
|
||
|
||
#endif
|