Před dalším dílem o klávesnici si musíme vysvětlit princip přerušení, k čemu slouží a jak jej využít.
Přerušení je okamžik, kdy Z80 dostane signál o tomto jevu, a zobrazovací obvody Spektra začnout vykreslovat na TV nový snímek obrazu podle obsahu videoram (16384-22527). Podle toho, jak je Z80 nastavena, se ještě něco vykoná. Můžeme Z80 nastavit na 2 chování:
1/ di
– disable interrupt, zákaz přerušení.
2/ ei
– enable interrupt, povolení přerušení.
Pokud je nastaveno di
, vždy se začne vykreslovat nový obraz, ale jinak si Z80 ničeho nevšímá.
Je-li ovšem nastaveno ei
, zachová se podle módu, který má nastaven. Jsou to tyto tři:
1/ im 0
– interrupt mode 0
2/ im 1
– interrupt mode 1
3/ im 2
– interrupt mode 2
im 0
se na ZXS nevyužívá, takže jen teoreticky: Z80 si přečte na datové sběrnici hodnotu a tu považuje za instrukci a tu provede. O žádné takové periférii nevím, která by toho využívala.
Je-li nastaven mód im 1
, při signálu přerušení se provede rst 56
(rst $38
). To je docela důležitý okamžik, právě tam se v ROM nachází rutina, která se stará o obsluhu klávesnice a hodin. Hodiny nás nezajímají, ale pro PeCaře: nejde o RTC. Pokud bude náš program využívat přerušení v módu im 1
, musí (minimálně v době přerušení) ukazovat registr iy do oblasti systémových proměnných Basicu (na hodnotu 23610) a ty musí být v pořádku, protože tam má rutina uloženy proměnné o autorepeatu a tam taky ukládá informaci o stištěné klávese.
S módem im 2
je to kapánek složitější. Při signálu přerušení Z80 přečte hodnotu z datové sběrnice a z ní udělá nižší bajt adresy. Z registru I udělá vyšší bajt adresy. Z této adresy vyzdvedne dvoubajtovou hodnotu coby další adresu a na tu skočí. Prostě něco jako CALL (ADRESA). Opět mi není známo o periférii, která by poslala na sběrnici nějakou hodnotu, ale tento mód přerušení se na spektru dá využít.
Několik pravidel, která se prerušení týkají:
Přijde-li signál přerušení, právě prováděná instrukce se dokončí. A to i ta, která je vícebajtová a prefixovaná.
V případě im 0 a im 1 im2 se nelze spoléhat na to, že na sběrnici se většinou hodnota $FF. Třeba D80 občas nastavuje nějaká nesmyslná numera.
Procesor při skoku do přerušení uloží na zásobník hodnotu následující instrukce, kterou má pokračovat a nastaví di
. Proto při návartu z přerušení použijeme sekvenci instrukcí ei , ret
nebo ei , reti
. Instrukce reti
má na ZXS stejný význam jako ret
.
cpu z80undoc relaxed on org 25000 START di ;nejprve zakaz preruseni ld a,$FD ;nastav vektor preruseni ld i,a ;to bude horni byte adresy cele tabulky im 2 ;nastav im 2 ei ;a povol prerusovani ;nasleduje hlavni provadeci smycka LOOP1 ld a,(VAR1) ;ktera cyklicky meni barvu atributu dec a ;kazdych 25/50 sekundy ld (VAR1),a jr nz,WAIT1 ld a,(22528) add a,8 and %111000 ld (22528),a ld a,25 ld (VAR1),a WAIT1 halt call 8020 ;dokud se nestiskne BREAK jr c,LOOP1 im 1 ;pak se nastavi normalni mod ret ;a vrati se do BASICu PRERUSENI ;smycka, ktera bezi pod prerusenim push af ;uloz registr, ktery se v prubehu meni ld a,(VAR2) ;je to podobna smycka dec a ;akorat ze barvu meni kazdych ld (VAR2),a ;50/50 sekundy (kazdou sekundu) jr nz,WAIT2 ;ale jiny atribut ld a,(22529) add a,8 and %111000 ld (22529),a ld a,50 ld (VAR2),a WAIT2 pop af ;vyzvedni registr ei ;a vrat se z preruseni do hlavni smycky ret VAR1 db 25 VAR2 db 50 org $FD00 ;na adrese $FD00 (registr i=$FD) db 257 dup ($FE) ;tabulka, ktera obsahuje 257krat hodnotu $FE org $FEFE ;a na adrese $FEFE jp PRERUSENI ;to hupsne do smycky c.2
A jak to vlastně celé funguje? Protože registr I má hodnotu $FD celá tabulka musí být na adrese s vyšším bajtem $FD. Musí být dlouhá 257 bajtů, protože když bude na sběrnici $FF bude se adresa skoku brát z adresy $FDFF a $FE00. Celá tabulka je vyplněna hodnotou $FE, takže vybraná adresa bude vždy $FEFE a tam se již nachází instrukce jp PRERUSENI
. Hlavní smyčka je LOOP1 a ta je vždy 1/50 sekundy přerušena při čekání halt
na signál přerušení. Tam to skočí do druhé smyčky PRERUSENI a ta skončí návratem z přerušení zpět do hlavní. Složité, ale užitečné hlavně v demech, kdy je druhá smyčka tvořena přehráváním hudby a hlavní smyčka se věnuje vlastnímu demu.
Toto vše se nazývá Maskovatelné přerušení.
Existuje ještě Nemaskovatelné přerušení (NMI), které není možné zakázat. To většinou nastane po stisku hardwarového tlačítka. To způsobí uložení návratové adresy (registru PC) a nastavení di
a skoku na adresu $66 (102). Vůbec nezáleží na povoleném/zakázaném přerušení. V ROM ZX je „úmyslně“ udělaná chyba, tuto chybu odstranili ve Skalici v Didaktiku Gama. Návrat z nemaskovatelného přerušní by mělo být instrukcí retn
. Tato instrukce nastaví zpět ei
nebo di
takové, jaké bylo.
Toto hardwarové tlačítko mají zařízení divIDE, D80 a MB02+. V ZXM se objevovali návody na výrobu generátoru signálu NMI, které současně s úpravou ROM a nahrání software do paměti způsobilo při stisku skok do paměťového monitoru. V D80 slouží k pořízení SNAPu, v divIDE na ovladání případného OS a v MB02+ taky.
Domácí úkol: Udělejte domácí úkol ze 4.dílu 🙂
Příště: Klávesnice.
9 komentáre na “5.díl: Módy přerušení”
Je nám líto, ale formulář pro přidávání komentářů je momentálně uzavřen.
hodne zajimave cteni; konecne v tom zacinam mit jasno; hned jak se dostanu k ZX (Pec+Emul, zivot je boj), tak si neco s prerusenim zkusim… dik Sweete za dalsi dil
Neni zac. Sam jsem s ukazkovym programem zapasil. Mikezt ovsem nezklamal a pomohl.
Sweete,
super clanek, jen male info, jelikoz je pameti vzdycky malo, ja na inicializaci IM2 pouzivam tento postup (usetrim tim 3 byty, vlastne v podstate vice, nebot spousteci adresa je stejna jako adresa IM2 tabulky :).
org 32768
IM2
jp START
ds 254
START
di
ld hl,IM2TAB
ld de,IM2TAB+1
ld bc,256
ld (hl),INTERUPT/256
ldir
ld a,IM2/256
Kurna nejak se podelalo formatovani toho prispevku … tak sorry 🙁
Zajímací řešení. V našem zdrojáku ale generátor tabulky není, tabulka je již hotova. Takže my paměť ušetříme. Jediné, co neušetříme, je místo na CF, protože se to musí uložit včetně tabulky. Takže pokud bychom chtěli ušetřit pamět a prostor na disketě, tak tabulku vytvoříme již ve zdrojáku a celý produkt proženeme kompresí. Tím ušetříme paměť v běžícím programu a místo na harddisku.
Nemusime ani komprimovat 🙂 staci program trochu rozLDIRovat 🙂 ale to by jsme asi jiz sli na komara tankem 🙂
Navrat z preruseni pres RETN?
To je nejaka specialita Assu, nebo mi uz hrabe a blbe si to pamatuju?
Ja bych se totiz vracel z preruseni pres RETI.
Fakt ted nevim…
dex of MB-Maniax
Xor, jsem debil.
Ja si nevsiml, ze cumim do nemaskovatelneho preruseni.
Ale stejne jsem ted z toho zmaten ako lesna vcelka.
Reti je totež jako napsat ei a pak ret 😉 ale asi se tim ušetří nějakej ten bajt…