From 80d7df910987db5201402fe987124f29f09344f3 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Tue, 25 Jul 2023 17:42:36 +1000 Subject: fuck off --- src/drivers/i2s_dac.cpp | 91 +++++++++++++---------------------------- src/drivers/include/i2s_dac.hpp | 3 +- src/drivers/include/storage.hpp | 4 -- src/drivers/spi.cpp | 5 ++- src/drivers/storage.cpp | 58 +++----------------------- 5 files changed, 39 insertions(+), 122 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/i2s_dac.cpp b/src/drivers/i2s_dac.cpp index 6ffc9e7b..74760543 100644 --- a/src/drivers/i2s_dac.cpp +++ b/src/drivers/i2s_dac.cpp @@ -5,7 +5,9 @@ */ #include "i2s_dac.hpp" -#include + +#include +#include #include #include @@ -21,6 +23,7 @@ #include "esp_log.h" #include "freertos/portmacro.h" #include "freertos/projdefs.h" +#include "freertos/ringbuf.h" #include "hal/gpio_types.h" #include "hal/i2c_types.h" @@ -28,7 +31,6 @@ #include "hal/i2s_types.h" #include "i2c.hpp" #include "soc/clk_tree_defs.h" -#include "sys/_stdint.h" namespace drivers { @@ -62,14 +64,6 @@ auto I2SDac::create(IGpios* expander) -> std::optional { i2s_chan_config_t channel_config = I2S_CHANNEL_DEFAULT_CONFIG(kI2SPort, I2S_ROLE_MASTER); - // Use the maximum possible DMA buffer size, since a smaller number of large - // copies is faster than a large number of small copies. - channel_config.dma_frame_num = 1024; - // Triple buffering should be enough to keep samples flowing smoothly. - // TODO(jacqueline): verify this with 192kHz 32bps. - channel_config.dma_desc_num = 4; - // channel_config.auto_clear = true; - ESP_ERROR_CHECK(i2s_new_channel(&channel_config, &i2s_handle, NULL)); // // First, instantiate the instance so it can do all of its power on @@ -90,7 +84,7 @@ auto I2SDac::create(IGpios* expander) -> std::optional { { .mclk_inv = false, .bclk_inv = false, - .ws_inv = true, + .ws_inv = false, }}, }; @@ -107,10 +101,9 @@ I2SDac::I2SDac(IGpios* gpio, i2s_chan_handle_t i2s_handle) : gpio_(gpio), i2s_handle_(i2s_handle), i2s_active_(false), - active_page_(), - clock_config_(I2S_STD_CLK_DEFAULT_CONFIG(44100)), + clock_config_(I2S_STD_CLK_DEFAULT_CONFIG(48000)), slot_config_(I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, - I2S_SLOT_MODE_STEREO)) { + I2S_SLOT_MODE_STEREO)) { clock_config_.clk_src = I2S_CLK_SRC_PLL_160M; // Keep the 5V circuity off until it's needed. @@ -122,6 +115,12 @@ I2SDac::I2SDac(IGpios* gpio, i2s_chan_handle_t i2s_handle) // Power up the charge pump. write_register(kPsCtrl, 0, 0b01); + + // TODO: testing + // write_register(kDacGainLeft, 0b01, 0x50); + // write_register(kDacGainRight, 0b11, 0x50); + write_register(kDacGainLeft, 0b01, 0x80); + write_register(kDacGainRight, 0b11, 0x78); } I2SDac::~I2SDac() { @@ -167,14 +166,18 @@ auto I2SDac::Reconfigure(Channels ch, BitsPerSample bps, SampleRate rate) switch (bps) { case BPS_16: slot_config_.data_bit_width = I2S_DATA_BIT_WIDTH_16BIT; + slot_config_.ws_width = 16; word_length = 0b00; break; case BPS_24: slot_config_.data_bit_width = I2S_DATA_BIT_WIDTH_24BIT; + slot_config_.ws_width = 24; word_length = 0b10; break; case BPS_32: + // TODO(jacqueline): Error on this? It's not supported anymore. slot_config_.data_bit_width = I2S_DATA_BIT_WIDTH_32BIT; + slot_config_.ws_width = 32; word_length = 0b11; break; } @@ -189,9 +192,9 @@ auto I2SDac::Reconfigure(Channels ch, BitsPerSample bps, SampleRate rate) ESP_ERROR_CHECK(i2s_channel_reconfig_std_clock(i2s_handle_, &clock_config_)); // Set the correct word size, and set the input format to I2S-justified. - write_register(kAifCtrl1, 0, (word_length << 3) & 0b10); + write_register(kAifCtrl1, 0, (word_length << 3) | 0b10); // Tell the DAC the clock ratio instead of waiting for it to auto detect. - write_register(kAifCtrl2, 0, bps == BPS_24 ? 0b100 : 0b011); + // write_register(kAifCtrl2, 0, bps == BPS_24 ? 0b100 : 0b011); if (i2s_active_) { i2s_channel_enable(i2s_handle_); @@ -208,12 +211,6 @@ auto I2SDac::WriteData(const cpp::span& data) -> void { } } -static constexpr double increment = (2.0 * 3.141592) / (44100.0 / 500.0); -static constexpr double amplitude = 16'777'216.0 * 0.6; -static double current = 0; -static uint8_t leftover = 0; -static bool left = false; - extern "C" IRAM_ATTR auto callback(i2s_chan_handle_t handle, i2s_event_data_t* event, void* user_ctx) -> bool { @@ -223,52 +220,20 @@ extern "C" IRAM_ATTR auto callback(i2s_chan_handle_t handle, if (event->data == nullptr || event->size == 0) { return false; } - /* uint8_t** buf = reinterpret_cast(event->data); - StreamBufferHandle_t src = reinterpret_cast(user_ctx); + auto src = reinterpret_cast(user_ctx); + BaseType_t ret = false; - std::size_t bytes_received = + size_t bytes_written = xStreamBufferReceiveFromISR(src, *buf, event->size, &ret); - if (bytes_received < event->size) { - memset(*buf + bytes_received, 0, event->size - bytes_received); + + // If we ran out of data, then make sure we clear out the DMA buffers rather + // than continuing to repreat the last few samples. + if (bytes_written < event->size) { + std::memset((*buf) + bytes_written, 0, event->size - bytes_written); } + return ret; - */ - uint8_t* buf = *(reinterpret_cast(event->data)); - std::size_t i = 0; - while (i < event->size) { - uint32_t sample = amplitude * std::sin(current); - if (leftover > 0) { - if (leftover == 2) { - buf[i++] = (sample >> 8) & 0xFF; - leftover--; - } - if (leftover == 1) { - buf[i++] = sample & 0xFF; - leftover--; - } - continue; - } - - buf[i++] = (sample >> 16) & 0xFF; - if (i == event->size) { - leftover = 2; - return false; - } - buf[i++] = (sample >> 8) & 0xFF; - if (i == event->size) { - leftover = 1; - return false; - } - buf[i++] = sample & 0xFF; - if (left) { - current += increment; - left = false; - } else { - left = true; - } - } - return false; } auto I2SDac::SetSource(StreamBufferHandle_t buffer) -> void { diff --git a/src/drivers/include/i2s_dac.hpp b/src/drivers/include/i2s_dac.hpp index 39eb9c4c..06c0dc16 100644 --- a/src/drivers/include/i2s_dac.hpp +++ b/src/drivers/include/i2s_dac.hpp @@ -18,6 +18,7 @@ #include "esp_err.h" #include "freertos/FreeRTOS.h" #include "freertos/portmacro.h" +#include "freertos/ringbuf.h" #include "freertos/stream_buffer.h" #include "result.hpp" #include "span.hpp" @@ -73,7 +74,7 @@ class I2SDac { IGpios* gpio_; i2s_chan_handle_t i2s_handle_; bool i2s_active_; - std::optional active_page_; + StreamBufferHandle_t buffer_; i2s_std_clk_config_t clock_config_; i2s_std_slot_config_t slot_config_; diff --git a/src/drivers/include/storage.hpp b/src/drivers/include/storage.hpp index a9269261..65be75f1 100644 --- a/src/drivers/include/storage.hpp +++ b/src/drivers/include/storage.hpp @@ -34,7 +34,6 @@ class SdStorage { static auto Create(IGpios* gpio) -> cpp::result; SdStorage(IGpios* gpio, - esp_err_t (*do_transaction)(sdspi_dev_handle_t, sdmmc_command_t*), sdspi_dev_handle_t handle_, std::unique_ptr host_, std::unique_ptr card_, @@ -47,15 +46,12 @@ class SdStorage { auto GetFs() -> FATFS*; // Not copyable or movable. - // TODO: maybe this could be movable? SdStorage(const SdStorage&) = delete; SdStorage& operator=(const SdStorage&) = delete; private: IGpios* gpio_; - esp_err_t (*do_transaction_)(sdspi_dev_handle_t, sdmmc_command_t*) = nullptr; - // SPI and SD driver info sdspi_dev_handle_t handle_; std::unique_ptr host_; diff --git a/src/drivers/spi.cpp b/src/drivers/spi.cpp index 1e9323ae..b31d1460 100644 --- a/src/drivers/spi.cpp +++ b/src/drivers/spi.cpp @@ -38,8 +38,9 @@ esp_err_t init_spi(void) { // manages its down use of DMA-capable memory. .max_transfer_sz = 128 * 16 * 2, // TODO: hmm .flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_IOMUX_PINS, - .intr_flags = - ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_IRAM, + .intr_flags = ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM, + //.intr_flags = ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | + // ESP_INTR_FLAG_IRAM, }; if (esp_err_t err = spi_bus_initialize(kSpiHost, &config, SPI_DMA_CH_AUTO)) { diff --git a/src/drivers/storage.cpp b/src/drivers/storage.cpp index 04da8819..db257dee 100644 --- a/src/drivers/storage.cpp +++ b/src/drivers/storage.cpp @@ -32,37 +32,12 @@ namespace drivers { const char* kStoragePath = "/sdcard"; -// Static functions for interrop with the ESP IDF API, which requires a -// function pointer. -namespace callback { -static std::atomic instance = nullptr; -static std::atomic - bootstrap = nullptr; - -static esp_err_t do_transaction(sdspi_dev_handle_t handle, - sdmmc_command_t* cmdinfo) { - auto bootstrap_fn = bootstrap.load(); - if (bootstrap_fn != nullptr) { - return bootstrap_fn(handle, cmdinfo); - } - auto instance_unwrapped = instance.load(); - if (instance_unwrapped == nullptr) { - ESP_LOGW(kTag, "uncaught sdspi transaction"); - return ESP_OK; - } - // TODO: what if a transaction comes in right now? - return instance_unwrapped->HandleTransaction(handle, cmdinfo); -} -} // namespace callback - auto SdStorage::Create(IGpios* gpio) -> cpp::result { gpio->WriteSync(IGpios::Pin::kSdPowerEnable, 1); gpio->WriteSync(IGpios::Pin::kSdMuxSwitch, IGpios::SD_MUX_ESP); gpio->WriteSync(IGpios::Pin::kSdMuxDisable, 0); sdspi_dev_handle_t handle; - std::unique_ptr host; - std::unique_ptr card; FATFS* fs = nullptr; // Now we can init the driver and set up the SD card into SPI mode. @@ -80,17 +55,10 @@ auto SdStorage::Create(IGpios* gpio) -> cpp::result { return cpp::fail(Error::FAILED_TO_INIT); } - host = std::make_unique(sdmmc_host_t SDSPI_HOST_DEFAULT()); - card = std::make_unique(); + auto host = std::make_unique(sdmmc_host_t SDSPI_HOST_DEFAULT()); + auto card = std::make_unique(); - // We manage the CS pin ourselves via the GPIO expander. To do this safely in - // a multithreaded environment, we wrap the ESP IDF do_transaction function - // with our own that acquires the CS mutex for the duration of the SPI - // transaction. - auto do_transaction = host->do_transaction; - host->do_transaction = &callback::do_transaction; host->slot = handle; - callback::bootstrap = do_transaction; // Will return ESP_ERR_INVALID_RESPONSE if there is no card esp_err_t err = sdmmc_card_init(host.get(), card.get()); @@ -101,6 +69,7 @@ auto SdStorage::Create(IGpios* gpio) -> cpp::result { ESP_ERROR_CHECK(esp_vfs_fat_register(kStoragePath, "", kMaxOpenFiles, &fs)); ff_diskio_register_sdmmc(fs->pdrv, card.get()); + ff_sdmmc_set_disk_status_check(fs->pdrv, true); // Mount right now, not on first operation. FRESULT ferr = f_mount(fs, "", 1); @@ -109,26 +78,19 @@ auto SdStorage::Create(IGpios* gpio) -> cpp::result { return cpp::fail(Error::FAILED_TO_MOUNT); } - return new SdStorage(gpio, do_transaction, handle, std::move(host), - std::move(card), fs); + return new SdStorage(gpio, handle, std::move(host), std::move(card), fs); } SdStorage::SdStorage(IGpios* gpio, - esp_err_t (*do_transaction)(sdspi_dev_handle_t, - sdmmc_command_t*), sdspi_dev_handle_t handle, std::unique_ptr host, std::unique_ptr card, FATFS* fs) : gpio_(gpio), - do_transaction_(do_transaction), handle_(handle), host_(std::move(host)), card_(std::move(card)), - fs_(fs) { - callback::instance = this; - callback::bootstrap = nullptr; -} + fs_(fs) {} SdStorage::~SdStorage() { // Unmount and unregister the filesystem @@ -137,22 +99,14 @@ SdStorage::~SdStorage() { esp_vfs_fat_unregister_path(kStoragePath); fs_ = nullptr; - callback::instance = nullptr; - // Uninstall the SPI driver sdspi_host_remove_device(this->handle_); sdspi_host_deinit(); - gpio_->WriteSync(IGpios::Pin::kSdPowerEnable, 0); + gpio_->WriteSync(IGpios::Pin::kSdPowerEnable, 1); gpio_->WriteSync(IGpios::Pin::kSdMuxDisable, 1); } -auto SdStorage::HandleTransaction(sdspi_dev_handle_t handle, - sdmmc_command_t* cmdinfo) -> esp_err_t { - // TODO: not needed anymore? - return do_transaction_(handle, cmdinfo); -} - auto SdStorage::GetFs() -> FATFS* { return fs_; } -- cgit v1.2.3