DPI
Overview
This sample demonstrates the application of driving a EK9716 LCD panel through DPI interface of the LCDC peripheral.
Requirements
For requirements, please refer to the Requirements.
Wiring
Connect P0_2 to the WRCLK pin.
Connect P1_5 to the HSYNC pin.
Connect P0_1 to the VSYNC pin.
Connect P0_0 to the DE pin.
For other data pins, refer to
EK9716_800480_rgb.h
.
Configurations
The following parameter pixel[i]
can be modified to change the color displayed on LCD screen.
for (uint32_t i = 0; i < EK9716_800480_LCD_WIDTH * EK9716_800480_LCD_HEIGHT; i++) { pixel[i] = 0x001F; }
Current default value is red in RGB565 format.
Building and Downloading
For building and downloading, please refer to the Building and Downloading.
Experimental Verification
Screen Refresh Successfully
The screen is refreshed with certain color determined in Configurations.
Code Overview
This section introduces the code and process description for initialization and corresponding function implementation in the sample.
Source Code Directory
The directories for project file and source code are as follows:
Project directory:
sdk\samples\peripheral\lcdc\lcdc_dpi\proj
Source code directory:
sdk\samples\peripheral\lcdc\lcdc_dpi\src
Initialization
The initialization process is included in lcd_pad_and_clk_init()
.
Enable clock of LCDC and select suitable clock source.
/* config LCD dev info */
RCC_PeriphClockCmd(APBPeriph_DISP, APBPeriph_DISP_CLOCK, ENABLE);
//from XTAL SOURCE = 40M
PERIBLKCTRL_PERI_CLK->u_324.BITS_324.disp_ck_en = 1;
PERIBLKCTRL_PERI_CLK->u_324.BITS_324.disp_func_en = 1;
PERIBLKCTRL_PERI_CLK->u_324.BITS_324.r_disp_mux_clk_cg_en = 1;
//From PLL1, SOURCE = 100M
PERIBLKCTRL_PERI_CLK->u_324.BITS_324.r_disp_div_en = 1;
PERIBLKCTRL_PERI_CLK->u_324.BITS_324.r_disp_clk_src_sel0 = 0; //pll1_peri(0) or pll2(1, pll2 = 160M)
PERIBLKCTRL_PERI_CLK->u_324.BITS_324.r_disp_clk_src_sel1 = 1; //pll(1) or xtal(0)
PERIBLKCTRL_PERI_CLK->u_324.BITS_324.r_disp_div_sel = 0; //div
Initialize all the pins to be used.
Pad_Config(LCDC_RGB_WRCLK, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE,
PAD_OUT_HIGH);
Pad_Config(LCDC_HSYNC, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);
Pad_Config(LCDC_VSYNC, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);
Pad_Config(LCDC_CSN_DE, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);
Pad_Dedicated_Config(LCDC_RGB_WRCLK, ENABLE);
Pad_Dedicated_Config(LCDC_HSYNC, ENABLE);
Pad_Dedicated_Config(LCDC_VSYNC, ENABLE);
Pad_Dedicated_Config(LCDC_CSN_DE, ENABLE);
Determine input and output color format, and select DPI interface. Enable infinite mode to continuously transmit data to LCD panel.
LCDC_InitTypeDef lcdc_init = {0};
lcdc_init.LCDC_Interface = LCDC_IF_DPI;
lcdc_init.LCDC_PixelInputFormat = LCDC_INPUT_RGB565;
lcdc_init.LCDC_PixelOutputFormat = LCDC_OUTPUT_RGB888;
lcdc_init.LCDC_PixelBitSwap = LCDC_SWAP_BYPASS; //lcdc_handler_cfg->LCDC_TeEn = LCDC_TE_DISABLE;
lcdc_init.LCDC_GroupSel = 1;
lcdc_init.LCDC_DmaThreshold = 64; //DMA MSize + Dma Threshold = 128
lcdc_init.LCDC_InfiniteModeEn = 1;
LCDC_Init(&lcdc_init);
Initialize DPI interface, including clock division and parameters of signals for synchronization.
uint32_t HSA = 48, HFP = 40, HBP = 40, HACT = EK9716_800480_LCD_WIDTH;
uint32_t VSA = 1, VFP = 13, VBP = 31, VACT = EK9716_800480_LCD_HEIGHT;
LCDC_eDPICfgTypeDef eDPICfg;
eDPICfg.eDPI_ClockDiv = 4;
eDPICfg.eDPI_HoriSyncWidth = HSA;
eDPICfg.eDPI_VeriSyncHeight = VSA;
eDPICfg.eDPI_AccumulatedHBP = HSA + HBP;
eDPICfg.eDPI_AccumulatedVBP = VSA + VBP;
eDPICfg.eDPI_AccumulatedActiveW = HSA + HBP + HACT;
eDPICfg.eDPI_AccumulatedActiveH = VSA + VBP + VACT;
eDPICfg.eDPI_TotalWidth = HSA + HBP + HACT + HFP;
eDPICfg.eDPI_TotalHeight = VSA + VBP + VACT + VFP;
eDPICfg.eDPI_DataEnPolarity = 1;
eDPICfg.eDPI_LineIntMask = 1; //Mask interrupt
eDPICfg.eDPI_ColorMap = EDPI_PIXELFORMAT_RGB888;//For RGB888
eDPICfg.eDPI_OperateMode = 0;//Video mode
eDPICfg.eDPI_LcdArc = 0; //Architecture 1,2,3
eDPICfg.eDPI_CmdMaxLatency = 0;
eDPICfg.eDPI_LineBufferPixelThreshold = eDPICfg.eDPI_TotalWidth / 2;
EDPI_Init(&eDPICfg);
Control Reset pin to finish reset procedure.
ek9716_reset_high();
platform_delay_ms(200);
ek9716_reset_low();
platform_delay_ms(200);
ek9716_reset_high();
platform_delay_ms(200);
Initialize memory space for data to be displayed.
for (uint32_t i = 0; i < EK9716_800480_LCD_WIDTH * EK9716_800480_LCD_HEIGHT; i++)
{
pixel[i] = 0x001F;
}
Initialize DMA parameter, including data size, burst size and source increament, to transmit data to LCD panel through initialized DPI interface. In this sample, linklist mode is selected.
LCDC_DMA_InitTypeDef LCDC_DMA_InitStruct = {0};
LCDC_DMA_StructInit(&LCDC_DMA_InitStruct);
LCDC_DMA_InitStruct.LCDC_DMA_ChannelNum = LCDC_DMA_CHANNEL_NUM;
LCDC_DMA_InitStruct.LCDC_DMA_DIR = LCDC_DMA_DIR_PeripheralToMemory;
LCDC_DMA_InitStruct.LCDC_DMA_SourceInc = LCDC_DMA_SourceInc_Inc;
LCDC_DMA_InitStruct.LCDC_DMA_DestinationInc = LCDC_DMA_DestinationInc_Fix;
LCDC_DMA_InitStruct.LCDC_DMA_SourceDataSize = LCDC_DMA_DataSize_Word;
LCDC_DMA_InitStruct.LCDC_DMA_DestinationDataSize = LCDC_DMA_DataSize_Word;
LCDC_DMA_InitStruct.LCDC_DMA_SourceMsize = LCDC_DMA_Msize_64;
LCDC_DMA_InitStruct.LCDC_DMA_DestinationMsize = LCDC_DMA_Msize_64;
LCDC_DMA_InitStruct.LCDC_DMA_Multi_Block_Mode = LLI_TRANSFER;
LCDC_DMA_InitStruct.LCDC_DMA_Multi_Block_En = ENABLE;
LCDC_DMA_InitStruct.LCDC_DMA_Multi_Block_Struct = LCDC_DMA_LINKLIST_REG_BASE + 0x50;
LCDC_DMA_Init(LCDC_DMA_CHANNEL_INDEX, &LCDC_DMA_InitStruct);
Initialize linklist for DMA configuration. In this sample, two buffers are used alternately, and their addresses increase gradually to fully cover the entire pixel buffer.
LCDC_DMALLI_InitTypeDef LCDC_DMA_LLI_Init = {0};
LCDC_DMA_LLI_Init.g1_source_addr = (uint32_t)p_buffer;
LCDC_DMA_LLI_Init.g2_source_addr = (uint32_t)((uint32_t)p_buffer + EK9716_800480_LCD_WIDTH *
EK9716_DRV_PIXEL_BITS / 8);
LCDC_DMA_LLI_Init.g1_sar_offset = EK9716_800480_LCD_WIDTH * EK9716_DRV_PIXEL_BITS / 8 * 2;
LCDC_DMA_LLI_Init.g2_sar_offset = EK9716_800480_LCD_WIDTH * EK9716_DRV_PIXEL_BITS / 8 * 2;
LCDC_DMA_LinkList_Init(&LCDC_DMA_LLI_Init, &LCDC_DMA_InitStruct);
Each time an entire frame has been transmitted to LCD panel, source address will be reset as pixel buffer address preset by API
LCDC_DMA_Infinite_Buf_Update()
. DMA will read the linklist set in step 8 again and start transmitting data infinitely.
LCDC_DMA_Infinite_Buf_Update((uint8_t *)p_buffer,
(uint8_t *)p_buffer + EK9716_800480_LCD_WIDTH *
EK9716_DRV_PIXEL_BITS / 8);
Determine how many pixels should be sent within each frame with API
LCDC_SetTxPixelLen()
.
LCDC_SetTxPixelLen(EK9716_800480_LCD_WIDTH * EK9716_800480_LCD_HEIGHT);
Functional Implementation
The LCDC functional implementation is demonstrated in ek9716_dma_init
.
Determine direction of data stream by calling
LCDC_SwitchDirect()
.
LCDC_SwitchDirect(LCDC_TX_MODE);
Let LCDC transmit data automatically by setting parameter
LCDC_AUTO_MODE
inLCDC_SwitchMode()
.
LCDC_SwitchMode(LCDC_AUTO_MODE);
Enable LCDC by calling
LCDC_Cmd()
.
LCDC_Cmd(ENABLE);
Use
LCDC_DMA_MultiBlockCmd()
to enable multiblock andLCDC_DMAChannelCmd()
to enable internal DMA channel.
LCDC_DMA_MultiBlockCmd(ENABLE);
LCDC_DMAChannelCmd(LCDC_DMA_CHANNEL_NUM, ENABLE);
Let DMA start to transmit data to internal FIFO with
LCDC_DmaCmd()
.
LCDC_DmaCmd(ENABLE);
Let LCDC start to transmit data from internal FIFO to selected interface by calling API
LCDC_AutoWriteCmd()
.
LCDC_AutoWriteCmd(ENABLE);