;Program: Zápis s pamětí
;*********************************
	LIST P = 16F84,	R = DEC
	#INCLUDE <P16F84.INC>
;---------------------------------
 __CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;****************************************************************************
RAM	EQU	H'0C'
RBF	EQU	RAM
RBF1	EQU	RAM+1
NUM	EQU	RAM+2
NUM1	EQU	RAM+3
TMP	EQU	RAM+4
TM1	EQU	RAM+5
TM2	EQU	RAM+6
ADRDD	EQU	RAM+7
POM	EQU	RAM+8

#define	Q	PORTB,0
#define	RS	PORTB,1	
#define	RW	PORTB,2
#define	E	PORTB,3
#define	BF	RBF,3
;****************************************************************************
	ORG	0
	GOTO	START
;****************************************************************************
;PODPROGRAMY
;****************************************************************************
INILCD	CALL	t15mS		;doba 15 milisekund
	BCF	RS
	BCF	RW
	CALL	A_OUT 		;port A výstup
	BSF	E
	MOVLW	B'00000011'
	MOVWF	PORTA
	BCF	E
	CALL	t4mS 		;doba 4 milisekund
	BSF	E
	MOVLW	B'00000011'
	MOVWF	PORTA
	BCF	E
	CALL	t100uS 		;doba 100 mikrosekund
	BSF	E
	MOVLW	B'00000011'
	MOVWF	PORTA
	BCF	E
	CALL	t100uS 		;doba 100 mikrosekund
	MOVLW	B'00101000'
	CALL	WRPRI 		;4.bitová komunikace a dva řádky
	MOVLW	B'00001000'
	CALL	WRPRI 		;displej OFF
	MOVLW	B'00001100'
	CALL	WRPRI 		;displej ON, kurzor OFF, blikání OFF
	MOVLW	B'00000110'
	CALL	WRPRI 		;inkrementace, normální operace
	RETURN
;----------------------------------------------------------------------------
WRDATA	BSF	RS 		;nastavení bitu RS pro zápis dat
	GOTO	$+2
WRPRI	BCF	RS 		;nastavení bitů RS a RW pro zápis příkazu
	BCF	RW
	MOVWF	TMP 		;číslo příkazu nebo data do registru TMP
	CALL	A_OUT 		;portA jako výstup
	SWAPF	TMP,W 		;horní 4 bity do registru W
	BSF	E
	MOVWF	PORTA 		;zápis 4 horních bitů do displeje
	BCF	E
	MOVFW	TMP 		;obsah registru TMP do registru W
	BSF	E
	MOVWF	PORTA 		;zápis dolních 4 bitů do displeje
	BCF	E
	CALL	T_BF 		;testování bitu BF
	RETURN
;----------------------------------------------------------------------------	
RDDATA	CALL	WRPRI 		;nastavení čtené adresy
	CALL	A_IN 		;port A vstup		
	BSF	RS
	BSF	RW
	BSF	E
	MOVFW	PORTA
	MOVWF	NUM 		;jedna půlka dat do registru NUM
	SWAPF	NUM,F
	BCF	E
	MOVLW	B'11110000'
	ANDWF	NUM,F 		;úprava registru NUM
	BSF	E
	MOVFW	PORTA
	MOVWF	NUM1
	BCF	E
	MOVLW	B'00001111'
	ANDWF	NUM1,W
	IORWF	NUM,F 		;druhá půlka dat do registru NUM
	CALL	T_BF 		;čeká konec operace
	RETURN
;----------------------------------------------------------------------------
T_BF	BCF	RS 		;podprogram testuje konec operace (bit BF)
	BSF	RW
	CALL	A_IN 		;portA vstup (po ukončení zase výstup)
	BSF	E
	MOVFW	PORTA
	MOVWF	RBF
	BCF	E
	NOP
	BSF	E
	MOVFW	PORTA
	MOVWF	RBF1
	BCF	E
	BTFSC	BF 		;je bit BF=0 ? (0 = konec operace)
	GOTO	$-10 		;ne - testuj znova
;----------------------------------------------------------------------------
A_OUT	MOVLW	B'11110000' 	;pin A0/A3 výstup, pin A4 vstup
	GOTO	$+2
A_IN	MOVLW	B'11111111' 	;pin A0/A7 vstup
	BSF	STATUS,RP0 	;banka 1
	MOVWF	TRISA 		;nastavení portu A
	BCF	STATUS,RP0 	;banka 0
	RETURN
;----------------------------------------------------------------------------
t15mS	MOVLW	49 		;doba 15 milisekund
	GOTO	$+2
t4mS	MOVLW	14 		;doba 4 milisekund
	MOVWF	TM1
	MOVLW	255
	MOVWF	TM2
	DECFSZ	TM2,F
	GOTO	$-1
	DECFSZ	TM1,F
	GOTO	$-5
	RETURN
;----------------------------------------------------------------------------
t100uS	MOVLW	83 		;doba 100 mikrosekund
	MOVWF	TM1
	DECFSZ	TM1,F
	GOTO	$-1
	RETURN
;****************************************************************************
t250mS	CLRF	TM2		;doba 250 milisekund
	CLRF	TM1
	NOP
	DECFSZ	TM1,F
	GOTO	$-2
	DECFSZ	TM2,F
	GOTO	$-4
	RETURN
;****************************************************************************
;PROGRAM
;****************************************************************************	
START	BSF	STATUS,RP0 	;banka 1
	MOVLW	B'11110001'
	MOVWF	TRISB 		;nastavení portu B
	BCF	STATUS,RP0 	;banka 0
	
	CALL	INILCD 		;inicializace displeje
	MOVLW	B'00001110'
	CALL	WRPRI		;kurzor ON
	MOVLW	1
	CALL	WRPRI		;reset displeje

	MOVLW	128
	MOVWF	ADRDD		;první adresa kurzoru
;----------------------------------------------------------------------------
KLAVES	MOVFW	ADRDD
	CALL	WRPRI		;zápis kurzoru
	CALL	t250mS		;doba 0,25 sekundy
KLAV	CLRF	POM		;POM=0
	MOVFW	POM
	MOVWF	PORTA		;adresa tlačítka na port A
	BTFSC	Q		;je stisknuto nějaké tlačítko?
	GOTO	SKOK		;ano, proveď skok
	INCF	POM,F		;ne, POM=POM+1
	BTFSS	POM,3		;je POM=8?
	GOTO	$-6		;ne
	GOTO	$-8		;ano
;----------------------------------------------------------------------------

VPRAVO	INCF	ADRDD,F		;adresa kurzoru + 1
	MOVFW	ADRDD
	XORLW	144
	BTFSC	STATUS,Z	;je kurzor mimo pravý okraj displeje?
	DECF	ADRDD,F		;ano, adresa kurzoru - 1
	GOTO	KLAVES		;ne, jdi na KLAVES

VLEVO	DECF	ADRDD,F		;adresa kurzoru - 1
	MOVFW	ADRDD
	XORLW	127
	BTFSC	STATUS,Z	;je kurzor mimo levý okraj displeje?
	INCF	ADRDD,F		;ano, adresa kurzoru + 1
	GOTO	KLAVES		;ne, jdi na KLAVES

NAHORU	MOVFW	ADRDD
	CALL	RDDATA		;přečti znak na adrese displeje
	INCF	NUM,F		;a zvyš je o jednu
	MOVFW	NUM
	XORLW	128
	BTFSC	STATUS,Z	;je DDRAM = 128?
	DECF	NUM,F		;ano, DDRAM - 1
	MOVFW	ADRDD		;ne 
	CALL	WRPRI		;zapiš adresu
	MOVFW	NUM
	CALL	WRDATA		;zapiš znak
	GOTO	KLAVES		;jdi na KLAVES

DOLU	MOVFW	ADRDD
	CALL	RDDATA		;přečti znak na adrese displeje
	DECF	NUM,F		;a sniž je o jednu
	MOVFW	NUM
	XORLW	31
	BTFSC	STATUS,Z	;je DDRAM = 31?
	INCF	NUM,F		;ano, DDRAM + 1
	MOVFW	ADRDD		;ne 
	CALL	WRPRI		;zapiš adresu
	MOVFW	NUM
	CALL	WRDATA		;zapiš znak
	GOTO	KLAVES		;jdi na KLAVES

K_ON	MOVLW	B'00001110'
	CALL	WRPRI		;kurzor ON
	GOTO	KLAVES		;jdi na KLAVES

K_OFF	MOVLW	B'00001100'
	CALL	WRPRI		;kurzor OFF
	GOTO	KLAVES		;jdi na KLAVES

ZAPIS	MOVLW	128
	MOVWF	ADRDD		;registr ADRDD = 128 (počáteční adresa DDRAM)
	CLRF	EEADR		;registr EEADR = 0 (počáteční adresa EEPROM)
ZAP	MOVFW	ADRDD
	CALL	RDDATA		;přečti data z adresy DDRAM
	MOVFW	NUM
	MOVWF	EEDATA		;a zapiš je do registru EEDATA
	BSF	STATUS,RP0	;banka 1
	BSF	EECON1,WREN	;zápis do paměti EEPROM povolen
	MOVLW	H'55'
	MOVWF	EECON2		;zápis bezpečnostního kódu
	MOVLW	H'AA'		;zápis bezpečnostního kódu
	MOVWF	EECON2		
	BSF	EECON1,WR	;zapiš data
	BTFSS	EECON1,EEIF	;je zápis skončen?
	GOTO	$-1		;ne,čekej
	BCF	EECON1,EEIF	;ano,vynuluj testovací bit EEIF
	BCF	EECON1,WREN	;zápis do paměti EEPROM zakázán
	BCF	STATUS,RP0	;banka 0
	INCF	EEADR,F		;zvyš adresu paměti o jednu
	INCF	ADRDD,F		;zvyš adresu ADRDD o jednu
	MOVFW	ADRDD
	XORLW	144
	BTFSS	STATUS,Z	;je adresa ADRDD = 144?
	GOTO	ZAP		;ne,jdi na návěští ZAP
	MOVLW	200		;ano
	CALL	WRPRI		;nastavení adresy DDRAM
	MOVLW	42
	CALL	WRDATA		;tisk "*"
	MOVLW	128		
	MOVWF	ADRDD		;registr ADRDD = 128 (počáteční adresa DDRAM)
	GOTO	KLAVES		;jdi na KLAVES

VYPIS	MOVLW	192
	MOVWF	ADRDD		;adresa dolního řádku do registru ADRDD
	CLRF	EEADR		;registr EEADR = 0 (počáteční adresa EEPROM)
VYP	BSF	STATUS,RP0	;banka 1
	BSF	EECON1,RD	;přečti data
	BCF	STATUS,RP0	;banka 0
	MOVFW	ADRDD
	CALL	WRPRI		;nastavení adresy DDRAM
	MOVFW	EEDATA
	CALL	WRDATA		;tisk přečtených dat
	INCF	EEADR,F		;zvyš adresu paměti o jednu
	INCF	ADRDD,F		;zvyš adresu ADRDD o jednu
	MOVFW	ADRDD
	XORLW	208
	BTFSS	STATUS,Z	;je adresa ADRDD = 208?
	GOTO	VYP		;ne,jdi na návěští VYP
	MOVLW	128		;ano
	MOVWF	ADRDD		;registr ADRDD = 128 (počáteční adresa DDRAM)
	GOTO	KLAVES		;jdi na KLAVES

;****************************************************************************
	ORG	768
SKOK	MOVLW	3
	MOVWF	PCLATH		;nastavení stránky PCLATH
	MOVFW	POM
	ADDWF	PCL,F		;skok dle velikosti POM
	GOTO	K_OFF		;vypnout kurzor
	GOTO	DOLU		;snižování čísla
	GOTO	VPRAVO		;kurzor doprava
	GOTO	NAHORU		;zvyšování čísla
	GOTO	VLEVO		;kurzor doleva
	GOTO	VYPIS		;výpis z paměti EEPROM
	GOTO	ZAPIS		;zápis do paměti EEPROM
	GOTO	K_ON		;zapnout kurzor
;****************************************************************************
	END	
	

