aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-08-25 17:31:38 +0200
committerDario Nieuwenhuis <[email protected]>2025-09-05 15:19:22 +0200
commit60b640bd977ac2d056061e0c0b7a497f815417f4 (patch)
treee09d531dbf5583f9621352300cc81bd46997ff9f
parentf6414d8cd22d18eb1adc5dfa2780bc94a150be30 (diff)
stm32/sai: update for new metapac, simplify cfgs.
-rw-r--r--embassy-stm32/src/sai/mod.rs318
-rw-r--r--examples/stm32h7/src/bin/sai.rs72
-rw-r--r--examples/stm32h723/src/bin/spdifrx.rs2
3 files changed, 56 insertions, 336 deletions
diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs
index 88cc225dd..ff81dabed 100644
--- a/embassy-stm32/src/sai/mod.rs
+++ b/embassy-stm32/src/sai/mod.rs
@@ -8,6 +8,7 @@ use embassy_hal_internal::PeripheralType;
8pub use crate::dma::word; 8pub use crate::dma::word;
9use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer}; 9use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer};
10use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed}; 10use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed};
11pub use crate::pac::sai::vals::Mckdiv as MasterClockDivider;
11use crate::pac::sai::{vals, Sai as Regs}; 12use crate::pac::sai::{vals, Sai as Regs};
12use crate::rcc::{self, RccPeripheral}; 13use crate::rcc::{self, RccPeripheral};
13use crate::{peripherals, Peri}; 14use crate::{peripherals, Peri};
@@ -45,7 +46,6 @@ pub enum Mode {
45} 46}
46 47
47impl Mode { 48impl Mode {
48 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
49 const fn mode(&self, tx_rx: TxRx) -> vals::Mode { 49 const fn mode(&self, tx_rx: TxRx) -> vals::Mode {
50 match tx_rx { 50 match tx_rx {
51 TxRx::Transmitter => match self { 51 TxRx::Transmitter => match self {
@@ -80,7 +80,6 @@ pub enum SlotSize {
80} 80}
81 81
82impl SlotSize { 82impl SlotSize {
83 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
84 const fn slotsz(&self) -> vals::Slotsz { 83 const fn slotsz(&self) -> vals::Slotsz {
85 match self { 84 match self {
86 SlotSize::DataSize => vals::Slotsz::DATA_SIZE, 85 SlotSize::DataSize => vals::Slotsz::DATA_SIZE,
@@ -103,7 +102,6 @@ pub enum DataSize {
103} 102}
104 103
105impl DataSize { 104impl DataSize {
106 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
107 const fn ds(&self) -> vals::Ds { 105 const fn ds(&self) -> vals::Ds {
108 match self { 106 match self {
109 DataSize::Data8 => vals::Ds::BIT8, 107 DataSize::Data8 => vals::Ds::BIT8,
@@ -128,7 +126,6 @@ pub enum FifoThreshold {
128} 126}
129 127
130impl FifoThreshold { 128impl FifoThreshold {
131 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
132 const fn fth(&self) -> vals::Fth { 129 const fn fth(&self) -> vals::Fth {
133 match self { 130 match self {
134 FifoThreshold::Empty => vals::Fth::EMPTY, 131 FifoThreshold::Empty => vals::Fth::EMPTY,
@@ -149,7 +146,6 @@ pub enum MuteValue {
149} 146}
150 147
151impl MuteValue { 148impl MuteValue {
152 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
153 const fn muteval(&self) -> vals::Muteval { 149 const fn muteval(&self) -> vals::Muteval {
154 match self { 150 match self {
155 MuteValue::Zero => vals::Muteval::SEND_ZERO, 151 MuteValue::Zero => vals::Muteval::SEND_ZERO,
@@ -168,7 +164,6 @@ pub enum Protocol {
168} 164}
169 165
170impl Protocol { 166impl Protocol {
171 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
172 const fn prtcfg(&self) -> vals::Prtcfg { 167 const fn prtcfg(&self) -> vals::Prtcfg {
173 match self { 168 match self {
174 Protocol::Free => vals::Prtcfg::FREE, 169 Protocol::Free => vals::Prtcfg::FREE,
@@ -226,7 +221,6 @@ pub enum StereoMono {
226} 221}
227 222
228impl StereoMono { 223impl StereoMono {
229 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
230 const fn mono(&self) -> vals::Mono { 224 const fn mono(&self) -> vals::Mono {
231 match self { 225 match self {
232 StereoMono::Stereo => vals::Mono::STEREO, 226 StereoMono::Stereo => vals::Mono::STEREO,
@@ -245,7 +239,6 @@ pub enum BitOrder {
245} 239}
246 240
247impl BitOrder { 241impl BitOrder {
248 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
249 const fn lsbfirst(&self) -> vals::Lsbfirst { 242 const fn lsbfirst(&self) -> vals::Lsbfirst {
250 match self { 243 match self {
251 BitOrder::LsbFirst => vals::Lsbfirst::LSB_FIRST, 244 BitOrder::LsbFirst => vals::Lsbfirst::LSB_FIRST,
@@ -264,7 +257,6 @@ pub enum FrameSyncOffset {
264} 257}
265 258
266impl FrameSyncOffset { 259impl FrameSyncOffset {
267 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
268 const fn fsoff(&self) -> vals::Fsoff { 260 const fn fsoff(&self) -> vals::Fsoff {
269 match self { 261 match self {
270 FrameSyncOffset::OnFirstBit => vals::Fsoff::ON_FIRST, 262 FrameSyncOffset::OnFirstBit => vals::Fsoff::ON_FIRST,
@@ -283,7 +275,6 @@ pub enum FrameSyncPolarity {
283} 275}
284 276
285impl FrameSyncPolarity { 277impl FrameSyncPolarity {
286 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
287 const fn fspol(&self) -> vals::Fspol { 278 const fn fspol(&self) -> vals::Fspol {
288 match self { 279 match self {
289 FrameSyncPolarity::ActiveLow => vals::Fspol::FALLING_EDGE, 280 FrameSyncPolarity::ActiveLow => vals::Fspol::FALLING_EDGE,
@@ -301,7 +292,6 @@ pub enum FrameSyncDefinition {
301} 292}
302 293
303impl FrameSyncDefinition { 294impl FrameSyncDefinition {
304 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
305 const fn fsdef(&self) -> bool { 295 const fn fsdef(&self) -> bool {
306 match self { 296 match self {
307 FrameSyncDefinition::StartOfFrame => false, 297 FrameSyncDefinition::StartOfFrame => false,
@@ -319,7 +309,6 @@ pub enum ClockStrobe {
319} 309}
320 310
321impl ClockStrobe { 311impl ClockStrobe {
322 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
323 const fn ckstr(&self) -> vals::Ckstr { 312 const fn ckstr(&self) -> vals::Ckstr {
324 match self { 313 match self {
325 ClockStrobe::Falling => vals::Ckstr::FALLING_EDGE, 314 ClockStrobe::Falling => vals::Ckstr::FALLING_EDGE,
@@ -337,7 +326,6 @@ pub enum ComplementFormat {
337} 326}
338 327
339impl ComplementFormat { 328impl ComplementFormat {
340 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
341 const fn cpl(&self) -> vals::Cpl { 329 const fn cpl(&self) -> vals::Cpl {
342 match self { 330 match self {
343 ComplementFormat::OnesComplement => vals::Cpl::ONES_COMPLEMENT, 331 ComplementFormat::OnesComplement => vals::Cpl::ONES_COMPLEMENT,
@@ -356,7 +344,6 @@ pub enum Companding {
356} 344}
357 345
358impl Companding { 346impl Companding {
359 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
360 const fn comp(&self) -> vals::Comp { 347 const fn comp(&self) -> vals::Comp {
361 match self { 348 match self {
362 Companding::None => vals::Comp::NO_COMPANDING, 349 Companding::None => vals::Comp::NO_COMPANDING,
@@ -375,7 +362,6 @@ pub enum OutputDrive {
375} 362}
376 363
377impl OutputDrive { 364impl OutputDrive {
378 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
379 const fn outdriv(&self) -> vals::Outdriv { 365 const fn outdriv(&self) -> vals::Outdriv {
380 match self { 366 match self {
381 OutputDrive::OnStart => vals::Outdriv::ON_START, 367 OutputDrive::OnStart => vals::Outdriv::ON_START,
@@ -384,196 +370,6 @@ impl OutputDrive {
384 } 370 }
385} 371}
386 372
387/// Master clock divider.
388#[derive(Copy, Clone, PartialEq)]
389#[allow(missing_docs)]
390#[cfg(any(sai_v1, sai_v2))]
391pub enum MasterClockDivider {
392 MasterClockDisabled,
393 Div1,
394 Div2,
395 Div4,
396 Div6,
397 Div8,
398 Div10,
399 Div12,
400 Div14,
401 Div16,
402 Div18,
403 Div20,
404 Div22,
405 Div24,
406 Div26,
407 Div28,
408 Div30,
409}
410
411/// Master clock divider.
412#[derive(Copy, Clone, PartialEq)]
413#[allow(missing_docs)]
414#[cfg(any(sai_v1_4pdm, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
415pub enum MasterClockDivider {
416 MasterClockDisabled,
417 Div1,
418 Div2,
419 Div3,
420 Div4,
421 Div5,
422 Div6,
423 Div7,
424 Div8,
425 Div9,
426 Div10,
427 Div11,
428 Div12,
429 Div13,
430 Div14,
431 Div15,
432 Div16,
433 Div17,
434 Div18,
435 Div19,
436 Div20,
437 Div21,
438 Div22,
439 Div23,
440 Div24,
441 Div25,
442 Div26,
443 Div27,
444 Div28,
445 Div29,
446 Div30,
447 Div31,
448 Div32,
449 Div33,
450 Div34,
451 Div35,
452 Div36,
453 Div37,
454 Div38,
455 Div39,
456 Div40,
457 Div41,
458 Div42,
459 Div43,
460 Div44,
461 Div45,
462 Div46,
463 Div47,
464 Div48,
465 Div49,
466 Div50,
467 Div51,
468 Div52,
469 Div53,
470 Div54,
471 Div55,
472 Div56,
473 Div57,
474 Div58,
475 Div59,
476 Div60,
477 Div61,
478 Div62,
479 Div63,
480}
481
482impl MasterClockDivider {
483 #[cfg(any(sai_v1, sai_v2))]
484 const fn mckdiv(&self) -> u8 {
485 match self {
486 MasterClockDivider::MasterClockDisabled => 0,
487 MasterClockDivider::Div1 => 0,
488 MasterClockDivider::Div2 => 1,
489 MasterClockDivider::Div4 => 2,
490 MasterClockDivider::Div6 => 3,
491 MasterClockDivider::Div8 => 4,
492 MasterClockDivider::Div10 => 5,
493 MasterClockDivider::Div12 => 6,
494 MasterClockDivider::Div14 => 7,
495 MasterClockDivider::Div16 => 8,
496 MasterClockDivider::Div18 => 9,
497 MasterClockDivider::Div20 => 10,
498 MasterClockDivider::Div22 => 11,
499 MasterClockDivider::Div24 => 12,
500 MasterClockDivider::Div26 => 13,
501 MasterClockDivider::Div28 => 14,
502 MasterClockDivider::Div30 => 15,
503 }
504 }
505
506 #[cfg(any(sai_v1_4pdm, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))]
507 const fn mckdiv(&self) -> u8 {
508 match self {
509 MasterClockDivider::MasterClockDisabled => 0,
510 MasterClockDivider::Div1 => 1,
511 MasterClockDivider::Div2 => 2,
512 MasterClockDivider::Div3 => 3,
513 MasterClockDivider::Div4 => 4,
514 MasterClockDivider::Div5 => 5,
515 MasterClockDivider::Div6 => 6,
516 MasterClockDivider::Div7 => 7,
517 MasterClockDivider::Div8 => 8,
518 MasterClockDivider::Div9 => 9,
519 MasterClockDivider::Div10 => 10,
520 MasterClockDivider::Div11 => 11,
521 MasterClockDivider::Div12 => 12,
522 MasterClockDivider::Div13 => 13,
523 MasterClockDivider::Div14 => 14,
524 MasterClockDivider::Div15 => 15,
525 MasterClockDivider::Div16 => 16,
526 MasterClockDivider::Div17 => 17,
527 MasterClockDivider::Div18 => 18,
528 MasterClockDivider::Div19 => 19,
529 MasterClockDivider::Div20 => 20,
530 MasterClockDivider::Div21 => 21,
531 MasterClockDivider::Div22 => 22,
532 MasterClockDivider::Div23 => 23,
533 MasterClockDivider::Div24 => 24,
534 MasterClockDivider::Div25 => 25,
535 MasterClockDivider::Div26 => 26,
536 MasterClockDivider::Div27 => 27,
537 MasterClockDivider::Div28 => 28,
538 MasterClockDivider::Div29 => 29,
539 MasterClockDivider::Div30 => 30,
540 MasterClockDivider::Div31 => 31,
541 MasterClockDivider::Div32 => 32,
542 MasterClockDivider::Div33 => 33,
543 MasterClockDivider::Div34 => 34,
544 MasterClockDivider::Div35 => 35,
545 MasterClockDivider::Div36 => 36,
546 MasterClockDivider::Div37 => 37,
547 MasterClockDivider::Div38 => 38,
548 MasterClockDivider::Div39 => 39,
549 MasterClockDivider::Div40 => 40,
550 MasterClockDivider::Div41 => 41,
551 MasterClockDivider::Div42 => 42,
552 MasterClockDivider::Div43 => 43,
553 MasterClockDivider::Div44 => 44,
554 MasterClockDivider::Div45 => 45,
555 MasterClockDivider::Div46 => 46,
556 MasterClockDivider::Div47 => 47,
557 MasterClockDivider::Div48 => 48,
558 MasterClockDivider::Div49 => 49,
559 MasterClockDivider::Div50 => 50,
560 MasterClockDivider::Div51 => 51,
561 MasterClockDivider::Div52 => 52,
562 MasterClockDivider::Div53 => 53,
563 MasterClockDivider::Div54 => 54,
564 MasterClockDivider::Div55 => 55,
565 MasterClockDivider::Div56 => 56,
566 MasterClockDivider::Div57 => 57,
567 MasterClockDivider::Div58 => 58,
568 MasterClockDivider::Div59 => 59,
569 MasterClockDivider::Div60 => 60,
570 MasterClockDivider::Div61 => 61,
571 MasterClockDivider::Div62 => 62,
572 MasterClockDivider::Div63 => 63,
573 }
574 }
575}
576
577/// [`SAI`] configuration. 373/// [`SAI`] configuration.
578#[allow(missing_docs)] 374#[allow(missing_docs)]
579#[non_exhaustive] 375#[non_exhaustive]
@@ -598,8 +394,7 @@ pub struct Config {
598 pub frame_length: u8, 394 pub frame_length: u8,
599 pub clock_strobe: ClockStrobe, 395 pub clock_strobe: ClockStrobe,
600 pub output_drive: OutputDrive, 396 pub output_drive: OutputDrive,
601 pub master_clock_divider: MasterClockDivider, 397 pub master_clock_divider: Option<MasterClockDivider>,
602 pub nodiv: bool,
603 pub is_high_impedance_on_inactive_slot: bool, 398 pub is_high_impedance_on_inactive_slot: bool,
604 pub fifo_threshold: FifoThreshold, 399 pub fifo_threshold: FifoThreshold,
605 pub companding: Companding, 400 pub companding: Companding,
@@ -628,8 +423,7 @@ impl Default for Config {
628 frame_sync_active_level_length: word::U7(16), 423 frame_sync_active_level_length: word::U7(16),
629 frame_sync_definition: FrameSyncDefinition::ChannelIdentification, 424 frame_sync_definition: FrameSyncDefinition::ChannelIdentification,
630 frame_length: 32, 425 frame_length: 32,
631 master_clock_divider: MasterClockDivider::MasterClockDisabled, 426 master_clock_divider: None,
632 nodiv: false,
633 clock_strobe: ClockStrobe::Rising, 427 clock_strobe: ClockStrobe::Rising,
634 output_drive: OutputDrive::Immediately, 428 output_drive: OutputDrive::Immediately,
635 is_high_impedance_on_inactive_slot: false, 429 is_high_impedance_on_inactive_slot: false,
@@ -761,15 +555,11 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> {
761 mclk: Peri<'d, impl MclkPin<T, S>>, 555 mclk: Peri<'d, impl MclkPin<T, S>>,
762 dma: Peri<'d, impl Channel + Dma<T, S>>, 556 dma: Peri<'d, impl Channel + Dma<T, S>>,
763 dma_buf: &'d mut [W], 557 dma_buf: &'d mut [W],
764 mut config: Config, 558 config: Config,
765 ) -> Self { 559 ) -> Self {
766 let (_sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); 560 let (_sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
767 mclk.set_as_af(mclk.af_num(), ck_af_type); 561 mclk.set_as_af(mclk.af_num(), ck_af_type);
768 562
769 if config.master_clock_divider == MasterClockDivider::MasterClockDisabled {
770 config.master_clock_divider = MasterClockDivider::Div1;
771 }
772
773 Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config) 563 Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config)
774 } 564 }
775 565
@@ -851,10 +641,7 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> {
851 ) -> Self { 641 ) -> Self {
852 let ch = T::REGS.ch(sub_block as usize); 642 let ch = T::REGS.ch(sub_block as usize);
853 643
854 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] 644 ch.cr1().modify(|w| w.set_saien(false));
855 {
856 ch.cr1().modify(|w| w.set_saien(false));
857 }
858 645
859 ch.cr2().modify(|w| w.set_fflush(true)); 646 ch.cr2().modify(|w| w.set_fflush(true));
860 647
@@ -877,55 +664,52 @@ impl<'d, T: Instance, W: word::Word> Sai<'d, T, W> {
877 } 664 }
878 } 665 }
879 666
880 #[cfg(any(sai_v1, sai_v1_4pdm, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] 667 ch.cr1().modify(|w| {
881 { 668 w.set_mode(config.mode.mode(if Self::is_transmitter(&ring_buffer) {
882 ch.cr1().modify(|w| { 669 TxRx::Transmitter
883 w.set_mode(config.mode.mode(if Self::is_transmitter(&ring_buffer) { 670 } else {
884 TxRx::Transmitter 671 TxRx::Receiver
885 } else { 672 }));
886 TxRx::Receiver 673 w.set_prtcfg(config.protocol.prtcfg());
887 })); 674 w.set_ds(config.data_size.ds());
888 w.set_prtcfg(config.protocol.prtcfg()); 675 w.set_lsbfirst(config.bit_order.lsbfirst());
889 w.set_ds(config.data_size.ds()); 676 w.set_ckstr(config.clock_strobe.ckstr());
890 w.set_lsbfirst(config.bit_order.lsbfirst()); 677 w.set_syncen(config.sync_input.syncen());
891 w.set_ckstr(config.clock_strobe.ckstr()); 678 w.set_mono(config.stereo_mono.mono());
892 w.set_syncen(config.sync_input.syncen()); 679 w.set_outdriv(config.output_drive.outdriv());
893 w.set_mono(config.stereo_mono.mono()); 680 w.set_mckdiv(config.master_clock_divider.unwrap_or(MasterClockDivider::DIV1));
894 w.set_outdriv(config.output_drive.outdriv()); 681 w.set_nodiv(config.master_clock_divider.is_none());
895 w.set_mckdiv(config.master_clock_divider.mckdiv().into()); 682 w.set_dmaen(true);
896 w.set_nodiv(config.nodiv); 683 });
897 w.set_dmaen(true); 684
898 }); 685 ch.cr2().modify(|w| {
899 686 w.set_fth(config.fifo_threshold.fth());
900 ch.cr2().modify(|w| { 687 w.set_comp(config.companding.comp());
901 w.set_fth(config.fifo_threshold.fth()); 688 w.set_cpl(config.complement_format.cpl());
902 w.set_comp(config.companding.comp()); 689 w.set_muteval(config.mute_value.muteval());
903 w.set_cpl(config.complement_format.cpl()); 690 w.set_mutecnt(config.mute_detection_counter.0 as u8);
904 w.set_muteval(config.mute_value.muteval()); 691 w.set_tris(config.is_high_impedance_on_inactive_slot);
905 w.set_mutecnt(config.mute_detection_counter.0 as u8); 692 });
906 w.set_tris(config.is_high_impedance_on_inactive_slot); 693
907 }); 694 ch.frcr().modify(|w| {
908 695 w.set_fsoff(config.frame_sync_offset.fsoff());
909 ch.frcr().modify(|w| { 696 w.set_fspol(config.frame_sync_polarity.fspol());
910 w.set_fsoff(config.frame_sync_offset.fsoff()); 697 w.set_fsdef(config.frame_sync_definition.fsdef());
911 w.set_fspol(config.frame_sync_polarity.fspol()); 698 w.set_fsall(config.frame_sync_active_level_length.0 as u8 - 1);
912 w.set_fsdef(config.frame_sync_definition.fsdef()); 699 w.set_frl(config.frame_length - 1);
913 w.set_fsall(config.frame_sync_active_level_length.0 as u8 - 1); 700 });
914 w.set_frl(config.frame_length - 1); 701
915 }); 702 ch.slotr().modify(|w| {
916 703 w.set_nbslot(config.slot_count.0 as u8 - 1);
917 ch.slotr().modify(|w| { 704 w.set_slotsz(config.slot_size.slotsz());
918 w.set_nbslot(config.slot_count.0 as u8 - 1); 705 w.set_fboff(config.first_bit_offset.0 as u8);
919 w.set_slotsz(config.slot_size.slotsz()); 706 w.set_sloten(vals::Sloten::from_bits(config.slot_enable as u16));
920 w.set_fboff(config.first_bit_offset.0 as u8); 707 });
921 w.set_sloten(vals::Sloten::from_bits(config.slot_enable as u16)); 708
922 }); 709 ch.cr1().modify(|w| w.set_saien(true));
923 710
924 ch.cr1().modify(|w| w.set_saien(true)); 711 if ch.cr1().read().saien() == false {
925 712 panic!("SAI failed to enable. Check that config is valid (frame length, slot count, etc)");
926 if ch.cr1().read().saien() == false {
927 panic!("SAI failed to enable. Check that config is valid (frame length, slot count, etc)");
928 }
929 } 713 }
930 714
931 Self { 715 Self {
diff --git a/examples/stm32h7/src/bin/sai.rs b/examples/stm32h7/src/bin/sai.rs
index 01937593a..847b70c85 100644
--- a/examples/stm32h7/src/bin/sai.rs
+++ b/examples/stm32h7/src/bin/sai.rs
@@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) {
63 tx_config.tx_rx = TxRx::Transmitter; 63 tx_config.tx_rx = TxRx::Transmitter;
64 tx_config.sync_output = true; 64 tx_config.sync_output = true;
65 tx_config.clock_strobe = ClockStrobe::Falling; 65 tx_config.clock_strobe = ClockStrobe::Falling;
66 tx_config.master_clock_divider = mclk_div; 66 tx_config.master_clock_divider = Some(mclk_div);
67 tx_config.stereo_mono = StereoMono::Stereo; 67 tx_config.stereo_mono = StereoMono::Stereo;
68 tx_config.data_size = DataSize::Data24; 68 tx_config.data_size = DataSize::Data24;
69 tx_config.bit_order = BitOrder::MsbFirst; 69 tx_config.bit_order = BitOrder::MsbFirst;
@@ -119,71 +119,7 @@ async fn main(_spawner: Spawner) {
119 } 119 }
120} 120}
121 121
122const fn mclk_div_from_u8(v: u8) -> MasterClockDivider { 122fn mclk_div_from_u8(v: u8) -> MasterClockDivider {
123 match v { 123 assert!((1..=63).contains(&v));
124 1 => MasterClockDivider::Div1, 124 MasterClockDivider::from_bits(v)
125 2 => MasterClockDivider::Div2,
126 3 => MasterClockDivider::Div3,
127 4 => MasterClockDivider::Div4,
128 5 => MasterClockDivider::Div5,
129 6 => MasterClockDivider::Div6,
130 7 => MasterClockDivider::Div7,
131 8 => MasterClockDivider::Div8,
132 9 => MasterClockDivider::Div9,
133 10 => MasterClockDivider::Div10,
134 11 => MasterClockDivider::Div11,
135 12 => MasterClockDivider::Div12,
136 13 => MasterClockDivider::Div13,
137 14 => MasterClockDivider::Div14,
138 15 => MasterClockDivider::Div15,
139 16 => MasterClockDivider::Div16,
140 17 => MasterClockDivider::Div17,
141 18 => MasterClockDivider::Div18,
142 19 => MasterClockDivider::Div19,
143 20 => MasterClockDivider::Div20,
144 21 => MasterClockDivider::Div21,
145 22 => MasterClockDivider::Div22,
146 23 => MasterClockDivider::Div23,
147 24 => MasterClockDivider::Div24,
148 25 => MasterClockDivider::Div25,
149 26 => MasterClockDivider::Div26,
150 27 => MasterClockDivider::Div27,
151 28 => MasterClockDivider::Div28,
152 29 => MasterClockDivider::Div29,
153 30 => MasterClockDivider::Div30,
154 31 => MasterClockDivider::Div31,
155 32 => MasterClockDivider::Div32,
156 33 => MasterClockDivider::Div33,
157 34 => MasterClockDivider::Div34,
158 35 => MasterClockDivider::Div35,
159 36 => MasterClockDivider::Div36,
160 37 => MasterClockDivider::Div37,
161 38 => MasterClockDivider::Div38,
162 39 => MasterClockDivider::Div39,
163 40 => MasterClockDivider::Div40,
164 41 => MasterClockDivider::Div41,
165 42 => MasterClockDivider::Div42,
166 43 => MasterClockDivider::Div43,
167 44 => MasterClockDivider::Div44,
168 45 => MasterClockDivider::Div45,
169 46 => MasterClockDivider::Div46,
170 47 => MasterClockDivider::Div47,
171 48 => MasterClockDivider::Div48,
172 49 => MasterClockDivider::Div49,
173 50 => MasterClockDivider::Div50,
174 51 => MasterClockDivider::Div51,
175 52 => MasterClockDivider::Div52,
176 53 => MasterClockDivider::Div53,
177 54 => MasterClockDivider::Div54,
178 55 => MasterClockDivider::Div55,
179 56 => MasterClockDivider::Div56,
180 57 => MasterClockDivider::Div57,
181 58 => MasterClockDivider::Div58,
182 59 => MasterClockDivider::Div59,
183 60 => MasterClockDivider::Div60,
184 61 => MasterClockDivider::Div61,
185 62 => MasterClockDivider::Div62,
186 63 => MasterClockDivider::Div63,
187 _ => panic!(),
188 }
189} 125}
diff --git a/examples/stm32h723/src/bin/spdifrx.rs b/examples/stm32h723/src/bin/spdifrx.rs
index 6d29e8a4d..b75a03ae8 100644
--- a/examples/stm32h723/src/bin/spdifrx.rs
+++ b/examples/stm32h723/src/bin/spdifrx.rs
@@ -168,7 +168,7 @@ fn new_sai_transmitter<'d>(
168 sai_config.slot_enable = 0xFFFF; // All slots 168 sai_config.slot_enable = 0xFFFF; // All slots
169 sai_config.data_size = sai::DataSize::Data32; 169 sai_config.data_size = sai::DataSize::Data32;
170 sai_config.frame_length = (CHANNEL_COUNT * 32) as u8; 170 sai_config.frame_length = (CHANNEL_COUNT * 32) as u8;
171 sai_config.master_clock_divider = hal::sai::MasterClockDivider::MasterClockDisabled; 171 sai_config.master_clock_divider = None;
172 172
173 let (sub_block_tx, _) = hal::sai::split_subblocks(sai); 173 let (sub_block_tx, _) = hal::sai::split_subblocks(sai);
174 Sai::new_asynchronous(sub_block_tx, sck, sd, fs, dma, buf, sai_config) 174 Sai::new_asynchronous(sub_block_tx, sck, sd, fs, dma, buf, sai_config)