mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-30 19:19:21 +00:00
I2S: fixed support for 24 and 32-bits, fixed tx/rx at the same time and others in log:
Add support 24, 32 bits @jxmao optimize i2s_zero_buffer @jxmao correct config support slave mode @jxmao correct setup pin support tx/rx at the same time Enhance pin power @jxmao add dynamic change number of channels remove nvs_init remove start log and enhance power pin setup using enum for i2s_channel and i2s_bits_per_sample, return ESP_ERR_INVALID_ARG when check params validate i2s_bits_per_sample and channel check tx & rx buffer before fill zero remove checking channel as @jxmao suggest limit dma buffer modify i2s pin back to gpio mux before configure gpio matrix, resolve github issue #512 Add support 24, 32 bits reduce push function Modify sample can test with 24, 32-bits Add i2s sample README Fixed i2s_set_clk got reset sometime can changes bit-wide while running Fix sample rate calculation for DAC mode from @jeroen modify example can change bits per sample every 5 seconds cleanup add comment for bytes_per_sample update as @angus suggestions Add i2s_set_clk api I2S driver bug fixed as following log: @jxmao optimize i2s_zero_buffer @jxmao correct config support slave mode @jxmao correct setup pin support tx/rx at the same time Enhance pin power @jxmao add dynamic change number of channels remove nvs_init remove start log and enhance power pin setup using enum for i2s_channel and i2s_bits_per_sample, return ESP_ERR_INVALID_ARG when check params validate i2s_bits_per_sample and channel check tx & rx buffer before fill zero remove checking channel as @jxmao suggest limit dma buffer modify i2s pin back to gpio mux before configure gpio matrix, resolve github issue #512 limit dma buffer to 4092 change gpio_matrix_*_check to inline function, remove some comments and rename test_i2s function to setup_triangle_sine_waves for change commit title
This commit is contained in:
11
examples/peripherals/i2s/README.md
Normal file
11
examples/peripherals/i2s/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# I2S Example
|
||||
|
||||
### This example shows:
|
||||
|
||||
Init and using I2S module:
|
||||
|
||||
* Generate 100Hz triangle wave in a channel, and sine wave in another, with 36Khz sample rates. Change bits per sample every 5 seconds
|
||||
|
||||
* You can change bits per sample and sample rates with `i2s_set_clk`
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
/* I2S Example
|
||||
|
||||
This example code will output 100Hz sine wave and triangle wave to 2-channel of I2S driver
|
||||
Every 5 seconds, it will change bits_per_sample [16, 24, 32] for i2s data
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
@@ -12,6 +13,7 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/i2s.h"
|
||||
#include "esp_system.h"
|
||||
#include <math.h>
|
||||
|
||||
|
||||
@@ -22,17 +24,65 @@
|
||||
|
||||
#define SAMPLE_PER_CYCLE (SAMPLE_RATE/WAVE_FREQ_HZ)
|
||||
|
||||
void app_main()
|
||||
static void setup_triangle_sine_waves(int bits)
|
||||
{
|
||||
int *samples_data = malloc(((bits+8)/16)*SAMPLE_PER_CYCLE*4);
|
||||
unsigned int i, sample_val;
|
||||
float sin_float, triangle_float, triangle_step = 65536.0 / SAMPLE_PER_CYCLE;
|
||||
//for 36Khz sample rates, we create 100Hz sine wave, every cycle need 36000/100 = 360 samples (4-bytes each sample)
|
||||
double sin_float, triangle_float, triangle_step = (double) pow(2, bits) / SAMPLE_PER_CYCLE;
|
||||
|
||||
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);
|
||||
|
||||
for(i = 0; i < SAMPLE_PER_CYCLE; i++) {
|
||||
sin_float = sin(i * PI / 180.0);
|
||||
if(sin_float >= 0)
|
||||
triangle_float += triangle_step;
|
||||
else
|
||||
triangle_float -= triangle_step;
|
||||
|
||||
sin_float *= (pow(2, bits)/2 - 1);
|
||||
|
||||
if (bits == 16) {
|
||||
sample_val = 0;
|
||||
sample_val += (short)triangle_float;
|
||||
sample_val = sample_val << 16;
|
||||
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;
|
||||
} else {
|
||||
samples_data[i*2] = ((int) triangle_float);
|
||||
samples_data[i*2 + 1] = ((int) sin_float);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
i2s_write_bytes(I2S_NUM, (const char *)samples_data, ((bits+8)/16)*SAMPLE_PER_CYCLE*4, 100);
|
||||
|
||||
free(samples_data);
|
||||
}
|
||||
void app_main()
|
||||
{
|
||||
//for 36Khz sample rates, we create 100Hz sine wave, every cycle need 36000/100 = 360 samples (4-bytes or 8-bytes each sample)
|
||||
//depend on bits_per_sample
|
||||
//using 6 buffers, we need 60-samples per buffer
|
||||
//2-channels, 16-bit each channel, total buffer is 360*4 = 1440 bytes
|
||||
//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_config_t i2s_config = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.bits_per_sample = 16, //16-bit per channel
|
||||
.bits_per_sample = 16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||
.communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
|
||||
.dma_buf_count = 6,
|
||||
@@ -45,25 +95,17 @@ void app_main()
|
||||
.data_out_num = 22,
|
||||
.data_in_num = -1 //Not used
|
||||
};
|
||||
|
||||
i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
|
||||
i2s_set_pin(I2S_NUM, &pin_config);
|
||||
|
||||
triangle_float = -32767;
|
||||
|
||||
for(i = 0; i < SAMPLE_PER_CYCLE; i++) {
|
||||
sin_float = sin(i * PI / 180.0);
|
||||
if(sin_float >= 0)
|
||||
triangle_float += triangle_step;
|
||||
else
|
||||
triangle_float -= triangle_step;
|
||||
sin_float *= 32767;
|
||||
|
||||
sample_val = 0;
|
||||
sample_val += (short)triangle_float;
|
||||
sample_val = sample_val << 16;
|
||||
sample_val += (short) sin_float;
|
||||
|
||||
i2s_push_sample(I2S_NUM, (char *)&sample_val, portMAX_DELAY);
|
||||
}
|
||||
int test_bits = 16;
|
||||
while (1) {
|
||||
setup_triangle_sine_waves(test_bits);
|
||||
vTaskDelay(5000/portTICK_RATE_MS);
|
||||
test_bits += 8;
|
||||
if(test_bits > 32)
|
||||
test_bits = 16;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user