diff --git a/Makefile b/Makefile index 01f32a5f..8337ec74 100644 --- a/Makefile +++ b/Makefile @@ -79,7 +79,7 @@ CORE_FILES=const.js config.js io.js main.js lib.js fpu.js ide.js pci.js floppy.j elf.js LIB_FILES=9p.js filesystem.js jor1k.js marshall.js utf8.js BROWSER_FILES=screen.js \ - keyboard.js mouse.js serial.js \ + keyboard.js mouse.js speaker.js serial.js \ network.js lib.js starter.js worker_bus.js dummy_screen.js CORE_FILES:=$(addprefix src/,$(CORE_FILES)) diff --git a/loader.js b/loader.js index 9f474a72..b92103c3 100644 --- a/loader.js +++ b/loader.js @@ -10,7 +10,7 @@ "memory.js dma.js pit.js vga.js ps2.js pic.js rtc.js uart.js acpi.js apic.js ioapic.js hpet.js " + "ne2k.js state.js virtio.js bus.js elf.js"; - var BROWSER_FILES = "main.js screen.js keyboard.js mouse.js serial.js lib.js network.js starter.js worker_bus.js"; + var BROWSER_FILES = "main.js screen.js keyboard.js mouse.js speaker.js serial.js lib.js network.js starter.js worker_bus.js"; //var LIB_FILES = "esprima.js walk.js"; var LIB_FILES = ""; diff --git a/src/browser/speaker.js b/src/browser/speaker.js new file mode 100755 index 00000000..4cd83a87 --- /dev/null +++ b/src/browser/speaker.js @@ -0,0 +1,67 @@ +"use strict"; + +/** + * @constructor + * @param {BusConnector} bus + * @suppress {deprecated} + */ +function SpeakerAdapter(bus) +{ + if (typeof window === "undefined") + { + return; + } + + /** @const @type {BusConnector} */ + this.bus = bus; + + this.audio_context = new (window.AudioContext || window.webkitAudioContext)(); + + this.beep_gain = this.audio_context.createGain(); + this.beep_gain.gain.value = 0; + this.beep_gain.connect(this.audio_context.destination); + + this.beep_oscillator = this.audio_context.createOscillator(); + this.beep_oscillator.type = 'square'; + this.beep_oscillator.frequency.value = 440; + this.beep_oscillator.connect(this.beep_gain); + this.beep_oscillator.start(); + + this.beep_playing = false; + this.beep_enable = false; + this.beep_frequency = 440; + this.pit_enabled = false; + + bus.register("pcspeaker-enable", function(yesplease) + { + this.beep_enable = yesplease; + this.beep_update(); + }, this); + + bus.register("pcspeaker-update", function(pit) + { + this.pit_enabled = pit.counter_mode[2] == 3; + this.beep_frequency = OSCILLATOR_FREQ * 1000 / pit.counter_reload[2]; + this.beep_update(); + }, this); +} + +SpeakerAdapter.prototype.beep_update = function() +{ + var current_time = this.audio_context.currentTime; + + if(this.pit_enabled && this.beep_enable) + { + this.beep_oscillator.frequency.setValueAtTime(this.beep_frequency, current_time); + if(!this.beep_playing) + { + this.beep_gain.gain.setValueAtTime(1, current_time); + this.beep_playing = true; + } + } + else if(this.beep_playing) + { + this.beep_gain.gain.setValueAtTime(0, current_time); + this.beep_playing = false; + } +} diff --git a/src/browser/starter.js b/src/browser/starter.js index e0159218..fd64311a 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -151,6 +151,11 @@ function V86Starter(options) this.serial_adapter = new SerialAdapter(options["serial_container"], adapter_bus); } + if(!options["disable_speaker"]) + { + this.speaker_adapter = new SpeakerAdapter(adapter_bus); + } + // ugly, but required for closure compiler compilation function put_on_settings(name, buffer) { diff --git a/src/cpu.js b/src/cpu.js index 5194a189..d9056a1e 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -736,7 +736,7 @@ CPU.prototype.init = function(settings, device_bus) this.devices.hdb = new IDEDevice(this, settings.hdb, false, ide_device_count++, device_bus); } - this.devices.pit = new PIT(this); + this.devices.pit = new PIT(this, device_bus); if(settings.enable_ne2k) { diff --git a/src/pit.js b/src/pit.js index d3f96429..c47ed21c 100644 --- a/src/pit.js +++ b/src/pit.js @@ -11,11 +11,13 @@ var OSCILLATOR_FREQ = 1193.1816666; // 1.193182 MHz * * Programmable Interval Timer */ -function PIT(cpu) +function PIT(cpu, bus) { /** @const @type {CPU} */ this.cpu = cpu; + this.bus = bus; + this.counter_start_time = new Float64Array(3); this.counter_start_value = new Uint16Array(3); @@ -42,6 +44,10 @@ function PIT(cpu) return ref_toggle << 4 | counter2_out << 5; }); + cpu.io.register_write(0x61, this, function(data) + { + this.bus.send("pcspeaker-enable", data & 1); + }); cpu.io.register_read(0x40, this, function() { return this.counter_read(0); }); cpu.io.register_read(0x41, this, function() { return this.counter_read(1); }); @@ -228,6 +234,8 @@ PIT.prototype.counter_write = function(i, value) { this.counter_next_low[i] ^= 1; } + + this.bus.send("pcspeaker-update", this); }; PIT.prototype.port43_write = function(reg_byte) @@ -303,4 +311,6 @@ PIT.prototype.port43_write = function(reg_byte) this.counter_mode[i] = mode; this.counter_read_mode[i] = read_mode; + + this.bus.send("pcspeaker-update", this); };