/* * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/i2s_std.h" #include "driver/gpio.h" #include "esp_check.h" #include "sdkconfig.h" #include "driver/i2c_master.h" #define EXAMPLE_BUFF_SIZE 2048 static i2s_chan_handle_t tx_chan; // I2S tx channel handler static i2s_chan_handle_t rx_chan; // I2S rx channel handler i2c_master_bus_config_t i2c_bus_config = { .clk_source = I2C_CLK_SRC_DEFAULT, .i2c_port = -1, .scl_io_num = GPIO_NUM_17, .sda_io_num = GPIO_NUM_18, .glitch_ignore_cnt = 7, }; i2c_master_bus_handle_t bus_handle; i2c_device_config_t chipconfig = { .scl_speed_hz = 100000, .device_address = 0b00100010 >> 1, }; static const char TAG[] = "i2c-eeprom"; static void i2s_example_read_task(void *args) { uint8_t *r_buf = (uint8_t *)calloc(1, EXAMPLE_BUFF_SIZE); assert(r_buf); // Check if r_buf allocation success size_t r_bytes = 0; /* Enable the RX channel */ ESP_ERROR_CHECK(i2s_channel_enable(rx_chan)); /* ATTENTION: The print and delay in the read task only for monitoring the data by human, * Normally there shouldn't be any delays to ensure a short polling time, * Otherwise the dma buffer will overflow and lead to the data lost */ while (1) { /* Read i2s data */ if (i2s_channel_read(rx_chan, r_buf, EXAMPLE_BUFF_SIZE, &r_bytes, 1000) == ESP_OK) { printf("Read Task: i2s read %d bytes\n-----------------------------------\n", r_bytes); printf("[0] %x [1] %x [2] %x [3] %x\n[4] %x [5] %x [6] %x [7] %x\n\n", r_buf[0], r_buf[1], r_buf[2], r_buf[3], r_buf[4], r_buf[5], r_buf[6], r_buf[7]); } else { printf("Read Task: i2s read failed\n"); } vTaskDelay(pdMS_TO_TICKS(200)); } free(r_buf); vTaskDelete(NULL); } static void i2s_example_write_task(void *args) { uint8_t *w_buf = (uint8_t *)calloc(1, EXAMPLE_BUFF_SIZE); assert(w_buf); // Check if w_buf allocation success /* Assign w_buf */ for (int i = 0; i < EXAMPLE_BUFF_SIZE; i += 8) { w_buf[i] = 170; // 0x12; w_buf[i + 1] = 170; // 0x34; w_buf[i + 2] = 170; // 0x56; w_buf[i + 3] = 170; // 0x78; w_buf[i + 4] = 170; // 0x9A; w_buf[i + 5] = 170; // 0xBC; w_buf[i + 6] = 170; // 0xDE; w_buf[i + 7] = 170; // 0xF0; } size_t w_bytes = EXAMPLE_BUFF_SIZE; /* (Optional) Preload the data before enabling the TX channel, so that the valid data can be transmitted immediately */ while (w_bytes == EXAMPLE_BUFF_SIZE) { /* Here we load the target buffer repeatedly, until all the DMA buffers are preloaded */ ESP_ERROR_CHECK(i2s_channel_preload_data(tx_chan, w_buf, EXAMPLE_BUFF_SIZE, &w_bytes)); } /* Enable the TX channel */ ESP_ERROR_CHECK(i2s_channel_enable(tx_chan)); while (1) { /* Write i2s data */ if (i2s_channel_write(tx_chan, w_buf, EXAMPLE_BUFF_SIZE, &w_bytes, 1000) == ESP_OK) { printf("Write Task: i2s write %d bytes\n", w_bytes); } else { printf("Write Task: i2s write failed\n"); } vTaskDelay(pdMS_TO_TICKS(200)); } free(w_buf); vTaskDelete(NULL); } static void i2s_example_init_std_duplex(void) { /* Setp 1: Determine the I2S channel configuration and allocate both channels * The default configuration can be generated by the helper macro, * it only requires the I2S controller id and I2S role */ i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER); ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_chan, &rx_chan)); /* Step 2: Setting the configurations of standard mode, and initialize rx & tx channels * The slot configuration and clock configuration can be generated by the macros * These two helper macros is defined in 'i2s_std.h' which can only be used in STD mode. * They can help to specify the slot and clock configurations for initialization or re-configuring */ i2s_std_config_t std_cfg = { .clk_cfg = { .sample_rate_hz = 16000, .clk_src = I2S_CLK_SRC_DEFAULT, .mclk_multiple = I2S_MCLK_MULTIPLE_512, }, .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_STEREO), .gpio_cfg = { .mclk = GPIO_NUM_21, .bclk = GPIO_NUM_2, .ws = GPIO_NUM_3, .dout = GPIO_NUM_4, .din = GPIO_NUM_5, .invert_flags = { .mclk_inv = false, .bclk_inv = false, .ws_inv = false, }, }, }; /* Initialize the channels */ ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &std_cfg)); ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_chan, &std_cfg)); } i2c_master_dev_handle_t i2c_dev; void app_main(void) { i2s_example_init_std_duplex(); ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &bus_handle)); int ret; gpio_set_pull_mode(GPIO_NUM_17, GPIO_PULLUP_ONLY); gpio_set_pull_mode(GPIO_NUM_18, GPIO_PULLUP_ONLY); ESP_GOTO_ON_ERROR(i2c_master_bus_add_device(bus_handle, &chipconfig, &i2c_dev), err, TAG, "i2c new bus failed"); while (1) { for (int i = 0; i < 256; i++) { if (i2c_master_probe(bus_handle, i, 1000) == ESP_OK) { printf("Found %d\n", i); } } } return; // Talk to configure dings /* Step 3: Create writing and reading task, enable and start the channels */ xTaskCreate(i2s_example_read_task, "i2s_example_read_task", 4096, NULL, 5, NULL); xTaskCreate(i2s_example_write_task, "i2s_example_write_task", 4096, NULL, 5, NULL); err: printf("Error\n"); return; }