 TITLE  "baro.asm"           ; atmospheric pressure
 List P=PIC16F684, R=DEC
 INCLUDE "p16f684.inc"

SCL		EQU 	2			; Clock line setup
SDA		EQU 	1			; Data line setup
CORR	EQU		6832 + 186	
; data segment
 CBLOCK 0x20                   
 del, cnt, temp  			; local variables 
 bar:2						; storage for pressure	
 bcd:2
 i, dataIO	
 ENDC

; code segment
 __CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT

 ORG 0                 
	bcf		STATUS, RP0		; switch to BANK 0
	clrf	PORTA			; initialize PORT A
	clrf	PORTC			; initialize PORT C
	movlw	0x07
	movwf	CMCON0			; comparators OFF
	bsf    	STATUS, RP0     ; switch to BANK 1

 	; ADC and ports configuration
	clrf	TRISA ^ 0x80	; configure PORTA for output
	movlw	b'011100'
	movwf	TRISC ^ 0x80
	movlw	b'10000000'
	movwf	ANSEL ^ 0x80	; configure RC3 as analog input
	movlw 	b'01110000' 	; set ADC Frc clock
	movwf 	ADCON1 ^ 0x80
	bcf    	STATUS, RP0		; back to BANK 0
	movlw	b'00011101'
	movwf 	ADCON0	 		; left justify, Vdd Vref, AN7, On	

	
loop
	movlw	250
	movwf	del
	call	delay			; 250 msec delay
	movlw	250
	movwf	del
	call	delay			; 250 msec delay

	bsf		ADCON0, GO		; start ADC operation
	btfsc	ADCON0, GO		; and wait for its completion	
	 goto 	$-1
	movf	ADRESH, w		; get high 8 bits of ADC
; movlw 250	

; compute bar*6 + CORR
	movwf	bar				; multiply bar by 6
	clrf	bar+1
	rlf		bar, f			; bar *= 2
	rlf		bar+1, f	
	bcf		bar, 0
	addwf	bar, f			; bar *= 3
	btfsc	STATUS, C
	 incf	bar+1, f
	rlf		bar, f			; bar *= 6
	rlf		bar+1, f
	bcf		bar, 0

	movlw	low	CORR		; add corr constant
	addwf	bar, f
	btfsc	STATUS, C
	 incf	bar+1, f
	movlw	high CORR		; bar = pressure*10
	addwf	bar+1, f		; (max 4 decimal digits)

	call	baro2BCD
;	movlw	5
;	addwf	bcd+1, f
	call	writeMSG
  	goto 	loop			; endless loop


; procedures
baro2BCD	
	movlw	16				; 16-bits
	movwf	temp			; make cycle counter
	clrf	bcd				; clear result area
	clrf	bcd+1
	
b2bcd2	
	movlw	bcd				; make pointer
	movwf	FSR
	movlw	4
	movwf	cnt

; Mike's routine:
b2bcd3	
	movlw	0x33		
	addwf	INDF, f			; add to both nybbles
	btfsc	INDF, 3			; test if low result > 7
	 andlw	0xF0			; low result >7 so take the 3 out
	btfsc	INDF, 7			; test if high result > 7
	 andlw	0x0F			; high result > 7 so ok
	subwf	INDF, f			; any results <= 7, subtract back
	incf	FSR, f			; point to next
	decfsz	cnt, f
	 goto	b2bcd3
	
	rlf		bar+0, f		; get another bit
	rlf		bar+1, f

	rlf		bcd+1, f		; put it into bcd
	rlf		bcd+0, f
	decfsz	temp, f			; all done?
	 goto	b2bcd2			; no, loop
	return					; yes

msg1						; first message to display
	addwf	PCL, f
	dt " Pressure:", 0

msg2						; second message to display
	addwf	PCL, f
	dt " mmHg", 0

;*******************LCD interface
writeMSG
; output of the top row (msg1)
	movlw	b'10000001'		; clear display
	call	writeLCD

	clrf 	i			
L1	movf	i, w
	call	msg1			; get the next char
	iorlw	0				; end of string?
	btfsc	STATUS, Z
	goto 	L2				; YES - jump out of the loop
	call 	writeLCD		; NO - send it to LCD
	incf	i, f			; update the char index
	goto 	L1

L2	movlw	0xC0
	call 	writeLCD		; move the cursor to the second line
	clrf	i				; clear the index of the second string

; output the bottom row 
	swapf	bcd, w
	andlw	0x0F
	addlw	48				; ASCII conversion
	call	writeLCD
	movf	bcd, w
	andlw	0x0F
	addlw	48
	call	writeLCD
	swapf	bcd+1, w
	andlw	0x0F
	addlw	48
	call	writeLCD
	movlw	46				; decimal point
	movwf	dataIO
	call	writeLCD
	movf	bcd+1, w
	andlw	0x0F
	addlw	48
	call	writeLCD	

; output msg2
L3 	movf	i, w				
	call	msg2			; get the next char
	iorlw	0				; end of string?
	btfsc	STATUS, Z			
	 goto 	L4				; YES - jump out of the loop
	call 	writeLCD		; NO - send it to LCD
	incf	i, f			; update the char index
	goto 	L3

L4	return

writeLCD					; write byte in W to the LCD line
	movwf	dataIO
	movlw	b'111001'
	andwf	PORTC, f
	movlw	0x87			; setup FSR to point to TRISC
	movwf	FSR
	bsf		INDF, SCL		; make sure that clock is high
	movlw	8
	movwf	cnt				; bits counter

w_loop
	btfss	PORTC, SCL		; wait for release of the clock line
	 goto	$-1

	bcf		INDF, SCL		; set clock low
	rlf		dataIO, f		; get the rightmost data bit
	btfss	STATUS, C
	 bcf	INDF, SDA
	btfsc	STATUS, C
	 bsf	INDF, SDA		; now the data bit is on the line
	goto	$+1				; short delay
	bsf		INDF, SCL		; raise clock up

	movlw	6				; a 20 usec delay
	addlw	-1
	btfss	STATUS, Z
	 goto	$-2

	decfsz	cnt, f
	 goto	w_loop			; repeat this 8 times
	return

delay						; a delay for del milliseconds
	movlw 	200
	
	sublw	1				; this loop takes 5us*200 = 1ms
	sublw	0				; for PIC @ 4 Mhz
	btfss	STATUS, Z
	goto 	$-3

	decfsz	del, f
	goto 	delay
	return

 end
