diff --git a/lib/obp60task/OBP60Extensions.cpp b/lib/obp60task/OBP60Extensions.cpp index 6566a62..8a7b879 100644 --- a/lib/obp60task/OBP60Extensions.cpp +++ b/lib/obp60task/OBP60Extensions.cpp @@ -56,7 +56,7 @@ GxEPD2_BW display(GxEPD2_4 GxEPD2_BW & getdisplay(){return display;} #endif -#ifdef DISPLAY_ST7796 +#ifdef TFT_DISPLAY // panel device + offscreen shadow framebuffer static LGFX panelDisplay; static LGFXCanvas shadowDisplay(&panelDisplay); @@ -307,7 +307,7 @@ void deepSleep(CommonData &common){ getdisplay().setCursor(65, 175); getdisplay().print("To wake up press key and wait 5s"); displayNextPage(); // Update display contents - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY getpaneldisplay().powerSave(true); // Display power save #else getdisplay().powerOff(); // Display power off @@ -336,7 +336,7 @@ void deepSleep(CommonData &common){ getdisplay().setCursor(65, 175); getdisplay().print("To wake up press wheel and wait 5s"); displayNextPage(); // Partial update - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY getpaneldisplay().powerSave(true); // Display power save #else getdisplay().powerOff(); // Display power off @@ -575,7 +575,7 @@ void drawButtonCenter(int16_t cx, int16_t cy, int8_t sx, int8_t sy, String text, void drawTextRalign(int16_t x, int16_t y, String text) { int16_t x1, y1; uint16_t w, h; -#ifdef DISPLAY_ST7796 +#ifdef TFT_DISPLAY w = getdisplay().textWidth(text); h = getdisplay().fontHeight(); #else @@ -1071,7 +1071,7 @@ void displayRudderPosition(int rudderPosition, uint8_t rangeDeg, uint16_t cx, ui String lbl = String(angle); int16_t bx, by; uint16_t bw, bh; - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY // LovyanGFX: compute width/height manually bw = getdisplay().textWidth(lbl); bh = getdisplay().fontHeight(); @@ -1100,7 +1100,7 @@ void doImageRequest(GwApi *api, int *pageno, const PageStruct pages[MAX_PAGE_NUM uint8_t *fb = nullptr; // EPD framebuffer std::vector imageBuffer; // image in webserver transferbuffer String mimetype; - #ifndef DISPLAY_ST7796 + #ifndef TFT_DISPLAY fb = getdisplay().getBuffer(); // available only for EPD #endif if (!fb) { diff --git a/lib/obp60task/OBP60Extensions.h b/lib/obp60task/OBP60Extensions.h index c6db616..1dc130f 100644 --- a/lib/obp60task/OBP60Extensions.h +++ b/lib/obp60task/OBP60Extensions.h @@ -9,8 +9,14 @@ #include // I2C FRAM #include -#ifdef DISPLAY_ST7796 - #include // TFT LCD lib for ST7796 color displays +#ifdef TFT_DISPLAY + #if !defined(TFT_320x480_ST7796) && !defined(TFT_320x480_ILI9488) + #error "TFT_DISPLAY requires one panel type: TFT_320x480_ST7796 or TFT_320x480_ILI9488" + #endif + #if defined(TFT_320x480_ST7796) && defined(TFT_320x480_ILI9488) + #error "Select exactly one TFT panel type: TFT_320x480_ST7796 or TFT_320x480_ILI9488" + #endif + #include // TFT LCD lib for 320x480 color displays #undef GxEPD_WHITE #define GxEPD_WHITE TFT_WHITE // Replacement color for white on TFT (OBPHardware.h) #undef GxEPD_BLACK @@ -82,8 +88,8 @@ GxEPD2_BW & getdisplay(); GxEPD2_BW & getdisplay(); #endif -#ifdef DISPLAY_ST7796 -// LovyanGFX based display wrapper for ST7796 +#ifdef TFT_DISPLAY +// LovyanGFX based display wrapper for TFT panels class LGFX : public lgfx::LGFX_Device { public: lgfx::Bus_SPI _bus_instance; @@ -93,7 +99,11 @@ public: auto cfg = _bus_instance.config(); cfg.spi_host = SPI2_HOST; cfg.spi_mode = 0; - cfg.freq_write = 80000000; + #if defined(TFT_320x480_ILI9488) + cfg.freq_write = 40000000; + #else + cfg.freq_write = 80000000; + #endif cfg.freq_read = 16000000; cfg.pin_sclk = OBP_SPI_CLK; cfg.pin_mosi = OBP_SPI_DIN; @@ -264,7 +274,7 @@ public: // E-Ink interface compatibility void setFullWindow() { /* no-op on TFT */ } - // Runtime panel offset control (ST7796) + // Runtime panel offset control for TFT panels void setPanelOffset(int16_t x, int16_t y) { auto cfg = _panel_instance.config(); cfg.offset_x = x; @@ -283,7 +293,11 @@ private: lgfx::GFXglyph* _adfGlyphBridge = nullptr; uint16_t _adfGlyphCount = 0; const GFXfont* _currentAdfFont = nullptr; - lgfx::Panel_ST7796 _panel_instance; + #if defined(TFT_320x480_ST7796) + lgfx::Panel_ST7796 _panel_instance; + #elif defined(TFT_320x480_ILI9488) + lgfx::Panel_ILI9488 _panel_instance; + #endif }; class LGFXCanvas : public lgfx::LGFX_Sprite { @@ -437,7 +451,7 @@ bool initDisplayScaleBuffer(uint16_t width, uint16_t height); #define PAGE_UPDATE 1 // page wants display to update #define PAGE_HIBERNATE 2 // page wants displey to hibernate -#ifdef DISPLAY_ST7796 +#ifdef TFT_DISPLAY #ifndef OBP_TFT_ENABLE_SCALING #define OBP_TFT_ENABLE_SCALING 1 #endif @@ -487,7 +501,7 @@ inline void drawMonochromeBitmap( bool lsbFirst=false, // true: least significant bit = left/top pixel bool mirrorX=false) // true: bytes run right-to-left within each row { - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY // TFT converts per‑pixel int bytesPerRow = (w + 7) / 8; for (int yy = 0; yy < h; yy++) { @@ -535,7 +549,7 @@ inline void displayDrawBitmap(int16_t x, int16_t y, const uint8_t *bmp, int16_t w, int16_t h, uint16_t color) { - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY drawMonochromeBitmap(x, y, bmp, w, h, color); #else getdisplay().drawBitmap(x, y, bmp, w, h, color); @@ -543,7 +557,7 @@ inline void displayDrawBitmap(int16_t x, int16_t y, } inline void displayFirstPage() { - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY initDisplayShadowBuffer(); #else getdisplay().firstPage(); @@ -551,7 +565,7 @@ inline void displayFirstPage() { } inline void displayNextPage() { - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY if (initDisplayShadowBuffer()) { LGFXCanvas &src = getdisplay(); LGFX &dst = getpaneldisplay(); @@ -620,7 +634,7 @@ inline void displayNextPage() { } inline void displaySetPartialWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) { - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY // TFT LCD doesn't use partial windows (void)x; (void)y; (void)w; (void)h; #else @@ -629,18 +643,18 @@ inline void displaySetPartialWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t } inline void displaySetFullWindow() { - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY // TFT LCD doesn't need setFullWindow() #else getdisplay().setFullWindow(); #endif } -// replacement for getTextBounds that works with both EPD and ST7796 +// replacement for getTextBounds that works with both EPD and TFT inline void displayGetTextBounds(const String &txt, int16_t x, int16_t y, int16_t *x0, int16_t *y0, uint16_t *w, uint16_t *h) { -#ifdef DISPLAY_ST7796 +#ifdef TFT_DISPLAY getdisplay().getTextBounds(txt, x, y, x0, y0, w, h); #else getdisplay().getTextBounds(txt, x, y, x0, y0, w, h); diff --git a/lib/obp60task/OBPcharts.cpp b/lib/obp60task/OBPcharts.cpp index b245972..9bf8f16 100644 --- a/lib/obp60task/OBPcharts.cpp +++ b/lib/obp60task/OBPcharts.cpp @@ -29,7 +29,7 @@ Chart::Chart(RingBuffer& dataBuf, double dfltRng, CommonData& common, bgColor = commonData->bgcolor; // display dimensions (avoid calling width()/height() on incomplete LGFX type) - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY dWidth = 480; dHeight = 320; #else diff --git a/lib/obp60task/PageNavigation.cpp b/lib/obp60task/PageNavigation.cpp index 95d0b6a..046886c 100644 --- a/lib/obp60task/PageNavigation.cpp +++ b/lib/obp60task/PageNavigation.cpp @@ -13,7 +13,7 @@ NetworkClient net(JSON_BUFFER); // Define network client ImageDecoder decoder; // Define image decoder -#ifdef DISPLAY_ST7796 +#ifdef TFT_DISPLAY // Set to true to render a generated RGB565 color-bar test image. static constexpr bool kShowRgb565StripeTestImage = false; @@ -82,7 +82,7 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map commonData = &common; common.logger->logDebug(GwLog::LOG,"Instantiate PageNavigation"); imageBackupCapacity = (size_t)GxEPD_WIDTH * (size_t)GxEPD_HEIGHT; - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY imageBackupCapacity *= 2U; #endif imageBackupData = (uint8_t*)heap_caps_malloc(imageBackupCapacity, MALLOC_CAP_SPIRAM); @@ -415,7 +415,7 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map // For more details see: https://github.com/norbert-walter/maps-converter String url = String("http://") + server + ":" + port + // OBP Server String("/get_image_json?") + // Service: Output B&W picture as JSON (Base64 + gzip) - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY "oformat=3" + // Image output format in JSON: 3=RGB565 format #else "oformat=4" + // Image output format in JSON: 4=b/w 1-Bit format @@ -425,7 +425,7 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map "&lon=" + String(longitude, 6) + // Longitude "&mrot=" + mapRot + // Rotation angle navigation map in degree "&mtype=" + mType + // Default Map: Open Street Map - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY "&itype=1" + // Image type: 1=Color #else "&itype=4" + // Image type: 4=b/w with dithering @@ -501,7 +501,7 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map if (imgSize < requiredBytesMono){ imgSize = requiredBytesMono; } - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY if (imgSize < requiredBytesRgb565){ imgSize = requiredBytesRgb565; } @@ -537,11 +537,11 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map } bool imageIsRgb565 = false; - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY imageIsRgb565 = (decodedSize >= requiredBytesRgb565); #endif - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY if (kShowRgb565StripeTestImage) { createRgb565StripeImage(reinterpret_cast(imageData), imgWidth, imgHeight); decodedSize = requiredBytesRgb565; @@ -563,7 +563,7 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map lostCounter = 0; // Show image (navigation map) - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY if (imageIsRgb565) { drawRgb565Image(0, 25, reinterpret_cast(imageData), imgWidth, imgHeight); } else { @@ -594,7 +594,7 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map // Show backup image (backup navigation map) if (hasImageBackup) { - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY if (imageBackupIsRgb565) { drawRgb565Image(0, 25, reinterpret_cast(imageBackupData), imageBackupWidth, imageBackupHeight); } else { diff --git a/lib/obp60task/obp60task.cpp b/lib/obp60task/obp60task.cpp index 606ca83..2c76b33 100644 --- a/lib/obp60task/obp60task.cpp +++ b/lib/obp60task/obp60task.cpp @@ -284,7 +284,7 @@ void underVoltageError(CommonData &common) { getdisplay().setCursor(65, 175); getdisplay().print("Charge battery and restart system"); displayNextPage(); // Partial update - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY getpaneldisplay().powerSave(true); // Display power save #else getdisplay().powerOff(); // Display power off @@ -308,7 +308,7 @@ void underVoltageError(CommonData &common) { getdisplay().setCursor(65, 175); getdisplay().print("To wake up repower system"); displayNextPage(); // Partial update - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY getpaneldisplay().powerSave(true); // Display power save #else getdisplay().powerOff(); // Display power off @@ -382,13 +382,13 @@ void OBP60Task(GwApi *api){ #ifdef DISPLAY_GDEY042T81 getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse - #elif defined DISPLAY_ST7796 - getpaneldisplay().init(); // Init for ST7796 TFT LCD panel + #elif defined(TFT_DISPLAY) + getpaneldisplay().init(); // Init for TFT LCD panel #else getdisplay().init(115200); // Init for normal displays #endif - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY getpaneldisplay().setRotation(0); // Set display orientation (horizontal) getpaneldisplay().setPanelOffset(0, 0); // Use full native framebuffer coordinates getpaneldisplay().fillScreen(0x0000); // Initialize full TFT screen to black (native RGB565) @@ -741,7 +741,7 @@ void OBP60Task(GwApi *api){ starttime1 = millis(); starttime2 = millis(); displaySetFullWindow(); // Set full update - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY // TFT LCD doesn't need refresh operations #else if(fastrefresh == "true"){ @@ -773,7 +773,7 @@ void OBP60Task(GwApi *api){ starttime2 = millis(); LOG_DEBUG(GwLog::DEBUG,"E-Ink full refresh first 5 min"); displaySetFullWindow(); // Set full update - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY // TFT LCD doesn't need refresh operations #else if(fastrefresh == "true"){ @@ -801,7 +801,7 @@ void OBP60Task(GwApi *api){ if(millis() > starttime2 + fullrefreshtime * 60 * 1000){ starttime2 = millis(); LOG_DEBUG(GwLog::DEBUG,"E-Ink full refresh"); - #ifdef DISPLAY_ST7796 + #ifdef TFT_DISPLAY // TFT LCD: no special refresh #else getdisplay().setFullWindow(); // Set full update @@ -905,7 +905,7 @@ void OBP60Task(GwApi *api){ displayNextPage(); // Partial update (fast) } if (ret & PAGE_HIBERNATE) { - #ifndef DISPLAY_ST7796 + #ifndef TFT_DISPLAY getdisplay().hibernate(); #endif } diff --git a/lib/obp60task/obp60task.h b/lib/obp60task/obp60task.h index 784eb30..af12a23 100644 --- a/lib/obp60task/obp60task.h +++ b/lib/obp60task/obp60task.h @@ -35,19 +35,19 @@ // OBP60 Task void OBP60Task(GwApi *param); DECLARE_USERTASK_PARAM(OBP60Task, 35000); // Need 35k RAM as stack size - #if defined(BOARD_OBP60S3) && defined(HARDWARE_V21) && defined(DISPLAY_ST7796) + #if defined(BOARD_OBP60S3) && defined(HARDWARE_V21) && defined(TFT_DISPLAY) DECLARE_CAPABILITY(obp70,true); #endif - #if defined(BOARD_OBP60S3) && defined(HARDWARE_V21) && !defined(DISPLAY_ST7796) + #if defined(BOARD_OBP60S3) && defined(HARDWARE_V21) && !defined(TFT_DISPLAY) DECLARE_CAPABILITY(obp60,true); #endif #ifdef BOARD_OBP40S3 DECLARE_CAPABILITY(obp40,true) #endif - #if defined(BOARD_OBP60S3) && defined(HARDWARE_V21) && defined(DISPLAY_ST7796) + #if defined(BOARD_OBP60S3) && defined(HARDWARE_V21) && defined(TFT_DISPLAY) DECLARE_STRING_CAPABILITY(HELP_URL, "https://obp60-v2-docu.readthedocs.io/en/latest/"); // Link to help pages #endif - #if defined(BOARD_OBP60S3) && defined(HARDWARE_V21) && !defined(DISPLAY_ST7796) + #if defined(BOARD_OBP60S3) && defined(HARDWARE_V21) && !defined(TFT_DISPLAY) DECLARE_STRING_CAPABILITY(HELP_URL, "https://obp60-v2-docu.readthedocs.io/en/latest/"); // Link to help pages #endif #ifdef BOARD_OBP40S3 diff --git a/lib/obp60task/platformio.ini b/lib/obp60task/platformio.ini index bcb213a..031e68c 100644 --- a/lib/obp60task/platformio.ini +++ b/lib/obp60task/platformio.ini @@ -55,7 +55,9 @@ build_flags= -D BOARD_OBP60S3 #Board OBP60 V2.1 with ESP32S3 # -D HARDWARE_V20 #OBP60 hardware revision V2.0 -D HARDWARE_V21 #OBP60 hardware revision V2.1 - -D DISPLAY_ST7796 #ST7796 TFT LCD display (480x320 color display) + -D TFT_DISPLAY #Enable TFT LCD display path (instead of E-Ink) + -D TFT_320x480_ST7796 #TFT panel type: ST7796 (320x480) +# -D TFT_320x480_ILI9488 #TFT panel type: ILI9488 (320x480), use instead of ST7796 -D OBP_TFT_ENABLE_SCALING=1 #TFT scaling on/off (1=scale to max Y=320, 0=no scaling) -D OBP_TFT_SCALE_ANTIALIAS=1 #Antialiasing for TFT scaling (1=on, 0=off) # -D ENABLE_PATCHES #enable patching of gateway code