ZX Spectrum > PROGRAMOWANIE

Przerwania

(1/5) > >>

Abrimaal:
Chciałbym, żeby podczas pracy programu chodziła (sama się wywołując) muzyka na przerwaniach.
Tutaj już nie pamiętam co i jak robić.
Załóżmy że główna pętla muzyki znajduje się pod 32768
Robię w dowolnym podzielnym przez 256 miejscu, 256B z adresem 32768 (0, 128 na zmianę)
(nie chcę używać tabeli 255,255 z ROM 48, bo chciałbym żeby to działało na 128 też.)
teraz chyba muszę wpisać wartości do rejestrów IR (tylko jakie)?
Czy do rejestru I adres tabeli?
I IM2 po uprzednim wywołaniu INIT muzyki powinno ją odgrywać niezależnie od chodzącego programu
(o ile nie ma w nim DI lub zmiany trybu przerwań)
Czego tu jeszcze brakuje?

YERZMYEY/HOOY-PROGRAM:
Ja to mam tylko engine w interpreterze BASICa do tego. Więc tobie to pewnie do niczego nie jest potrzebne. ;)

matofesi:
Czego brakuje... Przede wszystkim - jak zwykle - chęci przeczytania czegokolwiek na ten temat :P

Przerwania Z80 w trybie IM2 obsługiwane są w następujący sposób:
1. zgłoszenie przerwania z zewnątrz
2. procesor pobiera młodszy bajt adresu wektora obsługi przerwań z szyny danych
3. starszy bajt adresu wektora obsługi przerwań pobierany jest z rejestru I
4. spod w ten sposób skonstruowanego adresu pobierane są dwa bajty i następuje skok do właściwej procedury - cała obsługa przerwania od wywołania do wykonania pierwszej instrukcji w procedurze obsługi zajmuje 32 takty (to jakby ktoś potrzebował coś dokładnie policzyć i synchronizować).

Wektoryzowanie obsługi przerwań służy zasadniczo do tego, żeby różne urządzenia zewnętrzne mogły mieć swoje własne procedury obsługi przerwań - urządzenie zgłaszając przerwanie wystawia na szynie danych własny numer wektora (niektóre źródła podają, że bajt ten powinien mieć wyzerowany najniższy bit, inne, że procesor najniższy bit po prostu ignoruje) a dzięki temu procesor skacze do właściwej procedury.

W wypadku Spectrum cały mechanizm w zasadzie nigdy nie był używany - nie były nigdy produkowane urządzenia, które same z siebie zgłaszałyby przerwania. Stąd w zasadzie jedynym źródłem przerwań jest ULA generująca przerwania "zegarowe" ~50Hz. Problem w tym, że cały mechanizm obsługi w procesorze nadal działa i nadal młodszy bajt pobierany jest z szyny danych co powoduje, że w wypadku podłączania różnych urządzeń zewnętrznych może się tam pojawić w zasadzie dowolna wartość. Bez dodatkowych urządzeń zwykle jest to jednak 255. Niezależnie od tego aby zapewnić na 100% poprawną obsługę przerwań należy zastosować taką procedurę:

1. wyłączamy przerwania
2. przygotowujemy tablicę wektorów przerwań - musi się zaczynać od pełnej strony adresowej (zera w ośmiu najmłodszych bitach adresu). i zawierać 257 identycznych wartości. Wartości te składają się na adres procedury obsługi przerwań. Jeśli na przykład tworzymy tablicę wektorów pod adresem $8000 (32768) i wypełniamy ją wartością $81 to właściwa procedura będzie się znajdowała pod adresem $8181 (33153)
3. Pod adresem procedury możemy umieścić własny kod albo skok w inne miejsce pamięci, gdzie znajdzie się właściwa procedura.
4. do rejestru I ładujemy numer strony tablicy wektorów (starszy bajt jej adresu - wg przykładu $80).
5. przełączamy tryb obsługi przerwań - IM 2
6. włączamy przerwania
7. wykonujemy własny kod
8. wyłączamy przerwania
9. przełączamy tryb obsługi przerwań - IM 1
10. włączamy przerwania
20 wychodzimy do BASICa

Procedura obsługi przerwania musi oczywiście zapamiętać na początku wszystkie rejestry, których będziemy w niej używać a następnie przed zakończeniem musi je odtworzyć do stanu sprzed jej wywołania. Obsługę przerwania kończymy włączeniem przerwań (nie trzeba ich na początku wyłączać - robi to automatycznie procesor w cyklu przyjęcia przerwania) i wychodzimy rozkazem RET lub RETI. Ten drugi jest dłuższy, ale za to wystawia dodatkowe sygnały na szynie, co powoduje, że urządzenie zgłaszające przerwanie z zewnątrz jest w stanie rozpoznać fakt zakończenia obsługi tego przerwania i odpowiednio na niego zareagować. W wypadku Spectrum nie ma to strategicznego znaczenia i spokojnie możemy kończyć przerwanie używając RET.

Abrimaal:
Chęć czytania jest, tylko brak źródła. Zrozumiałem wszystko z wyjątkiem pkt.2

--- Cytat: matofesi w 2012.04.08, 12:10:29 ---2. przygotowujemy tablicę wektorów przerwań - musi się zaczynać od pełnej strony adresowej (zera w ośmiu najmłodszych bitach adresu). i zawierać 257 identycznych wartości.

--- Koniec cytatu ---
Czy cała tablica ma się składać z identycznych wartości 257 x #81 w naszym przykładzie?
Czy na początku ma być coś dodane - niezbyt rozumiem to "zera w ośmiu najmłodszych bitach adresu"?

RafalM:
Przerwania są dość ciężkie do zrozumienia, ale jak są chęci to się da.

A więc tak:

- adresy komórek pamięci w Spektrum są z zakresu 0-65535 i składają się z dwóch bajtów, starszego i młodszego

 Adres =starszy*256+młodszy.

- gdy ustawiamy przerwanie w trybie IM2 zaczynamy od ustawienia wartości rejestru I.

LD A,x
ID I,A

 Komputer będzie używał adresu I*256+n gdzie niestety n jest w ogólności liczbą losową (wspomniany bajt podawany przez urządzenia zewnętrzne).

Pod adresem I*256+n jest przechowywany ... następny adres :) Tym razem jest to już właściwy adres kodu przerwania.

Załóżmy że chcielibyśmy by kod przerwania był pod adresem 258 czyli 1*256+2. Ponieważ n jest nieznane teoretycznie należałoby wypełnić 256 bajtów powtarzając ten adres:

2,1,2,1,2,1,2....

(młodszy bajt idzie jako pierwszy)

Problem w tym że przy losowym n procesor mógłby przeczytać adres startując od złego bajtu jako 1,2 (czyli 2*256+1=513) zamiast 2,1 (1*256+2=258).

Dlatego najprościej jest umieścić przerwanie pod takim adresem gdzie starszy bajt=młodszy bajt i wypełnić wektor przerwań, czyli 256 bajtów wskazywanych przez I*256+n jedną wartością. Wtedy pomyłki na pewno nie będzie.

Nawigacja

[0] Indeks wiadomości

[#] Następna strona

Idź do wersji pełnej