From 1f25e96533be4a2cdaef3c2e7ede2d07c07cfa66 Mon Sep 17 00:00:00 2001 From: Stephen Hensley Date: Thu, 30 Apr 2026 09:27:30 -0700 Subject: [PATCH 1/2] dac initialization methods for the seed, and methods for taking dac pins for patch_sm --- src/system/patch_sm.rs | 8 ++++ src/system/seed.rs | 90 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/src/system/patch_sm.rs b/src/system/patch_sm.rs index 4ff35e0..9dfc956 100644 --- a/src/system/patch_sm.rs +++ b/src/system/patch_sm.rs @@ -457,4 +457,12 @@ impl PatchSmSystem { delay, } } + + pub fn take_dac_c1(&mut self) -> Option> { + self.c1.take() + } + + pub fn take_dac_c2(&mut self) -> Option> { + self.c2.take() + } } diff --git a/src/system/seed.rs b/src/system/seed.rs index 44bf52d..f148f8b 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,25 @@ pub struct SeedSystem { pub audio: audio::Audio, pub adc1: adc::Adc, pub adc2: adc::Adc, + pub c1: Option>, + pub c2: Option>, + dac_state: SeedDacState, pub sdram: &'static mut [f32], pub flash: crate::flash::Flash, pub internal_usb: Option, pub delay: Delay, } +enum SeedDacState { + Uninitialized { + dac: stm32::DAC, + dac12_rec: rcc::rec::Dac12, + }, + Channel1Initialized, + Channel2Initialized, + BothInitialized, +} + pub struct MinimalSeedSystem { pub gpio: crate::gpio::SeedGPIO, pub flash: crate::flash::Flash, @@ -495,10 +508,85 @@ impl SeedSystem { audio, adc1, adc2, + c1: None, + c2: None, + dac_state: SeedDacState::Uninitialized { + dac: resources.dac, + dac12_rec: resources.dac12_rec, + }, sdram, flash, internal_usb: Some(internal_usb), delay, } } + + pub fn init_dac_channels(&mut self) -> Option<()> { + match self.dac_state { + SeedDacState::BothInitialized => return Some(()), + SeedDacState::Channel1Initialized | SeedDacState::Channel2Initialized => { + return None; + } + SeedDacState::Uninitialized { .. } => {} + } + + let SeedDacState::Uninitialized { dac, dac12_rec } = + core::mem::replace(&mut self.dac_state, SeedDacState::BothInitialized) + else { + return None; + }; + let c1_pin = self.gpio.daisy23.take()?; + let c2_pin = self.gpio.daisy22.take()?; + let (c1, c2) = dac::dac(dac, (c1_pin, c2_pin), dac12_rec); + + self.c1 = Some(c1); + self.c2 = Some(c2); + Some(()) + } + + fn init_dac_c1(&mut self) -> Option<()> { + if self.c1.is_some() { + return Some(()); + } + + let SeedDacState::Uninitialized { dac, dac12_rec } = + core::mem::replace(&mut self.dac_state, SeedDacState::Channel1Initialized) + else { + return None; + }; + let c1_pin = self.gpio.daisy23.take()?; + let c1 = dac::dac(dac, c1_pin, dac12_rec); + self.c1 = Some(c1); + Some(()) + } + + fn init_dac_c2(&mut self) -> Option<()> { + if self.c2.is_some() { + return Some(()); + } + + let SeedDacState::Uninitialized { dac, dac12_rec } = + core::mem::replace(&mut self.dac_state, SeedDacState::Channel2Initialized) + else { + return None; + }; + let c2_pin = self.gpio.daisy22.take()?; + let c2 = dac::dac(dac, c2_pin, dac12_rec); + self.c2 = Some(c2); + Some(()) + } + + pub fn take_dac_c1(&mut self) -> Option> { + if self.c1.is_none() { + self.init_dac_c1()?; + } + self.c1.take() + } + + pub fn take_dac_c2(&mut self) -> Option> { + if self.c2.is_none() { + self.init_dac_c2()?; + } + self.c2.take() + } } From 22a4cb825212a799e84801d8e266dfc9182229b0 Mon Sep 17 00:00:00 2001 From: Stephen Hensley Date: Fri, 1 May 2026 08:46:17 -0700 Subject: [PATCH 2/2] refactor DAC management to its own struct to prevent borrow/ownership issues with usage from templates. --- src/system/patch_sm.rs | 36 +++++--- src/system/seed.rs | 183 +++++++++++++++++++++++------------------ 2 files changed, 129 insertions(+), 90 deletions(-) diff --git a/src/system/patch_sm.rs b/src/system/patch_sm.rs index 9dfc956..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,20 +470,11 @@ impl PatchSmSystem { audio, adc1, adc2, - c1: Some(c1), - c2: Some(c2), + dac: PatchSmDac::new(c1, c2), sdram, flash, internal_usb: Some(internal_usb), delay, } } - - pub fn take_dac_c1(&mut self) -> Option> { - self.c1.take() - } - - pub fn take_dac_c2(&mut self) -> Option> { - self.c2.take() - } } diff --git a/src/system/seed.rs b/src/system/seed.rs index f148f8b..1ccfbf5 100644 --- a/src/system/seed.rs +++ b/src/system/seed.rs @@ -10,15 +10,19 @@ pub struct SeedSystem { pub audio: audio::Audio, pub adc1: adc::Adc, pub adc2: adc::Adc, - pub c1: Option>, - pub c2: Option>, - dac_state: SeedDacState, + 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, @@ -29,6 +33,103 @@ enum SeedDacState { 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, @@ -508,85 +609,11 @@ impl SeedSystem { audio, adc1, adc2, - c1: None, - c2: None, - dac_state: SeedDacState::Uninitialized { - dac: resources.dac, - dac12_rec: resources.dac12_rec, - }, + dac: SeedDac::new(resources.dac, resources.dac12_rec), sdram, flash, internal_usb: Some(internal_usb), delay, } } - - pub fn init_dac_channels(&mut self) -> Option<()> { - match self.dac_state { - SeedDacState::BothInitialized => return Some(()), - SeedDacState::Channel1Initialized | SeedDacState::Channel2Initialized => { - return None; - } - SeedDacState::Uninitialized { .. } => {} - } - - let SeedDacState::Uninitialized { dac, dac12_rec } = - core::mem::replace(&mut self.dac_state, SeedDacState::BothInitialized) - else { - return None; - }; - let c1_pin = self.gpio.daisy23.take()?; - let c2_pin = self.gpio.daisy22.take()?; - let (c1, c2) = dac::dac(dac, (c1_pin, c2_pin), dac12_rec); - - self.c1 = Some(c1); - self.c2 = Some(c2); - Some(()) - } - - fn init_dac_c1(&mut self) -> Option<()> { - if self.c1.is_some() { - return Some(()); - } - - let SeedDacState::Uninitialized { dac, dac12_rec } = - core::mem::replace(&mut self.dac_state, SeedDacState::Channel1Initialized) - else { - return None; - }; - let c1_pin = self.gpio.daisy23.take()?; - let c1 = dac::dac(dac, c1_pin, dac12_rec); - self.c1 = Some(c1); - Some(()) - } - - fn init_dac_c2(&mut self) -> Option<()> { - if self.c2.is_some() { - return Some(()); - } - - let SeedDacState::Uninitialized { dac, dac12_rec } = - core::mem::replace(&mut self.dac_state, SeedDacState::Channel2Initialized) - else { - return None; - }; - let c2_pin = self.gpio.daisy22.take()?; - let c2 = dac::dac(dac, c2_pin, dac12_rec); - self.c2 = Some(c2); - Some(()) - } - - pub fn take_dac_c1(&mut self) -> Option> { - if self.c1.is_none() { - self.init_dac_c1()?; - } - self.c1.take() - } - - pub fn take_dac_c2(&mut self) -> Option> { - if self.c2.is_none() { - self.init_dac_c2()?; - } - self.c2.take() - } }