; --------------------------------------------
; driving a standard 14 pin LCD with 1x16 chars
; in 4-bit mode; fragments, no delay subroutines etc.
; tested on 16F630

#define	rs	PORTA,0	; LCD pin 4
#define	rw	PORTA,1 ; LCD pin 5
#define	en	PORTA,2 ; LCD pin 6
#define	out	PORTC	; RC3, RC2, RC1, RC0 to pins
			;  14,  13,  12,  11 of the LCD

; --------------------------------------------
send_nibble
; sends a nibble in w (low 4 bits) to the LCD
        movwf	out
	nop
	bsf	en	; LCD reads on falling edge
	nop
	nop
	nop
	bcf	en
	nop
	return

; --------------------------------------------
send_byte
; sends a byte in w to the LCD, in 4 bit mode
	movwf	byte
	swapf	byte,w
	andlw	0x0F
	call	send_nibble
	movf	byte,w
	andlw	0x0F
	call	send_nibble
	call	dly_175us
	return

; --------------------------------------------
setup_lcd
	call	dly_5ms
	call	dly_5ms
	call	dly_5ms
	bcf	rw
	bcf	rs
	bcf	en
	movlw	B'0011'
	call	send_nibble
	call	dly_5ms
	movlw	B'0011'
	call	send_nibble
	call	dly_175us
	movlw	B'0011'
	call	send_nibble
	call	dly_175us
	movlw	B'0010'		; set 4 bit operation
	call	send_nibble
	call	dly_175us
	movlw	B'00101000'	; two virtual lines
	call	send_byte
	movlw	B'00011100'	; cursor shift
	call	send_byte
	movlw	B'00000110'	; left to right
	call	send_byte
	movlw	B'00000001'	; clear
	call	send_byte
	call	dly_5ms
	movlw	B'00001100'	; display on, cursor off
	call	send_byte
	bsf	rs
	return

; --------------------------------------------
move_cursor
	; w contains cursor position, between 0 and 15
	movlw	D'8'
	subwf	offset,w
	btfsc	STATUS,C
	goto	line2
	movlw	H'00'
	goto	set_pos
line2	movlw	H'40'
set_pos
	addwf	offset,w
	xorlw	B'10000000'
	bcf	rs
	call	send_byte
	call	dly_5ms
	bsf	rs
	return

