; ; hello.mic.44.asm ; ; microphone hello-world program ; ; Neil Gershenfeld ; CBA MIT 10/25/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 txpin = PA6; transmit pin .equ comm_port = PORTA; comm port .equ comm_dir = DDRA; comm direction .equ nloop = 200 ; number of samples between framing .def bitcnt = R16; bit counter .def temp = R17; temporary storage .def temp1 = R18; temporary storage .def txbyte = R19; transmit byte .def loop_count = R20 ; loop counter .def hreading = R21 ; where each high sample value will be stored .def lreading = R22 ; where each low sample value will be stored .def currled = R23; holds the current LED pin .equ led1 = PA3 .equ led2 = PA4 .equ led3 = PA5 .equ led4 = PA6 .equ led5 = PA7 .equ led6 = PB2 .equ led_port_a = PORTA; LED port .equ led_dir_a = DDRA; LED dir .equ led_port_b = PORTB; LED port .equ led_dir_b = DDRB; LED dir ;.equ basln = 0 ;.equ baslnflt = 0.01 ; .equ gain = 3 .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; ; ; char_delay ; delay between characters ; char_delay: ldi temp, 255 char_delay_loop: ldi temp1, 10 char_delay_loop1: dec temp1 brne char_delay_loop1 dec temp brne char_delay_loop 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_a_on: sbi led_port_a, led5 ret blink_a_off: cbi led_port_a, led5 ret ;blink_b_on: ; sbi led_port_b, currled ; ret blink_b_off: cbi led_port_b, led6 ret blink_all_off: ldi currled, led1 rcall blink_a_off ldi currled, led2 rcall blink_a_off ldi currled, led3 rcall blink_a_off ldi currled, led4 rcall blink_a_off ldi currled, led5 rcall blink_a_off ret ; xxxxxxxx ; x xxxx x lights: ; turn on led 1? ; ldi currled, led1 ; cpi hreading,0x0 ; > 0? ; brbc 0,zerotest ; turn on led 2? ; ldi currled, led2 ; cpi hreading,0x40 ; > 64? ; brbc 0,zerotest ; turn on led 3? ; ldi currled, led3 ; cpi hreading,0x60 ; > 96? ; brbc 0,zerotest ; turn on led 4? ; ldi currled, led4 ; cpi hreading,0x80 ; > 128? ; brbc 0,zerotest ; turn on led 5? ldi currled, led5 cpi hreading,0xC0 ; > 192? brbc 0,zerotest ; turn on led 6? ; ldi currled, led6 ; cpi hreading,0xC0 ; > 192? ; brbc 0,zerotest rcall blink_delay rcall blink_a_off rcall blink_b_off ret zerotest: brbc 1,blink_a_on ; greater than? Turn on LED. ret ; ; 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_a, led1 sbi led_dir_a, led1 cbi led_port_a, led2 sbi led_dir_a, led2 cbi led_port_a, led3 sbi led_dir_a, led3 cbi led_port_a, led4 sbi led_dir_a, led4 cbi led_port_a, led5 sbi led_dir_a, led5 cbi led_port_b, led6 sbi led_dir_b, led6 ; ; set up A/D ; sbi ADMUX, REFS1 ; use 1.1V reference cbi ADMUX, REFS0 ; " sbi ADMUX, MUX5 ; differential, 20x gain, PA2-PA1 cbi ADMUX, MUX4 ; sbi ADMUX, MUX3 ; sbi ADMUX, MUX2 ; cbi ADMUX, MUX1 ; sbi ADMUX, MUX0 ; cbi ADMUX, ADLAR ; right-adjust result sbi ADCSRA, ADEN ; enable A/D cbi ADCSRA, ADATE ; disable auto-trigger sbi ADCSRA, ADPS2 ; set prescaler for /32 cbi ADCSRA, ADPS1 ; " sbi ADCSRA, ADPS0 ; " ; ; start main loop ; main_loop: ; ; send framing ; ldi txbyte, 1 rcall putchar rcall char_delay ldi txbyte, 2 rcall putchar rcall char_delay ldi txbyte, 3 rcall putchar rcall char_delay ldi txbyte, 4 rcall putchar rcall char_delay ; ; sample loop ; ldi loop_count, nloop sample_loop: ; ; read A/D ; sbi ADCSRA, ADSC ; start conversion adloopup: sbic ADCSRA, ADSC ; loop until complete rjmp adloopup ; ; send conversion ; in txbyte, ADCL ; low byte rcall putchar in txbyte, ADCH ; hi byte rcall putchar in hreading, ADCL in lreading, ADCH rcall lights ; ; loop ; dec loop_count brne sample_loop rjmp main_loop