; file mt.asm ; ; auth: Raphael Holzer, Dr. ; Swiss Federal Insitute of Technology ; 1015 Lausanne, Switzerland ; ; date: 17 April 2002 ; this program is testing some of the functions of the Olimex AVR-MT board ; ================= ; definitions ; ================= .include "2313def.inc" ; === constant definitions === ; PORT B .equ BUZZER = 4 .equ BUTTON1 = 5 .equ BUTTON2 = 6 .equ BUTTON3 = 7 ; PORTD .equ TX = 0 .equ RX = 1 .equ DALLAS = 2 .equ RELAY = 3 .equ RS = 4 .equ FREQ = 5 .equ E = 6 .set clock = 10000000 ; === register definitions === .def w = r16 ; working register .def _w = r17 ; working register for interrupts .def a0 = r18 ; argument for subroutines ; ================== ; main program ; ================== reset: ldi w, RAMEND ; load stack pointer SP out SPL,w sbi DDRD,RELAY ; RELAY = output rcall lcd_init ; initialize LCD module rcall beep ; short beep rjmp main str: .db "bc ",0 ; ASCII string constant main: ldi a0,'a' ; display a single character rcall lcd_putc ldi zl, low(str*2) ; load address of "string" into z ldi zh,high(str*2) rcall lcd_puts ; display "string" rcall lcd_putsi ; display "string" immediate .db "123",0 ; loop: sbi PORTD,RELAY ; turn on relay and LED rcall wait_500ms cbi PORTD,RELAY ; turn off relay and LED rcall wait_500ms rjmp loop ; infinite loop ; ============ ; buzzer ; ============ beep: ldi a0,250 ; load loop counter sbi DDRB,BUZZER ; make output sbi PORTB,BUZZER ; buzzer high rcall wait_1000us cbi PORTB,BUZZER ; buzzer low rcall wait_1000us dec a0 ; decrement loop count brne beep+2 ; loop back if not zero ret ; ================== ; LCD routines ; ================== lcd_init: sbi DDRD,E ; make E output sbi DDRD,RS ; make RS output in w,DDRB ori w,0x0f out DDRB,w ; make LCD data output cbi PORTD,RS ; address IR ldi w,100 rcall wait_ms ; wait 100ms ldi a0, 0b0011 ; 8-bit interface rcall lcd_put_nibble ldi w,100 rcall wait_ms ; wait 100ms ldi a0, 0b0011 ; 8-bit interface rcall lcd_put_nibble ldi w,100 rcall wait_ms ; wait 100ms ldi a0, 0b0010 ; 4-bit interface rcall lcd_put_nibble ldi w,2 rcall wait_ms ; wait 2ms ; this displays 8chars ($00..$07) followed by 8chars ($40..$47) ldi a0,0b00101000 ; 4-bits, 2-line 5x8-dots rcall lcd_ir ldi a0,0b00001111 ; disply=1, cursor=1, blink=1 rcall lcd_ir ldi a0,0b00000001 ; display clear rcall lcd_ir ldi w,2 rcall wait_ms ; wait 2ms ret lcd_ir: ; in a0 data byte to write to IR cbi PORTD,RS ; address IR rjmp lcd_put_byte lcd_putc: ; in a0 character to put to LCD sbi PORTD,RS ; address DR lcd_put_byte: ; in a0 data to put to LCD 4-bit interface push a0 ; temporary save a0 swap a0 ; get high nibble (D4..D7) rcall lcd_put_nibble ; put high nibble (D4..D7) pop a0 ; restore a0 ; put low nibble (D0..D3) ; (fall through) lcd_put_nibble: ; in a0 (lower nibble) in w,PORTB ; read whole portB andi a0,0x0f ; extract low nibble andi w, 0xf0 ; extract high nibble or w, a0 ; combine the two out PORTB,w ; update portB sbi PORTD,E ; pulse E=1 ldi w,100 rcall wait_us ; wait 100us cbi PORTD,E ; pulse E=0 ldi w,100 rcall wait_us ; wait 100us ret ; === LCD put string === ; displays the null-terminated "string" constant pointed by z lcd_puts: lpm ; read character pointed by Z tst r0 ; test for 0 breq lcd_puts_done mov a0,r0 rcall lcd_putc ; display character adiw zl,1 ; increment character pointer rjmp lcd_puts ; loop back lcd_puts_done: ret ; === LCD put string immediate === ; displays the null-terminated "string" constant ; following immediately the function call "lcd_putsi" lcd_putsi: pop zh ; load "return address" into z pop zl ; it's the begin of the "string" lsl zl ; multiply z by 2 rol zh ; to transform word->byte pointer rcall lcd_puts ; display the "string" adiw zl,1 ; increment z pointer lsr zh ; divide z by 2 ror zl ; to transform byte->word pointer ijmp ; indirect jump to address after "string" ; =================== ; wait routines ; =================== wait_1000ms: ; wait 1000 miliseconds (ms) rcall wait_500ms wait_500ms: ; wait 500 miliseconds (ms) rcall wait_250ms wait_250ms: ; wait 250 miliseconds (ms) ldi w,250 rcall wait_ms ret wait_ms: ; wait "w" miliseconds (ms) push w rcall wait_1000us pop w dec w brne PC-4 ret wait_1000us: ; wait 1000 microseconds (us) rcall wait_500us wait_500us: ; wait 500 microseconds (us) rcall wait_250us wait_250us: ; wait 250 microseconds (us) ldi w,249 rcall wait_us ret wait_us: ; wait "w" microseconds (us) ; in w dec w rcall wait7 brne PC-2 ret wait7: ret ; wait 7 cycles