;***************************************************** ;subroutine to send characters from ROM to number LCD ;***************************************************** ROMS: nextc: lpm ;Get next character from ROM tst R0 ;See if at end of message breq end1 ;If so, next message cpi charcnt ,8 ;addressing changes at char #8! brne wrtit ;at char 8, fix it ldi wreg ,0xC0 ;Set address to last 8 chars rcall lcdcmd wrtit: mov wreg, R0 ;Send it to the LCD rcall lcdput adiw ZL, 1 ;Increment Z-pointer inc charcnt ;keep track of chars on display rjmp nextc ;Loop for more end1: ldi longtime, 100 ;Wait 1.5 second for human to read it ldi timeout, 0 ;Delay 15 ms wait1: rcall delay dec longtime brne wait1 ret ;***************************************************** ;subroutine to send characters from RAM to number LCD ;***************************************************** RAMS: nextc1: ld R0, Z ;Get next character from RAM tst R0 ;See if at end of message breq end2 ;If so, next message cpi charcnt ,8 ;addressing changes at char #8! brne wrtit1 ;at char 8, fix it ldi wreg ,0xC0 ;Set address to last 8 chars rcall lcdcmd wrtit1: mov wreg, R0 ;Send it to the LCD rcall lcdput adiw ZL, 1 ;Increment Z-pointer inc charcnt ;keep track of chars on display rjmp nextc1 ;Loop for more end2: ldi longtime, 100 ;Wait 1.5 second for human to read it ldi timeout, 0 ;Delay 15 ms wait2: rcall delay dec longtime brne wait2 ret ;****************************************************** ;subroutine to send characters from ROM to function LCD ;****************************************************** ROMS1: nextc2: lpm ;Get next character from ROM tst R0 ;See if at end of message breq end3 ;If so, next message cpi charcnt ,8 ;addressing changes at char #8! brne wrtit2 ;at char 8, fix it ldi wreg ,0xC0 ;Set address to last 8 chars rcall lcdcmd1 wrtit2: mov wreg, R0 ;Send it to the LCD rcall lcdput1 adiw ZL, 1 ;Increment Z-pointer inc charcnt ;keep track of chars on display rjmp nextc2 ;Loop for more end3: ldi longtime, 100 ;Wait 1.5 second for human to read it ldi timeout, 0 ;Delay 15 ms wait3: rcall delay dec longtime brne wait3 ret ;***************************************************************************** ; LCD commands for number LCD ;***************************************************************************** ================================================ ; Clear entire LCD and delay for a bit lcdclr: ldi wreg,1 ;Clear LCD command rcall lcdcmd ldi timeout,256 ;Delay 15 mS for clear command rcall delay ret ================================================ ; Initialize LCD module lcdinit:ldi wreg,0 out PORTC,wreg ;Pull all pins low ldi wreg,0x80 out PORTA,wreg ldi wreg,0xff ;All pins on port C and A are outputs out DDRC,wreg out DDRA,wreg ldi timeout,256 ;Wait at least 15 mS at power up rcall delay ; LCD specs call for 3 repetitions as follows ldi wreg,3 ;Function set out PORTC,wreg ;to 8-bit mode nop ;nop is data setup time sbi PORTA,lcd1e ;Toggle enable line cbi PORTA,lcd1e ldi timeout,256 ;Wait at least 15 mS rcall delay ldi wreg,3 ;Function set out PORTC,wreg nop sbi PORTA,lcd1e ;Toggle enable line cbi PORTA,lcd1e ldi timeout,256 ;Wait at least 15 ms rcall delay ldi wreg,3 ;Function set out PORTC,wreg nop sbi PORTA,lcd1e ;Toggle enable line cbi PORTA,lcd1e ldi timeout,256 ;Wait at least 15 ms rcall delay ldi wreg,2 ;Function set, 4 line interface out PORTC,wreg nop sbi PORTA,lcd1e ;Toggle enable line cbi PORTA,lcd1e ldi wreg,0b11110000 ;Make 4 data lines inputs out DDRC,wreg ; Finally, ; At this point, the normal 4 wire command routine can be used ldi wreg,0b00100000 ;Function set, 4 wire, 1 line, 5x7 font rcall lcdcmd ldi wreg,0b00001100 ;Display on, no cursor, no blink rcall lcdcmd ldi wreg,0b00000110 ;Address increment, no scrolling rcall lcdcmd ret ============================================ ; Wait for LCD to go unbusy lcdwait:ldi wreg,0xF0 ;Make 4 data lines inputs out DDRC,wreg sbi PORTA,lcd1rw ;Set r/w pin to read cbi PORTA,lcd1rs ;Set register select to command waitloop: sbi PORTA,lcd1e ;Toggle enable line cbi PORTA,lcd1e in lcdstat,PINC ;Read busy flag ;Read, and ignore lower nibble sbi PORTA,lcd1e ;Toggle enable line cbi PORTA,lcd1e sbrc lcdstat,3 ;Loop until done rjmp waitloop ret ============================================= ; Send command in wreg to LCD lcdcmd: push wreg ;Save character rcall lcdwait ;Wait for LCD to be ready cbi PORTA, lcd1rw ldi wreg,0xFF ;Make all port C pins outputs out DDRC,wreg pop wreg ;Get character back push wreg ;Save another copy swap wreg ;Get upper nibble andi wreg,0x0F ;Strip off upper bits out PORTC,wreg ;Put on port nop ;wait for data setup time sbi PORTA,lcd1e ;Toggle enable line cbi PORTA,lcd1e pop wreg ;Recall character andi wreg,0x0F ;Strip off upper bits out PORTC,wreg ;Put on port nop sbi PORTA,lcd1e ;Toggle enable line cbi PORTA,lcd1e ldi wreg,0xF0 ;Make 4 data lines inputs out DDRC,wreg ret ============================================= ; Send character data in wreg to LCD lcdput: push wreg ;Save character rcall lcdwait ;Wait for LCD to be ready cbi PORTA,lcd1rw ldi wreg,0xFF ;Make all port C pins outputs out DDRC,wreg pop wreg ;Get character back push wreg ;Save another copy swap wreg ;Get upper nibble andi wreg,0x0F ;Strip off upper bits out PORTC,wreg ;Put on port sbi PORTA,lcd1rs ;Register select set for data nop sbi PORTA,lcd1e ;Toggle enable line cbi PORTA,lcd1e cbi PORTA,lcd1rs pop wreg ;Recall character andi wreg,0x0F ;Strip off upper bits out PORTC,wreg ;Put on port sbi PORTA,lcd1rs ;Register select set for data nop sbi PORTA,lcd1e ;Toggle enable line cbi PORTA,lcd1e cbi PORTA,lcd1rs ldi wreg,0xF0 ;Make 4 data lines inputs out DDRC,wreg ret ============================================= ;***** Timer 0 overflow interrupt handler t0int: set ;Set T flag ldi wreg,TSTOP ;Timer 0 off out TCCR0,wreg ;Stop timer reti ;Done, return ;***** Delay n*64 microseconds using timer 0, delay time passed in timeout ; weird construction, interrupt is called like a subroutine delay: in wreg,SREG ;Save status register push wreg out TCNT0,timeout clt ;Clear T ldi wreg,TCK256 ;Timer 0 prescaler, CK / 256 out TCCR0,wreg ;Run timer dwait: brtc dwait ;Wait for timer 0 interrupt to set T pop wreg ;Restore status register out SREG,wreg ret ;************************************************************************************* ; LCD commands for function LCD ;************************************************************************************* ================================================ ; Clear entire LCD and delay for a bit lcdclr1: ldi wreg,1 ;Clear LCD command rcall lcdcmd1 ldi timeout,256 ;Delay 15 mS for clear command rcall delay ret ================================================ ; Initialize LCD module lcdinit1: ldi wreg,0 out PORTC,wreg ;Pull all pins low ldi wreg,0x80 out PORTA,wreg ldi wreg,0xff ;All pins on port C and A are outputs out DDRC,wreg out DDRA,wreg ldi timeout,256 ;Wait at least 15 mS at power up rcall delay ; LCD specs call for 3 repetitions as follows ldi wreg,3 ;Function set out PORTC,wreg ;to 8-bit mode nop ;nop is data setup time sbi PORTA,lcd2e ;Toggle enable line cbi PORTA,lcd2e ldi timeout,256 ;Wait at least 15 mS rcall delay ldi wreg,3 ;Function set out PORTC,wreg nop sbi PORTA,lcd2e ;Toggle enable line cbi PORTA,lcd2e ldi timeout,256 ;Wait at least 15 ms rcall delay ldi wreg,3 ;Function set out PORTC,wreg nop sbi PORTA,lcd2e ;Toggle enable line cbi PORTA,lcd2e ldi timeout,256 ;Wait at least 15 ms rcall delay ldi wreg,2 ;Function set, 4 line interface out PORTC,wreg nop sbi PORTA,lcd2e ;Toggle enable line cbi PORTA,lcd2e ldi wreg,0b11110000 ;Make 4 data lines inputs out DDRC,wreg ; Finally, ; At this point, the normal 4 wire command routine can be used ldi wreg,0b00100000 ;Function set, 4 wire, 1 line, 5x7 font rcall lcdcmd1 ldi wreg,0b00001100 ;Display on, no cursor, no blink rcall lcdcmd1 ldi wreg,0b00000110 ;Address increment, no scrolling rcall lcdcmd1 ret ============================================ ; Wait for LCD to go unbusy lcdwait1: ldi wreg,0xF0 ;Make 4 data lines inputs out DDRC,wreg sbi PORTA,lcd2rw ;Set r/w pin to read cbi PORTA,lcd2rs ;Set register select to command waitloop1: sbi PORTA,lcd2e ;Toggle enable line cbi PORTA,lcd2e in lcdstat,PINC ;Read busy flag ;Read, and ignore lower nibble sbi PORTA,lcd2e ;Toggle enable line cbi PORTA,lcd2e sbrc lcdstat,3 ;Loop until done rjmp waitloop1 ret ============================================= ; Send command in wreg to LCD lcdcmd1: push wreg ;Save character rcall lcdwait1 ;Wait for LCD to be ready cbi PORTA,lcd2rw ldi wreg,0xFF ;Make all port C pins outputs out DDRC,wreg pop wreg ;Get character back push wreg ;Save another copy swap wreg ;Get upper nibble andi wreg,0x0F ;Strip off upper bits out PORTC,wreg ;Put on port nop ;wait for data setup time sbi PORTA,lcd2e ;Toggle enable line cbi PORTA,lcd2e pop wreg ;Recall character andi wreg,0x0F ;Strip off upper bits out PORTC,wreg ;Put on port nop sbi PORTA,lcd2e ;Toggle enable line cbi PORTA,lcd2e ldi wreg,0xF0 ;Make 4 data lines inputs out DDRC,wreg ret ============================================= ; Send character data in wreg to LCD lcdput1: push wreg ;Save character rcall lcdwait1 ;Wait for LCD to be ready cbi PORTA,lcd2rw ldi wreg,0xFF ;Make all port C pins outputs out DDRC,wreg pop wreg ;Get character back push wreg ;Save another copy swap wreg ;Get upper nibble andi wreg,0x0F ;Strip off upper bits out PORTC,wreg ;Put on port sbi PORTA,lcd2rs ;Register select set for data nop sbi PORTA,lcd2e ;Toggle enable line cbi PORTA,lcd2e cbi PORTA,lcd2rs pop wreg ;Recall character andi wreg,0x0F ;Strip off upper bits out PORTC,wreg ;Put on port sbi PORTA,lcd2rs ;Register select set for data nop sbi PORTA,lcd2e ;Toggle enable line cbi PORTA,lcd2e cbi PORTA,lcd2rs ldi wreg,0xF0 ;Make 4 data lines inputs out DDRC,wreg ret