summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2023-02-14 14:30:53 +1100
committerjacqueline <me@jacqueline.id.au>2023-02-14 14:30:53 +1100
commita65d996583c72e0d77805bcbc36da580aacb2848 (patch)
treeee64bb43ff2f44f495942e50e77176476b71f7b5 /src/drivers
parentfa1f1cd9aba914882b95e93cdf64ad01309aa633 (diff)
downloadtangara-fw-a65d996583c72e0d77805bcbc36da580aacb2848.tar.gz
Use the sync apis for I2S output
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/dac.cpp61
-rw-r--r--src/drivers/display.cpp4
-rw-r--r--src/drivers/include/dac.hpp9
3 files changed, 17 insertions, 57 deletions
diff --git a/src/drivers/dac.cpp b/src/drivers/dac.cpp
index eec1959f..70f344c4 100644
--- a/src/drivers/dac.cpp
+++ b/src/drivers/dac.cpp
@@ -8,9 +8,11 @@
#include "driver/i2s_common.h"
#include "driver/i2s_std.h"
#include "driver/i2s_types.h"
+#include "esp_attr.h"
#include "esp_err.h"
#include "esp_log.h"
#include "freertos/portmacro.h"
+#include "freertos/projdefs.h"
#include "hal/i2c_types.h"
#include "gpio_expander.hpp"
@@ -28,22 +30,13 @@ static const AudioDac::SampleRate kDefaultSampleRate =
AudioDac::SAMPLE_RATE_44_1;
static const AudioDac::BitsPerSample kDefaultBps = AudioDac::BPS_16;
-extern "C" {
-bool dma_callback(i2s_chan_handle_t handle,
- i2s_event_data_t* event,
- void* user_ctx) {
- AudioDac* dac = static_cast<AudioDac*>(user_ctx);
- return dac->WriteDataFromISR(static_cast<std::byte*>(event->data),
- event->size);
-}
-}
-
auto AudioDac::create(GpioExpander* expander)
-> cpp::result<std::unique_ptr<AudioDac>, Error> {
// TODO: tune.
i2s_chan_handle_t i2s_handle;
i2s_chan_config_t channel_config =
I2S_CHANNEL_DEFAULT_CONFIG(kI2SPort, I2S_ROLE_MASTER);
+
ESP_ERROR_CHECK(i2s_new_channel(&channel_config, &i2s_handle, NULL));
//
// First, instantiate the instance so it can do all of its power on
@@ -108,8 +101,7 @@ AudioDac::AudioDac(GpioExpander* gpio, i2s_chan_handle_t i2s_handle)
i2s_handle_(i2s_handle),
clock_config_(I2S_STD_CLK_DEFAULT_CONFIG(44100)),
slot_config_(I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT,
- I2S_SLOT_MODE_STEREO)),
- dma_queue_(nullptr) {
+ I2S_SLOT_MODE_STEREO)) {
gpio_->set_pin(GpioExpander::AUDIO_POWER_ENABLE, true);
gpio_->Write();
}
@@ -167,9 +159,7 @@ bool AudioDac::WaitForPowerState(
return has_matched;
}
-auto AudioDac::Reconfigure(BitsPerSample bps,
- SampleRate rate,
- QueueHandle_t dma_queue) -> std::size_t {
+auto AudioDac::Reconfigure(BitsPerSample bps, SampleRate rate) -> void {
// TODO(jacqueline): investigate how reliable the auto-clocking of the dac
// is. We might need to explicit reconfigure the dac here as well if it's not
// good enough.
@@ -183,44 +173,17 @@ auto AudioDac::Reconfigure(BitsPerSample bps,
bps == BPS_24 ? I2S_MCLK_MULTIPLE_384 : I2S_MCLK_MULTIPLE_256;
ESP_ERROR_CHECK(i2s_channel_reconfig_std_clock(i2s_handle_, &clock_config_));
- dma_queue_ = dma_queue;
-
- // TODO: less spooky action here plz.
- // dma_buffer_size = dma_frame_num (channel config) * slot_num (always 2?) *
- // slot_bit_width / 8
- //size_t dma_size = 240 * 2 * slot_config_.slot_bit_width / 8;
- size_t dma_size = 960;
- ESP_LOGI(kTag, "new dma size: %u bytes", dma_size);
-
- i2s_event_callbacks_t callbacks = {
- .on_recv = NULL,
- .on_recv_q_ovf = NULL,
- .on_sent = &dma_callback,
- .on_send_q_ovf = NULL,
- };
- ESP_ERROR_CHECK(
- i2s_channel_register_event_callback(i2s_handle_, &callbacks, this));
-
ESP_ERROR_CHECK(i2s_channel_enable(i2s_handle_));
-
- return dma_size;
}
-auto AudioDac::WriteDataFromISR(std::byte* data, std::size_t size) -> bool {
- std::byte* new_data;
- BaseType_t high_priority_task_awoken = pdFALSE;
-
- if (xQueueReceiveFromISR(dma_queue_, &new_data, &high_priority_task_awoken)) {
- // Item was received. Copy it into the DMA buffer.
- memcpy(data, new_data, size);
- free(new_data);
- ESP_DRAM_LOGI(kTag, "wrote dma");
- } else {
- // No item was received. Write empty data.
- memset(data, 0, size);
+auto AudioDac::WriteData(cpp::span<std::byte> data) -> std::size_t {
+ std::size_t bytes_written = 0;
+ esp_err_t err = i2s_channel_write(i2s_handle_, data.data(), data.size_bytes(),
+ &bytes_written, 0);
+ if (err != ESP_ERR_TIMEOUT) {
+ ESP_ERROR_CHECK(err);
}
-
- return high_priority_task_awoken;
+ return bytes_written;
}
void AudioDac::WriteRegister(Register reg, uint8_t val) {
diff --git a/src/drivers/display.cpp b/src/drivers/display.cpp
index ce8e7169..951a45eb 100644
--- a/src/drivers/display.cpp
+++ b/src/drivers/display.cpp
@@ -50,8 +50,8 @@ namespace callback {
static std::atomic<Display*> instance = nullptr;
extern "C" void flush_cb(lv_disp_drv_t* disp_drv,
- const lv_area_t* area,
- lv_color_t* color_map) {
+ const lv_area_t* area,
+ lv_color_t* color_map) {
auto instance_unwrapped = instance.load();
if (instance_unwrapped == nullptr) {
ESP_LOGW(kTag, "uncaught flush callback");
diff --git a/src/drivers/include/dac.hpp b/src/drivers/include/dac.hpp
index 698019b7..e682d8d7 100644
--- a/src/drivers/include/dac.hpp
+++ b/src/drivers/include/dac.hpp
@@ -10,6 +10,7 @@
#include "driver/i2s_std.h"
#include "driver/i2s_types.h"
#include "esp_err.h"
+#include "freertos/FreeRTOS.h"
#include "freertos/portmacro.h"
#include "result.hpp"
#include "span.hpp"
@@ -67,10 +68,9 @@ class AudioDac {
};
// TODO(jacqueline): worth supporting channels here as well?
- auto Reconfigure(BitsPerSample bps, SampleRate rate, QueueHandle_t dma_queue)
- -> std::size_t;
+ auto Reconfigure(BitsPerSample bps, SampleRate rate) -> void;
- auto WriteDataFromISR(std::byte* data, std::size_t size) -> bool;
+ auto WriteData(cpp::span<std::byte> data) -> std::size_t;
// Not copyable or movable.
AudioDac(const AudioDac&) = delete;
@@ -83,9 +83,6 @@ class AudioDac {
i2s_std_clk_config_t clock_config_;
i2s_std_slot_config_t slot_config_;
- // TODO: volatile?
- volatile QueueHandle_t dma_queue_;
-
/*
* Pools the power state for up to 10ms, waiting for the given predicate to
* be true.