From 0e27b956de747825a773554efd57f7d571e5420a Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Fri, 16 Apr 2021 00:09:46 +0100 Subject: [PATCH] Allow full customisation --- examples/beep.rs | 12 ++++++-- src/sound/mod.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 6 deletions(-) diff --git a/examples/beep.rs b/examples/beep.rs index f0dffc49..d45a8f19 100644 --- a/examples/beep.rs +++ b/examples/beep.rs @@ -7,12 +7,18 @@ use gba::sound; #[start] fn main(_argc: isize, _argv: *const *const u8) -> isize { - let mut gba = gba::Gba::new(); + let gba = gba::Gba::new(); gba.sound.enable(); - let sweep_settings = sound::SweepSettings::new(3, sound::SoundDirection::Decrease, 7); - gba.sound.channel1().play_sound(&sweep_settings); + let sweep_settings = sound::SweepSettings::default(); + gba.sound.channel1().play_sound( + 1024, + Some(0), + &sweep_settings, + &sound::EnvelopeSettings::default(), + sound::DutyCycle::Half, + ); loop {} } diff --git a/src/sound/mod.rs b/src/sound/mod.rs index a408fe03..7dfc04c6 100644 --- a/src/sound/mod.rs +++ b/src/sound/mod.rs @@ -46,10 +46,26 @@ impl SoundDirection { } impl Channel1 { - pub fn play_sound(&self, sweep_settings: &SweepSettings) { + pub fn play_sound( + &self, + frequency: u16, + length: Option, + sweep_settings: &SweepSettings, + envelope_settings: &EnvelopeSettings, + duty_cycle: DutyCycle, + ) { CHANNEL_1_SWEEP.set(sweep_settings.as_bits()); - CHANNEL_1_LENGTH_DUTY_ENVELOPE.set(0b111_1_001_01_111111); - CHANNEL_1_FREQUENCY_CONTROL.set(0b1_0_000_01000000000); + let length_bits = length.unwrap_or(0) as u16; + assert!(length_bits < 64, "Length must be less than 64"); + + let length_flag: u16 = length.map(|_| 1 << 14).unwrap_or(0); + let initial: u16 = 1 << 15; + + assert!(frequency < 2048, "Frequency must be less than 2048"); + + CHANNEL_1_LENGTH_DUTY_ENVELOPE + .set(envelope_settings.as_bits() | duty_cycle.as_bits() | length_bits); + CHANNEL_1_FREQUENCY_CONTROL.set(frequency | length_flag | initial); } } @@ -90,3 +106,53 @@ impl Default for SweepSettings { SweepSettings::new(0, SoundDirection::Increase, 0) } } + +pub struct EnvelopeSettings { + step_time: u8, + direction: SoundDirection, + initial_volume: u8, +} + +impl EnvelopeSettings { + pub fn new(step_time: u8, direction: SoundDirection, initial_volume: u8) -> Self { + assert!(step_time < 8, "Step time must be less than 8"); + assert!(initial_volume < 16, "Initial volume must be less that 16"); + EnvelopeSettings { + step_time, + direction, + initial_volume, + } + } + + fn as_bits(&self) -> u16 { + (self.step_time as u16) << 8 + | (self.direction.as_bits() << 11) + | ((self.initial_volume as u16) << 12) + } +} + +impl Default for EnvelopeSettings { + fn default() -> Self { + EnvelopeSettings::new(0, SoundDirection::Increase, 15) + } +} + +pub enum DutyCycle { + OneEighth, + OneQuarter, + Half, + ThreeQuarters, +} + +impl DutyCycle { + fn as_bits(&self) -> u16 { + use DutyCycle::*; + + match &self { + OneEighth => 0, + OneQuarter => 1, + Half => 2, + ThreeQuarters => 3, + } + } +}