Skip to content

Commit 35c1293

Browse files
[i2s] Don't restart dma when swapping buffers (#31)
1 parent bccd2d1 commit 35c1293

File tree

1 file changed

+19
-21
lines changed

1 file changed

+19
-21
lines changed

components/hub75/src/platforms/i2s/i2s_dma.cpp

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -978,29 +978,27 @@ void I2sDma::flip_buffer() {
978978
return;
979979
}
980980

981-
// Swap indices (front ↔ active)
981+
// Seamless descriptor chain redirection (no stop/start!)
982+
//
983+
// DMA is continuously traversing a circular descriptor chain (front buffer).
984+
// To switch buffers without stopping DMA:
985+
// 1. Redirect old front's last descriptor to new buffer's first descriptor
986+
// 2. Restore new buffer's circularity (so it loops forever when active)
987+
// 3. DMA seamlessly transitions at next frame boundary
988+
//
989+
// This matches the GDMA implementation and reference library approach.
990+
// No stop, no start, no visual glitch!
991+
992+
// Step 1: Redirect current front's last descriptor to new buffer's first descriptor
993+
descriptors_[front_idx_][descriptor_count_ - 1].qe.stqe_next = &descriptors_[active_idx_][0];
994+
995+
// Step 2: Restore new buffer's circularity (for when it becomes old front later)
996+
descriptors_[active_idx_][descriptor_count_ - 1].qe.stqe_next = &descriptors_[active_idx_][0];
997+
998+
// Step 3: Swap indices (after descriptor manipulation)
982999
std::swap(front_idx_, active_idx_);
9831000

984-
// Stop current DMA transfer
985-
i2s_dev_->conf.tx_start = 0;
986-
i2s_dev_->out_link.stop = 1;
987-
i2s_dev_->out_link.start = 0;
988-
989-
// Wait for stop to complete
990-
esp_rom_delay_us(100);
991-
992-
// Configure DMA burst mode
993-
i2s_dev_->lc_conf.val = I2S_OUT_DATA_BURST_EN | I2S_OUTDSCR_BURST_EN;
994-
995-
// Set address of new front buffer's descriptor chain
996-
i2s_dev_->out_link.addr = (uint32_t) &descriptors_[front_idx_][0];
997-
998-
// Start DMA with new chain
999-
i2s_dev_->out_link.stop = 0;
1000-
i2s_dev_->out_link.start = 1;
1001-
1002-
// Start I2S transmission with new buffer
1003-
i2s_dev_->conf.tx_start = 1;
1001+
// DMA seamlessly transitions at next frame boundary - no interruption!
10041002
}
10051003

10061004
// ============================================================================

0 commit comments

Comments
 (0)