Skip to content

Commit

Permalink
BENB refactor and split grid_esp32_lcd_model in two
Browse files Browse the repository at this point in the history
  • Loading branch information
benblaise-intech committed Feb 4, 2025
1 parent 52143e8 commit 7a57441
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 130 deletions.
168 changes: 75 additions & 93 deletions grid_esp/components/grid_esp32_lcd/grid_esp32_lcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,29 @@ static const char* TAG = "LCD";
#define LCD_SWAP_XY false
#define LCD_FLUSH_CALLBACK lcd_flush_ready

struct grid_esp32_lcd_model grid_esp32_lcd_state = {0};
bool grid_esp32_lcd_ready = 0;

bool color_trans_done_0(void* panel_io, void* edata, void* user_ctx) {
struct grid_esp32_lcd_model grid_esp32_lcd_states[2] = {0};

grid_esp32_lcd_state.tx_ready[0] = 1;
bool color_trans_done_0(struct esp_lcd_panel_io_t* panel_io, esp_lcd_panel_io_event_data_t* edata, void* user_ctx) {

grid_esp32_lcd_states[0].tx_ready = 1;

return true;
}

bool color_trans_done_1(void* panel_io, void* edata, void* user_ctx) {
bool color_trans_done_1(struct esp_lcd_panel_io_t* panel_io, esp_lcd_panel_io_event_data_t* edata, void* user_ctx) {

grid_esp32_lcd_state.tx_ready[1] = 1;
grid_esp32_lcd_states[1].tx_ready = 1;

return true;
}

void grid_esp32_lcd_set_ready(struct grid_esp32_lcd_model* lcd, bool ready) { lcd->ready = ready; }
void grid_esp32_lcd_set_ready(bool ready) { grid_esp32_lcd_ready = ready; }

bool grid_esp32_lcd_get_ready() { return grid_esp32_lcd_ready; }

void grid_esp32_lcd_spi_bus_init(struct grid_esp32_lcd_model* lcd, size_t max_color_sz) {
void grid_esp32_lcd_spi_bus_init(size_t max_color_sz) {

spi_bus_config_t bus_config;
memset(&bus_config, 0, sizeof(bus_config));
Expand All @@ -65,32 +69,32 @@ void grid_esp32_lcd_spi_bus_init(struct grid_esp32_lcd_model* lcd, size_t max_co
ESP_ERROR_CHECK(spi_bus_initialize(LCD_SPI_HOST, &bus_config, SPI_DMA_CH_AUTO));
}

void grid_esp32_lcd_panel_chipsel(struct grid_esp32_lcd_model* lcd, uint8_t lcd_index, uint8_t value) {

gpio_set_level(lcd->cs_gpio_num[lcd_index], value != 0);
}
void grid_esp32_lcd_panel_chipsel(struct grid_esp32_lcd_model* lcd, uint8_t value) { gpio_set_level(lcd->cs_gpio_num, value != 0); }

void grid_esp32_lcd_panel_init(struct grid_esp32_lcd_model* lcd, uint8_t lcd_index, enum grid_lcd_clock_t clock) {

assert(lcd_index < 2);
assert(clock < GRID_LCD_CLK_COUNT);

// Store mirror flags along x and y axes
lcd->mirrors[0] = lcd_index ? !LCD_MIRROR_X : LCD_MIRROR_X;
lcd->mirrors[1] = lcd_index ? !LCD_MIRROR_Y : LCD_MIRROR_Y;

esp_lcd_panel_io_spi_config_t io_config;
memset(&io_config, 0, sizeof(io_config));

io_config.cs_gpio_num = -1;

if (grid_hwcfg_module_is_vsnx_rev_a(&grid_sys_state)) {
lcd->cs_gpio_num[lcd_index] = (lcd_index ? 16 : 33);
lcd->cs_gpio_num = (lcd_index ? 16 : 33);
} else {
lcd->cs_gpio_num[lcd_index] = (lcd_index ? PIN_NUM_CS1 : PIN_NUM_CS0);
lcd->cs_gpio_num = (lcd_index ? PIN_NUM_CS1 : PIN_NUM_CS0);
}

gpio_set_direction(lcd->cs_gpio_num[lcd_index], GPIO_MODE_OUTPUT);
grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 1);
gpio_set_direction(lcd->cs_gpio_num, GPIO_MODE_OUTPUT);
grid_esp32_lcd_panel_chipsel(lcd, 1);

// Panel starts out ready for transmission
lcd->tx_ready[lcd_index] = 1;
lcd->tx_ready = 1;

io_config.dc_gpio_num = PIN_NUM_DC;
io_config.spi_mode = 0;
Expand Down Expand Up @@ -118,7 +122,7 @@ void grid_esp32_lcd_panel_init(struct grid_esp32_lcd_model* lcd, uint8_t lcd_ind
esp_lcd_spi_bus_handle_t bus_handle = LCD_SPI_HOST;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(bus_handle, &io_config, &panel_io_handle));

static bool (*trans_done[2])(void*, void*, void*) = {
static bool (*trans_done[2])(struct esp_lcd_panel_io_t*, esp_lcd_panel_io_event_data_t*, void*) = {
color_trans_done_0,
color_trans_done_1,
};
Expand All @@ -141,131 +145,109 @@ void grid_esp32_lcd_panel_init(struct grid_esp32_lcd_model* lcd, uint8_t lcd_ind
ESP_ERROR_CHECK(LCD_NEW_PANEL(panel_io_handle, &panel_config, &panel_handle));

// Assign handles
lcd->panel[lcd_index][clock] = panel_handle;
lcd->panel_io[lcd_index][clock] = panel_io_handle;
lcd->panel[clock] = panel_handle;
lcd->panel_io[clock] = panel_io_handle;
}

bool grid_esp32_lcd_panel_active(struct grid_esp32_lcd_model* lcd, uint8_t lcd_index) { return lcd->panel[lcd_index][GRID_LCD_CLK_SLOW] || lcd->panel[lcd_index][GRID_LCD_CLK_FAST]; }
bool grid_esp32_lcd_panel_active(struct grid_esp32_lcd_model* lcd) { return lcd->panel[GRID_LCD_CLK_SLOW] || lcd->panel[GRID_LCD_CLK_FAST]; }

void grid_esp32_lcd_panel_reset(struct grid_esp32_lcd_model* lcd, uint8_t lcd_index) {
void grid_esp32_lcd_panel_reset(struct grid_esp32_lcd_model* lcd) {

esp_lcd_panel_handle_t handle = lcd->panel[lcd_index][GRID_LCD_CLK_FAST];
esp_lcd_panel_handle_t handle = lcd->panel[GRID_LCD_CLK_FAST];

grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 0);
grid_esp32_lcd_panel_chipsel(lcd, 0);
esp_lcd_panel_reset(handle);
grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 1);
grid_esp32_lcd_panel_chipsel(lcd, 1);

grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 0);
grid_esp32_lcd_panel_chipsel(lcd, 0);
esp_lcd_panel_init(handle);
grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 1);
grid_esp32_lcd_panel_chipsel(lcd, 1);

grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 0);
grid_esp32_lcd_panel_chipsel(lcd, 0);
esp_lcd_panel_swap_xy(handle, LCD_SWAP_XY);
grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 1);
grid_esp32_lcd_panel_chipsel(lcd, 1);

grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 0);
grid_esp32_lcd_panel_chipsel(lcd, 0);
esp_lcd_panel_set_gap(handle, LCD_GAP_X, LCD_GAP_Y);
grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 1);
grid_esp32_lcd_panel_chipsel(lcd, 1);

bool mirror_x = lcd_index ? !LCD_MIRROR_X : LCD_MIRROR_X;
bool mirror_y = lcd_index ? !LCD_MIRROR_Y : LCD_MIRROR_Y;
grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 0);
esp_lcd_panel_mirror(handle, mirror_x, mirror_y);
grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 1);
grid_esp32_lcd_panel_chipsel(lcd, 0);
esp_lcd_panel_mirror(handle, lcd->mirrors[0], lcd->mirrors[1]);
grid_esp32_lcd_panel_chipsel(lcd, 1);

grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 0);
grid_esp32_lcd_panel_chipsel(lcd, 0);
esp_lcd_panel_invert_color(handle, LCD_INVERT_COLOR);
grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 1);
grid_esp32_lcd_panel_chipsel(lcd, 1);

grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 0);
esp_lcd_panel_disp_off(handle, false);
grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 1);
grid_esp32_lcd_panel_chipsel(lcd, 0);
esp_lcd_panel_disp_on_off(handle, true);
grid_esp32_lcd_panel_chipsel(lcd, 1);
}

bool grid_esp32_lcd_panel_tx_ready(struct grid_esp32_lcd_model* lcd, uint8_t lcd_index) { return lcd->tx_ready[lcd_index]; }
bool grid_esp32_lcd_panel_tx_ready(struct grid_esp32_lcd_model* lcd) { return lcd->tx_ready; }

int grid_esp32_lcd_draw_bitmap_blocking(struct grid_esp32_lcd_model* lcd, uint8_t lcd_index, uint16_t x, uint16_t y, uint16_t width, uint16_t height, void* framebuffer) {
int grid_esp32_lcd_panel_draw_bitmap_blocking(struct grid_esp32_lcd_model* lcd, uint16_t x, uint16_t y, uint16_t width, uint16_t height, void* framebuffer) {

esp_lcd_panel_handle_t handle = lcd->panel[lcd_index][GRID_LCD_CLK_FAST];
esp_lcd_panel_handle_t handle = lcd->panel[GRID_LCD_CLK_FAST];

if (handle == NULL) {
return 1;
}

lcd->tx_ready[lcd_index] = 0;
lcd->tx_ready = 0;

grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 0);
grid_esp32_lcd_panel_chipsel(lcd, 0);

esp_err_t err = esp_lcd_panel_draw_bitmap(handle, x, y, x + width, y + height, framebuffer);
if (err != ESP_OK) {

grid_platform_printf("err: %d\n", err);
}

while (lcd->tx_ready[lcd_index] == 0) {
while (lcd->tx_ready == 0) {
}

grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 1);
grid_esp32_lcd_panel_chipsel(lcd, 1);

return 0;
}

int grid_esp32_lcd_set_madctl(struct grid_esp32_lcd_model* lcd, uint8_t lcd_index, uint8_t madctl) {
int grid_esp32_lcd_panel_set_frctrl2(struct grid_esp32_lcd_model* lcd, uint8_t frctrl) {

esp_lcd_panel_io_handle_t handle = lcd->panel_io[lcd_index][GRID_LCD_CLK_SLOW];
esp_lcd_panel_io_handle_t handle = lcd->panel_io[GRID_LCD_CLK_SLOW];

if (handle == NULL) {
return 1;
}

grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 0);

uint8_t tx[1] = {
madctl,
};
esp_err_t err = esp_lcd_panel_io_tx_param(handle, LCD_CMD_MADCTL, tx, 1);

grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 1);

return err != ESP_OK;
}

int grid_esp32_lcd_set_frctrl2(struct grid_esp32_lcd_model* lcd, uint8_t lcd_index, uint8_t frctrl) {

esp_lcd_panel_io_handle_t handle = lcd->panel_io[lcd_index][GRID_LCD_CLK_SLOW];

if (handle == NULL) {
return 1;
}

grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 0);
grid_esp32_lcd_panel_chipsel(lcd, 0);

uint8_t tx[1] = {
frctrl,
};
esp_err_t err = esp_lcd_panel_io_tx_param(handle, 0xc6, tx, 1);

grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 1);
grid_esp32_lcd_panel_chipsel(lcd, 1);

return err != ESP_OK;
}

int grid_esp32_lcd_get_scanline(struct grid_esp32_lcd_model* lcd, uint8_t lcd_index, uint16_t offset, uint16_t* scanline) {
int grid_esp32_lcd_panel_get_scanline(struct grid_esp32_lcd_model* lcd, uint16_t offset, uint16_t* scanline) {

esp_lcd_panel_io_handle_t handle = lcd->panel_io[lcd_index][GRID_LCD_CLK_SLOW];
esp_lcd_panel_io_handle_t handle = lcd->panel_io[GRID_LCD_CLK_SLOW];

if (handle == NULL) {
return 1;
}

assert(lcd->tx_ready[lcd_index]);
assert(lcd->tx_ready);

grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 0);
grid_esp32_lcd_panel_chipsel(lcd, 0);

uint8_t rx[3] = {0};
esp_err_t err = esp_lcd_panel_io_rx_param(handle, LCD_CMD_GDCAN, rx, 3);

grid_esp32_lcd_panel_chipsel(lcd, lcd_index, 1);
grid_esp32_lcd_panel_chipsel(lcd, 1);

if (err != ESP_OK) {
return 1;
Expand Down Expand Up @@ -314,7 +296,7 @@ static bool in_range_ahead_excl(int min, int max, int a, int len, int x) {

bool grid_esp32_lcd_scan_in_range(int max_excl, int start, int length, int x) { return in_range_ahead_excl(0, max_excl, start, length, x); }

int grid_esp32_module_vsn_lcd_wait_scan_top(struct grid_esp32_lcd_model* lcd, bool active[2], int lines, int tx_lines, int ready_len, uint16_t scans[2]) {
int grid_esp32_module_vsn_lcd_wait_scan_top(struct grid_esp32_lcd_model* lcds, bool active[2], int lines, int tx_lines, int ready_len, uint16_t scans[2]) {

// Whether the scanline is in the allowable range
bool ready[2] = {false, false};
Expand All @@ -329,7 +311,7 @@ int grid_esp32_module_vsn_lcd_wait_scan_top(struct grid_esp32_lcd_model* lcd, bo
continue;
}

grid_esp32_lcd_get_scanline(lcd, i, LCD_SCAN_OFFSET, &scans[i]);
grid_esp32_lcd_panel_get_scanline(&lcds[i], LCD_SCAN_OFFSET, &scans[i]);

// A panel is ready when its scanline enters the allowable range
ready[i] = grid_esp32_lcd_scan_in_range(lines + 1, tx_lines, ready_len, scans[i]);
Expand All @@ -352,7 +334,7 @@ int grid_esp32_module_vsn_lcd_wait_scan_top(struct grid_esp32_lcd_model* lcd, bo
}
}

void grid_esp32_module_vsn_lcd_push_trailing(struct grid_esp32_lcd_model* lcd, int lcd_index, int lines, int columns, int tx_lines, uint8_t* frame, uint8_t* xferbuf) {
void grid_esp32_module_vsn_lcd_push_trailing(struct grid_esp32_lcd_model* lcds, int lcd_index, int lines, int columns, int tx_lines, uint8_t* frame, uint8_t* xferbuf) {

uint16_t scan;

Expand All @@ -367,30 +349,30 @@ void grid_esp32_module_vsn_lcd_push_trailing(struct grid_esp32_lcd_model* lcd, i

// Wait while the scanline is in the region to be transferred,
// to make sure our writes are always trailing it
grid_esp32_lcd_get_scanline(lcd, lcd_index, LCD_SCAN_OFFSET, &scan);
grid_esp32_lcd_panel_get_scanline(&lcds[lcd_index], LCD_SCAN_OFFSET, &scan);
while (grid_esp32_lcd_scan_in_range(lines + 1, i, tx_lines, scan)) {
grid_esp32_lcd_get_scanline(lcd, lcd_index, LCD_SCAN_OFFSET, &scan);
grid_esp32_lcd_panel_get_scanline(&lcds[lcd_index], LCD_SCAN_OFFSET, &scan);
}

// Transfer n lines
grid_esp32_lcd_draw_bitmap_blocking(lcd, lcd_index, 0, row, columns / 1, tx_lines, xferbuf);
grid_esp32_lcd_panel_draw_bitmap_blocking(&lcds[lcd_index], 0, row, columns / 1, tx_lines, xferbuf);
}
}

void grid_esp32_module_vsn_lcd_refresh(struct grid_esp32_lcd_model* lcd, struct grid_gui_model* guis, int lines, int columns, int tx_lines, int ready_len, uint8_t* xferbuf) {
void grid_esp32_module_vsn_lcd_refresh(struct grid_esp32_lcd_model* lcds, struct grid_gui_model* guis, int lines, int columns, int tx_lines, int ready_len, uint8_t* xferbuf) {

bool waiting[2] = {
grid_esp32_lcd_panel_active(lcd, 0),
grid_esp32_lcd_panel_active(lcd, 1),
grid_esp32_lcd_panel_active(&lcds[0]),
grid_esp32_lcd_panel_active(&lcds[1]),
};

while (waiting[0] || waiting[1]) {

uint16_t scans[2];

int lcd_index = grid_esp32_module_vsn_lcd_wait_scan_top(lcd, waiting, lines, tx_lines, ready_len, scans);
int lcd_index = grid_esp32_module_vsn_lcd_wait_scan_top(lcds, waiting, lines, tx_lines, ready_len, scans);

grid_esp32_module_vsn_lcd_push_trailing(lcd, lcd_index, lines, columns, tx_lines, guis[lcd_index].buffer, xferbuf);
grid_esp32_module_vsn_lcd_push_trailing(lcds, lcd_index, lines, columns, tx_lines, guis[lcd_index].buffer, xferbuf);

waiting[lcd_index] = false;
}
Expand All @@ -400,9 +382,6 @@ void grid_esp32_module_vsn_lcd_refresh(struct grid_esp32_lcd_model* lcd, struct

void grid_esp32_lcd_task(void* arg) {

struct grid_esp32_lcd_model* lcd = &grid_esp32_lcd_state;
struct grid_gui_model* guis = grid_gui_states;

uint32_t lcd_tx_lines = 16;
uint32_t lcd_tx_bytes = LCD_VRES * lcd_tx_lines * COLMOD_RGB888_BYTES;
uint8_t* xferbuf = malloc(lcd_tx_bytes);
Expand All @@ -412,7 +391,7 @@ void grid_esp32_lcd_task(void* arg) {
uint8_t counter = 0;

// Wait for another task to mark the LCD state as ready
while (!lcd->ready) {
while (!grid_esp32_lcd_get_ready()) {
vTaskDelay(1);
}

Expand All @@ -429,7 +408,10 @@ void grid_esp32_lcd_task(void* arg) {
grid_lua_semaphore_lock(&grid_lua_state);
#endif

grid_esp32_module_vsn_lcd_refresh(lcd, guis, LCD_LINES, LCD_COLUMNS, lcd_tx_lines, LCD_LINES / 16, xferbuf);
struct grid_esp32_lcd_model* lcds = grid_esp32_lcd_states;
struct grid_gui_model* guis = grid_gui_states;

grid_esp32_module_vsn_lcd_refresh(lcds, guis, LCD_LINES, LCD_COLUMNS, lcd_tx_lines, LCD_LINES / 16, xferbuf);

#ifdef USE_SEMAPHORE
grid_lua_semaphore_release(&grid_lua_state);
Expand Down
Loading

0 comments on commit 7a57441

Please sign in to comment.