#![deny(warnings)]
#![deny(unsafe_code)]
#![no_main]
#![no_std]
#[macro_use]
mod utilities;
use stm32h7xx_hal::time::Hertz;
pub const AUDIO_SAMPLE_HZ: Hertz = Hertz::from_raw(48_000);
const PLL3_P_HZ: Hertz = Hertz::from_raw(AUDIO_SAMPLE_HZ.raw() * 257);
#[rtic::app( device = stm32h7xx_hal::stm32, peripherals = true )]
mod app {
use cortex_m::asm::delay as delay_cycles;
use cortex_m::asm::nop;
use stm32h7xx_hal::prelude::*;
use stm32h7xx_hal::rcc::rec::Sai1ClkSel;
use stm32h7xx_hal::sai::{
self, I2SChanConfig, I2SDataSize, I2SDir, I2SSync, I2sUsers, Sai,
SaiChannel, SaiI2sExt, I2S,
};
use stm32h7xx_hal::stm32;
use stm32h7xx_hal::traits::i2s::FullDuplex;
use super::*;
use log::info;
#[shared]
struct SharedResources {
#[lock_free]
audio: Sai<stm32::SAI1, I2S>,
}
#[local]
struct LocalResources {}
#[init]
fn init(
mut ctx: init::Context,
) -> (SharedResources, LocalResources, init::Monotonics) {
utilities::logger::init();
let pwr = ctx.device.PWR.constrain();
let vos = example_power!(pwr).freeze();
let ccdr = ctx
.device
.RCC
.constrain()
.use_hse(16.MHz())
.sys_ck(400.MHz())
.pll3_p_ck(PLL3_P_HZ)
.freeze(vos, &ctx.device.SYSCFG);
let gpiob = ctx.device.GPIOB.split(ccdr.peripheral.GPIOB);
let gpioe = ctx.device.GPIOE.split(ccdr.peripheral.GPIOE);
let sai1_pins = (
gpioe.pe2.into_alternate(), gpioe.pe5.into_alternate(), gpioe.pe4.into_alternate(), gpioe.pe6.into_alternate(), Some(gpioe.pe3.into_alternate()), );
let mut codec = gpiob.pb11.into_push_pull_output();
codec.set_low();
delay_cycles(400_000);
codec.set_high();
let sai1_rec = ccdr.peripheral.SAI1.kernel_clk_mux(Sai1ClkSel::Pll3P);
let master_config =
I2SChanConfig::new(I2SDir::Tx).set_frame_sync_active_high(true);
let slave_config = I2SChanConfig::new(I2SDir::Rx)
.set_sync_type(I2SSync::Internal)
.set_frame_sync_active_high(true);
let mut audio = ctx.device.SAI1.i2s_ch_a(
sai1_pins,
AUDIO_SAMPLE_HZ,
I2SDataSize::BITS_24,
sai1_rec,
&ccdr.clocks,
I2sUsers::new(master_config).add_slave(slave_config),
);
ctx.core.SCB.enable_icache();
audio.listen(SaiChannel::ChannelB, sai::Event::Data);
audio.enable();
audio.try_send(0, 0).unwrap();
info!("Startup complete!");
(
SharedResources { audio },
LocalResources {},
init::Monotonics(),
)
}
#[task(binds = SAI1, shared = [audio] )]
fn passthru(ctx: passthru::Context) {
if let Ok((left, right)) = ctx.shared.audio.try_read() {
ctx.shared.audio.try_send(left, right).unwrap();
}
}
#[idle]
fn idle(_cx: idle::Context) -> ! {
loop {
nop();
}
}
}