Files
stc32g128k/Drivers/lcd.c

468 lines
14 KiB
C
Raw Normal View History

#include "lcd.h"
#include "lcd_font.h"
#include "../App/config.h"
#include "intrins.h"
// RM69310 屏幕接口引脚
sbit LCD_RST = P1^0; // 硬件复位
sbit LCD_DCX = P1^1; // 数据/命令选择
sbit LCD_SDI = P1^4; // SPI 数据输入 (MOSI)
sbit LCD_SCL = P1^5; // SPI 时钟 (SCLK)
sbit LCD_CS = P1^6; // SPI 片选 (CS)
// SGM3833 电源芯片控制脚
sbit SGM_CTRL = P3^4;
// External delay functions defined in main.c
extern void Delay_ms(u16 ms);
extern void Delay10us(void);
void SGM_SendPulse(u8 pulse_cnt)
{
u8 i;
SGM_CTRL = 0;
Delay_ms(5); // 确保进入关断/复位状态 (tOFF)
SGM_CTRL = 1;
Delay_ms(5); // 确保充分初始化 (tINIT >= 300us)
for(i = 0; i < pulse_cnt; i++)
{
SGM_CTRL = 0;
Delay10us();
SGM_CTRL = 1;
Delay10us();
}
SGM_CTRL = 1;
Delay_ms(5); // 确保数据稳定存储 (tSTORE >= 80us)
}
void SPI_SendData(u8 dat)
{
u8 i;
for(i = 0; i < 8; i++)
{
LCD_SCL = 0;
if(dat & 0x80)
LCD_SDI = 1;
else
LCD_SDI = 0;
_nop_();
LCD_SCL = 1;
_nop_();
dat <<= 1;
}
}
void WriteComm(u8 cmd)
{
LCD_CS = 0;
LCD_DCX = 0; // 命令模式
SPI_SendData(cmd);
LCD_CS = 1;
}
void WriteData(u8 dat)
{
LCD_CS = 0;
LCD_DCX = 1; // 数据模式
SPI_SendData(dat);
LCD_CS = 1;
}
void LCD_Reset(void)
{
LCD_RST = 1;
Delay_ms(10);
LCD_RST = 0;
Delay_ms(20);
LCD_RST = 1;
Delay_ms(120);
}
void LCD_Init(void)
{
// Configure LCD pins as push-pull output
P1M1 &= ~((1<<0) | (1<<1) | (1<<4) | (1<<5) | (1<<6));
P1M0 |= ((1<<0) | (1<<1) | (1<<4) | (1<<5) | (1<<6));
// Configure P3.4 (SGM_CTRL) as push-pull output
P3M1 &= ~(1 << 4);
P3M0 |= (1 << 4);
SGM_CTRL = 1;
LCD_CS = 1;
LCD_SCL = 1;
LCD_RST = 1;
LCD_DCX = 1;
LCD_Reset();
// 寄存器配置(源自 Truly 信利官方初始化配置)
WriteComm(0xFE);WriteData(0x01);
WriteComm(0x04);WriteData(0xa0); // SPI write ram enable
WriteComm(0x05);WriteData(0x70); // 128RGB
WriteComm(0x06);WriteData(0x3C); // NL = 240 line
WriteComm(0x25);WriteData(0x06); // normal mode: gamma1
WriteComm(0x26);WriteData(0x80); // T1A = 280
WriteComm(0x27);WriteData(0x12); // normal mode VBP = 12
WriteComm(0x28);WriteData(0x12); // normal mode VFP = 8
WriteComm(0x2A);WriteData(0x06); // idle mode: gamma1
WriteComm(0x2B);WriteData(0x80); // T1B = 280
WriteComm(0x2D);WriteData(0x12); // idle mode VBP = 12
WriteComm(0x2F);WriteData(0x12); // idle mode VFP = 8
WriteComm(0x37);WriteData(0x0C); // precharge to VGSP
WriteComm(0x6D);WriteData(0x18); // skip frame VGMP and VGSP regulator off
WriteComm(0x29);WriteData(0x01); // normal mode skip frame off
WriteComm(0x30);WriteData(0x43); // idle mode skip frame = 60/2 = 30Hz
WriteComm(0x0E);WriteData(0x83); // AVDD = 5.6V normal mode
WriteComm(0x0F);WriteData(0x83); // AVDD = 5.6V idle mode
WriteComm(0x10);WriteData(0x71); // AVDD = 3xVCI
WriteComm(0x11);WriteData(0xb3); // VCL = -2xVCI
WriteComm(0x12);WriteData(0xb3); // VCL = -2xVCI
WriteComm(0x13);WriteData(0x80); // VGH = AVDD normal mode
WriteComm(0x14);WriteData(0x80); // VGH = AVDD idle mode
WriteComm(0x15);WriteData(0x81); // VGL = VCL - VCI normal mode
WriteComm(0x16);WriteData(0x81); // VGL = VCL - VCI idle mode
WriteComm(0x18);WriteData(0x66); // VGHR = 6V normal/idle mode
WriteComm(0x19);WriteData(0x44); // VGLR = -6V normal/idle mode
WriteComm(0x1E);WriteData(0x02); // Switch EQ on
WriteComm(0x5B);WriteData(0x10); // VREFN5 on
WriteComm(0x62);WriteData(0x19); // VREFN5 = -3V normal mode
WriteComm(0x63);WriteData(0x19); // VREFN5 = -3V idle mode
WriteComm(0x70);WriteData(0x55); // display off SD to AVDD
WriteComm(0x1D);WriteData(0x02); // Switch EQ on
WriteComm(0x89);WriteData(0x18); // VGMP = 5.5V
WriteComm(0x8A);WriteData(0xb9); // VGSP = 2V
WriteComm(0x8B);WriteData(0x01); // VGMP VGSP high byte
WriteComm(0x8C);WriteData(0x10); // VGMP = 5.4V
WriteComm(0x8D);WriteData(0x90); // VGSP = 2V
WriteComm(0x8E);WriteData(0x01); // VGMP VGSP high byte
WriteComm(0x6E);WriteData(0x0A); // MIPI interface off
WriteComm(0x6A);WriteData(0x05); // MUX
WriteComm(0x3A);WriteData(0x08); // T1_sd
WriteComm(0x3B);WriteData(0x00); // Tp_sd
WriteComm(0x3D);WriteData(0x16); // Th_sd
WriteComm(0x3F);WriteData(0x27); // Tsw_sd
WriteComm(0x40);WriteData(0x0F); // Thsw_sd
WriteComm(0x41);WriteData(0x0D); // Thsd_sd
WriteComm(0x42);WriteData(0x14); // Mux 142536
WriteComm(0x43);WriteData(0x41);
WriteComm(0x44);WriteData(0x25);
WriteComm(0x45);WriteData(0x52);
WriteComm(0x46);WriteData(0x36);
WriteComm(0x47);WriteData(0x63);
WriteComm(0x48);WriteData(0x14);
WriteComm(0x49);WriteData(0x41);
WriteComm(0x4A);WriteData(0x25);
WriteComm(0x4B);WriteData(0x52);
WriteComm(0x4C);WriteData(0x36);
WriteComm(0x4D);WriteData(0x63);
WriteComm(0x4E);WriteData(0x14); // Data R1R2G1G2B1B2
WriteComm(0x4F);WriteData(0x41);
WriteComm(0x50);WriteData(0x25);
WriteComm(0x51);WriteData(0x52);
WriteComm(0x52);WriteData(0x36);
WriteComm(0x53);WriteData(0x63);
WriteComm(0x54);WriteData(0x14);
WriteComm(0x55);WriteData(0x41);
WriteComm(0x56);WriteData(0x25);
WriteComm(0x57);WriteData(0x52);
WriteComm(0x58);WriteData(0x36);
WriteComm(0x59);WriteData(0x63);
WriteComm(0x66);WriteData(0x90); // idle mode internal power
WriteComm(0x67);WriteData(0x40); // internal power delay 1 frame off
WriteComm(0x72);WriteData(0x1A); // internal OVDD = 4.6V
WriteComm(0x73);WriteData(0x07); // internal OVSS = -2V
WriteComm(0x74);WriteData(0x0C); // OVDD power from AVDD
WriteComm(0x6A);WriteData(0x3D); // swire 61=0x3D pulse
WriteComm(0x6B);WriteData(0x29); // swire 41=0x29 pulse
WriteComm(0xFE);WriteData(0x04);
WriteComm(0x5E);WriteData(0x01);
WriteComm(0x5F);WriteData(0xB8);
WriteComm(0x60);WriteData(0xBB);
WriteComm(0x61);WriteData(0xBB);
WriteComm(0x62);WriteData(0xBB);
WriteComm(0x76);WriteData(0xBB);
WriteComm(0x77);WriteData(0x3B);
WriteComm(0x78);WriteData(0x92);
WriteComm(0x79);WriteData(0xBB);
WriteComm(0x7A);WriteData(0xBB);
WriteComm(0x00);WriteData(0xDC); // SN_CK1
WriteComm(0x01);WriteData(0x00);
WriteComm(0x02);WriteData(0x02);
WriteComm(0x03);WriteData(0x00);
WriteComm(0x04);WriteData(0x08);
WriteComm(0x05);WriteData(0x01);
WriteComm(0x06);WriteData(0x70);
WriteComm(0x07);WriteData(0x0A);
WriteComm(0x08);WriteData(0x00);
WriteComm(0x09);WriteData(0xDC); // SN_CK2
WriteComm(0x0a);WriteData(0x00);
WriteComm(0x0b);WriteData(0x02);
WriteComm(0x0C);WriteData(0x00);
WriteComm(0x0D);WriteData(0x08);
WriteComm(0x0E);WriteData(0x00);
WriteComm(0x0F);WriteData(0x70);
WriteComm(0x10);WriteData(0x0A);
WriteComm(0x11);WriteData(0x00);
WriteComm(0x12);WriteData(0xCC); // EM_CK1
WriteComm(0x13);WriteData(0x00);
WriteComm(0x14);WriteData(0x02);
WriteComm(0x15);WriteData(0x00);
WriteComm(0x16);WriteData(0x20);
WriteComm(0x17);WriteData(0x00);
WriteComm(0x18);WriteData(0x28);
WriteComm(0x19);WriteData(0x26);
WriteComm(0x1A);WriteData(0x00);
WriteComm(0x1B);WriteData(0xCC); // EM_CK2
WriteComm(0x1C);WriteData(0x00);
WriteComm(0x1D);WriteData(0x02);
WriteComm(0x1E);WriteData(0x00);
WriteComm(0x1F);WriteData(0x20);
WriteComm(0x20);WriteData(0x01);
WriteComm(0x21);WriteData(0x28);
WriteComm(0x22);WriteData(0x26);
WriteComm(0x23);WriteData(0x00);
WriteComm(0x4C);WriteData(0x89); // SN_STV
WriteComm(0x4D);WriteData(0x00);
WriteComm(0x4E);WriteData(0x01);
WriteComm(0x4F);WriteData(0x00);
WriteComm(0x50);WriteData(0x01);
WriteComm(0x51);WriteData(0xBB);
WriteComm(0x52);WriteData(0xBB);
WriteComm(0x53);WriteData(0xCA); // EM_STV
WriteComm(0x54);WriteData(0x00);
WriteComm(0x55);WriteData(0x03);
WriteComm(0x56);WriteData(0x00);
WriteComm(0x58);WriteData(0x00);
WriteComm(0x59);WriteData(0x00);
WriteComm(0x65);WriteData(0x45); // 04
WriteComm(0x66);WriteData(0x0C); // 03
WriteComm(0x67);WriteData(0x00); // 10
WriteComm(0xFE);WriteData(0x01); // ID
WriteComm(0xE5);WriteData(0x00);
WriteComm(0xE6);WriteData(0x10);
WriteComm(0xE7);WriteData(0x31);
WriteComm(0xFE);WriteData(0x00); // 切换到 Page 0
WriteComm(0xC4);WriteData(0x80);
WriteComm(0x2A);WriteData(0x00);WriteData(0x04);WriteData(0x00);WriteData(0x7B); // 设置列
// 显式设置 16 位像素格式 (COLMOD = 0x75)
WriteComm(0x3A);WriteData(0x75);
WriteComm(0x11);WriteData(0x00); // 退出睡眠
Delay_ms(150);
WriteComm(0x29);WriteData(0x00); // 开启显示
Delay_ms(20);
}
void LCD_SetWindow(u16 x_start, u16 x_end, u16 y_start, u16 y_end)
{
WriteComm(0x2A);
WriteData((u8)(x_start >> 8));
WriteData((u8)(x_start & 0xFF));
WriteData((u8)(x_end >> 8));
WriteData((u8)(x_end & 0xFF));
WriteComm(0x2B);
WriteData((u8)(y_start >> 8));
WriteData((u8)(y_start & 0xFF));
WriteData((u8)(y_end >> 8));
WriteData((u8)(y_end & 0xFF));
}
void LCD_Clear(u16 color)
{
u16 i, j;
LCD_SetWindow(4, 123, 0, 239);
WriteComm(0x2C);
for(i = 0; i < 120; i++)
{
for(j = 0; j < 240; j++)
{
WriteData((u8)(color >> 8));
WriteData((u8)(color & 0xFF));
}
}
}
void LCD_FillRect(u16 x, u16 y, u16 w, u16 h, u16 color)
{
u16 i, count;
u8 ch = (u8)(color >> 8);
u8 cl = (u8)(color & 0xFF);
LCD_SetWindow(x + 4, x + w - 1 + 4, y, y + h - 1);
WriteComm(0x2C);
count = w * h;
for(i = 0; i < count; i++)
{
WriteData(ch);
WriteData(cl);
}
}
void LCD_DrawRectBorder(u16 x, u16 y, u16 w, u16 h, u16 color)
{
LCD_FillRect(x, y, w, 1, color);
LCD_FillRect(x, y + h - 1, w, 1, color);
LCD_FillRect(x, y, 1, h, color);
LCD_FillRect(x + w - 1, y, 1, h, color);
}
void LCD_DrawMonoBitmap(u16 x, u16 y, u16 w, u16 h, unsigned char code *bmp, u16 color, u16 bg_color)
{
u16 r, c;
u16 byte_width = (w + 7) / 8;
u8 ch = (u8)(color >> 8);
u8 cl = (u8)(color & 0xFF);
u8 bgh = (u8)(bg_color >> 8);
u8 bgl = (u8)(bg_color & 0xFF);
LCD_SetWindow(x + 4, x + w - 1 + 4, y, y + h - 1);
WriteComm(0x2C);
for(r = 0; r < h; r++)
{
for(c = 0; c < w; c++)
{
u16 byte_idx = r * byte_width + (c / 8);
u8 bit_shift = 7 - (c % 8);
if(bmp[byte_idx] & (1 << bit_shift))
{
WriteData(ch);
WriteData(cl);
}
else
{
WriteData(bgh);
WriteData(bgl);
}
}
}
}
void LCD_ShowChar8x16(u16 x, u16 y, char ch, u16 color, u16 bg_color)
{
u8 r, c;
u8 char_idx = ch - 0x20;
u8 f_h = (u8)(color >> 8);
u8 f_l = (u8)(color & 0xFF);
u8 b_h = (u8)(bg_color >> 8);
u8 b_l = (u8)(bg_color & 0xFF);
if(ch < 0x20 || ch > 0x7E) return;
LCD_SetWindow(x + 4, x + 8 - 1 + 4, y, y + 16 - 1);
WriteComm(0x2C);
for(r = 0; r < 16; r++)
{
u8 line = FONT_8x16[char_idx][r];
for(c = 0; c < 8; c++)
{
if(line & (0x80 >> c))
{
WriteData(f_h);
WriteData(f_l);
}
else
{
WriteData(b_h);
WriteData(b_l);
}
}
}
}
void LCD_ShowString(u16 x, u16 y, char *str, u16 color, u16 bg_color)
{
while(*str)
{
LCD_ShowChar8x16(x, y, *str, color, bg_color);
x += 8;
str++;
}
}
void LCD_ShowStringCentered(u16 y, char *str, u16 color, u16 bg_color)
{
u16 len = 0;
char *p = str;
while(*p++) len++;
if(len * 8 >= 120)
LCD_ShowString(0, y, str, color, bg_color);
else
LCD_ShowString((120 - len * 8) / 2, y, str, color, bg_color);
}
void LCD_ShowChar16x32(u16 x, u16 y, char ch, u16 color, u16 bg_color)
{
u8 r, c, i, j;
u8 char_idx = ch - 0x20;
u8 f_h = (u8)(color >> 8);
u8 f_l = (u8)(color & 0xFF);
u8 b_h = (u8)(bg_color >> 8);
u8 b_l = (u8)(bg_color & 0xFF);
if(ch < 0x20 || ch > 0x7E) return;
LCD_SetWindow(x + 4, x + 16 - 1 + 4, y, y + 32 - 1);
WriteComm(0x2C);
for(r = 0; r < 16; r++)
{
u8 line = FONT_8x16[char_idx][r];
for(i = 0; i < 2; i++)
{
for(c = 0; c < 8; c++)
{
u8 val_bit = (line & (0x80 >> c));
for(j = 0; j < 2; j++)
{
if(val_bit)
{
WriteData(f_h);
WriteData(f_l);
}
else
{
WriteData(b_h);
WriteData(b_l);
}
}
}
}
}
}
void LCD_ShowString16x32(u16 x, u16 y, char *str, u16 color, u16 bg_color)
{
while(*str)
{
LCD_ShowChar16x32(x, y, *str, color, bg_color);
x += 16;
str++;
}
}
void LCD_ShowString16x32Centered(u16 y, char *str, u16 color, u16 bg_color)
{
u16 len = 0;
char *p = str;
while(*p++) len++;
if(len * 16 >= 120)
LCD_ShowString16x32(0, y, str, color, bg_color);
else
LCD_ShowString16x32((120 - len * 16) / 2, y, str, color, bg_color);
}
// Touched to align with doc updates