韋東山嵌入式Linux學習——016 LCD(2)-編寫程序

編寫程序

/*
 *硬件平臺:韋東山嵌入式Linxu開發板(S3C2440.v3)
 *軟件平臺:運行於VMware Workstation 12 Player下UbuntuLTS16.04_x64 系統,
 *參考資料:開發版原理圖,S3C2440A datasheet,AT043TN24 datasheet
*/


一、框架講解

在這裏插入圖片描述

  1. 第一層:測試菜單層lcd_test.c
  2. 第二層:根據目的劃分三個C文件:framebuffer.cgeometry.cfont.c
  3. 第三層:LCD參數設置lcd.c考慮到拓展性,如果需要用到不同尺寸的lcd時,需要修改太多東西,所以在這一層下分了一個小層,用來放各種尺寸lcd的參數設置文件lcd_4_3.c,通過在lcd.c調用對應的文件。
  4. 第四層:LCD控制器設置lcd_controller.c考慮到拓展性,如果用到不同芯片驅動的lcd時,需要修改太多東西,所以在這一層下分了一個小層,用來放各種芯片的lcd控制器設置文件s3c2440_lcd_controller.c,通過在lcd_controller.c調用對應的文件。

二、設置文件編寫

1、lcd.c文件編寫


#include "lcd.h"
#include "lcd_controller.h"

#define LCD_NUM 10

/* 存儲多種尺寸lcd的結構體數組 */
static p_lcd_params p_array_lcd[LCD_NUM];

/* 存儲被選中的lcd的結構體 */
static p_lcd_params p_g_selected_lcd;

/* 註冊函數:下層代碼調用,把編寫好的lcd_params結構體放入到p_array_lcdr */
int register_lcd(p_lcd_params plcd)
{
	int i;

	for (i = 0; i < LCD_NUM; i++){
		if(!p_array_lcd[i]){
			p_array_lcd[i] = plcd;
			return i;
		}
	}
	return -1;
}

/* 尋找函數:上層代碼調用,根據名字作爲索引,找到該芯片在p_array_lcd中的位置並返回 */
int select_lcd(char *name)
{
	int i;

	for (i = 0; i < LCD_NUM; i++){
		if ((p_array_lcd[i]) && !(strcmp(p_array_lcd[i]->name, name))){
			p_g_selected_lcd = p_array_lcd[i];
			return i;
		}
	}
	return -1;
}

/* 得到lcd參數 */
void get_lcd_params(unsigned int *fb_base, int *xres, int *yres, int *bpp)
{
	*fb_base = p_g_selected_lcd->frm_base;
	*xres	 = p_g_selected_lcd->xres;
	*yres 	 = p_g_selected_lcd->yres;
	*bpp 	 = p_g_selected_lcd->bpp;
}

/* lcd使能函數 */
void lcd_enable(void)
{
	lcd_controller_enable();
}

/* lcd關閉函數 */
void lcd_disable(void)
{
	lcd_controller_disable();
}

/* lcd初始化函數 */
int lcd_init(void)
{
	/* 註冊LCD */
	lcd_4_3_add();
	
	/* 註冊LCD控制器 */
	lcd_controller_add();
	
	/* 選擇某款LCD */
	select_lcd("lcd_4.3");

	/* 選擇LCD控制器 */
	select_lcd_controller("s3c2440_lcdcon");

	/* 利用LCD參數,初始化LCD */
	lcd_controller_init(p_g_selected_lcd);
}


2、lcd_4_3.c文件編寫

在這裏插入圖片描述


#include "lcd.h"

#define LCD_FB_BASE 0x33c00000

/* lcd參數設置 */
lcd_params lcd_4_3_params = {
	.name = "lcd_4.3",
	.pin_pol = {
		.clk 	= NORMAL,	//normal:下降沿觸發	
		.hsync  = INVERT,	//normal:高脈衝
		.vsync  = INVERT,	//normal:高脈衝
		.rgb  	= NORMAL,	//normal:對應位爲1
		.de 	= NORMAL,	//normal: 高電平傳輸數據
		.pwren	= NORMAL,   //normal: 高電平有效
	},
	.time_seq = {
		/* 水平方向 */
		.thp = 41,	//thp:水平脈衝寬度,Horizontal Pulse width
		.thb = 2,	//thb:左邊黑框, 		 Horizontal Back porch
		.thf = 2,	//thf:右邊黑框, 		 Horizontal Front porch

		/* 垂直方向 */
		.tvp = 10,	//tvp:垂直脈衝寬度,Vertical Pulse width
		.tvb = 2,	//tvb:上邊黑框, 		 Vertical Back porch
		.tvf = 2,	//tvf:下邊黑框, 		 Vertical Front porch

		.vclk= 9,	//MHz
	},
	.xres = 480,
	.yres = 272,	
	.bpp  = 8,		//不支持24bpp
	.frm_base = LCD_FB_BASE,	
};

/* 把該尺寸lcd的結構體註冊到lcd.c的p_array_lcd結構體數組中 */
void lcd_4_3_add(void)
{
	register_lcd(&lcd_4_3_params);
}

3、lcd_controller.c文件編寫

#include "lcd_controller.h"

#define LCD_CONTROLLER_NUM 10

/* 存儲多種芯片的lcd控制器的結構體數組 */
static p_lcd_controller p_array_lcd_controller[LCD_CONTROLLER_NUM];

/* 存儲被選中的lcd控制器的結構體 */
static p_lcd_controller p_g_selected_lcd_controller;

/* 註冊函數:下層代碼調用,把編寫好的lcd_controller結構體放入到p_array_lcd_controller */
int register_lcd_controller(p_lcd_controller plcdcon)
{
	int i;

	for (i = 0; i < LCD_CONTROLLER_NUM; i++){
		if(!p_array_lcd_controller[i]){
			p_array_lcd_controller[i] = plcdcon;
			return i;
		}
	}
	return -1;
}

/* 尋找函數:上層代碼調用,根據名字作爲索引,找到該芯片在p_array_lcd_controller中的位置並返回 */
int select_lcd_controller(char *name)
{
	int i;

	for (i = 0; i < LCD_CONTROLLER_NUM; i++){
		if((p_array_lcd_controller[i]) && !(strcmp(p_array_lcd_controller[i]->name, name))){
			p_g_selected_lcd_controller = p_array_lcd_controller[i];
			return i;
		}
	}
	return -1;
}

void lcd_controller_add(void)
{
	s3c2440_lcd_controller_add();
}

/* 
 *	對於上層:用來接受不同的LCD參數
 *	對於下層:利用參數設置對應的LCD控制器
 */
int lcd_controller_init(p_lcd_params plcdparams)
{
	/* 調用對應初始化函數 */
	if (p_g_selected_lcd_controller){
		p_g_selected_lcd_controller->init(plcdparams);
		p_g_selected_lcd_controller->init_palette();
		return 0;
	}
	return -1;	
}

/* lcd控制器使能 */
void lcd_controller_enable(void)
{
	/* 調用對應初始化函數 */
	if (p_g_selected_lcd_controller)
		p_g_selected_lcd_controller->enable();
}

/* lcd控制器關閉 */
void lcd_controller_disable(void)
{
	/* 調用對應初始化函數 */
	if (p_g_selected_lcd_controller)
		p_g_selected_lcd_controller->disable();
}

4、s3c2440_lcd_controller.c文件編寫

4.1 寄存器配置

在這裏插入圖片描述

	/*
	 * [17:8] CLKVAL: TFT: VCLK = HCLK / [(CLKVAL+1) x 2]
	 *						CLKVAL = HCLK/VCLK/2-1 = 100/9/2-1 = 4.5 + 0.5 = 5
	 * [6:5]	:11 = TFT LCD panel
	 * [4:1]	: bpp 支持8,16,24bpp
	 * [0]		: LCD video output and the logic enable/disable
     */
    int CLKVAL = (double)VCLK/HCLK/2-1 + 0.5;
	int BPP = plcparams->bpp  == 8 ? 0xb :\
			  plcparams->bpp  == 16 ? 0xc : 0xd;
	
	LCDCON1 = (CLKVAL<<8) | (0x3<<5) | (BPP<<1);

在這裏插入圖片描述

	/* [31:24] : VBPD 		= tvb - 1
	 * [23:14] : LINEVAL 	= yres - 1
	 * [13:6]  : VFPD		= tvf - 1
	 * [5:0]   : VSPW		= tvp - 1
	 */
	LCDCON2 = ((plcparams->time_seq.tvb - 1)<<24)	| \
	          ((plcparams->yres - 1)<<14) 			| \
	          ((plcparams->time_seq.tvf - 1)<<6) 	| \
	          ((plcparams->time_seq.tvp - 1)<<0);

在這裏插入圖片描述

	/* [25:19] : HBPT 	  = thb - 1
	 * 18:8]	 : HOZBAL	  = xres - 1
	 * [7:0]  `: HFPD 	  = thf - 1
	 */
	LCDCON3 = ((plcparams->time_seq.thb - 1)<<19)	| \
			  ((plcparams->xres - 1)<<8)			| \ 
			  ((plcparams->time_seq.thf - 1)<<0);

在這裏插入圖片描述

	/* [7:0]   : HSPW	  = thp - 1
	 */
	LCDCON4 =	((plcparams->time_seq.thp - 1)<<0);

在這裏插入圖片描述

	/* 用來設置引腳極性, 設置16bpp, 設置內存中象素存放的格式
	 * [12] : BPP24BL
	 * [11] : FRM565, 1-565
	 * [10] : INVVCLK, 0 = The video data is fetched at VCLK falling edge
	 * [9]	: HSYNC是否反轉
	 * [8]	: VSYNC是否反轉
	 * [7]	: INVVD, rgb是否反轉
	 * [6]	: INVVDEN
	 * [5]	: INVPWREN
	 * [4]	: INVLEND
	 * [3]	: PWREN, LCD_PWREN output signal enable/disable
	 * [2]	: ENLEND
	 * [1]	: BSWP
	 * [0]	: HWSWP
	 */
	 pixeplace = plcparams->bpp == 24 ? (0) : |\
	 			 plcparams->bpp == 18 ? (1) : |\
	 			 (1<<1);
	 LCDCON5 = (plcparams->pin_pol.clk   << 10) |\
			   (plcparams->pin_pol.hsync << 9)  |\
			   (plcparams->pin_pol.vsync << 8)  |\
			   (plcparams->pin_pol.rgb   << 7)  |\
			   (plcparams->pin_pol.de    << 6)  |\
			   (plcparams->pin_pol.pwren << 5)  |\
			   (1<<11) | pixeplace;

在這裏插入圖片描述

	/* 
	 * [20: 0]:LCDBASEL [21: 1] of end address
	 */
	addr = plcparams->frm_base + plcparams->xres * plcparams->yres * plcparams->bpp;
	addr >>=1;
	addr &=0x1fffff;
	LCDSADDR2 = addr;

在這裏插入圖片描述

	/* framebuffer 地址 
	 * [29:21] :LCDBANK  [30:22] of fb
 	 * [20: 0] :LCDBASEU [21: 1] of fb
	 */
	addr = plcparams->frm_base & ~(1<<31);
	LCDSADDR1 = (addr >> 1);

4.2 完整代碼


#include "lcd.h"
#include "lcd_controller.h"
#include "../s3c2440_soc.h"

#define HCLK 100

void jz2440_lcd_pin_init(void)
{
	/* 初始化引腳 : 背光引腳 */
	GPBCON &= ~0x3;
	GPBCON |= 0x01;

	/* LCD專用引腳: VD0-VD23 */
	GPCCON = 0xaaaaaaaa;
	GPDCON = 0xaaaaaaaa;

	/* PWREN */
	GPGCON |= (3<<8);
}

/* 根據傳入的LCD參數設置LCD控制器 */
void s3c2440_lcd_controller_init(p_lcd_params plcparams)
{
	int pixeplace;
	unsigned int addr;

	jz2440_lcd_pin_init();
	/*
	 * [17:8]   : CLKVAL TFT: VCLK = HCLK / [(CLKVAL+1) x 2]
	 *						CLKVAL = HCLK/VCLK/2-1 = 100/9/2-1 = 4.5 + 0.5 = 5
	 * [6:5]	:11 = TFT LCD panel
	 * [4:1]	: bpp 支持8,16,24bpp
	 * [0]		: LCD video output and the logic enable/disable
	 * 
     */
    //int CLKVAL = 5;
	int CLKVAL = (float)HCLK/plcparams->time_seq.vclk/2-1+0.5;
	int BPP = plcparams->bpp  == 8 ? 0xb :\
			  plcparams->bpp  == 16 ? 0xc :\
			  0xd;	/* 0xd:24、32bpp */
	
	LCDCON1 = (CLKVAL << 8) | (3 << 5) | (BPP << 1);

	/* [31:24] : VBPD 		= tvb - 1
	 * [23:14] : LINEVAL 	= yres - 1
	 * [13:6]  : VFPD		= tvf - 1
	 * [5:0]   : VSPW		= tvp - 1
	 */
	LCDCON2 = ((plcparams->time_seq.tvb - 1) << 24)  |\
	          ((plcparams->yres - 1) << 14) 		  |\
	          ((plcparams->time_seq.tvf - 1) << 6) 	  |\
	          ((plcparams->time_seq.tvp - 1) << 0);

	/* [25:19] : HBPT 	  = thb - 1
 	 * 18:8]	 : HOZBAL	  = xres - 1
 	 * [7:0]  `: HFPD 	  = thf - 1
 	 */
	LCDCON3 = ((plcparams->time_seq.thb - 1) << 19) |\
			  ((plcparams->xres - 1) << 8)			 |\
			  ((plcparams->time_seq.thf - 1) << 0);
	
	/* [7:0]   : HSPW	  = thp - 1
	 */
	LCDCON4 =	((plcparams->time_seq.thp - 1)<<0);

	/* 用來設置引腳極性, 設置16bpp, 設置內存中象素存放的格式
	 * [12] : BPP24BL
	 * [11] : FRM565, 1-565
	 * [10] : INVVCLK, 0 = The video data is fetched at VCLK falling edge
	 * [9]	: HSYNC是否反轉
	 * [8]	: VSYNC是否反轉
	 * [7]	: INVVD, rgb是否反轉
	 * [6]	: INVVDEN
	 * [5]	: INVPWREN
	 * [4]	: INVLEND
	 * [3]	: PWREN, LCD_PWREN output signal enable/disable
	 * [2]	: ENLEND
	 * [1]	: BSWP
	 * [0]	: HWSWP
	 */
	pixeplace = plcparams->bpp == 32 ? (0) : \
	 			plcparams->bpp == 16 ? (1) : \
	 			(1<<1);
	
	LCDCON5 = (plcparams->pin_pol.clk   << 10) |\
			  (plcparams->pin_pol.hsync << 9)  |\
			  (plcparams->pin_pol.vsync << 8)  |\
			  (plcparams->pin_pol.rgb    << 7) |\
			  (plcparams->pin_pol.de     << 6) |\
			  (plcparams->pin_pol.pwren << 5)  |\
			  (1<<11) | pixeplace;

	/* framebuffer 地址 
	 * [29:21] :LCDBANK  [30:22] of fb
 	 * [20: 0] :LCDBASEU [21: 1] of fb
	 */
	addr = plcparams->frm_base & ~(1<<31);
	LCDSADDR1 = (addr >> 1);

	/* 
	 * [20: 0]:LCDBASEL [21: 1] of end address
	 */
	addr = plcparams->frm_base + plcparams->xres * plcparams->yres * plcparams->bpp/8;
	addr >>=1;
	addr &=0x1fffff;
	LCDSADDR2 = addr;
}

/* 根據傳入的LCD參數設置LCD控制器 */
void s3c2440_lcd_controller_enable(void)

{
	/* 背光引腳			:GBP0 */
	GPBDAT |= (1<<0);	
	
	/* pwren   		:給LCD提供AVDD */
	LCDCON5 |= (1<<3);
	
	/* LCDCON1'BITO':設置LCD控制器是否輸出信號 */
	LCDCON1 |= (1<<0);
}

/* 根據傳入的LCD參數設置LCD控制器 */
void s3c2440_lcd_controller_disable(void)
{
	/* 背光引腳			:GBP0 */
	GPBDAT &= ~(1<<0);	
	
	/* pwren   		:給LCD提供AVDD */
	LCDCON5 &= ~(1<<3);
	
	/* LCDCON1'BITO':設置LCD控制器是否輸出信號 */
	LCDCON1 &= ~(1<<0);
}

/* 設置調色板之前關閉LCD控制器 */
void s3c2440_lcd_controller_init_palette(void)
{
	volatile unsigned int *palette_base =  (volatile unsigned int *)0x4D000400;
	int i;

	int bit = LCDCON1 & (1<<0);

	/* LCDCON1'BIT 0 : 設置LCD控制器是否輸出信號 */
	if (bit)
		LCDCON1 &= ~(1<<0);

	for (i = 0; i < 256; i++)
	{
		/* 低16位 : rgb565 */ 
		*palette_base++ = i;
	}

	if (bit)
		LCDCON1 |= (1<<0);	
}

/* 定義結構體變量,存儲各種初始化函數的地址 */
struct lcd_controller s3c2440_lcd_controller = {
	.name 	  = "s3c2440_lcdcon",
	.init 	  = s3c2440_lcd_controller_init,
	.enable   = s3c2440_lcd_controller_enable,
	.disable  = s3c2440_lcd_controller_disable,
	.init_palette  = s3c2440_lcd_controller_init_palette,
};

/* 把s3c24400_lcd_controller註冊進p_array_lcd_controller中 */
void s3c2440_lcd_controller_add(void)
{
	register_lcd_controller(&s3c2440_lcd_controller);
}

三、目的函數編寫

1、畫點framebuffer.c文件編寫


#include "lcd.h"
#include "framebuffer.h"

/* 實現畫點 
/* bpp:32位 需要轉換成 16bpp 
 * 像素的基地址:fb_base + (每行多少字節)(xres*bpp/8)*y + (一行中像素多少字節)(x*bpp/8)
 * 獲得LCD參數: fb_base xres bpp
 */

static unsigned int fb_base;
static int xres, yres, bpp;

/* 獲得LCD參數 */
void fb_get_lcd_params(void)
{
	get_lcd_params(&fb_base, &xres, &yres, &bpp);
}

/* 把32bitsbpp 轉成 16bitsbpp */
unsigned short convert32bppto16bpp(unsigned int rgb)
{
	/* rgb:0x00RRGGBB */
	int r = (rgb>>16) & 0xff;
	int g = (rgb>>8)  & 0xff;
	int b = rgb & 0xff;
	
	/* rgb:0x565 */
	r = r >> 3;
	g = g >> 2;
	b = b >> 3;

	return ((r<<11) | (g<<5) | b);
}

/* 畫點函數 */
void draw_piont(int x, int y, unsigned int color)
{
	unsigned char  *pc;		/* 8bpp  */
	unsigned short *pw;		/* 16bpp */
	unsigned int   *pdw;	/* 32bpp */

	unsigned int pixel_base = fb_base + (xres * bpp / 8) * y + (x * bpp / 8);	//計算出單個像素地址

	switch (bpp)
	{
		case 8:
			pc  = (unsigned char *)pixel_base;
			*pc = color;
			break;
		case 16:
			pw  = (unsigned short *)pixel_base;
			*pw = convert32bppto16bpp(color);
			break;
		case 32:
			pdw  = (unsigned int *)pixel_base;
			*pdw = color;
			break;
	}
}

2、畫線、圈geometry.c文件編寫


#include "framebuffer.h"
#include "geometry.h"

/*
 * http://blog.csdn.net/p1126500468/article/details/50428613
 */
 //-------------畫圓函數。參數:圓心,半徑,顏色----------	
 // 	   畫1/8圓 然後其他7/8對稱畫  
 // 		 ---------------->X  
 // 		 |(0,0)   0  
 // 		 |	   7	 1	
 // 		 |	  6 	  2  
 // 		 |	   5	 3	
 // 	  (Y)V		  4  
 //  
 // 	 L = x^2 + y^2 - r^2  
 
 void draw_circle(int x, int y, int r, int color)  
 {	
	 int a, b, num;  
	 a = 0;  
	 b = r;  
	 while(22 * b * b >= r * r) 		 // 1/8圓即可  
	 {	
		 draw_piont(x + a, y - b,color); // 0~1  
		 draw_piont(x - a, y - b,color); // 0~7  
		 draw_piont(x - a, y + b,color); // 4~5  
		 draw_piont(x + a, y + b,color); // 4~3  
   
		 draw_piont(x + b, y + a,color); // 2~3  
		 draw_piont(x + b, y - a,color); // 2~1  
		 draw_piont(x - b, y - a,color); // 6~7  
		 draw_piont(x - b, y + a,color); // 6~5  
		   
		 a++;  
		 num = (a * a + b * b) - r*r;  
		 if(num > 0)  
		 {	
			 b--;  
			 a--;  
		 }	
	 }	
 }	
   
 //-----------畫線。參數:起始座標,終點座標,顏色--------	
 void draw_line(int x1,int y1,int x2,int y2,int color)
 {	
	 int dx,dy,e;  
	 dx=x2-x1;	 
	 dy=y2-y1;	
	 if(dx>=0)	
	 {	
		 if(dy >= 0) // dy>=0  
		 {	
			 if(dx>=dy) // 1/8 octant  
			 {	
				 e=dy-dx/2;  
				 while(x1<=x2)	
				 {	
					 draw_piont(x1,y1,color);  
					 if(e>0){y1+=1;e-=dx;}	   
					 x1+=1;  
					 e+=dy;  
				 }	
			 }	
			 else		 // 2/8 octant	
			 {	
				 e=dx-dy/2;  
				 while(y1<=y2)	
				 {	
					 draw_piont(x1,y1,color);  
					 if(e>0){x1+=1;e-=dy;}	   
					 y1+=1;  
					 e+=dx;  
				 }	
			 }	
		 }	
		 else			// dy<0  
		 {	
			 dy=-dy;   // dy=abs(dy)  
			 if(dx>=dy) // 8/8 octant  
			 {	
				 e=dy-dx/2;  
				 while(x1<=x2)	
				 {	
					 draw_piont(x1,y1,color);  
					 if(e>0){y1-=1;e-=dx;}	   
					 x1+=1;  
					 e+=dy;  
				 }	
			 }	
			 else		 // 7/8 octant	
			 {	
				 e=dx-dy/2;  
				 while(y1>=y2)	
				 {	
					 draw_piont(x1,y1,color);  
					 if(e>0){x1+=1;e-=dy;}	   
					 y1-=1;  
					 e+=dx;  
				 }	
			 }	
		 }	   
	 }	
	 else //dx<0  
	 {	
		 dx=-dx;	 //dx=abs(dx)  
		 if(dy >= 0) // dy>=0  
		 {	
			 if(dx>=dy) // 4/8 octant  
			 {	
				 e=dy-dx/2;  
				 while(x1>=x2)	
				 {	
					 draw_piont(x1,y1,color);  
					 if(e>0){y1+=1;e-=dx;}	   
					 x1-=1;  
					 e+=dy;  
				 }	
			 }	
			 else		 // 3/8 octant	
			 {	
				 e=dx-dy/2;  
				 while(y1<=y2)	
				 {	
					 draw_piont(x1,y1,color);  
					 if(e>0){x1-=1;e-=dy;}	   
					 y1+=1;  
					 e+=dx;  
				 }	
			 }	
		 }	
		 else			// dy<0  
		 {	
			 dy=-dy;   // dy=abs(dy)  
			 if(dx>=dy) // 5/8 octant  
			 {	
				 e=dy-dx/2;  
				 while(x1>=x2)	
				 {	
					 draw_piont(x1,y1,color);  
					 if(e>0){y1-=1;e-=dx;}	   
					 x1-=1;  
					 e+=dy;  
				 }	
			 }	
			 else		 // 6/8 octant	
			 {	
				 e=dx-dy/2;  
				 while(y1>=y2)	
				 {	
					 draw_piont(x1,y1,color);  
					 if(e>0){x1-=1;e-=dy;}	   
					 y1-=1;  
					 e+=dx;  
				 }	
			 }	
		 }	   
	 }	
 }	

3、寫字font.c文件編寫


#include "font.h"
#include "framebuffer.h"

/* 根據字母的點陣在LCD上描畫文字 使用linux的8x16點陣 */
extern const unsigned char fontdata_8x16[];

/* 獲得LCD參數 */
static unsigned int fb_base;
static int xres, yres, bpp;

void font_init(void)
{
	get_lcd_params(&fb_base, &xres, &yres, &bpp);
}

void fb_print_char(int x, int y, char c, unsigned int color)
{
	int i, j;
	/* 根據c的ascii碼在fontdata_8x16中得到點陣數據 */
	unsigned char *dots = &fontdata_8x16[c * 16];
	unsigned char data;
	int bit;
	
	/* 根據點陣來設置對應像素的顏色 */
	for (j = y; j < y+16; j++){
		data = *dots++;
		bit = 7;
		for (i = x; i < x+8; i++){
			if (data & (1 << bit))
				draw_piont(i, j, color);	
			bit--;		
		}
	}	
}

void fb_print_string(int x, int y, char *str, unsigned int color)
{
	int i, j;
	i = 0;

	while (str[i]){
		if (str[i] == '\n') 
			y = y + 16;
		else if (str[i] == '\r')
			x = 0;
		else{
			fb_print_char(x, y, str[i], color);
			x = x + 8;
			/* 超出行邊界 */
			if (x >= xres){
				x = 0;
				y = y + 16;
			}
		}
		i++;
	}
}

四、測試函數編寫


#include "geometry.h"
#include "font.h"

void lcd_test(void)
{
	unsigned int fb_base;
	int xres;
	int yres;
	int bpp;
	int x, y;
	unsigned short *p;
	unsigned int *p2;
	unsigned char *p0;

	/* 初始化LCD */
	lcd_init();

	/* 使能LCD */
	lcd_enable();

	/* 獲得LCD的參數:fb_base,分辨率(xres、yres),bpp */
	get_lcd_params(&fb_base, &xres, &yres, &bpp);
	fb_get_lcd_params();
	font_init();

	/* 往framebuf裏寫數據 
	 * bpp:8 , 紅綠藍 palette[xx]
	 * bpp:16,紅綠藍 565 
	 * bpp:32,紅綠藍 RRGGBB
	 */
	if (bpp == 8){
		/* palette[12] */
		p0 = (unsigned char *)fb_base;
		for (x = 0; x < xres ; x++)
			for (y = 0; y < yres; y++)
				*p0++ = 12;

		/* palette[47] */
		p0 = (unsigned char *)fb_base;
		for (x = 0; x < xres ; x++)
			for (y = 0; y < yres; y++)
				*p0++ = 47;
			
		/* palette[88] */
		p0 = (unsigned char *)fb_base;
		for (x = 0; x < xres ; x++)
			for (y = 0; y < yres; y++)
				*p0++ = 88;
			
		/* palette[0] */
		p0 = (unsigned char *)fb_base;
		for (x = 0; x < xres; x++)
			for (y = 0; y < yres; y++)
				*p0++ = 0;
	}
	else if (bpp == 16){
		/* Red */
		p = (unsigned short *)fb_base;
		for (x = 0; x < xres ; x++)
			for (y = 0; y < yres; y++)
				*p++ = 0xf800;

		/* Green */
		p = (unsigned short *)fb_base;
		for (x = 0; x < xres ; x++)
			for (y = 0; y < yres; y++)
				*p++ = 0x7e0;
			
		/* Blue */
		p = (unsigned short *)fb_base;
		for (x = 0; x < xres ; x++)
			for (y = 0; y < yres; y++)
				*p++ = 0x1f;
			
		/* black */
		p = (unsigned short *)fb_base;
		for (x = 0; x < xres; x++)
			for (y = 0; y < yres; y++)
				*p++ = 0;
	}
	else if (bpp == 32){
		/* Red */
		p2 = (unsigned int *)fb_base;
		for (x = 0; x < xres ; x++)
			for (y = 0; y < yres; y++)
				*p2++ = 0xff0000;

		/* Green */
		p2 = (unsigned int *)fb_base;
		for (x = 0; x < xres ; x++)
			for (y = 0; y < yres; y++)
				*p2++ = 0x00ff00;

		/* Blue */
		p2 = (unsigned int *)fb_base;
		for (x = 0; x < xres ; x++)
			for (y = 0; y < yres; y++)
				*p2++ = 0x0000ff;
			
		/* black */
		p2 = (unsigned int *)fb_base;
		for (x = 0; x < xres; x++)
			for (y = 0; y < yres; y++)
				*p2++ = 0;
	}
	//delay(1000000);
	
	/* 畫線 */
	draw_line(0, 0, xres - 1, 0, 0xff11);
	draw_line(xres - 1, 0, xres - 1, yres - 1, 0xffff);
	draw_line(0, yres - 1, xres - 1, yres - 1, 0xff00);
	draw_line(0, 0, 0, yres - 1, 0xff00ef);
	draw_line(0, 0, xres - 1, yres - 1, 0xff45);
	draw_line(xres - 1, 0, 0, yres - 1, 0xff07);

	//delay(1000000);

	/* 畫圓 */
	draw_circle(xres/2, yres/2, yres/4, 0xff);
	
	/* 寫字 */
	fb_print_string(10, 10, "www.100ask.net\n\r100ask.taobao.com", 0xff);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章