Add simple double buffer

This commit is contained in:
Gwilym Kuiper 2021-06-06 11:41:43 +01:00
parent 334472f749
commit 72dbf2ef9c

View file

@ -1,20 +1,24 @@
use crate::memory_mapped::MemoryMapped; use crate::memory_mapped::MemoryMapped;
#[non_exhaustive] #[non_exhaustive]
pub struct Mixer {} pub struct Mixer {
buffer: MixerBuffer,
}
impl Mixer { impl Mixer {
pub(crate) const unsafe fn new() -> Self { pub(crate) const unsafe fn new() -> Self {
Mixer {} Mixer {
buffer: MixerBuffer::new(),
}
} }
pub fn enable(&self) { pub fn enable(&self) {
set_sound_control_register_for_mixer(); set_sound_control_register_for_mixer();
set_timer_counter_for_frequency_and_enable(SOUND_FREQUENCY);
} }
pub fn play_sound_starting_at(&self, sound_memory: &[u8]) { pub fn vblank(&mut self) {
set_timer_counter_for_frequency_and_enable(SOUND_FREQUENCY); self.buffer.swap();
enable_dma1_for_sound(sound_memory);
} }
} }
@ -23,6 +27,34 @@ impl Mixer {
const SOUND_FREQUENCY: i32 = 10512; const SOUND_FREQUENCY: i32 = 10512;
const SOUND_BUFFER_SIZE: usize = 176; const SOUND_BUFFER_SIZE: usize = 176;
struct MixerBuffer {
buffer1: [i8; SOUND_BUFFER_SIZE],
buffer2: [i8; SOUND_BUFFER_SIZE],
buffer_1_active: bool,
}
impl MixerBuffer {
fn new() -> Self {
MixerBuffer {
buffer1: Default::default(),
buffer2: Default::default(),
buffer_1_active: true,
}
}
fn swap(&mut self) {
if self.buffer_1_active {
enable_dma1_for_sound(&self.buffer1);
} else {
enable_dma1_for_sound(&self.buffer2);
}
self.buffer_1_active = !self.buffer_1_active;
}
}
// Once we have proper DMA support, we should use that rather than hard coding these here too // Once we have proper DMA support, we should use that rather than hard coding these here too
const DMA1_SOURCE_ADDR: MemoryMapped<u32> = unsafe { MemoryMapped::new(0x0400_00bc) }; const DMA1_SOURCE_ADDR: MemoryMapped<u32> = unsafe { MemoryMapped::new(0x0400_00bc) };
const DMA1_DEST_ADDR: MemoryMapped<u32> = unsafe { MemoryMapped::new(0x0400_00c0) }; const DMA1_DEST_ADDR: MemoryMapped<u32> = unsafe { MemoryMapped::new(0x0400_00c0) };
@ -38,14 +70,14 @@ const TIMER0_CONTROL: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0102
const SOUND_CONTROL: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0082) }; const SOUND_CONTROL: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0082) };
const SOUND_CONTROL_X: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0084) }; const SOUND_CONTROL_X: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0084) };
fn enable_dma1_for_sound(sound_memory: &[u8]) { fn enable_dma1_for_sound(sound_memory: &[i8]) {
let dest_fixed: u16 = 2 << 5; // dest addr control = fixed let dest_fixed: u16 = 2 << 5; // dest addr control = fixed
let repeat: u16 = 1 << 9; let repeat: u16 = 1 << 9;
let transfer_type: u16 = 1 << 10; // transfer in words let transfer_type: u16 = 1 << 10; // transfer in words
let dma_start_timing: u16 = 3 << 12; // sound fifo timing let dma_start_timing: u16 = 3 << 12; // sound fifo timing
let enable: u16 = 1 << 15; // enable let enable: u16 = 1 << 15; // enable
let address: *const u8 = &sound_memory[0]; let address: *const i8 = &sound_memory[0];
DMA1_SOURCE_ADDR.set(address as u32); DMA1_SOURCE_ADDR.set(address as u32);
DMA1_DEST_ADDR.set(FIFOA_DEST_ADDR); DMA1_DEST_ADDR.set(FIFOA_DEST_ADDR);
DMA1_CONTROL.set(dest_fixed | repeat | transfer_type | dma_start_timing | enable); DMA1_CONTROL.set(dest_fixed | repeat | transfer_type | dma_start_timing | enable);