|
Serwis Edukacyjny w I-LO w Tarnowie
Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej
Autorzy: dr Ian Logan i dr Frank O'Hara |
©2026 mgr Jerzy Wałaszek
|
Dwoma procedurami w tym rozdziale są procedura BEEPER, która faktycznie steruje głośnikiem, oraz procedura polecenia BEEP.
Głośnik jest włączany przez ustawienie na 0 linii D4 podczas instrukcji OUT odnoszącej się do portu '254'. Gdy w podobnej sytuacji linia D4 zostaje ustawiona w stan wysoki, to głośnik jest wyłączany. Stąd 'pisk' może być wytworzony przez regularne zmienianie poziomu linii D4.
Rozważmy teraz dźwięk 'środkowe C', który posiada częstotliwość 261.63 Hz. Aby otrzymać ten dźwięk, głośnik musi być naprzemiennie włączany i wyłączany co 1/523,26 część sekundy. W SPECTRUM zegar systemowy jest ustawiony do pracy przy 3,5 MHz i dźwięk 'środkowe C' będzie wymagał instrukcji OUT wykonywanej z najwyższą dokładnością co 6.689 taktów zegarowych. Ta ostatnia wartość, zmniejszona nieco ze względu na czas niezbędny do wykonania różnych rozkazów, reprezentuje 'długość pętli czasowej' w procedurze BEEPER.
Wejście do tej procedury następuje z parą rejestrów DE zawierającą wartość 'f*t', gdzie dźwięk o danej częstotliwości 'f' ma posiadać czas trwania 't' sekund, i z parą rejestrów HL zawierającą wartość równą liczbie taktów zegara w 'pętli czasu' podzielonej przez '4'.
Np. Dla nuty 'środkowe C' mającej być odtwarzaną przez jedną sekundę DE zawiera +0105 (INT(261.3 * 1)) a HL zawiera +066A (otrzymane z 6,689/4 - 30.125).
03B5 BEEPER DI Wyłącz przerwania na okres trwania 'pisku'.
LD A,L Chwilowo zachowaj L.
SRL L Każde '1' w rejestrze L ma odpowiadać
SRL L '4' taktom zegara, lecz wykonaj
INT (L/4) i zamiast tego zliczaj '16' taktów.
CPL Wróć do pierwotnej wartości
AND +03 w L i sprawdź, ile zostało stracone
LD C,A przez obliczenie INT (L/4).
LD B,+00
LD IX,+03D1 Adres bazowy pętli czasowej.
ADD IX,BC Zmień długość pętli czasowej.
Użyj wcześniejszego punktu
dla każdego '1' utraconego przez wyznaczenie INT (L/4).
LD A,(BORDCR) Pobierz kolor bieżącego brzegu
AND +38 i przenieś go do bitów
RRCA 2, 1 1 0 rejestru A.
RRCA
RRCA
OR +08 Upewnij się, że wyjście MIC jest wyłączone.Teraz wejdź to pętli drugiej generacji. Wykonywane jest 'DE' obiegów, tj. obiegów dla każdego okresu dźwięku.
Para rejestrów HL zawiera 'długość pętli czasowej' przy 16 taktach zegara używanych dla każdego '1' w rejestrze L i 1.024 taktach zegara dla każdego '1' w rejestrze H..
03D1 BE-IX+3 NOP Dodaj '4' takty zegara dla każdego
03D2 BE-IX+2 NOP wcześniejszego punktu wejścia,
03D3 BE-IX+1 NOP który jest używany.
03D4 BE-IX+0 INC B Wartości w rejestrach B i C
INC C będą pochodziły z rejestrów H i L
- patrz niżej.
03D6 BE-H&L-LP DEC C 'Pętla czasowa'.
JR NZ,03D6,BE-H&L-LP 'BC' * '4' cykle zegara.
LD C,+3F (Lecz zauważ, że w punkcie połowy okresu
DEC B C będzie równe 'L+1'.)
JP NZ,03D6,BE-H&L-LPTeraz głośnik jest naprzemian włączany i wyłączany.
XOR +10 Zmień na przeciwny bit 4.
OUT (+FE),A Wykonaj operację OUT;
pozostawiając brzeg bez zmiany koloru.
LD B,H Resetuj rejestr B.
LD C,A Zachowaj rejestr A.
BIT 4,A Skocz, jeśli jest to punkt połowy okresu.
JR NZ,03F2,BE-AGAINPo pełnym cyklu para rejestrów DE jest testowana.
LD A,D Skocz naprzód, jeśli ostatni
OR E pełny okres został
JR Z,03D6,BE-END już wykonany.
LD A,C Pobierz zachowaną wartość.
LD C,L Resetuj rejestr C.
DEC DE Zmniejsz licznik obiegów.
JP (IX) Skocz wstecz do wymaganego
punktu startowego pętli.Ustawiane są parametry dla drugiej połowy cyklu.
03F2 BE-AGAIN LD C,L Resetuj rejestr C.
INC C Dodaj '16' cykli, ponieważ ta ścieżka
jest krótsza.
JP (IX) Skocz do tyłu.Po zakończeniu generacji dźwięku muszą zostać włączone przerwania.
03F6 BE-END EI Włącz przerwania.
RET Powróć ostatecznie.Wejście do tej procedury następuje z dwoma liczbami na stosie kalkulatora. Liczba na szczycie stosu przedstawia 'wysokość' nuty P, a liczba leżąca pod spodem przedstawia jej 'długość' t.
03F8 BEEP RST 0028,FP-CALC Użyty zostaje kalkulator zmiennoprzecinkowy
do manipulacji tymi wartościami - t i P.
DEFB +31,duplicate t,P,P
DEFB +27,int t,P,i (gdzie i = INT P)
DEFB +C0,st-mem-0 t,P,i (mem-0 zawiera i)
DEFB +03,subtract t,P (gdzie p jest częścią ułamkową P)
DEFB +34,stk-data Umieść na stosie liczbę 'K'.
DEFB +EC,exponent+7C 0.0577622606 (co jest
DEFB +6C,+98,+1F,+F5 nieco poniżej 12*(2^0.5)-1)
DEFB +04,multiply t,p*K
DEFB +A1,stk-one t,p*K,1
DEFB +0F,addition t,p*K+1
DEFB +38,end-calcTeraz wykonaj kilka testów na i, części całkowitej z 'wysokości' nuty.
LD HL,+5C92 Adres 'mem-0-1st' (MEMBOT).
LD A,(HL) Pobierz wykładnik i.
AND A Zgłoś błąd B, jeśli i nie jest
JR NZ,046C,REPORT-B w krótkiej postaci całkowitej.
INC HL Skopiuj bit znaku do
LD C,(HL) rejestru C.
INC HL Skopiuj młodszy bajt do
LD B,(HL) rejestru B i do
LD A,B rejestru A.
RLA Znów zgłoś błąd B, jeśli nie
SBC A,A spełnia warunku:
CP C -128<=i<=+127
JR NZ,046C,REPORT-B
INC HL
CP (HL)
JR NZ,046C,REPORT-B
LD A,B Pobierz młodszy bajt i
przetestuj go dalej.
ADD A,+3C
JP P,0425,BE-i-OK Zaakceptuj -60<=i<=67.
JP PO,046C,REPORT-B Odrzuć -128 do -61.Uwaga: Zakres od +70 do +127 zostanie odrzucony w dalszej części procedury.
Teraz dla każdej 'wysokości' można znaleźć prawidłową częstotliwość.
0425 BE-i-OK LD B,+FA Rozpocznij '6' oktaw poniżej środkowego C.
0427 BE-OCTAVE INC B Cyklicznie redukuj i w celu znalezienia
SUB +0C właściwej oktawy.
JR NC,0427,BE-OCTAVE
ADD A,+0C Anuluj ostatnie odejmowanie.
PUSH BC Zachowaj numer oktawy.
LD HL,+046E Adres bazowy 'tablicy półtonów'.
CALL 3406,LOC-MEM Rozpatrz tę tablicę i przekaż
CALL 33B4,STACK-NUM 'A-tą' wartość na stos kalkulatora (nazwijmy ją C).Teraz pod uwagę można wziąć część ułamkową 'wysokości'.
RST 0028,FP-CALC t, p*K+1, C
DEFB +04,multiply t, C*(p*K+1)
DEFB +38,end-calcOstateczna częstotliwość f jest znajdowana przez modyfikację 'ostatniej wartości' zgodnie z numerem oktawy.
POP AF Pobierz numer oktawy.
ADD A,(HL) Pomnóż 'ostatnią wartość' przez
LD (HL),A '2 do potęgi numeru oktawy.
RST 0028,FP-CALC t, f
DEFB +C0,st-mem-0 Chwilowo częstotliwość jest odkładana na bok
DEFB +02,delete do mem-0.Teraz uwaga jest kierowana na 'długość'.
DEFB +31,duplicate t, t
DEFB +38,end-calc
CALL 1E94,FIND-INT1 Wartość 'INT t' musi być
CP +0B w zakresie od +00 do +0A.
JR NC,046C,REPORT-BLiczba pełnych okresów w 'pisku' jest dana przez 'f*t', więc teraz ta wartość zostaje obliczona
RST 0028,FP-CALC t
DEFB +E0,get-mem-0 t, f
DEFB +04,multiply f*tWynik jest pozostawiany na stosie kalkulatora, natomiast obliczona zostaje wymagana długość 'pętli czasowej' dla 'pisku';
DEFB +E0,get-mem-0 f*t, f
DEFB +34,stk-data Wartość '3.5 * 10^6/8'
DEFB +80,four bytes jest tworzona na szczycie
DEFB +43,exponent +93 stosu kalkulatora.
DEFB +55,+9F,+80,(+00) f*t, f, 437,500 (dziesiętnie)
DEFB +01,exchange f*t, 437,500, f
DEFB +05,division f*t, 437,500/f
DEFB +34,stk-data
DEFB +35,exponent +85
DEFB +71,(+00,+00,+00) f*t, 437,500/f, 30.125 (dziesiętnie)
DEFB +03,subtract f*t, 437,500/f - 30.125
DEFB +38,end-calcUwaga: Wartość '437,500/f' daje długość 'połowy okresu' nuty skróconej o
30.125' dla '120.5' taktów, w czasie których dźwięk jest tworzony oraz są
obsługiwane liczniki.
Wartości te mogą teraz zostać przeniesione do odpowiednich rejestrów.
CALL 1E99,FIND-INT2 Wartość 'pętli czasowej' zostaje
PUSH BC umieszczona w parze rejestrów BC i zachowana.Uwaga: Jeśli wartość dla pętli czasowej jest zbyt duża, to powstanie błąd (powrót poprzez ERROR-1); w ten sposób unika się 'wysokości' od '+70 do +127'.
CALL 1E99,FIND-INT2 Wartość 'f*t' trafia do pary rejestrów BC.
POP HL Przenieś ją do pary rejestrów HL.
LD D,B Przenieś wartość 'f*t'
LD E,C do pary rejestrów DE.Jednakże przed wykonaniem 'pisku' sprawdź wartość 'f*t'.
LD A,D Wróć, jeśli 'f*t' dało
OR E wymagany wynik
RET Z 'brak taktów'.
DEC DE Zmniejsz liczbę taktów
JP 03B5,BEEPER i skocz do procedury BEEPER
(wykonując co najmniej jeden obieg).Raport B - liczba całkowita poza zakresem
046C REPORT-B RST 0008,ERROR-1 Wywołaj procedurę obsługi
DEFB +0A błędów.Ta tablica przechowuje częstotliwości dwunastu półtonów w oktawie.
częstotliwość w Hz. nuta
046E DEFB +89,+02,+D0,+12,+86 261.63 C
DEFB +89,+0A,+97,+60,+75 277.18 C#
DEFB +89,+12,+D5,+17,+1F 293.66 D
DEFB +89,+1B,+90,+41,+02 311.12 D#
DEFB +89,+24,+D0,+53,+CA 329.63 E
DEFB +89,+2E,+9D,+36,+B1 349.23 F
DEFB +89,+38,+FF,+49,+3E 369.99 F#
DEFB +89,+43,+FF,+6A,+73 392 G
DEFB +89,+4F,+A7,+00,+54 415.30 G#
DEFB +89,+5C,+00,+00,+00 440 A
DEFB +89,+69,+14,+F6,+24 466.16 A#
DEFB +89,+76,+F1,+10,+05 493.88 HPoniższa procedura odnosi się do ZX81 i nie została usunięta, gdy program został przepisany dla SPECTRUM.
04AA DEFB +CD,+FB,+24,+3A
DEFB +3B,+5C,+87,+FA
DEFB +8A,+1C,+E1,+D0
DEFB +E5,+CD,+F1,+2B
DEFB +62,+6B,+0D,+F8
DEFB +09,+CB,+FE,+C9
![]() |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2026 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.