171 lines
5.9 KiB
C
171 lines
5.9 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#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,
|
|
.flags.enable_internal_pullup = true,
|
|
};
|
|
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;
|
|
|
|
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;
|
|
}
|