;10ADC-V1.asm
;WWW.MWFTR.COM/book.html
;Charles Kim
;This program is to read voltage output from a rheostat
; and display the value on a PC terminal (current is updated every 2 seconds)
;
; AN0 is connected to the rheostat wiper
;;
;USE ONLY most significant 8 bits
;Max 5.00 V
;min 0.00 V
;
;PC's Hyper Terminal Set-Up: 8N1 19200
;Baud: 		19200
;Data Bit:	8
;Parity: 	None
;Stop Bit:	1
;Control: 	None

        list P = 16F877

STATUS	EQU	0x03
ZERO	EQU	0x02		;Z flag
TXSTA	EQU	0x98		;TX status and control
RCSTA	EQU	0x18		;RX status and control
SPBRG	EQU	0x99		;Baud Rate assignment
TXREG	EQU	0x19		;USART TX Register
RCREG	EQU	0x1A		;USART RX Register
PIR1	EQU	0x0C		;USART RX/TX buffer status (empty or full)
RCIF	EQU	0x05		;PIR1<5>: RX Buffer 1-Full  0-Empty
TXIF	EQU	0x04		;PIR1<4>: TX Buffer 1-empty 0-full
TXMODE	EQU	0x20		;TXSTA=00100000 : 8-bit, Async
RXMODE	EQU	0x90		;RCSTA=10010000 : 8-bit, enable port, enable RX
BAUD	EQU	0x0F		;0x0F (19200), 0x1F (9600)
PORTD	EQU	0x08
TRISD	EQU	0x88
PORTA	EQU	0x05
TRISA	EQU	0x85
ADCON0	EQU	0x1f
ADCON1	EQU	0x9f
ADRESH	EQU	0x1e		;High Byte Result
ADRESL	EQU	0x9E		;Low Byte Result
PIE1	EQU	0x8c
GO	EQU	0x02
ADIE	EQU	0x06
ADIF	EQU	0x06


;DISPLAY FORMAT (with two decimal points)
;
; ----	---- ----
;|   |  |  | |  |
;|   |  |  | |  |
;-----. ---- ----
; 
;


  
	CBLOCK	0x20
		temp
		tempten
		HIGHBYTE
		LOWBYTE
		HILO		;flagging for 1(10 or bigger) or 0 (less than 10)
		DIGIT1
		DIGIT2
		DIGIT3		;D1. D2 D3 (display format)  Double precision
		ASCIIreg
		AD1
		AD2
		AD3		;final 3 ASCII digits to be displayed
		Kount20us
		Kount120us   ;Delay count (number of instr cycles for delay)
		Kount100us
		Kount1ms
		Kount10ms
		Kount1s
		Kount10s
		Kount1m
	ENDC	
;
;The Next 5 lines must be here
;because of bootloader arrangement
;Bootloader first execute the first 4 addresses
;then jump to the address what the execution directs 
;=========================================================
        org 	0x0000      	;line 1
	MOVLW	0x00		;line 2 ($0000)
	MOVWF	0x0A		;line 3 ($0001)
	GOTO	START		;line 4 ($0002)
	NOP			;line 5 ($0003)
;======================================================
;start of the program from $0004

START	
	movlw	0xFF
	banksel	TRISA
	movwf	TRISA	;PORTA all outputs 

	banksel	PIE1
	bcf	PIE1, ADIE	;disable ADC interrupt

	banksel	ADCON0		;KKCCCGXO
	movlw	0xC1		;11000001
	movwf	ADCON0		;initialize ADC (RA0 is ADC port)

	
	movlw	0x00
	banksel	ADCON1
	movwf	ADCON1		;PORT A is for ADC channel
				;With LEFT JUSTIFICATION
				;We will ignore two least significant bits
				;without much loss
AGAIN	
	banksel	PIR1
	bcf	PIR1, ADIF	;clear conversion complete flag
	
	banksel	TEMP
	clrf	TEMP
	clrf	DIGIT1
	clrf	DIGIT2
	clrf	DIGIT3
	clrf	AD1
	clrf	AD2
	clrf	AD3
	clrf	HILO

	call	GetADC
	banksel	TEMP
	movwf	TEMP		;Now TEMP holds the 8-bit ADC result
;
; No conversion to Max +5.00  Min 0.00 value

; 1 0000 0000  -->256 --->500
; 0 1000 0000  -->128 --->250
; 0 0100 0000  -->64  --->125
; 0 0010 0000  -->32 ---->063
; 0 0001 0000  -->16 ---->032
; 0 0000 1000  -->8  ---->016
; 0 0000 0100  -->4 ----->008
; 0 0000 0010  -->2 ----->004
; 0 0000 0001  -->1 ----->002

	movlw	0x00
B0	btfss	TEMP,0x00	;check the bit 0 of the ADC result
	goto	B1
	incf	DIGIT3		;DIGIT3=DIGIT3+2
	incf	DIGIT3

B1	btfss	TEMP, 0x01	;bit 1 check
	goto	B2
	incf	DIGIT3
	incf	DIGIT3
	incf	DIGIT3
	incf	DIGIT3		;Digit3=digit3+4

B2	btfss	TEMP, 0x02	;bit 2 check
	goto	B3
	incf	DIGIT3
	incf	DIGIT3
	incf	DIGIT3
	incf	DIGIT3		;
	incf	DIGIT3
	incf	DIGIT3
	incf	DIGIT3
	incf	DIGIT3		;Digit3=digit3+8

; check if it is bigger than 10
	movf	DIGIT3, 0	; to W
	call	TEN
	btfss	HILO,0x00
	goto	B3		;Less than 10
	movlw	0x0A
	subwf	DIGIT3		;f - W -->f
	incf	DIGIT2
	clrf	HILO

B3	btfss	TEMP, 0x03	;bit 3 check
	goto	B4
	incf	DIGIT3
	incf	DIGIT3		;
	incf	DIGIT3
	incf	DIGIT3
	incf	DIGIT3
	incf	DIGIT3		;Digit3=digit3+6
	incf	DIGIT2		;Digit2=Digit2+1
; check if it is bigger than 10
	movf	DIGIT3, 0	; to W
	call	TEN
	btfss	HILO,0x00
	goto	B4		;Less than 10
	movlw	0x0A
	subwf	DIGIT3
	incf	DIGIT2
	clrf	HILO

B4	btfss	TEMP, 0x04	;bit 4 check
	goto	B5
	incf	DIGIT3
	incf	DIGIT3		;Digit3=Digit3+2
	incf	DIGIT2
	incf	DIGIT2
	incf	DIGIT2		;Digit2=Digit2+3

; check if it is bigger than 10
	movf	DIGIT3, 0	; to W
	call	TEN
	btfss	HILO,0x00
	goto	B5		;Less than 10
	movlw	0x0A
	subwf	DIGIT3
	incf	DIGIT2
	clrf	HILO

B5	btfss	TEMP, 0x05	;bit 5 check
	goto	B6
	incf	DIGIT3
	incf	DIGIT3
	incf	DIGIT3		;Digit3=Digit3+3
	incf	DIGIT2
	incf	DIGIT2
	incf	DIGIT2		;
	incf	DIGIT2
	incf	DIGIT2
	incf	DIGIT2		;Digit2=Digit2+6
; check if it is bigger than 10
	movf	DIGIT3, 0	; to W
	call	TEN
	btfss	HILO,0x00
	goto	D2A		;Less than 10
	movlw	0x0A
	subwf	DIGIT3
	incf	DIGIT2
	clrf	HILO
; Check DIGIT2 for 10 or above
D2A	movf	DIGIT2, 0
	call	TEN
	btfss	HILO, 0x00
	goto	B6
	movlw	0x0A
	subwf	DIGIT2
	incf	DIGIT1
	clrf	HILO

B6	btfss	TEMP, 0x06	;bit 6 check
	goto	B7
	incf	DIGIT3
	incf	DIGIT3
	incf	DIGIT3
	incf	DIGIT3
	incf	DIGIT3		;Digit3=Digit3+5
	incf	DIGIT2
	incf	DIGIT2		;Digit2=Digit2+2
	incf	DIGIT1		;DIgit1=Digit1+1

; check if it is bigger than 10
	movf	DIGIT3, 0	; to W
	call	TEN
	btfss	HILO,0x00
	goto	D2B		;Less than 10
	movlw	0x0A
	subwf	DIGIT3
	incf	DIGIT2
	clrf	HILO
; Check DIGIT2 for 10 or above
D2B	movf	DIGIT2, 0
	call	TEN
	btfss	HILO, 0x00
	goto	B7
	movlw	0x0A
	subwf	DIGIT2
	incf	DIGIT1
	clrf	HILO
	

B7	btfss	TEMP, 0x07	;bit 7 check
	goto	FINI
	incf	DIGIT2
	incf	DIGIT2
	incf	DIGIT2
	incf	DIGIT2
	incf	DIGIT2		;Digit2=Digit2+5
	incf	DIGIT1
	incf	DIGIT1		;DIgit1=Digit1+2

; check if it is bigger than 10

	movf	DIGIT2, 0
	call	TEN
	btfss	HILO, 0x00
	goto	FINI
	movlw	0x0A
	subwf	DIGIT2
	incf	DIGIT1
	clrf	HILO

FINI
	movf	DIGIT1,0
	call	HTOA
	movwf	AD1		;final digit to be displayed
	movf	DIGIT2,0
	call	HTOA
	movwf	AD2
	movf	DIGIT3,0
	call	HTOA
	movwf	AD3	

;
;ready to display
	movf	AD1, 0
	call	TXPOLL
	movlw	'.'
	call	TXPOLL
	movf	AD2,0
	call	TXPOLL
	movf	AD3,0
	call 	TXPOLL
	call	CRLF	;Line Change
;delay 2s
	call	delay1s
	call	delay1s


	goto	AGAIN


;===============================================================
;subroutine to check >=10 or <10 ==================
; >=10  ---> HILO=0
;<10 --->HILO =0
TEN	
	banksel	HILO
	clrf	HILO
	movwf	TEMPTEN
	btfss	TEMPTEN, 0x03	;3rd bit
	return
	btfss	TEMPTEN, 0x02
	goto	nextbit
	bsf	HILO,0x00
	return
nextbit btfss	TEMPTEN,0x01
	return
	bsf	HILO, 0x00
	return
;--------------------------------------------

	



;Subroutine GetADC =========================	
getadc	call	delay10ms	;warm up
	banksel	ADCON0
;	movlw	0
	bsf	ADCON0, GO	;start comversion
adcloop	btfsc	ADCON0, GO	;wat for conversion to finish
	goto	ADCloop
	bcf	PIR1, ADIF	;clear conversion complete flag
	movf	ADRESH,0
	return
;---------------------------------------------------------

;RS232 TX subroutine ============
TXPOLL
	banksel	PIR1
	btfss	PIR1, TXIF	; Check if TX buffer is empty
	goto	TXPOLL
	banksel	TXREG
	movwf	TXREG		; Place the character to TX buffer
	return
;-------------------------
;To send CR and LF ===============
CRLF
	movlw	H'0d'		;CR
	call	TXPOLL
	movlw	H'0a'		;LF
	call	TXPOLL
	return
;-----------------------------
;; === hex to ascii conversion subroutine
;move the content to W before call this routine
;final result will be stired back to W
HTOA
	movwf	ASCIIreg
;check 0-9 or A-F
	btfsc	ASCIIreg, 0x03	;0 - 7
	goto	RECHK
THIRTY	movlw	0x30
	addwf	ASCIIreg
	movf	ASCIIreg,0
	return		
	
RECHK	andlw	0x06	;
	btfsc	STATUS,ZERO
	goto	THIRTY
	movlw	0x37
	addwf	ASCIIreg	
	movf	ASCIIreg,0
	return
;----------------------
;==========================================================
;DELAY SUBROUTINES 


; 1 instruction cycle for 20MHz clock is 0.2 us
; Therefore 120 uS delay needs 600 instuction cycles
;  600 =199*3 +3 ---->Kount=199=0xC7
;  or  =198*3 +6 ---->Kount=198=0xC6
;  or  =197*3 +9 ---->Kount=197=0xC5

Delay20us
	banksel	Kount20us
	movlw	H'1F'		;D'31'
	movwf	Kount20us
R20us	decfsz	Kount20us
	goto	R20us
	return
;
;
Delay120us
	banksel	Kount120us
	movlw	H'C5'		;D'197'
	movwf	Kount120us
R120us	decfsz	Kount120us
	goto	R120us
	return
;
;100us delay needs 500 instruction cycles
;  500 =166*3 +2 ---->Kount=166=0xA6
;  or  =165*3 +5 ---->Kount=165=0xA5
;  or  =164*3 +8 ---->Kount=164=0xA4
Delay100us
	banksel	Kount100us
	movlw	H'A4'
	movwf	Kount100us
R100us	decfsz	Kount100us
	goto	R100us
	return

;
;10ms delay
; call 100 times of 100 us delay  (with some time discrepancy)
Delay10ms 
	banksel	Kount10ms
	movlw	H'64'	;100
	movwf	Kount10ms
R10ms	call	delay100us
	decfsz	Kount10ms
	goto	R10ms
	return
;
;
	
;1 sec delay
;call 100 times of 10ms delay
Delay1s
	banksel	Kount1s
	movlw	H'64'
	movwf	Kount1s
R1s	call	Delay10ms
	decfsz	Kount1s
	goto	R1s
	return
;
;
;10 s delay
;call 10 tiems of 1 s delay
Delay10s
	banksel	Kount10s
	movlw	H'0A'		;10
	movwf	Kount10s
R10s	call	Delay1s
	decfsz	Kount10s
	goto	R10s
	return
;
;1 min delay
;call	60 times of 1 sec delay
Delay1m
	banksel	Kount1m
	movlw	H'3C'	;60
	movwf	Kount1m
R1m	call	Delay1s
	decfsz	Kount1m
	goto	R1m
	return
;======================================================


        END

