; ; 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. ; ; ;cp (compare) ;brne (branch if not equal) ;breq (branch if equal) ;sbic (skip if bit in I/O register cleared) ;sbis (skip if bit in I/O register set) ; ; ; .include "tn44def.inc" .equ ledpa0 = PA0 ; LED source pin .equ ledpa1 = PA1 ; LED source pin .equ ledpa2 = PA2 ; LED source pin .equ ledpa3 = PA3 ; LED source pin .equ button = PB2 ; 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 temp2 = R21 .def temp3 = R22 .def temp4 = R23 .def temp6 = R24 .def temp7 = R25 .def temp8 = R26 .def temp9 = R27 .def temp10 = R28 .def count_reg = R29 .def count_reg2 = R30 .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 ;(NO OPERATION - PERFORMS A SINGLE CYCLE WITH NO OPERATION) 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) ; .equ sb = 1; number of stop bits putchar: ldi bitcnt, 9+sb; 1+8+sb (LOAD IMMEDIATE) com txbyte; invert everything (ONE'S COMPLEMENT-INVERT EVERYTHING) sec; set start bit (SET CARRY) putchar0: brcc putchar1; if carry set ;(BRANCH IF CARRY CLEARED) sbi PORTA, txpin; send a '0' ; (SET BIT IN I/O REGISTER) rjmp putchar2; else ; (RELATIVE JUMP) putchar1: cbi PORTA, txpin ; send a '1' (CLEAR BIT IN I/O REGISTER) nop ; even out timing (NO OPERATION ONE CYCLE) putchar2: putbitdelay; one bit delay (MACRO "putbitdelay") lsr txbyte; get next bit (LOGICAL SHIFT RIGHT) dec bitcnt; if not all bits sent (DECREMENT) brne putchar0; send next bit (BRANCH IF NOT EQUAL) ret; (SUBROUTINE RETURN) ; ; getchar ; assumes no line driver (doesn't invert bits) ; getchar: ldi bitcnt,9 ; 8 data bit + 1 stop bit (LOAD IMMEDIATE) getchar1: ;rcall fdloop_2 ; fade on ;rcall fdloop_3 ; fade off sbis PINA, rxpin ; wait for start bit (SKIP IF BIT IN I/O REGISTER SET) rjmp getchar1 ;(RELATIVE JUMP) getbitdelay ; delay to middle of bit MACRO getchar2: getbitdelay ; delay to next bit getbitdelay ; clc ; clear carry sbis PINA, rxpin ; if RX pin high skip (SKIP IF BIT IN I/O REGISTER SET) sec ; otherwise set carry (SET CARRY) dec bitcnt ;(DECREMENT (SUBTRACTS -1- FROM THE CONTENTS OF THE REGISTER) breq getchar3 ; return if all bits read (BRANCH IF EQUAL) ror rxbyte ; otherwise shift bit into receive byte (ROTATE RIGHT THROUGH CARRY) rjmp getchar2 ; go get next bit (RELATIVE JUMP) getchar3: ret ; ;added script to compare user input to 3 ; getcompare: print question question: .db "How many times did I blink?",10 nop nop nop nop ldi bitcnt,9 getcompare1: sbis PINA, rxpin rjmp getcompare1 getbitdelay getcompare2: getbitdelay getbitdelay clc sbis PINA, rxpin sec dec bitcnt breq getcompare3 ror rxbyte rjmp getcompare2 getcompare3: print message message: .db "you typed: ",0 mov txbyte, rxbyte ; (COPY REGISTER) rcall putchar ; (RELATIVE CALL SUB ROUTINE) ldi txbyte,10 ; (LOAD IMMEDIATE) rcall putchar ; (RELATIVE CALL SUB ROUTINE) nop subi rxbyte,48 ;ldi temp,3 cp rxbyte, count_reg breq getcompare4 print wrong wrong: .db "wrong...",10 cpi rxbyte,84 brne getcompare5 getcompare4: print right right: .db "right!",10 nop rcall fdloop_2 ; working fade rcall fdloop_3 rcall fdloop_2 ; working fade rcall fdloop_3 rcall fdloop_2 ; working fade getcompare5: ret ; ; blink ; blink the LED ; blink: sbi PORTA, ledpa0 ;(SET BIT I/O) ldi temp, 255 ;(LOAD IMMEDIATE) blink_loop: ldi temp1, 255 ;(LOAD IMMEDIATE) blink_loop1: dec temp1 ;(DECREMENT TEMP1) brne blink_loop1 ;(BRANCH IF NOT EQUAL) dec temp ; (DECREMENT TEMP) brne blink_loop ; (BRANCH IF NOT EQUAL) cbi PORTA, ledpa0 ret blink_off: sbi PORTA, ledpa0 cbi PORTA, ledpa0 ldi temp, 255 blink_off_loop: ldi temp1, 255 blink_off_loop1: dec temp1 brne blink_off_loop1 dec temp brne blink_off_loop sbi PORTA, ledpa0 cbi PORTA, ledpa0 ret ; ; print_db ; prints a null-terminated .db string ; print_db: print_loop: lpm ; (LOAD PROGRAM MEMORY) mov txbyte,R0 ; (COPY REGISTER) cpi txbyte,0 ; (COMPARE WITH IMMEDIATE) breq return ; (BRANCH IF EQUAL TO return:) rcall putchar ; (relative call) adiw zl, 1 ; (ADD IMEDIATE TO WORD in this case 1) rjmp print_loop ; relative jump 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) ;(LOAD IMMEDIATE) out SPH, temp; (OUT TO I/O LOCATION) ldi temp, low(RAMEND) out SPL, temp; (OUT TO I/O LOCATION) ; ; init comm pin ; cbi PORTA, txpin ;(CHANGED TO FROM sbi TO cbi clear bit in transmit pin) sbi DDRA, txpin ; (SET BIT IN I/O transmit PIN) ; ; init LED pins ; cbi PORTA, ledpa0 sbi DDRA, ledpa0 cbi PORTA, ledpa1 sbi DDRA, ledpa1 cbi PORTA, ledpa2 sbi DDRA, ledpa2 cbi PORTA, ledpa3 sbi DDRA, ledpa3 cbi DDRB, button sbi PORTB, button ;cbi PORTA, led_sink_pin ;sbi DDRA, led_sink_pin ; ; start main loop ; loop: nop nop nop nop print message3 message3: .db "press the button on the board to begin.",10 nop nop nop nop rcall count_loop got_random: rcall random_blink rcall getcompare ;rcall getchar ; (RELATIVE CALL SUB ROUTINE) ;print message ;message: .db "you typed: ",0 ;mov txbyte, rxbyte ; (COPY REGISTER) ;rcall putchar ; (RELATIVE CALL SUB ROUTINE) ;ldi txbyte,10 ; (LOAD IMMEDIATE) ;rcall putchar ; (RELATIVE CALL SUB ROUTINE) ;rcall led_on ; ;rcall delay2 ; on between fd loop and fdloop off ;rcall fdloop_off ;rcall fdloop_2 ; working fade ;rcall fdloop_3 ; working fade ;rcall led_on ; ;rcall led_off ;rcall fdloop ;rcall delay2 ;rcall delay ;on between 3 and 2 ;rcall fdloop ;rcall led_on ;rcall delay2 rjmp loop ; (RELATIVE JUMP) random_blink: ldi count_reg2,0 mov count_reg2,count_reg random_blink2: rcall blink rcall blink_off dec count_reg2 cpi count_reg2,0 brne random_blink2 ret count_loop: ldi count_reg,10 count_loop2: dec count_reg rcall button_loop count_loop3: cpi count_reg,1 brne count_loop2 cpi count_reg,1 breq count_loop ret button_loop: sbic PINB, button rjmp count_loop3 rjmp got_random ret led_count: led_count2: rcall blink rcall blink_off dec count_reg brne led_count2 ret fdloop_3: ldi temp3, 55 crap4: rcall led_off rcall delay rcall led_on rcall fade_on dec temp3 cpi temp3, 1 brne crap4 rcall led_off ret fdloop_2: ldi temp3, 1 crap3: rcall led_off rcall delay rcall led_on rcall fade_on inc temp3 cpi temp3, 120 brne crap3 rcall led_off ret fade_on: ldi temp, 67 delay_fade1: ldi temp1, 1 delay_fade2: mov temp2, temp3 delay_fade3: dec temp2 brne delay_fade3 dec temp1 brne delay_fade2 dec temp brne delay_fade1 ret led_on: sbi PORTA, ledpa0 sbi PORTA, ledpa1 sbi PORTA, ledpa2 sbi PORTA, ledpa3 ret led_off: cbi PORTA, ledpa0 cbi PORTA, ledpa1 cbi PORTA, ledpa2 cbi PORTA, ledpa3 ret delay2: ldi temp6, 255 delay_loop3: ldi temp7, 30 delay_loop4: ldi temp8, 255 delay_loop5: dec temp8 brne delay_loop5 dec temp7 brne delay_loop4 dec temp6 brne delay_loop3 ret delay: ldi temp9, 255 delay_loop1: ldi temp10, 25 delay_loop2: dec temp10 brne delay_loop2 dec temp9 brne delay_loop1 ret