; AD - Analog-Digital converter controller (AD7892-1)
; Written by Chris Cole, December 28, 1998 - cole@coledd.com
; This code is protected under the GPL - You are free to use and modify this code
; 16F84 running at 12MHz -> 333.3 nS/cycle; 9600 baud, 1bit=104uS => 312.5 cycles
; pins: 4=10kohm->+5V, 5=gnd, 14=+5V, 15&16=12MHz xtal (look at #define's)
; NOTE: Be sure to set the com port for 9600,N,8,1 and NO FLOW CONTROL!

	TITLE	"AD"	
	LIST	P=16F84	

	__CONFIG _CP_OFF & _WDT_OFF & _HS_OSC & _PWRTE_ON ;

#include "C:\progra~1\mplab\p16f84.inc" ;

#define RXpin232	PORTB,0	; (pin 6) - receive data line from PC 	(Input)
#define TXpin232	PORTB,1	; (pin 7) - transmit data line to PC 	(Output)
#define ConvSt		PORTB,2	; (pin 8) - A/D conversion start pin 	(O)
#define EOC		PORTB,3	; (pin 9) - A/D conversion done pin 	(I)
#define RFS		PORTB,4	; (pin 10) - A/D receive frame sync 	(O)
#define SClk		PORTB,5	; (pin 11) - A/D serial clock 		(O)
#define SData		PORTB,6	; (pin 12) - A/D serial data 		(I)
				;
RAMbase	EQU	0x0c		;
				;
; DNOP - Double NOP. Delay of 2 cycles, takes only one instruction ;
DNOP	MACRO			;
	LOCAL	Label		;
Label	GOTO	Label+1		;
	ENDM			;
				;
; Delay3W - Delay 3 * W cycles, three instructions ;
Delay3W	MACRO			;
	LOCAL	Label		;
	MOVWF	Delay		;
Label	DECFSZ	Delay		;
	GOTO	Label		;
	ENDM			;
				;
; Declarations			;
	CBLOCK	RAMbase		;
		Count		;
		Delay		;
		BitsToGo	;
		SerByte		;
	ENDC			;
				;
	ORG	0		;
	GOTO	Main		;
;----------------------------------------------------------------------------------------------------
Main				;
	bsf	STATUS, RP0	;
	movlw	b'11111'	; RAx all inputs
	movwf	TRISA		;
	movlw	b'11001001'	; RB1,2,4=output, rest inputs
	movwf	TRISB		;
	bcf	STATUS, RP0	;
Init				; set up initial states
	bsf	TXpin232	; 
	bsf	ConvSt		; 
	bsf	RFS		; 
	bsf	SClk		; 
	movlw	'R'		;
	call	SendChar232	;
	movlw	'e'		;
	call	SendChar232	;
	movlw	'a'		;
	call	SendChar232	;
	movlw	'd'		;
	call	SendChar232	;
	movlw	'y'		;
	call	SendChar232	;
	movlw	'.'		;
	call	SendChar232	;
	movlw	0x0a		;
	call	SendChar232	;
	movlw	0x0d		;
	call	SendChar232	;
MainLoop			; wait here for incoming 232 Cmd.
	call	Wait232		; 
	movwf	SerByte		;
	movlw	'a'		; If an 'a' is received, then ecquire the current A/D value
	xorwf	SerByte,w	; compare
	btfsc	STATUS,Z	; is this a match?
	  goto	Acquire		;
	goto	MainLoop	;
;----------------------------------------------------------------------------------------------------
Wait232				;
	btfsc	RXpin232	;
	  goto	Wait232		;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Get232				; returns serial value in w register
	movlw	8		;
	movwf	BitsToGo	;
	movlw	0x92		;
	Delay3W			; wait for startbit to pass (312+(312/2) cycles) and get into middle of first bit
GetNextBit232			;
	bcf	STATUS,C	; [1] zero out CARRY to begin with
	btfsc	RXpin232	; [1]
	  bsf	STATUS,C	; [1]
	rrf	SerByte		; [1] rotate right, bring in carry bit on left side
	movlw	0x65		; [1]
	Delay3W			; [303]
	decfsz	BitsToGo	; [1]
	  goto	GetNextBit232	; [2]
	movf	SerByte,w	;
	return			;
;----------------------------------------------------------------------------------------------------
SendChar232			;
	movwf	SerByte		; store char to send out
	movlw	8		;
	movwf	BitsToGo	; # bits to send out
	bcf	TXpin232	; send out start bit
	movlw	0x67		; [1] set length for start bit
	Delay3W			; [309]
TXLoop232			;
	rrf	SerByte		; [1]
	btfsc	STATUS,C	; [1] is it a 1?
	  goto	TXOne232	; [2] yes - send a '1'
	bcf	TXpin232	; [1]
	nop			; [1]
	movlw	0x65		; [1]
	Delay3W			; [303]
	decfsz	BitsToGo	; [1]
	  goto	TXLoop232	; [2]
	goto	DoneByte232	;
TXOne232			;
	bsf	TXpin232	; [1]
	movlw	0x65		; [1]
	Delay3W			; [303]
	decfsz	BitsToGo	; [1]
	  goto	TXLoop232	; [2]
DoneByte232			;
	bsf	TXpin232	; [1] send out stop bit
	movlw	0x65		; [1]
	Delay3W			; [303]
	bsf	TXpin232	; idle state for TXpin
	return			;
;----------------------------------------------------------------------------------------------------
Acquire				; Obtain a new value from the A/D converter
	bcf	ConvSt		; Reset ConvSt line
	bsf	ConvSt		; Tell A/D to begin conversion (rising-edge triggered)
	movlw	0x02		;
	Delay3W			; Wait for conversion to finish (1.47uS for the AD7892)
	bcf	RFS		; Assert Receive Frame Synchronization on the A/D
	call	GetNextADByte	; Read A/D High-Byte
	call	SendChar232	; Display it
	call	GetNextADByte	; Read A/D Low-Byte
	call	SendChar232	; Display it
	bsf	RFS		; End receive frame
	goto	MainLoop	; 
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
GetNextADByte			; Returns A/D value in w register
	movlw	8		; Get next 8 bits from A/D (8/16 - remember the first 4 bits are 0! ==12bit A/D)
	movwf	BitsToGo	;
GetNextADBit			;
	bcf	SClk		; A/D puts data out upon falling edge of SClk
	bsf	SClk		; A/D data becomes stable upon rising edge of SClk
	bcf	STATUS,C	; Zero out CARRY to begin with
	btfsc	SData		; 
	  bsf	STATUS,C	; 
	rlf	SerByte		; Rotate right, bring in carry bit on left side
	decfsz	BitsToGo	; 
	  goto	GetNextADBit	; 
	movf	SerByte,w	;
	return			;
;----------------------------------------------------------------------------------------------------
	END			;


