;Program: Regulátor
;***************************************************************
	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+14
POM	EQU	RAM+3
TMP	EQU	RAM+4
TM0	EQU	RAM+5
TM1	EQU	RAM+6
TM2	EQU	RAM+7
JEDN	EQU	RAM+8
DES	EQU	RAM+9
STA	EQU	RAM+10
MEM_W	EQU	RAM+11
MEM_S	EQU	RAM+12
TMR	EQU	RAM+13

#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
;***************************************************************
;PODPROGRAMY
;***************************************************************
	ORG	4		;adresa začátku přerušení
INTR	MOVWF	MEM_W		;úschova registru W
	SWAPF	STATUS,W	
	MOVWF	MEM_S		;úschova registru STATUS

	BCF	STATUS,RP0	;banka 0
	BCF	INTCON,T0IF	;vynulování bitu T0IF

	MOVFW	TMR
	XORLW	255
	BTFSS	STATUS,Z	;je obsah registru TMR=255?
	GOTO	INT_4		;ne,proveď skok na návěští INT_4
	BSF	PORTB,7		;ano,nastav pin B7=1
	GOTO	INT_2		;jdi na návěští INT_2
	
INT_4	MOVF	TMR,F
	BTFSS	STATUS,Z	;je obsah registru TMR=0?
	GOTO	INT_3		;ne,proveď skok na návěští INT_3
	BCF	PORTB,7		;ano,nastav pin B7=0
	GOTO	INT_2		;jdi na návěští INT_2
		
INT_3	BTFSC	POM,0		;je obsah registru POM=1?
	GOTO	INT_1		;ano,proveď skok na návěští INT_1

	MOVLW	1
	MOVWF	POM		;ne,tak nastav POM=1
	BSF	PORTB,7		;nastav pin B7=1
	COMF	TMR,W
	MOVWF	TMR0		;zapiš negaci registru TMR do registru TMR0
	GOTO	INT_2		;jdi na návěští INT_2

INT_1	CLRF	POM		;nastav POM=0
	BCF	PORTB,7		;nastav pin B7=0
	MOVFW	TMR
	MOVWF	TMR0		;obsah registru TMR do registru TMR0

INT_2	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
;----------------------------------------------------------------

t100mS	MOVLW	160		;doba 100 milisekund
	MOVWF	TM1
	MOVLW	207
	MOVWF	TM2
	DECFSZ	TM2,F
	GOTO	$-1
	DECFSZ	TM1,F
	GOTO	$-5
	RETURN
;****************************************************************

PREVOD	MOVLW	48
	MOVWF	JEDN		;registr JEDN=48
	MOVWF	DES		;registr DES=48
	MOVWF	STA		;registr STA=48
	MOVLW	100
	SUBWF	NUM,W		;registr W=NUM-100
	BTFSS	STATUS,C	;došlo k podtečení?
	GOTO	$+4		;ano,udělej skok
	MOVWF	NUM		;obsah W do NUM
	INCF	STA,F		;registr STA + 1
	GOTO	$-6		;odečítej znova 
	MOVLW	10
	SUBWF	NUM,W		;registr W=NUM-10
	BTFSS	STATUS,C	;došlo k podtečení?
	GOTO	$+4		;ano,udělej skok
	MOVWF	NUM		;obsah W do NUM
	INCF	DES,F		;registr DES + 1
	GOTO	$-6		;odečítej znova 
	MOVFW	NUM
	ADDWF	JEDN,F		;zbytek přičíst do registru JEDN
	RETURN
;******************************************************************

ZOBR	MOVLW	128
	CALL	WRPRI		;nastavení paměti DDRAM
	MOVFW	STA
	CALL	WRDATA		;tisk stovek
	MOVFW	DES
	CALL	WRDATA		;tisk desítek
	MOVFW	JEDN
	CALL	WRDATA		;tisk jednotek
	RETURN

;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;PROGRAM
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

START	BSF	STATUS,RP0	;banka 1
	MOVLW	B'01110001'
	MOVWF	TRISB		;nastavení portu B (B7 jako výstup)
	MOVLW	B'11000000'
	MOVWF	OPTION_REG	;zdroj signálu pro TMR0 fosc/4, dělící poměr 1:2
	BCF	STATUS,RP0	;banka 0

	CALL	INILCD		;inicializace displeje

	CLRF	POM		;vynulování registru POM
	CLRF	TMR		;vynulování registru TMR
	CLRF	NUM		;vynulování registru NUM

	CALL	PREVOD		;převod obsahu registru TMR na dekadické
	CALL	ZOBR		;zobrazení převodu (v tomto případě to bude 000)

	CLRF	TMR0		;vynulování registru TMR0
	MOVLW	B'10100000'
	MOVWF	INTCON		;povolit přerušení od přetečení registru TMR0

PROG	MOVLW	3
	MOVWF	PORTA
	BTFSS	Q		;je stisknuto tlačítko TL4?
	GOTO	PROG_1		;ne,proveď skok na návěští PROG_1
	MOVFW	TMR
	XORLW	255
	BTFSC	STATUS,Z	;je obsah registru TMR=255?
	GOTO	PROG		;ano,proveď skok na návěští PROG
	INCF	TMR,F		;zvyš obsah registru TMR o jednu

	GOTO	PROG_2		;proveď skok na návěští PROG_2

PROG_1	MOVLW	2
	MOVWF	PORTA
	BTFSS	Q		;je stisknuto tlačítko TL3?
	GOTO	PROG		;ne,proveď skok na návěští PROG
	MOVF	TMR,F
	BTFSC	STATUS,Z	;je obsah registru TMR=0?
	GOTO	PROG		;ano,proveď skok na návěští PROG
	DECF	TMR,F		;sniž obsah registru TMR o jednu

PROG_2	MOVFW	TMR
	MOVWF	NUM		;obsah registru TMR do registru NUM
	CALL	PREVOD		;převod obsahu registru TMR na dekadické
	CALL	ZOBR		;zobrazení převodu
	CALL	t100mS		;doba 100 milisekund
	GOTO	PROG		;proveď skok na návěští PROG

	END
