; 1		Vss -	Ground, 3rd pin of the potentiometer
; 2 	Vcc	-	5V DC, 1st pin of the potentiometer
; 3 	Vee	-	Middle pin of the potentiometer
; 4 	RS	-	RA0		(Data - 1, Instruction - 0)
; 5 	R/W	-	RA1		(R - 1, W - 0)
; 6		E	-	RA2		(Enable Pulse)
; 7		DB0	-	RB0		(LSB)
; 8		DB1	-	RB1
; 9		DB2	-	RB2
; 10	DB3	-	RB3		(Lower 4 bits)
; 11	DB4 -	RB4		(Upper 4 bits)
; 12	DB5	-	RB5
; 13	DB6	-	RB6
; 14	DB7	-	RB7		(MSB)

; Instruction Cycle Time = 1 / (4MHz / 4) = 1us per instruction

;***********************************************************************************

	LIST	p=16F84
	include	"p16f84.inc"
	__CONFIG _HS_OSC & _CP_OFF & _WDT_OFF & _PWRTE_OFF
	errorlevel -302

N 			EQU 0x0C
FIXDELAY	EQU 0x0D

;***********************************************************************************
		ORG 0x00
		GOTO START

START	CLRF	PORTA		; Clear PortA
		CLRF	PORTB		; Clear PortB
		MOVLW	0x00		
		BSF		STATUS, RP0	; Select Bank 1
		MOVWF	TRISA		; Set Port A to output
		MOVWF	TRISB		; Set Port B to output
		BCF		STATUS, RP0	; Select Bank 0
		MOVLW	0xE6		; Call for 46ms delay
		CALL 	NDELAY		; Wait for VCC of the LCD to reach 5V

INITLCD	BCF		PORTA, 0	; Clear RS to select Instruction Reg.
		BCF		PORTA, 1	; Clear R/W to write
		
		MOVLW	B'00111111'	; Function Set to 8 bit
		MOVWF	PORTB
		CALL	ENABLEPULSE
		MOVLW	0x15		; Call for 4.2ms delay
		CALL 	NDELAY

		MOVLW	B'00111111'	; Function Set to 8 bit again
		MOVWF	PORTB
		CALL	ENABLEPULSE
		CALL 	DELAY200	; Call for 200us delay

		MOVLW	B'00111111'	; Function Set to 8 bit again, to make sure it's 8 bit, really
		MOVWF	PORTB
		CALL	ENABLEPULSE
		CALL 	DELAY200	; Call for 200us delay

		MOVLW	B'00111011'	; Function Set to 8 bits, 2 lines and 5x7 dot matrix
		MOVWF 	PORTB
		CALL	ENABLEPULSE
		CALL	DELAY50		; Call 50us delay and wait for instruction completion

		MOVLW	B'00001000'	; Display OFF
		MOVWF	PORTB
		CALL	ENABLEPULSE
		CALL	DELAY50		; Call 50us delay and wait for instruction completion

		MOVLW	B'00000001'	; Clear Display
		MOVWF	PORTB
		CALL	ENABLEPULSE
		MOVLW	0x09		; Call 1.8ms delay and wait for instruction completion				
		CALL	NDELAY		

		MOVLW	B'00000010'	; Cursor Home
		MOVWF	PORTB
		CALL	ENABLEPULSE
		MOVLW	0x09		; Call 1.8ms delay and wait for instruction completion				
		CALL	NDELAY
		
		MOVLW	B'00001100'	; Display ON, Cursor OFF, Blinking OFF
		MOVWF	PORTB
		CALL	ENABLEPULSE
		CALL	DELAY50		; Call 50us delay and wait for instruction completion

		MOVLW 	B'00000110'	; Entry Mode Set, Increment & No display shift
		MOVWF	PORTB
		CALL	ENABLEPULSE
		CALL	DELAY50		; Call 50us delay and wait for instruction completion

; End of Initialization of LCD.

MAIN	BSF		PORTA, 0	; Set RS to select Data Reg.
		BCF		PORTA, 1	; Clear R/W to write

		MOVLW	A'H'		; Send char to be displayed on LCD
		MOVWF	PORTB
		CALL	ENABLEPULSE
		CALL 	DELAY50		; Wait for instruction completion.

		MOVLW	A'e'		; Send char to be displayed on LCD
		MOVWF	PORTB
		CALL	ENABLEPULSE
		CALL 	DELAY50		; Wait for instruction completion.

		MOVLW	A'l'		; Send char to be displayed on LCD
		MOVWF	PORTB
		CALL	ENABLEPULSE
		CALL 	DELAY50		; Wait for instruction completion.

		
		MOVLW	A'l'		; Send char to be displayed on LCD
		MOVWF	PORTB
		CALL	ENABLEPULSE
		CALL 	DELAY50		; Wait for instruction completion.

		MOVLW	A'o'		; Send char to be displayed on LCD
		MOVWF	PORTB
		CALL	ENABLEPULSE
		CALL 	DELAY50		; Wait for instruction completion.

		
		MOVLW	A'!'		; Send char to be displayed on LCD
		MOVWF	PORTB
		CALL	ENABLEPULSE
		CALL 	DELAY50		; Wait for instruction completion.


FOREVER	NOP
		GOTO FOREVER

;***********************************************************************************
; Enable Pulse for writing or reading instructions or data
;***********************************************************************************

ENABLEPULSE	BCF	PORTA, 2
			CALL DELAY50
			BSF	PORTA, 2	; 50us E-Pulse
			CALL DELAY50
			BCF PORTA, 2
			RETURN

;***********************************************************************************
; N DELAY SUBROUTINE, delay in multiples of 200us up to 200us*255 = 51ms (or more)
;***********************************************************************************

NDELAY
			MOVWF N				; N is delay multiplier
NOTOVER		CALL DELAY200		; Call for 200us
			DECFSZ N, 1			; Decrease N by 1
			GOTO NOTOVER		; The delay isn't done
			RETURN
	
;***********************************************************************************
; FIXED 200us DELAY (Possibly more due to execution time of the DECFSZ instruction.)
;***********************************************************************************

DELAY200	
			MOVLW 0xC8			; 200 LOOPS
			MOVWF FIXDELAY		; 200us fixed delay
NOTDONE200	DECFSZ FIXDELAY, 1 	; Decrement of FIXDELAY
			GOTO NOTDONE200		; If 200us isn't up go back to NOTDONE200
			RETURN				; If 200us is up then return to instruction.

;***********************************************************************************
; FIXED 50us DELAY (Possibly more due to execution time of the DECFSZ instruction.)
;***********************************************************************************

DELAY50	
			MOVLW 0x32			; 50 LOOPS
			MOVWF FIXDELAY		; 50us fixed delay
NOTDONE50	DECFSZ FIXDELAY, 1 	; Decrement of FIXDELAY
			GOTO NOTDONE50		; If 50us isn't up go back to NOTDONE50
			RETURN				; If 50us is up then return to instruction.

			END
