diff --git a/src/system/patch_sm.rs b/src/system/patch_sm.rs index 4ff35e0..775d090 100644 --- a/src/system/patch_sm.rs +++ b/src/system/patch_sm.rs @@ -10,14 +10,35 @@ pub struct PatchSmSystem { pub audio: audio::Audio, pub adc1: adc::Adc, pub adc2: adc::Adc, - pub c1: Option>, - pub c2: Option>, + pub dac: PatchSmDac, pub sdram: &'static mut [f32], pub flash: crate::flash::Flash, pub internal_usb: Option, pub delay: Delay, } +pub struct PatchSmDac { + c1: Option>, + c2: Option>, +} + +impl PatchSmDac { + fn new(c1: dac::C1, c2: dac::C2) -> Self { + Self { + c1: Some(c1), + c2: Some(c2), + } + } + + pub fn take_c1(&mut self) -> Option> { + self.c1.take() + } + + pub fn take_c2(&mut self) -> Option> { + self.c2.take() + } +} + pub struct MinimalPatchSmSystem { pub gpio: crate::gpio::PatchSmGPIO, pub flash: crate::flash::Flash, @@ -449,8 +470,7 @@ impl PatchSmSystem { audio, adc1, adc2, - c1: Some(c1), - c2: Some(c2), + dac: PatchSmDac::new(c1, c2), sdram, flash, internal_usb: Some(internal_usb), diff --git a/src/system/seed.rs b/src/system/seed.rs index 44bf52d..1ccfbf5 100644 --- a/src/system/seed.rs +++ b/src/system/seed.rs @@ -1,5 +1,5 @@ use log::info; -use stm32h7xx_hal::{adc, delay::Delay, dma, prelude::*, rcc, stm32, time::Hertz}; +use stm32h7xx_hal::{adc, dac, delay::Delay, dma, prelude::*, rcc, stm32, time::Hertz}; use crate::{audio::Audio, *}; @@ -10,12 +10,126 @@ pub struct SeedSystem { pub audio: audio::Audio, pub adc1: adc::Adc, pub adc2: adc::Adc, + pub dac: SeedDac, pub sdram: &'static mut [f32], pub flash: crate::flash::Flash, pub internal_usb: Option, pub delay: Delay, } +pub struct SeedDac { + c1: Option>, + c2: Option>, + state: SeedDacState, +} + +enum SeedDacState { + Uninitialized { + dac: stm32::DAC, + dac12_rec: rcc::rec::Dac12, + }, + Channel1Initialized, + Channel2Initialized, + BothInitialized, +} + +impl SeedDac { + fn new(dac: stm32::DAC, dac12_rec: rcc::rec::Dac12) -> Self { + Self { + c1: None, + c2: None, + state: SeedDacState::Uninitialized { dac, dac12_rec }, + } + } + + pub fn both_initialized(&self) -> bool { + matches!(self.state, SeedDacState::BothInitialized) + } + + pub fn init_channels( + &mut self, + c1_pin: hal::gpio::gpioa::PA4, + c2_pin: hal::gpio::gpioa::PA5, + ) -> Option<()> { + match self.state { + SeedDacState::BothInitialized => return Some(()), + SeedDacState::Channel1Initialized | SeedDacState::Channel2Initialized => { + return None; + } + SeedDacState::Uninitialized { .. } => {} + } + + let SeedDacState::Uninitialized { dac, dac12_rec } = + core::mem::replace(&mut self.state, SeedDacState::BothInitialized) + else { + return None; + }; + let (c1, c2) = dac::dac(dac, (c1_pin, c2_pin), dac12_rec); + + self.c1 = Some(c1); + self.c2 = Some(c2); + Some(()) + } + + fn init_c1(&mut self, c1_pin: hal::gpio::gpioa::PA4) -> Option<()> { + if self.c1.is_some() { + return Some(()); + } + + let SeedDacState::Uninitialized { dac, dac12_rec } = + core::mem::replace(&mut self.state, SeedDacState::Channel1Initialized) + else { + return None; + }; + let c1 = dac::dac(dac, c1_pin, dac12_rec); + self.c1 = Some(c1); + Some(()) + } + + fn init_c2(&mut self, c2_pin: hal::gpio::gpioa::PA5) -> Option<()> { + if self.c2.is_some() { + return Some(()); + } + + let SeedDacState::Uninitialized { dac, dac12_rec } = + core::mem::replace(&mut self.state, SeedDacState::Channel2Initialized) + else { + return None; + }; + let c2 = dac::dac(dac, c2_pin, dac12_rec); + self.c2 = Some(c2); + Some(()) + } + + pub fn take_c1_with_pin( + &mut self, + c1_pin: hal::gpio::gpioa::PA4, + ) -> Option> { + if self.c1.is_none() { + self.init_c1(c1_pin)?; + } + self.c1.take() + } + + pub fn take_c2_with_pin( + &mut self, + c2_pin: hal::gpio::gpioa::PA5, + ) -> Option> { + if self.c2.is_none() { + self.init_c2(c2_pin)?; + } + self.c2.take() + } + + pub fn take_c1(&mut self) -> Option> { + self.c1.take() + } + + pub fn take_c2(&mut self) -> Option> { + self.c2.take() + } +} + pub struct MinimalSeedSystem { pub gpio: crate::gpio::SeedGPIO, pub flash: crate::flash::Flash, @@ -495,6 +609,7 @@ impl SeedSystem { audio, adc1, adc2, + dac: SeedDac::new(resources.dac, resources.dac12_rec), sdram, flash, internal_usb: Some(internal_usb),