/* LCD driver routines CodeVisionAVR C Compiler (C) 1998-2004 Pavel Haiduc, HP InfoTech S.R.L. */ #asm .equ __lcd_direction=__lcd_port-1 .equ __lcd_pin=__lcd_port-2 .equ __lcd_rs=0 .equ __lcd_rd=1 .equ __lcd_enable=2 .equ __lcd_busy_flag=7 #endasm #pragma used+ static unsigned char _base_y[4]={0x80,0xc0}; unsigned char _lcd_x,_lcd_y,_lcd_maxx; #pragma used- static void _lcd_delay(void) { #asm ldi r31,15 __lcd_delay0: dec r31 brne __lcd_delay0 #endasm } void _lcd_ready(void) { #asm in r26,__lcd_direction andi r26,0xf ;set as input out __lcd_direction,r26 sbi __lcd_port,__lcd_rd ;RD=1 cbi __lcd_port,__lcd_rs ;RS=0 __lcd_busy: #endasm _lcd_delay(); #asm sbi __lcd_port,__lcd_enable ;EN=1 #endasm _lcd_delay(); #asm in r26,__lcd_pin cbi __lcd_port,__lcd_enable ;EN=0 #endasm _lcd_delay(); #asm sbi __lcd_port,__lcd_enable ;EN=1 #endasm _lcd_delay(); #asm cbi __lcd_port,__lcd_enable ;EN=0 sbrc r26,__lcd_busy_flag rjmp __lcd_busy #endasm } static void _lcd_write_nibble(void) { #asm andi r26,0xf0 or r26,r27 out __lcd_port,r26 ;write sbi __lcd_port,__lcd_enable ;EN=1 #endasm _lcd_delay(); #asm cbi __lcd_port,__lcd_enable ;EN=0 #endasm _lcd_delay(); } void _lcd_write_data(unsigned char data) { #asm cbi __lcd_port,__lcd_rd ;RD=0 in r26,__lcd_direction ori r26,0xf0 | (1<<__lcd_rs) | (1<<__lcd_rd) | (1<<__lcd_enable) ;set as output out __lcd_direction,r26 in r27,__lcd_port andi r27,0xf ld r26,y #endasm _lcd_write_nibble(); //RD=0, write MSN #asm ld r26,y swap r26 #endasm _lcd_write_nibble(); //write LSN #asm sbi __lcd_port,__lcd_rd ;RD=1 #endasm } /* write a byte to the LCD character generator or display RAM */ void lcd_write_byte(unsigned char addr, unsigned char data) { _lcd_ready(); _lcd_write_data(addr); _lcd_ready(); #asm sbi __lcd_port,__lcd_rs ;RS=1 #endasm _lcd_write_data(data); } static void _lcd_read_nibble(void) { #asm sbi __lcd_port,__lcd_enable ;EN=1 #endasm _lcd_delay(); #asm in r30,__lcd_pin ;read cbi __lcd_port,__lcd_enable ;EN=0 #endasm _lcd_delay(); #asm andi r30,0xf0 #endasm } static unsigned char lcd_read_byte0(void) { _lcd_delay(); _lcd_read_nibble(); // read MSN #asm mov r26,r30 #endasm _lcd_read_nibble(); // read LSN #asm cbi __lcd_port,__lcd_rd ;RD=0 swap r30 or r30,r26 #endasm } /* read a byte from the LCD character generator or display RAM */ unsigned char lcd_read_byte(unsigned char addr) { _lcd_ready(); _lcd_write_data(addr); _lcd_ready(); #asm in r26,__lcd_direction andi r26,0xf ;set as input out __lcd_direction,r26 sbi __lcd_port,__lcd_rs ;RS=1 #endasm return lcd_read_byte0(); } /* set the LCD display position x=0..39 y=0..3 */ void lcd_gotoxy(unsigned char x, unsigned char y) { _lcd_ready(); // RS=0 _lcd_write_data(_base_y[y]+x); _lcd_x=x; _lcd_y=y; } // clear the LCD void lcd_clear(void) { _lcd_ready(); // RS=0 _lcd_write_data(2); // cursor home _lcd_ready(); _lcd_write_data(0xc); // cursor off _lcd_ready(); _lcd_write_data(1); // clear _lcd_x=_lcd_y=0; } #pragma keep+ void lcd_putchar(char c) { #asm push r30 push r31 ld r26,y set cpi r26,10 breq __lcd_putchar1 clt #endasm ++_lcd_x; if (_lcd_x>_lcd_maxx) { #asm("__lcd_putchar1:") ++_lcd_y; lcd_gotoxy(0,_lcd_y); #asm("brts __lcd_putchar0") }; #asm rcall __lcd_ready sbi __lcd_port,__lcd_rs ;RS=1 ld r26,y st -y,r26 rcall __lcd_write_data __lcd_putchar0: pop r31 pop r30 #endasm } #pragma keep- // write the string str located in SRAM to the LCD void lcd_puts(char *str) { char k; while (k=*str++) lcd_putchar(k); } // write the string str located in FLASH to the LCD void lcd_putsf(char flash *str) { char k; while (k=*str++) lcd_putchar(k); } static void _long_delay(void) { #asm clr r26 clr r27 __long_delay0: sbiw r26,1 ;2 cycles brne __long_delay0 ;2 cycles #endasm } static void _lcd_init_write(unsigned char data) { #asm cbi __lcd_port,__lcd_rd ;RD=0 in r26,__lcd_direction ori r26,0xf7 ;set as output out __lcd_direction,r26 in r27,__lcd_port andi r27,0xf ld r26,y #endasm _lcd_write_nibble(); //RD=0, write MSN #asm sbi __lcd_port,__lcd_rd ;RD=1 #endasm } // initialize the LCD controller unsigned char lcd_init(unsigned char lcd_columns) { #asm cbi __lcd_port,__lcd_enable ;EN=0 cbi __lcd_port,__lcd_rs ;RS=0 #endasm _lcd_maxx=lcd_columns; _base_y[2]=lcd_columns+0x80; _base_y[3]=lcd_columns+0xc0; _long_delay(); _lcd_init_write(0x30); _long_delay(); _lcd_init_write(0x30); _long_delay(); _lcd_init_write(0x30); _long_delay(); _lcd_init_write(0x20); _long_delay(); _lcd_write_data(0x28); _long_delay(); _lcd_write_data(4); _long_delay(); _lcd_write_data(0x85); _long_delay(); #asm in r26,__lcd_direction andi r26,0xf ;set as input out __lcd_direction,r26 sbi __lcd_port,__lcd_rd ;RD=1 #endasm if (lcd_read_byte0()!=5) return 0; _lcd_ready(); _lcd_write_data(6); lcd_clear(); return 1; }