;program pro PIC16F84,4MHz 
;2x7seg. se společnou anodou
;PB0..a				
;PB1..b
;PB2..c
;PB3..d
;PB4..e
;PB5..f
;PB6..g
;PB7..DP
;PA0..Start
;PA1..Stop
;PA4..LED
;po zapnutí začne blikat LED
;po stisku Start se na 2x7seg. displeji začne měnit číslo 
;od 00 - 99. Rychlost změny stavu displeje každé 4ms.
;stiskem tlačítka Stop se zastaví a zobrazí číslo,bliká 1x za sec.
;tlačítko Ready provede reset uP
;**********************************************************
		include	"P16F84.INC"
		__config	_CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC 
;************************************************************
;	Definice proměnných
;************************************************************
save_W		equ	0Ch
save_stat	equ	0Dh
Time	equ	0Eh
Dig	equ	0Fh
Seg1	equ	10h
Seg2	equ	11h
MODE	equ 12h

#define An1	PORTA,2
#define An2	PORTA,3

#define	Stop PORTA,1
#define	Start	PORTA,0
#define	LED	PORTA,4
;************************************************************
		org	000h
		goto Init
;************************************************************
		org	004h
		bcf	INTCON,T0IF		;vymazání příznaku přerušení pro TMR0
		goto	Int_TMR0	;skok na rutinu přerušení
		retfie
;*************************************************************
Tab	
		addwf PCL,F	    ;přičte W k čítači instrukcí
   		retlw B'11000000' ;zobrazí 0
		retlw B'11111001' ;zobrazí 1
		retlw B'10100100' ;zobrazí 2
		retlw B'10110000' ;zobrazí 3
		retlw B'10011001' ;zobrazí 4
		retlw B'10010010' ;zobrazí 5
		retlw B'10000010' ;zobrazí 6
		retlw B'11111000' ;zobrazí 7
		retlw B'10000000' ;zobrazí 8
		retlw B'10010000' ;zobrazí 9
		retlw B'11111111' ;zhasnutý displej
		return
;*************************************************************
Int_TMR0	
		movwf	save_W			;Uložení W
		swapf	STATUS,W		;Obsah STATUS do W
		movwf	save_stat		;Uložení STATUS

		movlw	.6
		movwf	TMR0			;Nastavení TMR0 
		incf	Time,F			;Pomocný čítač

		btfss	Start			;Test tlačítka Start
		call	TL1				;Start = 0,jdi na TL1,Start = 1 pokračuj
		btfss	Stop			;test tlačítka Stop
		call	TL2				;Stop = 0,jdi na TL2,Stop = 1 pokračuj

;MODE,1 = 0 program pokračuje na zobrazení displeje(stav po zapnutí uP)

;MODE,1 = 1(stisknuto tlačítko Start), otestuj stav MODE,2
;MODE,2 = 0 stav disp. +1
;MODE,2 = 1(stisknuto tlačítko Stop) pokračuj na zobrazení aktuálního stavu

		btfss	MODE,1			;Test MODE,1
		goto	$+3				;MODE,1 = 0 jdi na +3
		btfss	MODE,2			;Mode,1 = 1; Test MODE,2
		call	Plus			;MODE,2 = 0, jdi na Plus
								;MODE,2 = 1, pokračuj	
		call	Displej

		swapf	save_stat,W
		movwf	STATUS			;Obnovení STATUS
		swapf	save_W,F
		swapf	save_W,W		;Obnovení W
		retfie
;*************************************************************
Displej	
		bsf		An1			;Vypnout Seg1
		bsf		An2			;Vypnout Seg2
;multiplex displeje
;MODE,2 = 0 netestuj stav MODE,7
;MODE,2 = 1 provede test MODE,7
;MODE,7 = 1 zapne anodu segment - disp. zobrazuje
;MODE,7 = 0 anoda zůstane vypnutá - disp. nezobrazuje

		decf	Dig,F		;Dig - 1
		btfsc	STATUS,Z	;Dig = 0 ?
		goto	Int_1		;ano,jdi na Int_1;ne pokračuj
Int_2						
		movf	Seg2,W		;obsah Seg2 do W
		call	Tab			;koduje podle Tab		
		movwf	PORTB		;obsah W na PORTB
		btfsc	MODE,2		;test MODE,2
		btfsc	MODE,7		;MODE,2 = 1; test MODE,7
		bcf		An2			;MODE,7 = 1,zapni Anodu segmentu 1
		return				;MODE,7 = 0,návrat
Int_1	
		movf	Seg1,W		
		call	Tab
		movwf	PORTB
		btfsc	MODE,2
		btfsc	MODE,7
		bcf		An1
		movlw	.2
		movwf	Dig
		return
;*************************************************************
;při stisknutí tlačítka dochází k zákmitům napětí, je toto programově  
;ošetřeno.V případě zakmitání je test opakován až při dalším přerušení.

TL1
		btfsc	Start		;test tlačítka Start
		return				;Start = 1 návrat

		bcf	MODE,0			;Start = 0; MODE,0 = 0 stop blikání LED
		bsf	MODE,1			;MODE,1 = 1	
		bsf	LED				;LED OFF
;		bcf	MODE,2			;MODE,2 = 0
		return
TL2		
		btfsc	Stop
		return				;Stop = 1 návrat

;MODE,2 = 1 zastavení generování čísel
;jelikož není změněno MODE,1,zůstane program v režimu zobrazení stavu
;až do resetu uP pomocí tlačítka READY. Poté znovu začne program od začátku.
;tj. začne blikat LED a čeká se na stisk tlačítka Start.
;Pokud by se přidal řádek s bcf	MODE,1 a v TL1 přidal řádek bcf MODE,2 
;program bude čekat na stisk tlačítka Start, ale nebude blikat LED.

		bsf	MODE,2			;MODE,2 = 1
;		bcf	MODE,1			;MODE,1 = 0
		return
;..............................................................
;00 - 99, poté se opakuje
Plus
		incf	Seg2,F		;stav Seg2 + 1
		movf	Seg2,W		;obsah Seg2 do W
		xorlw	.10			;W xor k(10)
		btfss	STATUS,Z	;test na shodu,Z = 1
		return				;ne 
		clrf	Seg2		;ano, reset Seg2
		incf	Seg1,F		;stav seg2 + 1
		movf	Seg1,W
		xorlw	.10			;W xor k
		btfss	STATUS,Z	;test na shodu,Z = 1
		return				;ne
		clrf	Seg1		;ano, reset Seg1
		return
;*************************************************************
Delay1s
		movf	Time,W		;obsah Time do W
		xorlw	.250		;W xor k
		btfss	STATUS,Z	;test na shodu,Z = 1
		goto	$-3			;ne
		return				;ano,návrat
;*************************************************************
;		Hlavní program
;*************************************************************
Init
		bsf	STATUS,RP0
		movlw	b'11100011'		;PA0-PA1,PA4 vstup,PA2-PA3 výstup
		movwf	PORTA			
		movlw	b'00000000'		;PORTB celý výstup
		movwf	PORTB
		movlw	b'11000011'		;Nastavení předděličky na 1:16
		movwf	01h				;vstup osc/4=(1MHz)
		bcf	STATUS,RP0
;přerušení po 1us x 16 x 250 = 4ms
		movlw 	.6				;nastavení časovače na 256-6 = 250
		movwf	TMR0			

		movlw	.2
		movwf	Dig
;oba segmenty displeje zhasnuty
		movlw	.10
		movwf	Seg1
		movwf	Seg2

		bsf	An1
		bsf	An2
		bsf	LED
;..............................
		bcf	INTCON,T0IF			;smazání příznaku přerušení od TMR0
		bsf	INTCON,T0IE			;povolení přerušení pro TMR0
		bsf	INTCON,GIE			;povolení všech přerušení

		bsf	MODE,0				;Povoleno blikání LED		
		bcf	MODE,1				;Start = 0
		bcf	MODE,2				;Stop  = 0

;po zapnutí uP začne blikat LED
;MODE,0 = 1 blikání LED
;MODE,0 = 0 LED OFF 
;stav MODE,7 řídí v režimu Stop blikání displeje
Opak
		btfsc	MODE,0			;test MODE,0
		bcf	LED					;MODE,0 = 1, LED ON
		bcf	MODE,7				;MODE,0 = 0; MODE,7 = 0	
		clrf	Time					
		call	Delay1s			;čekej 1s
		btfsc	MODE,0			;Test MODE,0
		bsf	LED					;MODE,0 = 1, LED 0FF
		bsf	MODE,7				;MODE,0 = 0;MODE,7 = 1
		clrf	Time
		call	Delay1s			;čekej 1s
		goto 	Opak
;*************************************************************
		end