Skip to content

Commit 70c2b24

Browse files
add handling for two SAI blocks with no master (e.g. daisy following another daisy, etc.) (#705)
1 parent 9bea05f commit 70c2b24

1 file changed

Lines changed: 39 additions & 18 deletions

File tree

‎src/per/sai.cpp‎

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ SaiHandle::Result SaiHandle::Impl::Init(const SaiHandle::Config& config)
115115
break;
116116
default: break;
117117
}
118+
const bool both_blocks_slave = config.a_sync == Config::Sync::SLAVE
119+
&& config.b_sync == Config::Sync::SLAVE;
120+
118121
// Audio Mode A
119122
if(config.a_sync == Config::Sync::MASTER)
120123
{
@@ -128,6 +131,8 @@ SaiHandle::Result SaiHandle::Impl::Init(const SaiHandle::Config& config)
128131
sai_a_handle_.Init.AudioMode
129132
= config.a_dir == Config::Direction::TRANSMIT ? SAI_MODESLAVE_TX
130133
: SAI_MODESLAVE_RX;
134+
// In external-clock dual-slave mode, Block A follows Block B since pins
135+
// exposed on SOMs are mostly from the Block B.
131136
sai_a_handle_.Init.Synchro = SAI_SYNCHRONOUS;
132137
}
133138
// Audio Mode B
@@ -143,7 +148,9 @@ SaiHandle::Result SaiHandle::Impl::Init(const SaiHandle::Config& config)
143148
sai_b_handle_.Init.AudioMode
144149
= config.b_dir == Config::Direction::TRANSMIT ? SAI_MODESLAVE_TX
145150
: SAI_MODESLAVE_RX;
146-
sai_b_handle_.Init.Synchro = SAI_SYNCHRONOUS;
151+
// When no channel is the master, B will remain async.
152+
sai_b_handle_.Init.Synchro
153+
= both_blocks_slave ? SAI_ASYNCHRONOUS : SAI_SYNCHRONOUS;
147154
}
148155
// Bitdepth / protocol (currently based on bitdepth..)
149156
// TODO probably split these up for better flexibility..
@@ -303,33 +310,47 @@ SaiHandle::Impl::StartDmaTransfer(int32_t* buffer_rx,
303310
buff_size_ = size;
304311
callback_ = callback;
305312

306-
// This assumes there will be one master and one slave
307-
if(config_.a_sync == Config::Sync::SLAVE)
313+
const bool a_slave = config_.a_sync == Config::Sync::SLAVE;
314+
const bool b_slave = config_.b_sync == Config::Sync::SLAVE;
315+
316+
auto start_block
317+
= [&](SAI_HandleTypeDef* hsai, Config::Direction dir) -> bool {
318+
HAL_StatusTypeDef status
319+
= dir == Config::Direction::RECEIVE
320+
? HAL_SAI_Receive_DMA(hsai, (uint8_t*)buffer_rx, size)
321+
: HAL_SAI_Transmit_DMA(hsai, (uint8_t*)buffer_tx, size);
322+
return status == HAL_OK;
323+
};
324+
325+
// Start synchronous slave before its source when there is one master/async block.
326+
// In dual-slave external-clock mode, start B first because A is configured synchronous to B.
327+
if(a_slave && b_slave)
308328
{
309-
config_.a_dir == Config::Direction::RECEIVE
310-
? HAL_SAI_Receive_DMA(&sai_a_handle_, (uint8_t*)buffer_rx, size)
311-
: HAL_SAI_Transmit_DMA(&sai_a_handle_, (uint8_t*)buffer_tx, size);
312-
config_.b_dir == Config::Direction::RECEIVE
313-
? HAL_SAI_Receive_DMA(&sai_b_handle_, (uint8_t*)buffer_rx, size)
314-
: HAL_SAI_Transmit_DMA(&sai_b_handle_, (uint8_t*)buffer_tx, size);
329+
if(!start_block(&sai_b_handle_, config_.b_dir)
330+
|| !start_block(&sai_a_handle_, config_.a_dir))
331+
return Result::ERR;
332+
}
333+
else if(a_slave)
334+
{
335+
if(!start_block(&sai_a_handle_, config_.a_dir)
336+
|| !start_block(&sai_b_handle_, config_.b_dir))
337+
return Result::ERR;
315338
}
316339
else
317340
{
318-
config_.b_dir == Config::Direction::RECEIVE
319-
? HAL_SAI_Receive_DMA(&sai_b_handle_, (uint8_t*)buffer_rx, size)
320-
: HAL_SAI_Transmit_DMA(&sai_b_handle_, (uint8_t*)buffer_tx, size);
321-
config_.a_dir == Config::Direction::RECEIVE
322-
? HAL_SAI_Receive_DMA(&sai_a_handle_, (uint8_t*)buffer_rx, size)
323-
: HAL_SAI_Transmit_DMA(&sai_a_handle_, (uint8_t*)buffer_tx, size);
341+
if(!start_block(&sai_b_handle_, config_.b_dir)
342+
|| !start_block(&sai_a_handle_, config_.a_dir))
343+
return Result::ERR;
324344
}
325345

326346
return Result::OK;
327347
}
328348
SaiHandle::Result SaiHandle::Impl::StopDmaTransfer()
329349
{
330-
HAL_SAI_DMAStop(&sai_a_handle_);
331-
HAL_SAI_DMAStop(&sai_b_handle_);
332-
return Result::OK;
350+
HAL_StatusTypeDef status_a = HAL_SAI_DMAStop(&sai_a_handle_);
351+
HAL_StatusTypeDef status_b = HAL_SAI_DMAStop(&sai_b_handle_);
352+
return (status_a == HAL_OK && status_b == HAL_OK) ? Result::OK
353+
: Result::ERR;
333354
}
334355

335356
float SaiHandle::Impl::GetSampleRate()

0 commit comments

Comments
 (0)