Compare commits

...

3 Commits

Author SHA1 Message Date
maddiebaka cb92f69ee3 Add doxyfile for doxygen 2025-12-20 16:22:28 -05:00
maddiebaka e1f4f46f23 Refactor out LCD init to display.c 2025-12-20 16:21:52 -05:00
maddiebaka 001d1dfeca Finish LCD init implementation 2025-12-20 14:53:22 -05:00
7 changed files with 3148 additions and 64 deletions
+1
View File
@@ -1,3 +1,4 @@
build
sdkconfig
sdkconfig.old
docs
+2976
View File
File diff suppressed because it is too large Load Diff
+2 -2
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
idf_component_register(SRCS "spincoat-plater-firmware.c" "dshot_esc_encoder.c" "display.c"
PRIV_REQUIRES esp_driver_rmt esp_driver_gpio esp_driver_uart esp_driver_spi esp_lcd unity
INCLUDE_DIRS ".")
+6
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
+127
View File
@@ -0,0 +1,127 @@
#include "display.h"
#include <inttypes.h>
#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/gpio.h"
#include "hal/spi_types.h"
#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"
SemaphoreHandle_t refresh_finish = NULL;
static const char * TAG = "spincoat-plater-firmware/display";
/**
* 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.
*/
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, "Turn on backlight");
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << GPIO_TFT_BL),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
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,
notify_refresh_ready, NULL);
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
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));
}
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#include "stdbool.h"
#include "esp_lcd_panel_io.h"
#define LCD_SPI_HOST SPI2_HOST
#define GPIO_TFT_MISO CONFIG_TFT_MISO_PIN
#define GPIO_TFT_MOSI CONFIG_TFT_MOSI_PIN
#define GPIO_TFT_SCKL CONFIG_TFT_SCKL_PIN
#define GPIO_TFT_CS CONFIG_TFT_CS_PIN
#define GPIO_TFT_DC CONFIG_TFT_DC_PIN
#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
/**
* Draws a test bitmap of stripes of colors to the LCD.
*/
void test_draw_bitmap(esp_lcd_panel_handle_t panel_handle);
/**
* Initializes the SPI LCD in preparation for writing graphics to it.
*/
void init_spi_lcd(void);
+9 -62
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,9 +22,11 @@
#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"
#include "display.h"
#if CONFIG_IDF_TARGET_ESP32H2
#define DSHOT_ESC_RESOLUTION_HZ 32000000 // 32MHz resolution, DSHot protocol needs a relative high resolution
@@ -31,17 +37,6 @@
#define GPIO_ESC_CTRL CONFIG_ESC_CTRL_PIN
#define GPIO_ESC_RX CONFIG_TELEMETRY_RX_PIN
#define UART_NUM UART_NUM_2
#define LCD_SPI_HOST SPI2_HOST
#define GPIO_TFT_MISO CONFIG_TFT_MISO_PIN
#define GPIO_TFT_MOSI CONFIG_TFT_MOSI_PIN
#define GPIO_TFT_SCKL CONFIG_TFT_SCKL_PIN
#define GPIO_TFT_CS CONFIG_TFT_CS_PIN
#define GPIO_TFT_DC CONFIG_TFT_DC_PIN
#define GPIO_TFT_BL CONFIG_TFT_BL_PIN // Backlight
#define TFT_HRES CONFIG_TFT_HRES
#define TFT_VRES CONFIG_TFT_VRES
#define ESP_INTR_FLAG_DEFAULT 0
static const char *TAG = "spincoat-plater-firmware";
@@ -122,6 +117,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,57 +135,6 @@ 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;
}
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.
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << GPIO_TFT_BL),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
gpio_config(&io_conf);
//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.");
}
/**
* Sends a DSHOT packet via the RMT. Make sure the RMT channel has been initialized