rt-thread-official/bsp/stm32/stm32f469-st-disco/board/ports/drv_lcd_otm8009a.c

526 lines
20 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-07-28 liu2guang the first version for STM32F469NI-Discovery.
* 2019-04-19 WillianChan porting STM32F469NI-Discovery lcd driver to
* the new STM32 BSP framework.
*/
#include <board.h>
#ifdef BSP_USING_LCD_OTM8009A
#include <lcd_port.h>
struct stm32_lcd
{
struct rt_device device;
struct rt_device_graphic_info info;
LTDC_HandleTypeDef ltdc;
DSI_HandleTypeDef dsi;
DSI_VidCfgTypeDef dsi_video;
DMA2D_HandleTypeDef dma2d;
};
static struct stm32_lcd lcd;
#define LCD_WIDTH ((uint16_t)800)
#define LCD_HEIGHT ((uint16_t)480)
#define LCD_HSYNC ((uint16_t)1)
#define LCD_HBP ((uint16_t)15)
#define LCD_HFP ((uint16_t)16)
#define LCD_VSYNC ((uint16_t)2)
#define LCD_VBP ((uint16_t)34)
#define LCD_VFP ((uint16_t)34)
const rt_uint8_t RDL01[] = {0x80, 0x09, 0x01, 0xFF};
const rt_uint8_t RDL02[] = {0x80, 0x09, 0xFF};
const rt_uint8_t RDL03[] = {0x00, 0x09, 0x0F, 0x0E, 0x07, 0x10, 0x0B, 0x0A, 0x04, 0x07, 0x0B, 0x08, 0x0F, 0x10, 0x0A, 0x01, 0xE1};
const rt_uint8_t RDL04[] = {0x00, 0x09, 0x0F, 0x0E, 0x07, 0x10, 0x0B, 0x0A, 0x04, 0x07, 0x0B, 0x08, 0x0F, 0x10, 0x0A, 0x01, 0xE2};
const rt_uint8_t RDL05[] = {0x79, 0x79, 0xD8};
const rt_uint8_t RDL06[] = {0x00, 0x01, 0xB3};
const rt_uint8_t RDL07[] = {0x85, 0x01, 0x00, 0x84, 0x01, 0x00, 0xCE};
const rt_uint8_t RDL08[] = {0x18, 0x04, 0x03, 0x39, 0x00, 0x00, 0x00, 0x18, 0x03, 0x03, 0x3A, 0x00, 0x00, 0x00, 0xCE};
const rt_uint8_t RDL09[] = {0x18, 0x02, 0x03, 0x3B, 0x00, 0x00, 0x00, 0x18, 0x01, 0x03, 0x3C, 0x00, 0x00, 0x00, 0xCE};
const rt_uint8_t RDL10[] = {0x01, 0x01, 0x20, 0x20, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0xCF};
const rt_uint8_t RDL11[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCB};
const rt_uint8_t RDL12[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCB};
const rt_uint8_t RDL13[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCB};
const rt_uint8_t RDL14[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCB};
const rt_uint8_t RDL15[] = {0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCB};
const rt_uint8_t RDL16[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0xCB};
const rt_uint8_t RDL17[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCB};
const rt_uint8_t RDL18[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB};
const rt_uint8_t RDL19[] = {0x00, 0x26, 0x09, 0x0B, 0x01, 0x25, 0x00, 0x00, 0x00, 0x00, 0xCC};
const rt_uint8_t RDL20[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x0A, 0x0C, 0x02, 0xCC};
const rt_uint8_t RDL21[] = {0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC};
const rt_uint8_t RDL22[] = {0x00, 0x25, 0x0C, 0x0A, 0x02, 0x26, 0x00, 0x00, 0x00, 0x00, 0xCC};
const rt_uint8_t RDL23[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x0B, 0x09, 0x01, 0xCC};
const rt_uint8_t RDL24[] = {0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC};
const rt_uint8_t RDL25[] = {0xFF, 0xFF, 0xFF, 0xFF};
const rt_uint8_t RDL27[] = {0x00, 0x00, 0x03, 0x1F, 0x2A};
const rt_uint8_t RDL28[] = {0x00, 0x00, 0x01, 0xDF, 0x2B};
const rt_uint8_t RDS01[] = {0x00, 0x00};
const rt_uint8_t RDS02[] = {0x00, 0x80};
const rt_uint8_t RDS03[] = {0xC4, 0x30};
const rt_uint8_t RDS04[] = {0x00, 0x8A};
const rt_uint8_t RDS05[] = {0xC4, 0x40};
const rt_uint8_t RDS06[] = {0x00, 0xB1};
const rt_uint8_t RDS07[] = {0xC5, 0xA9};
const rt_uint8_t RDS08[] = {0x00, 0x91};
const rt_uint8_t RDS09[] = {0xC5, 0x34};
const rt_uint8_t RDS10[] = {0x00, 0xB4};
const rt_uint8_t RDS11[] = {0xC0, 0x50};
const rt_uint8_t RDS12[] = {0xD9, 0x4E};
const rt_uint8_t RDS13[] = {0x00, 0x81};
const rt_uint8_t RDS14[] = {0xC1, 0x66};
const rt_uint8_t RDS15[] = {0x00, 0xA1};
const rt_uint8_t RDS16[] = {0xC1, 0x08};
const rt_uint8_t RDS17[] = {0x00, 0x92};
const rt_uint8_t RDS18[] = {0xC5, 0x01};
const rt_uint8_t RDS19[] = {0x00, 0x95};
const rt_uint8_t RDS20[] = {0x00, 0x94};
const rt_uint8_t RDS21[] = {0xC5, 0x33};
const rt_uint8_t RDS22[] = {0x00, 0xA3};
const rt_uint8_t RDS23[] = {0xC0, 0x1B};
const rt_uint8_t RDS24[] = {0x00, 0x82};
const rt_uint8_t RDS25[] = {0xC5, 0x83};
const rt_uint8_t RDS26[] = {0xC4, 0x83};
const rt_uint8_t RDS27[] = {0xC1, 0x0E};
const rt_uint8_t RDS28[] = {0x00, 0xA6};
const rt_uint8_t RDS29[] = {0x00, 0xA0};
const rt_uint8_t RDS30[] = {0x00, 0xB0};
const rt_uint8_t RDS31[] = {0x00, 0xC0};
const rt_uint8_t RDS32[] = {0x00, 0xD0};
const rt_uint8_t RDS33[] = {0x00, 0x90};
const rt_uint8_t RDS34[] = {0x00, 0xE0};
const rt_uint8_t RDS35[] = {0x00, 0xF0};
const rt_uint8_t RDS36[] = {0x11, 0x00};
const rt_uint8_t RDS37[] = {0x3A, 0x55};
const rt_uint8_t RDS38[] = {0x3A, 0x77};
const rt_uint8_t RDS39[] = {0x36, 0x60};
const rt_uint8_t RDS40[] = {0x51, 0x7F};
const rt_uint8_t RDS41[] = {0x53, 0x2C};
const rt_uint8_t RDS42[] = {0x55, 0x02};
const rt_uint8_t RDS43[] = {0x5E, 0xFF};
const rt_uint8_t RDS44[] = {0x29, 0x00};
const rt_uint8_t RDS45[] = {0x2C, 0x00};
const rt_uint8_t RDS46[] = {0xCF, 0x00};
const rt_uint8_t RDS47[] = {0xC5, 0x66};
const rt_uint8_t RDS48[] = {0x00, 0xB6};
const rt_uint8_t RDS49[] = {0xF5, 0x06};
const rt_uint8_t RDS50[] = {0x00, 0xB1};
const rt_uint8_t RDS51[] = {0xC6, 0x06};
static void otm8009a_reset(void)
{
rt_pin_mode (GET_PIN(H, 7), PIN_MODE_OUTPUT);
rt_pin_write(GET_PIN(H, 7), PIN_LOW);
rt_thread_delay(rt_tick_from_millisecond(20));
rt_pin_write(GET_PIN(H, 7), PIN_HIGH);
rt_thread_delay(rt_tick_from_millisecond(20));
}
void otm8009a_write_cmd(uint8_t *p, uint32_t num)
{
if (num <= 1)
{
HAL_DSI_ShortWrite(&(lcd.dsi), lcd.dsi_video.VirtualChannelID, DSI_DCS_SHORT_PKT_WRITE_P1, p[0], p[1]);
}
else
{
HAL_DSI_LongWrite(&(lcd.dsi), lcd.dsi_video.VirtualChannelID, DSI_DCS_LONG_PKT_WRITE, num, p[num], p);
}
}
void otm8009a_delay(uint32_t d)
{
rt_thread_delay(rt_tick_from_millisecond(d));
}
static void otm8009a_config(rt_uint32_t pixel_format)
{
otm8009a_write_cmd((rt_uint8_t *)RDS01, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL01, 3);
otm8009a_write_cmd((rt_uint8_t *)RDS02, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL02, 2);
otm8009a_write_cmd((rt_uint8_t *)RDS02, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS03, 0);
otm8009a_delay(10);
otm8009a_write_cmd((rt_uint8_t *)RDS04, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS05, 0);
otm8009a_delay(10);
otm8009a_write_cmd((rt_uint8_t *)RDS06, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS07, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS08, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS09, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS10, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS11, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS01, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS12, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS13, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS14, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS15, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS16, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS17, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS18, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS19, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS09, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS01, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL05, 2);
otm8009a_write_cmd((rt_uint8_t *)RDS20, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS21, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS22, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS23, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS24, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS25, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS13, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS26, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS15, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS27, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS28, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL06, 2);
otm8009a_write_cmd((rt_uint8_t *)RDS02, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL07, 6);
otm8009a_write_cmd((rt_uint8_t *)RDS29, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL08, 14);
otm8009a_write_cmd((rt_uint8_t *)RDS30, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL09, 14);
otm8009a_write_cmd((rt_uint8_t *)RDS31, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL10, 10);
otm8009a_write_cmd((rt_uint8_t *)RDS32, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS46, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS02, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL11, 10);
otm8009a_write_cmd((rt_uint8_t *)RDS33, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL12, 15);
otm8009a_write_cmd((rt_uint8_t *)RDS29, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL13, 15);
otm8009a_write_cmd((rt_uint8_t *)RDS30, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL14, 10);
otm8009a_write_cmd((rt_uint8_t *)RDS31, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL15, 15);
otm8009a_write_cmd((rt_uint8_t *)RDS32, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL16, 15);
otm8009a_write_cmd((rt_uint8_t *)RDS34, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL17, 10);
otm8009a_write_cmd((rt_uint8_t *)RDS35, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL18, 10);
otm8009a_write_cmd((rt_uint8_t *)RDS02, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL19, 10);
otm8009a_write_cmd((rt_uint8_t *)RDS33, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL20, 15);
otm8009a_write_cmd((rt_uint8_t *)RDS29, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL21, 15);
otm8009a_write_cmd((rt_uint8_t *)RDS30, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL22, 10);
otm8009a_write_cmd((rt_uint8_t *)RDS31, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL23, 15);
otm8009a_write_cmd((rt_uint8_t *)RDS32, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL24, 15);
otm8009a_write_cmd((rt_uint8_t *)RDS13, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS47, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS48, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS49, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS50, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS51, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS01, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL25, 3);
otm8009a_write_cmd((rt_uint8_t *)RDS01, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS01, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL03, 16);
otm8009a_write_cmd((rt_uint8_t *)RDS01, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL04, 16);
otm8009a_write_cmd((rt_uint8_t *)RDS36, 0);
otm8009a_delay(120);
switch (pixel_format)
{
case RTGRAPHIC_PIXEL_FORMAT_RGB565:
otm8009a_write_cmd((rt_uint8_t *)RDS37, 0);
break;
case RTGRAPHIC_PIXEL_FORMAT_RGB888:
case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
otm8009a_write_cmd((rt_uint8_t *)RDS38, 0);
break;
}
otm8009a_write_cmd((rt_uint8_t *)RDS39, 0);
otm8009a_write_cmd((rt_uint8_t *)RDL27, 4);
otm8009a_write_cmd((rt_uint8_t *)RDL28, 4);
otm8009a_write_cmd((rt_uint8_t *)RDS40, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS41, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS42, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS43, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS44, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS01, 0);
otm8009a_write_cmd((rt_uint8_t *)RDS45, 0);
}
rt_err_t otm8009a_init(void)
{
uint32_t lcd_clock = 27429;
uint32_t lanebyte_clock = 62500;
uint32_t HSA = LCD_HSYNC, HFP = LCD_HFP, HBP = LCD_HBP, HACT = LCD_WIDTH;
uint32_t VSA = LCD_VSYNC, VFP = LCD_VFP, VBP = LCD_VBP, VACT = LCD_HEIGHT;
/* <20><>λOTM8009A<39><41>ʾ<EFBFBD><CABE> */
otm8009a_reset();
/* <20><>ʼ<EFBFBD><CABC>STM32<33><32>ʾ<EFBFBD><CABE>ʱ<EFBFBD><CAB1> */
__HAL_RCC_LTDC_CLK_ENABLE();
__HAL_RCC_LTDC_FORCE_RESET();
__HAL_RCC_LTDC_RELEASE_RESET();
__HAL_RCC_DMA2D_CLK_ENABLE();
__HAL_RCC_DMA2D_FORCE_RESET();
__HAL_RCC_DMA2D_RELEASE_RESET();
__HAL_RCC_DSI_CLK_ENABLE();
__HAL_RCC_DSI_FORCE_RESET();
__HAL_RCC_DSI_RELEASE_RESET();
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
PeriphClkInitStruct.PLLSAI.PLLSAIN = 384;
PeriphClkInitStruct.PLLSAI.PLLSAIR = 7;
PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_2;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
/* <20><><EFBFBD><EFBFBD>NVIC */
HAL_NVIC_SetPriority(LTDC_IRQn, 3, 0);
HAL_NVIC_SetPriority(DMA2D_IRQn, 3, 0);
HAL_NVIC_SetPriority(DSI_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(LTDC_IRQn);
HAL_NVIC_EnableIRQ(DMA2D_IRQn);
HAL_NVIC_EnableIRQ(DSI_IRQn);
/* <20><><EFBFBD><EFBFBD>DSI */
DSI_PLLInitTypeDef dsi_pll;
lcd.dsi.Instance = DSI;
lcd.dsi.Init.NumberOfLanes = DSI_TWO_DATA_LANES;
lcd.dsi.Init.TXEscapeCkdiv = lanebyte_clock / 15620;
dsi_pll.PLLNDIV = 125;
dsi_pll.PLLIDF = DSI_PLL_IN_DIV2;
dsi_pll.PLLODF = DSI_PLL_OUT_DIV1;
HAL_DSI_DeInit(&(lcd.dsi));
HAL_DSI_Init(&(lcd.dsi), &(dsi_pll));
/* <20><><EFBFBD><EFBFBD>DSI Video */
lcd.dsi_video.VirtualChannelID = 0;
lcd.dsi_video.ColorCoding = DSI_RGB888;
lcd.dsi_video.VSPolarity = DSI_VSYNC_ACTIVE_HIGH;
lcd.dsi_video.HSPolarity = DSI_HSYNC_ACTIVE_HIGH;
lcd.dsi_video.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH;
lcd.dsi_video.Mode = DSI_VID_MODE_BURST;
lcd.dsi_video.NullPacketSize = 0xFFF;
lcd.dsi_video.NumberOfChunks = 0;
lcd.dsi_video.PacketSize = HACT;
lcd.dsi_video.HorizontalSyncActive = (HSA * lanebyte_clock) / lcd_clock;
lcd.dsi_video.HorizontalBackPorch = (HBP * lanebyte_clock) / lcd_clock;
lcd.dsi_video.HorizontalLine = ((HACT + HSA + HBP + HFP) * lanebyte_clock) / lcd_clock;
lcd.dsi_video.VerticalSyncActive = VSA;
lcd.dsi_video.VerticalBackPorch = VBP;
lcd.dsi_video.VerticalFrontPorch = VFP;
lcd.dsi_video.VerticalActive = VACT;
lcd.dsi_video.LPCommandEnable = DSI_LP_COMMAND_ENABLE;
lcd.dsi_video.LPLargestPacketSize = 16;
lcd.dsi_video.LPVACTLargestPacketSize = 0;
lcd.dsi_video.LPHorizontalFrontPorchEnable = DSI_LP_HFP_ENABLE;
lcd.dsi_video.LPHorizontalBackPorchEnable = DSI_LP_HBP_ENABLE;
lcd.dsi_video.LPVerticalActiveEnable = DSI_LP_VACT_ENABLE;
lcd.dsi_video.LPVerticalFrontPorchEnable = DSI_LP_VFP_ENABLE;
lcd.dsi_video.LPVerticalBackPorchEnable = DSI_LP_VBP_ENABLE;
lcd.dsi_video.LPVerticalSyncActiveEnable = DSI_LP_VSYNC_ENABLE;
HAL_DSI_ConfigVideoMode(&(lcd.dsi), &(lcd.dsi_video));
/* <20><><EFBFBD><EFBFBD>DSI PHY */
DSI_PHY_TimerTypeDef dsi_phy;
dsi_phy.ClockLaneHS2LPTime = 35;
dsi_phy.ClockLaneLP2HSTime = 35;
dsi_phy.DataLaneHS2LPTime = 35;
dsi_phy.DataLaneLP2HSTime = 35;
dsi_phy.DataLaneMaxReadTime = 0;
dsi_phy.StopWaitTime = 10;
HAL_DSI_ConfigPhyTimer(&(lcd.dsi), &dsi_phy);
/* <20><><EFBFBD><EFBFBD>LTDC */
lcd.ltdc.Instance = LTDC;
lcd.ltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
lcd.ltdc.Init.HorizontalSync = (HSA - 1);
lcd.ltdc.Init.AccumulatedHBP = (HSA + HBP - 1);
lcd.ltdc.Init.AccumulatedActiveW = (LCD_WIDTH + HSA + HBP - 1);
lcd.ltdc.Init.TotalWidth = (LCD_WIDTH + HSA + HBP + HFP - 1);
lcd.ltdc.LayerCfg->ImageWidth = LCD_WIDTH;
lcd.ltdc.LayerCfg->ImageHeight = LCD_HEIGHT;
lcd.ltdc.Init.Backcolor.Blue = 0x00;
lcd.ltdc.Init.Backcolor.Green = 0x00;
lcd.ltdc.Init.Backcolor.Red = 0x00;
HAL_LTDCEx_StructInitFromVideoConfig(&(lcd.ltdc), &(lcd.dsi_video));
HAL_LTDC_Init(&(lcd.ltdc));
HAL_DSI_Start(&(lcd.dsi));
otm8009a_config(RTGRAPHIC_PIXEL_FORMAT_ARGB888);
return RT_EOK;
}
void otm8009a_layer_init(uint16_t index, uint32_t framebuffer)
{
LTDC_LayerCfgTypeDef layer_cfg;
layer_cfg.WindowX0 = 0;
layer_cfg.WindowX1 = LCD_WIDTH;
layer_cfg.WindowY0 = 0;
layer_cfg.WindowY1 = LCD_HEIGHT;
layer_cfg.PixelFormat = LTDC_PIXEL_FORMAT_ARGB8888;
layer_cfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
layer_cfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;
layer_cfg.Alpha = 255;
layer_cfg.Alpha0 = 0;
layer_cfg.ImageWidth = LCD_WIDTH;
layer_cfg.ImageHeight = LCD_HEIGHT;
layer_cfg.Backcolor.Blue = 0;
layer_cfg.Backcolor.Green = 0;
layer_cfg.Backcolor.Red = 0;
layer_cfg.FBStartAdress = framebuffer;
HAL_LTDC_ConfigLayer(&(lcd.ltdc), &layer_cfg, index);
}
static void otm8009a_display_on(void)
{
HAL_DSI_ShortWrite(&(lcd.dsi), lcd.dsi_video.VirtualChannelID, DSI_DCS_SHORT_PKT_WRITE_P1, 0x29, 0x00);
}
static void otm8009a_display_off(void)
{
HAL_DSI_ShortWrite(&(lcd.dsi), lcd.dsi_video.VirtualChannelID, DSI_DCS_SHORT_PKT_WRITE_P1, 0x28, 0x00);
}
void LTDC_IRQHandler(void)
{
rt_interrupt_enter();
HAL_LTDC_IRQHandler(&(lcd.ltdc));
rt_interrupt_leave();
}
/* <20><><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD>: ---------------------------------------- */
static void lcd_fill_buffer(void *addr, uint32_t x_size, uint32_t y_size, uint32_t offset, uint32_t color)
{
lcd.dma2d.Instance = DMA2D;
lcd.dma2d.Init.Mode = DMA2D_R2M;
lcd.dma2d.Init.ColorMode = DMA2D_ARGB8888;
lcd.dma2d.Init.OutputOffset = offset;
if (HAL_DMA2D_Init(&lcd.dma2d) == HAL_OK)
{
if (HAL_DMA2D_ConfigLayer(&lcd.dma2d, 0) == HAL_OK)
{
if (HAL_DMA2D_Start(&lcd.dma2d, color, (uint32_t)addr, x_size, y_size) == HAL_OK)
{
HAL_DMA2D_PollForTransfer(&lcd.dma2d, 10);
}
}
}
}
void lcd_clear(uint32_t color)
{
/* Clear the LCD */
lcd_fill_buffer((uint32_t *)(lcd.ltdc.LayerCfg[0].FBStartAdress), LCD_WIDTH, LCD_HEIGHT, 0, color);
}
void lcd_fill_rect(uint16_t x_pos, uint16_t y_pos, uint16_t width, uint16_t height)
{
uint32_t Xaddress = (lcd.ltdc.LayerCfg[0].FBStartAdress) + 4 * (LCD_WIDTH * x_pos + y_pos);
lcd_fill_buffer((uint32_t *)Xaddress, width, height, (LCD_WIDTH - width), 0xFF00FF00);
}
/* <20><><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD> ----------------------------------------- */
static rt_err_t stm32_lcd_init(rt_device_t device)
{
lcd.info.width = LCD_WIDTH;
lcd.info.height = LCD_HEIGHT;
lcd.info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_ARGB888;
lcd.info.bits_per_pixel = 32;
lcd.info.framebuffer = (void *)rt_malloc_align(LCD_WIDTH * LCD_HEIGHT * (lcd.info.bits_per_pixel / 8), 32);
otm8009a_init();
otm8009a_layer_init(0, (uint32_t)lcd.info.framebuffer);
lcd_clear(0xFF000000);
return RT_EOK;
}
static rt_err_t stm32_lcd_control(rt_device_t device, int cmd, void *args)
{
switch(cmd)
{
case RTGRAPHIC_CTRL_RECT_UPDATE:
break;
case RTGRAPHIC_CTRL_POWERON:
otm8009a_display_on();
break;
case RTGRAPHIC_CTRL_POWEROFF:
otm8009a_display_off();
break;
case RTGRAPHIC_CTRL_GET_INFO:
rt_memcpy(args, &lcd.info, sizeof(lcd.info));
break;
case RTGRAPHIC_CTRL_SET_MODE:
break;
case RTGRAPHIC_CTRL_GET_EXT:
break;
}
return RT_EOK;
}
int rt_hw_lcd_init(void)
{
rt_err_t ret;
rt_memset(&lcd, 0x00, sizeof(lcd));
lcd.device.type = RT_Device_Class_Graphic;
lcd.device.init = stm32_lcd_init;
lcd.device.open = RT_NULL;
lcd.device.close = RT_NULL;
lcd.device.read = RT_NULL;
lcd.device.write = RT_NULL;
lcd.device.control = stm32_lcd_control;
lcd.device.user_data = (void *)&lcd.info;
ret = rt_device_register(&lcd.device, "lcd", RT_DEVICE_FLAG_RDWR);
return ret;
}
INIT_DEVICE_EXPORT(rt_hw_lcd_init);
#endif /* BSP_USING_LCD_OTM8009A */