mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-28 07:03:00 +08:00
184 lines
6.3 KiB
C
184 lines
6.3 KiB
C
/**
|
|
* @file lv_port_lcd_stm32_template.c
|
|
*
|
|
* Example implementation of the LVGL LCD display drivers on the STM32 platform
|
|
*/
|
|
|
|
/*Copy this file as "lv_port_disp.c" and set this value to "1" to enable content*/
|
|
#if 0
|
|
|
|
/*********************
|
|
* INCLUDES
|
|
*********************/
|
|
/* Include STM32Cube files here, e.g.:
|
|
#include "stm32f7xx_hal.h"
|
|
*/
|
|
|
|
#include "lv_port_disp.h"
|
|
#include "./src/drivers/display/st7789/lv_st7789.h"
|
|
|
|
/*********************
|
|
* DEFINES
|
|
*********************/
|
|
#ifndef MY_DISP_HOR_RES
|
|
#warning Please define or replace the macro MY_DISP_HOR_RES with the actual screen width, default value 320 is used for now.
|
|
#define MY_DISP_HOR_RES 320
|
|
#endif
|
|
|
|
#ifndef MY_DISP_VER_RES
|
|
#warning Please define or replace the macro MY_DISP_VER_RES with the actual screen height, default value 240 is used for now.
|
|
#define MY_DISP_VER_RES 240
|
|
#endif
|
|
|
|
#define BUS_SPI1_POLL_TIMEOUT 0x1000U
|
|
|
|
/**********************
|
|
* TYPEDEFS
|
|
**********************/
|
|
|
|
/**********************
|
|
* STATIC PROTOTYPES
|
|
**********************/
|
|
static void lcd_color_transfer_ready_cb(SPI_HandleTypeDef * hspi);
|
|
static int32_t lcd_io_init(void);
|
|
static void lcd_send_cmd(lv_display_t * disp, const uint8_t * cmd, size_t cmd_size, const uint8_t * param,
|
|
size_t param_size);
|
|
static void lcd_send_color(lv_display_t * disp, const uint8_t * cmd, size_t cmd_size, uint8_t * param,
|
|
size_t param_size);
|
|
|
|
/**********************
|
|
* STATIC VARIABLES
|
|
**********************/
|
|
static lv_display_t * lcd_disp;
|
|
static volatile int lcd_bus_busy = 0;
|
|
|
|
/**********************
|
|
* MACROS
|
|
**********************/
|
|
|
|
/**********************
|
|
* GLOBAL FUNCTIONS
|
|
**********************/
|
|
|
|
void lv_port_display_init(void)
|
|
{
|
|
/* Initialize LCD I/O */
|
|
if(lcd_io_init() != 0)
|
|
return;
|
|
|
|
/* Create the LVGL display object and the ST7789 LCD display driver */
|
|
lcd_disp = lv_st7789_create(MY_DISP_HOR_RES, MY_DISP_VER_RES, LV_LCD_FLAG_NONE, lcd_send_cmd, lcd_send_color);
|
|
lv_display_set_rotation(lcd_disp, LV_DISPLAY_ROTATION_270); /* set landscape orientation */
|
|
|
|
/* Example: two dynamically allocated buffers for partial rendering */
|
|
uint8_t * buf1 = NULL;
|
|
uint8_t * buf2 = NULL;
|
|
|
|
uint32_t buf_size = MY_DISP_HOR_RES * MY_DISP_VER_RES / 10 * lv_color_format_get_size(lv_display_get_color_format(
|
|
lcd_disp));
|
|
|
|
buf1 = lv_malloc(buf_size);
|
|
if(buf1 == NULL) {
|
|
LV_LOG_ERROR("display draw buffer malloc failed");
|
|
return;
|
|
}
|
|
|
|
buf2 = lv_malloc(buf_size);
|
|
if(buf2 == NULL) {
|
|
LV_LOG_ERROR("display buffer malloc failed");
|
|
lv_free(buf1);
|
|
return;
|
|
}
|
|
lv_display_set_buffers(lcd_disp, buf1, buf2, buf_size, LV_DISPLAY_RENDER_MODE_PARTIAL);
|
|
}
|
|
|
|
/**********************
|
|
* STATIC FUNCTIONS
|
|
**********************/
|
|
|
|
/* Callback is called when background transfer finished */
|
|
static void lcd_color_transfer_ready_cb(SPI_HandleTypeDef * hspi)
|
|
{
|
|
/* CS high */
|
|
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET);
|
|
lcd_bus_busy = 0;
|
|
lv_display_flush_ready(lcd_disp);
|
|
}
|
|
|
|
/* Initialize LCD I/O bus, reset LCD */
|
|
static int32_t lcd_io_init(void)
|
|
{
|
|
/* Register SPI Tx Complete Callback */
|
|
HAL_SPI_RegisterCallback(&hspi1, HAL_SPI_TX_COMPLETE_CB_ID, lcd_color_transfer_ready_cb);
|
|
|
|
/* reset LCD */
|
|
HAL_GPIO_WritePin(LCD_RESET_GPIO_Port, LCD_RESET_Pin, GPIO_PIN_RESET);
|
|
HAL_Delay(100);
|
|
HAL_GPIO_WritePin(LCD_RESET_GPIO_Port, LCD_RESET_Pin, GPIO_PIN_SET);
|
|
HAL_Delay(100);
|
|
|
|
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET);
|
|
HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_SET);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/* Platform-specific implementation of the LCD send command function. In general this should use polling transfer. */
|
|
static void lcd_send_cmd(lv_display_t * disp, const uint8_t * cmd, size_t cmd_size, const uint8_t * param,
|
|
size_t param_size)
|
|
{
|
|
LV_UNUSED(disp);
|
|
while(lcd_bus_busy); /* wait until previous transfer is finished */
|
|
/* Set the SPI in 8-bit mode */
|
|
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
|
|
HAL_SPI_Init(&hspi1);
|
|
/* DCX low (command) */
|
|
HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_RESET);
|
|
/* CS low */
|
|
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET);
|
|
/* send command */
|
|
if(HAL_SPI_Transmit(&hspi1, cmd, cmd_size, BUS_SPI1_POLL_TIMEOUT) == HAL_OK) {
|
|
/* DCX high (data) */
|
|
HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_SET);
|
|
/* for short data blocks we use polling transfer */
|
|
HAL_SPI_Transmit(&hspi1, (uint8_t *)param, (uint16_t)param_size, BUS_SPI1_POLL_TIMEOUT);
|
|
/* CS high */
|
|
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET);
|
|
}
|
|
}
|
|
|
|
/* Platform-specific implementation of the LCD send color function. For better performance this should use DMA transfer.
|
|
* In case of a DMA transfer a callback must be installed to notify LVGL about the end of the transfer.
|
|
*/
|
|
static void lcd_send_color(lv_display_t * disp, const uint8_t * cmd, size_t cmd_size, uint8_t * param,
|
|
size_t param_size)
|
|
{
|
|
LV_UNUSED(disp);
|
|
while(lcd_bus_busy); /* wait until previous transfer is finished */
|
|
/* Set the SPI in 8-bit mode */
|
|
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
|
|
HAL_SPI_Init(&hspi1);
|
|
/* DCX low (command) */
|
|
HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_RESET);
|
|
/* CS low */
|
|
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET);
|
|
/* send command */
|
|
if(HAL_SPI_Transmit(&hspi1, cmd, cmd_size, BUS_SPI1_POLL_TIMEOUT) == HAL_OK) {
|
|
/* DCX high (data) */
|
|
HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_SET);
|
|
/* for color data use DMA transfer */
|
|
/* Set the SPI in 16-bit mode to match endianness */
|
|
hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
|
|
HAL_SPI_Init(&hspi1);
|
|
lcd_bus_busy = 1;
|
|
HAL_SPI_Transmit_DMA(&hspi1, param, (uint16_t)param_size / 2);
|
|
/* NOTE: CS will be reset in the transfer ready callback */
|
|
}
|
|
}
|
|
|
|
#else /*Enable this file at the top*/
|
|
|
|
/*This dummy typedef exists purely to silence -Wpedantic.*/
|
|
typedef int keep_pedantic_happy;
|
|
#endif
|