Uloz prac režim v EEprom a po stisku reset načti program

Zdravím, naprogramoval jsem tuto práci:
V assembleru sestavte program, který bude plnit funkci zařízení pro generování
světelných efektů. Světelné efekty budou zobrazovány na LED diodách kitu EVB5.1.
Ovládání programu bude realizováno pomocí tlačítek kitu EVB5.1 (nezapomeňte
ošetřit zákmity tlačítek). Nastavení, změna pracovního módu a rychlosti přepínání
jednotlivých sekvencí, bude možné pouze při pozastavení běhu aplikace, v tomto
případě bude na LED diodách zobrazován pracovní mód aplikace, nebo rychlost
přepínání sekvencí (podle aktuální změny parametru).
Požadavky na funkce programu:
Pracovní módy světelných efektů budou ve formě:
 Běžícího světla.
 Inverzního běžícího světla.
 Obousměrného binárního čítače (0 – 255).
Požadavky na ovládání aplikace – pomocí tlačítek bude možné:
 Nastavení rychlosti změny zobrazované kombinace.
 Nastavení pracovního módu - přepínání mezi jednotlivými pracovními módy
aplikace.
 Pozastavení a opětovné spuštění aplikace.

Běžící světlo bude pracovat v nekonečném pracovním cyklu zprava do leva a
následně zpět, stejně tak inverzní běžící světlo. Binární čítač bude čítat nejprve
vzestupně od 1 do 255 a po dosažení hodnoty 255 zpět k hodnotě 1, po dosažení
hodnoty 1 opět změní směr čítání na vzestupný do 255 a tak pořád do kola,
v nekonečném cyklu.
Změna (rychlost změny) stavu bude nastavitelná pomocí tlačítek kitu v rozsahu
deseti kroků v rozmezí cca 0,1 – 1Hz (to znamená 10x – 1x za sekundu).
Aktuální pracovní režim bude uchován v paměti EEprom (pracovní mód a rychlost),
ze kterého bude po restartu aplikace opětovně načten.

A jediné co mi na programu nejde, je to že po stisku reset tlačítka nezačne program tam kde přestal a já si nevím rady. Poradil by mi prosím někdo jak upravit tento program?

.nolist						;definice ATMEGA32
.Include "m32def.inc"		;pro každý program stejné
.list

.DEF REG=R16				;promněná REG se ukládá do registru16
.DEF CITAC1=r23				;promněná CITAC1 se ukládá do registru17
.DEF CITAC2=r25 			;promněná CITAC2 se ukládá do registru18	
.DEF CITAC3=r19				;promněná CITAC3 se ukládá do registru19
.def A=r20					;promněná A se ukládá do registru20 , A je pomocná promněná na nastavení programového modu
.def POM=r21				;promněná POM se ukládá do registru21 , POM je pomocná promněná pro zapsání konstanty pro čítač
.def B=r22					;promněná B se ukládá do registru22, B je pomocná promněná pro nastavení rychlosti		
.EQU DDR=DDRB				;zápis DDR je ekvivalentní zápisu DDRB
.EQU PORT=PORTB				;zápis PORT je ekvivalentní zápisu PORTB
.DEF CNT1=R0					; počítadla
.DEF CNT2=R1					; pro USTAL
.CSEG
.ORG 0


RJMP START				;při restartu program skočí do návěští START

.ORG INT0Addr			;definice přerušení
RJMP PRERUS0			;připřerušení z PD2 skočí do návěští PRERUS0





START:
	LDI REG, LOW (RAMEND)	;inicializace zásobníku
	OUT SPL, REG			; nastav ukazatel SP na konec SRAM
	LDI REG,HIGH(RAMEND)	;nejprve dolní byyty potom horní byty
	OUT SPH,REG
	SER REG
	OUT DDR, REG			; aktivuj výstupy
	SBI PORTD, 2			; PRERUSENI !!NEMENIT!! S2 má pull – up rezistory
	CBI DDRD, 0			 ; nastavení pd0 jako vstup
	SBI DDRD, 0			 ; pd0 má pull – up rezistory, defaultní stav je 1
	CBI DDRD, 1			; pd0 má pull – up rezistory, defaultní stav je 1
	SBI DDRD, 1			; nastavení pd1 jako vstup
	CBI DDRD, 3			; pd0 má pull – up rezistory, defaultní stav je 1
	SBI PORTD,3

; obě přerušení se spouští od sestupné hrany
; bity 0 a 1 jsou pro INT0, bity 2 a 3 jsou pro INT1
; kombinace "10" nastaví citlivost na sestupnou hranu
	LDI REG,0b00001010
	OUT MCUCR,REG
; povoleni přerušeni INT0 
; bit 6 povoluje INT0 
	LDI REG, 0b01000000
	OUT GICR, REG
	LDI REG,0b00000000
	SEI							;povoluje přerušení
	SER REG						;do REG ulozi 0b11111111 (ldi REG, 0b11111111)
	OUT DDR, REG				;na PORTB posle obsah registru DDRB, portb je výstupní
	CLC							;vymaže se příznak C
	RCALL EEPROM_readA						;nahraje a z eeprom
	;LDI POM,8					;do POM se nahraje rychlost 8 což je cca 0,1hz
	RCALL EEPROM_readB						;vymaže se promněná B

; NEKONECNO:					;nekonečná smyčka ve které můžeme nastavit pomocí pd0 programový režim a pomocí pd3 rychlsot programu od nejrychlejší po nejpomalejší

; SBIS PIND,0				;skip if bit in IO is set takže dokud bude na pd0 další příkaz se nevykoná
; RJMP VYBER
; RCALL USTAL		; ustal, smyčka pro ustálení zákmitu
; SBIS PIND,0
; RJMP VYBER

; SBIS PIND,1			;skip if bit in IO is set takže dokud bude na pd1 další příkaz se nevykoná
; RJMP ZVYS
; RCALL USTAL		; ustal, smyčka pro ustálení zákmitu
; SBIS PIND,1
; RJMP ZVYS
; RJMP NEKONECNO

PRERUS0:			;co se vykoná když program přerušíme,

SEI					;nejprve se znovu povolí přerušení

SBIS PIND,0			;poté obdoba nekonečné smyčky, můžeme nastavir programový režim
RJMP VYBER
RCALL USTAL		; ustal
SBIS PIND,0
RJMP VYBER


SBIS PIND,3			; nebo se můžeme vrátit kde jsme skončili
RETI				;nefunkční při změně rychlosti

SBIS PIND,1			;nebo můžeme nastavit rychlost od nejrychlejší po nejpomalejší
RJMP ZVYS
RCALL USTAL		; ustal
SBIS PIND,1
RJMP ZVYS
RJMP PRERUS0		;program zůstane v přerušení dokud nevykonáme nějakou akci

ZVYS:			; návěští pro zvýšení promněné B tedy pro snížení rychlosti běhu programu

SBIS PIND,1		; ošetření zákitu
RJMP ZVYS
INC B			;zvýšení B o 1
RCALL EEPROM_writeB
OUT PORT,B		;ukázání promněné B na LEDkách aby jsme věděli co se děje
CPI B,11		;když je B>11 tak se skočí na VYMAZB a tím se B vynuluje, tedy v tomto případu se nastaví 1
BRGE VYMAZB
RJMP PRERUS0		;skočí se zpět do přerušení a čeká se buď na programový režim nebo na návrat do stávajícího programu


VYBER:			;návěští pro výběr programového režimu
SBIS PIND,0		;ošetření zákmitu
RJMP VYBER		;velmi podobná smyčka jako u rychlosti
INC A
RCALL EEPROM_writeA
OUT PORT,A
CPI A,0b00000100
BRGE VYMAZA
RJMP VYBERA			; jediný rozdíl je v tom že skočí na návěští VYBERA

VYBERA:			; to znamená že bu´d můžeme zvolit jiný programový režim nebo tlačítkem PD1 spustit program
SBIS PIND,0
RJMP VYBER
RCALL USTAL ; ustal
SBIS PIND,0
RJMP VYBER

SBIS PIND,3		;při stisku PD1
RJMP VOLBA		;se skočí na návětší VOLBA
RCALL USTAL		; ustal
SBIS PIND,3
RJMP VOLBA
CPI A,0b00000100		;pokud A>3 tak se vynuluje
BRGE VYMAZA
RJMP VYBERA

VYMAZB:	;návětší pro vynulování B
SER REG
OUT PORT,REG
LDI B,1
OUT PORT,B
RJMP PRERUS0

VYMAZA:		;návětší pro vynulování A
SER REG
OUT PORT,REG
CLR A
RJMP VYBER



VOLBA:				;návětší pro VOLBu programu do něj se skočí při zmáčknutí PD1 
CPI A,0b00000001
BREQ CITAC
CPI A,0b00000010
BREQ SVETLA
CPI A,0b00000011
BREQ SVETLAINV


CITAC:				;návěští pro první program, čítač který čítá od 1 do 255 a poté od 255 do 1
RCALL ROZHODNI      ;zde se vyvolá návěští ROZDONI které rozhodne o rychlosti programu v závislosti na proměné B
CLR REG
	CITACINC:		
		INC REG					;přičtení 1
		BRBS 3,NAPLNENO			;pokud se v příznaku přetečení objeví 1 (Overflow Flag) tak se skočí na návěští NAPLN, jinými slovy objeví se 9 bit		
		OUT PORT, REG			;na PORTB posle obsah registru DDRB
		RCALL CEKEJ				;zavola podprogram CEKEJ
		RJMP CITACINC			;skoci na navesti CITACINC,neboli nekonečná smyčka dokud se neobjeví OF

	VYMAZANO:
		CLR REG				;pro jistotu se REG vymaže
		RJMP CITACINC

	NAPLNENO:
		SER REG				;pro jistotu se do REG nahrají samé jedničky
		RJMP CITACDEC
	
	
	CITACDEC:	
		DEC REG					;odečtení 1
		BRBS 3,VYMAZANO			;pokud se v příznaku přetečení objeví 1 (Overflow Flag) tak se skočí na návěští NAPLN, jinými slovy objeví se -1 bit
		OUT PORT, REG			;na PORTB posle obsah registru DDRB
		RCALL CEKEJ				;zavola podprogram CEKEJ
		RJMP CITACDEC			;skoci na navesti CITACDEC

SVETLA:						;návětší pro normální běh světel
RCALL ROZHODNI				;zde se vyvolá návěští ROZDONI které rozhodne o rychlosti programu v závislosti na proměné B
LDI REG,0b11111111 ;
OUT DDR, REG ; aktivuj výstupy
CLC ; 0 do C

SMYCKA: 
OUT PORT, REG	; pošli
RCALL CEKEJ		; počkej 0,5 s
ROR REG				; posuň,ROR funguje tak že dělá mocninu dvou např 0010 po použí ROR vypadá 0001
BRCC SMYCKA3		; když je Carry Flag = 0 skočí se do SMYCKY3
BRCS SMYCKA			;pokud ale je CF=1 opakuje se režim s ROR

SMYCKA3:			; posuneme z okraje hodnotu
ROL REG
RJMP SMYCKA2
SMYCKA1:			; posuneme z okraje hodnotu
ROR REG
RJMP SMYCKA

SMYCKA2:				;stejný režim jako SMYCKA ale na druhou stranu
	OUT PORT, REG		;posli
	RCALL CEKEJ			;pockej cca 0,5s
	ROL REG				;posun
	BRCC SMYCKA1
	BRCS SMYCKA2

SVETLAINV:			; běh inverzního zobrazení světel
RCALL ROZHODNI		; znovu se vyvolá podprogram ROZHODNI a nastaví se rychlost
LDI REG,0b10000000	; jedna LED je zhasnutá ostatní jsou rozsvícený , při 0 je LED rozsvícená je zde opačná logika
CLC					;vymaže se příznak C
RJMP SMYCKA4
SMYCKA4:			;znovu skoro identické jako s normáním během
	OUT PORT, REG	;posli	
	RCALL CEKEJ		;pockej cca 0,5s	
	ROR REG			;posun
	BRCC SMYCKA4		; jediná vyjímka je zde kde se je Carry flag=0 až do konce běhu až poté se nastaví na 1 
	BRCS POSUN3			; a můžeme skočit do smyčky která ledky roluje na druhou stranu

POSUN3:
	ROL REG
	RJMP SMYCKA5
POSUN4:
	ROR REG
	RJMP SMYCKA4

SMYCKA5:			;identické jako předchozí
	OUT PORT, REG	;posli
	RCALL CEKEJ		;pockej cca 0,5s
	ROL REG			;posun
	BRCC SMYCKA5
	BRCS POSUN4
; čekací rutina čeká se podle toho jaká je hodnota v POM	
CEKEJ:	
	
	mov CITAC1,pom
	CLR CITAC2
	CLR CITAC3
	
CEKEJA:
	DEC CITAC3
	BRNE CEKEJA
	DEC CITAC2
	BRNE CEKEJA
	DEC CITAC1
	BRNE CEKEJA
	RET


USTAL:		;návětší pro Ustálení, velmi podobná funkce jako s Čekajícími smyčky prostě se decrementuje registr dokud v něm není 0
CLR CNT1	;CNT1=0
CLR CNT2	;CNT2=0
USTALS:
DEC CNT2		; sniž CNT2
BRNE USTALS		; test konec
DEC CNT1		 ; sniž CNT1
BRNE USTALS		; test konec
RET			; návrat

ROZHODNI:		;návětší pro ROZHODNutí která rychlost bude v čítači
CPI B,1
breq rych1
CPI B,2
breq rych2
CPI B,3
breq rych3
CPI B,4
breq rych4  ; Potřeba změni na BREQ po každém CPI 
CPI B,5
breq rych5
CPI B,6
breq rych6
CPI B,7
breq rych7
CPI B,8
breq rych8
CPI B,9
breq rych9
CPI B,10
breq rych10
rych1:
ldi pom,6
rjmp PRERUS0
rych2:
ldi pom,12
rjmp PRERUS0
rych3:
ldi pom,18
rjmp PRERUS0
rych4:
ldi pom,24
rjmp PRERUS0
rych5:
ldi pom,30
rjmp PRERUS0
rych6:
ldi pom,36
rjmp PRERUS0
rych7:
ldi pom,42
rjmp PRERUS0
rych8:
ldi pom,48
rjmp PRERUS0
rych9:
ldi pom,54
rjmp PRERUS0
rych10:
ldi pom,60
rjmp PRERUS0

EEPROM_writeA:
; Wait for completion of previous write
sbic EECR,EEWE
rjmp EEPROM_writeA
; Set up address (r18:r17) in address register
out EEARH, r18
out EEARL, r17
; Write data (r16) to data register
out EEDR,A
; Write logical one to EEMWE
sbi EECR,EEMWE
; Start eeprom write by setting EEWE
sbi EECR,EEWE
ret

EEPROM_readA:
; Wait for completion of previous write
sbic EECR,EEWE
rjmp EEPROM_readA
; Set up address (r18:r17) in address register
out EEARH, r18
out EEARL, r17
; Start eeprom read by writing EERE
sbi EECR,EERE
; Read data from data register
in A,EEDR
ret

EEPROM_writeB:
; Wait for completion of previous write
sbic EECR,EEWE
rjmp EEPROM_writeB
; Set up address (r18:r17) in address register
out EEARH, r18
out EEARL, r17
; Write data (r16) to data register
out EEDR,B
; Write logical one to EEMWE
sbi EECR,EEMWE
; Start eeprom write by setting EEWE
sbi EECR,EEWE
ret

EEPROM_readB:
; Wait for completion of previous write
sbic EECR,EEWE
rjmp EEPROM_readB
; Set up address (r18:r17) in address register
out EEARH, r18
out EEARL, r17
; Start eeprom read by writing EERE
sbi EECR,EERE
; Read data from data register
in B,EEDR
ret

Myslím, že jsi zcela správně nepochopil zadání programu. Nikde jsem se nedočetl, že bys měl program pozastavovat RESETem. Já jsem z toho pochopil, že spustíš efekt, ale na to, abys mohl změnit mód nebo rychlost efektu jej musíš pozastavit. Ukládání parametrů do EEPROM je tam jen kvůli resetu či vypnutí/zapnutí zařízení. Mimochodem - Tvoje verze přerušení INT0 je mírně řečeno nestandartní. KAŽDÁ obsluha přerušení musí být co možná nejkratší a ne, že v přerušení zůstaneš libovolně dlouho.