1use core::convert::Infallible;
2use core::marker::PhantomData;
3
4use crate::codec::{Codec, Pins as CodecPins};
5use defmt::info;
6use embassy_stm32::{self as hal, Peri};
7use grounded::uninit::GroundedArrayCell;
8
9use hal::sai::{self, MasterClockDivider};
10
11pub const BLOCK_LENGTH: usize = 32; pub const HALF_DMA_BUFFER_LENGTH: usize = BLOCK_LENGTH * 2; pub const DMA_BUFFER_LENGTH: usize = HALF_DMA_BUFFER_LENGTH * 2; #[unsafe(link_section = ".sram1_bss")]
21static TX_BUFFER: GroundedArrayCell<u32, DMA_BUFFER_LENGTH> = GroundedArrayCell::uninit();
22#[unsafe(link_section = ".sram1_bss")]
23static RX_BUFFER: GroundedArrayCell<u32, DMA_BUFFER_LENGTH> = GroundedArrayCell::uninit();
24
25pub type InterleavedBlock = [u32; HALF_DMA_BUFFER_LENGTH];
28
29pub struct AudioPeripherals<'a> {
37 pub codec_pins: CodecPins<'a>,
38 pub sai1: Peri<'a, hal::peripherals::SAI1>,
39 pub i2c2: Peri<'a, hal::peripherals::I2C2>,
40 pub dma1_ch0: Peri<'a, hal::peripherals::DMA1_CH0>,
41 pub dma1_ch1: Peri<'a, hal::peripherals::DMA1_CH1>,
42 pub dma1_ch2: Peri<'a, hal::peripherals::DMA1_CH2>,
43}
44
45impl<'a> AudioPeripherals<'a> {
46 pub async fn prepare_interface(self, audio_config: AudioConfig) -> Interface<'a, Idle> {
60 let tx_buffer: &mut [u32] = unsafe {
61 TX_BUFFER.initialize_all_copied(0);
62 let (ptr, len) = TX_BUFFER.get_ptr_len();
63 core::slice::from_raw_parts_mut(ptr, len)
64 };
65
66 let rx_buffer: &mut [u32] = unsafe {
67 RX_BUFFER.initialize_all_copied(0);
68 let (ptr, len) = RX_BUFFER.get_ptr_len();
69 core::slice::from_raw_parts_mut(ptr, len)
70 };
71
72 Interface {
73 codec: Codec::new(self, audio_config, tx_buffer, rx_buffer).await,
74 _state: PhantomData,
75 }
76 }
77}
78
79pub struct Idle {}
80pub struct Running {}
81pub trait InterfaceState {}
82impl InterfaceState for Idle {}
83impl InterfaceState for Running {}
84
85pub struct Interface<'a, S: InterfaceState> {
143 codec: Codec<'a>,
144 _state: PhantomData<S>,
145}
146
147impl<'a> Interface<'a, Idle> {
148 pub async fn start_interface(mut self) -> Result<Interface<'a, Running>, sai::Error> {
151 self.codec.start().await?;
152 Ok(Interface {
153 codec: self.codec,
154 _state: PhantomData,
155 })
156 }
157
158 #[cfg(any(feature = "seed_1_1", feature = "patch_sm"))]
160 pub async fn setup_and_release(
161 self,
162 ) -> Result<
163 (
164 sai::Sai<'a, hal::peripherals::SAI1, u32>,
165 sai::Sai<'a, hal::peripherals::SAI1, u32>,
166 hal::i2c::I2c<'a, hal::mode::Blocking, hal::i2c::Master>,
167 ),
168 sai::Error,
169 > {
170 self.start_interface().await.map(|i| i.codec.release())
171 }
172}
173
174impl Interface<'_, Running> {
175 pub async fn start_callback(
176 &mut self,
177 mut callback: impl FnMut(&[u32], &mut [u32]),
178 ) -> Result<Infallible, sai::Error> {
179 info!("enter audio callback loop");
180 let mut write_buf = [0; HALF_DMA_BUFFER_LENGTH];
181 let mut read_buf = [0; HALF_DMA_BUFFER_LENGTH];
182 loop {
183 self.codec.read(&mut read_buf).await?;
184 callback(&read_buf, &mut write_buf);
185 self.codec.write(&write_buf).await?;
186 }
187 }
188}
189
190impl<S: InterfaceState> Interface<'_, S> {
191 pub fn sai_rx_config(&self) -> &sai::Config {
192 &self.codec.sai_rx_config
193 }
194
195 pub fn sai_tx_config(&self) -> &sai::Config {
196 &self.codec.sai_tx_config
197 }
198}
199#[derive(Clone, Copy)]
200pub enum Fs {
201 Fs8000,
202 Fs32000,
203 Fs44100,
204 Fs48000,
205 Fs88200,
206 Fs96000,
207}
208const CLOCK_RATIO: u32 = 256; impl Fs {
210 pub fn into_clock_divider(self) -> MasterClockDivider {
211 let fs = match self {
212 Fs::Fs8000 => 8000,
213 Fs::Fs32000 => 32000,
214 Fs::Fs44100 => 44100,
215 Fs::Fs48000 => 48000,
216 Fs::Fs88200 => 88200,
217 Fs::Fs96000 => 96000,
218 };
219 let kernel_clock = hal::rcc::frequency::<hal::peripherals::SAI1>().0;
220 let mclk_div = (kernel_clock / (fs * CLOCK_RATIO)) as u8;
221 mclk_div_from_u8(mclk_div)
222 }
223}
224
225pub struct AudioConfig {
226 pub fs: Fs,
227}
228
229impl Default for AudioConfig {
230 fn default() -> Self {
231 AudioConfig { fs: Fs::Fs48000 }
232 }
233}
234
235const fn mclk_div_from_u8(v: u8) -> MasterClockDivider {
238 match v {
239 1 => MasterClockDivider::DIV1,
240 2 => MasterClockDivider::DIV2,
241 3 => MasterClockDivider::DIV3,
242 4 => MasterClockDivider::DIV4,
243 5 => MasterClockDivider::DIV5,
244 6 => MasterClockDivider::DIV6,
245 7 => MasterClockDivider::DIV7,
246 8 => MasterClockDivider::DIV8,
247 9 => MasterClockDivider::DIV9,
248 10 => MasterClockDivider::DIV10,
249 11 => MasterClockDivider::DIV11,
250 12 => MasterClockDivider::DIV12,
251 13 => MasterClockDivider::DIV13,
252 14 => MasterClockDivider::DIV14,
253 15 => MasterClockDivider::DIV15,
254 16 => MasterClockDivider::DIV16,
255 17 => MasterClockDivider::DIV17,
256 18 => MasterClockDivider::DIV18,
257 19 => MasterClockDivider::DIV19,
258 20 => MasterClockDivider::DIV20,
259 21 => MasterClockDivider::DIV21,
260 22 => MasterClockDivider::DIV22,
261 23 => MasterClockDivider::DIV23,
262 24 => MasterClockDivider::DIV24,
263 25 => MasterClockDivider::DIV25,
264 26 => MasterClockDivider::DIV26,
265 27 => MasterClockDivider::DIV27,
266 28 => MasterClockDivider::DIV28,
267 29 => MasterClockDivider::DIV29,
268 30 => MasterClockDivider::DIV30,
269 31 => MasterClockDivider::DIV31,
270 32 => MasterClockDivider::DIV32,
271 33 => MasterClockDivider::DIV33,
272 34 => MasterClockDivider::DIV34,
273 35 => MasterClockDivider::DIV35,
274 36 => MasterClockDivider::DIV36,
275 37 => MasterClockDivider::DIV37,
276 38 => MasterClockDivider::DIV38,
277 39 => MasterClockDivider::DIV39,
278 40 => MasterClockDivider::DIV40,
279 41 => MasterClockDivider::DIV41,
280 42 => MasterClockDivider::DIV42,
281 43 => MasterClockDivider::DIV43,
282 44 => MasterClockDivider::DIV44,
283 45 => MasterClockDivider::DIV45,
284 46 => MasterClockDivider::DIV46,
285 47 => MasterClockDivider::DIV47,
286 48 => MasterClockDivider::DIV48,
287 49 => MasterClockDivider::DIV49,
288 50 => MasterClockDivider::DIV50,
289 51 => MasterClockDivider::DIV51,
290 52 => MasterClockDivider::DIV52,
291 53 => MasterClockDivider::DIV53,
292 54 => MasterClockDivider::DIV54,
293 55 => MasterClockDivider::DIV55,
294 56 => MasterClockDivider::DIV56,
295 57 => MasterClockDivider::DIV57,
296 58 => MasterClockDivider::DIV58,
297 59 => MasterClockDivider::DIV59,
298 60 => MasterClockDivider::DIV60,
299 61 => MasterClockDivider::DIV61,
300 62 => MasterClockDivider::DIV62,
301 63 => MasterClockDivider::DIV63,
302 _ => panic!(),
303 }
304}