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 |
©2023 mgr Jerzy Wałaszek |
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-LP |
Teraz 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-AGAIN |
Po 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-calc |
Teraz 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-calc |
Ostateczna 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-B |
Liczba 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*t |
Wynik 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-calc |
Uwaga: 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 H |
Poniż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 ©2023 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: i-lo@eduinf.waw.pl
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.