Oberon/ETH Oberon/speaker
外觀
< Oberon | ETH Oberon
該文件最初託管在ETHZ。它仍在 ETH 許可證 下,並且位於 WayBack 存檔 中。
揚聲器支援
摘要
PC 揚聲器是一個窮人的聲音發生器,只能發出可憐的嗶嗶聲和尖叫聲,但在 Oberon 中程式設計很簡單。但是,由於使用了 SYSTEM 模組,因此程式碼不可移植。
如何透過程式控制揚聲器
假設一個頻率為 f 的聲音應該在時間 t 內發出。系統 Timer 2(可程式設計間隔定時器 (PIT) 中的三個定時器之一)用於控制聲音生成,分五個連續步驟。PIT 以 1.19318 MHz 的頻率執行。
- 計算一個 2 位元組計數器值(1 <= count <= 65'535),對應於指定的頻率 f - IntFreq。1'193'180 >= f >= 18.2
- 向埠地址 43H 傳送一個 PIT 控制字 - InitTimer
- 向埠地址 42H 傳送計數器值 - SetFreq
- 在埠地址 61H 處設定控制暫存器中的位 0 和 1 為“開”,以開啟揚聲器和放大器 - Tone
- 經過時間延遲 t 後,在埠地址 61H 處將相同的位設定為“關” - Tone
時間延遲必須由後臺任務控制。請注意,一旦揚聲器“開啟”,頻率可以隨意更改,甚至可以設定為不可聽的聲音以模擬靜音。
程式片段
CONST
TONES = 12; OCTAVES = 10;
ON = TRUE; OFF = FALSE;
A4 = 440; (* the latin "la" *)
(* Convert the frequency to an "internal" value *)
PROCEDURE IntFreq(hz: LONGINT): INTEGER;
CONST Rate = 1193180; (* Timer clock is 1.19318 MHz *)
BEGIN
RETURN SHORT(Rate DIV hz)
END IntFreq;
(* Set PIT control word to: Timer 2, 16-bit, mode 3, binary = {01110110} i.e. B6H *)
PROCEDURE InitTimer; (* Timer port address: 43H *)
BEGIN
SYSTEM.PORTOUT (43H, 0B6H)
END InitTimer;
(* Set counter value *)
PROCEDURE SetFreq(hz: LONGINT); (* Timer 2 port address: 42H *)
BEGIN
SYSTEM.PORTOUT (42H, CHR(hz MOD 100H));
SYSTEM.PORTOUT (42H, CHR(hz DIV 100H));
Tone(ON)
END SetFreq;
(* Switch speaker and amplifier on/off *)
PROCEDURE Tone(b: BOOLEAN); (* Loudspeaker port address: 61H *)
VAR s: SET;
BEGIN
SYSTEM.PORTIN (61H, SYSTEM.VAL(CHAR, s));
IF b THEN s := s + {0, 1} ELSE s := s - {0, 1} END;
SYSTEM.PORTOUT (61H, SYSTEM.VAL(CHAR, s))
END Tone;
(* Calculate table of "internal" frequencies for a number of octaves *)
PROCEDURE CalcTF;
VAR t, oct: INTEGER; f, f0, df: REAL;
BEGIN
df := Math.exp(Math.ln(2) / TONES);
f0 := A4 * df * df * df / 32; (* = c0 *)
FOR oct := 0 TO OCTAVES-1 DO
f := f0;
FOR t := 0 TO TONES-1 DO
TF[t, oct] := IntFreq(ENTIER(f));
f := f * df
END;
f0 := f0 * 2
END
END CalcTF;
(* Beep on the speaker: beepFreq during beepLen *)
PROCEDURE Beep*;
VAR wakeUp: LONGINT;
BEGIN
IF ~timerActive THEN
InitTimer;
SetFreq(beepFreq);
wakeUp := Input.Time() + beepLen * (Input.TimeUnit DIV 1000);
REPEAT UNTIL Input.Time() - wakeUp >= 0;
Tone(OFF);
timerActive := FALSE
END
END Beep;
2002 年 7 月 13 日 - 版權所有 © 2002 ETH Zürich。保留所有權利。
電子郵件:oberon at lists.inf.ethz.ch
主頁:http://www.ethoberon.ethz.ch/