Programowanie PC-Speaker'a
Programowanie głośniczka w assemblerze
Czy nie myślicie czasem, jakby to było, gdyby można było wzbogacić swój
program oprócz efektu wizualnego, także o efekt dźwiękowy?
Programowanie kart dźwiękowych (zwłaszcza tych nowoczesnych) może sprawiać
niemałe kłopoty. Stary, poczciwy PC-Speaker jest jednak urządzeniem względnie
prostym w programowaniu.
I to właśnie tutaj udowodnię. Najpierw troszkę teorii, potem - do dzieła!
Sporo urządzeń w komputerze ma własne porty, przez które można się
z nimi komunikować. Jednak głośniczek komputerowy nie ma własnego
portu.
Jest tak przede wszystkim ze względu na oszczędności w budowie
pierwszych PC-tów. Zamiast dać osobny port na głośnik, firmy
produkujące komputery wcisnęły go "pod opiekę" dwóch innych urządzeń:
czasomierza systemowego, który posłuży nam do wytworzenia impulsów
odpowiedniej częstotliwości
kontrolera klawiatury, który kontroluje, czy jest otwarty "kanał" z
czasomierza do głośniczka, tzn. czy można będzie wysyłać informacje.
Podstawowe porty czasomierza to porty od 40h do 43h (cały zakres to
40h - 5fh, h = szestnastkowo), kontrolera klawiatury zaś - 60h do 64h
(cały zakres: 60h - 6fh).
Nie będziemy ich jednak wszystkich używać. Będą na interesować tylko
porty 42h, 43h i 61h.
Zacznijmy więc coś pisać:
in al,61h
or al,3
out 61h,al
Co zrobiliśmy? W spisie portów (
Listy Przerwań Ralfa Brown'a) czytamy:
===========================
0061 R- KB controller port B control register (ISA, EISA)
0061 -W KB controller port B (ISA, EISA)
(R - czytanie (read) , W - pisanie (write))
===========================
oraz:
===========================
Bitfields for KB controller port B (system control port) [output]:
Bit(s) Description (Table P0392)
7 pulse to 1 for IRQ1 reset (PC,XT)
6-4 reserved
3 I/O channel parity check disable
2 RAM parity check disable
1 speaker data enable
0 timer 2 gate to speaker enable
===========================
Komenda "in al,61h" czyta bieżący status kontrolera, "or al,3" ustawia
(włącza) bity 0 (włączenie bramki do głośniczka) oraz 1 (włączenie
możliwości wysyłania danych do głośniczka), "out 61h,al" zapisuje
nowy status do kontrolera.
Głośniczek jest włączony. Trzeba mu podać jakiś sygnał. Do tego posłuży
nam czasomierz. W spisie portów czytamy:
===========================
0042 RW PIT counter 2, cassette & speaker
0043 RW PIT mode port, control word register for counters 0-2
Once a control word has been written (43h), it must be followed
immediately by performing the corresponding action to the counter
registers (40h-42h), else the system may hang!!
===========================
Do portów tych nie będziemy wysyłać jednak częstotliwości, którą chcemy
uzyskać. Czasomierz pracuje na częstotliwości 1193181 (1234DDh) Hz
i to tę wartość dzielimy przez żądaną częstotliwość. Wynik wysyłamy
do odpowiednich portów.
Piszmy więc:
mov bx,440h ; Standardowe "A", 440 Hz
mov dx,12h ; górna część "1234dd"
mov ax,34ddh ; dolna część "1234dd"
div bx ; ax = wartość do wysłania
push ax
mov al,0b6h
out 43h,al
pop ax
out 42h,al
mov al,ah
out 42,al
No i co my tutaj znowu zrobiliśmy?
4 pierwsze komendy to oczywiście uzyskanie wartości do wysłania na port,
ale reszta?
Najpierw: 0b6h = 1011 0110
===========================
Bity 7 i 6 = 10 = wybierz (standardowo niezajęty) czasomierz nr 2
(łącznie są 3: zegar czasu rzeczywistego, czasomierz odświeżania
pamięci RAM i ten trzeci, nieużywany)
Bity 5 i 4 = 11 = zapisujemy do czasomierza najpierw młodsze bity (0-7)
wartości, potem starsze (8-15)
Bity 3-1 = 011 = wybierz tryb nr 3, czyli generator fali kwadratowej
Bit 0 = 0 = licznik binarny 16-bitowy.
===========================
Zgodnie z tym, najpierw wysyłamy młodszy bajt, AL a potem starszy, AH.
Skoro na port można wysłać największą wartość 0ffffh (teoretycznie
największa jest 10000h, obcinana do 0000h), to jakiej odpowiada to
częstotliwośći?
1234dd / 10000h to ok. 12h, czyli 18. A dokładniej jest to coś około
18,2 Hz - standardowa częstotliwość zegara w komputerze (tj. aby
odmierzyć 1 sekundę trzeba ok 18 tyknięć tego zegara)
Nasz głośniczek już gra. Teraz trzeba sprawić, bo to troszkę potrwało.
Pomocne będzie przerwanie 15h, funkcja 86h:
mov cx,0fh
mov dx,4240h
mov ah,86h
int 15h ; pauza o długości CX:DX mikrosekund
I dźwięk trwa 1 sekundę (F4240h = 1.000.000). Teraz trzeba go
wyłączyć. Nic prostszego. Po prostu zamkniemy przejście między
czasomierzem a głośniczkiem:
in al,61h
and al,not 3 ; zerujemy bity 0 i 1
; NASM: "and al,~3"
out 61h,al
Mam nadzieję, że podałem wystarczająco informacji, abyście samodzielnie zaczęli programować
głośniczek. Jeśli mi się nie udało, to zawsze możecie skorzystać z gotowej procedury z mojej
biblioteki.
To już koniec. Miłej zabawy!
Wyszukiwarka
Podobne podstrony:
SPKR TUTDOS SPKR TUTSPKR TUTART121 tut 2phys tut 08phys tut 12DOS DIOD TUTSYS TUTART121 tut 3MYSZ TUTPWR TUTGRAF TUTtut?2 sdram vhdltut?bug hardware vhdlDE2BIBL TUTPWR TUTSYS TUTwięcej podobnych podstron