;Eric Melin and Brian Glassmeyer ;;*************************************** ;;*** Final Project Code - ;;*** Digital Answering machine ;;*************************************** ;Port A used for ADC - 0-2 used for LEDS ; a3 - delete ; a4 - skip ; a5 - stop ; a6 - play ; a7 used as input to ADC ;Port B ; pin b0 - RW line to RAM ; Pins B2 and B3 used for compare match of ; phone pickup and hangup ;Port C 3 pins interface to counter, ; 0 - CLR ; 1 - CLK ; 2 - Q12 ;outbit Highest bit ; 5 pins are upper 5 bits to RAM ;Port D 8 Bit output data while storing .include "8535def.inc" .device AT90S8535 .def savSREG =r1 ;save the status register .def AnaLo =r16 ;the lower byte of captured voltage .def AnaHi =r17 ;the upper byte of captured voltage .def temp =r18 ;temporary register .def tim1CapDeb =r19 ;debounce duration tracker .def TrySwitch =r20 ;flag for every receiver bounce .def cnt_bit12 =r21 ;counter bit to determine if overflow .def highCount =r22 ;upper 5 bits of counter .def AnaCaptoggle =r23 ;flag for PHONEON/PHONEOFF .def temp2 =r24 .def itemp =r25 ;temp reg for interrupts .def state =r26 ;state is 0 when no playback or recording, ;1 recording -1 playback .def MsgEnd =r27 ;End marker of last message .def debounceL =r28 ;counter to say whether button valid .def debounceH =r29 .equ START=0 .equ RECORD=1 .equ PLAY=2 .equ STOP=3 .equ SKIP=4 .equ DELETE=5 .equ HANGUP=6 .equ PHONEOFF=7 .equ PHONEON=8 ;************************************** .dseg ;allocate space to store message table ;msgTBL in format Start locations ;This stores upper 5 bits of counter ;message starts RAM location 1 + 5 upper bits msgTBL: .byte 32 ;max 32 messages ;************************************** .cseg .org $0000 rjmp RESET ;reset entry vector reti reti reti reti rjmp timer1cap ; fire when pick up phone rjmp t1match ; handle timing for sampling && playback reti reti reti reti reti reti reti reti reti reti RESET: ldi temp, LOW(RAMEND) ;setup stack pointer out SPL, temp ldi temp, HIGH(RAMEND) out SPH, temp ;establish inputs and outputs ser temp out DDRD, temp ; data line ldi temp, 0xF1 ; pin 6-8 as button inputs out DDRB, temp ; pin 0 for ramR/W - 2-3 for ana comp ldi temp, 0b11111011 out DDRC, temp ldi temp, 0x07 out DDRA, temp out PORTA,temp ; Turn all LEDs off by default ;Clear table to RAM rcall FillTBL ;Fill msgTBL with NO messages ;set up Timer 1 to interrupt on compare A match ;and set the compare time to 62500 ticks ldi temp,0b00110000 ;enable t1 matchA interrupt out TIMSK, temp ldi temp, 0x00 ;set the match A register to out OCR1AH, temp ;83 since 83*2us=166us=1/6000 ldi temp, 83 ;62500 = 0xf424 out OCR1AL, temp ldi temp,0b00001010 ;prescale timer by 8 (one tick=16 microsec) out TCCR1B, temp ;and clear-on-matchA ;set up analog converter to read channel 8 ldi temp, 7 out ADMUX, temp sei ;initialize variables INIT: rcall Clear clr highCount ldi state, START ldi AnaCaptoggle, PHONEOFF clr TrySwitch ldi Tim1CapDeb, 0xff clr MsgEnd clr cnt_bit12 clr debounceL ldi debounceH, 2 ldi temp, 0b00001111 ;Enable Timer1 Capture interupt out ACSR, temp ldi ZL, low(msgTBL) ;First msg will increment into location, sbiw ZL, 1 ; so decrement to counter this. COMMAND: ; Simple debouncing ... Don't allow go to these states if w/in 255 cycles.. out PORTA, state ; cpi debounceH, 1 ; brlt COMMAND cpi state, PLAY breq RECORDBREAK ; Playback can be interupted by phone call sbic PINA, 6 rjmp RECORDTST ldi state, PLAY ; if initial play load differently out PORTA, state clr highCount rcall Clear rjmp COMMAND RECORDBREAK: cpi state, RECORD brne STOPTST mov highCount, MsgEnd inc highCount ;Set SRAM location to end of queue rjmp RECwait RECORDTST: cpi state, RECORD breq RECwait STOPTST: sbic PINA, 5 rjmp SKIPTST ldi state, STOP out PORTA, state clr debounceL clr debounceH SKIPTST: sbic PINA, 4 rjmp DELTST ldi state, SKIP out PORTA, state clr debounceL clr debounceH DELTST: sbic PINA, 3 rjmp COMMAND clr debounceL clr debounceH ldi state, DELETE out PORTA, state rjmp COMMAND ;SAMPLE until HANGUP or out of RAM ;current sampled value in AnaLo RECwait: out PORTA, state cpi state, START breq COMMAND in temp, ADCSR ;wait for A to D start andi temp, 0b01000000;by checking if ADSC bit is set breq RECwait ;this bit is set by t1match interrupt await: cpi state, START breq COMMAND in temp, ADCSR ;wait for A to D done andi temp, 0b01000000;by checking ADSC bit brne await ;this bit is cleared by the AtoD hardware in AnaLo, ADCL ;read the voltage in AnaHi, ADCH lsr AnaHi ;double precision shift ror AnaLo ;right twice lsr AnaHi ror AnaLo rjmp RECwait ;;Increment 12 bit counter and handle overflow for INC_CNT: cpi state, PLAY ;If at end of message, stop playing. brne START_INC cp highCount, MsgEnd brlo START_INC cp highCount, MsgEnd brne START_INC ldi state, START out PORTA, state ret START_INC: sbi PORTC, 1 ; increment counter cbi PORTC, 1 sbic PINC, 2 rjmp IN_HIGH ;input is low tst cnt_bit12 breq DONE_CNT ;OVERFLOW has occured clr cnt_bit12 inc highCount cpi highCount, 32 breq OUT_OF_RANGE ;NOTE - highCount == 000xxxxx mov temp, highCount lsl temp lsl temp lsl temp ;NOTE - highCount == xxxxx000 out PORTC, temp ret IN_HIGH: ldi cnt_bit12, 1 DONE_CNT: ret OUT_OF_RANGE: cpi state, RECORD ;If message recording reaches end of SRAM, brne DONE_CNT ; stop recording to prevent overwriting. ldi state, STOP out PORTA, state mov MsgEnd, highCount ;Set end of message marker. clr highCount ret ;Clear the lower 12 address bits in external counter Clear: sbi PORTC,0 cbi PORTC,0 nop nop nop ret ;Fill msgTBL with default garbage FillTBL: ldi ZH, high(msgTBL) ldi ZL, low(msgTBL) ldi temp, 0xEE ldi temp2, -1 moreFill: st Z, temp adiw ZL,1 inc temp2 cpi temp2, 31 brne moreFill ret ;***** ;This interrupt fires when the phone connection is started ;or the phone hung up. ; This is debounced in t1match. timer1cap: in savSREG, SREG ser TrySwitch out SREG, savSREG reti ;***** ;This interrupt checks for state and handles appropriately. ; Also debounces receiver. t1match: in savSREG, SREG tst TrySwitch ;Has the receiver bounced? breq NoBounce ; -No bouncing...just continue. tst Tim1CapDeb ; -Bounced...is this a new bounce? breq Switch ; +New...switch AnaCapToggle. dec Tim1CapDeb ; +Old...continue debouncing. rjmp NoBounce Switch: clr TrySwitch ldi Tim1CapDeb, 0xff ;Initialize new debounce duration cpi AnaCapToggle, PHONEON ;Was phone ON or OFF breq SwitchOff ldi AnaCapToggle, PHONEON ; -OFF...switch on. ser itemp out DDRD, itemp ; data line (output) inc highCount adiw ZL, 1 st Z, highCount ;load message beginning into msgTBL ldi state, RECORD out PORTA, state ldi itemp, 0b00001110 ; change Timer1 Capture interupt to falling edge out ACSR, itemp rjmp NoBounce SwitchOff: ldi AnaCapToggle, PHONEOFF ; -ON...switch off. ldi state, START out PORTA, state ; change Timer1 Capture interupt to rising edge ldi itemp, 0b00001111 out ACSR, itemp tst highCount ;If SRAM ran out, MsgEnd already set. breq NoBounce mov MsgEnd, highCount ;Set end of message marker. NoBounce: ldi itemp, 0b11000101 ;start A to D conversion out ADCSR, itemp adiw debounceL,1 ST_RECORD: cpi state, RECORD brne ST_PLAY ;Handle recording com AnaLo out PORTD, AnaLo sbi PORTB, 0 cbi PORTB, 0 rcall INC_CNT rjmp ENDSTATE ST_PLAY: cpi state, PLAY brne ST_STOP clr itemp out DDRD, itemp ; data line (Hi-Z) sbi PORTB, 0 rcall INC_CNT rjmp ENDSTATE ST_STOP: cpi state, STOP brne ST_DELETE ldi state, STOP out PORTA, state rcall Clear clr highCount clr debounceL clr debounceH rjmp ENDSTATE ST_DELETE: cpi state, DELETE brne ST_SKIP rcall Clear clr highCount clr MsgEnd rcall FillTBL rjmp ENDSTATE ST_SKIP: cpi state, SKIP brne ENDSTATE tst highCount breq ENDSTATE ldi state, PLAY out PORTA, state rcall Clear ldi ZL, low(msgTBL) SkipSearch: ld itemp, Z cp itemp, highCount brsh SkipFound adiw ZL, 1 rjmp SkipSearch SkipFound: mov highCount, itemp ENDSTATE: out SREG, savSREG reti