;**************************************************************************
;* Test LCD displeje 2x16 znaku                                24.10.2001 *
;*                                                                        *
;**************************************************************************
;*                       http://www.cmail.cz/doveda                       *
;**************************************************************************
;*                                  PIC16F84                              *
;*                             --------\/--------                         *
;*                            -|RA2          RA1|-  LCD RS                *
;*                            -|RA3          RA0|-  LCD E                 *
;*            PODSVICENI      -|RA4         osc1|-  \ Krystal 4,00MHz     *
;*                       +5V  -|MCLR        osc2|-  /                     *
;*                        0V  -|Vss          Vdd|-  +5V                   *
;*            LCD data bit 4  -|RB0/INT  PGD/RB7|-                        *
;*            LCD data bit 5  -|RB1      PGC/RB6|-                        *
;*            LCD data bit 6  -|RB2          RB5|-                        *
;*            LCD data bit 7  -|RB3          RB4|-                        *
;*                             ------------------                         *
;*                                              DOVEDA BOYS (c) 1997-2001 *
;**************************************************************************

list	p=16f84, R=DEC
include	"p16f84.inc"

RAM		equ	0Ch	; první adresa paměti RAM pro PIC16F84 - 68bajtů (0C-2F)
TMP_W		equ	RAM+1	; temp preruseni
TMP_S		equ	RAM+2	; temp preruseni
TMP_PCL		equ	RAM+3	; temp preruseni

TMP0		equ	RAM+10	; cekaci smycka
TMP1		equ	RAM+11	; cekaci smycka
TMP2		equ	RAM+12	; cekaci smycka
TMP3		equ	RAM+13	; cekaci smycka, stisk tlacitka

TEXT		equ	RAM+20	; zobrazeni textu na LCD
ZNAK		equ	RAM+21	; zobrazeni znaku na LCD
ADRESA		equ	RAM+22	; inicializace cestiny, adresa pro misto znaku
CISLO		equ	RAM+23	; pomocne cislo

#define	E	PORTA,0		;
#define	RS	PORTA,1		;
#define	SVITI	PORTA,4		;

	org	0x2007		; adresa konfigurace PIC16F84
	dw _XT_OSC & _PWRTE_OFF & _WDT_OFF & _CP_OFF

	org	0x2100		; adresa EERAM
	de	0x02, 0x04, 0x1E, 0x01, 0x0F, 0x11, 0x0F, 0x00	; znak0 = 40h	á
	de	0x02, 0x04, 0x0C, 0x04, 0x04, 0x04, 0x0E, 0x00	; znak1 = 48h	í
	de	0x0A, 0x04, 0x0E, 0x11, 0x1F, 0x10, 0x0E, 0x00	; znak2 = 50h	ě
	de	0x0A, 0x04, 0x0E, 0x10, 0x0E, 0x01, 0x1E, 0x00	; znak3 = 58h	š
	de	0x0A, 0x04, 0x0E, 0x10, 0x10, 0x11, 0x0E, 0x00	; znak4 = 60h	č
	de	0x0A, 0x04, 0x16, 0x19, 0x10, 0x10, 0x10, 0x00	; znak5 = 68h	ř
	de	0x0A, 0x04, 0x1F, 0x02, 0x04, 0x08, 0x1F, 0x00	; znak6 = 70h	ž
	de	0x02, 0x04, 0x11, 0x11, 0x0F, 0x01, 0x0E, 0x00	; znak7 = 78h	ý

	org	0		; zacatek programu
	goto	INIT		; skok na počáteční inicializaci

;*************************************************************
TAB_TXT	addwf	PCL,F
	retlw	'T'		; 0
	retlw	'e'
	retlw	's'
	retlw	't'
	retlw	' '
	retlw	'L'
	retlw	'C'
	retlw	'D'
	retlw	80h		; konec textu
;-------------------------------
	retlw	'1'		; 9
	retlw	'.'
	retlw	'0'
	retlw	'-'
	retlw	'2'
	retlw	'0'
	retlw	'0'
	retlw	'2'
	retlw	80h		; konec textu
;-------------------------------
	retlw	' '		; 18
	retlw	04h
	retlw	'e'
	retlw	's'
	retlw	'k'
	retlw	07h
	retlw	' '
	retlw	' '
	retlw	80h		; konec textu
;-------------------------------
	retlw	' '		; 27
	retlw	'z'
	retlw	'n'
	retlw	'a'
	retlw	'k'
	retlw	'y'
	retlw	' '
	retlw	' '
	retlw	80h		; konec textu
;-------------------------------
	retlw	'L'		; 36
	retlw	'i'
	retlw	'n'
	retlw	'e'
	retlw	' '
	retlw	' '
	retlw	'1'
	retlw	' '
	retlw	80h		; konec textu
;-------------------------------
	retlw	'L'		; 45
	retlw	'i'
	retlw	'n'
	retlw	'e'
	retlw	' '
	retlw	' '
	retlw	'2'
	retlw	' '
	retlw	80h		; konec textu
;*************************************************************
TAB_CZ	addwf	PCL,F		; definování českých znaků pro LCD
;       ------------------------
	retlw	0x02		; znak0 = 40h	á
	retlw	0x04
	retlw	0x1E
	retlw	0x01
	retlw	0x0F
	retlw	0x11
	retlw	0x0F
	retlw	0x00
;       ------------------------
	retlw	0x02		; znak1 = 48h	í
	retlw	0x04
	retlw	0x0C
	retlw	0x04
	retlw	0x04
	retlw	0x04
	retlw	0x0E
	retlw	0x00
;       ------------------------
	retlw	0x0A		; znak2 = 50h	ě
	retlw	0x04
	retlw	0x0E
	retlw	0x11
	retlw	0x1F
	retlw	0x10
	retlw	0x0E
	retlw	0x00
;       ------------------------
	retlw	0x0A		; znak3 = 58h	š
	retlw	0x04
	retlw	0x0E
	retlw	0x10
	retlw	0x0E
	retlw	0x01
	retlw	0x1E
	retlw	0x00
;       ------------------------
	retlw	0x0A		; znak4 = 60h	č
	retlw	0x04
	retlw	0x0E
	retlw	0x10
	retlw	0x10
	retlw	0x11
	retlw	0x0E
	retlw	0x00
;       ------------------------
	retlw	0x0A		; znak5 = 68h	ř
	retlw	0x04
	retlw	0x16
	retlw	0x19
	retlw	0x10
	retlw	0x10
	retlw	0x10
	retlw	0x00
;       ------------------------
	retlw	0x0A		; znak6 = 70h	ž
	retlw	0x04
	retlw	0x1F
	retlw	0x02
	retlw	0x04
	retlw	0x08
	retlw	0x1F
	retlw	0x00
;       ------------------------
	retlw	0x02		; znak7 = 78h	ý
	retlw	0x04
	retlw	0x11
	retlw	0x11
	retlw	0x0F
	retlw	0x01
	retlw	0x0E
	retlw	0x00
;*************************************************************
INIT	movlw	b'00000'
	movwf	PORTA		; přednastavení PORTu A

	movlw	b'00000000'
	movwf	PORTB		; přednastavení PORTu B
;       ------------------------
	bsf	STATUS,RP0	; nastavení BANKY 1
	movlw	b'00000'	; portA 4-0 vystupy
	movwf	TRISA

	movlw	b'01010100'	; PULL-UPy ON, 1:256
	movwf	OPTION_REG
	movlw	b'11110000'	; portB 7-0, 4vstupy, 4vystupy
	movwf	TRISB

	bcf	STATUS,RP0	; nastavení BANKY 0
;       ------------------------
	call	INI_LCD		; inicializace LCD
;	call	CESTINA		; české znaky do LCD
;	call	CZ_INI		; české znaky do LCD

;	call	VERZE		; zobrazí softwerovou verzi
	
	GOTO	MAIN_1
;*************************************************************
MAIN	call	C_LCD		; smaz LCD displej, 1 radek a 1 znak
	movlw	.36		; text 36 - Line 1
	call	WR_TEXT
;       ------------------------
	call	LINE2
	movlw	.45		; text 45 - Line 2
	call	WR_TEXT
;       ------------------------
	call	CEK2s		; cekej 2 sekundu
;-------------------------------
	bsf	SVITI		; zapni podsvícení
;*************************************************************
MAIN_1	call	C_LCD		; smaz LCD displej, 1 radek a 1 znak

	movlw	'A'
	call	WR_DATA
	movlw	'n'
	call	WR_DATA
	movlw	'1'
	call	WR_DATA
	movlw	' '
	call	WR_DATA
	movlw	' '
	call	WR_DATA
	movlw	'2'
	call	WR_DATA
	movlw	'5'
	call	WR_DATA
	movlw	'5'
	call	WR_DATA
;       ------------------------
	call	LINE2

	movlw	'A'
	call	WR_DATA
	movlw	'n'
	call	WR_DATA
	movlw	'2'
	call	WR_DATA
	movlw	' '
	call	WR_DATA
	movlw	' '
	call	WR_DATA
	movlw	'1'
	call	WR_DATA
	movlw	'2'
	call	WR_DATA
	movlw	'8'
	call	WR_DATA

	bsf	SVITI		; zapni podsvícení

	call	CEK2s		; cekej 2 sekundu
;       ------------------------
	bcf	SVITI		; vypni podsvícení

	goto	MAIN_1
;*************************************************************
MAIN_2	call	C_LCD		; smaz LCD displej, 1 radek a 1 znak
	movlw	.18		; text 18 - ceske
	call	WR_TEXT
;       ------------------------
	call	LINE2
	movlw	.27		; text 27 - znaky
	call	WR_TEXT
;       ------------------------
	call	CEK2s		; cekej 2 sekundu
;*************************************************************
WR_TEXT	movwf	TEXT		; W -> TEXT
	call	TAB_TXT
	movwf	ZNAK		; W -> ZNAK
	sublw	0x80
	btfsc	STATUS,Z
	retlw	0x00		; pokud je znak = 80h, konec textu
;       ------------------------
	movf	ZNAK,W		; ZNAK -> W
	call	WR_DATA
;       ------------------------
	incf	TEXT,W		; TEXT + 1 -> W
	goto	WR_TEXT
;*************************************************************
LINE1	movlw	0x80		; 1 radek, 0 znak displeje
	goto	WR_CMD
;-------------------------------
LINE2	movlw	0xC0		; 2 radek, 0 znak displeje
	goto	WR_CMD
;-------------------------------
C_LCD	movlw	0x01		; smaz LCD a vrat se na pozici 0
	goto	WR_CMD
;-------------------------------
WR_CMD	bcf	RS		; RS=0, zápis instrukcí do LCD
	goto	WR_LCD
;-------------------------------
WR_DATA	bsf	RS		; RS=1, zápis dat do LCD
	goto	WR_LCD
;-------------------------------
WR_LCD	movwf	ZNAK		; přepsat W do ZNAK	!!! data v registru W !!!

	bsf	E		; nastav Enable
	movf	PORTB,W		; stav portu do W
	iorlw	0x0F		; zamaskuje dolni bity portu
	movwf	TMP1
;-------------------------------
	swapf	ZNAK,W
	iorlw	0xF0		; zamaskuje horní bity znaku

	andwf	TMP1,W		; pošle vyšší 4 bity
	movwf	PORTB		; !!! data zapsána na PORTB 0-3 !!!
	bcf	E		; zapiše do LCD
;-------------------------------
	bsf	E		; nastav Enable
	movf	ZNAK,W
	iorlw	0xF0		; zamaskuje horní bity znaku

	andwf	TMP1,W		; pošle nižší 4 bity
	movwf	PORTB		; !!! data zapsána na PORTB 0-3 !!!
	bcf	E		; zapiše do LCD
;-------------------------------
	btfsc	RS
	goto	CEK40		; RS=1, zápis dat - čekej 40 us
;       ------------------------
	movlw	0x04		; instrukce 1, 2 a 3 - čekej 1,64 ms
	subwf	ZNAK,W
	btfss	STATUS,C
	goto	CEK1m6		; C=0, instrukce CLEAR - čekej 1,64 ms
	goto	CEK40		; C=1, zápis dat - čekej 40 us
;*************************************************************
INI_LCD	call	CEK15m		; 4-bitová inicializace displeje LCD
;	call	CEK15m
	bcf	RS		; RS=0, zápis instrukcí do LCD
;       ------------------------
	movlw	03h
	movwf	PORTB
	bsf	E
	bcf	E		; zapiše do LCD
;	call	CEK4m		; čekej 4 ms
	call	CEK15m		; !! pro zjednoduseni dano 15ms !!
;       ------------------------
	bsf	E
	bcf	E		; zapiše do LCD
	call	CEK100		; čekej 100 us
;       ------------------------
	bsf	E
	bcf	E		; zapiše do LCD
	call	CEK1m6		; čekej 1,6 ms
;-------------------------------
	movlw	02h
	movwf	PORTB
	bsf	E
	bcf	E		; zapiše do LCD
	call	CEK1m6		; čekej 1,6 ms
;-------------------------------
	movlw	28h		; 00101000 - počet bitů, 2 řádky, 5x7 znak
	call	WR_CMD
	movlw	0Ch		; 00001100 - display ON, kurzor OFF, blikání OFF
	call	WR_CMD
	movlw	01h		; 00000001 - smaže displej
	call	WR_CMD
	movlw	06h		; 00000110 - směr kurzoru, posunu displeje
	call	WR_CMD
	return
;*************************************************************
CESTINA	movlw	0x00		; adresa prvního CZ znaku v EEPROM
	movwf	EEADR
	movlw	0x40		; adresa prvního znaku v LCD displeji
	movwf	ADRESA
;       ------------------------
	movf	ADRESA,W
	call	WR_CMD
	call	READ
	call	WR_DATA
	incf	EEADR,F
	incf	ADRESA,F
	movf	ADRESA,W
	sublw	0x80		; adresa posledního znaku v LCD displeji
	btfss	STATUS,Z
	goto	$-9
	return
;*************************************************************
READ	bsf	STATUS,RP0	; banka 1	!!! nastav EEADR !!!
	bsf	EECON1,RD	; EE read
	bcf	STATUS,RP0	; banka 0
;       ------------------------
	movf	EEDATA,W	; EEDATA -> W
	return			; 		!!! data v registru W !!!
;*************************************************************
CZ_INI	clrf	ADRESA
	movlw	0x40		; adresa znaku v LCD displeji
	call	WR_CMD
;-------------------------------
CZ_IN1;	movlw	0x40		; adresa znaku v LCD displeji
;	addwf	ADRESA,W
;	call	WR_CMD
;       ------------------------
	movf	ADRESA,W
	call	TAB_CZ
	call	WR_DATA
;       ------------------------
	incf	ADRESA,F
	movlw	0x40		; až dosáhne 40h tak skončí
	subwf	ADRESA,W
	btfss	STATUS,Z
	goto	CZ_IN1
;       ------------------------
	return
;*************************************************************
; časy pro frekvenci krystalu 4,00Mhz
; časy jsou spočítané od call CEKxxm do návratu na volání CEKxxm
; celkový výpočet  = 2+6+(2+(TMP0-1)*3+2)+3)*TMP1-1+2
; zkrácený výpočet = 8+((TMP0-1)*3+7)*TMP1+1
; malá smyčka = (TMP2-1)*3+2
;-------------------------------
CEK2s	movlw	.20		; TMP2 = 20  cekej 2 sekundu
	movwf	TMP3
	goto	SMYCKA2
;-------------------------------
CEK100m	movlw	0CFh		; cas = 100,009 ms
	movwf	TMP0
	movlw	0A0h
	movwf	TMP1
	goto	SMYCKA
;-------------------------------
CEK15m	movlw	0ABh		; cas = 15,002 ms
	movwf	TMP0
	movlw	01Dh
	movwf	TMP1
	goto	SMYCKA
;-------------------------------
CEK4m	movlw	0A5h		; cas = 4,001 ms
	movwf	TMP0
	movlw	008h
	movwf	TMP1
	goto	SMYCKA
;-------------------------------
CEK1m6	movlw	041h		; cas = 1,601 ms
	movwf	TMP0
	movlw	008h
	movwf	TMP1
	goto	SMYCKA
;-------------------------------
CEK100	movlw 	01Dh		; cas = 100 mikrosekund
	movwf	TMP0
	movlw	001h
	movwf	TMP1
	goto	SMYCKA
;-------------------------------
CEK40	movlw	009h		; cas = 40 mikrosekund
	movwf	TMP0
	movlw	001h
	movwf	TMP1
	goto	SMYCKA
;-------------------------------
SMYCKA2	call	CEK100m
	decfsz	TMP3,F		; největší smyčka
	goto	SMYCKA2
	retlw	00h
;-------------------------------
SMYCKA	movf	TMP0,W
	movwf	TMP2
SMYCKA1	decfsz	TMP2,F		; malá smyčka
	goto	SMYCKA1

	decfsz	TMP1,F		; velká smyčka
	goto	SMYCKA
	retlw	00h
;*************************************************************
VERZE	call	C_LCD		; smaz LCD displej, 1 radek a 1 znak
	movlw	0x00		; text 0 - jmeno sofware
	call	WR_TEXT

	call	LINE2
	movlw	0x09		; text 9 - verze, datum
	call	WR_TEXT

	call	CEK2s		; cekej 2 sekundu
	return
;*************************************************************
	end
