stm32f4xx-hal icon indicating copy to clipboard operation
stm32f4xx-hal copied to clipboard

wip: Serial audio interface (SAI)

Open mgottschlag opened this issue 4 years ago • 1 comments

This PR contains some preliminary code for the SAI. In the stm32f7xx-hal a driver already exists iirc, but that driver is limited to duplex I2S. This API is slightly more flexible, yet similarly easy to use.

Usage example:

// Initialize clocks.
let rcc = ctx.device.RCC.constrain();
let clocks = rcc
    .cfgr
    .use_hse(8.mhz())
    .saia_clk(172.mhz())
    .saib_clk(172.mhz())
    .freeze();
// Test that the SAI clock is suitable for 48000KHz audio.
assert!(clocks.saia_clk().unwrap() == 172.mhz().into());
assert!(clocks.saib_clk().unwrap() == 172.mhz().into());

let gpioe = ctx.device.GPIOE.split();
// SAIB is made synchronous to A.
let (saia, saib) = ctx.device.SAI.split_sync_b();
let protocol = Protocol {
    sync: Synchronization::I2S,
    word_size: 16,
    slot_size: 16,
    num_slots: 2,
};
let tx = saia.master_tx(
    (
        gpioe.pe2.into_alternate_af6(),
        gpioe.pe4.into_alternate_af6(),
        gpioe.pe5.into_alternate_af6(),
        gpioe.pe6.into_alternate_af6(),
    ),
    protocol,
    48000.hz(),
    clocks,
);
let rx = saib.slave_rx(gpioe.pe3.into_alternate_af6(), protocol);

let mut duplex = Duplex::new(rx, tx);
duplex.start();
loop {
    duplex.try_send(0xaaaa, 0xf0f0).ok();
    let _input = duplex.try_read();
}

Bits still missing:

  • DMA
  • Implementation of the new embedded-hal I2S traits
  • Support for everything but the STM32F429 (should be very simple)
  • Functions to deinitialize the SAI and release the pins
  • Documentation on how to set the SAI clock

mgottschlag avatar Jan 03 '21 13:01 mgottschlag

Any progress on this?

burrbull avatar Mar 01 '22 20:03 burrbull