 TITLE  "lcdTX.asm"            
 List P=12F683, R=DEC
 INCLUDE "p12F683.inc"

SCL	EQU	4			; Clock line setup
SDA	EQU 5				; Data line setup

; data segment
 CBLOCK 0x20                   
 del, cnt, i 				; local variables
 dataIO, sym
 button
 ENDC

; code segment
 __CONFIG _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	GPIO			; initialize GPIO
	movlw	7
	movwf	CMCON0			; disable the comparator
	clrf	ADCON0			; ADC OFF
  	bsf    	STATUS, RP0      	; change to BANK 1
	clrf	ANSEL ^ 0x80 		; all inputs digital 
	movlw	b'111100'
	movwf	TRISIO ^ 0x80		; enable GP5:2 for input
	bcf	OPTION_REG ^ 0x80, 7	; enable weak pull-up
	movlw	b'000100'		; on GPIO:2
	movwf	WPU ^ 0x80
  	bcf    	STATUS, RP0        	; back to BANK 0

	clrf	button
loop
	btfss	GPIO, 2			; button is pressed?
	 goto	debounce		; NO - keep monitoring it
	clrf	button

	goto 	loop

debounce
	btfsc	button, 0		; button debouncing
	 goto 	loop			; wait for button release

	bsf	button, 0		; button is pressed for the first time
	call	writeMSG

	movlw	20			; debouncing delay
	movwf	del
	call 	delay	
	goto	loop


; PROCEDURES
msg1					; first message to display
	addwf	PCL, f
	dt "  Welcome to", 0

msg2					; second message to display
	addwf	PCL, f
	dt "PIC programming", 0

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 (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'001111'
	andwf	GPIO, f
	movlw	0x85			; setup FSR to point to TRISIO
	movwf	FSR
	bsf	INDF, SCL		; make sure that clock is high
	movlw	8
	movwf	cnt			; bits counter

w_loop
	btfss	GPIO, 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 PIC12F683 @ 4 Mhz
	btfss	STATUS, Z
	goto 	$-3

	decfsz	del, f
	goto 	delay
	return
 END
