summaryrefslogtreecommitdiff
path: root/src/drivers/dac.cpp
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2023-01-21 19:01:54 +1100
committerjacqueline <me@jacqueline.id.au>2023-01-21 19:01:54 +1100
commit8ed3d7e31f8b16a24593c01a480b19b14a513b48 (patch)
treef055abec7631f9682396ad5c3f125824d76cc95e /src/drivers/dac.cpp
parentc7901ae4297d42d55bb3a06010198ecf14b3a7ba (diff)
downloadtangara-fw-8ed3d7e31f8b16a24593c01a480b19b14a513b48.tar.gz
Re-enable the parts of the audio pipeline that are working
Diffstat (limited to 'src/drivers/dac.cpp')
-rw-r--r--src/drivers/dac.cpp83
1 files changed, 47 insertions, 36 deletions
diff --git a/src/drivers/dac.cpp b/src/drivers/dac.cpp
index 78bf94c4..2c7b3e5b 100644
--- a/src/drivers/dac.cpp
+++ b/src/drivers/dac.cpp
@@ -4,9 +4,9 @@
#include "assert.h"
#include "driver/i2c.h"
-#include "driver/i2s.h"
+#include "driver/i2s_common.h"
+#include "driver/i2s_std.h"
#include "driver/i2s_types.h"
-#include "driver/i2s_types_legacy.h"
#include "esp_err.h"
#include "esp_log.h"
#include "hal/i2c_types.h"
@@ -28,45 +28,43 @@ static const AudioDac::BitsPerSample kDefaultBps = AudioDac::BPS_16;
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(I2S_NUM_AUTO, I2S_ROLE_MASTER);
+ i2s_new_channel(&channel_config, &i2s_handle, NULL);
+ //
// First, instantiate the instance so it can do all of its power on
// configuration.
- std::unique_ptr<AudioDac> dac = std::make_unique<AudioDac>(expander);
+ std::unique_ptr<AudioDac> dac = std::make_unique<AudioDac>(expander, i2s_handle);
// Whilst we wait for the initial boot, we can work on installing the I2S
// driver.
- i2s_config_t i2s_config = {
- // static_cast bc esp-adf uses enums incorrectly
- .mode = static_cast<i2s_mode_t>(I2S_MODE_MASTER | I2S_MODE_TX),
- .sample_rate = 44100,
- .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
- .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
- .communication_format = I2S_COMM_FORMAT_STAND_I2S,
- .intr_alloc_flags = ESP_INTR_FLAG_LOWMED,
- // TODO(jacqueline): tune dma buffer size. this seems very smol.
- .dma_buf_count = 8,
- .dma_buf_len = 64,
- .use_apll = false,
- .tx_desc_auto_clear = false,
- .fixed_mclk = 0,
- .mclk_multiple = I2S_MCLK_MULTIPLE_512, // TODO: double check
- .bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT,
+ i2s_std_config_t i2s_config = {
+ .clk_cfg = dac->clock_config_,
+ .slot_cfg = dac->slot_config_,
+ .gpio_cfg = {
+ .mclk = GPIO_NUM_0,
+ .bclk = GPIO_NUM_26,
+ .ws = GPIO_NUM_27,
+ .dout = GPIO_NUM_5,
+ .din = I2S_GPIO_UNUSED,
+ .invert_flags = {
+ .mclk_inv = false,
+ .bclk_inv = false,
+ .ws_inv = false,
+ }
+ },
};
- if (esp_err_t err =
- i2s_driver_install(kI2SPort, &i2s_config, 0, NULL) != ESP_OK) {
- ESP_LOGE(kTag, "failed to configure i2s pins %x", err);
+ if (esp_err_t err = i2s_channel_init_std_mode(i2s_handle, &i2s_config) != ESP_OK) {
+ ESP_LOGE(kTag, "failed to initialise i2s channel %x", err);
return cpp::fail(Error::FAILED_TO_INSTALL_I2S);
}
- i2s_pin_config_t pin_config = {.mck_io_num = GPIO_NUM_0,
- .bck_io_num = GPIO_NUM_26,
- .ws_io_num = GPIO_NUM_27,
- .data_out_num = GPIO_NUM_5,
- .data_in_num = I2S_PIN_NO_CHANGE};
- if (esp_err_t err = i2s_set_pin(kI2SPort, &pin_config) != ESP_OK) {
- ESP_LOGE(kTag, "failed to configure i2s pins %x", err);
- return cpp::fail(Error::FAILED_TO_INSTALL_I2S);
- }
+ // TODO: does starting the channel mean the dac will boot into a more
+ // meaningful state?
+ i2s_channel_enable(dac->i2s_handle_);
// Now let's double check that the DAC itself came up whilst we we working.
bool is_booted = dac->WaitForPowerState(
@@ -92,13 +90,17 @@ auto AudioDac::create(GpioExpander* expander)
return dac;
}
-AudioDac::AudioDac(GpioExpander* gpio) : gpio_(gpio) {
+AudioDac::AudioDac(GpioExpander* gpio, i2s_chan_handle_t i2s_handle) : gpio_(gpio),
+ i2s_handle_(i2s_handle),
+ clock_config_(I2S_STD_CLK_DEFAULT_CONFIG(48000)),
+ slot_config_(I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_STEREO)) {
gpio_->set_pin(GpioExpander::AUDIO_POWER_ENABLE, true);
gpio_->Write();
}
AudioDac::~AudioDac() {
- i2s_driver_uninstall(kI2SPort);
+ i2s_channel_disable(i2s_handle_);
+ i2s_del_channel(i2s_handle_);
gpio_->set_pin(GpioExpander::AUDIO_POWER_ENABLE, false);
gpio_->Write();
}
@@ -136,7 +138,7 @@ bool AudioDac::WaitForPowerState(
if (has_matched) {
break;
} else {
- ESP_LOGI(kTag, "Waiting for power state (was %d %x)", result.first,
+ ESP_LOGI(kTag, "Waiting for power state (was %d 0x%x)", result.first,
(uint8_t)result.second);
vTaskDelay(pdMS_TO_TICKS(1));
}
@@ -148,14 +150,23 @@ auto AudioDac::Reconfigure(BitsPerSample bps, SampleRate rate) -> bool {
// 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.
- i2s_set_clk(kI2SPort, rate, bps, I2S_CHANNEL_STEREO);
+ i2s_channel_disable(i2s_handle_);
+
+ slot_config_.slot_bit_width = (i2s_slot_bit_width_t) bps;
+ i2s_channel_reconfig_std_slot(i2s_handle_, &slot_config_);
+
+ // TODO: update mclk multiple as well if needed?
+ clock_config_.sample_rate_hz = rate;
+ i2s_channel_reconfig_std_clock(i2s_handle_, &clock_config_);
+
+ i2s_channel_enable(i2s_handle_);
return true;
}
auto AudioDac::WriteData(const cpp::span<std::byte>& data, TickType_t max_wait)
-> std::size_t {
std::size_t res = 0;
- i2s_write(kI2SPort, data.data(), data.size(), &res, max_wait);
+ i2s_channel_write(i2s_handle_, data.data(), data.size(), &res, max_wait);
return res;
}