From 6ab3c1cdbcaae4c1fd0369ec4ea1a349a5a944c8 Mon Sep 17 00:00:00 2001 From: Mateusz Zalega <mateusz@appliedsourcery.com> Date: Sun, 28 Jul 2019 20:20:59 +0200 Subject: [PATCH] LCD: implemented double buffering and asynchronous updates Signed-off-by: Mateusz Zalega <mateusz@appliedsourcery.com> --- lib/gfx/GUI_DEV/DEV_Config.c | 5 +++-- lib/gfx/GUI_DEV/DEV_Config.h | 6 +++-- lib/gfx/LCD/LCD_Driver.c | 43 +++++++++++++++++++++++++++++------- lib/gfx/LCD/LCD_Driver.h | 8 ++++--- 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/lib/gfx/GUI_DEV/DEV_Config.c b/lib/gfx/GUI_DEV/DEV_Config.c index 881b9eeb..5c1e4b22 100644 --- a/lib/gfx/GUI_DEV/DEV_Config.c +++ b/lib/gfx/GUI_DEV/DEV_Config.c @@ -39,10 +39,11 @@ static spi_req_t req = {.rx_data = NULL, .bits=8, .width = SPI17Y_WIDTH_1, .ssel = 0, .deass = 1, .ssel_pol = SPI17Y_POL_LOW, .tx_num = 0, .rx_num = 0}; /********************************************************************************/ -void lcd_write(uint8_t *data, int size) +void lcd_write(uint8_t *data, int size, lcd_write_cb_t wr_callback) { req.tx_data = data; req.len = size; - SPI_MasterTrans(SPI, &req); + req.callback = wr_callback; + SPI_MasterTransAsync(SPI, &req); } diff --git a/lib/gfx/GUI_DEV/DEV_Config.h b/lib/gfx/GUI_DEV/DEV_Config.h index 64487005..5e4ed5f7 100644 --- a/lib/gfx/GUI_DEV/DEV_Config.h +++ b/lib/gfx/GUI_DEV/DEV_Config.h @@ -43,6 +43,8 @@ #define UWORD uint16_t #define UDOUBLE uint32_t +typedef spi_callback_fn lcd_write_cb_t; + /** * GPIO config **/ @@ -57,9 +59,9 @@ extern const gpio_cfg_t DEV_DC_PIN; /** * SPI **/ -void lcd_write(uint8_t* data, int size); +void lcd_write(uint8_t* data, int size, lcd_write_cb_t wr_callback); void display_set_reset_pin(uint8_t state); -#define DEV_SPI_WRITE(_dat) lcd_write(&_dat, 1) +#define DEV_SPI_WRITE(_dat) lcd_write(&_dat, 1, NULL) #define DEV_RESET_LOW() display_set_reset_pin(0) #define DEV_RESET_HIGH() display_set_reset_pin(1) /** diff --git a/lib/gfx/LCD/LCD_Driver.c b/lib/gfx/LCD/LCD_Driver.c index 7cc1d15f..a75582d3 100644 --- a/lib/gfx/LCD/LCD_Driver.c +++ b/lib/gfx/LCD/LCD_Driver.c @@ -28,7 +28,27 @@ # ******************************************************************************/ #include "LCD_Driver.h" -static uint8_t screen[LCD_HEIGHT][LCD_WIDTH][2]; + +typedef union { + uint8_t fb[LCD_HEIGHT][LCD_WIDTH][2]; + uint8_t raw[LCD_HEIGHT * LCD_WIDTH * 2]; +} frame_t; + +static frame_t frames[2]; +static uint8_t active_frame; +static uint8_t update_in_progress; + +#define FRAME_SIZE sizeof(frames[0]) + +static inline frame_t *frame(void) +{ + return &frames[active_frame]; +} + +static void update_cb(void *spi_req, int error_code) +{ + update_in_progress = 0; +} /******************************************************************************* function: @@ -197,7 +217,7 @@ parameter : Xend : End UWORD coordinates Yend : End UWORD coordinatesen ******************************************************************************/ -void LCD_SetCursor(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend) +static void LCD_SetCursor(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend) { Xstart = Xstart + 1; Xend = Xend + 1; @@ -289,8 +309,8 @@ void LCD_SetUWORD(UWORD x, UWORD y, UWORD Color) void LCD_SetUWORD(UWORD x, UWORD y, UWORD Color) { - screen[y][x][0] = (Color >> 8); - screen[y][x][1] = (Color & 0xFF); + frame()->fb[y][x][0] = (Color >> 8); + frame()->fb[y][x][1] = (Color & 0xFF); } void LCD_Clear(UWORD Color) @@ -303,14 +323,21 @@ void LCD_Clear(UWORD Color) } } -void LCD_Set(uint8_t *data, int len) +static void LCD_Set(uint8_t *data, int len) { LCD_SetCursor(0, 0, 160 - 1, 80 - 1); DEV_Digital_Write(DEV_DC_PIN, 1); - lcd_write(data, len); + update_in_progress = 1; + lcd_write(data, len, update_cb); } -void LCD_Update(void) +int LCD_Update(void) { - LCD_Set((uint8_t *)screen, sizeof(screen)); + if (update_in_progress) + return 1; + + LCD_Set(frame()->raw, FRAME_SIZE); + active_frame = !active_frame; + return 0; } + diff --git a/lib/gfx/LCD/LCD_Driver.h b/lib/gfx/LCD/LCD_Driver.h index 54980b0c..6e4f3ed9 100644 --- a/lib/gfx/LCD/LCD_Driver.h +++ b/lib/gfx/LCD/LCD_Driver.h @@ -40,7 +40,6 @@ void LCD_WriteData_Byte(UBYTE da); void LCD_WriteData_Word(UWORD da); void LCD_WriteReg(UBYTE da); -void LCD_SetCursor(UWORD x1, UWORD y1, UWORD x2,UWORD y2); void LCD_SetUWORD(UWORD x, UWORD y, UWORD Color); void LCD_Init(void); @@ -48,7 +47,10 @@ void LCD_SetBacklight(UWORD Value); void LCD_Clear(UWORD Color); void LCD_ClearWindow(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend, UWORD UWORD); -void LCD_Set(uint8_t *data, int len); -void LCD_Update(void); +/* + * return value: 0 - asynchronous update was scheduled + * 1 - an update was already in progress + */ +int LCD_Update(void); #endif -- GitLab