408 lines
11 KiB
C
408 lines
11 KiB
C
/*********************************************************************
|
|
* File Name : lcd.c
|
|
* Author : WCH
|
|
* Version : V1.0.0
|
|
* Date : 2023/8/15
|
|
* Description : file for lcd screen.
|
|
*********************************************************************************
|
|
* Copyright (c) 2023 Nanjing Qinheng Microelectronics Co., Ltd.
|
|
* Attention: This software (modified or not) and binary are used for
|
|
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
|
*******************************************************************************/
|
|
|
|
#include "lcd.h"
|
|
#include "debug.h"
|
|
|
|
static uint16_t width;
|
|
static uint16_t height;
|
|
|
|
#define LCD_SOFT_RESET (0x01)
|
|
#define LCD_READ_ID (0x04)
|
|
#define LCD_READ_DISPLAY_STATUS (0x09)
|
|
#define LCD_ON (0x28)
|
|
#define LCD_OFF (0x29)
|
|
|
|
#define LCD_SET_X (0x2a)
|
|
#define LCD_SET_Y (0x2B)
|
|
#define LCD_MEM_WRITE (0x2C)
|
|
#define LCD_MEM_READ (0x2e)
|
|
|
|
static uint16_t color_buffer[2][FILL_BUFFER_COUNT] = {0};
|
|
|
|
/*********************************************************************
|
|
* @fn LCD_WR_REG
|
|
*
|
|
* @brief Write an 8-bit command to the LCD screen
|
|
*
|
|
* @param data - Command value to be written
|
|
*
|
|
* @return none
|
|
*/
|
|
static void LCD_WR_REG(uint8_t data)
|
|
{
|
|
LCD_CS_CLR;
|
|
LCD_DC_CLR;
|
|
SPI2_Write(data);
|
|
LCD_CS_SET;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn LCD_WR_DATA
|
|
*
|
|
* @brief Write an 8-bit data to the LCD screen
|
|
*
|
|
* @param data - the data to write
|
|
*
|
|
*/
|
|
static void LCD_WR_DATA(uint8_t data)
|
|
{
|
|
LCD_CS_CLR;
|
|
LCD_DC_SET;
|
|
SPI2_Write(data);
|
|
LCD_CS_SET;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn LCD_WriteReg
|
|
*
|
|
* @brief write a data to the register
|
|
*
|
|
* @param LCD_Reg - register address
|
|
* LCD_RegValue - the data to write
|
|
*
|
|
* @return none
|
|
*/
|
|
static void LCD_WriteReg(uint8_t LCD_Reg, uint8_t LCD_RegValue)
|
|
{
|
|
LCD_WR_REG(LCD_Reg);
|
|
LCD_WR_DATA(LCD_RegValue);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn Lcd_WriteData_16Bit
|
|
*
|
|
* @brief write two bytes to the lcd screen
|
|
*
|
|
* @param Data - the data to write
|
|
*
|
|
* @return none
|
|
*/
|
|
void Lcd_WriteData_16Bit(uint16_t Data)
|
|
{
|
|
LCD_CS_CLR;
|
|
LCD_DC_SET;
|
|
SPI2_Write(Data >> 8);
|
|
SPI2_Write(Data);
|
|
LCD_CS_SET;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn LCD_GPIOInit
|
|
*
|
|
* @brief Configuring the control gpio for the lcd screen
|
|
*
|
|
* @return none
|
|
*/
|
|
void LCD_GPIOInit(void)
|
|
{
|
|
GPIO_InitTypeDef GPIO_InitStructure;
|
|
RCC_APB2PeriphClockCmd(LCD_LED_RCC, ENABLE);
|
|
RCC_APB2PeriphClockCmd(LCD_DC_RCC, ENABLE);
|
|
RCC_APB2PeriphClockCmd(LCD_RST_RCC, ENABLE);
|
|
RCC_APB2PeriphClockCmd(LCD_CS_RCC, ENABLE);
|
|
|
|
GPIO_InitStructure.GPIO_Pin = LCD_LED_PIN;
|
|
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
|
GPIO_Init(LCD_LED_PORT, &GPIO_InitStructure);
|
|
|
|
GPIO_InitStructure.GPIO_Pin = LCD_DC_PIN;
|
|
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
|
GPIO_Init(LCD_DC_PORT, &GPIO_InitStructure);
|
|
|
|
GPIO_InitStructure.GPIO_Pin = LCD_RST_PIN;
|
|
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
|
GPIO_Init(LCD_RST_PORT, &GPIO_InitStructure);
|
|
|
|
GPIO_InitStructure.GPIO_Pin = LCD_CS_PIN;
|
|
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
|
GPIO_Init(LCD_CS_PORT, &GPIO_InitStructure);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn LCD_RESET
|
|
*
|
|
* @brief reset the lcd screen by the rst pin
|
|
*
|
|
* @return none
|
|
*/
|
|
void LCD_RESET(void)
|
|
{
|
|
LCD_RST_CLR;
|
|
Delay_Ms(100);
|
|
LCD_RST_SET;
|
|
Delay_Ms(50);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn LCD_Init
|
|
*
|
|
* @brief Initialization LCD screen
|
|
*
|
|
* @return none
|
|
*/
|
|
void LCD_Init(void)
|
|
{
|
|
SPI2_Init();
|
|
SPI2_DMA_Init();
|
|
LCD_GPIOInit();
|
|
LCD_RESET();
|
|
LCD_LED_SET;
|
|
|
|
LCD_WR_REG(0xCF);
|
|
LCD_WR_DATA(0x00);
|
|
LCD_WR_DATA(0xC9); //C1
|
|
LCD_WR_DATA(0X30);
|
|
LCD_WR_REG(0xED);
|
|
LCD_WR_DATA(0x64);
|
|
LCD_WR_DATA(0x03);
|
|
LCD_WR_DATA(0X12);
|
|
LCD_WR_DATA(0X81);
|
|
LCD_WR_REG(0xE8);
|
|
LCD_WR_DATA(0x85);
|
|
LCD_WR_DATA(0x10);
|
|
LCD_WR_DATA(0x7A);
|
|
LCD_WR_REG(0xCB);
|
|
LCD_WR_DATA(0x39);
|
|
LCD_WR_DATA(0x2C);
|
|
LCD_WR_DATA(0x00);
|
|
LCD_WR_DATA(0x34);
|
|
LCD_WR_DATA(0x02);
|
|
LCD_WR_REG(0xF7);
|
|
LCD_WR_DATA(0x20);
|
|
LCD_WR_REG(0xEA);
|
|
LCD_WR_DATA(0x00);
|
|
LCD_WR_DATA(0x00);
|
|
LCD_WR_REG(0xC0); //Power control
|
|
LCD_WR_DATA(0x1B); //VRH[5:0]
|
|
LCD_WR_REG(0xC1); //Power control
|
|
LCD_WR_DATA(0x00); //SAP[2:0];BT[3:0] 01
|
|
LCD_WR_REG(0xC5); //VCM control
|
|
LCD_WR_DATA(0x30); //3F
|
|
LCD_WR_DATA(0x30); //3C
|
|
LCD_WR_REG(0xC7); //VCM control2
|
|
LCD_WR_DATA(0XB7);
|
|
LCD_WR_REG(0x36); // Memory Access Control
|
|
LCD_WR_DATA(0x08);
|
|
LCD_WR_REG(0x3A);
|
|
LCD_WR_DATA(0x55);
|
|
LCD_WR_REG(0xB1);
|
|
LCD_WR_DATA(0x00);
|
|
LCD_WR_DATA(0x1A);
|
|
LCD_WR_REG(0xB6); // Display Function Control
|
|
LCD_WR_DATA(0x0A);
|
|
LCD_WR_DATA(0xA2);
|
|
LCD_WR_REG(0xF2); // 3Gamma Function Disable
|
|
LCD_WR_DATA(0x00);
|
|
LCD_WR_REG(0x26); //Gamma curve selected
|
|
LCD_WR_DATA(0x01);
|
|
LCD_WR_REG(0xE0); //Set Gamma
|
|
LCD_WR_DATA(0x0F);
|
|
LCD_WR_DATA(0x2A);
|
|
LCD_WR_DATA(0x28);
|
|
LCD_WR_DATA(0x08);
|
|
LCD_WR_DATA(0x0E);
|
|
LCD_WR_DATA(0x08);
|
|
LCD_WR_DATA(0x54);
|
|
LCD_WR_DATA(0XA9);
|
|
LCD_WR_DATA(0x43);
|
|
LCD_WR_DATA(0x0A);
|
|
LCD_WR_DATA(0x0F);
|
|
LCD_WR_DATA(0x00);
|
|
LCD_WR_DATA(0x00);
|
|
LCD_WR_DATA(0x00);
|
|
LCD_WR_DATA(0x00);
|
|
LCD_WR_REG(0XE1); //Set Gamma
|
|
LCD_WR_DATA(0x00);
|
|
LCD_WR_DATA(0x15);
|
|
LCD_WR_DATA(0x17);
|
|
LCD_WR_DATA(0x07);
|
|
LCD_WR_DATA(0x11);
|
|
LCD_WR_DATA(0x06);
|
|
LCD_WR_DATA(0x2B);
|
|
LCD_WR_DATA(0x56);
|
|
LCD_WR_DATA(0x3C);
|
|
LCD_WR_DATA(0x05);
|
|
LCD_WR_DATA(0x10);
|
|
LCD_WR_DATA(0x0F);
|
|
LCD_WR_DATA(0x3F);
|
|
LCD_WR_DATA(0x3F);
|
|
LCD_WR_DATA(0x0F);
|
|
LCD_WR_REG(0x2B);
|
|
LCD_WR_DATA(0x00);
|
|
LCD_WR_DATA(0x00);
|
|
LCD_WR_DATA(0x01);
|
|
LCD_WR_DATA(0x3f);
|
|
LCD_WR_REG(0x2A);
|
|
LCD_WR_DATA(0x00);
|
|
LCD_WR_DATA(0x00);
|
|
LCD_WR_DATA(0x00);
|
|
LCD_WR_DATA(0xef);
|
|
LCD_WR_REG(0x11); //Exit Sleep
|
|
Delay_Ms(120);
|
|
LCD_WR_REG(0x29); //display on
|
|
|
|
LCD_direction(USE_HORIZONTAL);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn LCD_SetWindows
|
|
*
|
|
* @brief Setting LCD display window
|
|
*
|
|
* @param xStar - the bebinning x coordinate of the LCD display window
|
|
* yStar - the bebinning y coordinate of the LCD display window
|
|
* xEnd - the endning x coordinate of the LCD display window
|
|
* yEnd - the endning y coordinate of the LCD display window
|
|
*
|
|
* @return none
|
|
*/
|
|
void LCD_SetWindows(uint16_t xStar, uint16_t yStar, uint16_t xEnd, uint16_t yEnd)
|
|
{
|
|
LCD_WR_REG(LCD_SET_X);
|
|
LCD_WR_DATA(xStar >> 8);
|
|
LCD_WR_DATA(0x00FF & xStar);
|
|
LCD_WR_DATA(xEnd >> 8);
|
|
LCD_WR_DATA(0x00FF & xEnd);
|
|
|
|
LCD_WR_REG(LCD_SET_Y);
|
|
LCD_WR_DATA(yStar >> 8);
|
|
LCD_WR_DATA(0x00FF & yStar);
|
|
LCD_WR_DATA(yEnd >> 8);
|
|
LCD_WR_DATA(0x00FF & yEnd);
|
|
LCD_WR_REG(LCD_MEM_WRITE);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn LCD_direction
|
|
*
|
|
* @brief Setting the display direction of LCD screen
|
|
*
|
|
* @param direction - direction:0-0 degree 1-90 degree 2-180 degree 3-270 degree
|
|
*
|
|
* @return none
|
|
*/
|
|
void LCD_direction(uint8_t direction)
|
|
{
|
|
switch (direction)
|
|
{
|
|
case 0:
|
|
width = LCD_W;
|
|
height = LCD_H;
|
|
LCD_WriteReg(0x36, (1 << 3) | (0 << 6) | (0 << 7)); //BGR==1,MY==0,MX==0,MV==0
|
|
break;
|
|
case 1:
|
|
width = LCD_H;
|
|
height = LCD_W;
|
|
LCD_WriteReg(0x36, (1 << 3) | (0 << 7) | (1 << 6) | (1 << 5)); //BGR==1,MY==1,MX==0,MV==1
|
|
break;
|
|
case 2:
|
|
width = LCD_W;
|
|
height = LCD_H;
|
|
LCD_WriteReg(0x36, (1 << 3) | (1 << 6) | (1 << 7)); //BGR==1,MY==0,MX==0,MV==0
|
|
break;
|
|
case 3:
|
|
width = LCD_H;
|
|
height = LCD_W;
|
|
LCD_WriteReg(0x36, (1 << 3) | (1 << 7) | (1 << 5)); //BGR==1,MY==1,MX==0,MV==1
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn LCD_Clear
|
|
*
|
|
* @brief Full screen filled LCD screen
|
|
*
|
|
* @param Color - Filled color
|
|
*
|
|
* @return none
|
|
*/
|
|
void LCD_Clear(uint16_t Color)
|
|
{
|
|
unsigned int i, m;
|
|
LCD_SetWindows(0, 0, width - 1, height - 1);
|
|
LCD_CS_CLR;
|
|
LCD_DC_SET;
|
|
for (i = 0; i < height; i++)
|
|
{
|
|
for (m = 0; m < width; m++)
|
|
{
|
|
Lcd_WriteData_16Bit(Color);
|
|
}
|
|
}
|
|
LCD_CS_SET;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn LCD_drawImageWithSize
|
|
*
|
|
* @brief read image from SPI Flash and display on the LCD screen
|
|
*
|
|
* @param x - the x coordinate of the LCD screen
|
|
* y - the y coordinate of the LCD screen
|
|
* width - the image width
|
|
* height - the image height
|
|
* addr - the image address in SPI flash
|
|
*
|
|
* @return none
|
|
*/
|
|
void LCD_drawImageWithSize(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint32_t addr)
|
|
{
|
|
uint32_t m = 0;
|
|
uint16_t x2 = (x + width) - 1;
|
|
uint16_t y2 = (y + height) - 1;
|
|
LCD_WR_REG(LCD_SET_X);
|
|
LCD_WR_DATA(x >> 8);
|
|
LCD_WR_DATA(0x00FF & x);
|
|
LCD_WR_DATA(x2 >> 8);
|
|
LCD_WR_DATA(0x00FF & x2);
|
|
|
|
LCD_WR_REG(LCD_SET_Y);
|
|
LCD_WR_DATA(y >> 8);
|
|
LCD_WR_DATA(0x00FF & y);
|
|
LCD_WR_DATA(y2 >> 8);
|
|
LCD_WR_DATA(0x00FF & y2);
|
|
|
|
LCD_WR_REG(LCD_MEM_WRITE);
|
|
LCD_CS_CLR;
|
|
LCD_DC_SET;
|
|
|
|
uint32_t count = width * height;
|
|
|
|
uint32_t fill_count = count / FILL_BUFFER_COUNT;
|
|
uint32_t else_count = count % FILL_BUFFER_COUNT;
|
|
SPI_Flash_Read_dma_start(addr);
|
|
|
|
SPI1_Read_DMA((uint8_t *)color_buffer[m], FILL_BUFFER_SIZE);
|
|
|
|
while (fill_count > 0)
|
|
{
|
|
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET)
|
|
;
|
|
fill_count--;
|
|
SPI2_Write_DMA((uint8_t *)color_buffer[m], FILL_BUFFER_SIZE);
|
|
m = !m;
|
|
SPI1_Read_DMA((uint8_t *)color_buffer[m], FILL_BUFFER_SIZE);
|
|
}
|
|
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET)
|
|
;
|
|
SPI2_Write_DMA((uint8_t *)color_buffer[m], else_count * COLOR_BYTE);
|
|
SPI_Flash_Read_dma_end();
|
|
}
|