📄 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 + -