Asembler: DOS: Programowanie głośniczka
Programowanie głośniczka w asemblerze
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, czyli czy można będzie wysyłać informacje.
Podstawowe porty czasomierza to porty od 40h do 43h (cały zakres to
40h - 5fh, h oznacza szesnastkowo), 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:
(przeskocz port 61h)
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:
(przeskocz opis portu 61h)
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:
(przeskocz opis portów 42h i 43h)
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ść, a wynik wysyłamy
do odpowiednich portów.
Piszmy więc:
(przeskocz włączanie głośniczka)
mov bx,440h ; Standardowy dźwięk A, 440 Hz
mov dx,12h ; górna część liczby 1234dd
mov ax,34ddh ; dolna część liczby 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ści?
1234dd / 10000h to ok. 12h, czyli 18. A dokładniej jest to coś około
18,2 Hz - standardowa częstotliwość zegara w komputerze (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!
Spis treści off-line (Alt+1)
Spis treści on-line (Alt+2)
Ułatwienia dla niepełnosprawnych (Alt+0)
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