;*******************************************************************************
;*	PROJEKT:	Úloha č. 8 - Práce s pamětí EEPROM                             *
;*******************************************************************************
;
;	AUTOR:	
;	ORGANIZACE:
;
;	VERZE:		12/13
;	DATUM:		2.1.2014
;
;###############################################################################
;
;	POPIS:	Program je určen pro výuku práce s uP PIC16F88.
;	======	Mikropočítač s tímto programem bude počítat počet zapnutí napájecího
;	napětí. Počet zapnutí bude uložen na adrese 10H v paměti EEPROM. Po uložení
;	nové hodnoty se rozsvítí desetinná tečka na sedmisegmentovém zobrazovači.
;	Po stisknutí tlačítka TL1 se na 1 sekundu zobrazí na sedmisegmentovém
;	zobrazovači jednotky počtu zapnutí napájení. Následuje zhasnutí zobrazovače,
;	rozsvícení tečky a čekání na další stisk tlačítka TL1.
;	U tlačítka TL1 jsou ošetřeny zákmity vznikající po jeho stisku.
;
;	PROCESOR:	PIC16F88						;typ použitého procesoru
;	OSCILÁTOR:	INTOSC=4MHz						;typ oscilátoru, kmitočet
;
;###############################################################################

	list		P=16f88, R=hex, F=inhx8m, b=4, N=95
				;typ procesoru, implicitní číselná soustava pro neoznačené
				;číselné hodnoty, popis výstupního souboru ".hex" a ".lst"

;----
;následuje blok definic hardware a absolutních adres registrů pro použitý
;procesor, definice proměnných
;----

;-------------------------------------------------------------------------------
;	DEKLARACE HW					;blok definic hardware - konfigurační slova
;-------------------------------------------------------------------------------

	__config	2007,0x3F50			;nastavení konfiguračního slova č.1.
;b13 	ochrana paměti programu proti vyčtení	-	1=vypnuto			1
;b12	určení vývodu pro CCP1					- 1=CCP1 na vývodu RB0	1	3

;b11	ladění v aplikaci		-	1=ICD je zakázáno, RB6a7 norm.výv.	1
;b10	ochrana proti zápisu do paměti programu	-	1=zápis povolen		1
;b9		ochrana proti zápisu do paměti programu	-	1=zápis povolen		1
;b8		ochrana paměti EEPROM proti vyčtení		-	1=vypnuto			1	F

;b7		programování nízkým napětím		-	0=LVP zakázáno, RB3 norm.v.	0
;b6		detekce poklesu napájecího napětí		-	1=povolen reset		1
;b5		reset na vývodu MCLR		-	1=zakázán, RA5 je digit. vstup	0
;b4		volba typu oscilátoru		-	1 pro INTOSC=4MHz,RA6a7 norm.v.	1	5

;b3		časovač pro zpoždění resetu při zapnutí	-	0=PWTR povolen		0
;b2		hlídací časovač Watchdog				-	0=WDT zakázán		0
;b1		volba typu oscilátoru		-	0 pro INTOSC=4MHz,RA6a7 norm.v.	0
;b0		volba typu oscilátoru		-	0 pro INTOSC=4MHz,RA6a7 norm.v.	0	0


	__config	2008,0x3FFC			;nastavení konfiguračního slova č.2.
;b13 	nepoužito														1
;b12	nepoužito														1	3

;b11	nepoužito														1
;b10	nepoužito														1
;b9		nepoužito														1
;b8		nepoužito														1	F

;b7		nepoužito														1
;b6		nepoužito														1
;b5		nepoužito														1
;b4		nepoužito														1	F

;b3		nepoužito														1
;b2		nepoužito														1
;b1		povol. přepnutí vnitřního a vnějšího oscil.	-	0=zakázáno		0
;b0		povolení monitorování taktovací frekvence	-	0=zakázáno		0	C

	errorlevel -302	; vypnuti Message [302]: Register in operand not in BANK 0


;-------------------------------------------------------------------------------
;	DEKLARACE SFR					;blok definic SFR
;-------------------------------------------------------------------------------

;(	#include	<pic16f88.inc>	)	;alternativa: načtení definic SFR z knihovny

;BANK0
indf		equ		0x00				;definice speciálních funkčních registrů
tmr0		equ		0x01				;(pojmenování použijeme přednostně shodné
pcl		equ		0x02				;s manuálem výrobce)
status		equ		0x03
fsr		equ		0x04
porta		equ		0x05
portb		equ		0x06
pclath		equ		0x0A
intcon		equ		0x0B
pir1		equ		0x0C
pir2		equ		0x0D
tmr1l		equ		0x0E
tmr1h		equ		0x0F
t1con		equ		0x10
tmr2		equ		0x11
t2con		equ		0x12
sspbuf		equ		0x13
sspcon		equ		0x14
ccpr1l		equ		0x15
ccpr1h		equ		0x16
ccp1con		equ		0x17
rcsta		equ		0x18
txreg		equ		0x19
rcreg		equ		0x1A
adresh		equ		0x1E
adcon0		equ		0x1F

;BANK1
optireg		equ		0x81				;definice SFR
trisa		equ		0x85
trisb		equ		0x86
pie1		equ		0x8C
pie2		equ		0x8D
pcon		equ		0x8E
osccon		equ		0x8F
osctune		equ		0x90
pr2		equ		0x92
sspadd		equ		0x93
sspstat		equ		0x94
txsta		equ		0x98
spbrg		equ		0x99
ansel		equ		0x9B
cmcon		equ		0x9C
cvrcon		equ		0x9D
adresl		equ		0x9E
adcon1		equ		0x9F

;BANK2
wdtcon		equ		0x105				;definice SFR
eedata		equ		0x10C
eeadr		equ		0x10D
eedath		equ		0x10E
eeadrh		equ		0x10F

;BANK3
eecon1		equ		0x18C				;definice SFR
eecon2		equ		0x18D


;pomocné definice
w		equ		0					;uložení výsledku do střadače
f		equ		1					;uložení výsledku do registru


;definice důležitých bitů speciálních funkčních registrů
#define		carry		status,0			;příznak přenosu
#define		dcarry		status,1			;poloviční příznak přenosu
#define		zero		status,2			;příznak nuly


;-------------------------------------------------------------------------------
;	DEKLARACE PROMĚNNÝCH A KONSTANT		;blok definic vlastních proměnných
;-------------------------------------------------------------------------------

;definice konstant
k1		equ		0x03				;první konstanta


;definice vlastních proměnných
pom1		equ		0x70				;pomocná proměnná ve zpoždění 1 ms
pom2		equ		0x71				;pomocná proměnná ve zpoždění 500 ms
pom3		equ		0x72				;pomocná proměnná ve zpoždění 10 ms
pocet		equ		0x73				;počet resetů napájecího napětí
znak		equ		0x74


;definice vlastních globálních proměnných pro všechny banky 
;p1		equ		0x70				;první vlastní globální proměnná


;definice vlastních bitů
#define 	bit1 		porta,3				;první vlastní bit


;počáteční nulování dat (počtu zapnutí) v EEPROM
		org		0x2110				;adresa 10H v EEPROM
		DE		0					;vynulování počtu zapnutí

;----
;pokud se v programu častěji opakuje skupina instrukcí, lze si vytvořit MAKRO,
;složené z těchto instrukcí. Do zdrojového textu se pak vkládá pouze volání
;makroinstrukce - zkrátí a zpřehlední se zdrojový text.
;----

;-------------------------------------------------------------------------------
;	DEFINICE MAKER
;-------------------------------------------------------------------------------

BANK0		macro					;BANKa0 v RWM - přepnutí do banky 0 v paměti dat
		bcf		status,5		;definice makra pro nastavení banky registrů
		bcf		status,6		;definice začíná direktivou macro a končí
		endm					;direktivou endm

BANK1		macro					;BANKa1 v RWM - přepnutí do banky 1 v paměti dat
		bsf		status,5
		bcf		status,6
		endm

BANK2		macro					;BANKa2 v RWM - přepnutí do banky 2 v paměti dat
		bcf		status,5
		bsf		status,6
		endm

BANK3		macro					;BANKa3 v RWM - přepnutí do banky 3 v paměti dat
		bsf		status,5
		bsf		status,6
		endm


;###############################################################################
;	P R O G R A M
;###############################################################################

;----
;následuje vlastní zdrojový text programu. První instrukce programu musí být
;uložena na adrese 0. Zdrojový text musí končit direktivou END. Adresa 4 je
;určena pro první instrukci obsluhy přerušení.
;----

;-------------------------------------------------------------------------------
;	START PROGRAMU - INICIALIZACE PROCESORU
;-------------------------------------------------------------------------------

		org     	0				;zahájení programu po RESETU
zac		call		init			;inicializace - konfigurace procesoru
		goto		starthp


;-------------------------------------------------------------------------------
;	OBSLUHA PŘERUŠENÍ
;-------------------------------------------------------------------------------

		org		4
		;...					;rutina obsluhy přerušení (vždy adr. 4!)
		;...
		return


;-------------------------------------------------------------------------------
;	HLAVNÍ PROGRAM
;-------------------------------------------------------------------------------

starthp							;tady začíná hlavní programová smyčka
		BANK0		;až BANK3 		;nastavit si potřebnou banku registrů

		call		cteni			;Přečti uložený počet zapnutí z EEPROM.
		movwf		pocet			;Ulož přečtený údaj do proměnné pocet.
		incf		pocet,f			;Inkrementuj proměnnou pocet.

		call		zapis			;Zapiš slabiku dat (pocet) do paměti EEPROM.

		BANK0
		movf		pocet,w
		call		tabulka			;Najdi odpovídající hexa kód pro displej.
		movwf		znak

		bcf		portb,4			;rozsvit tečku na signál že je zapnutí započítaný

test1		btfsc		portb,1			;Je stisknuto tlačítko TL1?
		goto		test1			;Není - čekej na stisk.
		call		zp_10ms			;Je - počkej 10 ms (ošetření zákmitů).
test2		btfss		portb,1			;Je uvolněno tlačítko TL1?
		goto		test2			;Není - čekej na uvolnění.
		bsf		portb,4			;Je - zhasni desetinnou tečku na zobrazovači.
		movf		znak,w
		movwf		porta			;Zobraz přečtený znak na zobrazovači.
		call		zp_1s			;Počkej 1 s.
		movlw		b'11111111'
		movwf		porta
		bcf		portb,4			;rozsvit tečku na signál že je zapnutí započítaný

		goto		test1			;Čekej na další stisk tlačítka TL1.		

;-------------------------------------------------------------------------------
;	PODPROGRAMY
;-------------------------------------------------------------------------------

tabulka		addwf		pcl,f			;Podprogram hexa kódu pro výpis čísla na dis-
								;pleji. Posun v tabulce o hodnotu ve střadači.
		retlw		h'80'			;Znak "0".
		retlw		h'D9'			;Znak "1".
		retlw		h'44'			;Znak "2".
		retlw		h'50'			;Znak "3".
		retlw		h'19'			;Znak "4".
		retlw		h'12'			;Znak "5".
		retlw		h'02'			;Znak "6".
		retlw		h'D8'			;Znak "7".
		retlw		h'00'			;Znak "8".
		retlw		h'10'			;Znak "9".
		retlw		h'F9'			;Znak "E" (11-té zapnutí, nelze zobrazit)

		decf		pocet			;12-té zapnutí, dekrementuj pocet na 11 
		call		zapis			; a ulož hodnotu 11
		retlw		h'F9'			;vrat se zpět se znakem "E"


		return

zp_1ms		movlw		d'248'			;Podprogram na zpoždění 1 ms.
		movwf		pom1			;Nastavení pomocné proměnné pom1 = 248.
zp1		nop						;Čekej 1 us.
		decfsz		pom1,f			;pom1 = pom1 - 1. Je pom1 = 0?
		goto		zp1				;Ne - zpět na zpoždění 1 us.
		return					;Ukonči podprogram.

zp_0.5s		movlw		d'248'			;Podprogram na zpoždění 500 ms.
		movwf		pom2			;Nastavení pomocné proměnné pom2 = 248.
zp2		call		zp_1ms			;Čekej 1 ms.
		call		zp_1ms			;Čekej 1 ms.
		nop						;Čekej 1 us.
		decfsz		pom2,f			;pom2 = pom2 - 1. Je pom2 = 0?
		goto		zp2				;Ne - zpět na zpoždění 1 ms.
		return					;Ukonči podprogram.

zp_10ms		movlw		d'10'			;Poprogram na zpoždění 10 ms.
		movwf		pom3			;Nastavení pomocné proměnné pom3 = 10.
zp3		call		zp_1ms			;Čekej 1 ms.
		decfsz		pom3,f			;pom3 = pom3 - 1. Je pom3 = 0?
		goto		zp3				;Ne - zpět na zpoždění 1 ms.
		return					;Ano - ukonči podprogram.

zp_1s		call		zp_0.5s			;Podprogram na zpoždění 1 s.
		call		zp_0.5s
		return					;Ukonči podprogram.

cteni
		BANK2
		movlw		h'10'
		movwf		eeadr			;Nastav ukazatel adresy na hodnotu 10H.
		BANK3
		bcf		eecon1,7		;volba pamět EEPROM
		bsf		eecon1,0		;zahájit čtení
		BANK2
		movf		eedata,w		;Ulož data (pocet) z EEPROM do střadače.
		return					;Ukonči podprogram.

zapis		BANK2					;Podprogram pro zápis slabiky dat do EEPROM.
		movlw		h'10'
		movwf		eeadr			;Nastav ukazatel adresy na hodnotu 10H.
		movf		pocet,w
		movwf		eedata			;data = pocet
		BANK3
		bcf		eecon1,7		;volba pamět EEPROM
		bsf		eecon1,2		;Povolení zápisu do EEPROM.
		movlw		0x55			;Autorizační sekvence pro zápis do EEPROM.
		movwf		eecon2			; dtto
		movlw		0xAA			; dtto
		movwf		eecon2			; dtto
		bsf		eecon1,1		;Provedení zápisu do EEPROM.
zapis_cekat	btfsc		eecon1,1
		goto		zapis_cekat
		bcf		eecon1,2		;zakázání dalšího zápisu do EEPROM
		return					;Ukonči podprogram.

;-------------------------------------------------------------------------------
;	INIT - INICIALIZACE PROCESORU, POČÁTEČNÍ NASTAVENÍ VÝSTUPŮ A PERIFERIÍ
;-------------------------------------------------------------------------------

init		BANK1
		clrf		ansel			;všechny vývody portů jsou digitální
		
		BANK0
		movlw		b'11111111'		;konfigurace vývodů brány PortA
		movwf		porta			;všechny linky portu A jsou v úrovni H =
								; = zhasnutí displeje	
		bsf		portb,4			;zhasni desetinnou tečku na zobrazovači.	

		BANK1
		movlw   	b'00000111'		;RB0 a RB1 jsou vstupy, RB4 je výstup
		movwf   	trisb			

		movlw		b'00000000'		;port A je výstupní
		movwf		trisa

		movlw		b'00000000'		;připojení pull-up rezistorů
		movwf		optireg

		movlw		b'01100000'		;nastavení vnitřního taktovacího oscilátoru
		movwf		osccon			;na 4 MHz - bity IRCF2-IRCF0 (FOSC2-FOSC0=100)

		BANK0

		return			;konec procedury inicializace procesoru

	end					;direktiva pro ukončení programu ( nesmí chybět !!! )
