New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RESOLVED] I2S-DMA buffer issue (a test app specific) (IDFGH-3814) #300
Comments
And this is my draft code for now (the only changes I did are in the App): #include "freertos/FreeRTOS.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include "driver/i2c.h"
#include "driver/i2s.h"
#include <math.h>
#define I2C_MASTER_SCL_IO 19 /*!< gpio number for I2C master clock */
#define I2C_MASTER_SDA_IO 18 /*!< gpio number for I2C master data */
#define I2C_MASTER_NUM I2C_NUM_1 /*!< I2C port number for master dev */
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
#define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */
#define WM8731_I2C_ADDR 0x1A /*!< slave address for WM8731 sensor */
#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
#define ACK_VAL 0x0 /*!< I2C ack value */
#define NACK_VAL 0x1 /*!< I2C nack value */
#define WM8731_LINVOL 0x00
#define WM8731_RINVOL 0x01
#define WM8731_LOUT1V 0x02
#define WM8731_ROUT1V 0x03
#define WM8731_APANA 0x04
#define WM8731_APDIGI 0x05
#define WM8731_PWR 0x06
#define WM8731_IFACE 0x07
#define WM8731_SRATE 0x08
#define WM8731_ACTIVE 0x09
#define WM8731_RESET 0x0f
#define WM8731_SAMPLING_FREQ_8K 8000u
#define WM8731_SAMPLING_FREQ_32K 32000u
#define WM8731_SAMPLING_FREQ_44K1 44100u
#define WM8731_SAMPLING_FREQ_48K 48000u
#define WM8731_SAMPLING_FREQ_88K2 88200u
#define WM8731_SAMPLING_FREQ_96K 96000u
#define WM8731_MCLK 12000000u
//#define CODEC_IS_MASTER
#define SAMPLE_RATE (36000)
#define I2S_NUM (0)
#define WAVE_FREQ_HZ (100)
#define PI 3.14159265
#define SAMPLE_PER_CYCLE (SAMPLE_RATE/WAVE_FREQ_HZ)
typedef struct wm8731_cmd_entry_s {
unsigned int reg_addr;
unsigned int reg_val;
} wm8731_cmd_entry_t;
typedef struct _sampling_ctrl {
long mclk;
long rate;
unsigned int fs;
unsigned char sr:4;
unsigned char bosr:1;
unsigned char usb:1;
} wm8731_sampling_ctrl_t;
wm8731_sampling_ctrl_t sampling_ctrl_tbl[] = {
/* 48k */
{12288000, 48000, 256, 0x0, 0x0, 0x0},
{18432000, 48000, 384, 0x0, 0x1, 0x0},
{12000000, 48000, 250, 0x0, 0x0, 0x1},
{6144000, 48000, 256, 0x7, 0x0, 0x0},
/* 32k */
{12288000, 32000, 384, 0x6, 0x0, 0x0},
{18432000, 32000, 576, 0x6, 0x1, 0x0},
{12000000, 32000, 375, 0x6, 0x0, 0x1},
/* 8k */
{12288000, 8000, 1536, 0x3, 0x0, 0x0},
{18432000, 8000, 2304, 0x3, 0x1, 0x0},
{11289600, 8000, 1408, 0xb, 0x0, 0x0},
{16934400, 8000, 2112, 0xb, 0x1, 0x0},
{12000000, 8000, 1500, 0x3, 0x0, 0x1},
/* 96k */
{12288000, 96000, 128, 0x7, 0x0, 0x0},
{18432000, 96000, 192, 0x7, 0x1, 0x0},
{12000000, 96000, 125, 0x7, 0x0, 0x1},
/* 44.1k */
{11289600, 44100, 256, 0x8, 0x0, 0x0},
{16934400, 44100, 384, 0x8, 0x1, 0x0},
{12000000, 44100, 272, 0x8, 0x1, 0x1},
/* 88.2k */
{11289600, 88200, 128, 0xf, 0x0, 0x0},
{16934400, 88200, 192, 0xf, 0x1, 0x0},
{12000000, 88200, 136, 0xf, 0x1, 0x1},
};
wm8731_cmd_entry_t wm8731_cmd_entries[] = {
{ WM8731_PWR, 0x80 },
{ WM8731_RESET, 0x00 },
{ WM8731_ACTIVE, 0x00 },
{ WM8731_APANA, 0x12 },
{ WM8731_APDIGI, 0x00 },
{ WM8731_PWR, 0x00 },
{ WM8731_IFACE, 0x02 },
{ WM8731_LINVOL, 0x17 },
{ WM8731_RINVOL, 0x17 },
{ WM8731_LOUT1V, 0x7F },
{ WM8731_ROUT1V, 0x7F },
{ WM8731_ACTIVE, 0x01 },
};
void i2c_master_init()
{
int i2c_master_port = I2C_MASTER_NUM;
i2c_config_t conf;
conf.mode = I2C_MODE_MASTER;
conf.sda_io_num = I2C_MASTER_SDA_IO;
conf.sda_pullup_en = GPIO_PULLUP_DISABLE;
conf.scl_io_num = I2C_MASTER_SCL_IO;
conf.scl_pullup_en = GPIO_PULLUP_DISABLE;
conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
i2c_param_config(i2c_master_port, &conf);
i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}
esp_err_t wm8731_config(i2c_port_t i2c_num, wm8731_cmd_entry_t* cmd_entries, unsigned int entries_count, unsigned int relaxation_time)
{
i2c_cmd_handle_t cmd;
int ret;
for (unsigned int i = 0; i < entries_count; i++)
{
unsigned char byte1 = (cmd_entries[i].reg_addr << 1) | (cmd_entries[i].reg_val >> 8);
unsigned char byte2 = cmd_entries[i].reg_val & 0xff;
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, WM8731_I2C_ADDR << 1 | WRITE_BIT, ACK_CHECK_EN);
i2c_master_write_byte(cmd, byte1, ACK_CHECK_EN);
i2c_master_write_byte(cmd, byte2, ACK_CHECK_EN);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if (ret == ESP_FAIL) {
return ESP_FAIL;
}
vTaskDelay(relaxation_time / portTICK_RATE_MS);
}
return ESP_OK;
}
void app_main(void)
{
int ret;
nvs_flash_init();
//vTaskDelay(500 / portTICK_RATE_MS);
i2c_master_init();
//vTaskDelay(500 / portTICK_RATE_MS);
ret = wm8731_config(I2C_MASTER_NUM, wm8731_cmd_entries, sizeof(wm8731_cmd_entries) / sizeof(wm8731_cmd_entry_t), 1);
printf("*******************\n");
printf("WM8731 initialization\n");
printf("*******************\n");
if (ret == ESP_OK) {
printf("Codec initialization success!\n");
} else {
printf("No ack, codec not connected...skip...\n");
}
vTaskDelay(500 / portTICK_RATE_MS);
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)
//using 6 buffers, we need 60-samples per buffer
//2-channels, 16-bit each channel, total buffer is 360*4 = 1440 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
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
.communication_format = I2S_COMM_FORMAT_I2S,
.dma_buf_count = 6,
.dma_buf_len = 60, //
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 //Interrupt level 1
};
i2s_pin_config_t pin_config = {
.bck_io_num = 23,
.ws_io_num = 21,
.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;
//printf("0x%x\n", sample_val);
i2s_push_sample(I2S_NUM, (char *)&sample_val, portMAX_DELAY);
}
} |
@tuanpmt , can you comment on this? Do you have any observations like that? |
@valiolv |
Great! Happy new year and thanks in advance! |
@valioiv Because i2s tx faster than sinwave calculation. Please re-calculate to a buffer first, then using i2s_write_bytes, or loop and push |
Oh sure, I see... I'll test tomorrow and will close the "issue". Thanks for the support! |
Hi :) I've just modified the part of generation and sending via I2S as you suggested like this: ...
unsigned int sample_val_arr[SAMPLE_PER_CYCLE] = { 0 };
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_arr[i] = 0;
sample_val_arr[i] += (short)triangle_float;
sample_val_arr[i] = sample_val_arr[i] << 16;
sample_val_arr[i] += (short) sin_float;
//printf("0x%x\n", sample_val);
// i2s_push_sample(I2S_NUM, (char *)&sample_val, portMAX_DELAY);
}
i2s_write_bytes(I2S_NUM, sample_val_arr, sizeof(sample_val_arr), portMAX_DELAY);
... Here are the diagrams: It works fine, man! Thanks a lot! |
Dear valioiv, I am trying also to connect my esp32 to wm8731 audio codec board with no success. Could you please clarify how did you connect your esp32 pins to the codec? Are the three i2s pins enough or do I have to set up the mclk also? Thanks in advance! |
I'm trying to use the I2S test application as a foundation for some audio project:
https://github.com/espressif/esp-idf/blob/master/examples/peripherals/i2s/main/app_main.c
I did NO modifications on the drivers, I've just connected a WM8731 audio codec chip and it started working properly. I hear the sound, but I noticed it's a bit buzzy. I expected clear triangular and sinusoidal 100Hz waves but they are not. I observe the following waveforms for the left and right channel respectively:
It is obvious there are buffers which are not filled with the real data but just zeros.
I really suspect this is some DMA buffer management issue. Most probably the buffer indexes are not updated and/or used properly. I tried to dig in the I2S-DMA affairs but I don't feel myself confident with it. Can somebody share their opinion at least?
The text was updated successfully, but these errors were encountered: