This repository has been archived on 2023-07-17. You can view files and clone it, but cannot push or open issues or pull requests.
bl_mcu_sdk/bsp/common/lcd/mipi_dpi/ili9488_dpi.c
2023-02-24 21:33:36 +08:00

240 lines
8.2 KiB
C

/**
* @file ili9488_dpi.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#include "../lcd.h"
#if defined(LCD_DPI_ILI9488)
#include "bflb_mtimer.h"
#include "bflb_gpio.h"
#include "ili9488_dpi.h"
#include "bl_mipi_dpi_pec.h"
#if (ILI9488_DPI_INIT_INTERFACE == 2)
#if defined(BL808)
#include "bl808_dbi.h"
#elif defined(BL616)
#include "bl616_dbi.h"
#endif
#elif (ILI9488_DPI_INIT_INTERFACE == 1)
#include "bflb_spi.h"
// #define ILI9488_SPI_INDEX SPI0_INDEX
#define ILI9488_SPI_ID 0
#define ILI9488_SPI_NAME "spi0"
#endif
/* mipi dpi (RGB) paramant */
static lcd_mipi_dpi_init_t dpi_para = {
.width = ILI9488_DPI_W, /* LCD Active Width */
.height = ILI9488_DPI_H, /* LCD Active Height */
/* Total Width = HSW + HBP + Active_Width + HFP */
.hsw = 4, /* LCD HSW (Hsync Pulse Width) */
.hbp = 4, /* LCD HBP (Hsync Back Porch) */
.hfp = 12, /* LCD HFP (Hsync Front Porch) */
/* Total Height = VSW + VBP + Active_Height + VFP */
.vsw = 6, /* LCD VSW (Vsync Pulse Width) */
.vbp = 6, /* LCD VBP (Vsync Back Porch) */
.vfp = 18, /* LCD VFP (Vsync Front Porch) */
.frame_rate = 60, /* Maximum refresh frame rate per second, Used to automatically calculate the clock frequency */
#if (ILI9488_DPI_PIXEL_FORMAT == 1)
.pixel_format = LCD_MIPI_DPI_PIXEL_FORMAT_RGB565,
#endif
.frame_buff = NULL,
};
#if (ILI9488_DPI_INIT_INTERFACE == 2)
/* dbi config */
static DBI_CFG_Type dbiCfg = {
.mode = DBI_TYPE_C_4_WIRE, /* DBI type B or C select */
.pixelFormat = DBI_PIXEL_RGB888, /* DBI pixel format */
.fifoFormat = DBI_FIFO_888_NBGR, /* DBI fifo format */
.continueEn = ENABLE, /* Enable:CS will stay asserted between each consecutive pixel, disable:CS will de-assert between each pixel */
.dummyEn = DISABLE, /* Enable:dummy cycle will be inserted between command phase adn data phase, disable:no dummy cycle */
.dummyCnt = 0, /* Dummy cycle count,effective only in type C(fixed to 1 in type B) */
.clkPhase = DBI_SCL_CLK_PHASE_0, /* DBI clock phase */
.clkPolarity = DBI_SCL_CLK_POLARITY_LOW, /* DBI clock polarity */
.period.startLen = 9,
.period.dataPhase0Len = 9,
.period.dataPhase1Len = 9,
.period.intervalLen = 9
};
#elif (ILI9488_DPI_INIT_INTERFACE == 1)
static struct bflb_device_s *ili9488_gpio;
static struct bflb_device_s *ili9488_spi;
/* spi write cmd */
static int ili9488_spi_write_cmd(uint8_t cmd)
{
ILI9488_SPI_DC_LOW;
ILI9488_SPI_CS_LOW;
bflb_spi_poll_send(ili9488_spi, cmd);
ILI9488_SPI_CS_HIGH;
ILI9488_SPI_DC_HIGH;
return 0;
}
/* spi write data */
static int ili9488_spi_write_data_byte(uint8_t data)
{
ILI9488_SPI_CS_LOW;
bflb_spi_poll_send(ili9488_spi, data);
ILI9488_SPI_CS_HIGH;
return 0;
}
#endif
static const ili9488_dpi_init_cmd_t ili9488_dpi_mode_init_cmds[] = {
{ 0x01, NULL, 0 }, /* software reset */
{ 0xFF, NULL, 10 }, /* delay 10ms */
{ 0x11, NULL, 0 }, /* Sleep Out */
{ 0xFF, NULL, 120 }, /* delay 120ms */
{ 0xE0, "\x00\x07\x0F\x0D\x1B\x0A\x3C\x78\x4A\x07\x0E\x09\x1B\x1E\x0F", 15 }, /* PGAMCTRL (Positive Gamma Control) */
{ 0xE1, "\x00\x22\x24\x26\x12\x07\x36\x47\x47\x06\x0A\x07\x30\x37\x0F", 15 }, /* NGAMCTRL (Negative Gamma Control) */
{ 0xC0, "\x10\x10", 2 }, /* Power Control 1 */
{ 0xC1, "\x41", 1 }, /* Power Control 2 */
{ 0xC5, "\x00\x20\xd0", 3 }, /* VCOM Control */
{ 0x36, "\x08", 1 }, /* Memory Access Control */
{ 0x3A, "\x50", 1 }, /* Interface Pixel 16bits/pixel*/
{ 0xB0, "\x00", 1 }, /* Interface Mode Control */
{ 0xB1, "\xB0", 1 }, /* Frame rate 70Hz */
{ 0xB4, "\x02", 1 }, /* Display Inversion Control */
// { 0xB5, "\x08\x08\x06\x12", 4},/* Display Inversion Control */
{ 0xB6, "\x30\x22\x3B", 3 }, /* Display Function Control, DE Mode */
{ 0xBE, "\x00\x04", 1 },
{ 0xE9, "\x00", 1 }, /* Set Image Function */
{ 0xF7, "\xA9\x51\x2C\x82", 4 }, /* Adjust Control 3 */
{ 0x29, NULL, 0 }, /* Display On */
{ 0xFF, NULL, 10 },
};
int ili9488_dpi_init(ili9488_dpi_color_t *screen_buffer)
{
/* Ili9488 needs to be initialized using the DBI(typeC) or SPI interface */
#if (ILI9488_DPI_INIT_INTERFACE == 2)
DBI_Init(&dbiCfg);
for (uint16_t i = 0; i < (sizeof(ili9488_dpi_mode_init_cmds) / sizeof(ili9488_dpi_init_cmd_t)); i++) {
if (ili9488_dpi_mode_init_cmds[i].cmd == 0xFF) {
bflb_mtimer_delay_ms(ili9488_dpi_mode_init_cmds[i].databytes);
} else {
DBI_SetPhaseState(ENABLE, DISABLE);
DBI_SendCmdWithNormalData(ili9488_dpi_mode_init_cmds[i].cmd, 0, NULL);
DBI_SetPhaseState(DISABLE, ENABLE);
for (uint8_t j = 0; j < ili9488_dpi_mode_init_cmds[i].databytes; j++) {
DBI_SendCmdWithNormalData(0xFF, 1, (uint8_t *)&ili9488_dpi_mode_init_cmds[i].data[j]);
}
}
}
DBI_SetPhaseState(DISABLE, DISABLE);
#elif (ILI9488_DPI_INIT_INTERFACE == 1)
/* spi */
struct bflb_spi_config_s spi_cfg = {
.freq = 8 * 1000 * 1000,
.role = SPI_ROLE_MASTER,
.mode = SPI_MODE3,
.data_width = SPI_DATA_WIDTH_8BIT,
.bit_order = SPI_BIT_MSB,
.byte_order = SPI_BYTE_LSB,
.tx_fifo_threshold = 0,
.rx_fifo_threshold = 0,
};
/* CS and DC pin init */
ili9488_gpio = bflb_device_get_by_name("gpio");
bflb_gpio_init(ili9488_gpio, ILI9488_DPI_SPI_CS_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
bflb_gpio_init(ili9488_gpio, ILI9488_DPI_SPI_DC_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
ILI9488_SPI_CS_HIGH;
ILI9488_SPI_DC_HIGH;
/* spi init */
ili9488_spi = bflb_device_get_by_name(ILI9488_SPI_NAME);
bflb_spi_init(ili9488_spi, &spi_cfg);
for (uint16_t i = 0; i < (sizeof(ili9488_dpi_mode_init_cmds) / sizeof(ili9488_dpi_init_cmd_t)); i++) {
if ((ili9488_dpi_mode_init_cmds[i].cmd == 0xFF) && (ili9488_dpi_mode_init_cmds[i].data == NULL) && (ili9488_dpi_mode_init_cmds[i].databytes)) {
bflb_mtimer_delay_ms(ili9488_dpi_mode_init_cmds[i].databytes);
} else {
/* send register address */
ili9488_spi_write_cmd(ili9488_dpi_mode_init_cmds[i].cmd);
/* send register data */
for (uint8_t j = 0; j < (ili9488_dpi_mode_init_cmds[i].databytes & 0x7F); j++) {
ili9488_spi_write_data_byte(ili9488_dpi_mode_init_cmds[i].data[j]);
}
}
}
#endif
if (screen_buffer == NULL) {
return -1;
}
/* mipi dpi init */
dpi_para.frame_buff = (void *)screen_buffer;
return lcd_mipi_dpi_init(&dpi_para);
}
int ili9488_dpi_screen_switch(ili9488_dpi_color_t *screen_buffer)
{
return lcd_mipi_dpi_screen_switch((void *)screen_buffer);
}
ili9488_dpi_color_t *ili9488_dpi_get_screen_using(void)
{
return (ili9488_dpi_color_t *)lcd_mipi_dpi_get_screen_using();
}
int ili9488_dpi_frame_callback_register(uint32_t callback_type, void (*callback)(void))
{
if (callback_type == FRAME_INT_TYPE_CYCLE) {
lcd_mipi_dpi_frame_callback_register(LCD_MIPI_DPI_FRAME_INT_TYPE_CYCLE, callback);
} else if (callback_type == FRAME_INT_TYPE_SWAP) {
lcd_mipi_dpi_frame_callback_register(LCD_MIPI_DPI_FRAME_INT_TYPE_SWAP, callback);
}
return 0;
}
#endif