diff --git a/platformio.ini b/platformio.ini index f9efad26..3bedaaa1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -55,7 +55,7 @@ debug_flags = #-D ENABLE_DEBUG_EVSE_MONITOR #-D ENABLE_DEBUG_DIVERT #-D ENABLE_DEBUG_LED - #-D ENABLE_DEBUG_LCD + -D ENABLE_DEBUG_LCD #-D ENABLE_DEBUG_MQTT #-D ENABLE_DEBUG_EMONCMS #-D ENABLE_DEBUG_TESLA_CLIENT @@ -105,8 +105,36 @@ build_partitions_debug = min_spiffs_debug.csv neopixel_lib = adafruit/Adafruit NeoPixel@1.11.0 gfx_display_libs = - lvgl/lvgl@8.3.9 - bodmer/TFT_eSPI@^2.5.31 + lvgl/lvgl@8.3.9 + bodmer/TFT_eSPI@^2.5.31 + SPI + +gfx_display_build_flags = + -D LV_CONF_INCLUDE_SIMPLE + -D LV_CONF_SUPPRESS_DEFINE_CHECK + -D USER_SETUP_LOADED + -D ILI9488_DRIVER + -D TFT_WIDTH=320 + -D TFT_HEIGHT=480 + -D TFT_BL=27 + -D TFT_MISO=12 + -D TFT_MOSI=13 + -D TFT_SCLK=14 + -D TFT_CS=15 + -D TFT_DC=2 + -D TFT_RST=-1 + -D TOUCH_CS=33 + -D LOAD_GLCD + -D LOAD_FONT2 + -D LOAD_FONT4 + -D LOAD_FONT6 + -D LOAD_FONT7 + -D LOAD_FONT8 + -D LOAD_GFXFF + -D SPI_FREQUENCY=15999999 + -D SPI_READ_FREQUENCY=20000000 + -D SPI_TOUCH_FREQUENCY=600000 + -D ENABLE_SCREEN_LCD_TFT [env] # specify exact Arduino ESP SDK version, requires platformio 3.5+ (curently dev version) @@ -332,6 +360,17 @@ build_flags = -D RAPI_PORT=Serial1 -D RX1=16 -D TX1=17 -#lib_deps = -# ${common.lib_deps} -# ${common.gfx_display_libs} +lib_deps = + ${common.lib_deps} + ${common.gfx_display_libs} + +[env:elecrow_esp32_hmi_dev] +extends = env:elecrow_esp32_hmi +build_flags = + ${env:elecrow_esp32_hmi.build_flags} + ${common.debug_flags} + ${common.gfx_display_build_flags} +upload_protocol = custom +upload_command = curl -F firmware=@$SOURCE http://$UPLOAD_PORT/update +#build_type = debug +#board_build.partitions = ${common.build_partitions_debug} diff --git a/src/lcd.cpp b/src/lcd.cpp index 76182e08..cdfc0900 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -2,6 +2,8 @@ #undef ENABLE_DEBUG #endif +#ifndef ENABLE_SCREEN_LCD_TFT + #include "emonesp.h" #include "lcd.h" #include "RapiSender.h" @@ -734,3 +736,5 @@ void LcdTask::onButton(int long_press) } LcdTask lcd; + +#endif // ENABLE_SCREEN_LCD_TFT diff --git a/src/lcd.h b/src/lcd.h index 9808fd97..dc6819ef 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -6,12 +6,17 @@ #define LCD_CLEAR_LINE (1 << 0) #define LCD_DISPLAY_NOW (1 << 1) -#define LCD_MAX_LEN 16 - #ifndef LCD_DISPLAY_CHANGE_TIME #define LCD_DISPLAY_CHANGE_TIME (4 * 1000) #endif +#if ENABLE_SCREEN_LCD_TFT +// HACK: This should be done in a much more C++ way +#include "lcd_tft.h" +#else + +#define LCD_MAX_LEN 16 + #define LCD_CHAR_STOP 1 #define LCD_CHAR_PLAY 2 #define LCD_CHAR_LIGHTNING 3 @@ -151,6 +156,9 @@ class LcdTask : public MicroTasks::Task void display(const char *msg, int x, int y, int time, uint32_t flags); }; +#endif // ENABLE_SCREEN_LCD_TFT + extern LcdTask lcd; #endif // __LCD_H + diff --git a/src/lcd_tft.cpp b/src/lcd_tft.cpp new file mode 100644 index 00000000..89672283 --- /dev/null +++ b/src/lcd_tft.cpp @@ -0,0 +1,110 @@ +#if defined(ENABLE_DEBUG) && !defined(ENABLE_DEBUG_LCD) +#undef ENABLE_DEBUG +#endif + +#ifdef ENABLE_SCREEN_LCD_TFT + +#ifndef LCD_BACKLIGHT_PIN +#define LCD_BACKLIGHT_PIN TFT_BL +#endif + +#include "emonesp.h" +#include "lcd.h" +#include "RapiSender.h" +#include "openevse.h" +#include "input.h" +#include "app_config.h" +#include + +void LcdTask::displayFlush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p ) +{ + uint32_t w = ( area->x2 - area->x1 + 1 ); + uint32_t h = ( area->y2 - area->y1 + 1 ); + + lcd._lcd.startWrite(); + lcd._lcd.setAddrWindow( area->x1, area->y1, w, h ); + lcd._lcd.pushColors( ( uint16_t * )&color_p->full, w * h, true ); + lcd._lcd.endWrite(); + + lv_disp_flush_ready( disp ); +} + +LcdTask::LcdTask() : + MicroTasks::Task(), + _lcd() +{ +} + +void LcdTask::display(const __FlashStringHelper *msg, int x, int y, int time, uint32_t flags) +{ +} + +void LcdTask::display(String &msg, int x, int y, int time, uint32_t flags) +{ +} + +void LcdTask::display(const char *msg, int x, int y, int time, uint32_t flags) +{ +} + +void LcdTask::begin(EvseManager &evse, Scheduler &scheduler, ManualOverride &manual) +{ + MicroTask.startTask(this); +} + +void LcdTask::setup() +{ + DBUGLN("LCD UI setup"); + + //lv_init(); + + _lcd.begin(); + _lcd.setRotation(1); + _lcd.fillScreen(TFT_BLACK); + + delay(100); + + pinMode(LCD_BACKLIGHT_PIN, OUTPUT); + digitalWrite(LCD_BACKLIGHT_PIN, HIGH); + + //size_t bufferSize = _screenWidth * _screenHeight / 13; + //_buf1 = ( lv_color_t * )malloc( bufferSize * sizeof( lv_color_t ) ); + //lv_disp_draw_buf_init( &_draw_buf, _buf1, NULL, bufferSize ); +// + //static lv_disp_drv_t disp_drv; + //lv_disp_drv_init( &disp_drv ); +// + //disp_drv.hor_res = _screenWidth; + //disp_drv.ver_res = _screenHeight; + //disp_drv.flush_cb = displayFlush; + //disp_drv.draw_buf = &_draw_buf; + //lv_disp_drv_register( &disp_drv ); + +// static lv_indev_drv_t indev_drv; +// lv_indev_drv_init( &indev_drv ); +// indev_drv.type = LV_INDEV_TYPE_POINTER; +// indev_drv.read_cb = my_touchpad_read; +// lv_indev_drv_register( &indev_drv ); + +} + +unsigned long LcdTask::loop(MicroTasks::WakeReason reason) +{ + DBUG("LCD UI woke: "); + DBUGLN(WakeReason_Scheduled == reason ? "WakeReason_Scheduled" : + WakeReason_Event == reason ? "WakeReason_Event" : + WakeReason_Message == reason ? "WakeReason_Message" : + WakeReason_Manual == reason ? "WakeReason_Manual" : + "UNKNOWN"); + + unsigned long nextUpdate = MicroTask.Infinate; + + //lv_timer_handler(); + + DBUGVAR(nextUpdate); + return nextUpdate; +} + +LcdTask lcd; + +#endif // ENABLE_SCREEN_LCD_TFT diff --git a/src/lcd_tft.h b/src/lcd_tft.h new file mode 100644 index 00000000..79f2244a --- /dev/null +++ b/src/lcd_tft.h @@ -0,0 +1,48 @@ +#ifndef __LCD_TFT_H +#define __LCD_TFT_H + +#define LCD_CHAR_STOP 1 +#define LCD_CHAR_PLAY 2 +#define LCD_CHAR_LIGHTNING 3 +#define LCD_CHAR_LOCK 4 +#define LCD_CHAR_CLOCK 5 + +#include "evse_man.h" +#include "scheduler.h" +#include "manual.h" + +#include +#include + + +class LcdTask : public MicroTasks::Task +{ + private: + TFT_eSPI _lcd; + + // The TFT screen is portrate natively, so we need to rotate it + const uint16_t _screenWidth = TFT_HEIGHT; + const uint16_t _screenHeight = TFT_WIDTH; + + lv_disp_draw_buf_t _draw_buf; + lv_color_t *_buf1; + + static void displayFlush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p); + + protected: + void setup(); + unsigned long loop(MicroTasks::WakeReason reason); + + public: + LcdTask(); + + void begin(EvseManager &evse, Scheduler &scheduler, ManualOverride &manual); + + void display(const __FlashStringHelper *msg, int x, int y, int time, uint32_t flags); + void display(String &msg, int x, int y, int time, uint32_t flags); + void display(const char *msg, int x, int y, int time, uint32_t flags); +}; + +extern LcdTask lcd; + +#endif // __LCD_TFT_H