;============================={INFORMATION}==================================
;	File:		lcd.asm
;	Project:	PIC/lcd
;	Author:		Tamás Nagy
;	Version:	1.00
;	Used PIC:	PIC16F88A
;****************************************************************************
;============================={DESCRIPTION}==================================
;LCD functions>
;	LCD_Init 	- initialize LCD display
;	LCD_Data 	- send data to LCD
;	LCD_Instr 	- send instruction to LCD
;	LCD_Clear 	- clear LCD
;	LCD_Goto 	- move cursor to position
;	LCD_ON 		- LCD ON
; 	LCD_OFF		- LCD OFF
;	LCD_Shift_Left	- shift display left
;	LCD_Shift_Right	- shift diplay right
;	LCD_Cursor_ON	- cursor ON
;	LCD_CBlink_ON	- cursor and cursor blink ON
;	LCD_CB_OFF	- cursor and cursor blink OFF
;	LCD_Cursor_Inc	- increment cursor position after writing data
;	LCD_Cursor_Dec	- decrement cursor position after writing data
;	LCD_Home	- return home (position 0)
;****************************************************************************
;	Delay times>
;	delay_100ms:
;		16MHz = 50ms
;		8MHz = 100ms	-> default setting, must change the delay
;		4MHz = 200ms
;		1MHz = 400ms
;	delay_1ms:
;		16MHz = 500us
;		8MHz = 1ms	-> default setting, must change the delay
;		4MHz = 2ms
;		1MHz = 4ms
;****************************************************************************
;------------------------------{DEFINITIONS}---------------------------------
#define		w	0
#define		f	1
;-------------------------------{VARIABLES}----------------------------------
	cblock	0x20
		t,t1,t2,LCD_Temp,temp,count
	endc
;=================================={LCD}=====================================
LCD_Init:
	movlw	d'50'		;wait more than 15ms power time
	call	delay_1ms
	movlw	b'00110000'	;function set, interface is 8 bit long
	call	LCD_Instr
	movlw	d'20'		;wait more than 5ms
	call	delay_1ms
	movlw	b'00110000'	;function set, interface is 8 bit long
	call	LCD_Instr
	movlw	d'2'		;wait more than 100us
	call	delay_1ms
	movlw	b'00110000'	;function set, interface is 8 bit long
	call	LCD_Instr
	movlw	d'2'		;wait 
	call	delay_1ms
	movlw	b'00100000'	;function set, interface is 4 bit long
	call	LCD_Instr
	movlw	d'2'		;wait 
	call	delay_1ms
	movlw	b'00101000'	;0 0 1 DL N F - - 
	call	LCD_Instr	;DL=0 (4 bit comunication), N=1 (two lines), F=0 (font= 5x8 dots)
	movlw	d'2'		;wait 
	call	delay_1ms
	movlw	b'00001000'	;0 0 0 0 1 D C B
	call	LCD_Instr	;D=0 (display off), C=0 (cursor off), B=0 (cursor blinking off)
	movlw	d'2'		;wait 
	call	delay_1ms
	movlw	b'00000001'	;clear display
	call	LCD_Instr	
	movlw	d'2'		;wait 
	call	delay_1ms
	movlw	b'00000110'	;0 0 0 0 0 1 I/D S
	call	LCD_Instr	;I/D=1 (increment position), S=1 (display shift)
	movlw	d'2'		;wait 
	call	delay_1ms
	movlw	b'00001100'	;turn on display, cursor and blinking
	call	LCD_Instr
	movlw	d'2'		;wait 
	call	delay_1ms
	movlw	b'00010100'
	call	LCD_Instr
	return	
;-----------------------------{Send LCD data}--------------------------------
LCD_Data:
	movwf	LCD_Temp
	bcf	LCD_D7		;clear all data pins
	bcf	LCD_D6
	bcf	LCD_D5
	bcf	LCD_D4
	
	btfsc	LCD_Temp,7	;writing upper 4 bits
	bsf	LCD_D7
	btfsc	LCD_Temp,6
	bsf	LCD_D6
	btfsc	LCD_Temp,5
	bsf	LCD_D5
	btfsc	LCD_Temp,4
	bsf	LCD_D4
	
	bsf	LCD_E		
	fill	(nop),30
	bcf	LCD_E
	
	bcf	LCD_D7		;clear again all data pins
	bcf	LCD_D6
	bcf	LCD_D5
	bcf	LCD_D4
	
	btfsc	LCD_Temp,3	;write lower 4 bits
	bsf	LCD_D7
	btfsc	LCD_Temp,2
	bsf	LCD_D6
	btfsc	LCD_Temp,1
	bsf	LCD_D5
	btfsc	LCD_Temp,0
	bsf	LCD_D4
	
	bsf	LCD_E
	fill	(nop),30
	bcf	LCD_E
	return
;--------------------------{Send LCD instruction}----------------------------
LCD_Instr:
	bcf	LCD_RS		;send instruction
	call	LCD_Data
	bsf	LCD_RS
	return
;--------------------------------{LCD Clear}---------------------------------
LCD_Clear:
	bcf	LCD_RS
	movlw	0x01		;LCD clear command
	call	LCD_Data
	bsf	LCD_RS
	movlw	d'1'
	call	delay_1ms
	return
;--------------------------------{LCD Goto}----------------------------------
LCD_Goto:
	iorlw	0x80		;LCD goto position
	bcf	LCD_RS
	call	LCD_Data
	bsf	LCD_RS
	movlw	d'1'
	call	delay_1ms
	return
;--------------------------------{LCD Home}----------------------------------
LCD_Home:
	movlw	0x02
	bcf	LCD_RS
	call	LCD_Data
	bsf	LCD_RS
	movlw	d'1'
	call	delay_1ms
	return	
;-----------------------------{LCD shift left}-------------------------------
;LCD shift instruction: 0 0 0 1 S/C R/L - -
;S/C: 0= Cursor move, 1= Display shift
;R/L: 0= Shift to the left, 1= Shift to the right
LCD_Shift_Left:
	movwf	count
shiftl:	movf	count,w
	iorlw	0x00
	btfsc	STATUS,Z
	return
	movlw	b'00011000'	;display shift to left
	bcf	LCD_RS
	call	LCD_Data
	bsf	LCD_RS
	decf	count,f
	movlw	d'2'		;wait between shifts (100ms/shift)
	call	delay_100ms
	goto	shiftl
;----------------------------{LCD shift right}-------------------------------
;LCD shift instruction: 0 0 0 1 S/C R/L - -
;S/C: 0= Cursor move, 1= Display shift
;R/L: 0= Shift to the left, 1= Shift to the right
LCD_Shift_Right:
	movwf	count
shiftr:	movf	count,w
	iorlw	0x00
	btfsc	STATUS,Z
	return
	movlw	b'00011100'	;display shift to right
	bcf	LCD_RS
	call	LCD_Data
	bsf	LCD_RS
	decf	count,f
	movlw	d'2'		;wait between shifts (100ms/shift)
	call	delay_100ms
	goto	shiftr
;------------------{OFF/ON DISPLAY, CURSOR, CURSOR BLINKING}-----------------
;Display instruction: 0 0 0 0 1 D C B
;Display ON/OFF bit  > 	D: 1= ON, 0= OFF
;Cursor ON/OFF bit   > 	C: 1= ON, 0= OFF
;Cursor blinking bit > 	B: 1= ON, 0= OFF 
LCD_ON:
	bcf	LCD_RS
	movlw	b'00001100'	;Disp = ON, Cursor= OFF, Blink= OFF
	call	LCD_Data
	bsf	LCD_RS
	movlw	d'1'
	call	delay_1ms
	return
LCD_OFF:
	bcf	LCD_RS
	movlw	b'00001000'	;Disp = OFF, Cursor= OFF, Blink= OFF
	call	LCD_Data
	bsf	LCD_RS
	movlw	d'1'
	call	delay_1ms
	return
LCD_Cursor_ON:
	bcf	LCD_RS
	movlw	b'00001110'	;Disp = ON, Cursor= ON, Blink= OFF
	call	LCD_Data
	bsf	LCD_RS
	movlw	d'1'
	call	delay_1ms
	return
LCD_CBlink_ON:
	bcf	LCD_RS
	movlw	b'00001111'	;Disp = ON, Cursor= ON, Blink= ON
	call	LCD_Data
	bsf	LCD_RS
	movlw	d'1'
	call	delay_1ms
	return
LCD_CB_OFF:			
	call	LCD_ON		;Disp = ON, Cursor= OFF, Blink= OFF
	return
;--------------{Cursor shift direction and Accompanies shift}---------------
;Instruction: 0 0 0 0 0 1 I/D S
;I/D: 0= Decrement, 1= Increment
;S: 1= Accompanies display shift
LCD_Cursor_Inc:	
	iorlw	b'00000110'
	bcf	LCD_RS
	call	LCD_Data
	bsf	LCD_RS
	movlw	d'1'
	call	delay_1ms
	return
LCD_Cursor_Dec:
	iorlw	b'00000100'
	bcf	LCD_RS
	call	LCD_Data
	bsf	LCD_RS
	movlw	d'1'
	call	delay_1ms
	return
;****************************************************************************
;-------------------------------{DELAY 100ms}--------------------------------
delay_100ms:			;default 8MHz clock
	movwf	t		
	clrf	t1		;16MHz = 50ms
	clrf	t2		;8MHz = 100ms
del:	decfsz	t2,f		;4MHz = 200ms
	goto	del		;1MHz = 400ms
	decfsz	t1,f		
	goto	del
	decfsz	t,f
	goto	del		
	return
;--------------------------------{DELAY 1ms}----------------------------------	
delay_1ms:			;default 8MHz clock
	movwf	t
	clrf	t1		;16MHz = 500us
del1:	fill	(nop),5		;8MHz = 1ms
	decfsz	t1,f		;4MHz = 2ms
	goto	del1		;1MHz = 4ms
	decfsz	t,f
	goto	del1
	return
;****************************************************************************