Rozdział 3
PRZERWANIA SYSTEMOWE
Komputery Atari posiadają bardzo rozbudowany system
przerwań, który stanowi jeden z najmocniejszych punktów systemu
operacyjnego. Część przerwań jest wykorzystywana bezpośrednio
przez OS, a niektóre są przeznaczone do zastosowania przez
programy użytkownika. Są też one najczęściej wykorzystywanym
przez programistów elementem systemu. Wszystkie występujące w
Atari przerwania można podzielić na dwie zasadnicze grupy:
przerwania niemaskowalne (NMI - Non Maskable Interrupt) i
maskowalne (IRQ - Interrupt ReQuest).
Zgłoszenie przerwania następuje na drodze sprzętowej
poprzez przekazanie do CPU sygnału żądania przerwania
odpowiednio po linii NMI lub IRQ szyny sterowania. Po
otrzymaniu żądania przerwania NMI procesor odkłada na stos
aktualną zawartość licznika programu i rejestru statusu oraz
wykonuje skok pod adres zawarty w rejestrze NMIVEC ($FFFA).
Przerwania NMI nie można zablokować i musi ono zostać wykonane.
Żądanie przerwania IRQ jest obsługiwane podobnie z dwiema
istotnymi różnicami. Najpierw sprawdzany jest bit I rejestru
statusu i gdy jest on ustawiony, to żądanie przerwania jest
ignorowane i procesor kontynuuje wykonywanie programu. Gdy bit
I jest skasowany, wykonywane są operacje jak przy NMI, a
następnie skok pod adres zawarty w rejestrze IRQVEC ($FFFE).
Dzięki zastosowaniu takiego sposobu postępowania przerwania IRQ
mogą być zablokowane (zamaskowane) przez ustawienie bitu I w
rejestrze statusu procesora.
Wypada dodać, że RESET jest także przerwaniem. Ma ono
najwyższy priorytet i zawsze musi być wykonane. Wektor
przerwania RESET (RESETVEC) jest umieszczony pod adresem $FFFC,
między wektorami NMIVEC i IRQVEC.
3.1. Procedury przerwań niemaskowalnych
Mimo, iż przerwanie niemaskowalne nie może zostać
zablokowane, to jednak istnieje możliwość jego zabronienia.
Wynika to z budowy wewnętrznej komputera. Żądanie przerwania
niemaskowalnego jest wysyłane do CPU przez procesor obrazowy
ANTIC. Może on wysłać sygnał żądania przerwania tylko wtedy,
gdy ustawiony jest bit 6 lub 7 w jego sprzętowym rejestrze
NMIEN (NMI ENable - $D40E).
Ustawienie bitu 6 zezwala na żądanie przerwania wywołanego
przez impuls synchronizacji pionowej obrazu (VBLKI - Vertical
BLanK Interrupt). Ustawienie bitu 7 zezwala na żądanie
przerwania wywołanego przez program ANTIC-a (DLI - Display List
Interrupt). Jednocześnie z żądaniem przerwania ANTIC ustawia
odpowiedni bit w rejestrze NMIST (NMI STatus) informującym o
źródle przerwania.
3.1.1. Procedura rozpoznania źródła przerwania
Po otrzymaniu sygnału żądania przerwania niemaskowalnego
procesor pobiera z rejestru NMIVEC (NMI VECtor) adres procedury
obsługi tego przerwania i przechodzi do jej wykonywania od
pobranego adresu. Adres ten wskazuje na procedurę NMIFIRST
($C018).
0100 ;NMI FIRST
0110 ;
0120 DLIV = $0200
0130 NMIST = $D40F
0140 VVBLKI = $0222
0150 ;
0160 *= $C018
0170 ;
0180 BIT NMIST
0190 BPL VBL
0200 JMP (DLIV)
0210 VBL CLD
0220 PHA
0230 TXA
0240 PHA
0250 TYA
0260 PHA
0270 STA NMIST
0280 JMP (VVBLKI)
W pierwszym kroku procedury sprawdzany jest najstarszy bit
rejestru NMIST. Jeżeli jest on ustawiony, to znaczy, że
przerwanie zostało wywołane przez program ANTIC-a i wykonywany
jest skok do adresu zawartego w rejestrze DLIV (DLI Vector).
Wskazywana przez ten rejestr procedura nie występuje w systemie
i musi być zaprogramowana przez użytkownika. Wektor DLIV
wskazuje więc normalnie rozkaz RTI.
Gdy bit 7 w NMIST jest skasowany, to znaczy, że chodzi o
przerwanie synchronizacji pionowej (Vertical BLanK Interrupt -
VBLKI). W takim przypadku kasowany jest tryb dziesiętny
procesora, zawartości jego rejestrów są odkładane na stos i
rejestr NMIST jest zerowany, aby umożliwić zasygnalizowanie
kolejnego przerwania. Następnie wykonywany jest skok do
procedury wskazywanej przez wektor VVBLKI (Vector VBLK
Immediate).
3.1.2. Struktura przerwania VBLK
Przerwanie synchronizacji pionowej podzielone jest na dwie
części. Każda z nich jest wskazywana przez wektor umieszczony w
pamięci RAM. Umożliwia to prostą ingerencję programisty w
przebieg przerwania. Schemat procedury jest następujący:
<VVBLKI>
|
v
+--------------+---------------+
| | |
| | ++----------------++
| ++--------++ ||"natychmiastowa"||
| || SYSVBL || || procedura VBLK ||
| ++--------++ || użytkownika ||
| | ++----------------++
| v |
v +<--------------+
++----------------++ |
|| "zastępcza" || v
|| procedura VBLK || <VVBLKD>
|| użytkownika || |
++----------------++ v
| +---------------+
| | |
| | v
| | ++----------------++
| | || "opóźniona" ||
| | || procedura VBLK ||
| | || użytkownika ||
| | ++----------------++
| v |
+------------->+<--------------+
|
v
++---------++
|| EXITVBL ||
++---------++
Z powyższego schematu widać, że użytkownik może wstawić
swoją procedurę zarówno przed ("natychmiastowa"), jak i po
("opóźniona") procedurze systemowej. Możliwe jest także
całkowite ominięcie procedury systemowej przez procedurę
użytkownika ("zastępcza"). W tym celu wystarczy jedynie zmienić
odpowiednie wektory. Istnieje tu jednak pewne
niebezpieczeństwo. Gdy przerwanie zostanie wywołane podczas
wykonywania tej zmiany, to system zawiesi się. Dla uniknięcia
takiej sytuacji OS zawiera specjalną procedurę SETVBLV, która
służy do zmian wektorów.
3.1.3. Systemowa procedura VBLKI
Podstawowym zadaniem procedury przerwania synchronizacji
pionowej jest odliczanie czasu i obsługa zegarów systemowych.
Przede wszystkim na początku procedury zwiększany jest stan
zegara czasu rzeczywistego RTCLOCK (Real Time CLOCK). W tej
fazie zwiększany jest także co 256 przerwań rejestr ATRACT i
wykonywana jest obsługa tzw. trybu przyciągania uwagi.
Tryb przyciągania uwagi (Attract Mode) jest specyficznym
pomysłem twórców Atari. Rejestr ATRACT jest zerowany przez
każde naciśnięcie klawisza. Jeżeli jednak osiągnie on wartość
$80 (trwa to 32768 cykli zegarowych, czyli 645,36 sekund), to
włączany jest tryb Attract. Rejestr ATRACT otrzymuje wartość
$FE, rejestr ATRMSK wartość $F6 (zamiast $FE), a rejestr COLRSH
wartość drugiego bajtu zegara RTCLOCK. Teraz wartość koloru
pobrana z rejestru-cienia jest poddawana operacji EOR z
zawartością COLRSH i AND z ATRMSK oraz zapisywana do rejestru
koloru. Powoduje to cykliczne zmiany kolorów na ekranie.
Następnie z wartością zero w rejestrze X wywoływana jest
procedura DECTIM w celu zmniejszenia stanu licznika systemowego
TIMCNT1 (TIMer CouNTer 1). Powrót z tej procedury z ustawionym
bitem Z w rejestrze statusu oznacza wyzerowanie licznika i
powoduje wywołanie poprzez skok do JMPTIM1 procedury od adresu
wskazanego przez wektor TIMVEC1 (TIMer VECtor 1).
Teraz sprawdzany jest znacznik CRITIC (CRITICal I/O). Jeśli
jego wartość jest różna od zera, oznacza to, że wykonywana jest
przez system operacja wejścia/wyjścia krytyczna czasowo. W
takim przypadku procedura przerwania VBLK jest kończona skokiem
bezpośrednio do procedury EXITVBL.
0100 ;SYStem Vertical 0370 JSTICK2 = $027A
0110 ;BLank interrupt 0380 JSTICK3 = $027B
0120 ; 0390 KBCODE = $D209
0130 ATRACT = $4D 0400 KBCODES = $02FC
0140 ATRMSK = $4E 0410 KEYDEL = $02F1
0150 CHACT = $02F3 0420 KEYDIS = $026D
0160 CHBAS = $02F4 0430 KEYREP = $02DA
0170 CHBASE = $D409 0440 LPENH = $D40C
0180 CHRCTL = $D401 0450 LPENHS = $0234
0190 COLPF1 = $D017 0460 LPENV = $D40D
0200 COLPF1S = $02C5 0470 LPENVS = $0235
0210 COLPM0 = $D012 0480 PADDL0 = $0270
0220 COLPM0S = $02C0 0490 PORTA = $D300
0230 COLRSH = $4F 0500 POT0 = $D200
0240 CONSOL = $D01F 0510 POTGO = $D20B
0250 CRITIC = $42 0520 PTRIG0 = $027C
0260 DECTIM = $C255 0530 PTRIG1 = $027D
0270 DLPTR = $D402 0540 RTCLOCK = $12
0280 DLPTRS = $0230 0550 SKSTAT = $D20F
0290 DMACTL = $D400 0560 SRTIMER = $022B
0300 DMACTLS = $022F 0570 STACK = $0100
0310 EXITVBL = $C28A 0580 TIMCNT1 = $0218
0320 GINTLK = $03FA 0590 TIMVEC1 = $0226
0330 GTIACTL = $D01B 0600 TIMVEC2 = $0228
0340 GTICTLS = $026F 0610 TRIG0 = $D010
0350 JSTICK0 = $0278 0620 TRIG0S = $0284
0360 JSTICK1 = $0279 0630 TRIG1 = $D011
0640 TRIG1S = $0285 1200 LDA VSFLAG
0650 TRIG2S = $0286 1210 BEQ NSC
0660 TRIG3 = $D013 1220 DEC VSFLAG
0670 TRIG3S = $0287 1230 LDA #$08
0680 VSCROL = $D405 1240 SEC
0690 VSFLAG = $026C 1250 SBC VSFLAG
0700 VVBLKD = $0224 1260 AND #$07
0710 ; 1270 STA VSCROL
0720 *= $C0DF 1280 NSC LDX #$08
0730 ; 1290 STX CONSOL
0740 WAIT JMP WAIT 1300 COL CLI
0750 SYSVBL INC RTCLOCK+2 1310 LDA COLPM0S,X
0760 BNE ATT 1320 EOR COLRSH
0770 INC ATRACT 1330 AND ATRMSK
0780 INC RTCLOCK+1 1340 STA COLPM0,X
0790 BNE ATT 1350 DEX
0800 INC RTCLOCK 1360 BPL COL
0810 ATT LDA #$FE 1370 LDA CHBAS
0820 LDX #$00 1380 STA CHBASE
0830 LDY ATRACT 1390 LDA CHACT
0840 BPL ATR 1400 STA CHRCTL
0850 STA ATRACT 1410 LDX #$02
0860 LDX RTCLOCK+1 1420 JSR DECTIM
0870 LDA #$F6 1430 BNE NTI2
0880 ATR STA ATRMSK 1440 JSR JMPTIM2
0890 STX COLRSH 1450 NTI2 LDX #$02
0900 LDA COLPF1S 1460 TIM INX
0910 EOR COLRSH 1470 INX
0920 AND ATRMSK 1480 LDA TIMCNT1,X
0930 STA COLPF1 1490 ORA TIMCNT1+1,X
0940 LDX #$00 1500 BEQ NTI3
0950 JSR DECTIM 1510 JSR DECTIM
0960 BNE NTI1 1520 STA TIMVEC1,X
0970 JSR JMPTIM1 1530 NTI3 CPX #$08
0980 NTI1 LDA CRITIC 1540 BNE TIM
0990 BNE IOC 1550 LDA SKSTAT
1000 TSX 1560 AND #$04
1010 LDA STACK+4,X 1570 BEQ NKY
1020 AND #$04 1580 LDA KEYDEL
1030 BEQ PHASE2 1590 BEQ NKY
1040 IOC JMP EXITVBL 1600 DEC KEYDEL
1050 PHASE2 LDA TRIG3 1610 NKY LDA SRTIMER
1060 CMP GINTLK 1620 BEQ JOY
1070 BNE WAIT 1630 LDA SKSTAT
1080 LDA LPENV 1640 AND #$04
1090 STA LPENVS 1650 BNE NOKEY
1100 LDA LPENH 1660 DEC SRTIMER
1110 STA LPENHS 1670 BNE JOY
1120 LDA DLPTRS+1 1680 LDA KEYDIS
1130 STA DLPTR+1 1690 BNE JOY
1140 LDA DLPTRS 1700 LDA KEYREP
1150 STA DLPTR 1710 STA SRTIMER
1160 LDA DMACTLS 1720 LDA KBCODE
1170 STA DMACTL 1730 CMP #$9F
1180 LDA GTICTLS 1740 BEQ JOY
1190 STA GTIACTL 1750 CMP #$83
1760 BEQ JOY 2040 STA TRIG1S
1770 CMP #$84 2050 STA TRIG3S
1780 BEQ JOY 2060 LDX #$03
1790 CMP #$94 2070 PAD LDA POT0,X
1800 BEQ JOY 2080 STA PADDL0,X
1810 AND #$3F 2090 STA PADDL0+4,X
1820 CMP #$11 2100 DEX
1830 BEQ JOY 2110 BPL PAD
1840 LDA KBCODE 2120 STA POTGO
1850 STA KBCODES 2130 LDX #$02
1860 JMP JOY 2140 LDY #$01
1870 NOKEY LDA #$00 2150 PDT LDA JSTICK0,Y
1880 STA SRTIMER 2160 LSR A
1890 JOY LDA PORTA 2170 LSR A
1900 LSR A 2180 LSR A
1910 LSR A 2190 STA PTRIG1,X
1920 LSR A 2200 STA PTRIG1+4,X
1930 LSR A 2210 LDA #$00
1940 STA JSTICK1 2220 ROL A
1950 STA JSTICK3 2230 STA PTRIG0,X
1960 LDA PORTA 2240 STA PTRIG0+4,X
1970 AND #$0F 2250 DEX
1980 STA JSTICK0 2260 DEX
1990 STA JSTICK2 2270 DEY
2000 LDA TRIG0 2280 BPL PDT
2010 STA TRIG0S 2290 JMP (VVBLKD)
2020 STA TRIG2S 2300 JMPTIM1 JMP (TIMVEC1)
2030 LDA TRIG1 2310 JMPTIM2 JMP (TIMVEC2)
Jeżeli nie ma ograniczenia czasowego, to wykonywana jest
druga faza procedury przerwania VBLK. Najpierw porównywane są
zawartości rejestrów TRIG3 i GINTLK. Gdy są one różne, to
znaczy, że został wyjęty lub włożont cartridge. Powoduje to
skok do procedury WAIT, której pełna nazwa - WAIT for RESET
(Czekaj na RESET) - dobrze wyjaśnia działanie: system zawiesza
się i oczekuje na naciśnięcie klawisza RESET.
W dalszej części procedury przerwania rejestry sprzętowe
układów komputera uaktualniane są według rejestrów-cieni. Teraz
następuje także zmniejszenie zawartości licznika przesuwu
pionowego obrazu VSFLAG i przepisanie jej do VSCROL.
Kolejny etap obejmuje czterokrotne wywołanie procedury
DECTIM w celu zmniejszenia stanu pozostałych liczników
systemowych. W przypadku wyzerowania licznika TIMCNT2 poprzez
JMPTIM2 wywoływana jest procedura użytkownika (normalnie nie
wykorzystywana przez OS). Wyzerowanie pozostałych liczników
jest jedynie sygnalizowane we wskaźnikach TIMFLG3-TIMFLG5
(TIMer FLaG).
Teraz wykonywana jest wstępna obsługa klawiatury. Jeśli
rejestr SKSTAT (Serial/Keyboard STATus) sygnalizuje naciśnięcie
klawisza, to zmniejszany jest licznik KEYDEL, który określa
czas pomiędzy kolejnymi odczytami klawiatury. Naciśnięcie
klawisza powoduje także zmniejszenie stanu licznika SRTIMER
(wykorzystywany przez POKEY) i sprawdzanie kodu klawisza. Gdy
nie jest to CTRL-1, HELP, CTRL-F1, CTRL-F2 ani CTRL-F4 (trzy
ostatnie kody dotyczą modelu 1200XL), to zostaje przepisany do
rejestru-cienia w pamięci RAM.
Ostatnią częścią procedury SYSVBL jest przepisanie
informacji z portów joysticków obsługiwanych przez układy I/O
do rejestrów RAM. Z układu PIA odczytywane jest położenie
joysticków, z układu POKEY położenie potencjometrów, a z GTIA -
stan przycisków w joystickach i potencjometrach. Stare modele
400/800 posiadały gniazda dla czterech joysticków lub ośmiu
potencjometrów, a modele XL/XE mają ich o połowę mniej.
Ponieważ niektóre starsze gry wymagają takiej ilości
manipulatorów jak w 400/800, to wartości dotyczące joysticków 0
i 1 są kopiowane do rejestrów joysticków 2 i 3. To samo dotyczy
potencjometrów (wartości z 0-3 są kopiowane do 4-7).
Procedura SYSVBL kończy się skokiem pod adres wskazywany
przez wektor VVBLKD (Vector VBLK Deferred). Normalnie wskazuje
on procedurę EXITVBL, lecz może być zmieniony przez użytkownika
(przy pomocy SETVBLV).
0100 ;EXIT Vertical BLank interrupt
0110 ;
0120 *= $C28A
0130 ;
0140 PLA
0150 TAY
0160 PLA
0170 TAX
0180 PLA
0190 RTI
Zakończenie przerwania synchronizacji pionowej odbywa się
poprzez procedurę EXITVBL. Jej jedynym zadaniem jest
odtworzenie ze stosu umieszczonych tam na początku procedury
obsługi przerwania rejestrów procesora. Po instrukcji RTI
procesor odtwarza jeszcze rejestr statusu i licznik programu,
co automatycznie powoduje kontynuowanie programu od miejsca, w
którym wystąpiło żądanie przerwania.
3.1.4. Procedury uzupełniające VBLKI
Podczas przerwania synchronizacji pięciokrotnie wywoływana
jest procedura DECTIM. Służy ona do zmniejszania liczników
systemowych TIMCNT1-5. Przed jej wywołaniem w rejestrze X musi
zostać umieszczony numer licznika zmniejszony o 1 i pomnożony
przez 2 ((licznik-1)*2), czyli indeks licznika liczony od
TIMCNT1.
0100 ;DECrement TIMer
0110 ;
0120 TIMCNT = $0218
0130 ;
0140 *= $C255
0150 ;
0160 LDY TIMCNT,X
0170 BNE DCL
0180 LDY TIMCNT+1,X
0190 BEQ DCL
0200 DEC TIMCNT+1,X
0210 DCL DEC TIMCNT,X
0220 BNE NOT0
0230 LDY TIMCNT+1,X
0240 BNE NOT0
0250 LDA #$00
0260 RTS
0270 NOT0 LDA #$FF
0280 RTS
Jeżeli zmniejszenie stanu licznika spowoduje jego
wyzerowanie, to przed opuszczeniem procedury do akumulatora
wpisywana jest wartość 0. W przeciwnym wypadku zawartością
akumulatora jest #$FF.
Wyzerowanie licznika TIMCNT1 lub TIMCNT2 powoduje wywołanie
procedury, której adres wskazuje wektor TIMVEC1 lub TIMVEC2.
Normalnie procedura licznika 2 jest niewykorzystana, natomiast
TIMEVEC1 wskazuje procedurę TIM1INT.
0100 ;TIMer 1 INTerrupt
0110 ;
0120 TIMFLG = $0317
0130 ;
0140 *= $EC11
0150 ;
0160 LDA #$00
0170 STA TIMFLG
0180 RTS
Procedura ta zeruje wskaźnik Timeout (czasu oczekiwania na
odpowiedź), co jest wykorzystywane podczas operacji
wejścia/wyjścia.
3.1.5. Ingerencja w procedurę VBLKI
Jak wspomniano wcześniej zmiana procedury synchronizacji
pionowej jest bardzo prosta. Własną procedurę użytkownik może
umieścić w dowolnym miejscu procedury systemowej lub też
zamiast niej. Dostęp systemu do procedury użytkownika uzyskuje
się przez zmianę wektorów VVBLKI i/lub VVBLKD. Służy do tego
procedura SETVBLV.
Wymaga ona przed wywołaniem umieszczenia w rejestrze X
starszego bajtu wektora, w rejestrze Y młodszego bajtu wektora
i w akumulatorze numeru zmienianego wektora. Numery wektorów są
następujące:
0 - VIMIRQ
1 - TIMCNT1
2 - TIMCNT2
3 - TIMCNT3
4 - TIMCNT4
5 - TIMCNT5
6 - VVBLKI
7 - VVBLKD
8 - TIMVEC1
9 - TIMVEC2
Wymienione powyżej rejestry TIMCNT są licznikami
zliczającymi wstecz (do zera) i zamiast wektora należy podać
dla nich wartość początkową.
0100 ;SET Vertical BLank
0110 ;interrupt Vectors
0120 ;
0130 INTEMP = $022D
0140 VIMIRQ = $0216
0150 WSYNC = $D40A
0160 ;
0170 *= $C272
0180 ;
0190 ASL A
0200 STA INTEMP
0210 TXA
0220 LDX #$05
0230 STA WSYNC
0240 LOOP DEX
0250 BNE LOOP
0260 LDX INTEMP
0270 STA VIMIRQ+1,X
0280 TYA
0290 STA VIMIRQ,X
0300 RTS
A oto opis działania SETVBLV. Najpierw numer wektora
mnożony jest przez 2 (adresy są dwubajtowe) i odkładany
tymczasowo do INTEMP, a do akumulatora przepisywana jest
zawartość rejestru X. Po wpisaniu dowolnej wartości do rejestru
WSYNC (Wait for SYNChronisation) następuje zatrzymanie
procesora, aż do impulsu synchronizacji pionowej. Następnie, po
odliczeniu czasu potrzebnego na wykonanie przez ANTIC operacji
tworzenia linii obrazu, do rejestru określonego wartością
pobraną z INTEMP (indeks od VIMIRQ) wpisywany jest starszy bajt
z akumulatora i młodszy z rejestru Y. Procedura kończy się
zwykłym rozkazem RTS.
3.1.6. Procedura przerwania DL
Mimo, iż system operacyjny nie korzysta z przerwań
wywoływanych przez program ANTIC-a (Display List Interrupt), to
w pamięci ROM znajduje się procedura tego przerwania. Służy ona
do obsługi delikatnego przesuwu obrazu. Przesuw delikatny
polega na pionowym przemieszczaniu obrazu o jedną linię
ekranową. Dla przesunięcia o jeden wiersz (linię obrazu) w
trybie GRAPHICS 0 trzeba wykonać osiem przesunięć o linię
ekranu.
0100 ;Fine Scroll Display List
0110 ;
0120 ATRMSK = $4E
0130 COLPF1 = $D017
0140 COLPF2S = $02C6
0150 COLRSH = $4F
0160 WSYNC = $D40A
0170 ;
0180 *= $FCC4
0190 ;
0200 PHA
0210 LDA COLPF2S
0220 EOR COLRSH
0230 AND ATRMSK
0240 STA WSYNC
0250 STA COLPF1
0260 PLA
0270 RTI
Procedura ta jest wywoływana przed wyświetleniem ostatniej
linii obrazu i powoduje zmianę koloru tej linii tak, aby nie
była widoczna jej zawartość. Ma to na celu ukrycie dodatkowej,
ostatniej linii podczas przesuwania obrazu.
3.2. Procedury przerwań maskowalnych
Żądanie przerwania maskowalnego IRQ powoduje (po zapisaniu
na stos licznika programu i rejestru statusu) skok pod adres
wskazany przez wektor IRQVEC ($FFFE). Wektor ten zawiera adres
procedury JMPIRQV ($C02C).
0100 ;JuMP IRQ Vector
0110 ;
0120 VIMIRQ = $0216
0130 ;
0140 *= $C02C
0150 ;
0160 CLD
0170 JMP (VIMIRQ)
Ta króciutka procedura została dodana w modelach XL/XE,
ponieważ wcześniejsze modele 400/800 robiły "dziwne" rzeczy
podczas przerwań. Brakowało tam po prostu instrukcji CLD, która
wyłącza dziesiętny tryb pracy procesora. Teraz po skasowaniu
trybu dziesiętnego następuje skok do głównej procedury
przerwania IRQ wskazywanej przez wektor VIMIRQ (Vector
IMmediate IRQ).
3.2.1. Procedura rozpoznania źródła przerwania
Do rozpoznania źródła sygnału żądania przerwania
wykorzystywany jest przede wszystkim rejestr IRQST (IRQ
STatus), którego każdy bit odpowiada jednemu z możliwych źródeł
przerwania. Normalnie wszystkie bity tego rejestru są
ustawione. Sygnał żądania przerwania powoduje (na drodze
sprzętowej) skasowanie bitu odpowiadającego źródłu tego
sygnału. Przyporządkowanie bitów rejestru IRQST jest
następujące:
0 - przerwanie zegara TIMER1
1 - przerwanie zegara TIMER2
2 - przerwanie zegara TIMER4
3 - przerwanie końca transmisji
4 - przerwanie zapisu szeregowego
5 - przerwanie odczytu szeregowego
6 - przerwanie klawiatury
7 - przerwanie klawisza BREAK
Analogiczne przyporządkowanie mają bity rejestru IRQEN (IRQ
ENable). Skasowanie bitu w tym rejestrze powoduje zabronienie
odpowiadającego mu przerwania IRQ.
Rozpoznanie źródła przerwania IRQ wykonuje procedura
SINRDYI. Wiele z jej odgałęzień jest aktualnie nie
wykorzystane. Są one przewidziane dla przyszłych rozszerzeń
systemu lub zastosowania przez użytkownika.
W procedurze SINRDYI można zauważyć jedną z niewielu
niekonsekwencji systemu. W jej środku jest wstawiona procedura
BREAKIRQ, która nie ma żadnego związku z SINRDYI i musi być
ominięta.
0100 ;Serial INput ReaDY Irq
0110 ;
0120 DLIV = $0200
0130 IRQENS = $10
0140 IRQST = $D20E
0150 KEYDIS = $026D
0160 NEWIOP = $028C
0170 PACTL = $D302
0180 PBCTL = $D303
0190 PDVREG = $D1FF
0200 PINTMSK = $0249
0210 PORTA = $D300
0220 PORTB = $D301
0230 VBREAK = $0206
0240 VINTER = $0204
0250 VPIRQ = $0238
0260 VPRCED = $0202
0270 VSERIN = $020A
0280 ;
0290 *= $C030
0300 ;
0310 PHA
0320 LDA IRQST
0330 AND #$20
0340 BNE PDV
0350 LDA #$DF
0360 STA IRQST
0370 LDA IRQENS
0380 STA IRQST
0390 JMP (VSERIN)
0400 PDV TXA
0410 PHA
0420 LDA PDVREG
0430 AND PINTMSK
0440 BEQ MSK
0450 JMP (VPIRQ)
0460 MSK LDX #$06
0470 LOOP LDA MASKTAB,X
0480 CPX #$05
0490 BNE BPS1
0500 AND IRQENS
0510 BEQ BPS2
0520 BPS1 BIT IRQST
0530 BEQ FIN
0540 BPS2 DEX
0550 BPL LOOP
0560 JMP PRC
0570 FIN EOR #$FF
0580 STA IRQST
0590 LDA IRQENS
0600 STA IRQST
0610 CPX #$00
0620 BNE NEW
0630 LDA KEYDIS
0640 BNE PRC
0650 NEW LDA VECTAB,X
0660 TAX
0670 LDA DLIV,X
0680 STA NEWIOP
0690 LDA DLIV+1,X
0700 STA NEWIOP+1
0710 PLA
0720 TAX
0730 JMP (NEWIOP)
0740 ;
0750 *= $C0A0
0760 ;
0770 PRC PLA
0780 TAX
0790 BIT PACTL
0800 BPL INT
0810 LDA PORTA
0820 JMP (VPRCED)
0830 INT BIT PBCTL
0840 BPL BRK
0850 LDA PORTB
0860 JMP (VINTER)
0870 BRK PLA
0880 STA NEWIOP
0890 PLA
0900 PHA
0910 AND #$10
0920 BEQ EXIT
0930 LDA NEWIOP
0940 PHA
0950 JMP (VBREAK)
0960 EXIT LDA NEWIOP
0970 PHA
0980 PLARTI PLA
0990 RTI RTI
1000 ;
1010 ;MASK TABle
1020 ;
1030 MASKTAB .BYTE $80,$40,$04,$02
1040 .BYTE $01,$08,$10,$20
1050 ;
1060 ;VECtor TABle
1070 ;
1080 VECTAB .BYTE $36,$08,$14,$12
1090 .BYTE $10,$0E,$0C,$0A
W pierwszej kolejności sprawdzany jest bit 5 IRQST, który
sygnalizuje zapełnienie rejestru wejściowego i konieczność
odczytania z niego danych. Gdy bit 5 jest skasowany, sterowanie
zostaje przekazane do procedury ISRSIR.
Następnie przez porównywanie poszczególnych bitów w
rejestrach PDVREG i PINTMSK (Parallel INTerrupt MaSK)
sprawdzane jest, czy źródłem żądania przerwania jest nowe
urządzenie dołączone do szyny równoległej. Jeśli tak, to
wykonywany jest skok do procedury obsługi tego przerwania
wskazanej wektorem VPIRQ (Vector Parallel IRQ).
Teraz sprawdzane są pozostałe bity rejestru IRQST w
kolejności określonej przez maski bitowe z tabeli MASKTAB.
Kolejność ta wyznacza więc priorytet przerwań maskowalnych. Po
znalezieniu skasowanego bitu pozostałe są ustawiane, aby
zablokować przerwania o niższym priorytecie. Gdy przerwanie
zostało wywołane naciśnięciem klawisza (oprócz BREAK), to
sprawdzane jest jeszcze, czy rejestr KEYDIS (KEYboard DISable)
nie wskazuje zablokowania klawiatury.
Następnie według znalezionego źródła przerwania odszukiwany
jest w tabeli VECTAB indeks jego wektora. Wektor ten jest
umieszczany w rejestrze NEWIOP i wykonywany jest skok pod
zawarty tam adres. W ten sposób wywoływane są procedury ISRODN,
ISRXD, CPUIRQ i BREAKIRQ. Pozostałe trzy wektory procedur
obsługi przerwań wywołanych przez liczniki POKEY-a nie są
normalnie wykorzystywane przez OS. Wskazują one na sekwencję
rozkazów PLA, RTI i powodują powrót z przerwania.
Jeżeli do tej pory nie zostało znalezione źródło
przerwania, to sprawdzane są jeszcze porty układu PIA.
Stwierdzenie żądania przerwania przez port A powoduje skok pod
adres wskazany wektorem VPRCED (Vector PRoCEeD), a przez port B
- wektorem VINTER (Vector INTERrupt). Także te procedury nie są
używane przez system i przerwania kończy się sekwencją PLA,
RTI.
Na końcu kontrolowany jest bit B rejestru statusu procedora
sprzed przerwania (trzeba go więc pobrać ze stosu). Jeśli bit B
jest ustawiony, to znaczy, że przerwanie zostało wywołane
rozkazem BRK i następuje skok pod adres umieszczony w rejestrze
VBREAK (normalnie wskazuje on PLA, RTI - koniec przerwania).
Jeżeli nie zostało odnalezione żadne źródło przerwania, to
system operacyjny zakłada, że wystąpił jakiś błąd i kończy
procedurę przerwania.
3.2.2. Przerwanie odczytu z szyny szeregowej
Kontrolujący komunikację z urządzeniami zewnętrznymi
poprzez szynę szeregową układ POKEY jest głównym źródłem
przerwań maskowalnych. Jednocześnie z sygnałem żądania
przerwania kasuje on odpowiedni bit rejestru IRQST, aby wskazać
systemowi operacyjnemu konkretną przyczynę przerwania.
Najwyższy priorytet ma przerwanie wywoływane przez POKEY,
gdy w rejestrze SERIN (SERial INput) pojawi się bajt danych z
urządzenia zewnętrznego. Kasowany jest wtedy bit 5 rejestru
IRQST i procedura SINRDYI po rozpoznaniu źródła przerwania
wywołuje procedurę ISRSIR
0100 ;Interrupt Service Routine
0110 ;at Serial Input Ready
0120 ;
0130 BUFEN = $34
0140 BUFR = $32
0150 BUFRFL = $38
0160 CHKSUM = $31
0170 NOCKSM = $3C
0180 RECVND = $39
0190 SERIN = $D20D
0200 SKSTAT = $D20F
0210 SKSTRES = $D20A
0220 STATUS = $30
0230 ;
0240 *= $EB2E
0250 ;
0260 LDA SKSTAT
0270 STA SKSTRES
0280 BMI NER1
0290 LDY #$8C
0300 STY STATUS
0310 NER1 AND #$20
0320 BNE NER2
0330 LDY #$8E
0340 STY STATUS
0350 NER2 LDA BUFRFL
0360 BEQ EMPTY
0370 LDA SERIN
0380 CMP CHKSUM
0390 BEQ END
0400 LDY #$8F
0410 STY STATUS
0420 END LDA #$FF
0430 STA RECVND
0440 EXIT PLA
0450 TAY
0460 PLA
0470 RTI
0480 EMPTY LDA SERIN
0490 LDY #$00
0500 STA (BUFR),Y
0510 CLC
0520 ADC CHKSUM
0530 ADC #$00
0540 STA CHKSUM
0550 INC BUFR
0560 BNE BPS
0570 INC BUFR+1
0580 BPS LDA BUFR
0590 CMP BUFEN
0600 LDA BUFR+1
0610 SBC BUFEN+1
0620 BCC EXIT
0630 LDA NOCKSM
0640 BEQ CKS
0650 LDA #$00
0660 STA NOCKSM
0670 BEQ END
0680 CKS LDA #$FF
0690 STA BUFRFL
0700 BNE EXIT
Procedura ISRSIR najpierw sprawdza rejestr statusu złącza
szeregowego i klawiatury SKSTAT. Poszczególne bity tego
rejestru sygnalizują prawidłowość operacji odczytu. Gdy
ustawiony jest bit 7, to znaczy, że odczytano zbyt mało lub
zbyt dużo bitów. Powoduje to wpisanie do rejestru STATUS kodu
błędu $8C (tzw. Framing Error). Ustawienie bitu 5 oznacza
przepełnienie bufora i powoduje sygnalizowanie błędu o kodzie
$8E (SIO Overrun).
Następnie sprawdzany jest znacznik zapełnienia bufora
wejściowego, w którym wartość różna od zera oznacza pełny
bufor. W takim przypadku odebrany bajt danych traktowany jest
jako suma kontrolna i porównywany z zawartością rejestru
CHKSUM. Gdy są one różne, to sygnalizowany jest błąd sumy
kontrolnej (kod $8F). Przed końcem procedury wskaźnik
zakończenia transmisji RECVND (RECeiVe eND) jest jeszcze
ustawiany na wartość $FF.
Jeśli bufor wejściowy nie został jeszcze zapełniony, to
bajt z rejestru wejściowego SERIN zostaje umieszczony w buforze
i adres bufora (BUFR - BUFfeR) zwiększa się o jeden. Teraz
następuje porównanie tego adresu z adresem końca bufora (BUFEN
- BUFfer ENd). Gdy są one różne, procedura się kończy. W
przeciwnym razie sprawdzany jest znacznik NOCKSM (NO ChecK
SuM). Jego zawartość równa zero oznacza, że po danych nastąpi
suma kontrolna. Wskaźnik zapełnienia bufora ustawiany jest więc
na wartość $FF i procedura się kończy. Jeżeli wskaźnik NOCKSM
ma wartość różną od zera, to znaczy, że nie będzie sumy
kontrolnej. W tym przypadku przed zakończeniem przerwania
wskaźnik RECVND otrzymuje wartość $FF, a NOCKSM - wartość zero.
3.2.3. Przerwanie zapisu na szynę szeregową.
Stwierdzenie przez procedurę SINDRYI skasowania bitu 4
rejestru IRQST oznacza, że rejestr wyjściowy SEROUT został
opróżniony i konieczne jest umieszczenie w nim następnego bajtu
do zapisu na urządzeniu zewnętrznym. Wywoływana jest w tym celu
procedura ISRODN.
0100 ;Interrupt Service Routine
0110 ;if Output Data Needed
0120 ;
0130 BUFEN = $34
0140 BUFR = $32
0150 CHKSNT = $3B
0160 CHKSUM = $31
0170 IRQEN = $D20E
0180 IRQEND = $10
0190 SEROUT = $D20D
0200 ;
0210 *= EAAD
0220 ;
0230 TYA
0240 PHA
0250 INC BUFR
0260 BNE BPS
0270 INC BUFR+1
0280 BPS LDA BUFR
0290 CMP BUFEN
0300 LDA BUFR+1
0310 SBC BUFEN+1
0320 BCC CONT
0330 LDA CHKSNT
0340 BNE SEND
0350 LDA CHKSUM
0360 STA SEROUT
0370 LDA #$FF
0380 STA CHKSNT
0390 BNE EXIT
0400 SEND LDA IRQENS
0410 ORA #$08
0420 STA IRQENS
0430 STA IRQEN
0440 EXIT PLA
0450 TAY
0460 PLA
0470 RTI
0480 CONT LDY #$00
0490 LDA (BUFR),Y
0500 STA SEROUT
0510 CLC
0520 ADC CHKSUM
0530 ADC #$00
0540 STA CHKSUM
0550 JMP EXIT
Na początku procedury adres bufora wyjściowego jest
zwiększany o jeden i porównywany z adresem końca bufora. Jeżeli
są one różne, to bajt danych z bufora jest przesyłany do
rejestru SEROUT (SERial OUTput) oraz dodawany do zawartości
rejestru CHKSUM.
Gdy cały bufor został opróżniony, to sprawdzany jest
wskaźnik CHKSNT (CHecK sum SeNT). Jeśli jest równy zero, to do
rejestru SEROUT przepisywana jest suma kontrolna z rejestru
CHKSUM i znacznik CHKSNT otrzymuje wartość $FF.
Jeżeli CHKSNT wa wartość $FF, to znaczy, że suma kontrolna
nie będzie wysyłana i bit 3 rejestru IRQEN jest ustawiany, co
zezwala na wywołanie przerwania przez koniec transmisji.
3.2.4. Przerwanie końca transmisji szeregowej.
0100 ;Interrupt Service Routine
0110 ;if eXmitend Data
0120 ;
0130 CHKSNT = $3B
0140 IRQEN = $D20E
0150 IRQENS = $10
0160 XMTDON = $3A
0170 ;
0180 *= $EAEC
0190 ;
0200 LDA CHKSNT
0210 BEQ EXIT
0220 STA XMTDON
0230 LDA IRQENS
0240 AND #$F7
0250 STA IRQENS
0260 STA IRQEN
0270 EXIT PLA
0280 RTI
Skasowanie bitu 3 w rejestrze IRQST sygnalizuje zakończenie
transmisji szeregowej i powoduje wywołanie z SINDRYI procedury
ISRXD.
Najpierw badany jest wskaźnik CHKSNT. Jeśli jest równy 0,
to suma kontrolna nie była wysłana i procedura się kończy. W
przeciwnym razie CHKSNT jest przepisywany do wskaźnika XMTDON
(eXMiTe DONe) sygnalizującego zakończenie transmisji i w
rejestrze IRQEN kasowany jest bit zezwolenia na przerwanie
końca transmisji (bit 3).
3.2.5. Przerwanie klawiatury
Naciśnięcie dowolnego klawisza (oprócz BREAK) powoduje
skasowanie bitu 6 rejestru IRQST. Procedura SINDRYI po
rozpoznaniu źródła przerwania wywołuje wtedy procedurę CPUIRQ,
której zadaniem jest odczyt naciśniętego klawisza.
< CPU IRQ >
|
v
nie /-------------\ tak
+--------< KBCODE=OLDKBC >-------+
| \-------------/ |
| v
v tak /--------\
+<-------------------------< KEYDEL=0 >
| \--------/
v nie |
/----------\ nie v
< KBCODE=$83 >---------------+ < RPT >
\----------/ |
| tak v
v /--------\ nie
+----------------+ < KEYDIS=0 >---------+
| KEYDIS EOR $FF | \--------/ |
+----------------+ tak | v
| v < EXIT >
v /----------\ tak
nie /--------\ tak < KBCODE=$9F >---+
+-< KEYDIS=0 >-+ \----------/ |
| \--------/ | nie | v
v v | +----------------+
+------------+ +------------+ | | SSFLAG EOR $FF |
| PB AND $FB | | PB ORA $04 | | +----------------+
+------------+ +------------+ | |
| | | v
+----->+<------+ | < CONT >
| v
v nie /--------------------\ tak
< CONT > +-< (KBCODE AND $3F)=$11 >-+
| \--------------------/ |
| |
v v
tak /----------\ nie +------------------+
+--< KBCODE=$84 >---+ | KBCODE -> HLPFLG |
| \----------/ | +------------------+
v v |
tak /---------\ /----------\ nie v
+------< DMACTLS=0 > < KBCODE=$94 >--+ < CONT >
| \---------/ \----------/ |
| | tak | +--------+
| | v |
| v +------------------+ |
| +-------------------+ | CHBAS <=> CHSPTR | |
| | DMACTLS -> DMASAV | +------------------+ |
| +-------------------+ | |
| | v |
| v tak /---------\ nie |
| +-----------+ +-< CHBAS=$CC >-+ |
| | DMACTLS=0 | | \---------/ | |
| +-----------+ | | |
| | v v |
| v +------------+ +------------+ |
+----------->+ | PB AND $F7 | | PB ORA $08 | |
| +------------+ +------------+ |
| | | |
| +------>+<------+ +----+
| | |
| | v
| | +-------------------+
| | | KBCODE -> KBCODES |
| | | KBCODE -> OLDKBC |
| < CONT > | +-------------------+
| | v |
| +--------->+<------------+
| |
| v
| +------------+
| | KEYDEL=$03 |
| | ATRACT=$00 |
| +------------+ < RPT >
| | |
| v |
| +<------------+
| |
| |
| v
| +-------------------+
| | KRPDEL -> SRTIMER |
| +-------------------+
| |
| v
| nie /---------\
+<------------< DMACTLS=0 >
| \---------/
| | tak
| v
| +------------------+
| | DMASAV -> DMACTL | < EXIT >
| +------------------+ |
| | |
| V |
+------------------>+<-----------------+
|
V
< koniec przerwania >
Należy zwrócić uwagę, że znaczna część wykonywanych w tej
procedurze czynności dotyczy wyłącznie modelu 1200XL
posiadającego klawisze funkcyjne od F1 do F4. Poprzez
przedefiniowanie klawiszy można jednak zaimplementować te
funkcje w pozostałych modelach serii XL i XE.
Procedura CPUIRQ rozpoczyna się od porównania kodu
naciśniętego klawisza pobranego z rejestru KBCODE (KeyBoard
CODE) z kodem zapisanym w rejestrze OLDKBC (OLD KeyBoard Code)
podczas poprzedniego przerwania. Jeżeli są takie same, to
znaczy, że naciśnięty jest ten sam klawisz. Wtedy sprawdzany
jest rejestr KEYDEL (KEYboard DELay) określający czas między
dwoma naciśnięciami klawiszy. Gdy jest on różny od zera, to
następuje skok do końcowej fazy procedury.
Jeśli został naciśnięty inny klawisz niż poprzednio lub
upłynął czas między dwoma odczytami, to kolejno sprawdzane są
specjalne kombinacje klawiszy. Odczytany kod klawisza równy $83
oznacza naciśnięcie CONTROL-F1. Kombinacja ta służy do
włączania i wyłączania klawiatury (w 1200XL), więc na
zawartości rejestru KEYDIS dokonywana jest operacja EOR $FF, co
powoduje przełączenie klawiatury (KEYDIS=0 - klawiatura
włączona, KEYDIS=$FF - wyłączona). Następnie jest ustawiany lub
kasowany bit 3 rejestru PORTB, który w modelu 1200XL steruje
diodą LED 1 sygnalizującą zablokowanie klawiatury. Po
zablokowaniu klawiatury procedura się kończy.
Jako druga sprawdzana jest kombinacja klawiszy CONTROL-1,
która zatrzymuje i wznawia przesuw pionowy obrazu (scrolling).
Rozpoznanie tej kombinacji (kod $9F) powoduje przełączenie -
poprzez EOR $FF - zawartości rejestru SSFLAG (Start/Stop FLAG).
Normalnie w rejestrze tym znajduje się wartość 0. Naciśnięcie
CONTROL-1 zmienia ją na $FF i powoduje zatrzymanie
wyprowadzania danych na ekran. Kolejne naciśnięcie CONTROL-1
przywraca poprzednią sytuację.
0100 ;CPU Interrupt ReQuest
0110 ;
0120 ATRACT = $4D
0130 CHBAS = $02F4
0140 CHSPTR = $026B
0150 DMACTLS = $022F
0160 DMASAV = $02DD
0170 HLPFLG = $02DC
0180 KBCODE = $D209
0190 KBCODES = $02FC
0200 KEYDEL = $02F1
0210 KEYDIS = $026D
0220 KRPDEL = $02D9
0230 OLDKBC = $02F2
0240 PORTB = $D301
0250 SRTIMER = $022B
0260 SSFLAG = $02FF
0270 ;
0280 *= $FC19
0290 ;
0300 TXA
0310 PHA
0320 TYA
0330 PHA
0340 LDY PORTB
0350 LDA KBCODE
0360 CMP OLDKBC
0370 BNE NKY
0380 LDX KEYDEL
0390 BNE RPT
0400 NKY LDX KEYDIS
0410 CMP #$83
0420 BNE NKB
0430 TXA
0440 EOR #$FF
0450 STA KEYDIS
0460 BNE KBEN
0470 TYA
0480 ORA #$04
0490 BNE KEND
0500 KBEN TYA
0510 AND #$FB
0520 KEND TAY
0530 BCS CONT
0540 NKB TXA
0550 BNE EXIT
0560 LDA KBCODE
0570 TAX
0580 CMP #$9F
0590 BNE NC1
0600 LDA SSFLAG
0610 EOR #$FF
0620 STA SSFLAG
0630 BCS CONT
0640 NC1 AND #$3F
0650 CMP #$11
0660 BNE FKY
0670 STX HLPFLG
0680 BEQ CONT
0690 STORE STX KBCODES
0700 STX OLDKBC
0710 CONT LDA #$03
0720 STA KEYDEL
0730 LDA #$00
0740 STA ATRACT
0750 RPT LDA KRPDEL
0760 STA SRTIMER
0770 LDA DMACTLS
0780 BNE EXIT
0790 LDA DMASAV
0800 STA DMACTLS
0810 EXIT STY PORTB
0820 PLA
0830 TAY
0840 PLA
0850 TAX
0860 PLA
0870 RTI
0880 FKY CPX #$84
0890 BEQ DISP
0900 CPX #$94
0910 BNE STORE
0920 LDA CHBAS
0930 LDX CHSPTR
0940 STA CHSPTR
0950 STX CHBAS
0960 CPX #$CC
0970 BEQ SET2
0980 TYA
0990 ORA $08
1000 TAY
1010 BNE CONT
1020 SET2 TYA
1030 AND #$F7
1040 TAY
1050 JMP CONT
1060 DISP LDA DMACTLS
1070 BEQ EXIT
1080 STA DMASAV
1090 LDA #$00
1100 STA DMACTLS
1110 BEQ EXIT
Następnie badane jest, czy sześć młodszych bitów rejestru
KBCODE ma wartość $11, co oznacza naciśnięcie klawisza HELP (w
dowolnej kombinacji z SHIFT i/lub CONTROL). Jeśli tak, to
zawartość KBCODE jest przepisywana do HLPFLG (HeLP FLaG).
Jako ostatnie sprawdzane są dwie kombinacje klawiszy
charakterystyczne dla 1200XL. Kod $84 oznacza kombinację
CONTROL-F2, a kod $94 kombinację CONTROL-F4. Pierwsza z nich
włącza i wyłącza dostęp ANTIC-a do pamięci, a więc włącza i
wyłącza obraz. Na czas wyłączenia obrazu zawartość rejestru
DMACTLS (DMA ConTroL Shadow register) jest przechowywana w
DMASAV (DMA SAVe).
Kombinacja CONTROL-F4 przełącza wbudowane zestawy znaków:
standardowy i międzynarodowy. W tym przypadku zamieniane są
miejscami zawartości wektorów CHBAS (CHaracter set BASe) i
CHSPTR (CHaracter Set PoinTeR) oraz ustawiany lub kasowany jest
bit 4 PORTB, który w 1200XL steruje diodą LED 2 (świeci się
przy korzystaniu z zestawu międzynarodowego).
Gdy nie została rozpoznana żadna z wymienionych kombinacji
klawiszy, to kod naciśniętego klawisza jest zapisywany do
rejestrów KBCODES i OLDKBC, rejestr KEYDEL otrzymuje wartość 3,
a ATRACT jest zerowany. Następnie zawartość KRPDEL (Key RePeat
DELay) jest przepisywana do licznika SRTIMER i procedura się
kończy.
3.2.6. Przerwanie klawisza BREAK
Klawisz BREAK posiada szczególne znaczenie i jego
naciśnięcie jest oddzielnie sygnalizowane w bicie 7 rejestru
IRQST. Przerwanie wywołane naciśnięciem tego klawisza jest
obsługiwane przez procedurę BREAKIRQ.
0100 ;BREAK key IRQ
0110 ;
0120 ATRACT = $4D
0130 CRSINH = $02F0
0140 IRQSTAT = $11
0150 SSFLAG = $02FF
0160 ;
0170 *= $C092
0180 ;
0190 LDA #$00
0200 STA IRQSTAT
0210 STA SSFLAG
0220 STA CRSINH
0230 STA ATRACT
0240 PLA
0250 RTI
Jedynym zadaniem tej procedury jest wyzerowanie rejestrów
IRQSTAT, SSFLAG, ATRACT i CRSINH. Znaczenie trzech pierwszych
było już omawiane. Rejestr CRSINH (CuRSor INHibition) określa
widoczność kursora. Jeżeli zawiera on wartość różną od zera, to
kursor jest niewidoczny na ekranie.
3.2.7. Przerwanie nowego urządzenia
Jako ostatnie zostanie omówione przerwanie, które ma drugi
priorytet - ustępuje jedynie przerwaniu wywołanemu przez odczyt
z szyny szeregowej. Jest to przerwanie wywoływane przez nowe
urządzenie przyłączone do szyny równoległej. Znaczenie
określenia "nowe urządzenie" zostało wyjaśnione wcześniej.
Żądanie przerwania jest sygnalizowane przez nowe urządzenie
w rejestrze PINTMSK i procedura SINDRYI po sprawdzeniu
istnienia urządzenia (w rejestrze PDVREG) wywołuje procedurę
NEWIOREQ.
0100 ;NEW I/O REQest
0110 ;
0120 BITMASK = $CA21
0130 DEVINT = $D808
0140 PDVREG = $D1FF
0150 PDVRS = $0248
0160 ;
0170 *= $C96E
0180 ;
0190 LDX #$08
0200 NEXT ROR A
0210 BCS FIND
0220 DEX
0230 BNE NEXT
0240 FIND LDA PDVRS
0250 PHA
0260 LDA BITMASK-1,X
0270 STA PDVRS
0280 STA PDVREG
0290 JSR DEVINT
0300 PLA
0310 STA PDVRS
0320 STA PDVREG
0330 PLA
0340 TAX
0350 PLA
0360 RTI
Przed wywołaniem tej procedury w akumulatorze ustawione są
bity odpowiadające urządzeniom żądającym przerwania. Po
znalezieniu urządzenia, które wysłało sygnał żądania
przerwania, aktualna zawartość rejestru PDVRS jest odkładana na
stos, a w PDVRS jest umieszczana odpowiednia maska bitowa
pobrana z tabeli BITMASK.
1000 ;BIT MASK
1010 ;
1020 *= $CA21
1030 ;
1040 .BYTE $80,$40,$20,$10
1050 .BYTE $08,$04,$02,$01
Następnie wywoływana jest znajdująca się w pamięci ROM
nowego urządzenia procedura obsługi przerwania DEVINT (DEVice
INTerrupt). Po jej zakończeniu odtwarzana jest ze stosu
zawartość rejestrów PDVRS i PDVREG i na tym przerwanie jest
zakończone.
|