⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vgacon_lcd.c

📁 T6963LCD屏的驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
{	u16 i;	lcd_num_columns = LCD_NUM_COLUMNS;	lcd_num_lines   = LCD_NUM_LINES;        lcd_vram_base = (unsigned long)vram;        lcd_vram_len  = 0x2000;	lcd_data_port = 0x378;	lcd_status_port = lcd_data_port+1;	lcd_control_port = lcd_data_port+2;	lcd_type = TYPE_LCD;	lcd_type_name = "generic Toshiba T6963C";	// initialize control port	CEHI;  // disable chip	RDHI;  // disable reading from LCD	WRHI;  // disable writing to LCD	CDHI;  // command/status mode        DATAOUT; // make 8-bit parallel port an output port        write_lcd_command_word(SET_GRAPHIC_HOME_ADDRESS,ATTRIB_BASE);        write_lcd_command_word(SET_GRAPHIC_AREA,LCD_NUM_COLUMNS);        write_lcd_command_word(SET_TEXT_HOME_ADDRESS,TEXT_BASE);        write_lcd_command_word(SET_TEXT_AREA,LCD_NUM_COLUMNS);        write_lcd_command(SET_MODE | ATTRIBUTE_MODE | EXTERNAL_CG);        write_lcd_command_2_bytes(SET_OFFSET_REGISTER,CHARGEN_BASE>>11,0);        write_lcd_command(SET_CURSOR_PATTERN | 7); // cursor is 8 lines high        write_lcd_command_2_bytes(SET_CURSOR_POINTER,0,0);            // load 6x8 font with VGA map        write_lcd_command_word(SET_ADDRESS_POINTER,CHARGEN_BASE);        for (i=0; i<FONTDATAMAX; ++i) {            write_lcd_command_byte(DATA_WRITE_INC,fontdata_6x8[i]);        }        lcd_enable_text();        lcd_enable_graphic();        lcd_enable_cursor();        lcd_enable_blink();        lcd_clear_text_area();	printk("lcdcon: %s with %ldK of memory initialized (NO DETECTION IMPLEMENTED YET).\n",		lcd_type_name, lcd_vram_len/1024);	return "LCD-0";}static void lcdcon_init(struct vc_data *c, int init){        unsigned long p;#ifdef LCD_DEBUG        printk(KERN_DEBUG "lcdcon: lcdcon_init %i\n",init);#endif        c->vc_can_do_color = 0;	c->vc_cols = lcd_num_columns;	c->vc_rows = lcd_num_lines;       	c->vc_complement_mask = 0x0800;	 /* reverse video */        p = *c->vc_uni_pagedir_loc;        if (c->vc_uni_pagedir_loc == &c->vc_uni_pagedir ||            !--c->vc_uni_pagedir_loc[1])                con_free_unimap(c->vc_num);        c->vc_uni_pagedir_loc = lcdcon_uni_pagedir;        lcdcon_uni_pagedir[1]++;        if (!lcdcon_uni_pagedir[0] && p)                con_set_default_unimap(c->vc_num);}static void lcd_set_mem_top(struct vc_data *c){    if (c->vc_visible_origin != lcd_vram_base) {        printk("lcdcon: invalid lcd_set_mem_top");    }}static void lcdcon_deinit(struct vc_data *c){        /* When closing the last console, reset video origin */        if (!--lcdcon_uni_pagedir[1]) {                c->vc_visible_origin = lcd_vram_base;                lcd_set_mem_top(c);                con_free_unimap(c->vc_num);        }        c->vc_uni_pagedir_loc = &c->vc_uni_pagedir;        con_set_default_unimap(c->vc_num);#ifdef LCD_DEBUG        printk(KERN_DEBUG "lcdcon: lcdcon_deinit\n");#endif}static inline u16 lcd_convert_attr(u16 ch){    /* only reverse, blinking and reverse+blinking supported */    /* underline simulated by reverse */    u16 attr=0;#ifdef LCD_DEBUG_X        printk(KERN_DEBUG "lcdcon: lcdcon_convert_attr %i\n",ch);#endif    if (ch & 0x8000) {        // blink        attr |= 0x0800;    }    if (ch & 0x1000) {        // reverse        attr |= 0x0500;    }    if (ch & 0x0800) {        // underline, simulate by reverse        attr |= 0x0500;    }    return (ch & 0x00ff) | attr;}static u8 lcdcon_build_attr(struct vc_data *c, u8 color, u8 intensity, 			    u8 blink, u8 underline, u8 reverse){#ifdef LCD_DEBUG        printk(KERN_DEBUG "lcdcon: lcdcon_build_attr "               "%i,%i,%i,%i,%i\n",color,intensity,blink,underline,reverse);#endif    return (intensity & 3) |           ((underline & 1) << 2) |           ((reverse   & 1) << 3) |           ((blink     & 1) << 7);}static void lcdcon_invert_region(struct vc_data *c, u16 *p, int count){  /*        u16 i;        printk(KERN_DEBUG "lcdcon: unimplemented lcdcon_invert_region begin"               "%p,%i\n",p,count);	for (i=0; i<count; ++i) {	  printk(KERN_DEBUG "lcdcon: pos %i=%i\n",i,*(p+i));	}        printk(KERN_DEBUG "lcdcon: lcdcon_invert_region end\n");	*/}static void lcdcon_putc(struct vc_data *c, int ch, int y, int x){    u16 ch_converted;    u16 position;#ifdef LCD_DEBUG        printk(KERN_DEBUG "lcdcon: lcdcon_putc "               "%i,%i,%i\n",ch,y,x);#endif    position=POSITION(x,y);    ch_converted=lcd_convert_attr(ch);    // save character to memory buffer    screen[position]=ch;    // write character code to LCD    write_lcd_command_word(SET_ADDRESS_POINTER,TEXT_BASE+position);    write_lcd_command_byte(DATA_WRITE,ch_converted & 0x00ff);    // write character attribute to LCD    write_lcd_command_word(SET_ADDRESS_POINTER,ATTRIB_BASE+position);    write_lcd_command_byte(DATA_WRITE,ch_converted>>8);    lcd_enable_text();    lcd_enable_graphic();}static void lcdcon_putcs(struct vc_data *c, const unsigned short *s,		         int count, int y, int x){    u16 i;    u16 position;#ifdef LCD_DEBUG        printk(KERN_DEBUG "lcdcon: lcdcon_putcs begin "               "%p,%i,%i,%i\n",s,count,y,x);#endif    position=POSITION(x,y);    // save characters to memory buffer    for (i=0; i<count; ++i) {#ifdef LCD_DEBUG_X        printk(KERN_DEBUG "lcdcon: lcdcon_putcs char "               "%i\n",*(s+i));#endif        screen[position+i]=*(s+i);    }    // write character codes to LCD    write_lcd_command_word(SET_ADDRESS_POINTER,TEXT_BASE+position);    for (i=0; i<count; ++i) {        write_lcd_command_byte(DATA_WRITE_INC,            lcd_convert_attr(screen[position+i]) & 0x00ff);    }    // write character attributes to LCD    write_lcd_command_word(SET_ADDRESS_POINTER,ATTRIB_BASE+position);    for (i=0; i<count; ++i) {        write_lcd_command_byte(DATA_WRITE_INC,            lcd_convert_attr(screen[position+i])>>8);    }#ifdef LCD_DEBUG        printk(KERN_DEBUG "lcdcon: lcdcon_putcs end\n");#endif    lcd_enable_text();    lcd_enable_graphic();}static void lcdcon_clear(struct vc_data *c, int y, int x,             		 int height, int width){    int xx,yy;#ifdef LCD_DEBUG        printk(KERN_DEBUG "lcdcon: lcdcon_clear "               "%i,%i,%i,%i\n",y,x,height,width);#endif    if (width <= 0 || height <= 0)      	return;    for (yy=0; yy<height; ++yy) {        for (xx=0; xx<width; ++xx) {            lcdcon_putc(c,c->vc_video_erase_char,y+yy,x+xx);        }    }}                        static void lcd_memset(u16 d, const unsigned short ch, u16 count){    u16 i;    u16 ch_converted;    ch_converted=lcd_convert_attr(ch);    // memset to memory buffer    for (i=0; i<count; ++i) {        screen[d+i]=ch;    }    // memset to LCD text area    write_lcd_command_word(SET_ADDRESS_POINTER,TEXT_BASE+d);    for (i=0; i<count; ++i) {        write_lcd_command_byte(DATA_WRITE_INC,ch_converted & 0x00ff);    }    // memset to LCD attribute area    write_lcd_command_word(SET_ADDRESS_POINTER,ATTRIB_BASE+d);    for (i=0; i<count; ++i) {        write_lcd_command_byte(DATA_WRITE_INC,ch_converted>>8);    }}static void lcd_memmove(u16 d, u16 s, u16 count){    u16 i;    if (d<s) {        // move memory buffer        for (i=0; i<count; ++i) {            screen[d+i]=screen[s+i];	}    } else {        // move memory buffer        for (i=0; i<count; ++i) {            screen[d+count-1-i]=screen[s+count-1-i];	}    }    // update LCD text area    write_lcd_command_word(SET_ADDRESS_POINTER,TEXT_BASE+d);    for (i=0; i<count; ++i) {        write_lcd_command_byte(DATA_WRITE_INC,            lcd_convert_attr(screen[d+i]) & 0x00ff);    }    // update LCD attribute area    write_lcd_command_word(SET_ADDRESS_POINTER,ATTRIB_BASE+d);    for (i=0; i<count; ++i) {        write_lcd_command_byte(DATA_WRITE_INC,            lcd_convert_attr(screen[d+i])>>8);    }}static void lcdcon_bmove(struct vc_data *c, int sy, int sx,                         int dy, int dx, int height, int width){        u16 src, dest;#ifdef LCD_DEBUG        printk("lcdcon: lcdcon_bmove "               "%i,%i,%i,%i,%i,%i\n",sy,sx,dy,dx,height,width);#endif        if (width <= 0 || height <= 0)                return;        if (sx==0 && dx==0 && width==lcd_num_columns) {                lcd_memmove(POSITION(0,dy), POSITION(0,sy), height*width);        } else if (dy < sy || (dy == sy && dx < sx)) {                src  = POSITION(sx, sy);                dest = POSITION(dx, dy);                for (; height > 0; height--) {                        lcd_memmove(dest, src, width);                        src  += lcd_num_columns;                        dest += lcd_num_columns;                }        } else {                src  = POSITION(sx, sy+height-1);                dest = POSITION(dx, dy+height-1);          	for (; height > 0; height--) {                        lcd_memmove(dest, src, width);                        src  -= lcd_num_columns;                        dest -= lcd_num_columns;		}        }        lcd_enable_text();        lcd_enable_graphic();}static int lcdcon_switch(struct vc_data *c){	return 1;	/* redrawing needed */}static int lcdcon_set_palette(struct vc_data *c, unsigned char *table){	return -EINVAL;}static int lcdcon_blank(struct vc_data *c, int blank){        printk("lcdcon: unimplemented lcdcon_blank %i\n",blank);	return 0;}static int lcdcon_font_op(struct vc_data *c, struct console_font_op *op){	return -ENOSYS;}static int lcdcon_scrolldelta(struct vc_data *c, int lines){#ifdef LCD_DEBUG        printk(KERN_DEBUG "lcdcon: lcdcon_scrolldelta %i\n",lines);#endif	return 0;}static void lcdcon_cursor(struct vc_data *c, int mode){#ifdef LCD_DEBUG        printk(KERN_DEBUG "lcdcon: lcdcon_cursor %i\n",mode);#endif	if (mode == CM_ERASE) {                lcd_disable_cursor();		return;	}        write_lcd_command_2_bytes(SET_CURSOR_POINTER,c->vc_x,c->vc_y);	switch (c->vc_cursor_type & 0x0f) {		case CUR_LOWER_THIRD:	lcd_set_cursor_size(0, 1); break;		case CUR_LOWER_HALF:	lcd_set_cursor_size(0, 3); break;		case CUR_TWO_THIRDS:	lcd_set_cursor_size(0, 5); break;		case CUR_BLOCK:		lcd_set_cursor_size(0, 7); break;		case CUR_NONE:		lcd_set_cursor_size(8, 7); break;		default:		lcd_set_cursor_size(0, 1); break;	}        lcd_enable_cursor();        lcd_enable_text();        lcd_enable_graphic();}static int lcdcon_scroll(struct vc_data *c, int t, int b, int dir, int lines){#ifdef LCD_DEBUG        printk(KERN_DEBUG "lcdcon: lcdcon_scroll "               "t=%i,b=%i,dir=%i,lines=%i\n",t,b,dir,lines);#endif        if (!lines) return 0;        if (lines>c->vc_rows) lines=c->vc_rows;        switch (dir) {        case SM_UP:            lcd_memmove(POSITION(0,t),POSITION(0,t+lines),                        (b-t-lines)*lcd_num_columns);            lcd_memset(POSITION(0,b-lines),c->vc_video_erase_char,                       lines*lcd_num_columns);            break;        case SM_DOWN:            lcd_memmove(POSITION(0,t+lines),POSITION(0,t),                        (b-t-lines)*lcd_num_columns);            lcd_memset(POSITION(0,t),c->vc_video_erase_char,                       lines*lcd_num_columns);            break;        }        lcd_enable_text();        lcd_enable_graphic();#ifdef LCD_DEBUG        printk(KERN_DEBUG "lcdcon: lcdcon_scroll more "               "eattr=%i,lines=%i,lcd_num_columns=%i,c->vc_rows=%i\n",               c->vc_video_erase_char,lines,lcd_num_columns,c->vc_rows);#endif	return 0;}static int lcdcon_set_origin(struct vc_data *c){#ifdef LCD_DEBUG        printk(KERN_DEBUG "lcdcon: lcdcon_set_origin\n");#endif        c->vc_origin = c->vc_visible_origin = lcd_vram_base;        lcd_set_mem_top(c);        return 1;}static void lcdcon_save_screen(struct vc_data *c){        u16 i;        static int lcd_bootup_console = 0;#ifdef LCD_DEBUG        printk(KERN_DEBUG "lcdcon: lcdcon_set_origin\n");#endif        if (!lcd_bootup_console) {	  /* This is a gross hack, but here is the only place we can	   * set bootup console parameters without messing up generic	   * console initialization routines.	   */                lcd_bootup_console = 1;                c->vc_x = LCD_NUM_COLUMNS;                c->vc_y = LCD_NUM_LINES;        }        for (i=0; i<c->vc_screenbuf_size/2; ++i) {            *(c->vc_screenbuf+i)=screen[i];        }}/* *  The console `switch' structure for the LCD based console */struct consw vga_con = {	lcdcon_startup,		/* con_startup */	lcdcon_init,		/* con_init */	lcdcon_deinit,		/* con_deinit */	lcdcon_clear,		/* con_clear */	lcdcon_putc,		/* con_putc */	lcdcon_putcs,		/* con_putcs */	lcdcon_cursor,		/* con_cursor */	lcdcon_scroll,		/* con_scroll */	lcdcon_bmove,		/* con_bmove */	lcdcon_switch,		/* con_switch */	lcdcon_blank,		/* con_blank */	lcdcon_font_op,		/* con_font_op */	lcdcon_set_palette,	/* con_set_palette */	lcdcon_scrolldelta,	/* con_scrolldelta */	NULL, //lcdcon_set_origin,	/* con_set_origin */	NULL, // lcdcon_save_screen,	/* con_save_screen */	lcdcon_build_attr,	/* con_build_attr */	NULL, // lcdcon_invert_region,	/* con_invert_region */};#ifdef STANDALONEint main(void){    unsigned short buffer[80];    struct vc_data c;    int i;    ioperm(0x378,3,1);    ioperm(0x80,1,1);    c.vc_rows=16;    c.vc_cols=40;    c.vc_video_erase_char=32;    lcdcon_startup();    lcdcon_init(&c,1);    for (i=0; i<16; ++i) {        buffer[0]=i/10+48;        buffer[1]=i%10+48;        lcdcon_putcs(&c,buffer,2,i,0);    }    lcdcon_scroll(&c,0,16,1,1);    return 0;}#endif // def STANDALONE

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -