; A/D conversion with a ADC0831 chip  (ADC.asm)
;	a simple example of the SPI (serial peripheral interface) protocol
	LIST	p=16F628		;tell assembler what chip we are using
	include "P16F628.inc"		;include the defaults for the chip
	__config 0x3D18			;sets the configuration settings (oscillator type etc.)



; Read wikipedia article on SPI !!!!




; we will wire 	A0 to CS (chip select)	pin 1 on ADC0831
;		A1 to CK (clock)	pin 7 on ADC0831
;		A2 to DO (Data Out)	pin 6 on ADC0831

; ADC0831 other wiring
;		pin 5 and 8 to Vdd
;		pin 3 and 4 to ground
;		pin 2 - voltage to measure


; Hey!! Using equ makes life easy!!!

CS	equ	0
CK	equ	1
DO	equ	2
OUTPUT		equ	PORTB
ADCPORT		equ	PORTA

	cblock 0x20
		counta
		countb
		count1
		read_value			;value to read into from chip
		loopy				;dummy loop counter
	endc

	org 0x00
	movlw	0x07
	movwf	CMCON			;turn comparators off (make it like a 16F84)

	bsf	STATUS,RP0
	movlw	0x00	
	movwf	TRISB			; PORTB is output
	movlw	0xfc
	movwf	TRISA			; PORTA is input
	bcf	STATUS,RP0	

; set the clock low and the chip select high
	bcf	ADCPORT,CK
	bsf	ADCPORT,CS

top
	call 	read_ADC
	movf	read_value,w
	movwf	OUTPUT	
	goto 	top

read_ADC
	bcf	ADCPORT,CS

;pulse the clock

	bsf	ADCPORT,CK
	call 	Delay10
	bcf	ADCPORT,CK
	call 	Delay10
	bsf	ADCPORT,CK
	call 	Delay10
	bcf	ADCPORT,CK
	call 	Delay10

;read and shift 8 times
	clrf	read_value
	movlw	0x08
	movwf	loopy
next_bit

 	bsf	ADCPORT,CK       	
    	call 	Delay10


	btfsc	ADCPORT,DO		; skip next instruction if input==0
	goto	set_carry		
	bcf	STATUS,C
	goto	rotate_it
set_carry
	bsf	STATUS,C
rotate_it
	rlf	read_value,f

    bcf		ADCPORT,CK    
    call 	Delay10
    
	decfsz 	loopy
	goto 	next_bit
  
; all done, pulse clock once  
    bsf		ADCPORT,CK
    call 	Delay10
    bcf		ADCPORT,CK
    call 	Delay10

;deselect chip

    bsf		ADCPORT,CS

	return	



; modified Delay routine, direct calls for specified times
; or load W and call Delay for a custom time.Taken from some Brit named Nigel 
; http://www.winpicprog.co.uk/pic_tutorial2.htm

Delay0	retlw	0x00			;delay 0mS - return immediately
Delay1	movlw	d'1'			;delay 1mS
	goto	Delay
Delay5	movlw	d'5'			;delay 5mS
	goto	Delay
Delay10	movlw	d'10'			;delay 10mS
	goto	Delay
Delay20	movlw	d'20'			;delay 20mS
	goto	Delay
Delay50	movlw	d'50'			;delay 50mS
	goto	Delay
Delay100	movlw	d'100'		;delay 100mS
	goto	Delay
Delay250	movlw	d'250'		;delay 250 ms
Delay	movwf	count1
d1	movlw	0xC7			;delay 1mS
	movwf	counta
	movlw	0x01
	movwf	countb
Delay_0
	decfsz	counta, f
	goto	$+2
	decfsz	countb, f
	goto	Delay_0

	decfsz	count1	,f
	goto	d1
	retlw	0x00

	end