;Program: Servo
	LIST P = 16F84,	R = DEC
	#INCLUDE <P16F84.INC>
;---------------------------------------------------------------

 __CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;***************************************************************
RAM	EQU	H'0C'
;---------------------------------------------------------------
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
TM3	EQU	RAM+7
ADRDD	EQU	RAM+8
POM	EQU	RAM+9
HEX	EQU	RAM+10
MEM_S	EQU	RAM+11
MEM_W	EQU	RAM+12
TMR	EQU	RAM+13
JEDN	EQU	RAM+14
DES	EQU	RAM+15

#define	Q	PORTB,0
#define	RS	PORTB,1	
#define	RW	PORTB,2
#define	E	PORTB,3
#define	BF	RBF,3
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
	ORG	0
	GOTO	START
	ORG	4
;***************************************************************
;PODPROGRAMY
;***************************************************************
INTR	MOVWF	MEM_W		;úschova registru W
	SWAPF	STATUS,W	
	MOVWF	MEM_S		;úschova registru STATUS

	BCF	STATUS,RP0	;banka 0

	MOVFW	HEX
	MOVWF	TMR		;zapiš obsah registru HEX do registru TMR

	BSF	PORTB,7		;pin B7 = 1

	MOVLW	248		;časová smyčka 1 mS
	MOVWF	TM3
	NOP
	DECFSZ	TM3,F
	GOTO	$-2

	INCF	TMR,F		;registr TMR + 1
INT_1	MOVLW	2		;časová smyčka 10 uS
	MOVWF	TM3
	DECFSZ	TM3,F
	GOTO	$-1
	DECFSZ	TMR,F		;je TMR = 0?	
	GOTO	INT_1		;ne,jdi na návěští INT_1

	BCF	PORTB,7		;pin B7 = 0

	MOVLW	110
	MOVWF	TMR0		;nastav TMR0 na 110
	BCF	INTCON,T0IF	;vynulování bitu T0IF

	SWAPF	MEM_S,W
	MOVWF	STATUS		;obnova registru STATUS
	SWAPF	MEM_W,F
	SWAPF	MEM_W,W		;obnova registru W
	RETFIE

;****************************************************************
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
	MOVLW	1
	CALL	WRPRI		;reset displeje
	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	246		;doba 15 milisekund
	GOTO	$+2
t4mS	MOVLW	66		;doba 4 milisekund
	MOVWF	TM1
	MOVLW	19
	MOVWF	TM2
	DECFSZ	TM2,F
	GOTO	$-1
	DECFSZ	TM1,F
	GOTO	$-5
	RETURN
;----------------------------------------------------------------
t100uS	MOVLW	33		;doba 100 mikrosekund
	MOVWF	TM1
	DECFSZ	TM1,F
	GOTO	$-1
	RETURN

;***************************************************************
t500mS	CLRF	TM2		;doba 500 milisekund
	CLRF	TM1
	NOP
	DECFSZ	TM1,F
	GOTO	$-2
	NOP
	DECFSZ	TM1,F
	GOTO	$-2
	DECFSZ	TM2,F
	GOTO	$-7
	RETURN

;***************************************************************
PREV_X	MOVWF	POM		;úschova adresy DDRAM
	CALL	RDDATA		;načtení čísla z adresy DDRAM do NUM
	CLRF	HEX		;vynulování registru HEX
	MOVLW	47
	SUBWF	NUM,F		;registr NUM=NUM-47

	DECF	NUM,F		;registr NUM-1
	BTFSC	STATUS,Z	;je NUM=0?
	GOTO	$+4		;ano,proveď skok
	MOVLW	10		;ne
	ADDWF	HEX,F		;registr HEX=HEX+10
	GOTO	$-5		;a znova dokola

	INCF	POM,W		;uschovaná adresa DDRAM+1
	CALL	RDDATA		;načtení čísla z adresy DDRAM do NUM
	MOVLW	47
	SUBWF	NUM,F		;registr NUM=NUM-47

	DECF	NUM,F		;registr NUM-1
	BTFSC	STATUS,Z	;je NUM=0?
	GOTO	$+3		;ano,proveď skok
	INCF	HEX,F		;ne,registr HEX=HEX-1
	GOTO	$-4		;a znova dokola
	
	MOVFW	HEX		;obsah HEX do W
	RETURN

;***************************************************************
TISK	MOVFW	ADRDD
	CALL	WRPRI
	MOVFW	NUM
	CALL	WRDATA
	RETURN

;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;PROGRAM
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
START	BSF	STATUS,RP0	;banka 1
	MOVLW	B'01110001'
	MOVWF	TRISB		;nastavit port B (B7 výstup)
	MOVLW	B'11000110'
	MOVWF	OPTION_REG	;nastavit OPTION_REG
	BCF	STATUS,RP0	;banka 0

	CALL	INILCD		;proveď inicializaci displeje

	MOVLW	49
	MOVWF	HEX		;registr HEX = 49
	MOVLW	135
	CALL	WRPRI		;nastav adresu DDRAM displeje na 135
	MOVLW	52
	CALL	WRDATA		;tisk "4"
	MOVLW	57
	CALL	WRDATA		;tisk "9"
	MOVLW	B'00001110'
	CALL	WRPRI		;kurzor povolen

	MOVLW	B'10100000'
	MOVWF	INTCON		;přerušení povoleno

	MOVLW	135
	MOVWF	ADRDD		;výchozí adresa DDRAM (135)

KLAVES	MOVFW	ADRDD
	CALL	WRPRI		;nastav adresu DDRAM displeje

	CALL	t500mS		;doba 0,5 sekundy

KLAV	CLRF	POM		;0 do registru POM
	MOVFW	POM
	MOVWF	PORTA		;obsah registru POM na port A
	BTFSC	Q		;je stisknuto příslušné tlačítko?
	GOTO	SKOK		;ano,proveď jdi na návěští SKOK
	INCF	POM,F		;registr POM + 1
	BTFSS	POM,3		;je POM = 8?
	GOTO	$-6		;ne,udělej skok
	GOTO	KLAV		;ano,jdi na KLAV

;**************************************************************
ENTER	MOVLW	135		;adresa DDRAM do registru W
	CALL	PREV_X		;proveď převod
	GOTO	KLAVES		;jdi na návěští KLAVES

DOLU	MOVFW	ADRDD		;adresa DDRAM do registru W
	CALL	RDDATA		;přečti data
	DECF	NUM,F		;registr NUM - 1
	MOVFW	NUM
	XORLW	47
	BTFSC	STATUS,Z	;je NUM = 47?
	INCF	NUM,F		;ano,odečti jednu
	CALL	TISK		;proveď tisk na displej
	GOTO	KLAVES		;jdi na návěští KLAVES

PRAVO	INCF	ADRDD,F		;adresa DDRAM + 1
	MOVFW	ADRDD
	XORLW	137
	BTFSC	STATUS,Z	;je adresa DDRAM = 137?
	DECF	ADRDD,F		;ano,tak odečti jednu
	GOTO	KLAVES		;jdi na návěští KLAVES

NAHR	MOVFW	ADRDD		;adresa DDRAM do registru W
	CALL	RDDATA		;přečti data
	INCF	NUM,F		;registr NUM + 1
	MOVFW	NUM
	XORLW	58
	BTFSC	STATUS,Z	;je NUM = 58?
	DECF	NUM,F		;ano,odečti jednu
	CALL	TISK		;proveď tisk na displej
	GOTO	KLAVES		;jdi na návěští KLAVES

VLEVO	DECF	ADRDD,F		;adresa DDRAM - 1
	MOVFW	ADRDD
	XORLW	134
	BTFSC	STATUS,Z	;je adresa DDRAM = 134?
	INCF	ADRDD,F		;ano,tak přičti jednu
	GOTO	KLAVES		;jdi na návěští KLAVES

;**************************************************************
	ORG	768		;nastavení adresy programové paměti
SKOK	MOVLW	3
	MOVWF	PCLATH		;nastavení stránky PCLATH
	MOVFW	POM
	ADDWF	PCL,F		;skok podle velikosti POM
	GOTO	ENTER		;jdi na návěští ENTER
	GOTO	DOLU		;jdi na návěští DOLU
	GOTO	PRAVO		;jdi na návěští PRAVO
	GOTO	NAHR		;jdi na návěští NAHR
	GOTO	VLEVO		;jdi na návěští VLEVO
	GOTO	KLAV		;jdi na návěští KLAV
	GOTO	KLAV		;jdi na návěští KLAV
	GOTO	KLAV		;jdi na návěští KLAV

	END
