; ; hello.echo.44.asm ; ; 115200 baud serial echo and LED hello-world program ; ; Neil Gershenfeld ; CBA MIT 7/28/07 ; ; (c) Massachusetts Institute of Technology 2007 ; Permission granted for experimental and personal use; ; license for commercial sale available from MIT. ; .include "tn44def.inc" .equ led_sink_pin = PA1 ; LED sink pin .equ led_source_pin = PA2 ; LED source pin .equ txpin = PA6; transmit pin .equ rxpin = PA7; receive pin .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 ; ; print ; .macro print ldi zl,low(@0*2) ldi zh,high(@0*2) rcall print_db .endmacro ; ; putbitdelay ; putchar bit delay ; 115200 baud, 20 MHz clock /8 ; .macro putbitdelay nop nop nop nop nop nop nop nop nop nop nop nop .endmacro ; ; getbitdelay ; getchar bit delay ; 115200 baud, 20 MHz clock /8 ; .macro getbitdelay nop nop nop nop nop nop nop .endmacro .cseg .org 0 rjmp reset ; ; putchar ; assumes no line driver (doesn't invert bits) [LOOKS LIKE IT INVERTS BITS] ; .equ sb = 1; number of stop bits putchar: ldi bitcnt, 9+sb; 1+8+sb com txbyte; invert everything [?BECAUSE HIGH=0 IN GETCHAR?] sec; set start bit [ALREADY SET BY COM] putchar0: brcc putchar1; if carry set [BRANCH IF CARRY NOT SET] sbi PORTA, txpin; send a '0' rjmp putchar2; else putchar1: cbi PORTA, txpin ; send a '1' nop ; even out timing putchar2: putbitdelay; one bit delay lsr txbyte; get next bit dec bitcnt; if not all bits sent brne putchar0; send next bit ret; ; ; getchar ; assumes no line driver (doesn't invert bits) ; getchar: ldi bitcnt,9 ; 8 data bit + 1 stop bit getchar1: sbis PINA, rxpin ; wait for start bit rjmp getchar1 getbitdelay ; delay to middle of bit [MIDDLE OF _BYTE_?] getchar2: getbitdelay ; delay to next bit getbitdelay ; clc ; clear carry sbis PINA, rxpin ; if RX pin high skip [HIGH = 0?] sec ; otherwise set carry dec bitcnt breq getchar3 ; return if all bits read ror rxbyte ; otherwise shift bit into receive byte rjmp getchar2 ; go get next bit getchar3: ret ; ; blink ; blink the LED ; blink: sbi PORTA, led_source_pin ldi temp, 255 blink_loop: ldi temp1, 255 blink_loop1: dec temp1 brne blink_loop1 dec temp brne blink_loop cbi PORTA, led_source_pin ret ; ; print_db ; prints a null-terminated .db string ; print_db: print_loop: lpm ; [LOAD MEMORY LOCATION Z REG POINTS TO INTO R0] mov txbyte,R0 cpi txbyte,0 breq return rcall putchar adiw zl, 1 ; [INCREMENT MEMORY POINTER (WHY NOT ZH:ZL?)] rjmp print_loop return: ret ; ; main program ; reset: ; ; set fuse low byte to 0x7E for 20 MHz resonator ; ; 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 PORTA, txpin sbi DDRA, txpin ; ; init LED pins ; cbi PORTA, led_source_pin sbi DDRA, led_source_pin cbi PORTA, led_sink_pin sbi DDRA, led_sink_pin ; ; start main loop ; loop: rcall getchar print message message: .db "received character: ",0 mov txbyte, rxbyte rcall putchar rcall blink mov txbyte, rxbyte rcall putchar rcall blink ldi txbyte,10 rcall putchar rjmp loop