-
Notifications
You must be signed in to change notification settings - Fork 840
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue 1974 add sai driver #1975
Issue 1974 add sai driver #1975
Conversation
Pull changes from embassy main
Pull changes from base embassy repo
Update to embassy head
…gilbert/embassy into issue-1974-add-sai-driver
@Dirbaio |
Hello @tyler-gilbert, do you by any chance have any public examples of this being used? I would like to give it a go in my project, and having a reference would help me a lot. Thanks |
I have a private project I am using: use embassy_stm32::sai::{Config, FifoThreshold, MasterClockDivider, StereoMono};
info!("Creating SAI");
let (tx_peripherals, tx_buffer, rx_peripherals, rx_buffer) = {
let s = singleton::get_mut();
(
s.peripherals.sai_transmitter.take().unwrap(),
s.sai_dma_tx_buffer.as_mut_slice(),
s.peripherals.sai_receiver.take().unwrap(),
s.sai_dma_rx_buffer.as_mut_slice(),
)
};
#[cfg(feature = "stm32u585ai")]
let (sub_block_transmitter, sub_block_receiver) = sai::split_subblocks(tx_peripherals.sai);
#[cfg(not(feature = "stm32u585ai"))]
let (sub_block_receiver, sub_block_transmitter) = sai::split_subblocks(tx_peripherals.sai);
//The NAU8315 has some odd bring up requirements. The EN may need to be toggled after cycling the power.
//The EN or power may also need to be cycles after the SCLK/FS signals are available.
let (tx_config, transmitter) = {
let tx_config = {
let mut config = Config::default();
config.mode = Mode::Master;
config.tx_rx = TxRx::Transmitter;
config.mute_detection_counter = embassy_stm32::dma::word::U5(0);
config.master_clock_divider = MasterClockDivider::Div12;
config.fifo_threshold = FifoThreshold::Empty;
config.sync_output = true;
config.stereo_mono = StereoMono::Mono;
// NAU8315 datasheet claims min bitrate clock with 8KHz FS clock is 2048KHz
// On the STM32U545, this works with and without the following lines of code
// On the STM32F429, without the following lines of code, there are a lot of pops and snaps
config.frame_length = sai::MAX_FRAME_LENGTH;
config.frame_sync_active_level_length = embassy_stm32::dma::word::U7(128);
config
};
(
tx_config,
sai::Sai::new_asynchronous(
sub_block_transmitter,
tx_peripherals.sck,
tx_peripherals.sd,
tx_peripherals.fs,
tx_peripherals.dma,
tx_buffer,
tx_config,
),
)
};
let receiver = {
let rx_config = {
let mut config = tx_config.clone();
config.tx_rx = TxRx::Receiver;
// This doesn't work even if the transmitter is running. It may need to use the same FS and BCLK
// Getting the mic/speaker sync'd is important for echo cancellation
//config.mode = Mode::Slave;
//config.sync_input = SyncInput::Internal;
config.data_size = DataSize::Data32;
config.frame_length = 64;
config.frame_sync_active_level_length = embassy_stm32::dma::word::U7(32);
config
};
sai::Sai::new_asynchronous(
sub_block_receiver,
rx_peripherals.sck,
rx_peripherals.sd,
rx_peripherals.fs,
rx_peripherals.dma,
rx_buffer,
rx_config,
)
};
// When syncing the mic to the speaker, speaker needs to be started for data to flow.
// But it still isn't working with separate FS and BCLK.
//transmitter.start();
Self {
codec_mutex: Mutex::new(codec::AudioCodec::new(AudioCodecConfig::None)),
input: RefCell::new(input::Input::new(receiver)),
output: RefCell::new(output::Output::new(transmitter)),
window: RemoveNoise::new_window(),
mic_channel: MicChannel::new(),
speaker_channel: SpeakerChannel::new(),
speaker_to_mic_channel: SpeakerToMicChannel::new(),
is_cancel_echo: RefCell::new(false),
} Some snippets on reading and writing: pub async fn write(&self, samples: &[audio::Sample]) -> Result<(), sai::Error> {
let mut io = self.io.borrow_mut();
io.transmitter.write(Self::samples_as_slice(samples)).await
}
let result = io.receiver.read(read_frame.as_mut_slice()).await; I haven't committed the changes that are needed to use it with GPDMA (STM32U5 and other new chips) and a circular buffer. But I have that working locally. |
@tyler-gilbert thanks a lot, that helps |
This adds an SAI transmitter driver. The receiver is straightforward to add. It just requires some
new_
functions and setting up the IO appropriately.This is working on the STM32F429.
Closes #1974.