;*********************************************************************************************************
;************************************   Xiamen DISPLAY   *************************************************
;*********************************************************************************************************

	list p=16f76
	include "p16f76.inc"
	errorlevel -302 ; supress "register not in bank0, check page bits" message
	__CONFIG _PWRTE_OFF & _BODEN_OFF &_HS_OSC & _WDT_OFF

#DEFINE lcd_RS		PORTA, 0		;LCD Register Select
#DEFINE lcd_RW		PORTA, 1		;LCD Read/Write
#DEFINE lcd_E		PORTA, 2		;LCD Enable
#DEFINE lcd_LED		PORTA, 3		;LCD Backlight
#DEFINE lcd_DAT		PORTB

J		equ	0x20
K		equ	0x21
PDel0	equ	0x22
PDel1	equ	0x23
PDel2	equ	0x24
PDel3	equ	0x25
PDel4	equ	0x26
PDel5	equ	0x27
PDel6	equ	0x28
POSI	equ	0x29

		org		0x00		;Program start
		goto	INICIO

;*****************************************************************************************
;Main program
;*****************************************************************************************
INICIO:
		clrf	STATUS
		bsf		STATUS,RP0	;Change to Bank 1
		movlw	0x06
		movwf	ADCON1
	    movlw   0x00    	;Set w = 00000000
    	movwf   PORTA  		;Set PORTA & PORTB as outputs
    	movwf   PORTB
		bcf		STATUS,RP0	;Change to Bank 0

		call	LCD_INI

;DIRECCIONES DDRAM
; 0x80 LINEA 1 POSICION 1
; 0xC0 LINEA 2 POSICION 1
; 0x94 LINEA 3 POSICION 1
; 0xD4 LINEA 4 POSICION 1
;
;   1    2    3    4    5    6    7    8    9    10   11   12   13   14   15   16   17   18   19   20
;  ___________________________________________________________________________________________________
; | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 8A | 8B | 8C | 8D | 8E | 8F | 90 | 91 | 92 | 93 |
; |---------------------------------------------------------------------------------------------------|
; | C0 | C1 | C2 | C3 | C4 | C5 | C6 | C7 | C8 | C9 | CA | CB | CC | CD | CE | CF | D0 | D1 | D2 | D3 |
; |---------------------------------------------------------------------------------------------------|
; | 94 | 95 | 96 | 97 | 98 | 99 | 9A | 9B | 9C | 9D | 9E | 9F | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 |
; |---------------------------------------------------------------------------------------------------|
; | D4 | D5 | D6 | D7 | D8 | D9 | DA | DB | DC | DD | DE | DF | E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7 |
; |___________________________________________________________________________________________________|
;

		movlw   0xC8		;Set DDRAM Address
		movwf   POSI
		call	LCD_CMD

		call	Delay_50ms

		movlw   0x48		;"H"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x4F		;"O"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x4C		;"L"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x41		;"A"
		call	LCD_DAT
		call	ADDRESS

		call	Delay_50ms

		movlw   0x9C		;Set DDRAM Address
		movwf   POSI
		call	LCD_CMD

		call	Delay_50ms

		movlw   0x4D		;"M"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x55		;"U"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x4E		;"N"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x44		;"D"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x4F		;"O"
		call	LCD_DAT


acabar	nop
		goto	acabar		;Buclee infinito

;*****************************************************************************************
;Subroutines
;*****************************************************************************************
LCD_INI:
	clrf	PORTA		;PORTA = w = 00000000
	clrf	PORTB		;PORTB = w = 00000000

	call	Delay_32ms

	movlw   0x38		;Function Set
	call	LCD_CMD

	call	Delay_40us

	movlw   0x0C		;Display ON/OFF Control
	call	LCD_CMD

	call	Delay_40us

	movlw   0x01		;Clear Display
	call	LCD_CMD

	call	Delay_2ms

	movlw   0x06		;Entry Mode Set
	call	LCD_CMD

	call	Delay_50ms

	return

LCD_E:
	bsf		lcd_E		;LCD Enable=1
	nop
	bcf		lcd_E		;LCD Enable=0
	return

LCD_CMD:
	bcf		lcd_E		;LCD Enable=0
	bcf		lcd_RW		;Activate Write operation RW=0
	bcf		lcd_RS		;RS=0
	movwf	PORTB
	bsf		lcd_E		;LCD Enable=1
	bcf		lcd_E		;LCD Enable=0
	return

LCD_DAT:
	bcf		lcd_E		;LCD Enable=0
	bcf		lcd_RW		;Activate Write operation RW=0
	bsf		lcd_RS		;RS=1
	movwf	PORTB
	bsf		lcd_E		;LCD Enable=1
	bcf		lcd_E		;LCD Enable=0
	return

ADDRESS:
		INCF    POSI, 1		;Incrementa posicion del cursor
		movlw   POSI		;Set DDRAM Address
		call	LCD_CMD

		call	Delay_50ms

		return

;*****************************************************************************************
;Delay 5 useg subroutine
;*****************************************************************************************
Delay_5us:
	goto D1         ; 2 ciclos delay
D1  goto D2         ; 2 ciclos delay
D2  goto D3         ; 2 ciclos delay
D3  goto D4         ; 2 ciclos delay
D4  goto D5         ; 2 ciclos delay
D5  				; 1 ciclo delay
	return			; 2+2 Fin.

;*****************************************************************************************
;Delay 40 useg subroutine
;*****************************************************************************************
Delay_40us:
		movlw	.18			; 1 set numero de repeticion 
		movwf	PDel0		; 1 |
PLoop0	clrwdt				; 1 clear watchdog
		decfsz	PDel0, 1	; 1 + (1) es el tiempo 0  ?
		goto	PLoop0		; 2 no, loop
PDelL1	goto	PDelL2		; 2 ciclos delay
PDelL2	clrwdt				; 1 ciclo delay
		return				; 2+2 Fin.

;*****************************************************************************************
;Delay 2 mseg subroutine
;*****************************************************************************************
Delay_2ms:
		movlw	.5			; 1 set numero de repeticion  (B)
        movwf	PDel1		; 1 |
PLoop1  movlw	.159		; 1 set numero de repeticion  (A)
        movwf	PDel2		; 1 |
PLoop2  clrwdt				; 1 clear watchdog
        clrwdt				; 1 ciclo delay
        decfsz	PDel2, 1	; 1 + (1) es el tiempo 0  ? (A)
        goto	PLoop2		; 2 no, loop
        decfsz	PDel1, 1	; 1 + (1) es el tiempo 0  ? (B)
        goto	PLoop1		; 2 no, loop
        return				; 2+2 Fin.

;*****************************************************************************************
;Delay 32 mseg subroutine
;*****************************************************************************************
Delay_32ms:
		movlw	.89			; 1 set numero de repeticion  (B)
		movwf	PDel3		; 1 |
PLoop3  movlw	.143		; 1 set numero de repeticion  (A)
        movwf	PDel4		; 1 |
PLoop4  clrwdt				; 1 clear watchdog
        clrwdt				; 1 ciclo delay
        decfsz	PDel4, 1	; 1 + (1) es el tiempo 0  ? (A)
        goto	PLoop4		; 2 no, loop
        decfsz	PDel3, 1	; 1 + (1) es el tiempo 0  ? (B)
        goto	PLoop3		; 2 no, loop
PDelL3  goto	PDelL4		; 2 ciclos delay
PDelL4  goto	PDelL5		; 2 ciclos delay
PDelL5						; 1 ciclo delay
        return				; 2+2 Fin.

;*****************************************************************************************
;Delay 50 mseg subroutine
;*****************************************************************************************
Delay_50ms:
		movlw	.110		; 1 set numero de repeticion  (B)
        movwf	PDel5		; 1 |
PLoop5  movlw	.181		; 1 set numero de repeticion  (A)
        movwf	PDel6		; 1 |
PLoop6  clrwdt				; 1 clear watchdog
        clrwdt				; 1 ciclo delay
        decfsz	PDel6, 1	; 1 + (1) es el tiempo 0  ? (A)
        goto	PLoop6		; 2 no, loop
        decfsz	PDel5, 1	; 1 + (1) es el tiempo 0  ? (B)
        goto	PLoop5		; 2 no, loop
PDelL6  goto	PDelL7		; 2 ciclos delay
PDelL7  goto	PDelL8		; 2 ciclos delay
PDelL8  clrwdt				; 1 ciclo delay
        return				; 2+2 Fin.

	end
