;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; measurer.asm ; the operating system for the HTMAA (How to Measure Almost Anything) tool ; ; (c) a whole lot of people taking class 863 at the MIT Media Lab in 2005 ; see credits at bottom, or in indvidual sections ; ; .include "tn13def.inc" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Pin Definitions Section ; .equ txpin = PB1; transmit pin .equ rxpin = PB0; receive pin .equ micpin = PB2; mic data in pin ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Variable Declarations ; .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 .def which_mode = R21; stores which mode we are currently in ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Interrupt Handlers ; .cseg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Program memory: ; .org 0 rjmp init ; let's start by running init ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Utility functions ; these can be used by any code ; ; putchar ; assumes no line driver (doesn't invert bits) ; .equ sb = 1; number of stop bits putchar: ldi bitcnt, 9+sb; 1+8+sb com txbyte; invert everything sec; set start bit putchar0: brcc putchar1; if carry set sbi PORTB, txpin; send a '0' rjmp putchar2; else putchar1: cbi PORTB, txpin; send a '1' nop ; even out timing putchar2: rcall bitdelay; one bit delay rcall bitdelay 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 PINB, rxpin ; wait for start bit rjmp getchar1 rcall bitdelay ; 0.5 bit delay getchar2: rcall bitdelay ; 1 bit delay rcall bitdelay ; clc ; clear carry sbis PINB, rxpin ; if RX pin high skip 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 ; ; print ; prints a null-terminated string ; print: print_loop: lpm mov txbyte,R0 cpi txbyte,0 breq return rcall putchar inc zl rjmp print_loop return: ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Mode-specific functions ; ; Digitize input from microphone ; mic_mode: ; main mic program ; ; initiate communication ; sbi PORTB, txpin ; set initial value sbi DDRB, txpin ; set for output ; ; initiate the A/D converter ; cbi ADMUX, REFS0 ; set Vcc as the reference voltage cbi ADMUX, ADLAR ; right-adjust result (make sure left-adj is off) sbi ADCSRA, ADEN ; enable A/D cbi ADCSRA, ADATE ; set for single-shot measurement (turn off auto trigger) cbi ADCSRA, ADIE ; disable A/D interrupt cbi ADCSRA, ADPS2 ; set prescaler for input clock=tinyclock/2 cbi ADCSRA, ADPS1 ; " cbi ADCSRA, ADPS0 ; " (these settings make the A/D input clock as fast as possible) cbi ADMUX, MUX1 ; input on ADC1 sbi ADMUX, MUX0 ; " ; ; infinite main mic loop ; mic_loop: ; ; read first response ; sbi ADCSRA, ADSC ; start conversion adloopa: sbic ADCSRA, ADSC ; loop until A/D conversion is complete rjmp adloop1a ; ;read next response mic_loopb: sbi ADCSRA, ADSC ; start conversion ; send last conversion and wait for current conversion to end ; in txbyte, ADCL ; send low byte from previous conversion rcall putchar in txbyte,ADCH ; send high byte from previous conversion rcall putchar ; adloopb: sbic ADCSRA, ADSC ; loop until conversion is complete rjmp adloop2b ; rjmp mic_loop ; continue to get and send conversions forever. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Operating System functions ; these functions are only to be used by the operating system microcode ; if you need to use them, please let seth know, and he will make an accessor ; ; ; bit delay .equ b = 17 ; 9600 bps 5V bitdelay: ldi temp, b bitloop: dec temp brne bitloop ret ; ; print_delay ; delay between printed lines ; .equ delay = 200 print_delay: ldi temp1, delay charloop1: ldi temp, delay charloop0: dec temp brne charloop0 dec temp1 brne charloop1 ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; init: main entry point for the program ; pick a mode to work in, and go do it. ; init: ldi temp, low(RAMEND) ; set stack pointer to top of RAM out SPL, temp rjmp mic_mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; CREDITS: ; Stacy DeRuiter ; microcode (Seth)