@@ -8,7 +8,57 @@ lv_disp_drv_t disp_drv;
88lv_disp_draw_buf_t draw_buf;
99lv_color_t buf[LVGL_BUFFER_SIZE];
1010lv_color_t buf2[LVGL_BUFFER_SIZE]; // Second buffer for double buffering
11- Adafruit_ST7735* tft_driver = nullptr ;
11+ lgfx::LGFX_Device* tft_driver = nullptr ;
12+ extern SPIClass* hardwareSPI; // External reference to shared SPI instance
13+
14+ // Custom LovyanGFX configuration for ST7735
15+ class LGFX_ST7735 : public lgfx ::LGFX_Device {
16+ lgfx::Panel_ST7735S _panel_instance;
17+ lgfx::Bus_SPI _bus_instance;
18+
19+ public:
20+ LGFX_ST7735 () {
21+ {
22+ auto cfg = _bus_instance.config ();
23+ cfg.spi_host = SPI2_HOST; // Use SPI2 (HSPI)
24+ cfg.spi_mode = 0 ;
25+ cfg.freq_write = 27000000 ; // SPI speed for writing
26+ cfg.freq_read = 16000000 ; // SPI speed for reading
27+ cfg.spi_3wire = false ;
28+ cfg.use_lock = true ;
29+ cfg.dma_channel = SPI_DMA_CH_AUTO;
30+ cfg.pin_sclk = 12 ;
31+ cfg.pin_mosi = 11 ;
32+ cfg.pin_miso = 13 ;
33+ cfg.pin_dc = 14 ;
34+ _bus_instance.config (cfg);
35+ _panel_instance.setBus (&_bus_instance);
36+ }
37+ {
38+ auto cfg = _panel_instance.config ();
39+ cfg.pin_cs = 10 ;
40+ cfg.pin_rst = 15 ;
41+ cfg.pin_busy = -1 ;
42+ cfg.memory_width = 160 ;
43+ cfg.memory_height = 128 ;
44+ cfg.panel_width = 160 ;
45+ cfg.panel_height = 128 ;
46+ // ST7735 BLACKTAB variant - specific settings for 160x128 display
47+ cfg.offset_x = 0 ;
48+ cfg.offset_y = 0 ;
49+ cfg.offset_rotation = 0 ;
50+ cfg.dummy_read_pixel = 8 ;
51+ cfg.dummy_read_bits = 1 ;
52+ cfg.readable = false ;
53+ cfg.invert = false ; // User reported darker display, so no invert needed
54+ cfg.rgb_order = false ; // Try RGB order instead of BGR
55+ cfg.dlen_16bit = false ;
56+ cfg.bus_shared = true ; // Important for shared SPI
57+ _panel_instance.config (cfg);
58+ }
59+ setPanel (&_panel_instance);
60+ }
61+ };
1262uint32_t lvgl_last_update = 0 ;
1363// Define the shared SPI bus mutex
1464SemaphoreHandle_t spiBusMutex = NULL ;
@@ -31,6 +81,7 @@ void setupLvglDisplay(
3181 int8_t rst_pin,
3282 SPIClass* spi
3383) {
84+ // Note: TFT_eSPI doesn't use the spi parameter - it's configured via build flags
3485 USBSerial.println (" Setting up LVGL display" );
3586
3687 // Create SPI bus mutex on first use if not already created
@@ -41,18 +92,26 @@ void setupLvglDisplay(
4192 }
4293 }
4394
44- // Create the TFT driver instance if not already created
95+ // Create the LovyanGFX driver instance if not already created
4596 if (tft_driver == nullptr ) {
46- tft_driver = new Adafruit_ST7735 (spi, displayCS, dc_pin, rst_pin);
47-
48- // Initialize the display
49- tft_driver->initR (INITR_BLACKTAB);
50- tft_driver->setRotation (deviceData.screen_rotation );
97+ // Store the shared SPI instance
98+ hardwareSPI = spi;
5199
52- // Optimize SPI speed - limited by MCP2515 max of 10MHz on shared bus
53- tft_driver-> setSPISpeed ( 10000000 ); // 10MHz - safe for both ST7735 and MCP2515
100+ // Create custom ST7735 configuration for LovyanGFX
101+ tft_driver = new LGFX_ST7735 ();
54102
55- tft_driver->fillScreen (ST77XX_BLACK);
103+ // Initialize display with custom configuration
104+ if (tft_driver->init ()) {
105+ tft_driver->setRotation (deviceData.screen_rotation );
106+
107+ // Clear screen with a test pattern to verify it's working
108+ tft_driver->fillScreen (0x0000 ); // Black
109+ tft_driver->fillRect (10 , 10 , 50 , 50 , 0xF800 ); // Red square for testing
110+
111+ USBSerial.println (" LovyanGFX ST7735 initialized successfully" );
112+ } else {
113+ USBSerial.println (" ERROR: LovyanGFX ST7735 initialization failed!" );
114+ }
56115 }
57116
58117 // Initialize LVGL buffer
@@ -81,40 +140,22 @@ void setupLvglDisplay(
81140 lv_disp_set_theme (lv_disp_get_default (), theme);
82141}
83142
84- // Optimized flush callback to minimize tearing and improve performance
85- // CS pin management is handled here where actual SPI communication occurs
143+ // High-performance flush callback using LovyanGFX with DMA
86144void lvgl_flush_cb (lv_disp_drv_t * disp, const lv_area_t * area, lv_color_t * color_p) {
87145 uint32_t w = (area->x2 - area->x1 + 1 );
88146 uint32_t h = (area->y2 - area->y1 + 1 );
89- uint32_t len = w * h;
90147
91- // Guard shared SPI bus for display flush
148+ // LovyanGFX handles SPI transactions internally, but we still guard for MCP2515
92149 if (spiBusMutex != NULL ) {
93150 xSemaphoreTake (spiBusMutex, portMAX_DELAY);
94151 }
95152
96- // Disable interrupts during critical display update to prevent tearing
97- portDISABLE_INTERRUPTS ();
98-
99- // Make sure display CS is selected
100- digitalWrite (displayCS, LOW);
101-
102- // Start optimized write sequence
153+ // LovyanGFX DMA-optimized pixel transfer
103154 tft_driver->startWrite ();
104155 tft_driver->setAddrWindow (area->x1 , area->y1 , w, h);
105-
106- // Push colors using DMA for optimal performance
107- tft_driver->writePixels ((uint16_t *)color_p, len); // NOLINT(readability/casting)
108-
109- // Complete write sequence
156+ tft_driver->writePixels ((uint16_t *)color_p, w * h); // NOLINT(readability/casting)
110157 tft_driver->endWrite ();
111158
112- // Deselect display CS when done
113- digitalWrite (displayCS, HIGH);
114-
115- // Re-enable interrupts
116- portENABLE_INTERRUPTS ();
117-
118159 if (spiBusMutex != NULL ) {
119160 xSemaphoreGive (spiBusMutex);
120161 }
@@ -134,7 +175,11 @@ void lv_tick_handler() {
134175 }
135176}
136177
137- // Update LVGL - call this regularly
178+ // Shared SPI helper function
179+ SPIClass* getSharedSPI () {
180+ return hardwareSPI;
181+ }
182+
138183void updateLvgl () {
139184 uint32_t current_ms = millis ();
140185
0 commit comments