pub trait PwmDutySink {
fn set_duty(&mut self, duty: u16);
}
impl<F: FnMut(u16)> PwmDutySink for F {
fn set_duty(&mut self, duty: u16) {
self(duty);
}
}
#[inline]
pub fn tick_into<S: PwmDutySink, const N: usize>(
engine: &mut crate::AudioEngine<'_, N>,
sink: &mut S,
) -> u16 {
let duty = engine.tick();
sink.set_duty(duty);
duty
}
pub fn fill_buffer_into<S: PwmDutySink, const N: usize>(
engine: &mut crate::AudioEngine<'_, N>,
buf: &mut [u16],
sink: &mut S,
) -> usize {
let n = engine.fill_duty_buffer(buf);
if let Some(&duty) = buf.last() {
sink.set_duty(duty);
}
n
}
pub fn fill_dma_half_buffers<const N: usize>(
engine: &mut crate::AudioEngine<'_, N>,
half_buf: &mut [u16],
) -> usize {
engine.fill_duty_buffer(half_buf)
}
#[derive(Debug, PartialEq, Eq)]
pub struct DutyBuffer<'a> {
pub buf: &'a mut [u16],
pub cursor: usize,
}
impl<'a> DutyBuffer<'a> {
pub const fn new(buf: &'a mut [u16]) -> Self {
Self { buf, cursor: 0 }
}
}
impl PwmDutySink for DutyBuffer<'_> {
fn set_duty(&mut self, duty: u16) {
if self.cursor < self.buf.len() {
self.buf[self.cursor] = duty;
self.cursor += 1;
}
}
}
#[derive(Debug, Clone)]
pub struct DmaDoubleBuffer<T, const N: usize> {
buffer: [[T; N]; 2],
active_half: usize,
}
impl<T: Copy + Default, const N: usize> DmaDoubleBuffer<T, N> {
pub const HALF_SIZE: usize = N;
pub const TOTAL_SIZE: usize = N * 2;
pub fn new() -> Self {
Self {
buffer: [[T::default(); N]; 2],
active_half: 0,
}
}
pub const fn from_buffers(buf0: [T; N], buf1: [T; N]) -> Self {
Self {
buffer: [buf0, buf1],
active_half: 0,
}
}
pub fn buffers(&self) -> &[[T; N]; 2] {
&self.buffer
}
pub fn buffers_mut(&mut self) -> &mut [[T; N]; 2] {
&mut self.buffer
}
pub fn current_half_mut(&mut self) -> &mut [T; N] {
&mut self.buffer[self.active_half]
}
pub fn current_half(&self) -> &[T; N] {
&self.buffer[self.active_half]
}
pub fn swap_and_get_next(&mut self) -> &mut [T; N] {
self.active_half ^= 1;
self.current_half_mut()
}
pub fn fill_and_swap<F>(&mut self, mut fill_fn: F) -> &mut [T; N]
where
F: FnMut(&mut [T; N]),
{
let next_half = self.active_half ^ 1;
fill_fn(&mut self.buffer[next_half]);
self.active_half = next_half;
&mut self.buffer[next_half]
}
}
impl<T: Copy + Default, const N: usize> Default for DmaDoubleBuffer<T, N> {
fn default() -> Self {
Self::new()
}
}