📄 lcddrive.c
字号:
#define IN_LCDDRIVE
#include "config.h"
// 定义FRAMEBUFFER缓冲区
__align(4) volatile uint16 FrameBuffer[GUI_LCM_YMAX][GUI_LCM_XMAX];
void LCD_PortInit(void)
{
// 设置C口(VCLK,HSYNC,VSYNC,VM,VD2--VD7),C1--C4,C10--C15
rGPCUP = rGPCUP | (0x7E0F<<1); // 禁止上拉电阻
rGPCCON = (rGPCCON & (~(0x3FFC00FF<<2))) | (0x2AA800AA<<2);
// 设置D口(VD10--VD15, VD18--VD23),D2--D7, D10--D15
rGPDUP = rGPDUP | (0x3F3F<<2);
rGPDCON = (rGPDCON & (~(0xFFF0FFF<<4))) | (0xAAA0AAA<<4);
}
void LCD_ControlInit(void)
{
rLCDCON1 = (1<<8)|(0<<7)|(3<<5)|(0x0C<<1)|0;
rLCDCON2 = (32<<24)|(479<<14)|(9<<6)|(0);
rLCDCON3 = (47<<19)|(639<<8)|(15);
rLCDCON4 = 95;
rLCDCON5=(1<<11)|(0<<10)|(1<<9)|(1<<8)|(0<<7)|(0<<6)|(0<<5)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|1;
rLCDSADDR1 = ((((uint32)FrameBuffer) & 0x7FC00000) >>1) | ((((uint32)FrameBuffer) & 0x003FFFFE) >>1);
rLCDSADDR2 = (((uint32)FrameBuffer + 640*480*2) & 0x003FFFFE) >>1;
rLCDSADDR3 = (0<<11) | (640);
// 禁止LCD的FIFO中断、帧同步中断
rLCDINTMSK = rLCDINTMSK | 3;
// 禁止LPC3600
rLPCSEL = 0x00;
// 禁止临时调色板
rTPAL = 0x000000000;
}
void LCD_DispOn(void)
{
rLCDCON1 = rLCDCON1 | 0x01; // ENVID=1
}
void LCD_DispOff(void)
{
rLCDCON1 = rLCDCON1 & 0xFFFFFFFE; // ENVID=0
}
void TFT_FillSCR(uint16 dat)
{
uint16 i, j;
volatile uint16 *p_buffer;
p_buffer = (uint16 *)FrameBuffer; // 设置填充显示缓冲区的地址
for(i=0; i<GUI_LCM_YMAX; i++) // 历遍所有行
{
for(j=0; j<GUI_LCM_XMAX; j++) // 历遍所有列
{
*p_buffer++ = dat; // 填充数据
} // end of for(j=0; j<GUI_LCM_XMAX; j++)...
} // end of for(i=0; i<GUI_LCM_YMAX; i++)...
}
void GUI_Initialize(void)
{
LCD_PortInit(); // 初始化LCD控制口线
LCD_ControlInit(); // 初始化LCD控制器
LCD_DispOn(); // 打开LCD显示
TFT_FillSCR(GUI_CCOLOR); // 全屏填充清屏颜色(即清屏)
}
void GUI_FillSCR(TCOLOR dat)
{
TFT_FillSCR(dat);
}
void GUI_ClearSCR(void)
{
TFT_FillSCR(GUI_CCOLOR);
}
uint32 GUI_Point(uint16 x, uint16 y, TCOLOR color)
{
volatile uint16 *p_buffer;
// 参数过滤
if(x >= GUI_LCM_XMAX) return(0);
if(y >= GUI_LCM_YMAX) return(0);
// 刷新显示
p_buffer = (uint16 *)FrameBuffer; // 设置填充显示缓冲区的地址
p_buffer = p_buffer + y*GUI_LCM_XMAX + x; // 计算显示点对应显示缓冲区的位置
*p_buffer = color; // 写入数据
return(1);
}
uint32 GUI_ReadPoint(uint16 x, uint16 y, TCOLOR *ret)
{
volatile uint16 *p_buffer;
// 参数过滤
if(x >= GUI_LCM_XMAX) return(0);
if(y >= GUI_LCM_YMAX) return(0);
// 读取数据
p_buffer = (uint16 *)FrameBuffer; // 设置填充显示缓冲区的地址
p_buffer = p_buffer + y*GUI_LCM_XMAX + x; // 计算显示点对应显示缓冲区的位置
*ret = *p_buffer; // 读到数据
return(1);
}
void GUI_HLine(uint16 x0, uint16 y0, uint16 x1, TCOLOR color)
{
volatile uint16 *p_buffer;
uint16 bak;
if(x0 > x1) // 对x0、x1大小进行排列,以便画图
{
bak = x1;
x1 = x0;
x0 = bak;
}
if(x0 >= GUI_LCM_XMAX) return; // 参数过滤
if(y0 >= GUI_LCM_YMAX) return;
p_buffer = (uint16 *)FrameBuffer; // 设置填充显示缓冲区的地址
p_buffer = p_buffer + y0*GUI_LCM_XMAX + x0; // 计算显示点对应显示缓冲区的位置
while(x1 >= x0)
{
*p_buffer++ = color; // 不断填充并显示
x0++;
if(x0 >= GUI_LCM_XMAX) return; // 若超出一行的范围,则直接退出
}
}
void GUI_RLine(uint16 x0, uint16 y0, uint16 y1, TCOLOR color)
{
uint16 bak;
if(y0 > y1) // 对y0、y1大小进行排列,以便画图
{
bak = y1;
y1 = y0;
y0 = bak;
}
if(x0 >= GUI_LCM_XMAX) return; // 参数过滤
if(y0 >= GUI_LCM_YMAX) return;
while(y1 >= y0)
{
GUI_Point(x0, y0, color); // 逐点显示,描出垂直线
y0++;
if(y0 >= GUI_LCM_YMAX) return; // 若超出屏幕的范围,则直接退出
}
}
void GUI_Rectangle(uint32 x0, uint32 y0, uint32 x1, uint32 y1, TCOLOR color)
{
GUI_HLine(x0, y0, x1, color);
GUI_HLine(x0, y1, x1, color);
GUI_RLine(x0, y0, y1, color);
GUI_RLine(x1, y0, y1, color);
}
void GUI_RectangleFill(uint32 x0, uint32 y0, uint32 x1, uint32 y1, TCOLOR color)
{
uint32 i;
// 先找出矩形左上角与右下角的两个点,保存在(x0,y0),(x1,y1)
if(x0 > x1) // 若x0>x1,则x0与x1交换
{
i = x0;
x0 = x1;
x1 = i;
}
if(y0 > y1) // 若y0>y1,则y0与y1交换
{
i = y0;
y0 = y1;
y1 = i;
}
// 判断是否只是直线
if(y0 == y1)
{
GUI_HLine(x0, y0, x1, color);
return;
}
if(x0 == x1)
{
GUI_RLine(x0, y0, y1, color);
return;
}
while(y0 <= y1)
{
GUI_HLine(x0, y0, x1, color); // 当前画水平线
y0++; // 下一行
}
}
void GUI_Line(uint32 x0, uint32 y0, uint32 x1, uint32 y1, TCOLOR color)
{
int32 dx; // 直线x轴差值变量
int32 dy; // 直线y轴差值变量
int8 dx_sym; // x轴增长方向,为-1时减值方向,为1时增值方向
int8 dy_sym; // y轴增长方向,为-1时减值方向,为1时增值方向
int32 dx_x2; // dx*2值变量,用于加快运算速度
int32 dy_x2; // dy*2值变量,用于加快运算速度
int32 di; // 决策变量
dx = x1-x0; // 求取两点之间的差值
dy = y1-y0;
// 判断增长方向,或是否为水平线、垂直线、点
if(dx>0) // 判断x轴方向
{
dx_sym = 1; // dx>0,设置dx_sym=1
}
else
{
if(dx<0)
{
dx_sym = -1; // dx<0,设置dx_sym=-1
}
else
{
// dx==0,画垂直线,或一点
GUI_RLine(x0, y0, y1, color);
return;
}
} // end of if(dx>0)...else...
if(dy>0) // 判断y轴方向
{
dy_sym = 1; // dy>0,设置dy_sym=1
}
else
{
if(dy<0)
{
dy_sym = -1; // dy<0,设置dy_sym=-1
}
else
{
// dy==0,画水平线,或一点
GUI_HLine(x0, y0, x1, color);
return;
}
} // end of if(dy>0)...else...
// 将dx、dy取绝对值
dx = dx_sym * dx;
dy = dy_sym * dy;
// 计算2倍的dx及dy值
dx_x2 = dx*2;
dy_x2 = dy*2;
// 使用Bresenham法进行画直线
if(dx >= dy) // 对于dx>=dy,则使用x轴为基准
{
di = dy_x2 - dx;
while(x0 != x1)
{
GUI_Point(x0, y0, color);
x0 += dx_sym;
if(di<0)
{
di += dy_x2; // 计算出下一步的决策值
}
else
{
di += dy_x2 - dx_x2;
y0 += dy_sym;
}
} // end of while(x0 != x1)...
GUI_Point(x0, y0, color); // 显示最后一点
}
else // 对于dx<dy,则使用y轴为基准
{
di = dx_x2 - dy;
while(y0 != y1)
{
GUI_Point(x0, y0, color);
y0 += dy_sym;
if(di<0)
{
di += dx_x2;
}
else
{
di += dx_x2 - dy_x2;
x0 += dx_sym;
}
} // end of while(y0 != y1)...
GUI_Point(x0, y0, color); // 显示最后一点
} // end of if(dx >= dy)...else...
}
void GUI_DispPic( uint16 x, uint16 y,
uint16 w, uint16 h,
uint16 *buffer)
{
int i, j;
volatile uint16 *p_buffer;
// 需填充区域参数过滤
if( (x >= GUI_LCM_XMAX) ||
(y >= GUI_LCM_YMAX)
)
{ return;
}
if((x+w) > GUI_LCM_XMAX)
{ return;
}
if((y+h) > GUI_LCM_YMAX)
{ return;
}
// 更新显示数据
for(i=0; i<h; i++) // 输出h行数据
{
// 输出一行(w)数据
p_buffer = (uint16 *)FrameBuffer;
p_buffer = p_buffer + y*GUI_LCM_XMAX + x;
for(j=0; j<w; j++)
{
*p_buffer++ = *buffer++; // 输出数据
}
// 指向下一行
y++;
} // end of for(i=0; i<h; i++)...
}
/*********************************************************************************************************
** End Of File
********************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -