![]() |
Hardware-ProjekteProf. Jürgen Plate |
Um einen Ton zu erzeugen, muß zunächst der zuständige Timer mit der gewünschten Frequenz programmiert werden. Dieser Timer wird über die Ports 43H und 42H angesprochen. Die Frequenz wird durch einen 16-Bit-Teilfaktor bestimmt, der die Taktfrequenz des Timers entsprechend herunterteilt:
Teilfaktor = 133100/Frequenz
Zum Ein-und Ausschalten des Lautsprechers dürfen nur die beiden
Bits 0 und 1 des PPI gesetzt oder gelöscht werden, die anderen
Bits müssen erhalten bleiben.
Glücklicherweise ist der interne Lautsprecher Teil der Linux Console und daher ein character device. So bleibt einem der direkte Portzugriff erspart. Es genügt die Funktion ioctl(). Für den internen Lautsprecher gibt es zwei Requests, die sich auf den Kernel stützen:
ioctl (fd, KDMKTONE,(long) argument)
ioctl(fd,KIOCSOUND,(int) tone).
Tonhoehe = 1190000/Frequenz
Die Dauer wird in Timer Ticks gemessen. Beie Aufrufe kehren sofort
zurück, das Programm wird also durch das Piepsen nicht blockiert.
KDMKTONE eignet sich gut für Warnsignale, weil der Ton von selbst
endet. KIOCSOUND kann verwendet werden, um Melodien zu spielen.
Um hier wieder Stille zu erhalten, muß die Tonhöhe 0 angegeben werden.
Bei Verwendung von Noten gilt für die Frequenzen:
262 C - "middle C"
277 C#
294 D
311 D#
330 E
349 F
370 F#
392 G
415 G#
440 A
466 A#
494 H
Um andere Oktaven zu bilden, einfach immer die höchste Noten-Freqenz
mit 1.0595, multiplizieren und runden. Zum Beispiel ergibt sich
aus den H oben: 494 * 1.0595 = 523.393, gerundet 523 Hz für das "C",
das eine Oktave höher liegt als das "middle C".
Das folgende Programm erzeugt auf dem internen Lautsprecher einen Ton der Frequenz freq [Hz] und der Dauer duration [ms]. Es kehrt nicht sofort zurück, sondern wartet, bis der Ton fertig gespielt wurde.
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Spielen mit dem internen PC-Lautsprecher unter Linux
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Das Programm erzeugt auf dem internen Lautsprecher einen
* Ton der Frequenz freq [Hz] und der Dauer duration [ms]
*
* Aufruf: beep [freq duration]
*
* Beim Aufruf ohne Parameter wird ein 880-Hz-Ton 100 ms lang erzeugt.
*
* Wegen des Zugriffs auf /dev/console (wahlweise /dev/tty0)
* und der ioctl-Aufrufe kann das Programm nur von root
* aufgerufen werden (ggf. mit 'chmod 4711 beep' SUD-root setzen)
* Für eine Produktiv-Version sollte noch eine Fehlerbehandlung
* hinzugefügt werden.
*
* JPL 10.11.04
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/kd.h>
#include <unistd.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
int fd;
long duration, freq, res;
fd = open("/dev/console",O_RDONLY);
if (argc > 2)
{
freq = atoi(argv[1]);
duration = atoi(argv[2]);
}
else
{
freq = 880;
duration = 100;
}
if (freq > 0)
{
res = (duration << 16) + (1193180/freq);
ioctl(fd,KDMKTONE,res);
}
usleep(duration*1000);
close(fd);
return(0);
}
Nun kann man z.B. ein Shell-Script schreiben, das den Anfang von
Beethovens "Für Elise" spielt:
#!/bin/bash beep 659 120 # Treble E beep 0 120 beep 622 120 # Treble D# beep 0 120 beep 659 120 # Treble E beep 0 120 beep 622 120 # Treble D# beep 0 120 beep 659 120 # Treble E beep 0 120 beep 494 120 # Treble B beep 0 120 beep 587 120 # Treble D beep 0 120 beep 523 120 # Treble C beep 0 120 beep 440 120 # Treble A beep 0 140 beep 262 120 # Middle C beep 0 120 beep 330 120 # Treble E beep 0 120 beep 440 120 # Treble A beep 0 120 beep 494 120 # Treble B beep 0 140 beep 330 120 # Treble E beep 0 120 beep 415 120 # Treble G# beep 0 120 beep 494 120 # Treble B beep 0 120 beep 523 120 # Treble C beep 0 140 beep 330 120 # Treble E beep 0 120 beep 659 120 # Treble E beep 0 120 beep 622 120 # Treble D# beep 0 120 beep 659 120 # Treble E beep 0 120 beep 622 120 # Treble D# beep 0 120 beep 659 120 # Treble E beep 0 120 beep 494 120 # Treble B beep 0 120 beep 587 120 # Treble D beep 0 120 beep 523 120 # Treble C beep 0 120 beep 440 120 # Treble A beep 0 140 beep 262 120 # Middle C beep 0 120 beep 330 120 # Treble E beep 0 120 beep 440 120 # Treble A beep 0 120 beep 494 120 # Treble B beep 0 140 beep 330 120 # Treble E beep 0 120 beep 523 120 # Treble C beep 0 120 beep 494 120 # Treble B beep 0 140 beep 440 120 # Treble A"beep" läßt sich sinnvoll beim Betrieb von Servern einsetzen, die normalerweise keine Soundkarte haben - und oft auch keinen Monitor und keine Tastatur.