;**************************************************************************
; CYCLOMET.ASM					(c) Ing. Miroslav Němeček
;--------------------------------------------------------------------------
; Zařízení slouží k měření informací sportovního zařízení nebo byciklu.
; Měření probíhá pomocí snímacího čidla (spínací kontakt), spínající
; po určité vzdálenosti dráhy (vzdálenost určuje v programu konstanta LENINC).
;
; Zobrazují se tyto údaje: uběhlý čas, urazená vzdálenost, aktuální rychlost,
; celková urazená vzdálenost. Mód zobrazení se přepíná stiskem tlačítka.
;
; Před zobrazením údaje se vypíše text názvu údaje:
;	"tIM" ... čas (time) ve formátu MM.SS nebo HH.MM - měří při nenulové rychlosti
;	"diS" ... vzdálenost (distance) ve formátu kk.kk nebo kkk.k (v kilometrech)
;	"SPE" ... rychlost (speed) ve formátu sss.s (v kilometrech za hodinu)
;	"odo" ... celková vzdálenost (odometer) ve formátu kkkk (v kilometrech)
;	"Aut" ... automatická změna zobrazení (po 4 sekundách)
;
; Podržením tlačítka po dobu 2 sekund se ukazatele vynulují (kromě celkové
; vzdálenosti). Celkovou vzdálenost lze nulovat odpojením napájecího zdroje.
; Po 30 sekundové neaktivitě se měřič vypne. Tlačítkem nebo senzorem lze
; opět aktivovat.
;
; Měřič lze napájet 2 tužkovými monočlánky. Pro minimalizaci spotřeby proudu
; je použit krystal 32 kHz. Překreslování displeje probíhá proto pomaleji,
; než je běžné (s kmitočtem 16 Hz), displej může při bočním pohledu blikat.
; Paralelně k senzoru (na vstupu ze senzoru) je připojen kondenzátor o kapacitě
; přibližně 22 nF, který zajišťuje prodloužení příliš krátkých impulsů z čidla
; a vyhlazení zakmitávání kontaktů čidla. Kapacita kondenzátoru závisí na
; použitém senzoru a na jeho spínací době. Příliš velká kapacita kondenzátoru
; se projeví výpadky měření při velkých rychlostech (počitadlo se zastavuje).
; Příliš nízká kapacita se projeví nepravidelností údaje a nepravidelným nárustem
; rychlosti při nízkých rychlostech.
;**************************************************************************

	RADIX	DEC
	CONFIG	LP

; Označení segmentů displeje:
;
;		 -- A3 -	 -- A2 -	 -- A1 -
;	|	|	|	|	|	|	|
;	|	F3	B3	F2	B2	F1	B1
;	|	|	|	|	|	|	|
;	H3	 -- G3 -	 -- G2 -	 -- G1 -
;	|	|	|	|	|	|	|
;	|	E3	C3	E2	C2	E1	C1
;	|	|	|	|	|	|	|
;    		 -- D3 -   H2 	 -- D2 -    H1	 -- D1 -
;
; Bity portů:
;	A0 ... C3, F2/REG1, H2/REG2
;	A1 ... A3, G3/REG1, H3/REG2
;	A2 ... zápis do registru REG1 (hodnotou "1")
;	A3 ... zápis do registru REG2 (hodnotou "1")
;	A4 ... společná elektroda ("1" = inverze)
;
;	B0 ... F1, A1/REG1, D1/REG2
;	B1 ... G1, A2/REG1, C2/REG2
;	B2 ... H1, B2/REG1, D2/REG2
;	B3 ... E1, B1/REG1, C1/REG2
;	B4 ... vstup z tlačítka ("1" = stisknuto)
;	B5 ... vstup ze senzoru ("1" = sepnuto)
;	B6 ... B3, G2/REG1, E2/REG2
;	B7 ... D3, F3/REG1, E3/REG2

; ----- konstanty

; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
LENINC	EQU	20	; přírustek vzdálenosti na impuls (cm)
			; - tato konstanta závisí na zařízení
; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

QUITMAX	EQU	30	; čítač pro uklidnění (sekund)
VELTIME	EQU	115	; čítač pro měření rychlosti (=3.6 sekundy)
CSTATE	EQU	4*32	; čítač automatického přepínání (=4 sekundy)
CIND	EQU	24	; čítač doby indikace změny stavu (zlomky sekund)

;--------------------------------------------------------------------------
;	proměnné
;--------------------------------------------------------------------------

	CBLOCK

; ----- výstupní registry

Reg0			; výstupní registr 0 (bez mezizápisu)
			;	bit0 ... F1
			;	bit1 ... G1
			;	bit2 ... H1
			;	bit3 ... E1
			;	bit4 ... C3
			;	bit5 ... A3
			;	bit6 ... B3
			;	bit7 ... D3

Reg1			; výstupní registr 1
			;	bit0 ... A1
			;	bit1 ... A2
			;	bit2 ... B2
			;	bit3 ... B1
			;	bit4 ... F2
			;	bit5 ... G3
			;	bit6 ... G2
			;	bit7 ... F3

Reg2			; výstupní registr 2
			;	bit0 ... D1
			;	bit1 ... C2
			;	bit2 ... D2
			;	bit3 ... C1
			;	bit4 ... H2
			;	bit5 ... H3
			;	bit6 ... E2
			;	bit7 ... E3

DByte			; bajt k dekódování nebo k odeslání na displej

TByte			; pomocný střadač k zobrazení
TByte2			; pomocný střadač k zobrazení 2

; ----- ovládání

Flags			; příznaky
			;	bit 0: 1=inverze výstupu
			;	bit 1: 1=tlačítko stisknuto
			;	bit 2: 1=senzor sepnut
			;	bit 3: 1=dlouhé stisknutí tlačítka
			;	bit 4: 1=automatická změna stavu
			;	bit 5: 1=čas běží
			;	bit 6: 1=zobrazena indikace stavu
			;	bit 7: 1=zobrazena indikace Aut

RelKey			; čítač uvolnění tlačítka
LongKey			; čítač dlouhého stisknutí tlačítka

State			; aktuální stav (0 až 3) (viz tabulka stavů níže)
CState			; čítač pro automatickou změnu stavu
CInd			; čítač indikace nového stavu

Quit			; čítač pro klid (sekund)

HlasN			; uschované číslo hlášení (při zobrazení hlášení)

; ----- uběhlý čas

Hundr			; 1/32 sekundy
Second			; uběhlé sekundy
Minute			; uběhlé minuty
Hour			; uběhlé hodiny

; ----- urazená vzdálenost

LenCM			; urazená vzdálenost (centimetry, 0 až 99)
LenM			; urazená vzdálenost (metry, 0 až 9)
LenDM			; urazená vzdálenost (dekametry, 0 až 9)
LenHM			; urazená vzdálenost (hektometry, 0 až 9)
LenKM			; urazená vzdálenost (kilometry, 0 až 199)

; ----- celková urazená vzdálenost

SLenDM			; celková urazená vzdálenost (dekametry, 0 až 99)
SLenKM			; celková urazená vzdálenost (kilometry, 0 až 9)
SLenHM			; celková urazená vzdálenost (desítky kilometrů, 0 až 199)

; ----- rychlost (čítání metrů po 3.6 sekundy odpovídá rychlosti v km/hod)

VelTim			; čítač měřící doby pro rychlost
CVelCM			; čítač rychlosti v cm (0 až 99)
CVelM			; čítač rychlosti v m (0 až 199)

VelHM			; rychlost v hektometrech (0 až 9)
VelKM			; rychlost v kilometrech (0 až 199)

; ----- úschova registrů při přerušení

TempW			; úschova registru W při přerušení
TempS			; úschova registru STATUS při přerušení
	ENDC

; ----- symboly stavů

STIME	EQU	0	; zobrazení uběhlého času
SLENGTH	EQU	1	; zobrazení urazené vzdálenosti
SSPEED	EQU	2	; zobrazení rychlosti
SSLEN	EQU	3	; zobrazení celkové urazené vzdálenosti

SAUT	EQU	4	; automatické zobrazení (konstanta určena jen pro obsluhu indikace)

;--------------------------------------------------------------------------
;	vektory
;--------------------------------------------------------------------------

	ORG	0
	goto	Start		; skok na start programu

	ORG	4
	goto	Inter		; skok na obsluhu přerušení

;--------------------------------------------------------------------------
;	tabulky
;--------------------------------------------------------------------------

; ----- tabulka číslic
; Bitová mapa segmentů číslice:
;
;	 -- 0 --
;	|	|
;	5	1
;	|	|
;	 -- 6 --
;	|	|
;	4	2
;	|	|
;	 -- 3 --

ChrTab	addwf	PCL,F
	dt	00111111b	; 0
	dt	00000110b	; 1
	dt	01011011b	; 2
	dt	01001111b	; 3
	dt	01100110b	; 4
	dt	01101101b	; 5
	dt	01111101b	; 6
	dt	00000111b	; 7
	dt	01111111b	; 8
	dt	01101111b	; 9
	dt	01110111b	; 10: A
	dt	00011100b	; 11: u
	dt	01111000b	; 12: t
	dt	01011110b	; 13: d
	dt	01011100b	; 14: o
	dt	01110011b	; 15: P
	dt	00110111b	; 16: M
	dt	01111001b	; 17: E

ACHAR	EQU	10		; A
UCHAR	EQU	11		; u
TCHAR	EQU	12		; t (time)
DCHAR	EQU	13		; d (distance)
OCHAR	EQU	14		; o (odometer)
SCHAR	EQU	5		; S (speed)
PCHAR	EQU	15		; P
MCHAR	EQU	16		; M
ECHAR	EQU	17		; E
ICHAR	EQU	1		; I

; ----- obsluha zobrazení podle stavu

StatTab	addwf	PCL,F
	goto	DspTim		; zobrazení uběhlého času
	goto	DspDis		; zobrazení urazené vzdálenosti
	goto	DspSpe		; zobrazení rychlosti
	goto	DspOdo		; zobrazení celkové vzdálenosti

; ----- texty pro indikaci stavu

HlasT1	addwf	PCL,F
	dt	TCHAR		; čas 't'
	dt	DCHAR		; vzdálenosti 'd'
	dt	SCHAR		; rychlost 'S'
	dt	OCHAR		; celková vzdálenost 'o'
	dt	ACHAR		; automatika 'A'

HlasT2	addwf	PCL,F
	dt	ICHAR		; čas 'I'
	dt	ICHAR		; vzdálenosti 'I'
	dt	PCHAR		; rychlost 'P'
	dt	DCHAR		; celková vzdálenost 'd'
	dt	UCHAR		; automatika 'u'


HlasT3	addwf	PCL,F
	dt	MCHAR		; čas 'M'
	dt	SCHAR		; vzdálenosti 'S'
	dt	ECHAR		; rychlost 'E'
	dt	OCHAR		; celková vzdálenost 'o'
	dt	TCHAR		; automatika 't'

;--------------------------------------------------------------------------
;	start programu
;--------------------------------------------------------------------------

; ----- nastavení směru bitů portŮ

Start	bsf	STATUS,RP0	; zapnutí bitu RP0 (bit 5) registru STATUS (číslo 3)

	movlw	00000b		; volba směru bitů: 0=výstup, 1=vstup
	movwf	TRISA		; nastavení bitů portu A (registr TRISA)
	movlw	00110000b	; volba směru bitů: 0=výstup, 1=vstup
	movwf	TRISB		; nastavení bitů portu B (registr TRISB)

; ----- nastavení časovače Timer0
; Obsluha přerušení se vyvolává 32x za sekundu, kmitočet pro LCD
; je tedy 16 Hz. Pro krystal 32768 Hz je taktovací frekvence 8192 Hz,
; požadovaný dělicí poměr je 256, předdělička bude odpojena.

	movlw	0 + bit3 + bit7	; dělička odpojena, připojena k WDT, bez pull-up
	movwf	OPTION_REG	; nastavení OPTION registru časovačů
	bcf	STATUS,RP0	; zapnutí banky 0

; ----- inicializace příznaků a proměnných

	clrf	Reg0		; nulování registru 0
	clrf	Reg1		; nulování registru 1
	clrf	Reg2		; nulování registru 2

	clrf	Flags		; inicializace příznaků
	clrf	RelKey		; nulování čítače uvolnění tlačítka
	clrf	LongKey		; nulování čítače dlouhého stisku

	call	Clear		; nulování registrů

	clrf	SLenDM		; celková vzdálenost v Dm
	clrf	SLenKM		; celková vzdálenost v km
	clrf	SLenHM		; celková vzdálenost v desítkách kilometrů

; ----- inicializace obsluhy přerušení

Loop	movlw	bit3 + bit5 + bit7 ; povoleno přerušení od TMR0, RB4-RB7 a globální přerušení
	movwf	INTCON		; nastavení registru přerušení INTCON

; ----- inicializace čítače pro klid

	movlw	QUITMAX		; konstanta pro uklidnění
	movwf	Quit		; nastavení čítače pro klid

; ----- dosažení stavu klidu
	
Loop2	movf	Quit,F		; test, zda je stav klidu
	btfss	STATUS,Z	; dosažen stav klidu?
	goto	Loop3		; není stav klidu

	movlw	bit3		; povoleno vzbuzení RB4-RB7, zákaz přerušení
	movwf	INTCON		; nastavení registru přerušení INTCON

	clrf	PORTB		; vynulování výstupu na port B
	clrf	PORTA		; vynulování výstupu na port A
	bsf	PORTA,2		; vynulování registru 1
	bcf	PORTA,2
	bsf	PORTA,3		; vynulování registru 2
	bcf	PORTA,3

	SLEEP			; klid

	movlw	64		; interval dlouhého sisku tlačítka (2 sekundy)
	movwf	LongKey		; čítač dlouhého stisku tlačítka
	movlw	2		; nová hodnota čítače uvolnění (60 ms)
	movwf	RelKey		; inicializace čítače uvolnění

	goto	Loop		; nová inicializace čítače klidu

Loop3	goto	Loop2

;--------------------------------------------------------------------------
;	vymazání registrů
;--------------------------------------------------------------------------

Clear	clrf	Hundr		; nulování setin sekundy
	clrf	Second		; nulování sekund
	clrf	Minute		; nulování minut
	clrf	Hour		; nulování hodin 24 hodin

	clrf	LenCM		; nulování vzdálenosti v cm
	clrf	LenM		; nulování vzdálenosti v m
	clrf	LenDM		; nulování vzdálenosti v dm
	clrf	LenHM		; nulování vzdálenosti v hm
	clrf	LenKM		; nulování vzdálenosti v km

	movlw	CSTATE		; čítač automatické změny stavu
	movwf	CState		; inicializace čítače automatické změny

	clrf	State		; inicializace stavu
	bsf	Flags,4		; zapnutí automatiky

	movlw	VELTIME		; konstanta čítače doby rychlosti
	movwf	VelTim		; čítač měřící doby rychlosti
	clrf	CVelCM		; čítač rychlosti v cm
	clrf	CVelM		; čítač rychlosti v m
	clrf	VelHM		; rychlost v hektometrech
	clrf	VelKM		; rychlost v kilometrech
	return

;--------------------------------------------------------------------------
;	zobrazení čísla W jako poslední 2 číslice (0 až 99)
;--------------------------------------------------------------------------

; ----- úschova bajtu k zobrazení

DispN1	movwf	TByte		; úschova bajtu k zobrazení
	clrf	TByte2		; nulování střadače

; ----- test bitu 3 číslice

	movlw	80
	subwf	TByte,W		; test čísla 80
	btfss	STATUS,C	; je číslo 80 a více?
	goto	DispN12		; není číslo 80 a více
	movwf	TByte		; zkorigovaná hodnota
	bsf	TByte2,3	; nastavení bitu 3

; ----- test bitu 2 číslice

DispN12	movlw	40
	subwf	TByte,W		; test čísla 40
	btfss	STATUS,C	; je číslo 40 a více?
	goto	DispN13		; není číslo 40 a více
	movwf	TByte		; zkorigovaná hodnota
	bsf	TByte2,2	; nastavení bitu 2

; ----- test bitu 1 číslice

DispN13	movlw	20
	subwf	TByte,W		; test čísla 20
	btfss	STATUS,C	; je číslo 20 a více?
	goto	DispN14		; není číslo 20 a více
	movwf	TByte		; zkorigovaná hodnota
	bsf	TByte2,1	; nastavení bitu 1

; ----- test bitu 0 číslice

DispN14	movlw	10
	subwf	TByte,W		; test čísla 10
	btfss	STATUS,C	; je číslo 10 a více?
	goto	DispN15		; není číslo 10 a více
	movwf	TByte		; zkorigovaná hodnota
	bsf	TByte2,0	; nastavení bitu 0

; ----- zobrazení vyššího čísla

DispN15	movf	TByte2,W	; načtení vyššího čísla
	call	DekNum2		; zobrazení vyššího čísla

; ----- zobrazení nižšího čísla

	movf	TByte,W		; načtení nižšího čísla
	call	DekNum1		; zobrazení nižšího čísla
	return

;--------------------------------------------------------------------------
;	zobrazení čísla W jako první 2 číslice (0 až 19)
;--------------------------------------------------------------------------

; ----- úschova bajtu k zobrazení

DispN2	movwf	TByte		; úschova bajtu k zobrazení
	clrf	TByte2		; nulování střadače

; ----- test bitu 0 číslice

	movlw	10
	subwf	TByte,W		; test čísla 10
	btfss	STATUS,C	; je číslo 10 a více?
	goto	DispN25		; není číslo 10 a více
	movwf	TByte		; zkorigovaná hodnota
	bsf	TByte2,0	; nastavení bitu 0

; ----- zobrazení vyššího čísla

DispN25	movf	TByte2,W	; načtení vyššího čísla
	call	DekNum4		; zobrazení vyššího čísla

; ----- zobrazení nižšího čísla

	movf	TByte,W		; načtení nižšího čísla
	call	DekNum3		; zobrazení nižšího čísla
	return

;--------------------------------------------------------------------------
;	zobrazení čísla W jako poslední 3 číslice (0 až 199)
;--------------------------------------------------------------------------

; ----- úschova bajtu k zobrazení

DispN3	movwf	TByte		; úschova bajtu k zobrazení

; ----- zobrazení čísla < 10 (kvůli potlačení úvodních nul)

	movlw	10		; bude se testovat 10 a více
	subwf	TByte,W		; test čísla 10 a větší
	btfsc	STATUS,C	; je číslo 10 a větší?
	goto	DispN30		; není číslo 10 a větší

	call	DekNm40		; vypnutí nejvyšší číslice "1"
	clrw			; W <- 0
	call	DekNm30		; vymazání čísla 3
	goto	DispN36		; dekódování nejnižšího čísla

; ----- test bitu 0 nejvyšší číslice

DispN30	clrf	TByte2		; nulování střadače
	movlw	100
	subwf	TByte,W		; test čísla 100
	btfss	STATUS,C	; je číslo 100 a více?
	goto	DispN31		; není číslo 100 a více
	movwf	TByte		; zkorigovaná hodnota
	bsf	TByte2,0	; nastavení bitu 0

; ----- zobrazení nejvyššího čísla

DispN31	movf	TByte2,W	; načtení nejvyššího čísla
	call	DekNum4		; zobrazení nejvyššího čísla

; ----- test bitu 3 číslice

	movlw	80
	subwf	TByte,W		; test čísla 80
	btfss	STATUS,C	; je číslo 80 a více?
	goto	DispN32		; není číslo 80 a více
	movwf	TByte		; zkorigovaná hodnota
	bsf	TByte2,3	; nastavení bitu 3

; ----- test bitu 2 číslice

DispN32	movlw	40
	subwf	TByte,W		; test čísla 40
	btfss	STATUS,C	; je číslo 40 a více?
	goto	DispN33		; není číslo 40 a více
	movwf	TByte		; zkorigovaná hodnota
	bsf	TByte2,2	; nastavení bitu 2

; ----- test bitu 1 číslice

DispN33	movlw	20
	subwf	TByte,W		; test čísla 20
	btfss	STATUS,C	; je číslo 20 a více?
	goto	DispN34		; není číslo 20 a více
	movwf	TByte		; zkorigovaná hodnota
	bsf	TByte2,1	; nastavení bitu 1

; ----- test bitu 0 číslice

DispN34	movlw	10
	subwf	TByte,W		; test čísla 10
	btfss	STATUS,C	; je číslo 10 a více?
	goto	DispN35		; není číslo 10 a více
	movwf	TByte		; zkorigovaná hodnota
	bsf	TByte2,0	; nastavení bitu 0

; ----- zobrazení vyššího čísla

DispN35	movf	TByte2,W	; načtení vyššího čísla
	call	DekNum3		; zobrazení vyššího čísla

; ----- zobrazení nižšího čísla

DispN36	movf	TByte,W		; načtení nižšího čísla
	call	DekNum2		; zobrazení nižšího čísla
	return

;--------------------------------------------------------------------------
;	dekódování číslice 1 (W=0 až 9)
;--------------------------------------------------------------------------

; ----- uložení bajtu k dekódování

DekNum1	call	ChrTab		; dekódování na segmenty
	movwf	DByte		; úschova bajtu k dekódování

; ----- segment A

	bcf	Reg1,0
	btfsc	DByte,0
	bsf	Reg1,0
	
; ----- segment B

	bcf	Reg1,3
	btfsc	DByte,1
	bsf	Reg1,3

; ----- segment C

	bcf	Reg2,3
	btfsc	DByte,2
	bsf	Reg2,3

; ----- segment D

	bcf	Reg2,0
	btfsc	DByte,3
	bsf	Reg2,0

; ----- segment E

	bcf	Reg0,3
	btfsc	DByte,4
	bsf	Reg0,3

; ----- segment F

	bcf	Reg0,0
	btfsc	DByte,5
	bsf	Reg0,0

; ----- segment G

	bcf	Reg0,1
	btfsc	DByte,6
	bsf	Reg0,1
	return

;--------------------------------------------------------------------------
;	dekódování číslice 2 (W=0 až 9)
;--------------------------------------------------------------------------

; ----- uložení bajtu k dekódování

DekNum2	call	ChrTab		; dekódování na segmenty
	movwf	DByte		; úschova bajtu k dekódování

; ----- segment A

	bcf	Reg1,1
	btfsc	DByte,0
	bsf	Reg1,1
	
; ----- segment B

	bcf	Reg1,2
	btfsc	DByte,1
	bsf	Reg1,2

; ----- segment C

	bcf	Reg2,1
	btfsc	DByte,2
	bsf	Reg2,1

; ----- segment D

	bcf	Reg2,2
	btfsc	DByte,3
	bsf	Reg2,2

; ----- segment E

	bcf	Reg2,6
	btfsc	DByte,4
	bsf	Reg2,6

; ----- segment F

	bcf	Reg1,4
	btfsc	DByte,5
	bsf	Reg1,4

; ----- segment G

	bcf	Reg1,6
	btfsc	DByte,6
	bsf	Reg1,6
	return

;--------------------------------------------------------------------------
;	dekódování číslice 3 (W=0 až 9)
;--------------------------------------------------------------------------

; ----- uložení bajtu k dekódování

DekNum3	call	ChrTab		; dekódování na segmenty
DekNm30	movwf	DByte		; úschova bajtu k dekódování

; ----- segment A

	bcf	Reg0,5
	btfsc	DByte,0
	bsf	Reg0,5
	
; ----- segment B

	bcf	Reg0,6
	btfsc	DByte,1
	bsf	Reg0,6

; ----- segment C

	bcf	Reg0,4
	btfsc	DByte,2
	bsf	Reg0,4

; ----- segment D

	bcf	Reg0,7
	btfsc	DByte,3
	bsf	Reg0,7

; ----- segment E

	bcf	Reg2,7
	btfsc	DByte,4
	bsf	Reg2,7

; ----- segment F

	bcf	Reg1,7
	btfsc	DByte,5
	bsf	Reg1,7

; ----- segment G

	bcf	Reg1,5
	btfsc	DByte,6
	bsf	Reg1,5
	return

;--------------------------------------------------------------------------
;	dekódování číslice 4 (W=0 až 1)
;--------------------------------------------------------------------------

; ----- dekódování číslice

DekNum4	bsf	Reg2,5		; zapnutí číslice "1"
	iorlw	0		; test, zda je číslo 0
	btfsc	STATUS,Z	; je číslo 0?
DekNm40	bcf	Reg2,5		; vypnutí číslice "1"
	return

;--------------------------------------------------------------------------
;	vypnutí desetinné tečky
;--------------------------------------------------------------------------

SetPT0	bcf	Reg0,2
	bcf	Reg2,4
	return

;--------------------------------------------------------------------------
;	zobrazení desetinné tečky na pozici 1
;--------------------------------------------------------------------------

SetPT1	bsf	Reg0,2
	bcf	Reg2,4
	return

;--------------------------------------------------------------------------
;	zobrazení desetinné tečky na pozici 2
;--------------------------------------------------------------------------

SetPT2	bcf	Reg0,2
	bsf	Reg2,4
	return

;--------------------------------------------------------------------------
;	nulování výstupních registrů (zachovává registr W)
;--------------------------------------------------------------------------

NulReg	clrf	Reg0		; nulování registru 0
	clrf	Reg1		; nulování registru 1
	clrf	Reg2		; nulování registru 2
	return

;--------------------------------------------------------------------------
;	indikace stavu W (nebo aktuálního stavu Indik0)
;--------------------------------------------------------------------------

; ----- použije se aktuální stav

Indik0	movf	State,W		; načtení aktuálního stavu

; ----- vynulování výstupních registrů

Indik	call	NulReg		; vynulování výstupních registrů

; ----- dekódování levého znaku

	movwf	HlasN		; úschova čísla hlášení
	call	HlasT1		; načtení prvního znaku
	call	DekNum3		; dekódování prvního znaku

; ----- dekódování středního znaku

	movf	HlasN,W		; načtení čísla hlášení
	call	HlasT2		; načtení druhého znaku
	call	DekNum2		; dekódování druhého znaku

; ----- dekódování pravého znaku

	movf	HlasN,W		; načtení čísla hlášení
	call	HlasT3		; načtení třetího znaku
	call	DekNum1		; dekódování prvního znaku

; ----- zapnutí příznaku zobrazení indikace

	bsf	Flags,6		; zapnutí příznaku indikace

; ----- nastavení čítače doby indikace

	movlw	CIND		; doba indikace
	movwf	CInd		; nastavení čítače indikace
	return

;--------------------------------------------------------------------------
;	zobrazení uběhlého času
;--------------------------------------------------------------------------

; ----- zobrazení desetinné tečky

DspTim	call	SetPT0		; vypnutí desetinné tečky
	btfsc	Flags,5		; běží čas? (pokud ne, tečka svítí vždy)
	btfss	Hundr,4		; je druhá polovina sekundy?
	call	SetPT2		; zobrazení desetinné tečky

; ----- rozlišení formátu zobrazení času

	movf	Hour,F		; test, zda jsou nějaké hodiny
	btfss	STATUS,Z	; jsou nějaké hodiny?
	goto	DspTim2		; jsou hodiny
	movlw	20		; maximálně minut
	subwf	Minute,W	; test přetečení minut
	btfsc	STATUS,C	; je přetečení minut?
	goto	DspTim2		; zobrazení pro 20 a více minut

; ----- zobrazen čas MM.SS

	movf	Second,W	; načtení sekund
	call	DispN1		; zobrazení sekund jako pravé číslo
	movf	Minute,W	; načtení minut
	goto	DspTim3		; zobrazení minut

; ----- zobrazen čas HH.MM

DspTim2	movf	Minute,W	; načtení minut
	call	DispN1		; zobrazení minut jako pravé číslo
	movf	Hour,W		; načtení hodin
DspTim3	call	DispN2		; zobrazení levého čísla
	return

;--------------------------------------------------------------------------
;	zobrazení urazené vzdálenosti
;--------------------------------------------------------------------------

; ----- rozlišení módu zobrazení

DspDis	movlw	20		; maximální vzdálenost v km
	subwf	LenKM,W		; test přetečení vzdálenosti
	btfss	STATUS,C	; je přetečení vzdálenosti?
	goto	DspDis2		; není přetečení - zobrazení v módu kk.kk

; ----- zobrazení v módu kkk.k

	movf	LenHM,W		; vzdálenost ve stovkách m
	call	DekNum1		; dekódování poslední číslice
	movf	LenKM,W		; vzdálenost v km
	call	DispN3		; dekódování jednotek km

	call	SetPT1		; zobrazení desetinné tečky
	return

; ----- zobrazení v módu kk.kk

DspDis2	movf	LenDM,W		; vzdálenost v desítkách m
	call	DekNum1		; dekódování poslední číslice
	movf	LenHM,W		; vzdálenost ve stovkách m
	call	DekNum2		; dekódování předposlední číslice
	movf	LenKM,W		; vzdálenost v km
	call	DispN2		; dekódování jednotek km

	call	SetPT2		; zobrazení desetinné tečky
	return

;--------------------------------------------------------------------------
;	zobrazení rychlosti
;--------------------------------------------------------------------------

DspSpe	movf	VelHM,W		; nižší číslice rychlosti
	call	DekNum1		; dekódování poslední číslice

	call	SetPT1		; zobrazení desetinné tečky

	movf	VelKM,W		; vyšší číslo
	call	DispN3		; zobrazení desítek km
	return

;--------------------------------------------------------------------------
;	zobrazení celkové vzdálenosti (výstupní registry musí být vynulovány)
;--------------------------------------------------------------------------

DspOdo	movf	SLenKM,W	; celková vzdálenost v km
	call	DekNum1		; dekódování poslední číslice

	movf	SLenHM,W	; celková vzdálenost v desítkách km
	btfss	STATUS,Z	; jsou desítky km = 0?
	call	DispN3		; zobrazení desítek km
	return

;--------------------------------------------------------------------------
;	obsluha přerušení
;--------------------------------------------------------------------------

; ----- úschova registrů W a STATUS

Inter	movwf	TempW		; úschova registru W
	swapf	STATUS,W	; načtení STATUS registru do W
	movwf	TempS		; úschova STATUS registru

; ----- test, zda je přerušení od portu

	btfss	INTCON,0	; je přerušení od portu?
	goto	Inter1		; není přerušení od portu
	bcf	INTCON,0	; nulování příznaku přerušení od portu

; ----- inicializace čítače pro klid

	movlw	QUITMAX		; konstanta pro uklidnění
	movwf	Quit		; nastavení čítače pro klid

; ----- test, zda je senzor sepnut

	btfsc	PORTB,5		; je senzor sepnut?
	goto	Inter0		; senzor je sepnut
	bcf	Flags,2		; vypnutí příznaku sepnutí senzoru
	goto	Inter1

; ----- test, zda senzor byl sepnut

Inter0	btfsc	Flags,2		; byl senzor již sepnut?
	goto	Inter1		; senzor byl již sepnut
	bsf	Flags,2		; zapnutí příznaku sepnutí senzoru
	
; ----- zapnutí běhu času

Intr00	bsf	Flags,5		; zapnutí běhu času

; ----- čítání urazené vzdálenosti

	movlw	LENINC		; přírustek vzdálenosti na impuls
	addwf	LenCM,F		; zvýšení urazené vzdálenosti v cm
	movlw	100		; max. hodnota vzdálenosti v cm
	subwf	LenCM,W		; test přetečení vzdálenosti v cm
	btfss	STATUS,C	; je přetečení vzdálenosti?
	goto	Inter02		; není přetečení vzdálenosti
	movwf	LenCM		; přetékající hodnota

	incf	LenM,F		; zvýšení vzdálenosti v m
	movlw	10		; max. hodnota vzdálenosti v m
	subwf	LenM,W		; test přetečení vzdálenosti v m
	btfss	STATUS,C	; je přetečení vzdálenosti?
	goto	Inter02		; není přetečení vzdálenosti
	movwf	LenM		; přetékající hodnota

	incf	LenDM,F		; zvýšení vzdálenosti v Dm
	movlw	10		; max. hodnota vzdálenosti v Dm
	subwf	LenDM,W		; test přetečení vzdálenosti v Dm
	btfss	STATUS,C	; je přetečení vzdálenosti?
	goto	Inter01		; není přetečení vzdálenosti
	movwf	LenDM		; přetékající hodnota

	incf	LenHM,F		; zvýšení vzdálenosti v Hm
	movlw	10		; max. hodnota vzdálenosti v Hm
	subwf	LenHM,W		; test přetečení vzdálenosti v Hm
	btfss	STATUS,C	; je přetečení vzdálenosti?
	goto	Inter01		; není přetečení vzdálenosti
	movwf	LenHM		; přetékající hodnota
	
	incf	LenKM,F		; zvýšení vzdálenosti v km
	movlw	200		; max. hodnota vzdálenosti v km
	subwf	LenKM,W		; test přetečení vzdálenosti v km
	btfss	STATUS,C	; je přetečení vzdálenosti?
	goto	Inter01		; není přetečení vzdálenosti
	movwf	LenKM		; přetékající hodnota

; ----- čítání celkové vzdálenosti (po změně vzdálenosti v Dm)

Inter01	incf	SLenDM,F	; zvýšení vzdálenosti v Dm
	movlw	100		; max. hodnota vzdálenosti v Dm
	subwf	SLenDM,W	; test přetečení vzdálenosti v Dm
	btfss	STATUS,C	; je přetečení vzdálenosti?
	goto	Inter02		; není přetečení vzdálenosti
	movwf	SLenDM		; přetékající hodnota

	incf	SLenKM,F	; zvýšení vzdálenosti v km
	movlw	10		; max. hodnota vzdálenosti v km
	subwf	SLenKM,W	; test přetečení vzdálenosti v km
	btfss	STATUS,C	; je přetečení vzdálenosti?
	goto	Inter02		; není přetečení vzdálenosti
	movwf	SLenKM		; přetékající hodnota
	
	incf	SLenHM,F	; zvýšení vzdálenosti v desítkách km
	movlw	200		; max. hodnota vzdálenosti v desítkách km
	subwf	SLenHM,W	; test přetečení vzdálenosti v desítkách km
	btfss	STATUS,C	; je přetečení vzdálenosti?
	goto	Inter02		; není přetečení vzdálenosti
	movwf	SLenHM		; přetékající hodnota

; ----- čítání rychlosti

Inter02	movlw	LENINC		; přírustek vzdálenosti na impuls
	addwf	CVelCM,F	; zvýšení urazené vzdálenosti v cm
	movlw	100		; max. hodnota vzdálenosti v cm
	subwf	CVelCM,W	; test přetečení vzdálenosti v cm
	btfss	STATUS,C	; je přetečení vzdálenosti?
	goto	Inter1		; není přetečení vzdálenosti
	movwf	CVelCM		; přetékající hodnota

	incf	CVelM,F		; zvýšení vzdálenosti v m

; ----- test, zda je přerušení od TMR0

Inter1	btfss	INTCON,2	; je přerušení od časovače?
	goto	Inter9		; není přerušení od časovače
	bcf	INTCON,2	; nulování příznaku přerušení od TMR0

; ----- čítání setin sekundy

	incf	Hundr,F		; zvýšení čítače setin sekundy
	movf	Hundr,W		; načtení čítače setin sekundy do W
	sublw	32		; test maximální hodnoty setin sekundy
	btfss	STATUS,Z	; je přetečení setin sekundy?
	goto	Inter2		; není ještě přetečení setin sekundy
	clrf	Hundr		; nulování čítače setin sekundy

; ----- čítání stavu klidu

	decf	Quit,F		; čítač stavu klidu

; ----- test, zda běží čas

	btfss	Flags,5		; běží čas?
	goto	Inter2		; čas neběží

; ----- zvýšení čítače sekund

	incf	Second,F	; zvýšení čítače sekund
	movf	Second,W	; načtení čítače sekund
	sublw	60		; test maximální hodnoty sekund
	btfss	STATUS,Z	; je přetečení sekund?
	goto	Inter2
	clrf	Second		; nulování čítače sekund

; ----- zvýšení čítače minut

	incf	Minute,F	; zvýšení čítače minut
	movf	Minute,W	; načtení čítače minut
	sublw	60		; test maximální hodnoty minut
	btfss	STATUS,Z	; je přetečení minut?
	goto	Inter2
	clrf	Minute		; nulování čítače minut

; ----- zvýšení čítače hodin

	incf	Hour,F		; zvýšení čítače hodin
	movf	Hour,W		; načtení čítače hodin
	sublw	20		; test maximální hodnoty hodin
	btfsc	STATUS,Z	; je přetečení hodin?
	clrf	Hour		; nulování čítače hodin

; ----- zobrazení indikace

Inter2	btfss	Flags,6		; je zapnuta indikace?
	goto	Inter20		; není zapnuta indikace
	decfsz	CInd,F		; čítač doby indikace
	goto	Inter28		; není ještě konec indikace

	bcf	Flags,6		; vypnutí indikace
	btfss	Flags,7		; je indikace automatiky?
	goto	Inter20		; není indikace automatiky

	bcf	Flags,7		; vypnutí indikace automatiky
	call	Indik0		; indikace aktuálního stavu
	goto	Inter28

; ----- zobrazení podle stavu

Inter20	call	NulReg		; vynulování výstupních registrů
	movf	State,W		; načtení aktuálního stavu
	call	StatTab		; zobrazení

; ----- zobrazení displeje a vstup z tlačítka

Inter28	call	ReDisp		; překreslení displeje

; ----- automatické přepínání zobrazení

	btfss	Flags,4		; je automatické přepínání?
	goto	Inter3		; není automatické přepínání
	decfsz	CState,F	; čítání automatické změny
	goto	Inter3		; není automatická změna

	movlw	CSTATE		; čítač automatické změny stavu
	movwf	CState		; inicializace čítače automatické změny

	incf	State,F		; zvýšení čítače stavu
	movlw	3		; maximální stav
	subwf	State,W		; test maximálního stavu
	btfsc	STATUS,Z	; je maximální stav?
	clrf	State		; nulování stavu	

	call	Indik0		; zobrazení nového stavu

; ----- vstup z tlačítka

Inter3	btfss	Flags,1		; je stisk tlačítka?
	goto	Inter5		; není stisk tlačítka

; ----- nulování

	btfss	Flags,3		; je dlouhý stisk tlačítka?
	goto	Inter32		; není dlouhý stisk tlačítka

	call	Clear		; vymazání registrů

	movlw	0xff		; všechny bity budou zapnuty
	movwf	Reg0		; zapnutí bitů registru 0
	movwf	Reg1		; zapnutí bitů registru 1
	movwf	Reg2		; zapnutí bitů registru 2

	bsf	Flags,6		; zapnutí příznaku indikace

	movlw	32*4		; doba indikace (4 sekundy)
	movwf	CInd		; nastavení čítače indikace

	goto	Inter5

; ----- posun stavu

Inter32	btfss	Flags,4		; je automatická změna stavu?
	goto	Inter33		; není automatická změna stavu

	bcf	Flags,4		; vypnutí automatické změny stavu
	movlw	STIME		; přechod na zobrazení času
	movwf	State		; základní stav
	goto	Inter34		; indikace stavu

Inter33	incf	State,W		; zvýšení čítače stavů
	andlw	11b		; maskování hodnoty
	movwf	State		; nová hodnota stavu
	btfss	STATUS,Z	; je přechod přes konec?
	goto	Inter34		; není přechod přes konec

	bsf	Flags,4		; zapnutí automatické změny
	movlw	CSTATE		; čítač automatické změny stavu
	movwf	CState		; inicializace čítače automatické změny

	bsf	Flags,7		; zapnutí příznaku automatiky
	movlw	SAUT		; stav automatiky
Inter34	call	Indik		; zobrazení stavu

; ----- čítání doby měření rychlosti

Inter5	decfsz	VelTim,F	; čítání doby měření
	goto	Inter9		; není ještě konec měření

	movlw	VELTIME		; konstanta čítače doby rychlosti
	movwf	VelTim		; čítač měřící doby rychlosti

	clrf	VelHM		; rychlost v hektometrech
	movf	CVelCM,W	; čítač rychlosti v cm

Inter52	incf	VelHM,F		; čítač rychlosti v hektometrech
	addlw	-10		; čítání dekád
	btfsc	STATUS,C	; je přetečení?
	goto	Inter52		; spočtení dekád
	decf	VelHM,F		; návrat poslední hodnoty

	movf	CVelM,W		; čítač rychlosti v m
	movwf	VelKM		; rychlost v km

	clrf	CVelCM		; čítač rychlosti v cm
	clrf	CVelM		; čítač rychlosti v m

	bsf	Flags,5		; zapnutí běhu času
	iorwf	VelHM,W		; test, zda je rychlost = 0
	btfsc	STATUS,Z	; je nějaká rychlost?
	bcf	Flags,5		; vypnutí běhu času

; ----- návrat registrů W a STATUS

Inter9	swapf	TempS,0		; původní STATUS registr k navrácení
	movwf	STATUS		; návrat původního STATUS registru
	swapf	TempW,1		; předpříprava původního registru W
	swapf	TempW,0		; návrat původního W registru
	retfie			; návrat z obsluhy přerušení

;--------------------------------------------------------------------------
;	odeslání bajtu W na displej (s rozlišením inverze)
;--------------------------------------------------------------------------

; ----- inverze bajtu

OutByte	btfsc	Flags,0		; je inverze zobrazení?
	xorlw	0xff		; inverze bajtu

; ----- úschova bajtu k odeslání

	movwf	DByte		; úschova bajtu k odeslání

; ----- výstup na port B (bit 4 a 5 nevyužit, jsou to vstupy)

	movwf	PORTB		; výstup na port B

; ----- výstup na port A

	bcf	PORTA,0		; vypnutí bitu 0 portu A
	bcf	PORTA,1		; vypnutí bitu 1 portu A
	swapf	DByte,W		; načtení bajtu k výstupu
	andlw	bit0 + bit1	; maskování bitů k nastavení
	iorwf	PORTA,F		; výstup bitů na port A
	return

;--------------------------------------------------------------------------
;	překreslení displeje LCD
;--------------------------------------------------------------------------

; ----- nastavení registru 2

ReDisp	movf	Reg2,W		; načtení registru 2
	call	OutByte		; výstup bajtu na port
	bsf	PORTA,3		; zapnutí výstupu do registru 2
	bcf	PORTA,3		; vypnutí výstupu do registru 2

; ----- nastavení registru 1

	movf	Reg1,W		; načtení registru 1
	call	OutByte		; výstup bajtu na port
	bsf	PORTA,2		; zapnutí výstupu do registru 1
	bcf	PORTA,2		; vypnutí výstupu do registru 1

; ----- nastavení registru 0

	movf	Reg0,W		; načtení registru 0
	call	OutByte		; výstup bajtu na port

; ----- nastavení společné elektrody

	bcf	PORTA,4		; vypnutí společné elektrody
	btfsc	Flags,0		; je inverze zobrazení?
	bsf	PORTA,4		; zapnutí společné elektrody

; ----- překlopení příznaku inverze

	movlw	bit0		; bit k překlopení stavu
	xorwf	Flags,F		; překlopení příznaku inverze

; ----- obsluha vstupu z tlačítka

	bcf	Flags,1		; vypnutí příznaku stisku tlačítka
	bcf	Flags,3		; vypnutí příznaku dlouhého stisku tlačítka

	movf	RelKey,F	; test, zda běží čítač uvolnění tlačítka
	btfsc	STATUS,Z	; běží čítač uvolnění tlačítka?
	goto	ReDsp32		; čítač neběží

	decfsz	LongKey,F	; čítač opakování tlačítka
	goto	ReDsp31		; není ještě 0
	bsf	Flags,3		; příznak dlouhého stisku tlačítka
	goto	ReDsp34

ReDsp31	btfsc	PORTB,4		; je tlačítko stisknuto?
	goto	ReDsp36		; je stisknuto - inicializace čítače uvolnění
	decf	RelKey,F	; snížení čítače uvolnění
	goto	ReDisp4

ReDsp32	btfss	PORTB,4		; je tlačítko stisknuto?
	goto	ReDisp4		; tlačítko není stisknuto

ReDsp34	movlw	64		; interval dlouhého sisku tlačítka (2 sekundy)
	movwf	LongKey		; čítač dlouhého stisku tlačítka
	bsf	Flags,1		; příznak stisku tlačítka

ReDsp36	movlw	2		; nová hodnota čítače (60 ms)
	movwf	RelKey		; nová inicializace čítače uvolnění

ReDisp4	return
