/* LCD driver routines CodeVisionAVR C Compiler (C) 1998-2000 Pavel Haiduc, HP InfoTech S.R.L. */ unsigned char _base_y[4]={0x80,0xc0}; #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=3 #endasm unsigned char _lcd_x,_lcd_y,_lcd_maxx; 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: rcall __lcd_delay sbi __lcd_port,__lcd_enable ;EN=1 rcall __lcd_delay sbic __lcd_pin,__lcd_busy_flag rjmp __lcd_busy cbi __lcd_port,__lcd_enable ;EN=0 #endasm } #asm __lcd_write_nibble: andi r26,0xf0 or r26,r27 out __lcd_port,r26 ;write sbi __lcd_port,__lcd_enable ;EN=1 rcall __lcd_delay cbi __lcd_port,__lcd_enable ;EN=0 __lcd_delay: nop nop nop nop nop nop ret #endasm void _lcd_write_data(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 rcall __lcd_write_nibble ;RD=0, write MSN ld r26,y swap r26 rcall __lcd_write_nibble ;write LSN sbi __lcd_port,__lcd_rd ;RD=1 #endasm } /* write a byte to the LCD character generator or display RAM */ #if funcused lcd_write_byte 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); } #endif #if funcused lcd_read_byte #asm __lcd_read_nibble: sbi __lcd_port,__lcd_enable ;EN=1 rcall __lcd_delay in r30,__lcd_pin ;read cbi __lcd_port,__lcd_enable ;EN=0 rcall __lcd_delay andi r30,0xf0 ret #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 rcall __lcd_delay rcall __lcd_read_nibble ;read MSN mov r26,r30 rcall __lcd_read_nibble ;read LSN cbi __lcd_port,__lcd_rd ;RD=0 swap r30 or r30,r26 #endasm } #endif /* set the LCD display position x=0..39 y=0..3 */ #if funcused lcd_gotoxy || funcused lcd_putchar || funcused lcd_puts || funcused lcd_putsf 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; } #endif // clear the LCD #if funcused lcd_clear || funcused lcd_init void lcd_clear(void) { _lcd_ready(); // RS=0 _lcd_write_data(0xc); // cursor off _lcd_ready(); _lcd_write_data(1); // clear _lcd_x=_lcd_y=0; } #endif #if funcused lcd_putchar || funcused lcd_puts || funcused lcd_putsf 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 } #endif // write the string str located in SRAM to the LCD #if funcused lcd_puts void lcd_puts(char *str) { #ifdef _MODEL_TINY_ #asm clr r31 #endasm #endif #ifdef _MODEL_SMALL_ #asm ldd r31,y+1 #endasm #endif #asm ld r30,y __lcd_puts0: ld r26,z+ tst r26 breq __lcd_puts1 st -y,r26 rcall _lcd_putchar rjmp __lcd_puts0 __lcd_puts1: #endasm } #endif // write the string str located in FLASH to the LCD #if funcused lcd_putsf void lcd_putsf(char flash *str) { #asm ld r30,y ldd r31,y+1 __lcd_putsf0: lpm tst r0 breq __lcd_putsf1 adiw r30,1 st -y,r0 rcall _lcd_putchar rjmp __lcd_putsf0 __lcd_putsf1: #endasm } #endif #if funcused lcd_init void _long_delay(void) { #asm clr r26 clr r27 __long_delay0: sbiw r26,1 ;2 cycles brne __long_delay0 ;2 cycles #endasm } // initialize the LCD controller void 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_write_data(0x30); _long_delay(); _lcd_write_data(0x30); _long_delay(); _lcd_write_data(0x30); _long_delay(); _lcd_write_data(0x20); _lcd_ready(); _lcd_write_data(0x28); _lcd_ready(); _lcd_write_data(6); lcd_clear(); } #endif