;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; loggingmic1.asm ; microphone signal undergoes ADC (in the tiny26L) and is stored in 1M atmel flash memory, it can be accessed later. ; ; (c) Stacy DeRuiter, 2005 ; ; ; .include "tn26def.inc" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Pin Definitions Section ; .equ txpin = PA2; transmit pin .equ rxpin = PA1; receive pin .equ micpin = PA0; Mic data in pin (ADC0) .equ ledpin = PA7; LED pin (to indicate start of recording) .equ buttonpin = PA6; button to start recording or data return .equ sopin = PB1; serial data out pin (to FLASH memory) DO NOT change which pins si/so are if you are going to use USI .equ sipin = PB0; serial data in pin (from FLASH memory) .equ sckpin = PB2; SCK pin to FLASH memory (clock sync btw tiny26 and FLASH) .equ cspin = PB3; chip select pin for FLASH memory (to select the FLASH mem. for operation) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 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 pagecnt = R21; page counter (keeping track of which page of the flash memory you are writing on) .def buffcnt = r22; buffer loop counter (keeping track of number of bytes written to flash memory buffer) .def temp2 = r23 ; temp storage ; ;.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) ;this is just Neil's putchar, but with PORTB changed to PORTA ;(since the tiny26 has both A and B and our tx/rx pins are on PORTA) ; .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 PORTA, txpin; send a '0' rjmp putchar2; else putchar1: cbi PORTA, 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 PINA, 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 PINA, 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 ; ; hello world hello_mode: sbi PORTA, txpin; init comm pin sbi DDRA, txpin hw_loop: rcall getchar inc rxbyte mov txbyte, rxbyte rcall putchar rjmp hw_loop ret ; Recording Mode record_mode: ; main data-logging (recording) program ; ; ;initialize communication between ATtiny26 and Atmel 1Mbit FLASH memory ;set the from-FLASH input pin and the button pin as input, and to-FLASH, SCK, CS, and led pins as outputs ; cbi PORTB, sopin ; set the serial-out-from-FLASH pin (to ATtiny26 from FLASH) as an input cbi DDRB, sopin ; " ; sbi PORTA, buttonpin ; set the button pin (button push starts recording) as an input with internal pull-up resistor cbi DDRA, buttonpin ; " ; cbi PORTB, sipin ; set the serial-in-to-FLASH pin (from ATtiny26 to FLASH) as an output sbi DDRB, sipin ; " ; cbi PORTB, sckpin ; set the sck pin as an output sbi DDRB, sckpin ; " ; sbi PORTB, cspin ; set the chip select pin as an output; when it is low the FLASH is listening sbi DDRB, cspin ; " ; cbi PORTA, ledpin ; set the ledpin as an output sbi DDRA, ledpin ; " ; sbi PORTA, txpin ;init comm pin sbi DDRA, txpin ; ; wait for button to be pushed to start recording ; waitloop: sbic PINA, buttonpin ; check for button; if button is pushed, exit loop, flash LED, and start recording rjmp waitloop sbi PORTA, ledpin ; flash the led to indicate recording is about to start rcall long_print_delay cbi PORTA, ledpin ; turn off the led ; ; initiate the A/D converter of the ATtiny26 for input on AD0 (PA0) ; cbi ADMUX, REFS0 ; setting REFS0 = 0 and REFS1 = 1 sets the ADC to use internal...(next line) sbi ADMUX, REFS1 ; ...Vref = 2.56V as the reference voltage cbi ADMUX, ADLAR ; right-adjust bits in ADC output data bytes (make sure left-adj is off) sbi ADCSRA, ADEN ; enable the A/D cbi ADCSRA, ADFR ; set ADC for single-shot measurement (turn off free running mode) cbi ADCSRA, ADIE ; disable A/D interrupt sbi ADCSRA, ADPS2 ; set ADC prescaler for input clock=tinyclock/32 (so ADC clock cycles at 16MHz/32 = 500kHz)... cbi ADCSRA, ADPS1 ; " (the ADC clock can run much faster, but we only want audio samples at 10kHz, so only need... sbi ADCSRA, ADPS0 ; " one every 1600 tiny26 clock cycles (=every 50 ADC cycles at /32, and ADC takes 13 ADC cycles.) ; cbi ADMUX, MUX4 ; setting MUX0, MUX1,...MUX4 = 0 in the ADMUX register tells the ADC... cbi ADMUX, MUX3 ; to use a single input from PB0 (ADC0). With other settings the ADC... cbi ADMUX, MUX2 ; can use the difference between two adjacent pins, or the difference... cbi ADMUX, MUX1 ; between two pins multiplied by some gain factor, as input. cbi ADMUX, MUX0 ; " ; ; main recording loop (recording continues until memory is full. This code has no way to stop recording.) ; ; ; convert input from the microphone to digital ; sbi ADCSRA, ADSC ; start the first conversion adloop1up: sbic ADCSRA, ADSC ; loop until complete rjmp adloop1up ; ;adc_delay; want a delay of 12 ADC clock cycles = 384 tiny26 cycles before next sample. ;adc_delay_loop: ;will not put this loop in the code for now. Problem: initiating writing to the flash (needs to be ;done every 264 data bytes sent) takes some cycles, and writing a page takes up to 20ms. That will ;royally screw up the sampling frequency. For right now, just not worrying about it. ; ; send high byte of the conversion to the FLASH memory chip ;memory has 264 byte pages, so can send 264 conversions to buffer and then have to write a page. ;This serial transfer uses the Universal Serial Interface of the ATtiny26 (see ATtiny26 datasheet). ; ;the flash_loop writes a byte to the FLASH buffer. It should repeat 264 times, then wait for the ;flash memory to write the page from the buffer to the real memory. ; ;the page_loop controls which page the flash is writing to, and it should loop from 0 to 511. ;After 511 pages have been written the memory will be full. ; ldi pagecnt, 0 ; start writing on page 0, and write on all the pages till they are gone page_loop1: ; cbi PORTB, cspin; select the flash memory (make it start listening) ; ;Tell the flash to write to memory through its buffer ; ldi txbyte, 0x82 ; 82H is the 8-bit opcode telling the flash to write to memory through the buffer out USIDR,txbyte ldi txbyte,(1<