#include "hardware.inc" #include "avriodef.inc" ; ; Serial A/D chip ; ; Implements a cheesy A/D using the 1200 analog comparator ; ; Implements a cheesy mux by tri-stating and grounding 1 of 10 pins. ; The idea is to float a bunch of voltage sources (photo darlingtons) ; grounding each in turn and wire or'ing all their outputs together to ; the Analog comparator. ; ; Implements a terse two wire serial interface, ala the sharp GP2D02 ; proximity sensor. ; ; Initiat conversion by setting the clock low. ; SerialAD responds by dropping Vout (PD3) 500ns later. ; after conversion is done SerialAD raises Vout ; Set the clock high to shift out the next bit of data (minimum pulse ; width of 500ns ; set the clock low and read the data ; There is no limit on how long the low pulse can be. ; ; There is a 2 ms timeout: if the clock stays high longer than 2ms ; the chip resets and waits until the next logic low on the clock. ; ; There are 11 A/D channels. Each reports 8 bits, so you need to ; clock out 88 bits of data (lsb first). At anytime you can stop ; reading data and hold the clock high 2 ms to reset the chip. ; NAME SERIALAD org 0 rjmp reset rjmp INT0_Interrupt rjmp TOV0_Interrupt rjmp ACI_Interrupt ; ;-------------------------------------------------------- ; ; Initialize hardware: ; ; Since this can be entered due to a hardware reset, or an rjmp, ; we need to explicitly set all registers and peripherals. Can't ; assume anything. ; ; Reset Ports: Enable pullup on Vin (noise suppression) ; Reset Timer & A/D ; Set sleep mode ; Enable INT0 (Vin) low active, ; Enable Interrupts then sleep. ; reset: ldi tmp1, DDRD_INIT out DDRD, tmp1 ldi tmp1, PORTD_INIT out PORTD, tmp1 ldi tmp1, DDRB_INIT out DDRB, tmp1 ldi tmp1, PORTB_INIT out PORTB, tmp1 clr R31 out TCCR0, R31 ; Disable Timer ldi tmp1, 1<R0) ; ; Preload registers with values needed to reset ; the 2ms reset timer ; ldi tmp1, CLK256 ; TCCR0 Value ldi tmp2, TCNT0_INIT ; TCNT0 Value ; ; We don't actually start the timer until the hosts raises Vin, indicating ; it is ready to clock data. After that we maintain a 2ms timer for all clock ; transistions. If the timer expires, the chip will reset it'self. ; sei ; Enable Interrupts (TOV0 interrupt resets chip) sbi VOUTBIT ; Raise VOUT indicating conversion done OutputNextChannel: ldi BitCnt, 8 ld TxData, Z OutputNextBit: sbis VIN ; Spin waiting for Vin transition high rjmp $-2 sbrc TxData, 0 ; Output next bit of data sbi VOUTBIT sbrs TxData, 0 cbi VOUTBIT out TCNT0, tmp2 ; Reset 2ms timeout out TCCR0, tmp1 ; Activate the reset timer sbic VIN ; Wait for negative transition rjmp $-2 out TCNT0, tmp2 ; Reset 2ms timeout lsr TxData dec BitCnt brne OutputNextBit ; ; Get next AD channel and repeat above ; inc Channel cpi Channel, MAXCHANNEL*2 brlt OutputNextChannel ; ; If we are done with all channels and the clock goes low, then ; just start the conversion cycle over again. ; rjmp reset END