Files
2023-12-01 10:33:09 +08:00

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();
}