#include "i2s_out.h" #include "waveform.h" #include "debug.h" #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/i2s_std.h" #include "esp_log.h" #define TAG "i2s_out" #define BUF_FRAMES 480 #define PIN_BCLK GPIO_NUM_16 #define PIN_WS GPIO_NUM_15 #define PIN_DOUT GPIO_NUM_17 static i2s_chan_handle_t tx_handle; void i2s_out_init(void) { i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER); ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle, NULL)); i2s_std_config_t std_cfg = { .clk_cfg = { .sample_rate_hz = SAMPLE_RATE, .clk_src = I2S_CLK_SRC_DEFAULT, .mclk_multiple = I2S_MCLK_MULTIPLE_512, }, .slot_cfg = { .data_bit_width = I2S_DATA_BIT_WIDTH_32BIT, .slot_bit_width = I2S_SLOT_BIT_WIDTH_32BIT, .slot_mode = I2S_SLOT_MODE_STEREO, .slot_mask = I2S_STD_SLOT_BOTH, .ws_width = 32, .ws_pol = false, .bit_shift = false, .left_align = true, .big_endian = false, .bit_order_lsb = false, }, .gpio_cfg = { .mclk = I2S_GPIO_UNUSED, .bclk = PIN_BCLK, .ws = PIN_WS, .dout = PIN_DOUT, .din = I2S_GPIO_UNUSED, .invert_flags = { .mclk_inv = false, .bclk_inv = false, .ws_inv = false, }, }, }; ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle, &std_cfg)); ESP_ERROR_CHECK(i2s_channel_enable(tx_handle)); ESP_LOGI(TAG, "I2S TX: 48kHz 24-bit stereo, BCLK=%d WS=%d DOUT=%d", PIN_BCLK, PIN_WS, PIN_DOUT); } static void i2s_out_task(void *arg) { int32_t buf[BUF_FRAMES * 2]; size_t bytes_written; DBG("i2s_out_task started"); for (;;) { waveform_fill_buffer(buf, BUF_FRAMES); i2s_channel_write(tx_handle, buf, sizeof(buf), &bytes_written, portMAX_DELAY); } } void i2s_out_start_task(void) { xTaskCreatePinnedToCore(i2s_out_task, "i2s_out", 8192, NULL, 10, NULL, 1); }