; ; hello7.1.asm ; Neil Gershenfeld CBA MIT 12/14/05 ; 16x2 44780 LCD hello-world ; master processor ; .include "tn13def.inc" .def txbyte = R17 .def lcdbyte = R18 .def bitcnt = R19 .def temp = R20 .def temp1 = R21 .def temp2 = R22 .def temp3 = R23 .equ E = PB2 .equ RS = PB1 .equ RS_bit = 7 .equ DB7 = PB2 .equ DB6 = PB1 .equ DB5 = PB0 .equ DB4 = PB3 .equ txpin = PB3 .cseg .org 0 rjmp reset ; ; lcd_putchar ; lcd_putchar: ; ; set RS ; sbi PORTB, RS ; ; load high nibble ; clr txbyte sbrc lcdbyte, 7 ori txbyte, (1 << DB7) sbrc lcdbyte, 6 ori txbyte, (1 << DB6) sbrc lcdbyte, 5 ori txbyte, (1 << DB5) sbrc lcdbyte, 4 ori txbyte, (1 << DB4) ; ; send to processor #2 ; rcall putchar ; ; strobe E after delay ; nop nop nop nop nop nop nop cbi PORTB, E nop nop nop nop nop nop nop sbi PORTB, E ; ; wait ; rcall lcd_delay ; ; load low nibble ; clr txbyte sbrc lcdbyte, 3 ori txbyte, (1 << DB7) sbrc lcdbyte, 2 ori txbyte, (1 << DB6) sbrc lcdbyte, 1 ori txbyte, (1 << DB5) sbrc lcdbyte, 0 ori txbyte, (1 << DB4) ; ; send to processor #2 ; rcall putchar ; ; strobe E after delay ; nop nop nop nop nop nop nop cbi PORTB, E nop nop nop nop nop nop nop sbi PORTB, E ; ; wait ; rcall lcd_delay ret ; ; putchar ; assumes no line driver (doesn't invert bits) ; .equ sb = 1; number of stop bits putchar: ldi bitcnt, 9+sb; 1+8+sb com txbyte; invert everything sec; set start bit putchar0: brcc putchar1; if carry set sbi PORTB, txpin; send a '0' rjmp putchar2; else putchar1: cbi PORTB, txpin ; send a '1' nop ; even out timing putchar2: rcall bit_delay; one bit delay rcall bit_delay lsr txbyte; get next bit dec bitcnt; if not all bits sent brne putchar0; send next bit ret; ; ; bit delay ; .equ b = 17 ; 9600 bps bit_delay: ldi temp, b bitloop: dec temp brne bitloop ret ; ; lcd_long_delay ; .equ lcd_long_delay_time = 100 lcd_long_delay: ldi temp1, lcd_long_delay_time lcd_long_delay1: ldi temp2, lcd_long_delay_time lcd_long_delay2: ldi temp3, lcd_long_delay_time lcd_long_delay3: dec temp3 brne lcd_long_delay3 dec temp2 brne lcd_long_delay2 dec temp1 brne lcd_long_delay1 ret ; ; lcd_delay ; .equ lcd_delay_time = 100 lcd_delay: ldi temp1, lcd_delay_time lcd_delay1: ldi temp2, lcd_delay_time lcd_delay2: dec temp2 brne lcd_delay2 dec temp1 brne lcd_delay1 ret ; ; lcd_putcmd ; lcd_putcmd: ; ; clear RS ; cbi PORTB, RS ; ; send data bits to processor #2 ; rcall putchar ; ; strobe E after delay ; nop nop nop nop nop nop nop cbi PORTB, E nop nop nop nop nop nop nop sbi PORTB, E ; ; wait ; rcall lcd_delay ret ; ; lcd_init ; lcd_init: ; ; power-up delay ; rcall lcd_delay sbi PORTB, E ; ; initialization sequence ; ldi txbyte, (1 << DB5) + (1 << DB4) rcall lcd_putcmd rcall lcd_long_delay ldi txbyte, (1 << DB5) + (1 << DB4) rcall lcd_putcmd ldi txbyte, (1 << DB5) + (1 << DB4) rcall lcd_putcmd ; ; 4-bit interface ; ldi txbyte, (1 << DB5) rcall lcd_putcmd ; ; two lines, 5x7 font ; ldi txbyte, (1 << DB5) rcall lcd_putcmd ldi txbyte, (1 << DB7) rcall lcd_putcmd ; ; display on ; clr txbyte rcall lcd_putcmd ldi txbyte, (1 << DB7) + (1 << DB6) + (1 << DB5) rcall lcd_putcmd ; ; entry mode ; clr txbyte rcall lcd_putcmd ldi txbyte, (1 << DB6) + (1 << DB5) rcall lcd_putcmd ret ; ; lcd_print ; prints a null-terminated string ; lcd_print: lcd_print_loop: lpm mov lcdbyte,R0 cpi lcdbyte,0 breq return rcall lcd_putchar inc zl rjmp lcd_print_loop return: ret ; ; strings to print ; line_1: .db "Hello to",0 line_2: .db "the world!",0 ; ; reset routine ; reset: ; ; set stack pointer to top of RAM ; ldi temp, low(RAMEND) out SPL, temp ; ; init I/O pins ; cbi PORTB, txpin sbi DDRB, txpin cbi PORTB, E sbi DDRB, E cbi PORTB, RS sbi DDRB, RS ; ; init LCD ; rcall lcd_init ; ; infinite main loop ; main: ; ; go to zero position ; clr txbyte rcall lcd_putcmd ldi txbyte, (1 << DB5) rcall lcd_putcmd ; ; print first line ; ldi zl,low(line_1*2) ldi zh,high(line_1*2) rcall lcd_print ; ; move to second line ; ldi txbyte, (1 << DB7) + (1 << DB6) rcall lcd_putcmd clr txbyte rcall lcd_putcmd ; ; print second line ; ldi zl,low(line_2*2) ldi zh,high(line_2*2) rcall lcd_print ; ; pause ; rcall lcd_long_delay ; ; clear display ; clr txbyte rcall lcd_putcmd ldi txbyte, (1 << DB4) rcall lcd_putcmd ; ; repeat ; rjmp main