 TITLE  "photo1.asm"          		; first prototype
 List P=16F84a, R=DEC
 INCLUDE "p16F84a.inc"

; data segment
 CBLOCK 0x00C                   
 del, cmd				; variables for passing the parameters
 temp, i				; local variables 
 cnt, n, r
 n1, n2					; number to display
 digits
 digits1
 digits2	
 ENDC

; code segment
 PAGE
 __CONFIG _CP_OFF  & _PWRTE_ON  & _WDT_OFF & _HS_OSC

  org 0        		              	; start program at the beginning of mem
  	bsf    	STATUS, RP0      	; change to BANK 1	
  	clrf    TRISB ^ 0x80      	; enable RB1-RB7 for output 
	bcf	TRISA ^ 0x80, 3		; enable input on RA3
	bcf	TRISA ^ 0x80, 0
  	bcf    	STATUS, RP0        	; back to BANK 0

	call 	initLCD			; initialize LCD display

loop
	call 	measure1		; get n1
	call 	measure2		; get n2
	movf	n1, w
	movwf	n
	call 	n2a			; covert n into a string

	movlw	2			; cursor back home
	call 	writeCMD
	movlw	5
	movwf	del
	call 	delay

	movf	digits, w		; write n1 to LCD
	call 	writeDATA
	movf	digits+1, w
	call 	writeDATA
	movf	digits+2, w
	call 	writeDATA

	movf	n2, w			; do the same with the second measrmt
	movwf	n
	call 	n2a

	movlw	0xC0
	call	writeCMD		; cursor to the second line

	movf	digits, w		; write n2 to LCD
	call 	writeDATA
	movf	digits+1, w
	call 	writeDATA
	movf	digits+2, w
	call 	writeDATA

	bcf	PORTB, 6
	bcf	PORTB, 7

	movf	n2, w			; w = n1 - n2
	subwf	n1, w			
	btfss	STATUS, C
	sublw	0			; w = |n1 - n2|
	sublw	15			; w = 15 - w
	btfsc	STATUS, C			
	goto 	L2			; diff is small - continue

	movf	n2, w
	subwf	n1, w
	btfss	STATUS, C
	goto 	L1	
	bsf	PORTB, 6
	goto 	L2
L1	bsf	PORTB, 7

L2	movlw	50			; 50 msec delay
	movwf	del
	call	delay
  	goto 	loop			; endless loop


; procedures
initLCD					; initialize LCD right after power up
	movlw	15
	movwf	del
	call 	delay			; a 15 msec delay after power is on

	movlw	3
	movwf	PORTB			; start LCD init process
	movlw	5
	movwf	del	
	call 	delay			; wait for 5 msec	

	movlw	3
	movwf	PORTB			; start LCD init process
	bsf	PORTB, 4		; toggle the LCD Enable pin
	bcf	PORTB, 4
	movlw	5
	movwf	del	
	call 	delay			; wait for 5 msec

	bsf	PORTB, 4		; repeat the reset command (2nd time)
	bcf	PORTB, 4
	movlw	40			; wait for 200 usec
	sublw	1
	sublw	0
	btfss	STATUS, Z
	goto	$-3

	bsf	PORTB, 4		; repeat the reset command (3rd time)
	bcf	PORTB, 4
	movlw	40			; wait for 200 usec
	sublw	1
	sublw	0
	btfss	STATUS, Z
	goto	$-3

	movlw	2			; initialize LCD 4-bit mode
	movwf	PORTB
	bsf	PORTB, 4		; toggle the LCD Enable pin
	bcf	PORTB, 4

	movlw	0x28			; 2-line mode
	call	writeCMD

	movlw	1
	call 	writeCMD		; clear display

	movlw	5			; wait for 5 msec after clearing
	movwf	del
	call 	delay

	movlw	0x06			; cursor move after each char
	call 	writeCMD

	movlw	0x0E			; turn on LCD and enable cursor
	call 	writeCMD
	return

writeCMD				; write to LCD a 1-byte command in W
	movwf	temp
	swapf	temp, w
	andlw	0x0F			; leave only the high 4 bits in W
	movwf	PORTB
	bsf	PORTB, 4		; toggle the E bit
	bcf	PORTB, 4
	
	movfw	temp			; proceed with the low bit
	andlw	0x0F
	movwf	PORTB
	bsf	PORTB, 4		; toggle the  bit	
	bcf	PORTB, 4

	movlw	40			; wait for 200 usec
	sublw	1
	sublw	0
	btfss	STATUS, Z
	goto	$-3
	return

writeDATA				; write to LCD a 1-byte data in W
	movwf	temp
	swapf	temp, w
	andlw	0x0F			; leave only the lower 4 bits in W	
	movwf	PORTB
	bsf	PORTB, 5		; sending data
	bsf	PORTB, 4		; toggle the E bit
	bcf	PORTB, 4
	
	movfw	temp			; proceed with the low bit
	andlw	0x0F
	movwf	PORTB
	bsf	PORTB, 5		; sending data
	bsf	PORTB, 4		; toggle the  bit	
	bcf	PORTB, 4

	movlw	5			; wait for 5 msec
	movwf	del
	call 	delay
	return

delay					; a delay for del milliseconds
	movlw 	200
	
	sublw	1			; this loop takes 5us*200 = 1ms
	sublw	0			; for PIC16F84A @ 4 Mhz
	btfss	STATUS, Z
	goto 	$-3

	decfsz	del,f
	goto 	delay
	return

div10					; computing n = n/10 and r = n%10
	movlw	5
	movwf	cnt			; cnt = 5
	movf	n, w				
	movwf	r			; r = n
	clrf	n			; n = 0
	movlw	0xA0
	bsf	STATUS, C
		
	subwf	r, f			; loop that executes 5 times
	btfsc	STATUS, C
	goto	$+3
	addwf	r, f
	bcf	STATUS, C

	rlf	n, f			; C = bit of n/10
	movwf	temp
	rrf	temp, f
	movf	temp, w			; shift right W

	decfsz 	cnt, f			; div is done in 5 loop iterations
	goto	$-10			; end of loop
    	return

n2a                                     ; convert a number n into ASCII string
	call 	div10			; n = n / 10; r = n %10	
	movf	r, w
	addlw	48			; ADCII conversion
	movwf	digits+2

	call 	div10
	movf	r, w
	addlw	48
	movwf	digits+1

	call	div10	
	movf	r, w
	addlw 	48
	movwf	digits
	return

measure1				; get the number n1
	clrf	n1		
	bsf	PORTA, 3		; take cap high
		
	incf	n1, f
 	movlw	255
	subwf	n1, w
	btfsc	STATUS, Z
	goto	$+3
	btfsc	PORTA, 2		; is input low ?
	goto	$-6			; back to loop

	bcf	PORTA, 3		; take cap low
	return

measure2				; get the number n2
	clrf	n2
	bsf	PORTA, 0		; take cap high
	
	incf	n2, f
 	movlw	255
	subwf	n2, w
	btfsc	STATUS, Z
	goto	$+3
	btfsc	PORTA, 1		; is input low ?
	goto	$-6			; back to loop

	bcf	PORTA, 0		; take cap low
	return

 end
