mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-16 23:05:38 +00:00
lcd: add esp_lcd component
* Support intel 8080 LCD panel IO on ESP32-S3 * Support RGB LCD panel on ESP32-S3 * Support SPI && I2C LCD panel IO on all esp chips
This commit is contained in:
126
components/esp_lcd/src/esp_lcd_common.c
Normal file
126
components/esp_lcd/src/esp_lcd_common.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "soc/rtc.h" // for querying XTAL clock
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_LCDCAM_SUPPORTED
|
||||
#include "esp_lcd_common.h"
|
||||
#include "hal/lcd_ll.h"
|
||||
#include "hal/lcd_hal.h"
|
||||
|
||||
typedef struct esp_lcd_platform_t {
|
||||
portMUX_TYPE spinlock; // spinlock used to protect platform level resources
|
||||
union {
|
||||
void *panels[SOC_LCD_RGB_PANELS]; // array of RGB LCD panel instances
|
||||
void *buses[SOC_LCD_I80_BUSES]; // array of i80 bus instances
|
||||
}; // LCD peripheral can only work under either RGB mode or intel 8080 mode
|
||||
} esp_lcd_platform_t;
|
||||
|
||||
esp_lcd_platform_t s_lcd_platform = {
|
||||
.spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED,
|
||||
.buses = {} // initially the bus slots and panel slots are empty
|
||||
};
|
||||
|
||||
int lcd_com_register_device(lcd_com_device_type_t device_type, void *device_obj)
|
||||
{
|
||||
int member_id = -1;
|
||||
switch (device_type) {
|
||||
case LCD_COM_DEVICE_TYPE_I80:
|
||||
// search for a bus slot then register to platform
|
||||
for (int i = 0; (i < SOC_LCD_I80_BUSES) && (member_id == -1); i++) {
|
||||
portENTER_CRITICAL(&s_lcd_platform.spinlock);
|
||||
if (!s_lcd_platform.buses[i]) {
|
||||
s_lcd_platform.buses[i] = device_obj;
|
||||
member_id = i;
|
||||
}
|
||||
portEXIT_CRITICAL(&s_lcd_platform.spinlock);
|
||||
}
|
||||
break;
|
||||
case LCD_COM_DEVICE_TYPE_RGB:
|
||||
// search for a panel slot then register to platform
|
||||
for (int i = 0; (i < SOC_LCD_RGB_PANELS) && (member_id == -1); i++) {
|
||||
portENTER_CRITICAL(&s_lcd_platform.spinlock);
|
||||
if (!s_lcd_platform.panels[i]) {
|
||||
s_lcd_platform.panels[i] = device_obj;
|
||||
member_id = i;
|
||||
}
|
||||
portEXIT_CRITICAL(&s_lcd_platform.spinlock);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return member_id;
|
||||
}
|
||||
|
||||
void lcd_com_remove_device(lcd_com_device_type_t device_type, int member_id)
|
||||
{
|
||||
switch (device_type) {
|
||||
case LCD_COM_DEVICE_TYPE_I80:
|
||||
portENTER_CRITICAL(&s_lcd_platform.spinlock);
|
||||
if (s_lcd_platform.buses[member_id]) {
|
||||
s_lcd_platform.buses[member_id] = NULL;
|
||||
}
|
||||
portEXIT_CRITICAL(&s_lcd_platform.spinlock);
|
||||
break;
|
||||
case LCD_COM_DEVICE_TYPE_RGB:
|
||||
portENTER_CRITICAL(&s_lcd_platform.spinlock);
|
||||
if (s_lcd_platform.panels[member_id]) {
|
||||
s_lcd_platform.panels[member_id] = NULL;
|
||||
}
|
||||
portEXIT_CRITICAL(&s_lcd_platform.spinlock);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long lcd_com_select_periph_clock(lcd_hal_context_t *hal)
|
||||
{
|
||||
unsigned long resolution_hz = 0;
|
||||
int clock_source = -1;
|
||||
#if CONFIG_LCD_PERIPH_CLK_SRC_PLL160M
|
||||
resolution_hz = 160000000 / LCD_PERIPH_CLOCK_PRE_SCALE;
|
||||
clock_source = LCD_LL_CLOCK_SRC_PLL160M;
|
||||
#elif CONFIG_LCD_PERIPH_CLK_SRC_XTAL
|
||||
resolution_hz = rtc_clk_xtal_freq_get() * 1000000 / LCD_PERIPH_CLOCK_PRE_SCALE;
|
||||
clock_source = LCD_LL_CLOCK_SRC_XTAL;
|
||||
#else
|
||||
#error "invalid LCD peripheral clock source"
|
||||
#endif
|
||||
|
||||
lcd_ll_set_group_clock_src(hal->dev, clock_source, LCD_PERIPH_CLOCK_PRE_SCALE, 1, 0);
|
||||
return resolution_hz;
|
||||
}
|
||||
|
||||
void lcd_com_mount_dma_data(dma_descriptor_t *desc_head, const void *buffer, size_t len)
|
||||
{
|
||||
size_t prepared_length = 0;
|
||||
uint8_t *data = (uint8_t *)buffer;
|
||||
dma_descriptor_t *desc = desc_head;
|
||||
while (len > DMA_DESCRIPTOR_BUFFER_MAX_SIZE) {
|
||||
desc->dw0.suc_eof = 0; // not the end of the transaction
|
||||
desc->dw0.size = DMA_DESCRIPTOR_BUFFER_MAX_SIZE;
|
||||
desc->dw0.length = DMA_DESCRIPTOR_BUFFER_MAX_SIZE;
|
||||
desc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
desc->buffer = &data[prepared_length];
|
||||
desc = desc->next; // move to next descriptor
|
||||
prepared_length += DMA_DESCRIPTOR_BUFFER_MAX_SIZE;
|
||||
len -= DMA_DESCRIPTOR_BUFFER_MAX_SIZE;
|
||||
}
|
||||
if (len) {
|
||||
desc->dw0.suc_eof = 1; // end of the transaction
|
||||
desc->dw0.size = len;
|
||||
desc->dw0.length = len;
|
||||
desc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
desc->buffer = &data[prepared_length];
|
||||
desc = desc->next; // move to next descriptor
|
||||
prepared_length += len;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOC_LCDCAM_SUPPORTED
|
Reference in New Issue
Block a user