i2s: update examples and unit-tests

This commit is contained in:
laokaiyao
2022-04-02 21:31:35 +08:00
parent 621d0aa942
commit 0fe3bb8ab7
38 changed files with 800 additions and 464 deletions

View File

@@ -10,7 +10,7 @@
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s_controller.h"
#include "driver/i2s.h"
#include "driver/gpio.h"
#include "esp_system.h"
#include "esp_log.h"
@@ -28,31 +28,27 @@
#define SAMPLE_PER_CYCLE (SAMPLE_RATE/WAVE_FREQ_HZ)
static const char *TAG = "i2s_example";
static i2s_chan_handle_t tx_handle = NULL;
static const char* TAG = "i2s_example";
static void setup_triangle_sine_waves(int bits)
{
int *samples_data = malloc(((bits + 8) / 16) * SAMPLE_PER_CYCLE * 4);
int *samples_data = malloc(((bits+8)/16)*SAMPLE_PER_CYCLE*4);
unsigned int i, sample_val;
double sin_float, triangle_float, triangle_step = (double) pow(2, bits) / SAMPLE_PER_CYCLE;
size_t i2s_bytes_write = 0;
static i2s_std_slot_config_t slot_cfg = I2S_STD_PHILIP_SLOT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO);
static i2s_std_clk_config_t clk_cfg = I2S_STD_CLK_CONFIG(SAMPLE_RATE);
printf("\r\nTest bits=%d free mem=%d, written data=%d\n", bits, esp_get_free_heap_size(), ((bits + 8) / 16)*SAMPLE_PER_CYCLE * 4);
printf("\r\nTest bits=%d free mem=%d, written data=%d\n", bits, esp_get_free_heap_size(), ((bits+8)/16)*SAMPLE_PER_CYCLE*4);
triangle_float = -(pow(2, bits) / 2 - 1);
triangle_float = -(pow(2, bits)/2 - 1);
for (i = 0; i < SAMPLE_PER_CYCLE; i++) {
for(i = 0; i < SAMPLE_PER_CYCLE; i++) {
sin_float = sin(i * 2 * PI / SAMPLE_PER_CYCLE);
if (sin_float >= 0) {
if(sin_float >= 0)
triangle_float += triangle_step;
} else {
else
triangle_float -= triangle_step;
}
sin_float *= (pow(2, bits) / 2 - 1);
sin_float *= (pow(2, bits)/2 - 1);
if (bits == 16) {
sample_val = 0;
@@ -61,34 +57,26 @@ static void setup_triangle_sine_waves(int bits)
sample_val += (short) sin_float;
samples_data[i] = sample_val;
} else if (bits == 24) { //1-bytes unused
samples_data[i * 2] = ((int) triangle_float) << 8;
samples_data[i * 2 + 1] = ((int) sin_float) << 8;
samples_data[i*2] = ((int) triangle_float) << 8;
samples_data[i*2 + 1] = ((int) sin_float) << 8;
} else {
samples_data[i * 2] = ((int) triangle_float);
samples_data[i * 2 + 1] = ((int) sin_float);
samples_data[i*2] = ((int) triangle_float);
samples_data[i*2 + 1] = ((int) sin_float);
}
}
ESP_LOGI(TAG, "set data bit width to %d", bits);
/* Updata clock and slot information */
slot_cfg.data_bit_width = bits;
i2s_stop_channel(tx_handle);
i2s_set_slot(tx_handle, &slot_cfg);
if (bits == 24) {
/**
* Because '24' has factor '3'
* The mclk multiple must be able to divide by '3' as well
* Otherwise the sample rate won't be accurate */
clk_cfg.mclk_multiple = I2S_MCLK_MULTIPLE_384;
i2s_set_clock(tx_handle, &clk_cfg);
} else {
clk_cfg.mclk_multiple = I2S_MCLK_MULTIPLE_256;
i2s_set_clock(tx_handle, &clk_cfg);
}
i2s_start_channel(tx_handle);
ESP_LOGI(TAG, "set clock");
i2s_set_clk(I2S_NUM, SAMPLE_RATE, bits, 2);
//Using push
// for(i = 0; i < SAMPLE_PER_CYCLE; i++) {
// if (bits == 16)
// i2s_push_sample(0, &samples_data[i], 100);
// else
// i2s_push_sample(0, &samples_data[i*2], 100);
// }
// or write
ESP_LOGI(TAG, "write data");
i2s_write_channel(tx_handle, samples_data, ((bits + 8) / 16)*SAMPLE_PER_CYCLE * 4, &i2s_bytes_write, 100);
i2s_write(I2S_NUM, samples_data, ((bits+8)/16)*SAMPLE_PER_CYCLE*4, &i2s_bytes_write, 100);
free(samples_data);
}
@@ -100,32 +88,35 @@ void app_main(void)
//using 6 buffers, we need 60-samples per buffer
//if 2-channels, 16-bit each channel, total buffer is 360*4 = 1440 bytes
//if 2-channels, 24/32-bit each channel, total buffer is 360*8 = 2880 bytes
i2s_gpio_config_t i2s_pin = {
.mclk = I2S_GPIO_UNUSED,
.bclk = I2S_BCK_IO,
.ws = I2S_WS_IO,
.dout = I2S_DO_IO,
.din = I2S_DI_IO
i2s_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
.sample_rate = SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_MSB,
.dma_desc_num = 6,
.dma_frame_num = 60,
.use_apll = false,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 //Interrupt level 1
};
i2s_chan_config_t chan_cfg = I2S_CHANNEL_CONFIG(I2S_ROLE_MASTER, I2S_COMM_MODE_STD, &i2s_pin);
chan_cfg.id = I2S_NUM;
i2s_new_channel(&chan_cfg, &tx_handle, NULL);
i2s_std_slot_config_t slot_cfg = I2S_STD_PHILIP_SLOT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO);
i2s_std_clk_config_t clk_cfg = I2S_STD_CLK_CONFIG(SAMPLE_RATE);
#if SOC_I2S_SUPPORTS_APLL
// APLL clock is more accurate when sample rate is high
clk_cfg.clk_src = I2S_CLK_APLL;
#endif
i2s_init_channel(tx_handle, &clk_cfg, &slot_cfg);
i2s_start_channel(tx_handle);
i2s_pin_config_t pin_config = {
.mck_io_num = I2S_PIN_NO_CHANGE,
.bck_io_num = I2S_BCK_IO,
.ws_io_num = I2S_WS_IO,
.data_out_num = I2S_DO_IO,
.data_in_num = I2S_DI_IO //Not used
};
i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM, &pin_config);
int test_bits = 16;
while (1) {
setup_triangle_sine_waves(test_bits);
vTaskDelay(pdMS_TO_TICKS(5000));
vTaskDelay(5000/portTICK_PERIOD_MS);
test_bits += 8;
if (test_bits > 32) {
if(test_bits > 32)
test_bits = 16;
}
}
}