; ; hello.echo.44.asm ; ; 115200 baud serial echo and LED hello-world program ; ; Neil Gershenfeld ; CBA MIT 10/12/09 ; ; (c) Massachusetts Institute of Technology 2009 ; Permission granted for experimental and personal use; ; license for commercial sale available from MIT. ; .include "tn44def.inc" .equ led_pin = PB2; LED pin .equ led_port = PORTB; LED port .equ led_dir = DDRB; LED dir .equ txpin = PA6; transmit pin .equ rxpin = PA7; receive pin .equ comm_port = PORTA; comm port .equ comm_dir = DDRA; comm direction .equ comm_pins = PINA; comm pins .def bitcnt = R16; bit counter .def temp = R17; temporary storage .def temp1 = R18; temporary storage .def txbyte = R19; transmit byte .def rxbyte = R20; receive byte .equ button_port = PORTA ; button port (note same as comm) .equ button_dir = DDRA ; pin direction (note same as comm) .equ button_pin = PA3; button .equ pina_ins = PINA ; input pins ; ; print ; .macro print ldi zl,low(@0*2) ldi zh,high(@0*2) rcall print_db .endmacro .cseg .org 0 rjmp reset ; ; half_bit_delay ; serial half bit delay ; half_bit_delay: ldi temp, 25; 115200 baud (20 MHz clock /1) half_bit_delay_loop: dec temp brne half_bit_delay_loop ret ; ; putchar ; assumes no line driver (doesn't invert bits) ; ;putchar: ; ldi bitcnt, 10; 1 start + 8 data + 1 stop bit ; com txbyte; invert everything ; sec; set start bit ; putchar0: ; brcc putchar1; if carry set ; sbi comm_port, txpin; send a '0' ; rjmp putchar2; else ; putchar1: ; cbi comm_port, txpin ; send a '1' ; nop; even out timing ; putchar2: ; rcall half_bit_delay; bit delay ; rcall half_bit_delay; " ; lsr txbyte; get next bit ; dec bitcnt; if not all bits sent ; brne putchar0; send next bit ; ret; ; ; ; blink_delay ; LED blink delay ; blink_delay: ldi temp, 255 blink_delay_loop: ldi temp1, 255 blink_delay_loop1: dec temp1 brne blink_delay_loop1 dec temp brne blink_delay_loop ret ; ; blink ; blink the LED ; blink: sbi led_port, led_pin rcall blink_delay cbi led_port, led_pin ret ; ; print_db ; prints a null-terminated .db string ; ;print_db: ; print_loop: ; lpm ; mov txbyte,R0 ; cpi txbyte,0 ; breq return ; rcall putchar ; adiw zl, 1 ; rjmp print_loop ; return: ; ret getButton: sbic pina_ins, button_pin ; check if button is low rjmp getButton getButtonRel: sbis pina_ins, button_pin ; don't proceed until button released and pin pulled back up rjmp getButtonRel ret toggleLED: ldi temp, 1 ; temp is what the bit is set at sbic pina_ins, led_pin ; if bit is set yay, if not, don't skip and set it to zero ldi temp, 0 cbi led_port, led_pin ; should be zero going to 1 sbrc temp, 0 ; if temp == 1 skip (or if temp !=1 execute (i.e. temp == 0)) sbi led_port, led_pin ; zero goes to one ret ; LED toggled! ; ; main program ; reset: ; ; set fuse low byte to 0x7E for 20 MHz resonator ; ; set clock divider to /1 ; ldi temp, (1 << CLKPCE) ldi temp1, (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0) out CLKPR, temp out CLKPR, temp1 ; ; set stack pointer to top of RAM ; ldi temp, high(RAMEND) out SPH, temp ldi temp, low(RAMEND) out SPL, temp ; ; init comm pin ; sbi comm_port, txpin sbi comm_dir, txpin ; ; init LED pins ; cbi led_port, led_pin sbi led_dir, led_pin ; ; init Button pins ; going from b00 so no transitions need to be worried about but we clear anyway cbi button_port, button_pin ; clear pin empty cbi button_dir, button_pin ; set direction to input (zero) sbi button_port, button_pin ; pull pini-up ; ; start main loop ; loop: rcall getButton ; sbis pina_ins, led_pin sbi led_port, led_pin ; rcall toggleLed rcall getButton ; sbis pina_ins, led_pin cbi led_port, led_pin ; cbi led_port, led_pin ; rcall blink rjmp loop