Full Version : Glassmeyer/Melin 8535 Digital Answer Machine (ASM)
avr >>SOUND & MUSIC PROJECTS >>Glassmeyer/Melin 8535 Digital Answer Machine (ASM)


Admin5- 04-21-2006
AT90LS8535 Digital Answering Machine

Brian Glassmeyer and Eric Melin

Introduction

We were given the task of designing something cool using the AT90LS85835 8-bit microcontroller for our final project in EE476. We decided that an answering machine was interesting because it involved interfacing many analog parts, a reasonable amount of coding, and would leave us with a finished product that actually does something. The answering machine is one of few everyday microcontroller utilities that can be implemented fairly easily and we are really happy with our final product. We also realize that we share a common fear of analog circuitry and felt this would force us to gain working knowledge of this material.


High Level Design -

Our answering machine is designed to:

Record – on phone pickup start recording
Playback – on Button 7 push
Stop Playback – on Button 6 push
Skip Messages – on Button 5 push
Delete Messages – on Button 4 push
Program/Hardware Design -

The main tasks in this design were to record voice and play it back, address the SRAM, and store/read from the SRAM. We achieved recording by using the ADC provided with the AVR microcontroller. We sampled voice at a rate of 6000 samples / second giving us just under voice quality recording.

To make it more realistic, we used a regular telephone as our microphone for input into the ADC. We did not use external phone lines because we did not want to deal with ringing circuitry and there is no phone line access in the EE lab. Through testing, we discovered that the phone operates on a supply from 6V-18V through its red wire. Voice input results in a current modulation in the green wire of the phone cord. By using a 7V supply, we assured that the peak voltage across a 330Ohm resistor on the green wire would be less than our ARef of 4.096V. A lot of debouncing of the hangup receiver is required in software.

Due to budget restraints, we ordered a 128kx8 SRAM from digikey. With the above sampling rate, this allows us to record and save 21.8 seconds (128ksam / 6000sam/sec = 21.8sec).

We needed to order an external counter to address this much memory. To sddress 128k memory locations, we need 17 bits. Our external counter provided the 12 lower bits (only requiring two inputs itself) while we drew the higher 5 bits off the microcontroller. These higher 5 bits give us instant access to 32 different locations. The lower 12 bits can only be incremented or cleared. This means we may waste a maximum of 4096 address bits at the end of a message. This is merely .68 seconds and is hardly an issue.

The 8 bit samples are sent to a DAC through a bus connected also to the microcontroller and the SRAM. The DAC sends its output through an opamp to a simple external speaker. The use of one data bus allows messages to be heard while first being recorded and while being played back. During playback, however, you must remember to set the microcontroller to Hi-Z in order to prevent multiple drivers to the single bus.


Testing Methods -

Realizing the amount of external hardware that would be interacting, we approached our testing in several stages. We wrote individual test codes for every external component (these codes are linked below). Only after we successfully operated and controlled each of these seperately did we combine them into one project. We never fully debugged this code, but only used it as a means to observe the counter and ram were working. We then used simple tests again to verify and correct any wiring issues.

-Our first full test was to input voice and directly output it through the DAC (the SRAM was bypassed on the bus).
-The second test was to record the voice into the SRAM and display the bits on the LEDs.
-We automatically started and stopped recording using the analog comparator on the green wire of the phone cord.
-Combining these we eventually built up our record and play functions.
-The delete function was then added.
-Implemented skip meant we needed memory management using dynamic tables and flags.
-Fool-proofing our design involved finding remote errors that could occur in extreme situations.


Results of the Design -

The answering machine can record up to our full 21 seconds and play it back in clearly understandable output. We can record anywhere from one 21.8 second message to thirtytwo .68 second messages. This leaves an incredible amount of flexibilty for an answering machine where message lengths vary unpredictably.

Multiple messages are recorded one after another. Using the play button will begin with the first message and play until the end of the last message. The delete button will erase all of the messages at once (just like a cassette tape answering machine). The stop button will cease any playing and return to the beginning of the message queue. The skip button will cease the current message and begin playing the next message in the queue.

Cool Extra Features:

Recording will stop automatically if the end of the SRAM is reached preventing circular overwriting.
Play will stop and end of last message preventing extra garbage from being played.
Skip will not play beyond last message.
Play and skip will not work if there are no messages present.
Picking up the phone during play will cease play and start recording at end of message queue.

Software Designed -

Digital Answering Machine
Include file
Test DAC conversion
Test Counter
Test RAM

Answering Machine Schematic (and pics) -

Schematic
Full view of layout
Close-up of surface mount contraption

Spec Sheets and References

ram spec
counter spec
8535 spec
howstuffworks.com

What We Would Do Differently

We would order a counter and RAM that was not surface mount. In order to make these chips usable we made an interesting contraption. We placed the surface mount chip ontop of a wire wrap socket. Soldering short leads to its pins, we folded the wires around the sides of the socket and wire wrapped them to the posts underneath. This results in a DIP-like package shown above in the schematic and pics section.

We would implement the debouncing of the input capture from the beginning to facillitate testing. Getting a clean pickup and hangup of the phone caused many problems.


Extensions

We thought of many extensions to this project if we had more time.
Use serial interface with computer for larger storage capabilities (but we prefer the stand-alone approach not dependant on the computer).
We would have liked to implement more powerful memory management. Currently, our delete is an all-or-nothing format. We would like to be able to individually delete one message at a time. In order to accomplish this, we would need to shift all messages after the deleted message forward to fill the gap. This would be more effective for our short memory than dynamic links.
Interface with the phone network w/ ringer circuitry to answer real phone company calls. An intro message would then be appropriate.
Adding beeps between messages for distiction.


Link: http://instruct1.cit.cornell.edu/courses/e...ts/s1999/melin/

CODE

;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  





Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.