summaryrefslogtreecommitdiff
path: root/src/drivers/i2s_dac.cpp
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-05-08 16:03:03 +1000
committerjacqueline <me@jacqueline.id.au>2024-05-08 16:03:03 +1000
commit265049c5192cf0ce862c7db7b4745636afb6c17b (patch)
tree6729bc947c6c2d2d196c9e7baa994a35aeea76ee /src/drivers/i2s_dac.cpp
parentb242ba998699208c87dc066158964de0866b61e2 (diff)
downloadtangara-fw-265049c5192cf0ce862c7db7b4745636afb6c17b.tar.gz
Count samples going in and out of the drain buffer
This is a more accurate way of knowing which track is playing when, and also simplifies a lot of fragile logic in audio_fsm
Diffstat (limited to 'src/drivers/i2s_dac.cpp')
-rw-r--r--src/drivers/i2s_dac.cpp22
1 files changed, 18 insertions, 4 deletions
diff --git a/src/drivers/i2s_dac.cpp b/src/drivers/i2s_dac.cpp
index a271fce0..e5efe198 100644
--- a/src/drivers/i2s_dac.cpp
+++ b/src/drivers/i2s_dac.cpp
@@ -5,6 +5,7 @@
*/
#include "drivers/i2s_dac.hpp"
+#include <stdint.h>
#include <cmath>
#include <cstdint>
@@ -140,11 +141,10 @@ auto I2SDac::SetPaused(bool paused) -> void {
}
}
-static volatile bool sSwapWords = false;
+DRAM_ATTR static volatile bool sSwapWords = false;
-auto I2SDac::Reconfigure(Channels ch,
- BitsPerSample bps,
- SampleRate rate) -> void {
+auto I2SDac::Reconfigure(Channels ch, BitsPerSample bps, SampleRate rate)
+ -> void {
std::lock_guard<std::mutex> lock(configure_mutex_);
if (i2s_active_) {
@@ -217,6 +217,8 @@ auto I2SDac::WriteData(const std::span<const std::byte>& data) -> void {
}
}
+DRAM_ATTR static volatile uint32_t sSamplesRead = 0;
+
extern "C" IRAM_ATTR auto callback(i2s_chan_handle_t handle,
i2s_event_data_t* event,
void* user_ctx) -> bool {
@@ -235,6 +237,14 @@ extern "C" IRAM_ATTR auto callback(i2s_chan_handle_t handle,
size_t bytes_written =
xStreamBufferReceiveFromISR(src, buf, event->size, &ret);
+ // Assume 16 bit samples.
+ size_t samples = bytes_written / 2;
+ if (UINT32_MAX - sSamplesRead < samples) {
+ sSamplesRead = samples - (UINT32_MAX - sSamplesRead);
+ } else {
+ sSamplesRead = sSamplesRead + samples;
+ }
+
// The ESP32's I2S peripheral has a different endianness to its processors.
// ESP-IDF handles this difference for stereo channels, but not for mono
// channels. We therefore sometimes need to swap each pair of words as they're
@@ -276,6 +286,10 @@ auto I2SDac::SetSource(StreamBufferHandle_t buffer) -> void {
}
}
+auto I2SDac::SamplesUsed() -> uint32_t {
+ return sSamplesRead;
+}
+
auto I2SDac::set_channel(bool enabled) -> void {
if (i2s_active_ == enabled) {
return;