?? lcd_drv.c
字號:
} // 計算兩點的垂直距離 tmp = y2 - y1; // 用點組成垂直的直線 for (i = 0; i <= tmp; i++ ) { lcd_kernel_pixel(x, y1 + i,color); } return;}// 繪制一條水平直線static void lcd_kernel_hline(int x1, int x2, int y, COLOR color){ int tmp; int i = 0; // 如果起始點的x坐標大于終止點的x坐標, 則交換起始點和終止點 if (x1 > x2) { tmp = x1; x1 = x2; x2 = tmp; } // 計算兩點的水平距離 tmp = x2 - x1; // 用點組成水平的直線 for (i = 0; i <= tmp; i++ ) { lcd_kernel_pixel(x1 + i, y, color); } return;}// 繪制一個矩形邊框// 邊框左上角坐標為(start_x, start_y)// 邊框右下角坐標為(end_x, end_y))static void lcd_kernel_rectangle(int start_x,int start_y,int end_x,int end_y,COLOR color){ lcd_kernel_vline(start_x, start_y, end_y, color); /* 繪制左邊框 */ lcd_kernel_vline(end_x, start_y, end_y, color); /* 繪制右邊框 */ lcd_kernel_hline(start_x, end_x, start_y, color); /* 繪制上邊框 */ lcd_kernel_hline(start_x, end_x, end_y, color); /* 繪制下邊框 */ return;}// 顯示一個ASCII字符// codes為指定ASCII字符的8 x 16點陣數組static void lcd_kernel_text_en(int x, int y, unsigned char* codes, COLOR color){ int i, j; // 顯示8 x 16的點陣 for (i = 0;i < 16; i++) { // 移動x坐標至要顯示的字符的右側的邊界上 x += 8; // 從左向右顯示一行點 for (j = 0; j < 8; j++) { // x坐標向左移一個像素 x--; // 根據點陣信息顯示一個指定顏色的點 if ((codes[i] >> j) & 0x1) { lcd_kernel_pixel(x, y, color); } } // 開始顯示新的一行, y坐標向下移一個像素 y++; } return;}// 顯示一個中文字符// codes為指定中文字符的16 * 16點陣數組static void lcd_kernel_text_chs(int x, int y, unsigned char* codes, COLOR color){ int i, j, k; // 顯示16 * 16的點陣 for(i = 0;i < 16; i++) { // 循環兩次, // 先顯示字符的左半部分的一行, // 然后顯示字符的右半部分的一行 for (j = 0; j < 2; j++) { // 計算x坐標的位置 // 左半部分的起始點為x + 8 // 右半部分的起始點為x + 16 x += 8 * ( j + 1); // 從左向右顯示左(右)半部分的一行 for (k = 0; k < 8; k++) { // x坐標向左移一個像素 x--; // 根據點陣信息顯示一個指定顏色的點 // codes[2 * i + j]計算行點陣在數組中的位置: // 2 * i + 0 為左半部分的行點陣信息 // 2 * i + 1 為右半部分的行點陣信息 if ((codes[2 * i + j] >> k) & 0x1) { lcd_kernel_pixel(x,y,color); } } } // 開始顯示新的一行, // x坐標回到原先位置, // y坐標向下移一個像素 x -= 8; ++y; } return;}// 用指定顏色清屏static void lcd_kernel_clear(COLOR color){ unsigned char buffer[3]; long i; COLOR pure_color; printk("\nclear the screen to color '%d' !!!\n",color); pure_color=color&0x0000f; pure_color|=(color&0x000f)<<4; // 根據像素點的位置, 設置相應的更新字節 // 以兩個像素點為一組, 共三個字節// buffer[0] = color & 0xff; //green(M)+red(L)// buffer[1] = ((color & 0xf00) >> 8) + ((color & 0x0f) << 4);//red(M)+blue(L)// buffer[2] = color >> 4;//blue(M)+green(L) // *(__lcd_base + i) = 0x11;// *(__lcd_base + i) = buffer[i % 3]; // 更新顯示緩沖區 // for (i = 0; i < SCR_X * SCR_Y * 3 * BPP / 8; i++) for (i = 0; i < SCR_X * SCR_Y * 1 * BPP / 8; i++){ *(__lcd_base + i) = pure_color; /* if (i & 0x1) { pure_color = (color & 0x000f) << 4; // add by ywc *(__lcd_base + i) &= 0x0f; *(__lcd_base + i) |= pure_color; }else{ pure_color = (color & 0x000f); // add by ywc *(__lcd_base + i) &= 0xf0; *(__lcd_base + i) |= pure_color; } */ }}// 打開LCD設備文件static int lcd_kernel_open(struct inode *node, struct file *file){ return 0;}// 對LCD設備文件進行讀操作static int lcd_kernel_read(struct file *file, char *buff, size_t count, loff_t *offp){ return 0;}// 對LCD設備文件進行寫操作static int lcd_kernel_write(struct file *file, const char *buff, size_t count, loff_t *offp){ return 0;}/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// by ywc 2004-04-17 對LCD設備文件按字節進行寫操作(應用程序無法通過write//調用到該函數???暫時沒有找出原因,所以先通過ioctl復制位圖緩沖到顯存//static int lcd_kernel_writeb(struct file *file, const char *buff, size_t count, loff_t *offp)static int lcd_kernel_writeb(const char *buff, size_t count, int rownum){ int i; unsigned char * fb_ptr; fb_ptr=(unsigned char *)__lcd_base; // printk("\n!!!enter the lcd_kernel_writeb()"); for(i=0;i<count;i++){ //*(fb_ptr+20*rownum+i)=*(buff+i); *(fb_ptr+i)=*(buff+i); } return 0;}static int lcd_kernel_writew(const char *buff, size_t count, int rownum){ int i; // unsigned char * fb_ptr; unsigned long * fb_ptr_word; fb_ptr_word=(unsigned long *)__lcd_base; // printk("\n!!!enter the lcd_kernel_writeb()"); for(i=0;i<count/4;i++){ *(fb_ptr_word+i)=*((unsigned long *)buff+i); } return 0;}///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 對LCD設備文件進行讀寫之外的其它操作static int lcd_kernel_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ // 根據指令ID, 調用相應的操作 switch (cmd) { // 清屏 case LCD_Clear: { struct lcd_display clear_display; // 復制顯示結構 if (copy_from_user(&clear_display, (struct lcd_display*)arg, sizeof(struct lcd_display))) { printk("System: copy_from_user error!\n"); printk("Caller: lcd_kernel_ioctl -> LCD_Clear!\n"); return -1; } // 調用清屏函數 lcd_kernel_clear(clear_display.color); break; } // 繪制像素點 case LCD_Draw_Pixel: { struct lcd_display pixel_display; // 復制顯示結構 if ( copy_from_user(&pixel_display, (struct lcd_display*)arg, sizeof(struct lcd_display))) { printk("System: copy_from_user error!\n"); printk("Caller: lcd_kernel_ioctl -> LCD_Draw_Pixel!\n"); return -1; } // 調用畫點函數 lcd_kernel_pixel(pixel_display.x1, pixel_display.y1, pixel_display.color); break; } // 繪制垂直直線 case LCD_Draw_VLine: { struct lcd_display vline_display; // 復制顯示結構 if ( copy_from_user(&vline_display, (struct lcd_display*)arg, sizeof(struct lcd_display))) { printk("System: copy_from_user error!\n"); printk("Caller: lcd_kernel_ioctl -> LCD_Draw_VLine!\n"); return -1; } // 調用畫線函數 lcd_kernel_vline(vline_display.x1, vline_display.y1, vline_display.y2, vline_display.color); break; } // 繪制水平直線 case LCD_Draw_HLine: { struct lcd_display hline_display; // 復制顯示結構 if ( copy_from_user(&hline_display,(struct lcd_display*)arg,sizeof(struct lcd_display))) { printk("System: copy_from_user error!\n"); printk("Caller: lcd_kernel_ioctl -> LCD_Draw_HLine!\n"); return -1; } // 調用畫線函數 lcd_kernel_hline(hline_display.x1, hline_display.x2, hline_display.y1, hline_display.color); break; } // 繪制矩形邊框 case LCD_Draw_Rectangle: { struct lcd_display rect_display; // 復制顯示結構 if (copy_from_user(&rect_display, (struct lcd_display*)arg, sizeof(struct lcd_display))) { printk("System: copy_from_user error!\n"); printk("Caller: lcd_kernel_ioctl -> LCD_Draw_Rectangle!\n"); return -1; } // 調用畫矩形邊框函數 lcd_kernel_rectangle(rect_display.x1, rect_display.y1, rect_display.x2, rect_display.y2, rect_display.color); break; } //將位圖緩沖區寫入顯存 add by ywc 2004-04-18 case LCD_Draw_Buf: { struct lcd_display buf_display; // 復制顯示結構 if ( copy_from_user(&buf_display, (struct lcd_display*)arg, sizeof(struct lcd_display))) { printk("System: copy_from_user error!\n"); printk("Caller: lcd_kernel_ioctl -> LCD_Draw_Buf!\n"); return -1; } //調用復制位圖緩沖到顯存的函數 //lcd_kernel_writeb(buf_display.lcd_buf, buf_display.lcd_buf_size,buf_display.lcd_row); lcd_kernel_writew(buf_display.lcd_buf, buf_display.lcd_buf_size,buf_display.lcd_row); break; } // 顯示一個ASCII字符 case LCD_Write_EN: { struct lcd_display en_display; // 復制顯示結構 if ( copy_from_user(&en_display, (struct lcd_display*)arg, sizeof(struct lcd_display))) { printk("System: copy_from_user error!\n"); printk("Caller: lcd_kernel_ioctl -> LCD_Write_EN!\n"); return -1; } // 調用顯示字符函數 lcd_kernel_text_en(en_display.x1, en_display.y1, en_display.codes, en_display.color); break; } // 顯示一個中文字符 case LCD_Write_CN: { struct lcd_display cn_display; // 復制顯示結構 if ( copy_from_user(&cn_display,(struct lcd_display*)arg,sizeof(struct lcd_display))) { printk("System: copy_from_user error!\n"); printk("Caller: lcd_kernel_ioctl -> LCD_Write_EN!\n"); return -1; } // 調用顯示字符函數 lcd_kernel_text_chs(cn_display.x1, cn_display.y1, cn_display.codes, cn_display.color); break; } // 保存屏幕指定部分內容 case LCD_Save_SCR: { // 調用保存屏幕函數 lcd_kernel_save_screen((*(struct lcd_screen*)arg).x1, (*(struct lcd_screen*)arg).y1, (*(struct lcd_screen*)arg).x2, (*(struct lcd_screen*)arg).y2, (*(struct lcd_screen*)arg).buffer); break; } // 加載保存的屏幕內容到指定位置 case LCD_Load_SCR: { struct lcd_screen load_screen; // 復制屏幕結構 if ( copy_from_user(&load_screen,(struct lcd_screen*)arg,sizeof(struct lcd_screen))) { printk("System: copy_from_user error!\n"); printk("Caller: lcd_kernel_ioctl -> LCD_Load_SCR!\n"); return -1; } // 調用加載屏幕函數 lcd_kernel_load_screen(load_screen.x1, load_screen.y1, *load_screen.buffer); break; } // 釋放保存的屏幕內容 case LCD_Release_SCR: { lcd_kernel_release_screen((*(struct lcd_screen*)arg).buffer); break; } default: printk("Unknown LCD command ID.\n"); } return 0;}// 釋放LCD設備文件static int lcdexp_release(struct inode *node, struct file *file){ // 緩存基址復位 __lcd_base = (unsigned char *)0xc0000000; return 0;}// LCD設備文件操作結構static struct file_operations lcd_fops = { open: lcd_kernel_open, /* 打開設備文件 */ read: lcd_kernel_read, /* 設備文件的讀操作 */ ioctl: lcd_kernel_ioctl, /* 設備文件的其它操作 */ //write: lcd_kernel_write, /* 設備文件的寫操作 */ write: lcd_kernel_writeb, /* 設備文件的寫操作 */ release: lcdexp_release, /* 釋放設備文件 */};// 初始化LCD設備static int __init lcd_kernel_init(void){ int result; /* 注冊設備結果 */ long i; // 設置顯示緩存基地址 __lcd_base = (unsigned char*)0xc0000000; // 注冊LCD系統設備 printk("\nRegistering LCD Device\t--->\t"); result = register_chrdev(DEV_MAJOR, "lcd_ep7312", &lcd_fops); if (result < 0) { printk(KERN_INFO "[FAILED: Cannot register lcd_ep7312!]\n"); return -EBUSY; } else printk("[OK]\n"); printk("Initializing LCD Device\t--->\t\n"); // 設置LCD setup_lcd(); // printk(" \nsetup_lcd runing end !//y ywc"); // 初始化顯示緩沖區內容// for (i=0; i < SCR_X * SCR_Y * 3 * BPP / 8; i++)/* for (i=0; i < SCR_X * SCR_Y * 1* BPP / 8; i++) { *__lcd_base++ = 0x00; // *__lcd_base= 0x11; __lcd_base++; // *(__lcd_base)&= 0xf0;// *(__lcd_base)|= 0x04;// *(__lcd_base)&= 0x0f;// *(__lcd_base)|= 0x40; // __lcd_base++; }*/ //printk("\n__lcd_base=%p,*__lcd_base=%x\n",--__lcd_base,*__lcd_base); // 復位顯存基地址 __lcd_base =(unsigned char*)0xc0000000; //printk("\n__lcd_base=%x\n",__lcd_base); printk("[OK]\n"); // 顯示成功加載信息 printk("\nEP7312 LCD Driver installed.\n");// printk("Written by BIT200009123.\n"); return 0;}// 釋放LCD設備static void __exit lcd_kernel_exit(void){ // 注銷LCD設備, 并釋放保存屏幕緩沖區 printk("Unregistering LCD Device\t--->\t"); unregister_chrdev(DEV_MAJOR, "lcd_ep7312"); printk("[OK]\n"); return;}// 初始化模塊module_init(lcd_kernel_init);// 卸載模塊module_exit(lcd_kernel_exit);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -