;============================={INFORMATION}=====================================
;	File:		lcd.asm
;	Project:	PIC
;	Author:		Tamás Nagy
;	Version:	1.50
;	Used PIC:	PIC18F26K80
;==================={PROCESSOR + INCLUDE + CONFIG}==============================


; PIC18F26K80 Configuration Bit Settings

; ASM source line config statements

		#include "p18F26K80.inc"

; CONFIG1L
		CONFIG  RETEN = ON            ; VREG Sleep Enable bit (Ultra low-power regulator is Enabled (Controlled by SRETEN bit))
		CONFIG  INTOSCSEL = HIGH      ; LF-INTOSC Low-power Enable bit (LF-INTOSC in High-power mode during Sleep)
		CONFIG  SOSCSEL = LOW         ; SOSC Power Selection and mode Configuration bits (Low Power SOSC circuit selected)
		CONFIG  XINST = OFF           ; Extended Instruction Set (Disabled)

; CONFIG1H
		CONFIG  FOSC = INTIO2         ; Oscillator (Internal RC oscillator)
		CONFIG  PLLCFG = OFF          ; PLL x4 Enable bit (Disabled)
		CONFIG  FCMEN = OFF           ; Fail-Safe Clock Monitor (Disabled)
		CONFIG  IESO = OFF            ; Internal External Oscillator Switch Over Mode (Disabled)

; CONFIG2L
		CONFIG  PWRTEN = ON           ; Power Up Timer (Enabled)
		CONFIG  BOREN = SBORDIS       ; Brown Out Detect (Enabled in hardware, SBOREN disabled)
		CONFIG  BORV = 3              ; Brown-out Reset Voltage bits (1.8V)
		CONFIG  BORPWR = ZPBORMV      ; BORMV Power level (ZPBORMV instead of BORMV is selected)

; CONFIG2H
		CONFIG  WDTEN = OFF           ; Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled)
		CONFIG  WDTPS = 1048576       ; Watchdog Postscaler (1:1048576)

; CONFIG3H
		CONFIG  CANMX = PORTC         ; ECAN Mux bit (ECAN TX and RX pins are located on RC6 and RC7, respectively)
		CONFIG  MSSPMSK = MSK7        ; MSSP address masking (7 Bit address masking mode)
		CONFIG  MCLRE = ON            ; Master Clear Enable (MCLR Enabled, RE3 Disabled)

; CONFIG4L
		CONFIG  STVREN = ON           ; Stack Overflow Reset (Enabled)
		CONFIG  BBSIZ = BB2K          ; Boot Block Size (2K word Boot Block size)

; CONFIG5L
		CONFIG  CP0 = OFF             ; Code Protect 00800-03FFF (Disabled)
		CONFIG  CP1 = OFF             ; Code Protect 04000-07FFF (Disabled)
		CONFIG  CP2 = OFF             ; Code Protect 08000-0BFFF (Disabled)
		CONFIG  CP3 = OFF             ; Code Protect 0C000-0FFFF (Disabled)

; CONFIG5H
		CONFIG  CPB = OFF             ; Code Protect Boot (Disabled)
		CONFIG  CPD = OFF             ; Data EE Read Protect (Disabled)

; CONFIG6L
		CONFIG  WRT0 = OFF            ; Table Write Protect 00800-03FFF (Disabled)
		CONFIG  WRT1 = OFF            ; Table Write Protect 04000-07FFF (Disabled)
		CONFIG  WRT2 = OFF            ; Table Write Protect 08000-0BFFF (Disabled)
		CONFIG  WRT3 = OFF            ; Table Write Protect 0C000-0FFFF (Disabled)

; CONFIG6H
		CONFIG  WRTC = OFF            ; Config. Write Protect (Disabled)
		CONFIG  WRTB = OFF            ; Table Write Protect Boot (Disabled)
		CONFIG  WRTD = OFF            ; Data EE Write Protect (Disabled)

; CONFIG7L
		CONFIG  EBTR0 = OFF           ; Table Read Protect 00800-03FFF (Disabled)
		CONFIG  EBTR1 = OFF           ; Table Read Protect 04000-07FFF (Disabled)
		CONFIG  EBTR2 = OFF           ; Table Read Protect 08000-0BFFF (Disabled)
		CONFIG  EBTR3 = OFF           ; Table Read Protect 0C000-0FFFF (Disabled)

; CONFIG7H
		CONFIG  EBTRB = OFF           ; Table Read Protect Boot (Disabled)

;*******************************************************************************
;=============================={DEFINITIONS}====================================
;-------------------------------{I/O PORTS}-------------------------------------
		#define	LCD_E	LATB,1
		#define	LCD_RS	LATB,0
		#define	LCD_D4	LATB,2
		#define	LCD_D5	LATB,3
		#define	LCD_D6	LATB,4
		#define	LCD_D7	LATB,5
		#define	f		1
;-------------------------------{VARIABLES}-------------------------------------
		cblock	0x060
				t,t1,t2,LCD_Temp,temp,count
		endc
;=============================(PROGRAM START)===================================
		org		0x000
;*******************************************************************************
;==========================={MAIN PROGRAM START}================================
main:	
		movlw	0x70
		movwf	OSCCON
		clrf	PORTB
		clrf	LATB
		clrf	TRISB
		bsf		LCD_RS
		bcf		LCD_E
		call	LCD_Init
		call	LCD_ON
		movlw	d'0'
		call	LCD_Goto
		clrf	count
loop:	
		movf	count,w		;counter
		call	msg1		;call text table
		iorlw	0x00		;when return zero then sleep
		btfsc	STATUS,Z	;checking zero bit
		goto	next
		call	LCD_Data	;write character
		incf	count,f		;increment counter
		incf	count,f
		goto	loop
next:
		movlw	d'40'
		call	LCD_Goto
		clrf	count
msgwrite2:
		movf	count,w		;counter
		call	msg2		;call text table
		iorlw	0x00		;when return zero then sleep
		btfsc	STATUS,Z	;checking zero bit
		goto	next1
		call	LCD_Data	;write character
		incf	count,f		;increment counter
		incf	count,f
		goto	msgwrite2
next1:
		movlw	d'80'
		call	delay_100ms
		movlw	d'40'
		call	LCD_Shift_Right
		movlw	d'40'
		call	LCD_Shift_Left
		movlw	d'80'
		call	delay_100ms
		call	LCD_Clear
		sleep
	
msg1:	addwf	PCL,f,0		;character table
		dt	" Hello vilag ",0
msg2:	addwf	PCL,f,0
		dt	" PIC18F26K80 ",0

;*******************************************************************************
;============================={DESCRIPTION}=====================================
;LCD functions>
;	LCD_Init			- initalize 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_Blink_ON		- 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
;		4MHz = 200ms
;		1MHz = 400ms
;	delay_500us:
;		16MHz = 250us
;		8MHz = 500us	-> default
;		4MHz = 1ms
;		1MHz = 2ms
;*******************************************************************************
;=================================={LCD}========================================
LCD_Init:
		movlw	d'60'			; 15ms delay
		call	delay_500us		; Function set 8 bit
		bcf		LCD_RS
		bcf		LCD_D7
		bcf		LCD_D6
		bsf		LCD_D5
		bsf		LCD_D4
		bsf		LCD_E
		bcf		LCD_E

		movlw	d'20'			; 5ms delay
		call	delay_500us		; Function set 8 bit
		bsf		LCD_RS
		bcf		LCD_D7
		bcf		LCD_D6
		bsf		LCD_D5
		bsf		LCD_D4
		bsf		LCD_E
		bcf		LCD_E

		bsf		LCD_RS			; Function set 8 bit
		bcf		LCD_D7
		bcf		LCD_D6
		bsf		LCD_D5
		bsf		LCD_D4
		bsf		LCD_E
		bcf		LCD_E

		movlw	b'00100000'		;function set, interface is 4 bit long
		call	LCD_Instr
	
		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)
	
		call	LCD_OFF

		call	LCD_Clear

		movlw	d'0'
		call	LCD_Cursor_Inc

		return				;display OFF, cursor not setted
;-----------------------------{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
		movlw	d'2'
		call	delay_500us
		bcf		LCD_E

		movlw	d'1'
		call	delay_500us
		
		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
		movlw	d'2'
		call	delay_500us
		bcf		LCD_E
	
		movlw	d'1'
		call	delay_500us
	
		clrf	LCD_Temp
		
		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'4'
		call	delay_500us
		return
;--------------------------------{LCD Goto}-------------------------------------
LCD_Goto:
		iorlw	0x80		;LCD goto position
		bcf		LCD_RS
		call	LCD_Data
		bsf		LCD_RS
		movlw	d'4'
		call	delay_500us
		return
;--------------------------------{LCD Home}-------------------------------------
LCD_Home:
		movlw	0x02
		bcf		LCD_RS
		call	LCD_Data
		bsf		LCD_RS
		movlw	d'3'
		call	delay_500us
		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'3'		;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'3'		;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
		return
LCD_OFF:
		bcf		LCD_RS
		movlw	b'00001000'	;Disp = OFF, Cursor= OFF, Blink= OFF
		call	LCD_Data
		bsf		LCD_RS
		return
LCD_Cursor_ON:
		bcf		LCD_RS
		movlw	b'00001110'	;Disp = ON, Cursor= ON, Blink= OFF
		call	LCD_Data
		bsf		LCD_RS
		return
LCD_CBlink_ON:
		bcf		LCD_RS
		movlw	b'00001111'	;Disp = ON, Cursor= ON, Blink= ON
		call	LCD_Data
		bsf		LCD_RS
		return
LCD_Blink_ON:
		bcf		LCD_RS
		movlw	b'00001101'	;DISP= ON, Cursor= OFF, Blink= ON
		call	LCD_Data
		bsf		LCD_RS
		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
		return
LCD_Cursor_Dec:
		iorlw	b'00000100'
		bcf		LCD_RS
		call	LCD_Data
		bsf		LCD_RS
		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		;2MHz = 400ms
		decfsz	t1,f	;1MHz = 800ms
		goto	del
		decfsz	t,f
		goto	del
		return
;--------------------------------{DELAY 500us}----------------------------------	
delay_500us:			;default 8MHz clock
		movwf	t
		clrf	t1		;16MHz = 250us
del1:	nop				;8MHz = 500us
		decfsz	t1,f	;4MHz = 1ms
		goto	del1	;2MHz = 2ms
		decfsz	t,f		;1MHz = 4ms
		goto	del1
		return
;*******************************************************************************
		end