Last active
September 17, 2020 01:55
-
-
Save C47D/fb6e4a07fc64434c94004ddd646a1d8b to your computer and use it in GitHub Desktop.
Prototype implementation of an "platform-agnostic" lv_drivers for LVGL.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @file disp_spi.c | |
* | |
*/ | |
/********************* | |
* INCLUDES | |
*********************/ | |
#include <string.h> | |
#include "lvgl/lvgl.h" | |
#include "disp_spi.h" | |
#include "spi_dma.h" | |
/********************* | |
* DEFINES | |
*********************/ | |
#define TAG "disp_spi" | |
/********************** | |
* TYPEDEFS | |
**********************/ | |
/********************** | |
* STATIC PROTOTYPES | |
**********************/ | |
/********************** | |
* STATIC VARIABLES | |
**********************/ | |
static volatile disp_spi_send_flag_t spi_flags = 0; | |
/********************** | |
* MACROS | |
**********************/ | |
/********************** | |
* GLOBAL FUNCTIONS | |
**********************/ | |
void display_spi_transaction(const uint8_t *data, uint16_t length, | |
disp_spi_send_flag_t flags, disp_spi_read_data *out, | |
uint64_t addr) | |
{ | |
(void) addr; | |
(void) out; | |
if (0 == length) { | |
return; | |
} | |
spi_flags = flags; | |
/* Wait for previous pending transaction results */ | |
display_tl_poll_is_busy(); | |
if (flags & DISP_SPI_RECEIVE) { | |
} | |
if (flags & DISP_SPI_ADDRESS_24) { | |
} | |
/* Poll/Complete/Queue transaction */ | |
if (flags & DISP_SPI_SEND_POLLING) { | |
// NOTE: Platform dependent | |
send_spi(data, (size_t) length); | |
} else if (flags & DISP_SPI_SEND_SYNCHRONOUS) { | |
} else { | |
// NOTE: Platform dependent | |
send_spi_dma(data, NULL, (size_t) length); | |
} | |
} | |
void display_tl_poll_is_busy(void) | |
{ | |
while (spi_xfer_is_ongoing()) { | |
} | |
} | |
void display_spi_acquire(void) | |
{ | |
} | |
void display_spi_release(void) | |
{ | |
} | |
/********************** | |
* STATIC FUNCTIONS | |
**********************/ | |
/* Called on the spi complete callback */ | |
void display_colors_sent_notification(void) | |
{ | |
if (spi_flags & DISP_SPI_SIGNAL_FLUSH) { | |
lv_disp_t * disp = NULL; | |
#if (LVGL_VERSION_MAJOR >= 7) | |
disp = _lv_refr_get_disp_refreshing(); | |
#else /* Before v7 */ | |
disp = lv_refr_get_disp_refreshing(); | |
#endif | |
lv_disp_flush_ready(&disp->driver); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @file disp_spi.h | |
* | |
*/ | |
#ifndef DISP_SPI_H | |
#define DISP_SPI_H | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
/********************* | |
* INCLUDES | |
*********************/ | |
#include <stdint.h> | |
#include <stdbool.h> | |
#include <stddef.h> | |
/********************* | |
* DEFINES | |
*********************/ | |
/********************** | |
* TYPEDEFS | |
**********************/ | |
typedef enum _disp_spi_send_flag_t { | |
DISP_SPI_SEND_QUEUED = 0x00000000, | |
DISP_SPI_SEND_POLLING = 0x00000001, | |
DISP_SPI_SEND_SYNCHRONOUS = 0x00000002, | |
DISP_SPI_SIGNAL_FLUSH = 0x00000004, | |
DISP_SPI_RECEIVE = 0x00000008, | |
DISP_SPI_CMD_8 = 0x00000010, /* Reserved */ | |
DISP_SPI_CMD_16 = 0x00000020, /* Reserved */ | |
DISP_SPI_ADDRESS_8 = 0x00000040, /* Reserved */ | |
DISP_SPI_ADDRESS_16 = 0x00000080, /* Reserved */ | |
DISP_SPI_ADDRESS_24 = 0x00000100, /* Reserved */ | |
DISP_SPI_ADDRESS_32 = 0x00000200, /* Reserved */ | |
DISP_SPI_MODE_DIO = 0x00000400, /* Reserved */ | |
DISP_SPI_MODE_QIO = 0x00000800, /* Reserved */ | |
DISP_SPI_MODE_DIOQIO_ADDR = 0x00001000, /* Reserved */ | |
} disp_spi_send_flag_t; | |
typedef struct _disp_spi_read_data { | |
uint8_t _dummy_byte; | |
union { | |
uint8_t byte; | |
uint16_t word; | |
uint32_t dword; | |
} __attribute__((packed)); | |
} disp_spi_read_data __attribute__((aligned(4))); | |
/********************** | |
* GLOBAL PROTOTYPES | |
**********************/ | |
void display_spi_transaction(const uint8_t *data, uint16_t length, | |
disp_spi_send_flag_t flags, disp_spi_read_data *out, uint64_t addr); | |
void display_tl_poll_is_busy(void); | |
inline void display_tl_send_data(uint8_t *data, uint16_t length) { | |
display_spi_transaction(data, length, DISP_SPI_SEND_POLLING, NULL, 0); | |
} | |
inline void display_tl_send_colors(uint8_t *data, uint16_t length) { | |
display_spi_transaction(data, length, | |
DISP_SPI_SEND_QUEUED | DISP_SPI_SIGNAL_FLUSH, | |
NULL, 0); | |
} | |
/* NOTE: Both functions can be used in a OSAL layer */ | |
void display_spi_acquire(void); | |
void display_spi_release(void); | |
/* Called when the async data has been sent */ | |
void display_colors_sent_notification(void); | |
/********************** | |
* MACROS | |
**********************/ | |
/* Receive data helpers */ | |
#define member_size(type, member) sizeof(((type *)0)->member) | |
#define SPI_READ_DUMMY_LEN member_size(disp_spi_read_data, _dummy_byte) | |
#define SPI_READ_BYTE_LEN (SPI_READ_DUMMY_LEN + member_size(disp_spi_read_data, byte)) | |
#define SPI_READ_WORD_LEN (SPI_READ_DUMMY_LEN + member_size(disp_spi_read_data, word)) | |
#define SPI_READ_DWORD_LEN (SPI_READ_DUMMY_LEN + member_size(disp_spi_read_data, dword)) | |
#ifdef __cplusplus | |
} /* extern "C" */ | |
#endif | |
#endif /*DISP_SPI_H*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef DRIVER_GENERIC_H | |
#define DRIVER_GENERIC_H | |
#include <stdint.h> | |
#include <stddef.h> | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
/********************* | |
* INCLUDES | |
*********************/ | |
#include "lvgl/lvgl.h" | |
typedef enum { | |
DATA_MODE_CMD, | |
DATA_MODE_DATA, | |
} data_mode_t; | |
typedef enum { | |
DISPLAY_BACKLIGHT_CONTROL_DISABLE, | |
DISPLAY_BACKLIGHT_CONTROL_ENABLE, | |
} display_backlight_control_t; | |
typedef struct { | |
void (*display_backlight_control)(lv_disp_drv_t *drv, display_backlight_control_t backlight_control); | |
void (*data_mode)(lv_disp_drv_t *drv, data_mode_t mode); | |
void (*delay_ms)(lv_disp_drv_t *drv, uint32_t ms); | |
void (*write_blocking)(const uint8_t *tx_data, const size_t size); | |
void (*write_async)(const uint8_t *tx_data, uint8_t *rx_data, const size_t size); | |
void (*hw_reset)(lv_disp_drv_t *drv); | |
} driver_generic_t; | |
#ifdef __cplusplus | |
} /* extern "C" */ | |
#endif | |
#endif /* DRIVER_GENERIC_H */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @file ili9341.c | |
*/ | |
/********************* | |
* INCLUDES | |
*********************/ | |
#include "ili9341.h" | |
#include "disp_spi.h" | |
/********************* | |
* DEFINES | |
*********************/ | |
#define DRIVER_NAME "ILI9341" | |
/********************** | |
* TYPEDEFS | |
**********************/ | |
/* The LCD needs a bunch of command/argument values to be initialized. | |
* They are stored in this struct. */ | |
typedef struct { | |
uint8_t cmd; | |
uint8_t data[16]; | |
/* No of data in data; bit 7 = delay after set; 0xFF = end of cmds. */ | |
uint8_t databytes; | |
} lcd_init_cmd_t; | |
/********************** | |
* STATIC PROTOTYPES | |
**********************/ | |
static inline void ili9341_set_mode(lv_disp_drv_t *drv, data_mode_t mode); | |
static void ili9341_set_orientation(lv_disp_drv_t *drv, uint8_t orientation); | |
static void ili9341_send_cmd(lv_disp_drv_t *drv, uint8_t cmd); | |
static void ili9341_send_data(lv_disp_drv_t *drv, void *data, uint16_t length); | |
/* Sending color data to the display can be both blocking and async, but is | |
* better to use async. When we're done sending color data we need to call | |
* lv_disp_flush_ready(&disp->driver) */ | |
static void ili9341_send_color(lv_disp_drv_t *drv, void *data, uint16_t length); | |
/********************** | |
* STATIC VARIABLES | |
**********************/ | |
/********************** | |
* MACROS | |
**********************/ | |
/********************** | |
* GLOBAL FUNCTIONS | |
**********************/ | |
void ili9341_init(lv_disp_drv_t * drv) | |
{ | |
driver_generic_t *driver = (driver_generic_t *) drv->user_data; | |
/* Display initialization descriptor */ | |
lcd_init_cmd_t ili_init_cmds[] = { | |
{0xCF, {0x00, 0x83, 0X30}, 3}, | |
{0xED, {0x64, 0x03, 0X12, 0X81}, 4}, | |
{0xE8, {0x85, 0x01, 0x79}, 3}, | |
{0xCB, {0x39, 0x2C, 0x00, 0x34, 0x02}, 5}, | |
{0xF7, {0x20}, 1}, | |
{0xEA, {0x00, 0x00}, 2}, | |
{ILI9341_REG_PWCTRL1, {0x26}, 1}, | |
{ILI9341_REG_PWCTRL2, {0x11}, 1}, | |
{ILI9341_REG_VMCTRL1, {0x35, 0x3E}, 2}, | |
{ILI9341_REG_VMCTRL2, {0xBE}, 1}, | |
{ILI9341_REG_MADCTL, {0x28}, 1}, | |
{ILI9341_REG_PIXSET, {0x55}, 1}, | |
{ILI9341_REG_FRMCTR1, {0x00, 0x1B}, 2}, | |
{0xF2, {0x08}, 1}, | |
{ILI9341_REG_GAMSET, {0x01}, 1}, | |
{ILI9341_REG_PGAMCTRL, {0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0X87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00}, 15}, | |
{ILI9341_REG_NGAMCTRL, {0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F}, 15}, | |
{ILI9341_REG_CASET, {0x00, 0x00, 0x00, 0xEF}, 4}, | |
{ILI9341_REG_PASET, {0x00, 0x00, 0x01, 0x3f}, 4}, | |
{ILI9341_REG_RAMWR, {0}, 0}, | |
{ILI9341_REG_ETMOD, {0x07}, 1}, | |
{ILI9341_REG_DISCTRL, {0x0A, 0x82, 0x27, 0x00}, 4}, | |
{ILI9341_REG_SLPOUT, {0}, 0x80}, | |
{ILI9341_REG_DISPON, {0}, 0x80}, | |
{0, {0}, 0xff}, | |
}; | |
/* Reset the display. | |
* TODO: Software reset when no hardware nRST is available */ | |
driver->hw_reset(drv); | |
/* Send the display initialization descriptor */ | |
uint16_t cmd = 0; | |
while (ili_init_cmds[cmd].databytes != 0xff) { | |
ili9341_send_cmd(drv, ili_init_cmds[cmd].cmd); | |
ili9341_send_data(drv, ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F); | |
if (ili_init_cmds[cmd].databytes & 0x80) { | |
driver->delay_ms(drv, 100); | |
} | |
cmd++; | |
} | |
ili9341_enable_backlight(drv, DISPLAY_BACKLIGHT_CONTROL_ENABLE); | |
/* Landscape */ | |
ili9341_set_orientation(drv, 2); | |
ili9341_send_cmd(drv, ILI9341_REG_DINVOFF); | |
} | |
void ili9341_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map) | |
{ | |
uint8_t data[4] = {0}; | |
uint32_t pixels_to_update = lv_area_get_width(area) * lv_area_get_height(area); | |
/* times two because each pixel is 2 bytes when LV_COLOR_DEPTH is set to RGB565 */ | |
uint32_t bytes_to_send = pixels_to_update * 2; | |
/*Column addresses*/ | |
data[0] = (area->x1 >> 8) & 0xFF; | |
data[1] = area->x1 & 0xFF; | |
data[2] = (area->x2 >> 8) & 0xFF; | |
data[3] = area->x2 & 0xFF; | |
ili9341_send_cmd(drv, ILI9341_REG_CASET); | |
ili9341_send_data(drv, data, 4); | |
/*Page addresses*/ | |
data[0] = (area->y1 >> 8) & 0xFF; | |
data[1] = area->y1 & 0xFF; | |
data[2] = (area->y2 >> 8) & 0xFF; | |
data[3] = area->y2 & 0xFF; | |
ili9341_send_cmd(drv, ILI9341_REG_PASET); | |
ili9341_send_data(drv, data, 4); | |
/*Memory write*/ | |
ili9341_send_cmd(drv, ILI9341_REG_RAMWR); | |
ili9341_send_color(drv, (void*) color_map, bytes_to_send); | |
} | |
/* TODO: How we can check if the driver_generic_t have an display_backlight_control | |
* callback registered. */ | |
void ili9341_enable_backlight(lv_disp_drv_t *drv, display_backlight_control_t backlight_en) | |
{ | |
driver_generic_t *driver = (driver_generic_t *) drv->user_data; | |
driver->display_backlight_control(drv, backlight_en); | |
} | |
void ili9341_sleep_in(lv_disp_drv_t *drv) | |
{ | |
uint8_t data[] = {0x08}; | |
ili9341_send_cmd(drv, ILI9341_REG_SLPIN); | |
ili9341_send_data(drv, &data, 1); | |
} | |
void ili9341_sleep_out(lv_disp_drv_t *drv) | |
{ | |
uint8_t data[] = {0x08}; | |
ili9341_send_cmd(drv, ILI9341_REG_SLPOUT); | |
ili9341_send_data(drv, &data, 1); | |
} | |
/********************** | |
* STATIC FUNCTIONS | |
**********************/ | |
/* NOTE: | |
* This is a blocking function, so maybe we could rename display_tl_send_data to | |
* display_tl_send_blocking. */ | |
static void ili9341_send_cmd(lv_disp_drv_t *drv, uint8_t cmd) | |
{ | |
display_tl_poll_is_busy(); | |
ili9341_set_mode(drv, DATA_MODE_CMD); | |
display_tl_send_data(&cmd, 1); | |
} | |
/* NOTE: | |
* This is a blocking function, so maybe we could rename display_tl_send_data to | |
* display_tl_send_blocking. */ | |
static void ili9341_send_data(lv_disp_drv_t *drv, void * data, uint16_t length) | |
{ | |
display_tl_poll_is_busy(); | |
ili9341_set_mode(drv, DATA_MODE_DATA); | |
display_tl_send_data(data, length); | |
} | |
/* NOTE: | |
* In this case it's better to send the data in async mode (because we send the | |
* pixel color information), so maybe we could rename display_tl_send_colors to | |
* display_tl_send_async. */ | |
static void ili9341_send_color(lv_disp_drv_t *drv, void *data, uint16_t length) | |
{ | |
display_tl_poll_is_busy(); | |
ili9341_set_mode(drv, DATA_MODE_DATA); | |
display_tl_send_colors(data, length); | |
} | |
static void ili9341_set_orientation(lv_disp_drv_t *drv, uint8_t orientation) | |
{ | |
(void) drv; | |
uint8_t orientation_code[] = { | |
0x48, /* Portrait */ | |
0x88, /* Portrait inverted */ | |
0x28, /* Landscape */ | |
0xE8 /* Landscape inverted */ | |
}; | |
ili9341_send_cmd(drv, ILI9341_REG_MADCTL); | |
ili9341_send_data(drv, (void *) &orientation_code[orientation], 1); | |
} | |
static inline void ili9341_set_mode(lv_disp_drv_t *drv, data_mode_t mode) | |
{ | |
driver_generic_t *driver = (driver_generic_t *) drv->user_data; | |
driver->data_mode(drv, mode); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @file ILI9341.h | |
*/ | |
#ifndef ILI9341_H | |
#define ILI9341_H | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
/********************* | |
* INCLUDES | |
*********************/ | |
#include "lvgl/lvgl.h" | |
/* Maybe rename to lv_driver_generic */ | |
#include "driver_generic.h" | |
/********************* | |
* DEFINES | |
*********************/ | |
#define ILI9341_REG_SLPIN (0x10U) | |
#define ILI9341_REG_SLPOUT (0x11U) | |
#define ILI9341_REG_DINVOFF (0x20U) | |
#define ILI9341_REG_GAMSET (0x26U) | |
#define ILI9341_REG_DISPON (0x29U) | |
#define ILI9341_REG_CASET (0x2AU) | |
#define ILI9341_REG_PASET (0x2BU) | |
#define ILI9341_REG_RAMWR (0x2CU) | |
#define ILI9341_REG_MADCTL (0x36U) | |
#define ILI9341_REG_PIXSET (0x3AU) | |
#define ILI9341_REG_FRMCTR1 (0xB1U) | |
#define ILI9341_REG_DISCTRL (0xB6U) | |
#define ILI9341_REG_ETMOD (0xB7U) | |
#define ILI9341_REG_PWCTRL1 (0xC0U) | |
#define ILI9341_REG_PWCTRL2 (0xC1U) | |
#define ILI9341_REG_VMCTRL1 (0xC5U) | |
#define ILI9341_REG_VMCTRL2 (0xC7U) | |
#define ILI9341_REG_PGAMCTRL (0xE0U) | |
#define ILI9341_REG_NGAMCTRL (0xE1U) | |
/********************** | |
* TYPEDEFS | |
**********************/ | |
/********************** | |
* GLOBAL PROTOTYPES | |
**********************/ | |
void ili9341_init(lv_disp_drv_t *drv); | |
void ili9341_flush(lv_disp_drv_t *drv, const lv_area_t * area, lv_color_t * color_map); | |
void ili9341_enable_backlight(lv_disp_drv_t *drv, display_backlight_control_t backlight_en); | |
void ili9341_sleep_in(lv_disp_drv_t *drv); | |
void ili9341_sleep_out(lv_disp_drv_t *drv); | |
/********************** | |
* MACROS | |
**********************/ | |
#ifdef __cplusplus | |
} /* extern "C" */ | |
#endif | |
#endif /*ILI9341_H*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "project.h" | |
#include <stdbool.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include "lvgl/lvgl.h" | |
#include "ili9341.h" | |
#include "spi_dma.h" | |
#include "disp_spi.h" | |
#include "driver_generic.h" | |
#include "psoc_platform.h" | |
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) | |
#define DISPLAY_BUFFER_SIZE (LV_HOR_RES_MAX * 10) | |
enum { FEED_FORM_CMD = 0x0C }; | |
CY_ISR(spi_tx_dma_done); | |
CY_ISR(spi_tx_isr_handler); | |
CY_ISR(timer_tick_handler); | |
/* This struct is passed as lv_disp_drv_t.user_data, you should "register" | |
* your platform specific functions in here. */ | |
driver_generic_t ili9341_driver = { | |
.display_backlight_control = psoc_display_backlight_control, | |
.data_mode = psoc_data_mode, | |
.delay_ms = psoc_delay_ms, | |
.hw_reset = psoc_hw_reset | |
}; | |
int main(void) | |
{ | |
isr_SPI_TX_DMA_StartEx(spi_tx_dma_done); | |
isr_SPI_TX_StartEx(spi_tx_isr_handler); | |
isr_Timer_StartEx(timer_tick_handler); | |
CyGlobalIntEnable; | |
UART_Start(); | |
SPI_Start(); | |
spi_initialize_dma(); | |
lv_init(); | |
static lv_color_t buf1[DISPLAY_BUFFER_SIZE]; | |
static lv_color_t buf2[DISPLAY_BUFFER_SIZE]; | |
static lv_disp_buf_t disp_buf; | |
lv_disp_buf_init(&disp_buf, buf1, buf2, DISPLAY_BUFFER_SIZE); | |
lv_disp_drv_t disp_drv; | |
lv_disp_drv_init(&disp_drv); | |
disp_drv.flush_cb = ili9341_flush; | |
disp_drv.buffer = &disp_buf; | |
disp_drv.user_data = &ili9341_driver; | |
lv_disp_drv_register(&disp_drv); | |
ili9341_init(&disp_drv); | |
Timer_Start(); | |
lv_obj_t *scr = lv_disp_get_scr_act(NULL); | |
lv_obj_t *label = lv_label_create(scr, NULL); | |
lv_label_set_text(label, "Protect DJ Smokey at all costs!"); | |
lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, 0); | |
for(;;) | |
{ | |
CyDelay(1); | |
lv_task_handler(); | |
} | |
} | |
void timer_tick_handler(void) | |
{ | |
lv_tick_inc(1); | |
LV_TICK_Write(~LV_TICK_Read()); | |
Timer_ReadStatusRegister(); | |
} | |
/* NOTE: The DMA done interrupt is being triggered when the DMA is done | |
* transferring data into the SPI TX FIFO, this means it's gets triggered | |
* even when the SPI TX FIFO still holds the last 4 byte of data. | |
* | |
* To know when spi is actually done transfering the data we can enable | |
* the SPI_INT_ON_SPI_DONE (and SPI_INT_ON_TX_NOT_FULL). */ | |
void spi_tx_dma_done(void) | |
{ | |
spi_xfer_set_status(SPI_XFER_DONE); | |
SPI_SetTxInterruptMode((0u << SPI_STS_TX_FIFO_NOT_FULL_SHIFT) | (1u << SPI_STS_SPI_DONE_SHIFT)); | |
} | |
/* SPI interrupt handler */ | |
void spi_tx_isr_handler(void) | |
{ | |
/* Clear the interrupt source flag */ | |
volatile uint8_t spi_tx_sts = SPI_ReadTxStatus(); | |
/* If the DMA is done and we get the SPI_STS_SPI_DONE interrupt then | |
* the SPI FIFO is empty. */ | |
if ((SPI_XFER_DONE == spi_xfer_get_status()) && (SPI_STS_SPI_DONE & spi_tx_sts)) { | |
SS_Write(1); | |
/* Data transfer is done, we can disable SPI interrupts */ | |
SPI_SetTxInterruptMode(0); | |
spi_xfer_on_completion(); | |
/* Let LVGL the flush has been finished */ | |
display_colors_sent_notification(); | |
} | |
} | |
/* [] END OF FILE */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "driver_generic.h" | |
#include "DISP_DC.h" | |
#include "DISP_RST.h" | |
#include "DISP_BCKL.h" | |
#include "UART.h" | |
#include "CyLib.h" | |
void psoc_display_backlight_control(lv_disp_drv_t *drv, display_backlight_control_t backlight_control) | |
{ | |
(void) drv; | |
DISP_BCKL_Write(DISPLAY_BACKLIGHT_CONTROL_ENABLE == backlight_control ? 1 : 0); | |
} | |
void psoc_data_mode(lv_disp_drv_t *drv, data_mode_t mode) | |
{ | |
(void) drv; | |
if (DATA_MODE_CMD == mode) { | |
DISP_DC_Write(0); | |
} else { | |
DISP_DC_Write(1); | |
} | |
} | |
void psoc_delay_ms(lv_disp_drv_t *drv, uint32_t ms) | |
{ | |
(void) drv; | |
CyDelay(ms); | |
} | |
void psoc_write_blocking(const uint8_t *tx_data, const size_t size) | |
{ | |
} | |
void psoc_write_async(const uint8_t *tx_data, uint8_t *rx_data, const size_t size) | |
{ | |
} | |
void psoc_hw_reset(lv_disp_drv_t *drv) | |
{ | |
(void) drv; | |
DISP_RST_Write(0); | |
CyDelay(100); | |
DISP_RST_Write(1); | |
CyDelay(100); | |
} | |
/* [] END OF FILE */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef PSOC_PLATFORM_H | |
#define PSOC_PLATFORM_H | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
/********************* | |
* INCLUDES | |
*********************/ | |
#include "lvgl/lvgl.h" | |
#include "driver_generic.h" | |
void psoc_display_backlight_control(lv_disp_drv_t *drv, display_backlight_control_t backlight_control); | |
void psoc_data_mode(lv_disp_drv_t *drv, data_mode_t mode); | |
void psoc_delay_ms(lv_disp_drv_t *drv, uint32_t ms); | |
void psoc_write_blocking(const uint8_t *tx_data, const size_t size); | |
void psoc_write_async(const uint8_t *tx_data, uint8_t *rx_data, const size_t size); | |
void psoc_hw_reset(lv_disp_drv_t *drv); | |
#ifdef __cplusplus | |
} /* extern "C" */ | |
#endif | |
#endif /* PSOC_PLATFORM_H */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is meant to be a draft of an "platform-agnostic" lv_driver arch, it's somewhat based on the work done by zladay with the lvgl_esp32_drivers.
How does it works:
The user fills an
driver_generic_t
object with callbacks to some platform specific code, this object is passed asuser_data
in thelv_disp_drv_t
struct, so we need to enableLV_USE_USER_DATA
inlv_conf.h
.The user callbacks are called from the display specific, in this case the
ili9341
display driver. Inside this driver we send the data through atransport layer
so the display doesn't care if the display is connected to the MCU via SPI, I2C, parallel, etc. Thedisplay_tl
layer is currently nameddisp_spi
.User (MCU) specific code.
The only files with platform specific code is
psoc_platform
header and source file. For now we currently need to provide the following callbacks:write_blocking
andwrite_async
will be used by thetl
, not yet implemented.TODO
device
, so it handle rotation of display and touch devices automatically.