Generování zvuku pomocí zabudovaného reproduktoru počítačů PC

Úkolem tohoto cvičení je:

  1. seznámit se s možnostmi vytváření zvuku zabudovaným reproduktorem
  2. vytvořit v jazyce Turbo Pascal krátký program, generující zvuk prostřednictvím PPI
  3. s využitím znalostí o obvodu 8053 vytvořit funkce funkce obdobné knihovním procedurám sound() a nosound()

Přístup ke vstupně/výstupnímu adresovému prostoru

Přístup ke vstupně/výstupním adresám umožňuje v jazyce Turbo Pascal předdefinované jednorozměrné pole Port[]. Index i prvky pole Port[] jsou typu Byte.

Je-li prvek pole Port použit na pravé straně výrazu, přeloží se jako intrukce vstupu ze vstupně/výstupní adresy, dané indexem prvku. Přiřazení do prvku pole způsobí zápis na příslušnou vstupně/výstupní adresu.

Příklad:

     Port[$20] := $20;  { Výstup hodnoty 20H na adresu 20H }
     w := Port[$B2];    { Vstup z adresy 0B2H }

Generování zvuku na počítačích IBM kompatibilních

Již první počítače IBM PC měly vestavěný reproduktor. Tento reproduktor zná pouze dva stavy: zapnuto a vypnuto. Rychlým střídavým zapínáním a vypínáním reproduktoru můžeme vytvářet "tóny".

Zvuky pomocí zabudovaného reproduktoru můžeme tvořit dvěma způsoby. První metoda je ovládat reproduktor dvěma bity PPI (Programmable Peripherial Interface). Druhou metodou je použít zabudovaný čítač/časovač 8253.

Generování zvuku pomocí čítače/časovače 8253

Hlavní částí obvodu 8253 jsou tři navzájem nezávislé čítače, které se odlišují číslováním. Každý čítač je 16-bitový, s předvolbou, synchronní, dekrementující, čítající buď binárně nebo dekadicky. Může pracovat v šesti pracovních modech. Pracovní mód, způsob čtení a zápisu a číselná soustava čítání se volí zápisem modovacího slova CW do řídícího registru CWR.

Jednotlivé čítače jsou v počítačích typu PC obsazeny takto:

čítač obsazení čítače
0 hodiny systému
1 občerstvování paměti (pouze u modelů PC a PC/XT)
2 ovládání vestavěného reproduktoru

Poznámka: Čítač číslo 0 je zodpovědný za chod systémových hodin. Obvykle je naprogramován tak, aby generoval přibližně 18.2 hodinových "tiků" za sekundu. Při každém tiku je vygenerováno přerušení č. 8.

Přístup k čítačům a CWR obvodu 8253 je na těchto vstupně/výstupních adresách:

Dec Hex význam
64 40 předvolba nebo čtení stavu čítače č. 0
65 41 předvolba nebo čtení stavu čítače č. 1
66 42 předvolba nebo čtení stavu čítače č. 2
67 43 zápis řídícího slova do CWR

Vstup CLK všech čítačů dostává signál z hlavních hodin počítače (obvod 8284a), které oscilují frekvencí 1193180 Hz. Obsah všech běžících čítačů se sníží o 1 při každém hodinovém cyklu vstupního signálu, čítač se dostane do koncového stavu při dočítání do hodnoty 0.

Vstup GATE čítače č. 2, kterým lze zevně povolit nebo zastavit čítání, je ovládán bitem 0 PPI (popis PPI je v následujícím oddíle).

Ovládání reproduktoru výstupem OUT čítače č. 2 je možné povolit nebo zakázat bitem č. 1 PPI.

Generování zvuku pomocí obvodu 8253 vyžaduje modovat čítač č. 2 a zapsat do něj předvolbu. Nejprve se zapíše na adresu 43h modovací slovo, pak se zapíše jedna nebo dvě (podle modování) slabiky předvolby na adresu 42h. Poté je zapotřebí povolit čítání a ovládání reproduktoru nastavením spodních dvou bitů PPI.

Modovací slovo obvodu 8253 má tento formát:
Bit D7 D6 D5 D4 D3 D2 D1 D0
Symbol SC1 SC0 RW1 RW0 M2 M1 M0 BCD

Bity SC1 a SC0 volí modovaný čítač (tj. 10b pro čítač č. 2), a bit BCD volí binární/dekadické čítání (0 pro binární čítání). Význam ostatních bitů je následující:

RW (read/write - čtení/zápis)
RW1 RW0 význam
0 0 operace s registrem OL (output latch)
0 1 čtení nebo zápis jen dolní slabiky
1 0 čtení nebo zápis jen dolní slabiky
1 1 čtení nebo zápis dolní a pak horní slabiky

Po nastavení 00b (output latch) je nutné přečíst hodnotu čítače - prostřednictvím registru OL je zaručena jeho stabilní hodnota.

M (mode - nastavení modu)
M2 M1 M0 význam
0 0 0 přerušení po dočítání
0 0 1 monostabilní generátor
0 1 0 dělič frekvence
0 1 1 dělič frekvence se střídou 0.5
1 0 0 strobování spouštěné programem
1 0 1 strobování spouštěné signálem

Každý čítač 8053 může pracovat v jednom ze šesti modů (viz také výše uvedenou tabulku):

Mód 0 - přerušení po dočítání
po nastavení tohoto módu bude výstup 0, po dočítání se výstup změní na 1 a zůstane tak do přeprogramování čítače. Čítač pokračuje v čítání.
Mód 1 - monostabilní generátor
po načtení hodnoty bude výstup 0, po dočítání se změní na 1 a čítání se zastaví.
Mód 2 - dělič frekvence
výstup bude 0 jednu periodu vstupních hodin, po zbytek čítání bude výstup 1. Pak se cyklus opakuje.
Mód 3 - dělič frekvence se střídou 0.5
polovinu doby čítání bude výstup 1, druhou polovinu 0. Pak se cyklus opakuje.
Mód 4 - strobování spouštěné programem
po nastavení módu bude výstup 1, změní se na 0 po dočítání.
Mód 5 - strobování spouštěné signálem
podobně jako mód 4, ale čítání se spouští signálem.

Pro generování tónu se v aplikačních programech používá druhý čítač, zápis dolní a pak horní slabiky, mód 3 (dělička frekvence se střídou 0.5), binární čítání - tj. CW bude 10110110b = B6h.

Používání obvodu 8253 pro generování zvuku je podstatně rozšířenější než přímé ovládání pomocí PPI ze dvou důvodů: Má menší spotřebu času procesoru a je na rychlosti procesoru nezávislé.

Generování zvuku přímým ovládáním reproduktoru

Reproduktor je ovládán obvodem nazývaným Programmable Peripherial Interface (PPI) který používá port 61h (97). Pro ovládání reproduktoru jsou použity pouze nejnižší dva bity. Ostatní bity jsou určeny k jiným účelům, proto je důležité, abychom je při práci s reproduktorem neovlivňovali.

Pokud je obsah nejnižšího bitu nulový, stav reproduktoru se bude řídit bitem 1 PPI. Pak můžeme reproduktor přímo ovládat nastavením prvního bitu - nastavení na 1 reproduktor zapne, nastavení na 0 jej vypne.

Nastavením nejnižšího bitu PPI na 1 připojíme k reproduktoru výstup čítače 2 obvodu 8253 a spustíme čítání (viz popis i8253 v přecházejícím oddíle).

Přímé ovládání reproduktoru má tu nevýhodu, že v generovaném zvuku se projeví přerušení časovače. Jediná možnost jak tomu zabránit je přerušení zakázat, což zase znemožňuje počítači správné časování.

Poznámka: Hrátky s PPI mohou způsobit nefunkčnost procedur sound() a nosound(). Po skončení práce s PPI nastavte bity 0 a 1 PPI na hodnotu 0.

Příkladové řešení úloh

  1. Generování zvuku pomocí PPI: ppi.pas
  2. Generování zvuku obvodem 8253: 8253.pas

Flašinet

Pokud vám snad předchozí úlohy připadaly nezáživné, můžete si napsat jednoduchý "flašinet". V souboru flasinet.txt najdete melodii flašinetu jako poslounost řádek ve tvaru

        číslo1, číslo2, číslo3,

kde číslo1 je frekvence tónu (v Hz), číslo2 je doba trvání tónu (v milisekundách) a číslo3 je doba trvání pauzy (opět v ms).

Váš flašinet můžete napsat nejprve pomocí procedur Turbo Pascalu (sound, nosound a delay) a poté s užitím vašich vlastních procedur pro generování zvuku.

(K této úloze nemám příkladové řešení.)


Lukáš Petrlík
luki@kiv.zcu.cz