From 94d15de3f44ca5fe2d021993c9f7377a2c22dbca Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Thu, 10 Jun 2021 22:20:37 +0100 Subject: [PATCH] Move GBA hardware related stuff to hw.rs --- agb/src/sound/mixer/hw.rs | 48 ++++++++++++++++++++++++++++++++ agb/src/sound/mixer/mod.rs | 57 ++++---------------------------------- 2 files changed, 53 insertions(+), 52 deletions(-) create mode 100644 agb/src/sound/mixer/hw.rs diff --git a/agb/src/sound/mixer/hw.rs b/agb/src/sound/mixer/hw.rs new file mode 100644 index 00000000..43d3bf75 --- /dev/null +++ b/agb/src/sound/mixer/hw.rs @@ -0,0 +1,48 @@ +use crate::memory_mapped::MemoryMapped; + +// Once we have proper DMA support, we should use that rather than hard coding these here too +const DMA1_SOURCE_ADDR: MemoryMapped = unsafe { MemoryMapped::new(0x0400_00bc) }; +const DMA1_DEST_ADDR: MemoryMapped = unsafe { MemoryMapped::new(0x0400_00c0) }; +const _DMA1_WORD_COUNT: MemoryMapped = unsafe { MemoryMapped::new(0x0400_00c4) }; // sound ignores this for some reason +const DMA1_CONTROL: MemoryMapped = unsafe { MemoryMapped::new(0x0400_00c6) }; + +const FIFOA_DEST_ADDR: u32 = 0x0400_00a0; + +// Similarly for proper timer support +const TIMER0_COUNTER: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0100) }; +const TIMER0_CONTROL: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0102) }; + +const SOUND_CONTROL: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0082) }; +const SOUND_CONTROL_X: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0084) }; + +pub(super) fn enable_dma1_for_sound(sound_memory: &[i8]) { + let dest_fixed: u16 = 2 << 5; // dest addr control = fixed + let repeat: u16 = 1 << 9; + let transfer_type: u16 = 1 << 10; // transfer in words + let dma_start_timing: u16 = 3 << 12; // sound fifo timing + let enable: u16 = 1 << 15; // enable + + DMA1_CONTROL.set(0); + DMA1_SOURCE_ADDR.set(sound_memory.as_ptr() as u32); + DMA1_DEST_ADDR.set(FIFOA_DEST_ADDR); + DMA1_CONTROL.set(dest_fixed | repeat | transfer_type | dma_start_timing | enable); +} + +pub(super) fn set_sound_control_register_for_mixer() { + let sound_a_volume_100: u16 = 1 << 2; + let sound_a_rout: u16 = 1 << 8; + let sound_a_lout: u16 = 1 << 9; + let sound_a_fifo_reset: u16 = 1 << 11; + + SOUND_CONTROL.set(sound_a_volume_100 | sound_a_rout | sound_a_lout | sound_a_fifo_reset); + + // master sound enable + SOUND_CONTROL_X.set(1 << 7); +} + +pub(super) fn set_timer_counter_for_frequency_and_enable(frequency: i32) { + let counter = 65536 - (16777216 / frequency); + TIMER0_COUNTER.set(counter as u16); + + TIMER0_CONTROL.set(1 << 7); // enable the timer +} diff --git a/agb/src/sound/mixer/mod.rs b/agb/src/sound/mixer/mod.rs index 3c0fbfdc..3c232607 100644 --- a/agb/src/sound/mixer/mod.rs +++ b/agb/src/sound/mixer/mod.rs @@ -1,4 +1,4 @@ -use crate::memory_mapped::MemoryMapped; +mod hw; #[non_exhaustive] pub struct MixerController {} @@ -27,8 +27,8 @@ impl Mixer { } pub fn enable(&self) { - set_timer_counter_for_frequency_and_enable(SOUND_FREQUENCY); - set_sound_control_register_for_mixer(); + hw::set_timer_counter_for_frequency_and_enable(SOUND_FREQUENCY); + hw::set_sound_control_register_for_mixer(); } pub fn vblank(&mut self) { @@ -118,9 +118,9 @@ impl MixerBuffer { self.buffer_1_active = !self.buffer_1_active; if self.buffer_1_active { - enable_dma1_for_sound(&self.buffer1); + hw::enable_dma1_for_sound(&self.buffer1); } else { - enable_dma1_for_sound(&self.buffer2); + hw::enable_dma1_for_sound(&self.buffer2); } } @@ -146,50 +146,3 @@ impl MixerBuffer { } } } - -// Once we have proper DMA support, we should use that rather than hard coding these here too -const DMA1_SOURCE_ADDR: MemoryMapped = unsafe { MemoryMapped::new(0x0400_00bc) }; -const DMA1_DEST_ADDR: MemoryMapped = unsafe { MemoryMapped::new(0x0400_00c0) }; -const _DMA1_WORD_COUNT: MemoryMapped = unsafe { MemoryMapped::new(0x0400_00c4) }; // sound ignores this for some reason -const DMA1_CONTROL: MemoryMapped = unsafe { MemoryMapped::new(0x0400_00c6) }; - -const FIFOA_DEST_ADDR: u32 = 0x0400_00a0; - -// Similarly for proper timer support -const TIMER0_COUNTER: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0100) }; -const TIMER0_CONTROL: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0102) }; - -const SOUND_CONTROL: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0082) }; -const SOUND_CONTROL_X: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0084) }; - -fn enable_dma1_for_sound(sound_memory: &[i8]) { - let dest_fixed: u16 = 2 << 5; // dest addr control = fixed - let repeat: u16 = 1 << 9; - let transfer_type: u16 = 1 << 10; // transfer in words - let dma_start_timing: u16 = 3 << 12; // sound fifo timing - let enable: u16 = 1 << 15; // enable - - DMA1_CONTROL.set(0); - DMA1_SOURCE_ADDR.set(sound_memory.as_ptr() as u32); - DMA1_DEST_ADDR.set(FIFOA_DEST_ADDR); - DMA1_CONTROL.set(dest_fixed | repeat | transfer_type | dma_start_timing | enable); -} - -fn set_sound_control_register_for_mixer() { - let sound_a_volume_100: u16 = 1 << 2; - let sound_a_rout: u16 = 1 << 8; - let sound_a_lout: u16 = 1 << 9; - let sound_a_fifo_reset: u16 = 1 << 11; - - SOUND_CONTROL.set(sound_a_volume_100 | sound_a_rout | sound_a_lout | sound_a_fifo_reset); - - // master sound enable - SOUND_CONTROL_X.set(1 << 7); -} - -fn set_timer_counter_for_frequency_and_enable(frequency: i32) { - let counter = 65536 - (16777216 / frequency); - TIMER0_COUNTER.set(counter as u16); - - TIMER0_CONTROL.set(1 << 7); // enable the timer -}