[target-stm32f429i-disco]: Initial lcd support
This commit is contained in:
committed by
Travis Geiselbrecht
parent
145e9a0d27
commit
014de968e1
88
target/stm32f429i-disco/include/target/lcd.h
Normal file
88
target/stm32f429i-disco/include/target/lcd.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Luka Panio <lukapanio@gmail.com>
|
||||
*
|
||||
* Use of this source code is governed by a MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stm32f4xx_gpio.h>
|
||||
|
||||
/* LCD Size (Width and Height) */
|
||||
#define LCD_SIZE_PIXEL_WIDTH ((uint16_t)240)
|
||||
#define LCD_SIZE_PIXEL_HEIGHT ((uint16_t)320)
|
||||
|
||||
#define LCD_FRAME_BUFFER ((uint32_t)0xD0000000)
|
||||
#define BUFFER_OFFSET ((uint32_t)0x50000)
|
||||
|
||||
#define LCD_BACKGROUND_LAYER 0x0000
|
||||
|
||||
/**
|
||||
* @brief LCD Control pin
|
||||
*/
|
||||
#define LCD_NCS_PIN GPIO_Pin_2
|
||||
#define LCD_NCS_GPIO_PORT GPIOC
|
||||
#define LCD_NCS_GPIO_CLK RCC_AHB1Periph_GPIOC
|
||||
|
||||
/**
|
||||
* @brief LCD Command/data pin
|
||||
*/
|
||||
#define LCD_WRX_PIN GPIO_Pin_13
|
||||
#define LCD_WRX_GPIO_PORT GPIOD
|
||||
#define LCD_WRX_GPIO_CLK RCC_AHB1Periph_GPIOD
|
||||
|
||||
/**
|
||||
* @brief LCD SPI Interface pins
|
||||
*/
|
||||
#define LCD_SPI_SCK_PIN GPIO_Pin_7 /* PF.07 */
|
||||
#define LCD_SPI_SCK_GPIO_PORT GPIOF /* GPIOF */
|
||||
#define LCD_SPI_SCK_GPIO_CLK RCC_AHB1Periph_GPIOF
|
||||
#define LCD_SPI_SCK_SOURCE GPIO_PinSource7
|
||||
#define LCD_SPI_SCK_AF GPIO_AF_SPI5
|
||||
#define LCD_SPI_MISO_PIN GPIO_Pin_8 /* PF.08 */
|
||||
#define LCD_SPI_MISO_GPIO_PORT GPIOF /* GPIOF */
|
||||
#define LCD_SPI_MISO_GPIO_CLK RCC_AHB1Periph_GPIOF
|
||||
#define LCD_SPI_MISO_SOURCE GPIO_PinSource8
|
||||
#define LCD_SPI_MISO_AF GPIO_AF_SPI5
|
||||
#define LCD_SPI_MOSI_PIN GPIO_Pin_9 /* PF.09 */
|
||||
#define LCD_SPI_MOSI_GPIO_PORT GPIOF /* GPIOF */
|
||||
#define LCD_SPI_MOSI_GPIO_CLK RCC_AHB1Periph_GPIOF
|
||||
#define LCD_SPI_MOSI_SOURCE GPIO_PinSource9
|
||||
#define LCD_SPI_MOSI_AF GPIO_AF_SPI5
|
||||
#define LCD_SPI SPI5
|
||||
#define LCD_SPI_CLK RCC_APB2Periph_SPI5
|
||||
|
||||
/**
|
||||
* @brief LCD Registers
|
||||
*/
|
||||
#define LCD_SLEEP_OUT 0x11 /* Sleep out register */
|
||||
#define LCD_GAMMA 0x26 /* Gamma register */
|
||||
#define LCD_DISPLAY_OFF 0x28 /* Display off register */
|
||||
#define LCD_DISPLAY_ON 0x29 /* Display on register */
|
||||
#define LCD_COLUMN_ADDR 0x2A /* Colomn address register */
|
||||
#define LCD_PAGE_ADDR 0x2B /* Page address register */
|
||||
#define LCD_GRAM 0x2C /* GRAM register */
|
||||
#define LCD_MAC 0x36 /* Memory Access Control register*/
|
||||
#define LCD_PIXEL_FORMAT 0x3A /* Pixel Format register */
|
||||
#define LCD_WDB 0x51 /* Write Brightness Display register */
|
||||
#define LCD_WCD 0x53 /* Write Control Display register*/
|
||||
#define LCD_RGB_INTERFACE 0xB0 /* RGB Interface Signal Control */
|
||||
#define LCD_FRC 0xB1 /* Frame Rate Control register */
|
||||
#define LCD_BPC 0xB5 /* Blanking Porch Control register*/
|
||||
#define LCD_DFC 0xB6 /* Display Function Control register*/
|
||||
#define LCD_POWER1 0xC0 /* Power Control 1 register */
|
||||
#define LCD_POWER2 0xC1 /* Power Control 2 register */
|
||||
#define LCD_VCOM1 0xC5 /* VCOM Control 1 register */
|
||||
#define LCD_VCOM2 0xC7 /* VCOM Control 2 register */
|
||||
#define LCD_POWERA 0xCB /* Power control A register */
|
||||
#define LCD_POWERB 0xCF /* Power control B register */
|
||||
#define LCD_PGAMMA 0xE0 /* Positive Gamma Correction register*/
|
||||
#define LCD_NGAMMA 0xE1 /* Negative Gamma Correction register*/
|
||||
#define LCD_DTCA 0xE8 /* Driver timing control A */
|
||||
#define LCD_DTCB 0xEA /* Driver timing control B */
|
||||
#define LCD_POWER_SEQ 0xED /* Power on sequence register */
|
||||
#define LCD_3GAMMA_EN 0xF2 /* 3 Gamma enable register */
|
||||
#define LCD_INTERFACE 0xF6 /* Interface control register */
|
||||
#define LCD_PRC 0xF7 /* Pump ratio control register */
|
||||
|
||||
@@ -13,12 +13,15 @@
|
||||
#include <stm32f4xx_usart.h>
|
||||
#include <stm32f4xx_rcc.h>
|
||||
#include <stm32f4xx_gpio.h>
|
||||
#include <stm32f4xx_ltdc.h>
|
||||
#include <platform/stm32.h>
|
||||
#include <platform/gpio.h>
|
||||
#include <target.h>
|
||||
#include <target/debugconfig.h>
|
||||
#include <target/gpioconfig.h>
|
||||
|
||||
extern uint8_t STM_LCD_Init(void);
|
||||
|
||||
void target_early_init(void) {
|
||||
#ifdef DEBUG_UART
|
||||
#if DEBUG_UART == 1
|
||||
@@ -38,6 +41,7 @@ void target_early_init(void) {
|
||||
gpio_config(GPIO_LED1, GPIO_OUTPUT);
|
||||
gpio_config(GPIO_LED2, GPIO_OUTPUT);
|
||||
gpio_config(GPIO_LED3, GPIO_OUTPUT);
|
||||
STM_LCD_Init();
|
||||
}
|
||||
|
||||
void target_init(void) {
|
||||
|
||||
683
target/stm32f429i-disco/lcd.c
Normal file
683
target/stm32f429i-disco/lcd.c
Normal file
@@ -0,0 +1,683 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Travis Geiselbrecht
|
||||
* Copyright (c) 2022 Luka Panio
|
||||
*
|
||||
* Use of this source code is governed by a MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
/*
|
||||
* COPYRIGHT(c) 2015 STMicroelectronics
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <lk/err.h>
|
||||
#include <lk/debug.h>
|
||||
#include <lk/trace.h>
|
||||
#include <target.h>
|
||||
#include <lk/compiler.h>
|
||||
#include <string.h>
|
||||
#include <dev/gpio.h>
|
||||
#include <dev/display.h>
|
||||
#include <kernel/timer.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <arch/ops.h>
|
||||
#include <platform/stm32.h>
|
||||
#include <platform/gpio.h>
|
||||
#include <stm32f4xx_rcc.h>
|
||||
#include <stm32f4xx_ltdc.h>
|
||||
#include <stm32f4xx_gpio.h>
|
||||
#include <stm32f4xx_spi.h>
|
||||
#include <target/lcd.h>
|
||||
|
||||
/*
|
||||
* lcd initialization sequence, taken from
|
||||
* STM32F429I-Discovery_FW_V1.0.3/Utilities/STM32F429I-Discovery/stm32f429i_discovery_lcd.[ch]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Controls LCD Chip Select (CS) pin
|
||||
* @param NewState CS pin state
|
||||
* @retval None
|
||||
*/
|
||||
void STM_LCD_ChipSelect(FunctionalState NewState)
|
||||
{
|
||||
if (NewState == DISABLE)
|
||||
{
|
||||
GPIO_ResetBits(LCD_NCS_GPIO_PORT, LCD_NCS_PIN); /* CS pin low: LCD disabled */
|
||||
}
|
||||
else
|
||||
{
|
||||
GPIO_SetBits(LCD_NCS_GPIO_PORT, LCD_NCS_PIN); /* CS pin high: LCD enabled */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the LCD_SPI interface.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void STM_LCD_SPIConfig(void)
|
||||
{
|
||||
SPI_InitTypeDef SPI_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
/* Enable LCD_SPI_SCK_GPIO_CLK, LCD_SPI_MISO_GPIO_CLK and LCD_SPI_MOSI_GPIO_CLK clock */
|
||||
RCC_AHB1PeriphClockCmd(LCD_SPI_SCK_GPIO_CLK | LCD_SPI_MISO_GPIO_CLK | LCD_SPI_MOSI_GPIO_CLK, ENABLE);
|
||||
|
||||
/* Enable LCD_SPI and SYSCFG clock */
|
||||
RCC_APB2PeriphClockCmd(LCD_SPI_CLK, ENABLE);
|
||||
|
||||
/* Configure LCD_SPI SCK pin */
|
||||
GPIO_InitStructure.GPIO_Pin = LCD_SPI_SCK_PIN;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
|
||||
GPIO_Init(LCD_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
|
||||
|
||||
/* Configure LCD_SPI MISO pin */
|
||||
GPIO_InitStructure.GPIO_Pin = LCD_SPI_MISO_PIN;
|
||||
GPIO_Init(LCD_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
|
||||
|
||||
/* Configure LCD_SPI MOSI pin */
|
||||
GPIO_InitStructure.GPIO_Pin = LCD_SPI_MOSI_PIN;
|
||||
GPIO_Init(LCD_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
|
||||
|
||||
/* Connect SPI SCK */
|
||||
GPIO_PinAFConfig(LCD_SPI_SCK_GPIO_PORT, LCD_SPI_SCK_SOURCE, LCD_SPI_SCK_AF);
|
||||
|
||||
/* Connect SPI MISO */
|
||||
GPIO_PinAFConfig(LCD_SPI_MISO_GPIO_PORT, LCD_SPI_MISO_SOURCE, LCD_SPI_MISO_AF);
|
||||
|
||||
/* Connect SPI MOSI */
|
||||
GPIO_PinAFConfig(LCD_SPI_MOSI_GPIO_PORT, LCD_SPI_MOSI_SOURCE, LCD_SPI_MOSI_AF);
|
||||
|
||||
SPI_I2S_DeInit(LCD_SPI);
|
||||
|
||||
/* SPI configuration -------------------------------------------------------*/
|
||||
/* If the SPI peripheral is already enabled, don't reconfigure it */
|
||||
if ((LCD_SPI->CR1 & SPI_CR1_SPE) == 0)
|
||||
{
|
||||
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
|
||||
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
|
||||
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
|
||||
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
|
||||
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
|
||||
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
|
||||
/* SPI baudrate is set to 5.6 MHz (PCLK2/SPI_BaudRatePrescaler = 90/16 = 5.625 MHz)
|
||||
to verify these constraints:
|
||||
- ILI9341 LCD SPI interface max baudrate is 10MHz for write and 6.66MHz for read
|
||||
- l3gd20 SPI interface max baudrate is 10MHz for write/read
|
||||
- PCLK2 frequency is set to 90 MHz
|
||||
*/
|
||||
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
|
||||
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
|
||||
SPI_InitStructure.SPI_CRCPolynomial = 7;
|
||||
SPI_Init(LCD_SPI, &SPI_InitStructure);
|
||||
|
||||
/* Enable L3GD20_SPI */
|
||||
SPI_Cmd(LCD_SPI, ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
static void STM_LCD_AF_GPIOConfig(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
|
||||
/* Enable GPIOA, GPIOB, GPIOC, GPIOD, GPIOF, GPIOG AHB Clocks */
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | \
|
||||
RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | \
|
||||
RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOG, ENABLE);
|
||||
|
||||
/* GPIOs Configuration */
|
||||
/*
|
||||
+------------------------+-----------------------+----------------------------+
|
||||
+ LCD pins assignment +
|
||||
+------------------------+-----------------------+----------------------------+
|
||||
| LCD_TFT R2 <-> PC.10 | LCD_TFT G2 <-> PA.06 | LCD_TFT B2 <-> PD.06 |
|
||||
| LCD_TFT R3 <-> PB.00 | LCD_TFT G3 <-> PG.10 | LCD_TFT B3 <-> PG.11 |
|
||||
| LCD_TFT R4 <-> PA.11 | LCD_TFT G4 <-> PB.10 | LCD_TFT B4 <-> PG.12 |
|
||||
| LCD_TFT R5 <-> PA.12 | LCD_TFT G5 <-> PB.11 | LCD_TFT B5 <-> PA.03 |
|
||||
| LCD_TFT R6 <-> PB.01 | LCD_TFT G6 <-> PC.07 | LCD_TFT B6 <-> PB.08 |
|
||||
| LCD_TFT R7 <-> PG.06 | LCD_TFT G7 <-> PD.03 | LCD_TFT B7 <-> PB.09 |
|
||||
-------------------------------------------------------------------------------
|
||||
| LCD_TFT HSYNC <-> PC.06 | LCDTFT VSYNC <-> PA.04 |
|
||||
| LCD_TFT CLK <-> PG.07 | LCD_TFT DE <-> PF.10 |
|
||||
-----------------------------------------------------
|
||||
|
||||
*/
|
||||
|
||||
/* GPIOA configuration */
|
||||
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_LTDC);
|
||||
GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_LTDC);
|
||||
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_LTDC);
|
||||
GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_LTDC);
|
||||
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_LTDC);
|
||||
|
||||
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_6 | \
|
||||
GPIO_Pin_11 | GPIO_Pin_12;
|
||||
|
||||
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
/* GPIOB configuration */
|
||||
GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, 0x09);
|
||||
GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, 0x09);
|
||||
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_LTDC);
|
||||
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_LTDC);
|
||||
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_LTDC);
|
||||
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_LTDC);
|
||||
|
||||
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 | \
|
||||
GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
|
||||
|
||||
GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* GPIOC configuration */
|
||||
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_LTDC);
|
||||
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_LTDC);
|
||||
GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_LTDC);
|
||||
|
||||
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10;
|
||||
|
||||
GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||
|
||||
/* GPIOD configuration */
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource3, GPIO_AF_LTDC);
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_LTDC);
|
||||
|
||||
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_6;
|
||||
|
||||
GPIO_Init(GPIOD, &GPIO_InitStruct);
|
||||
|
||||
/* GPIOF configuration */
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource10, GPIO_AF_LTDC);
|
||||
|
||||
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
|
||||
|
||||
GPIO_Init(GPIOF, &GPIO_InitStruct);
|
||||
|
||||
/* GPIOG configuration */
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource6, GPIO_AF_LTDC);
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource7, GPIO_AF_LTDC);
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource10, 0x09);
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource11, GPIO_AF_LTDC);
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource12, 0x09);
|
||||
|
||||
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10 | \
|
||||
GPIO_Pin_11 | GPIO_Pin_12;
|
||||
|
||||
GPIO_Init(GPIOG, &GPIO_InitStruct);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets or reset LCD control lines.
|
||||
* @param GPIOx: where x can be B or D to select the GPIO peripheral.
|
||||
* @param CtrlPins: the Control line.
|
||||
* This parameter can be:
|
||||
* @arg LCD_NCS_PIN: Chip Select pin
|
||||
* @arg LCD_NWR_PIN: Read/Write Selection pin
|
||||
* @arg LCD_RS_PIN: Register/RAM Selection pin
|
||||
* @param BitVal: specifies the value to be written to the selected bit.
|
||||
* This parameter can be:
|
||||
* @arg Bit_RESET: to clear the port pin
|
||||
* @arg Bit_SET: to set the port pin
|
||||
* @retval None
|
||||
*/
|
||||
void STM_LCD_CtrlLinesWrite(GPIO_TypeDef* GPIOx, uint16_t CtrlPins, BitAction BitVal)
|
||||
{
|
||||
/* Set or Reset the control line */
|
||||
GPIO_WriteBit(GPIOx, (uint16_t)CtrlPins, (BitAction)BitVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures LCD control lines in Output Push-Pull mode.
|
||||
* @note The LCD_NCS line can be configured in Open Drain mode
|
||||
* when VDDIO is lower than required LCD supply.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void STM_LCD_CtrlLinesConfig(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
/* Enable GPIOs clock*/
|
||||
RCC_AHB1PeriphClockCmd(LCD_NCS_GPIO_CLK | LCD_WRX_GPIO_CLK, ENABLE);
|
||||
|
||||
/* Configure NCS in Output Push-Pull mode */
|
||||
GPIO_InitStructure.GPIO_Pin = LCD_NCS_PIN;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(LCD_NCS_GPIO_PORT, &GPIO_InitStructure);
|
||||
|
||||
/* Configure WRX in Output Push-Pull mode */
|
||||
GPIO_InitStructure.GPIO_Pin = LCD_WRX_PIN;
|
||||
GPIO_Init(LCD_WRX_GPIO_PORT, &GPIO_InitStructure);
|
||||
|
||||
/* Set chip select pin high */
|
||||
STM_LCD_CtrlLinesWrite(LCD_NCS_GPIO_PORT, LCD_NCS_PIN, Bit_SET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes command to select the LCD register.
|
||||
* @param LCD_Reg: address of the selected register.
|
||||
* @retval None
|
||||
*/
|
||||
void STM_LCD_WriteCommand(uint8_t LCD_Reg)
|
||||
{
|
||||
/* Reset WRX to send command */
|
||||
STM_LCD_CtrlLinesWrite(LCD_WRX_GPIO_PORT, LCD_WRX_PIN, Bit_RESET);
|
||||
|
||||
/* Reset LCD control line(/CS) and Send command */
|
||||
STM_LCD_ChipSelect(DISABLE);
|
||||
SPI_I2S_SendData(LCD_SPI, LCD_Reg);
|
||||
|
||||
/* Wait until a data is sent(not busy), before config /CS HIGH */
|
||||
|
||||
while(SPI_I2S_GetFlagStatus(LCD_SPI, SPI_I2S_FLAG_TXE) == RESET) ;
|
||||
|
||||
while(SPI_I2S_GetFlagStatus(LCD_SPI, SPI_I2S_FLAG_BSY) != RESET);
|
||||
|
||||
STM_LCD_ChipSelect(ENABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes data to select the LCD register.
|
||||
* This function must be used after STM_LCD_WriteCommand() function
|
||||
* @param value: data to write to the selected register.
|
||||
* @retval None
|
||||
*/
|
||||
void STM_LCD_WriteData(uint8_t value)
|
||||
{
|
||||
/* Set WRX to send data */
|
||||
STM_LCD_CtrlLinesWrite(LCD_WRX_GPIO_PORT, LCD_WRX_PIN, Bit_SET);
|
||||
|
||||
/* Reset LCD control line(/CS) and Send data */
|
||||
STM_LCD_ChipSelect(DISABLE);
|
||||
SPI_I2S_SendData(LCD_SPI, value);
|
||||
|
||||
/* Wait until a data is sent(not busy), before config /CS HIGH */
|
||||
|
||||
while(SPI_I2S_GetFlagStatus(LCD_SPI, SPI_I2S_FLAG_TXE) == RESET) ;
|
||||
|
||||
while(SPI_I2S_GetFlagStatus(LCD_SPI, SPI_I2S_FLAG_BSY) != RESET);
|
||||
|
||||
STM_LCD_ChipSelect(ENABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the LCD controller (Power On sequence as described in ILI9341 Datasheet)
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void STM_LCD_PowerOn(void)
|
||||
{
|
||||
STM_LCD_WriteCommand(0xCA);
|
||||
STM_LCD_WriteData(0xC3);
|
||||
STM_LCD_WriteData(0x08);
|
||||
STM_LCD_WriteData(0x50);
|
||||
STM_LCD_WriteCommand(LCD_POWERB);
|
||||
STM_LCD_WriteData(0x00);
|
||||
STM_LCD_WriteData(0xC1);
|
||||
STM_LCD_WriteData(0x30);
|
||||
STM_LCD_WriteCommand(LCD_POWER_SEQ);
|
||||
STM_LCD_WriteData(0x64);
|
||||
STM_LCD_WriteData(0x03);
|
||||
STM_LCD_WriteData(0x12);
|
||||
STM_LCD_WriteData(0x81);
|
||||
STM_LCD_WriteCommand(LCD_DTCA);
|
||||
STM_LCD_WriteData(0x85);
|
||||
STM_LCD_WriteData(0x00);
|
||||
STM_LCD_WriteData(0x78);
|
||||
STM_LCD_WriteCommand(LCD_POWERA);
|
||||
STM_LCD_WriteData(0x39);
|
||||
STM_LCD_WriteData(0x2C);
|
||||
STM_LCD_WriteData(0x00);
|
||||
STM_LCD_WriteData(0x34);
|
||||
STM_LCD_WriteData(0x02);
|
||||
STM_LCD_WriteCommand(LCD_PRC);
|
||||
STM_LCD_WriteData(0x20);
|
||||
STM_LCD_WriteCommand(LCD_DTCB);
|
||||
STM_LCD_WriteData(0x00);
|
||||
STM_LCD_WriteData(0x00);
|
||||
STM_LCD_WriteCommand(LCD_FRC);
|
||||
STM_LCD_WriteData(0x00);
|
||||
STM_LCD_WriteData(0x1B);
|
||||
STM_LCD_WriteCommand(LCD_DFC);
|
||||
STM_LCD_WriteData(0x0A);
|
||||
STM_LCD_WriteData(0xA2);
|
||||
STM_LCD_WriteCommand(LCD_POWER1);
|
||||
STM_LCD_WriteData(0x10);
|
||||
STM_LCD_WriteCommand(LCD_POWER2);
|
||||
STM_LCD_WriteData(0x10);
|
||||
STM_LCD_WriteCommand(LCD_VCOM1);
|
||||
STM_LCD_WriteData(0x45);
|
||||
STM_LCD_WriteData(0x15);
|
||||
STM_LCD_WriteCommand(LCD_VCOM2);
|
||||
STM_LCD_WriteData(0x90);
|
||||
STM_LCD_WriteCommand(LCD_MAC);
|
||||
STM_LCD_WriteData(0xC8);
|
||||
STM_LCD_WriteCommand(LCD_3GAMMA_EN);
|
||||
STM_LCD_WriteData(0x00);
|
||||
STM_LCD_WriteCommand(LCD_RGB_INTERFACE);
|
||||
STM_LCD_WriteData(0xC2);
|
||||
STM_LCD_WriteCommand(LCD_DFC);
|
||||
STM_LCD_WriteData(0x0A);
|
||||
STM_LCD_WriteData(0xA7);
|
||||
STM_LCD_WriteData(0x27);
|
||||
STM_LCD_WriteData(0x04);
|
||||
|
||||
/* colomn address set */
|
||||
STM_LCD_WriteCommand(LCD_COLUMN_ADDR);
|
||||
STM_LCD_WriteData(0x00);
|
||||
STM_LCD_WriteData(0x00);
|
||||
STM_LCD_WriteData(0x00);
|
||||
STM_LCD_WriteData(0xEF);
|
||||
/* Page Address Set */
|
||||
STM_LCD_WriteCommand(LCD_PAGE_ADDR);
|
||||
STM_LCD_WriteData(0x00);
|
||||
STM_LCD_WriteData(0x00);
|
||||
STM_LCD_WriteData(0x01);
|
||||
STM_LCD_WriteData(0x3F);
|
||||
STM_LCD_WriteCommand(LCD_INTERFACE);
|
||||
STM_LCD_WriteData(0x01);
|
||||
STM_LCD_WriteData(0x00);
|
||||
STM_LCD_WriteData(0x06);
|
||||
|
||||
STM_LCD_WriteCommand(LCD_GRAM);
|
||||
thread_sleep(200);
|
||||
|
||||
STM_LCD_WriteCommand(LCD_GAMMA);
|
||||
STM_LCD_WriteData(0x01);
|
||||
|
||||
STM_LCD_WriteCommand(LCD_PGAMMA);
|
||||
STM_LCD_WriteData(0x0F);
|
||||
STM_LCD_WriteData(0x29);
|
||||
STM_LCD_WriteData(0x24);
|
||||
STM_LCD_WriteData(0x0C);
|
||||
STM_LCD_WriteData(0x0E);
|
||||
STM_LCD_WriteData(0x09);
|
||||
STM_LCD_WriteData(0x4E);
|
||||
STM_LCD_WriteData(0x78);
|
||||
STM_LCD_WriteData(0x3C);
|
||||
STM_LCD_WriteData(0x09);
|
||||
STM_LCD_WriteData(0x13);
|
||||
STM_LCD_WriteData(0x05);
|
||||
STM_LCD_WriteData(0x17);
|
||||
STM_LCD_WriteData(0x11);
|
||||
STM_LCD_WriteData(0x00);
|
||||
STM_LCD_WriteCommand(LCD_NGAMMA);
|
||||
STM_LCD_WriteData(0x00);
|
||||
STM_LCD_WriteData(0x16);
|
||||
STM_LCD_WriteData(0x1B);
|
||||
STM_LCD_WriteData(0x04);
|
||||
STM_LCD_WriteData(0x11);
|
||||
STM_LCD_WriteData(0x07);
|
||||
STM_LCD_WriteData(0x31);
|
||||
STM_LCD_WriteData(0x33);
|
||||
STM_LCD_WriteData(0x42);
|
||||
STM_LCD_WriteData(0x05);
|
||||
STM_LCD_WriteData(0x0C);
|
||||
STM_LCD_WriteData(0x0A);
|
||||
STM_LCD_WriteData(0x28);
|
||||
STM_LCD_WriteData(0x2F);
|
||||
STM_LCD_WriteData(0x0F);
|
||||
|
||||
STM_LCD_WriteCommand(LCD_SLEEP_OUT);
|
||||
thread_sleep(200);
|
||||
STM_LCD_WriteCommand(LCD_DISPLAY_ON);
|
||||
/* GRAM start writing */
|
||||
STM_LCD_WriteCommand(LCD_GRAM);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LCD Configuration.
|
||||
* @note This function Configure tha LTDC peripheral :
|
||||
* 1) Configure the Pixel Clock for the LCD
|
||||
* 2) Configure the LTDC Timing and Polarity
|
||||
* 3) Configure the LTDC Layer 1 :
|
||||
* - The frame buffer is located at FLASH memory
|
||||
* - The Layer size configuration : 480x272
|
||||
* @retval
|
||||
* None
|
||||
*/
|
||||
static void STM_LCD_Config(void)
|
||||
{
|
||||
LTDC_InitTypeDef LTDC_InitStruct;
|
||||
|
||||
/* Configure the LCD Control pins ------------------------------------------*/
|
||||
STM_LCD_CtrlLinesConfig();
|
||||
STM_LCD_ChipSelect(DISABLE);
|
||||
STM_LCD_ChipSelect(ENABLE);
|
||||
|
||||
/* Configure the LCD_SPI interface -----------------------------------------*/
|
||||
STM_LCD_SPIConfig();
|
||||
|
||||
/* Power on the LCD --------------------------------------------------------*/
|
||||
STM_LCD_PowerOn();
|
||||
|
||||
/* Enable the LTDC Clock */
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_LTDC, ENABLE);
|
||||
|
||||
/* Enable the DMA2D Clock */
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2D, ENABLE);
|
||||
|
||||
/* Configure the LCD Control pins --------------------------------------------*/
|
||||
STM_LCD_AF_GPIOConfig();
|
||||
|
||||
/* LTDC Configuration *********************************************************/
|
||||
/* Polarity configuration */
|
||||
/* Initialize the horizontal synchronization polarity as active low */
|
||||
LTDC_InitStruct.LTDC_HSPolarity = LTDC_HSPolarity_AL;
|
||||
/* Initialize the vertical synchronization polarity as active low */
|
||||
LTDC_InitStruct.LTDC_VSPolarity = LTDC_VSPolarity_AL;
|
||||
/* Initialize the data enable polarity as active low */
|
||||
LTDC_InitStruct.LTDC_DEPolarity = LTDC_DEPolarity_AL;
|
||||
/* Initialize the pixel clock polarity as input pixel clock */
|
||||
LTDC_InitStruct.LTDC_PCPolarity = LTDC_PCPolarity_IPC;
|
||||
|
||||
/* Configure R,G,B component values for LCD background color */
|
||||
LTDC_InitStruct.LTDC_BackgroundRedValue = 0;
|
||||
LTDC_InitStruct.LTDC_BackgroundGreenValue = 0;
|
||||
LTDC_InitStruct.LTDC_BackgroundBlueValue = 0;
|
||||
|
||||
/* Configure PLLSAI prescalers for LCD */
|
||||
/* Enable Pixel Clock */
|
||||
/* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
|
||||
/* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAI_N = 192 Mhz */
|
||||
/* PLLLCDCLK = PLLSAI_VCO Output/PLLSAI_R = 192/4 = 48 Mhz */
|
||||
/* LTDC clock frequency = PLLLCDCLK / RCC_PLLSAIDivR = 48/8 = 6 Mhz */
|
||||
RCC_PLLSAIConfig(192, 7, 4);
|
||||
RCC_LTDCCLKDivConfig(RCC_PLLSAIDivR_Div8);
|
||||
|
||||
/* Enable PLLSAI Clock */
|
||||
RCC_PLLSAICmd(ENABLE);
|
||||
/* Wait for PLLSAI activation */
|
||||
while(RCC_GetFlagStatus(RCC_FLAG_PLLSAIRDY) == RESET)
|
||||
{
|
||||
}
|
||||
|
||||
/* Timing configuration */
|
||||
/* Configure horizontal synchronization width */
|
||||
LTDC_InitStruct.LTDC_HorizontalSync = 9;
|
||||
/* Configure vertical synchronization height */
|
||||
LTDC_InitStruct.LTDC_VerticalSync = 1;
|
||||
/* Configure accumulated horizontal back porch */
|
||||
LTDC_InitStruct.LTDC_AccumulatedHBP = 29;
|
||||
/* Configure accumulated vertical back porch */
|
||||
LTDC_InitStruct.LTDC_AccumulatedVBP = 3;
|
||||
/* Configure accumulated active width */
|
||||
LTDC_InitStruct.LTDC_AccumulatedActiveW = 269;
|
||||
/* Configure accumulated active height */
|
||||
LTDC_InitStruct.LTDC_AccumulatedActiveH = 323;
|
||||
/* Configure total width */
|
||||
LTDC_InitStruct.LTDC_TotalWidth = 279;
|
||||
/* Configure total height */
|
||||
LTDC_InitStruct.LTDC_TotalHeigh = 327;
|
||||
|
||||
LTDC_Init(<DC_InitStruct);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the LCD Layers.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void LCD_LayerInit(void)
|
||||
{
|
||||
LTDC_Layer_InitTypeDef LTDC_Layer_InitStruct;
|
||||
|
||||
/* Windowing configuration */
|
||||
/* In this case all the active display area is used to display a picture then :
|
||||
Horizontal start = horizontal synchronization + Horizontal back porch = 30
|
||||
Horizontal stop = Horizontal start + window width -1 = 30 + 240 -1
|
||||
Vertical start = vertical synchronization + vertical back porch = 4
|
||||
Vertical stop = Vertical start + window height -1 = 4 + 320 -1 */
|
||||
LTDC_Layer_InitStruct.LTDC_HorizontalStart = 30;
|
||||
LTDC_Layer_InitStruct.LTDC_HorizontalStop = (LCD_SIZE_PIXEL_WIDTH + 30 - 1);
|
||||
LTDC_Layer_InitStruct.LTDC_VerticalStart = 4;
|
||||
LTDC_Layer_InitStruct.LTDC_VerticalStop = (LCD_SIZE_PIXEL_HEIGHT + 4 - 1);
|
||||
|
||||
/* Pixel Format configuration*/
|
||||
LTDC_Layer_InitStruct.LTDC_PixelFormat = LTDC_Pixelformat_ARGB8888;
|
||||
/* Alpha constant (255 totally opaque) */
|
||||
LTDC_Layer_InitStruct.LTDC_ConstantAlpha = 255;
|
||||
/* Default Color configuration (configure A,R,G,B component values) */
|
||||
LTDC_Layer_InitStruct.LTDC_DefaultColorBlue = 0;
|
||||
LTDC_Layer_InitStruct.LTDC_DefaultColorGreen = 0;
|
||||
LTDC_Layer_InitStruct.LTDC_DefaultColorRed = 0;
|
||||
LTDC_Layer_InitStruct.LTDC_DefaultColorAlpha = 0;
|
||||
/* Configure blending factors */
|
||||
LTDC_Layer_InitStruct.LTDC_BlendingFactor_1 = LTDC_BlendingFactor1_CA;
|
||||
|
||||
/* the length of one line of pixels in bytes + 3 then :
|
||||
Line Lenth = Active high width x number of bytes per pixel + 3
|
||||
Active high width = LCD_SIZE_PIXEL_WIDTH
|
||||
number of bytes per pixel = 4 (pixel_format : ARGB8888)
|
||||
*/
|
||||
LTDC_Layer_InitStruct.LTDC_CFBLineLength = ((LCD_SIZE_PIXEL_WIDTH * 4) + 3);
|
||||
/* the pitch is the increment from the start of one line of pixels to the
|
||||
start of the next line in bytes, then :
|
||||
Pitch = Active high width x number of bytes per pixel */
|
||||
LTDC_Layer_InitStruct.LTDC_CFBPitch = (LCD_SIZE_PIXEL_WIDTH * 4);
|
||||
|
||||
/* Configure the number of lines */
|
||||
LTDC_Layer_InitStruct.LTDC_CFBLineNumber = LCD_SIZE_PIXEL_HEIGHT;
|
||||
|
||||
/* Start Address configuration : the LCD Frame buffer is defined on SDRAM */
|
||||
LTDC_Layer_InitStruct.LTDC_CFBStartAdress = LCD_FRAME_BUFFER;
|
||||
|
||||
/* Initialize LTDC layer 1 */
|
||||
LTDC_LayerInit(LTDC_Layer1, <DC_Layer_InitStruct);
|
||||
|
||||
/* Configure blending factors */
|
||||
LTDC_Layer_InitStruct.LTDC_BlendingFactor_1 = LTDC_BlendingFactor1_PAxCA;
|
||||
|
||||
/* LTDC configuration reload */
|
||||
LTDC_ReloadConfig(LTDC_IMReload);
|
||||
|
||||
/* Enable foreground & background Layers */
|
||||
LTDC_LayerCmd(LTDC_Layer1, ENABLE);
|
||||
|
||||
/* LTDC configuration reload */
|
||||
LTDC_ReloadConfig(LTDC_IMReload);
|
||||
|
||||
/* dithering activation */
|
||||
LTDC_DitherCmd(ENABLE);
|
||||
}
|
||||
|
||||
uint8_t STM_LCD_Init(void) {
|
||||
/*!< At this stage the microcontroller clock setting is already configured,
|
||||
this is done through SystemInit() function which is called from startup
|
||||
files (startup_stm32f429_439xx.s) before to branch to application main.
|
||||
*/
|
||||
|
||||
dprintf(SPEW, "initializing LCD\n");
|
||||
|
||||
/* Configure LCD : Only one layer is used */
|
||||
STM_LCD_Config();
|
||||
|
||||
/* Enable Layer 1 */
|
||||
LTDC_LayerCmd(LTDC_Layer1, ENABLE);
|
||||
|
||||
/* Reload configuration of Layer 1 */
|
||||
LTDC_ReloadConfig(LTDC_IMReload);
|
||||
|
||||
/* Enable The LCD */
|
||||
LTDC_Cmd(ENABLE);
|
||||
|
||||
/* Setup layers */
|
||||
LCD_LayerInit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* LK display api here */
|
||||
status_t display_get_framebuffer(struct display_framebuffer *fb) {
|
||||
/* fb->image.pixels = (void *)hLtdcEval.LayerCfg[ActiveLayer].FBStartAdress;
|
||||
|
||||
if (hLtdcEval.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_ARGB8888) {
|
||||
fb->format = DISPLAY_FORMAT_ARGB_8888;
|
||||
fb->image.format = IMAGE_FORMAT_ARGB_8888;
|
||||
fb->image.rowbytes = BSP_LCD_GetXSize() * 4;
|
||||
} else if (hLtdcEval.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565) {
|
||||
fb->format = DISPLAY_FORMAT_RGB_565;
|
||||
fb->image.format = IMAGE_FORMAT_RGB_565;
|
||||
fb->image.rowbytes = BSP_LCD_GetXSize() * 2;
|
||||
} else {
|
||||
panic("unhandled pixel format\n");
|
||||
return ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
fb->image.width = BSP_LCD_GetXSize();
|
||||
fb->image.height = BSP_LCD_GetYSize();
|
||||
fb->image.stride = BSP_LCD_GetXSize();
|
||||
fb->flush = NULL;*/
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t display_get_info(struct display_info *info) {
|
||||
info->format = DISPLAY_FORMAT_ARGB_8888;
|
||||
info->width = LCD_SIZE_PIXEL_WIDTH;
|
||||
info->height = LCD_SIZE_PIXEL_HEIGHT;
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t display_present(struct display_image *image, uint starty, uint endy) {
|
||||
TRACEF("display_present - not implemented");
|
||||
DEBUG_ASSERT(false);
|
||||
return NO_ERROR;
|
||||
}
|
||||
@@ -15,7 +15,8 @@ GLOBAL_DEFINES += \
|
||||
PLL_P_VALUE=2
|
||||
|
||||
MODULE_SRCS += \
|
||||
$(LOCAL_DIR)/init.c
|
||||
$(LOCAL_DIR)/init.c \
|
||||
$(LOCAL_DIR)/lcd.c
|
||||
|
||||
include make/module.mk
|
||||
|
||||
|
||||
Reference in New Issue
Block a user