; LCD Display Demo.asm
; Include the header file for our target chip
	#include "p16f676.inc"

; First line, declare that we want a 16F676 PICC
; and that our numbers will be in Hexadecimal
; unless otherwise noted
	LIST P=16f676, R=HEX

; Tell the programmer what options we want to use
; In this case:
; _WDT_OFF -- Watchdog Timer Off
; _INTRC_OSC_NOCLKOUT -- Internal Oscillator
; _CP_OFF -- Code Protect Off
; _MCLRE_OFF -- disable reset pin, so we can use it for I/O

	__CONFIG _WDT_OFF & _INTRC_OSC_NOCLKOUT & _CP_OFF & _MCLRE_OFF

; Variable Declarations
; Here we assign memory locations for our variables

	cblock	0x20
	  command
	  delay1
	  delay2
	  counter1
	  counter2
	  out_char
	endc
; Uses PORTA<4> for RS, PORTA<5> for E, PORTC<4:7> for 4-bit data bus
; consult HD44780 data sheet for more information
; or http://www.myke.com/lcd.htm for details

#define		RS			PORTA, 4
#define 	E			PORTA, 5
#define 	DATAPORT		PORTC

sdelay	macro
; delays for 3*256 cycles = 153.6us
	local	d0
	movlw	h'50'
	movwf	delay1
d0:	decfsz	delay1,f
	goto	d0
	endm

Estrobe	macro
	bsf		E
	nop
	nop
	nop
	bcf		E
	endm

; First column is always for labels.  Anything in the first
; column will be interpreted by the assembler as a label

	org 	0

	goto	Start

Start
	clrf	DATAPORT			; Initialize Data Port
	clrw				; Clear W register
	bsf		STATUS,RP0		; Select Register Bank 1
	movwf	TRISC			; Set C to all outputs
	movlw	b'000001'
	movwf	TRISA			; set A to all outputs

	movlw	b'00000001'
	movwf	ANSEL			; turn on only analog input 0

	bcf		ADCON1,ADCS2		; set ADCS<2:0> = 001 ->
	bcf		ADCON1,ADCS1		; Sample Time 8*Tosc
	bsf		ADCON1,ADCS0		; from Data Sheet

	bcf		STATUS,RP0		; select Register Bank 0

	movlw	b'11100011'		; set A/D input channel 0
	andwf	ADCON0, f

	bcf		ADCON0, ADFM		; set shift left
	bcf		ADCON0, VCFG		; set reference voltage = Vdd
	bsf		ADCON0, ADON		; turn on A/D converter

	call	ResetDisplay

loop
	bsf		ADCON0, GO		; acquire a sample
wait_for_sample
	btfsc	ADCON0, NOT_DONE
	goto	wait_for_sample

;	call	ClearDisplay

	movlw	b'10000000'
	call	SendCommand

	movlw	d'16'
	movwf	counter2

	movf	ADRESH, W
	movwf	counter1
	swapf	counter1,f
	movlw	h'0f'
	andwf	counter1,f

	movf	counter1,w
	subwf	counter2,f
	
	movf	counter1,f		; update zero flag

	btfsc	STATUS,Z
	goto	BarGraph_Done
	
BarGraph_Loop:
	movlw	b'00111010'
	call	DisplayChar	
	decfsz	counter1,f
	goto	BarGraph_Loop

BarGraph_Done:

	movf	counter2,f		; update zero flag

	btfsc	STATUS,Z
	goto	BarGraph2_Done
	
BarGraph2_Loop:
	movlw	b'00010000'
	call	DisplayChar	
	decfsz	counter2,f
	goto	BarGraph2_Loop

BarGraph2_Done:

;	call	HexToASCII
;	call	DisplayChar
	
;	swapf	out_char,f
;	movf	out_char,w
;	andlw	h'0f'
;	call	HexToASCII
;	call	DisplayChar

;	call	sdelay

	goto	loop

HexToASCII
	sublw	d'9'			; subtract 10 from w
	btfsc	STATUS, C		; if /borrow is clear
	goto	ascii_1			; n < 10
	sublw	h'40'			; make A-F
	return
ascii_1
	sublw	h'39'			; make 0-9
	return



DisplayChar
; Displays character in w
	bsf	RS
	call	SendCommand
	bcf	RS
	return

ClearDisplay:
; Clear the LCD display
; R/S = 0, R/W = 0, DATA1=b'0000', DATA2=b'0001'
	bcf	RS
	movlw	b'00000001'
	call	SendCommand
	movlw	d'100'
	call	delay
	return

SendCommand:
; sends a one-byte command in w to LCD
; assumes RS already set correctly, E cleared
	movwf	command
	swapf	command,f
	movf	command,w
	movwf	DATAPORT
	Estrobe
	swapf	command,f
	movf	command,w
	movwf	DATAPORT
	Estrobe
	sdelay
	return	

ResetDisplay:
; Initializes LCD
	bcf	E
	bcf	RS
	movlw	d'20'			; wait 15.4msec
	call	delay

	movlw	0x3			;
	movwf	DATAPORT			; send 0x3 out
	Estrobe
	movlw	d'6'
	call	delay			; wait 5msec

	Estrobe				; send another 0x3 out
	sdelay				; wait ~160us

	Estrobe				; send another 0x3 out
	sdelay				; wait ~160us

	movlw	0x28			; 4 line interface, 2 line display
	call	SendCommand

	movlw	0x10			; turn off display
	call	SendCommand

	call	ClearDisplay

	movlw	0x06			; set cursor autoincrement
	call	SendCommand

	movlw	b'00001100'		; turn on display
	call	SendCommand	

	return

delay	
; delay for 2+770*w cycles
; at 20MHz that's about 0.154msec*w
	movwf	delay1
	clrf	delay2
d1:
	decfsz	delay2,f
	goto	d1
	decfsz	delay1,f
	goto	d1
	return

	END				; End of program