#include "lcd.h"
#include "stdlib.h"
#include "font.h"
#include <stdio.h>
SRAM_HandleTypeDef TFTSRAM_Handler; // SRAM句柄(用于控制LCD)
/* LCD的画笔颜色和背景色 */
uint32_t POINT_COLOR = 0xFF000000; // 画笔颜色
uint32_t BACK_COLOR = 0xFFFFFFFF; // 背景色
/* 管理LCD重要参数,默认为竖屏 */
_lcd_dev lcddev;
/**
* @brief 写寄存器函数
* @param regval: 寄存器值
* @retval None
*/
void LCD_WR_REG(__IO uint16_t regval)
{
regval = regval; // 使用-O2优化的时候,必须插入的延时
LCD->LCD_REG = regval; // 写入要写的寄存器序号
}
/**
* @brief 写LCD数据
* @param data: 要写入的值
* @retval None
*/
void LCD_WR_DATA(__IO uint16_t data)
{
data = data; // 使用-O2优化的时候,必须插入的延时
LCD->LCD_RAM = data;
}
/**
* @brief 读LCD数据
* @retval 读到的值
*/
uint16_t LCD_RD_DATA(void)
{
__IO uint16_t ram; // 防止被优化
ram = LCD->LCD_RAM;
return ram;
}
/**
* @brief 写寄存器
* @param LCD_Reg: 寄存器地址
* @param LCD_RegValue: 要写入的数据
* @retval None
*/
void LCD_WriteReg(uint16_t LCD_Reg, uint16_t LCD_RegValue)
{
LCD->LCD_REG = LCD_Reg; // 写入要写的寄存器序号
LCD->LCD_RAM = LCD_RegValue; // 写入数据
}
/**
* @brief 读寄存器
* @param LCD_Reg: 寄存器地址
* @retval 读到的数据
*/
uint16_t LCD_ReadReg(uint16_t LCD_Reg)
{
LCD_WR_REG(LCD_Reg); // 写入要读的寄存器序号
delay_us(5);
return LCD_RD_DATA(); // 返回读到的值
}
// 开始写GRAM
void LCD_WriteRAM_Prepare(void)
{
LCD->LCD_REG = lcddev.wramcmd;
}
/**
* @brief LCD写GRAM
* @param RGB_Code: 颜色值
* @retval None
*/
void LCD_WriteRAM(uint16_t RGB_Code)
{
LCD->LCD_RAM = RGB_Code; // 写十六位GRAM
}
/**
* @brief 从ILI93xx读出的数据为GBR格式,而我们写入的时候为RGB格式。通过该函数转换。
* @param c: GBR格式的颜色值
* @retval RGB格式的颜色值
*/
uint16_t LCD_BGR2RGB(uint16_t c)
{
uint16_t r, g, b, rgb;
b = (c >> 0) & 0x1f;
g = (c >> 5) & 0x3f;
r = (c >> 11) & 0x1f;
rgb = (b << 11) + (g << 5) + (r << 0);
return(rgb);
}
// 当mdk -O1时间优化时需要设置
// 延时i
void opt_delay(uint8_t i)
{
while(i--);
}
//读取个某点的颜色值
//x,y:坐标
//返回值:此点的颜色
uint32_t LCD_ReadPoint(uint16_t x, uint16_t y)
{
uint16_t r = 0, g = 0, b = 0;
if(x >= lcddev.width || y >= lcddev.height)return 0; //超过了范围,直接返回
LCD_SetCursor(x, y);
if(lcddev.id == 0X9341 || lcddev.id == 0X5310 || lcddev.id == 0X1963)LCD_WR_REG(0X2E); //9341/3510/1963 发送读GRAM指令
else if(lcddev.id == 0X5510)LCD_WR_REG(0X2E00); //5510 发送读GRAM指令
r = LCD_RD_DATA(); //dummy Read
if(lcddev.id == 0X1963)return r; //1963直接读就可以
opt_delay(2);
r = LCD_RD_DATA(); //实际坐标颜色
//9341/NT35310/NT35510要分2次读出
opt_delay(2);
b = LCD_RD_DATA();
g = r & 0XFF; //对于9341/5310/5510,第一次读取的是RG的值,R在前,G在后,各占8位
g <<= 8;
return (((r >> 11) << 11) | ((g >> 10) << 5) | (b >> 11)); //ILI9341/NT35310/NT35510需要公式转换一下
}
//LCD开启显示
void LCD_DisplayOn(void)
{
if(lcddev.id == 0X9341 || lcddev.id == 0X5310 || lcddev.id == 0X1963)LCD_WR_REG(0X29); //开启显示
else if(lcddev.id == 0X5510)LCD_WR_REG(0X2900); //开启显示
}
//LCD关闭显示
void LCD_DisplayOff(void)
{
if(lcddev.id == 0X9341 || lcddev.id == 0X5310 || lcddev.id == 0X1963)LCD_WR_REG(0X28); //关闭显示
else if(lcddev.id == 0X5510)LCD_WR_REG(0X2800); //关闭显示
}
//设置光标位置(对RGB屏无效)
//Xpos:横坐标
//Ypos:纵坐标
void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
{
if(lcddev.id == 0X9341 || lcddev.id == 0X5310)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(Xpos >> 8);
LCD_WR_DATA(Xpos & 0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(Ypos >> 8);
LCD_WR_DATA(Ypos & 0XFF);
}
else if(lcddev.id == 0X1963)
{
if(lcddev.dir == 0) //x坐标需要变换
{
Xpos = lcddev.width - 1 - Xpos;
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(0);
LCD_WR_DATA(0);
LCD_WR_DATA(Xpos >> 8);
LCD_WR_DATA(Xpos & 0XFF);
}
else
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(Xpos >> 8);
LCD_WR_DATA(Xpos & 0XFF);
LCD_WR_DATA((lcddev.width - 1) >> 8);
LCD_WR_DATA((lcddev.width - 1) & 0XFF);
}
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(Ypos >> 8);
LCD_WR_DATA(Ypos & 0XFF);
LCD_WR_DATA((lcddev.height - 1) >> 8);
LCD_WR_DATA((lcddev.height - 1) & 0XFF);
}
else if(lcddev.id == 0X5510)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(Xpos >> 8);
LCD_WR_REG(lcddev.setxcmd + 1);
LCD_WR_DATA(Xpos & 0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(Ypos >> 8);
LCD_WR_REG(lcddev.setycmd + 1);
LCD_WR_DATA(Ypos & 0XFF);
}
}
//设置LCD的自动扫描方向(对RGB屏无效)
//注意:其他函数可能会受到此函数设置的影响(尤其是9341),
//所以,一般设置为L2R_U2D即可,如果设置为其他扫描方式,可能导致显示不正常.
//dir:0~7,代表8个方向(具体定义见lcd.h)
//9341/5310/5510/1963等IC已经实际测试
void LCD_Scan_Dir(uint8_t dir)
{
uint16_t regval = 0;
uint16_t dirreg = 0;
uint16_t temp;
if((lcddev.dir == 1 && lcddev.id != 0X1963) || (lcddev.dir == 0 && lcddev.id == 0X1963)) //横屏时,对1963不改变扫描方向!竖屏时1963改变方向
{
switch(dir)//方向转换
{
case 0:
dir = 6;
break;
case 1:
dir = 7;
break;
case 2:
dir = 4;
break;
case 3:
dir = 5;
break;
case 4:
dir = 1;
break;
case 5:
dir = 0;
break;
case 6:
dir = 3;
break;
case 7:
dir = 2;
break;
}
}
if(lcddev.id == 0x9341 || lcddev.id == 0X5310 || lcddev.id == 0X5510 || lcddev.id == 0X1963) //9341/5310/5510/1963,特殊处理
{
switch(dir)
{
case L2R_U2D://从左到右,从上到下
regval |= (0 << 7) | (0 << 6) | (0 << 5);
break;
case L2R_D2U://从左到右,从下到上
regval |= (1 << 7) | (0 << 6) | (0 << 5);
break;
case R2L_U2D://从右到左,从上到下
regval |= (0 << 7) | (1 << 6) | (0 << 5);
break;
case R2L_D2U://从右到左,从下到上
regval |= (1 << 7) | (1 << 6) | (0 << 5);
break;
case U2D_L2R://从上到下,从左到右
regval |= (0 << 7) | (0 << 6) | (1 << 5);
break;
case U2D_R2L://从上到下,从右到左
regval |= (0 << 7) | (1 << 6) | (1 << 5);
break;
case D2U_L2R://从下到上,从左到右
regval |= (1 << 7) | (0 << 6) | (1 << 5);
break;
case D2U_R2L://从下到上,从右到左
regval |= (1 << 7) | (1 << 6) | (1 << 5);
break;
}
if(lcddev.id == 0X5510)dirreg = 0X3600;
else dirreg = 0X36;
if((lcddev.id != 0X5310) && (lcddev.id != 0X5510) && (lcddev.id != 0X1963))regval |= 0X08; //5310/5510/1963不需要BGR
LCD_WriteReg(dirreg, regval);
if(lcddev.id != 0X1963) //1963不做坐标处理
{
if(regval & 0X20)
{
if(lcddev.width < lcddev.height) //交换X,Y
{
temp = lcddev.width;