From ce3a13a91cf9a90b07bcb1d65a192c0c6bc14c90 Mon Sep 17 00:00:00 2001 From: jplaisance Date: Thu, 21 Nov 2024 14:50:03 -0600 Subject: [PATCH] added optional intermediate buffer to SaiHandle to allow full use of cpu in audio callback at low block sizes --- src/daisy_seed.cpp | 5 ++++ src/daisy_seed.h | 2 ++ src/hid/audio.cpp | 11 +++++++++ src/hid/audio.h | 2 ++ src/per/sai.cpp | 60 ++++++++++++++++++++++++++++++++++++++++------ src/per/sai.h | 2 ++ 6 files changed, 75 insertions(+), 7 deletions(-) diff --git a/src/daisy_seed.cpp b/src/daisy_seed.cpp index 88e74ce4e..15e2f79ba 100644 --- a/src/daisy_seed.cpp +++ b/src/daisy_seed.cpp @@ -220,6 +220,11 @@ float DaisySeed::AudioCallbackRate() const return callback_rate_; } +void DaisySeed::SetIntermediateBuffers(int32_t* buffer_sai1, int32_t* buffer_sai2) +{ + audio_handle.SetIntermediateBuffers(buffer_sai1, buffer_sai2); +} + void DaisySeed::SetLed(bool state) { led.Write(state); diff --git a/src/daisy_seed.h b/src/daisy_seed.h index af449ce26..c4e4611c6 100644 --- a/src/daisy_seed.h +++ b/src/daisy_seed.h @@ -97,6 +97,8 @@ class DaisySeed /** Returns the rate in Hz that the Audio callback is called */ float AudioCallbackRate() const; + void SetIntermediateBuffers(int32_t* buffer_sai1, int32_t* buffer_sai2 = nullptr); + /** Returns the SAI Handle for the Daisy Seed * This can be useful when adding a secondary codec, * the result of this function can be passed to the audio reinit diff --git a/src/hid/audio.cpp b/src/hid/audio.cpp index 211e83cf2..b35ef0855 100644 --- a/src/hid/audio.cpp +++ b/src/hid/audio.cpp @@ -58,6 +58,12 @@ class AudioHandle::Impl : AudioHandle::Result::ERR; } + void SetIntermediateBuffers(int32_t* buffer_sai1, int32_t* buffer_sai2) + { + sai1_.SetIntermediateBuffer(buffer_sai1); + sai2_.SetIntermediateBuffer(buffer_sai2); + } + float GetSampleRate() { return sai1_.GetSampleRate(); } AudioHandle::Result SetPostGain(float val) @@ -520,6 +526,11 @@ AudioHandle::Result AudioHandle::SetBlockSize(size_t size) return pimpl_->SetBlockSize(size); } +void AudioHandle::SetIntermediateBuffers(int32_t* buffer_sai1, int32_t* buffer_sai2) +{ + pimpl_->SetIntermediateBuffers(buffer_sai1, buffer_sai2); +} + float AudioHandle::GetSampleRate() { return pimpl_->GetSampleRate(); diff --git a/src/hid/audio.h b/src/hid/audio.h index 47fbc4744..910f44963 100644 --- a/src/hid/audio.h +++ b/src/hid/audio.h @@ -122,6 +122,8 @@ class AudioHandle */ Result SetBlockSize(size_t size); + void SetIntermediateBuffers(int32_t* buffer_sai1, int32_t* buffer_sai2 = nullptr); + /** Sets the amount of gain adjustment to perform before and after callback. ** useful if the hardware has additional headroom, and the nominal value shouldn't be 1.0 ** diff --git a/src/per/sai.cpp b/src/per/sai.cpp index f8cc2848d..b7fe70500 100644 --- a/src/per/sai.cpp +++ b/src/per/sai.cpp @@ -1,5 +1,6 @@ #include "per/sai.h" #include "daisy_core.h" +#include namespace daisy { @@ -39,8 +40,15 @@ class SaiHandle::Impl /** Offset stored for weird inter-SAI stuff.*/ size_t dma_offset; + // Optional buffer for audio callback output + int32_t* buff_intermediate_ = nullptr; + + void SetIntermediateBuffer(int32_t* buffer) { buff_intermediate_ = buffer; } + /** Callback that dispatches user callback from Cplt and HalfCplt DMA Callbacks */ - void InternalCallback(size_t offset); + void InternalCallbackRx(size_t offset); + + void InternalCallbackTx(size_t offset); /** Pin Initiazlization */ void InitPins(); @@ -283,15 +291,25 @@ void SaiHandle::Impl::DeInitDma(PeripheralBlock block) } } -void SaiHandle::Impl::InternalCallback(size_t offset) +void SaiHandle::Impl::InternalCallbackRx(size_t offset) { int32_t *in, *out; in = buff_rx_ + offset; - out = buff_tx_ + offset; + out = (buff_intermediate_ ? buff_intermediate_ : buff_tx_ + offset); if(callback_) callback_(in, out, buff_size_ / 2); } +void SaiHandle::Impl::InternalCallbackTx(size_t offset) +{ + if (!buff_intermediate_) { + return; + } + int32_t* in = buff_intermediate_; + int32_t* out = buff_tx_ + offset; + std::memcpy(out, in, buff_size_ / 2 * sizeof(*out)); +} + SaiHandle::Result SaiHandle::Impl::StartDmaTransfer(int32_t* buffer_rx, int32_t* buffer_tx, @@ -503,12 +521,12 @@ extern "C" void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef* hsai) if(hsai->Instance == SAI1_Block_A || hsai->Instance == SAI1_Block_B) { sai_handles[0].dma_offset = 0; - sai_handles[0].InternalCallback(0); + sai_handles[0].InternalCallbackRx(0); } else if(hsai->Instance == SAI2_Block_A || hsai->Instance == SAI2_Block_B) { sai_handles[1].dma_offset = 0; - sai_handles[1].InternalCallback(0); + sai_handles[1].InternalCallbackRx(0); } } @@ -517,12 +535,36 @@ extern "C" void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef* hsai) if(hsai->Instance == SAI1_Block_A || hsai->Instance == SAI1_Block_B) { sai_handles[0].dma_offset = sai_handles[0].buff_size_ / 2; - sai_handles[0].InternalCallback(sai_handles[0].dma_offset); + sai_handles[0].InternalCallbackRx(sai_handles[0].dma_offset); } else if(hsai->Instance == SAI2_Block_A || hsai->Instance == SAI2_Block_B) { sai_handles[1].dma_offset = sai_handles[1].buff_size_ / 2; - sai_handles[1].InternalCallback(sai_handles[1].dma_offset); + sai_handles[1].InternalCallbackRx(sai_handles[1].dma_offset); + } +} + +extern "C" void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef* hsai) +{ + if(hsai->Instance == SAI1_Block_A || hsai->Instance == SAI1_Block_B) + { + sai_handles[0].InternalCallbackTx(0); + } + else if(hsai->Instance == SAI2_Block_A || hsai->Instance == SAI2_Block_B) + { + sai_handles[1].InternalCallbackTx(0); + } +} + +extern "C" void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef* hsai) +{ + if(hsai->Instance == SAI1_Block_A || hsai->Instance == SAI1_Block_B) + { + sai_handles[0].InternalCallbackTx(sai_handles[0].buff_size_ / 2); + } + else if(hsai->Instance == SAI2_Block_A || hsai->Instance == SAI2_Block_B) + { + sai_handles[1].InternalCallbackTx(sai_handles[1].buff_size_ / 2); } } @@ -579,5 +621,9 @@ size_t SaiHandle::GetOffset() const return pimpl_->dma_offset; } +void SaiHandle::SetIntermediateBuffer(int32_t* buffer) { + pimpl_->SetIntermediateBuffer(buffer); +} + } // namespace daisy diff --git a/src/per/sai.h b/src/per/sai.h index 54c0e72a9..d8d2d9805 100644 --- a/src/per/sai.h +++ b/src/per/sai.h @@ -154,6 +154,8 @@ class SaiHandle /** Returns the current offset within the SAI buffer, will be either 0 or size/2 */ size_t GetOffset() const; + void SetIntermediateBuffer(int32_t* buffer); + inline bool IsInitialized() const { return pimpl_ == nullptr ? false : true;