Skip to content

Commit

Permalink
Add speaker device for the beep command
Browse files Browse the repository at this point in the history
  • Loading branch information
vinc committed Oct 22, 2024
1 parent 9584f8a commit 0645094
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 27 deletions.
1 change: 1 addition & 0 deletions src/api/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ fn device_type(name: &str) -> Result<DeviceType, ()> {
"vga-font" => Ok(DeviceType::VgaFont),
"vga-mode" => Ok(DeviceType::VgaMode),
"vga-palette" => Ok(DeviceType::VgaPalette),
"speaker" => Ok(DeviceType::Speaker),
"ata" => Ok(DeviceType::Drive),
_ => Err(()),
}
Expand Down
9 changes: 9 additions & 0 deletions src/sys/fs/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::sys::console::Console;
use crate::sys::net::socket::tcp::TcpSocket;
use crate::sys::net::socket::udp::UdpSocket;
use crate::sys::rng::Random;
use crate::sys::speaker::Speaker;
use crate::sys::vga::{VgaFont, VgaMode, VgaPalette, VgaBuffer};

use alloc::vec;
Expand All @@ -33,6 +34,7 @@ pub enum DeviceType {
VgaFont = 11,
VgaMode = 12,
VgaPalette = 13,
Speaker = 14,
}

impl TryFrom<&[u8]> for DeviceType {
Expand All @@ -54,6 +56,7 @@ impl TryFrom<&[u8]> for DeviceType {
11 => Ok(DeviceType::VgaFont),
12 => Ok(DeviceType::VgaMode),
13 => Ok(DeviceType::VgaPalette),
14 => Ok(DeviceType::Speaker),
_ => Err(()),
}
}
Expand Down Expand Up @@ -98,6 +101,7 @@ pub enum Device {
VgaFont(VgaFont),
VgaMode(VgaMode),
VgaPalette(VgaPalette),
Speaker(Speaker),
Drive(Drive),
}

Expand All @@ -119,6 +123,7 @@ impl TryFrom<&[u8]> for Device {
DeviceType::VgaFont => Ok(Device::VgaFont(VgaFont::new())),
DeviceType::VgaMode => Ok(Device::VgaMode(VgaMode::new())),
DeviceType::VgaPalette => Ok(Device::VgaPalette(VgaPalette::new())),
DeviceType::Speaker => Ok(Device::Speaker(Speaker::new())),
DeviceType::Drive if buf.len() > 2 => {
let bus = buf[1];
let dsk = buf[2];
Expand Down Expand Up @@ -181,6 +186,7 @@ impl FileIO for Device {
Device::VgaFont(io) => io.read(buf),
Device::VgaMode(io) => io.read(buf),
Device::VgaPalette(io) => io.read(buf),
Device::Speaker(io) => io.read(buf),
Device::Drive(io) => io.read(buf),
}
}
Expand All @@ -200,6 +206,7 @@ impl FileIO for Device {
Device::VgaFont(io) => io.write(buf),
Device::VgaMode(io) => io.write(buf),
Device::VgaPalette(io) => io.write(buf),
Device::Speaker(io) => io.write(buf),
Device::Drive(io) => io.write(buf),
}
}
Expand All @@ -219,6 +226,7 @@ impl FileIO for Device {
Device::VgaFont(io) => io.close(),
Device::VgaMode(io) => io.close(),
Device::VgaPalette(io) => io.close(),
Device::Speaker(io) => io.close(),
Device::Drive(io) => io.close(),
}
}
Expand All @@ -238,6 +246,7 @@ impl FileIO for Device {
Device::VgaFont(io) => io.poll(event),
Device::VgaMode(io) => io.poll(event),
Device::VgaPalette(io) => io.poll(event),
Device::Speaker(io) => io.poll(event),
Device::Drive(io) => io.poll(event),
}
}
Expand Down
1 change: 1 addition & 0 deletions src/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,6 @@ pub mod pic;
pub mod process;
pub mod rng;
pub mod serial;
pub mod speaker;
pub mod syscall;
pub mod vga;
65 changes: 65 additions & 0 deletions src/sys/speaker.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use super::clk;

use crate::api::fs::{FileIO, IO};

use core::convert::TryInto;
use x86_64::instructions::port::Port;

#[derive(Debug, Clone)]
pub struct Speaker;

impl Speaker {
pub fn new() -> Self {
Self {}
}
}

impl FileIO for Speaker {
fn read(&mut self, _buf: &mut [u8]) -> Result<usize, ()> {
Err(())
}

fn write(&mut self, buf: &[u8]) -> Result<usize, ()> {
if let Ok(bytes) = buf.try_into() {
match f64::from_be_bytes(bytes) {
0.0 => stop_sound(),
freq => start_sound(freq),
}
return Ok(8);
}
Err(())
}

fn close(&mut self) {}

fn poll(&mut self, event: IO) -> bool {
match event {
IO::Read => false,
IO::Write => true,
}
}
}

// See: https://wiki.osdev.org/PC_Speaker

const SPEAKER_PORT: u16 = 0x61;

fn start_sound(freq: f64) {
debug!("speaker::start_sound({})", freq);
let divider = (clk::pit_frequency() / freq) as u16;
let channel = 2;
clk::set_pit_frequency(divider, channel);

let mut speaker: Port<u8> = Port::new(SPEAKER_PORT);
let tmp = unsafe { speaker.read() };
if tmp != (tmp | 3) {
unsafe { speaker.write(tmp | 3) };
}
}

fn stop_sound() {
debug!("speaker::stop_sound()");
let mut speaker: Port<u8> = Port::new(SPEAKER_PORT);
let tmp = unsafe { speaker.read() } & 0xFC;
unsafe { speaker.write(tmp) };
}
42 changes: 17 additions & 25 deletions src/usr/beep.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,28 @@
use crate::api::console::Style;
use crate::api::process::ExitCode;
use crate::{api, sys};
use crate::api::fs;
use crate::api::syscall;

use x86_64::instructions::port::Port;
const SPEAKER: &'static str = "/dev/speaker";

// See: https://wiki.osdev.org/PC_Speaker

const SPEAKER_PORT: u16 = 0x61;

fn start_sound(freq: f64) {
let divider = (sys::clk::pit_frequency() / freq) as u16;
let channel = 2;
sys::clk::set_pit_frequency(divider, channel);

let mut speaker: Port<u8> = Port::new(SPEAKER_PORT);
let tmp = unsafe { speaker.read() };
if tmp != (tmp | 3) {
unsafe { speaker.write(tmp | 3) };
fn start_sound(freq: f64) -> Result<(), ExitCode> {
let buf = freq.to_be_bytes();
if !fs::is_device(SPEAKER) || fs::write(SPEAKER, &buf).is_err() {
error!("Could not write to '{}'", SPEAKER);
Err(ExitCode::Failure)
} else {
Ok(())
}
}

fn stop_sound() {
let mut speaker: Port<u8> = Port::new(SPEAKER_PORT);
let tmp = unsafe { speaker.read() } & 0xFC;
unsafe { speaker.write(tmp) };
fn stop_sound() -> Result<(), ExitCode> {
start_sound(0.0)
}

fn beep(freq: f64, len: f64) {
start_sound(freq);
api::syscall::sleep(len);
stop_sound();
fn beep(freq: f64, len: f64) -> Result<(), ExitCode> {
start_sound(freq)?;
syscall::sleep(len);
stop_sound()
}

pub fn main(args: &[&str]) -> Result<(), ExitCode> {
Expand Down Expand Up @@ -75,8 +68,7 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
i += 1;
}

beep(freq, len / 1000.0);
Ok(())
beep(freq, len / 1000.0)
}

fn help() -> Result<(), ExitCode> {
Expand Down
5 changes: 3 additions & 2 deletions src/usr/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,12 @@ pub fn copy_files(verbose: bool) {
create_dev("/dev/clk/boot", "clk-boot", verbose);
create_dev("/dev/clk/epoch", "clk-epoch", verbose);
create_dev("/dev/clk/rtc", "clk-rtc", verbose);
create_dev("/dev/null", "null", verbose);
create_dev("/dev/random", "random", verbose);
create_dev("/dev/console", "console", verbose);
create_dev("/dev/net/tcp", "tcp", verbose);
create_dev("/dev/net/udp", "udp", verbose);
create_dev("/dev/null", "null", verbose);
create_dev("/dev/random", "random", verbose);
create_dev("/dev/speaker", "speaker", verbose);
create_dev("/dev/vga/buffer", "vga-buffer", verbose);
create_dev("/dev/vga/font", "vga-font", verbose);
create_dev("/dev/vga/mode", "vga-mode", verbose);
Expand Down

0 comments on commit 0645094

Please sign in to comment.