diff options
| author | jacqueline <me@jacqueline.id.au> | 2024-05-31 11:52:19 +1000 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2024-05-31 11:52:19 +1000 |
| commit | f84474d94d3618b9dc2581b72aea768052a40dd7 (patch) | |
| tree | 85aa535684074acf09fb7e19dd21d03edbe94443 /src/drivers/include | |
| parent | 2ff8eac022f397bb1aed28aca376fbe422fc8b3c (diff) | |
| download | tangara-fw-f84474d94d3618b9dc2581b72aea768052a40dd7.tar.gz | |
Introduce a PcmBuffer abstraction for handling source draining
Diffstat (limited to 'src/drivers/include')
| -rw-r--r-- | src/drivers/include/drivers/bluetooth.hpp | 10 | ||||
| -rw-r--r-- | src/drivers/include/drivers/i2s_dac.hpp | 11 | ||||
| -rw-r--r-- | src/drivers/include/drivers/pcm_buffer.hpp | 72 |
3 files changed, 82 insertions, 11 deletions
diff --git a/src/drivers/include/drivers/bluetooth.hpp b/src/drivers/include/drivers/bluetooth.hpp index ad61fcc1..030907d9 100644 --- a/src/drivers/include/drivers/bluetooth.hpp +++ b/src/drivers/include/drivers/bluetooth.hpp @@ -14,6 +14,7 @@ #include <stdint.h> #include "drivers/bluetooth_types.hpp" #include "drivers/nvs.hpp" +#include "drivers/pcm_buffer.hpp" #include "esp_a2dp_api.h" #include "esp_avrc_api.h" #include "esp_gap_bt_api.h" @@ -42,9 +43,8 @@ class Bluetooth { auto SetPreferredDevice(std::optional<bluetooth::MacAndName> dev) -> void; auto PreferredDevice() -> std::optional<bluetooth::MacAndName>; - auto SetSource(StreamBufferHandle_t) -> void; + auto SetSource(PcmBuffer*) -> void; auto SetVolumeFactor(float) -> void; - auto SamplesUsed() -> uint32_t; auto SetEventHandler(std::function<void(bluetooth::Event)> cb) -> void; }; @@ -114,8 +114,8 @@ class BluetoothState : public tinyfsm::Fsm<BluetoothState> { static auto discovery() -> bool; static auto discovery(bool) -> void; - static auto source() -> StreamBufferHandle_t; - static auto source(StreamBufferHandle_t) -> void; + static auto source() -> PcmBuffer*; + static auto source(PcmBuffer*) -> void; static auto event_handler(std::function<void(Event)>) -> void; @@ -147,7 +147,7 @@ class BluetoothState : public tinyfsm::Fsm<BluetoothState> { static std::optional<bluetooth::MacAndName> sConnectingDevice_; static int sConnectAttemptsRemaining_; - static std::atomic<StreamBufferHandle_t> sSource_; + static std::atomic<PcmBuffer*> sSource_; static std::function<void(Event)> sEventHandler_; auto connect(const bluetooth::MacAndName&) -> bool; diff --git a/src/drivers/include/drivers/i2s_dac.hpp b/src/drivers/include/drivers/i2s_dac.hpp index 0776dbab..138a0c03 100644 --- a/src/drivers/include/drivers/i2s_dac.hpp +++ b/src/drivers/include/drivers/i2s_dac.hpp @@ -16,6 +16,7 @@ #include "driver/i2s_std.h" #include "driver/i2s_types.h" +#include "drivers/pcm_buffer.hpp" #include "esp_err.h" #include "freertos/FreeRTOS.h" #include "freertos/portmacro.h" @@ -39,9 +40,9 @@ constexpr size_t kI2SBufferLengthFrames = 1024; */ class I2SDac { public: - static auto create(IGpios& expander) -> std::optional<I2SDac*>; + static auto create(IGpios& expander, PcmBuffer&) -> std::optional<I2SDac*>; - I2SDac(IGpios& gpio, i2s_chan_handle_t i2s_handle); + I2SDac(IGpios& gpio, PcmBuffer&, i2s_chan_handle_t i2s_handle); ~I2SDac(); auto Start() -> void; @@ -69,9 +70,6 @@ class I2SDac { auto Reconfigure(Channels ch, BitsPerSample bps, SampleRate rate) -> void; auto WriteData(const std::span<const std::byte>& data) -> void; - auto SetSource(StreamBufferHandle_t buffer) -> void; - - auto SamplesUsed() -> uint32_t; // Not copyable or movable. I2SDac(const I2SDac&) = delete; @@ -81,9 +79,10 @@ class I2SDac { auto set_channel(bool) -> void; IGpios& gpio_; + PcmBuffer& buffer_; i2s_chan_handle_t i2s_handle_; + bool i2s_active_; - StreamBufferHandle_t buffer_; std::mutex configure_mutex_; i2s_std_clk_config_t clock_config_; diff --git a/src/drivers/include/drivers/pcm_buffer.hpp b/src/drivers/include/drivers/pcm_buffer.hpp new file mode 100644 index 00000000..6630f720 --- /dev/null +++ b/src/drivers/include/drivers/pcm_buffer.hpp @@ -0,0 +1,72 @@ +/* + * Copyright 2024 jacqueline <me@jacqueline.id.au> + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#pragma once + +#include <stdint.h> +#include <atomic> +#include <cstddef> +#include <span> + +#include "freertos/FreeRTOS.h" + +#include "freertos/ringbuf.h" +#include "portmacro.h" + +namespace drivers { + +/* + * A circular buffer of signed, 16-bit PCM samples. PcmBuffers are the main + * data structure used for shuffling large amounts of read-to-play samples + * throughout the system. + */ +class PcmBuffer { + public: + PcmBuffer(size_t size_in_samples); + ~PcmBuffer(); + + /* Adds samples to the buffer. */ + auto send(std::span<const int16_t>) -> void; + + /* + * Fills the given span with samples. If enough samples are available in + * the buffer, then the span will be filled with samples from the buffer. Any + * shortfall is made up by padding the given span with zeroes. + */ + auto receive(std::span<int16_t>, bool isr) -> BaseType_t; + + auto clear() -> void; + auto isEmpty() -> bool; + + /* + * How many samples have been added to this buffer since it was created. This + * method overflows by wrapping around to zero. + */ + auto totalSent() -> uint32_t; + + /* + * How many samples have been removed from this buffer since it was created. + * This method overflows by wrapping around to zero. + */ + auto totalReceived() -> uint32_t; + + // Not copyable or movable. + PcmBuffer(const PcmBuffer&) = delete; + PcmBuffer& operator=(const PcmBuffer&) = delete; + + private: + auto readSingle(std::span<int16_t>, bool isr) + -> std::pair<size_t, BaseType_t>; + + StaticRingbuffer_t meta_; + uint8_t* buf_; + + std::atomic<uint32_t> sent_; + std::atomic<uint32_t> received_; + RingbufHandle_t ringbuf_; +}; + +} // namespace drivers |
