i2stest/main/i2s_main.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;
}