Finish LCD init implementation

This commit is contained in:
maddiebaka
2025-12-20 14:53:22 -05:00
parent 1763303f3c
commit 001d1dfeca
3 changed files with 103 additions and 36 deletions

View File

@@ -1,3 +1,3 @@
idf_component_register(SRCS "spincoat-plater-firmware.c" "dshot_esc_encoder.c"
PRIV_REQUIRES esp_driver_rmt esp_driver_gpio esp_driver_uart esp_driver_spi esp_lcd
PRIV_REQUIRES esp_driver_rmt esp_driver_gpio esp_driver_uart esp_driver_spi esp_lcd unity
INCLUDE_DIRS ".")

View File

@@ -49,5 +49,11 @@ menu "Pin Mapping Configuration"
default 240
help
This is the vertical resolution for the front-panel SPI LCD
config TFT_BPP
int "The bits per pixel of the TFT display"
default 16
help
This is the bits per pixel for the TFT display and influences
how much memory the display buffer takes up
endmenu

View File

@@ -8,6 +8,10 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "unity.h"
#include "unity_test_runner.h"
#include "esp_log.h"
#include "driver/rmt_tx.h"
@@ -18,6 +22,7 @@
#include "esp_lcd_panel_ops.h"
#include "driver/spi_common.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_commands.h"
#include "esp_lcd_ili9341.h"
#include "dshot_esc_encoder.h"
@@ -41,11 +46,14 @@
#define GPIO_TFT_BL CONFIG_TFT_BL_PIN // Backlight
#define TFT_HRES CONFIG_TFT_HRES
#define TFT_VRES CONFIG_TFT_VRES
#define TFT_BPP CONFIG_TFT_BPP
#define ESP_INTR_FLAG_DEFAULT 0
static const char *TAG = "spincoat-plater-firmware";
static SemaphoreHandle_t refresh_finish = NULL;
static QueueHandle_t uart_queue = NULL;
const int uart_buffer_size = (1024 * 2);
@@ -122,6 +130,9 @@ void init_rmt_esc_tx(void) {
initialize_esc_throttle();
}
/**
* Initialize the UART receive pin so that we can receive telemetry data from the connected ESC.
*/
void init_telemetry_uart_rx(void) {
uart_config_t uart_config = {
.baud_rate = 115200,
@@ -137,41 +148,49 @@ void init_telemetry_uart_rx(void) {
ESP_ERROR_CHECK(uart_set_pin(UART_NUM, UART_PIN_NO_CHANGE, GPIO_ESC_RX, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
}
void spi_lcd_transfer_done(void) {
return;
/**
* Callback for the TFT LCD, notifying when the screen is ready for another chunk of data and
* releasing the drawing semaphore.
*/
IRAM_ATTR static bool notify_refresh_ready(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx)
{
BaseType_t need_yield = pdFALSE;
xSemaphoreGiveFromISR(refresh_finish, &need_yield);
return (need_yield == pdTRUE);
}
/**
* Draws a test bitmap of stripes of colors to the LCD.
*/
static void test_draw_bitmap(esp_lcd_panel_handle_t panel_handle)
{
refresh_finish = xSemaphoreCreateBinary();
TEST_ASSERT_NOT_NULL(refresh_finish);
uint16_t row_line = TFT_VRES / TFT_BPP;
uint8_t byte_per_pixel = TFT_BPP / 8;
uint8_t *color = (uint8_t *)heap_caps_calloc(1, row_line * TFT_VRES * byte_per_pixel, MALLOC_CAP_DMA);
TEST_ASSERT_NOT_NULL(color);
for (int j = 0; j < TFT_BPP; j++) {
for (int i = 0; i < row_line * TFT_HRES ; i++) {
for (int k = 0; k < byte_per_pixel; k++) {
color[i * byte_per_pixel + k] = (SPI_SWAP_DATA_TX(BIT(j), TFT_BPP) >> (k * 8)) & 0xff;
}
}
TEST_ESP_OK(esp_lcd_panel_draw_bitmap(panel_handle, 0, j * row_line, TFT_HRES , (j + 1) * row_line, color));
xSemaphoreTake(refresh_finish, portMAX_DELAY);
}
free(color);
vSemaphoreDelete(refresh_finish);
}
/**
* Initializes the SPI LCD in preparation for writing graphics to it.
*/
void init_spi_lcd(void) {
ESP_LOGI(TAG, "Initialize SPI bus");
// TODO might need to replace with another config var
const spi_bus_config_t bus_config = ILI9341_PANEL_BUS_SPI_CONFIG(GPIO_TFT_SCKL,
GPIO_TFT_MOSI,
TFT_HRES * TFT_VRES * sizeof(uint16_t));
ESP_ERROR_CHECK(spi_bus_initialize(LCD_SPI_HOST, &bus_config, SPI_DMA_CH_AUTO));
ESP_LOGI(TAG, "Install panel IO");
esp_lcd_panel_io_handle_t io_handle = NULL;
const esp_lcd_panel_io_spi_config_t io_config = ILI9341_PANEL_IO_SPI_CONFIG(GPIO_TFT_CS, GPIO_TFT_DC,
NULL, NULL);
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_SPI_HOST, &io_config, &io_handle));
ESP_LOGI(TAG, "Install ILI9341 panel driver");
esp_lcd_panel_handle_t panel_handle = NULL;
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = -1,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(io_handle, &panel_config, &panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
ESP_LOGI(TAG, "Turning on backlight");
printf("Configured pin is reported as %d\n", CONFIG_TFT_BL_PIN);
// TODO: This pin isn't going high. Configure it properly.
ESP_LOGI(TAG, "Turn on backlight");
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << GPIO_TFT_BL),
@@ -182,11 +201,53 @@ void init_spi_lcd(void) {
};
gpio_config(&io_conf);
gpio_set_level(GPIO_TFT_BL, 1);
ESP_LOGI(TAG, "Initialize SPI bus");
const spi_bus_config_t bus_config = ILI9341_PANEL_BUS_SPI_CONFIG(GPIO_TFT_SCKL,
GPIO_TFT_MOSI, TFT_HRES * 80 * TFT_BPP / 8);
TEST_ESP_OK(spi_bus_initialize(LCD_SPI_HOST, &bus_config, SPI_DMA_CH_AUTO));
ESP_LOGI(TAG, "Install panel IO");
esp_lcd_panel_io_handle_t io_handle = NULL;
const esp_lcd_panel_io_spi_config_t io_config = ILI9341_PANEL_IO_SPI_CONFIG(GPIO_TFT_CS, GPIO_TFT_DC,
TEST_ESP_OK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_SPI_HOST, &io_config, &io_handle));
ESP_LOGI(TAG, "Install ili9341 panel driver");
esp_lcd_panel_handle_t panel_handle = NULL;
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = -1, // Shared with Touch reset
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
.color_space = ESP_LCD_COLOR_SPACE_BGR,
#elif ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(6, 0, 0)
.rgb_endian = LCD_RGB_ENDIAN_BGR,
#else
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR,
#endif
.bits_per_pixel = TFT_BPP,
};
TEST_ESP_OK(esp_lcd_new_panel_ili9341(io_handle, &panel_config, &panel_handle));
TEST_ESP_OK(esp_lcd_panel_reset(panel_handle));
TEST_ESP_OK(esp_lcd_panel_init(panel_handle));
TEST_ESP_OK(esp_lcd_panel_mirror(panel_handle, true, true));
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
TEST_ESP_OK(esp_lcd_panel_disp_off(panel_handle, false));
#else
TEST_ESP_OK(esp_lcd_panel_disp_on_off(panel_handle, true));
#endif
//gpio_reset_pin(GPIO_TFT_BL);
//gpio_set_direction(GPIO_TFT_BL, GPIO_MODE_OUTPUT);
ESP_ERROR_CHECK(gpio_set_level(GPIO_TFT_BL, 1));
ESP_LOGI(TAG, "Finished init of spi LCD.");
ESP_LOGI(TAG, "Drawing bitmap.");;
test_draw_bitmap(panel_handle);
vTaskDelay(pdMS_TO_TICKS(3000));
// Tear it back down, move this into a function to clean up after ourselves if it's ever needed.
ESP_LOGI(TAG, "Destroying and cleaning up LCD/SPI handles.");
gpio_reset_pin(GPIO_TFT_BL);
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
TEST_ESP_OK(spi_bus_free(LCD_SPI_HOST));
}
/**