I'm using ESP-IDF v4.2-dev-1415-ga2263571b and started with the i2s_adc_dac example.
Generating the 100hz was straight forward however I can't continuously read from i2s channel.
The first time the program executes i2s_read, I see the correct adc data in i2s_read_buff however the data does not change the next time the program runs i2s_read. So the output looks like:
Code: Select all
======
ff 3f ff 3f ff 3f ff 3f
ff 3f ff 3f ff 3f ff 3f
ff 3f ff 3f ff 3f ff 3f
ff 3f ff 3f ff 3f ff 3f
======
======
ff 3f ff 3f ff 3f ff 3f
ff 3f ff 3f ff 3f ff 3f
ff 3f ff 3f ff 3f ff 3f
ff 3f ff 3f ff 3f ff 3f
======
======
ff 3f ff 3f ff 3f ff 3f
ff 3f ff 3f ff 3f ff 3f
ff 3f ff 3f ff 3f ff 3f
ff 3f ff 3f ff 3f ff 3f
======
This is how I'm reading:
Code: Select all
void i2s_read_task(void*arg)
{
int i2s_read_len = EXAMPLE_I2S_READ_LEN;
size_t bytes_read;
char* i2s_read_buff = (char*) calloc(i2s_read_len, sizeof(char));
i2s_adc_enable(EXAMPLE_I2S_NUM);
while (1) {
i2s_read(EXAMPLE_I2S_NUM, (char*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
vTaskDelay(100 / portTICK_PERIOD_MS);
example_disp_buf((uint8_t*) i2s_read_buff, 32);
}
}
Here is the program file. I tried several different things but here you can see I'm using seperate tasks for i2s_write and i2s_read
Code: Select all
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_spi_flash.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_partition.h"
#include "driver/i2s.h"
#include "driver/adc.h"
#include "audio_example_file.h"
#include "esp_adc_cal.h"
#define V_REF 1100
#define EXAMPLE_I2S_NUM (0)
#define EXAMPLE_I2S_SAMPLE_RATE (6000)
#define EXAMPLE_I2S_SAMPLE_BITS (16)
#define EXAMPLE_I2S_READ_LEN (16 * 1024)
#define EXAMPLE_I2S_FORMAT (I2S_CHANNEL_FMT_RIGHT_LEFT)
#define EXAMPLE_I2S_CHANNEL_NUM ((EXAMPLE_I2S_FORMAT < I2S_CHANNEL_FMT_ONLY_RIGHT) ? (2) : (1))
#define I2S_ADC_UNIT ADC_UNIT_1
#define I2S_ADC_CHANNEL ADC1_CHANNEL_3
void example_i2s_init(void)
{
int i2s_num = EXAMPLE_I2S_NUM;
i2s_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN,
.sample_rate = EXAMPLE_I2S_SAMPLE_RATE,
.bits_per_sample = EXAMPLE_I2S_SAMPLE_BITS,
.communication_format = I2S_COMM_FORMAT_PCM,
.channel_format = EXAMPLE_I2S_FORMAT,
.intr_alloc_flags = 0,
.dma_buf_count = 2,
.dma_buf_len = 1024,
.use_apll = 1,
};
//install and start i2s driver
i2s_driver_install(i2s_num, &i2s_config, 0, NULL);
//init DAC pad
i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
//init ADC pad
i2s_set_adc_mode(I2S_ADC_UNIT, I2S_ADC_CHANNEL);
i2s_set_clk(EXAMPLE_I2S_NUM, 6000, EXAMPLE_I2S_SAMPLE_BITS, 1);;
}
void total_buf(uint8_t* buf, int length)
{
uint32_t total = 0;
for (int i = 0; i < length; i++) {
total += buf[i];
}
printf("Total: %u\n", total);
}
void example_disp_buf(uint8_t* buf, int length)
{
printf("======\n");
for (int i = 0; i < length; i++) {
printf("%02x ", buf[i]);
if ((i + 1) % 8 == 0) {
printf("\n");
}
}
printf("======\n");
}
/**
* @brief Scale data to 16bit/32bit for I2S DMA output.
* DAC can only output 8bit data value.
* I2S DMA will still send 16 bit or 32bit data, the highest 8bit contains DAC data.
*/
int example_i2s_dac_data_scale(uint8_t* d_buff, uint8_t* s_buff, uint32_t len)
{
uint32_t j = 0;
#if (EXAMPLE_I2S_SAMPLE_BITS == 16)
for (int i = 0; i < len; i++) {
d_buff[j++] = 0;
d_buff[j++] = s_buff[i];
}
return (len * 2);
#else
for (int i = 0; i < len; i++) {
d_buff[j++] = 0;
d_buff[j++] = 0;
d_buff[j++] = 0;
d_buff[j++] = s_buff[i];
}
return (len * 4);
#endif
}
void i2s_read_task(void*arg)
{
int i2s_read_len = EXAMPLE_I2S_READ_LEN;
size_t bytes_read;
char* i2s_read_buff = (char*) calloc(i2s_read_len, sizeof(char));
i2s_adc_enable(EXAMPLE_I2S_NUM);
while (1) {
i2s_read(EXAMPLE_I2S_NUM, (char*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
vTaskDelay(100 / portTICK_PERIOD_MS);
example_disp_buf((uint8_t*) i2s_read_buff, 32);
}
}
void i2s_write_task(void*arg)
{
size_t bytes_written;
int i2s_read_len = EXAMPLE_I2S_READ_LEN;
uint8_t* i2s_write_buff = (uint8_t*) calloc(i2s_read_len, sizeof(char));
int tot_size = sizeof(audio_table);
while (1) {
int offset = 0;
while (offset < tot_size) {
int play_len = ((tot_size - offset) > (4 * 1024)) ? (4 * 1024) : (tot_size - offset);
int i2s_wr_len = example_i2s_dac_data_scale(i2s_write_buff, (uint8_t*)(audio_table + offset), play_len);
i2s_write(EXAMPLE_I2S_NUM, i2s_write_buff, i2s_wr_len, &bytes_written, portMAX_DELAY);
offset += play_len;
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
esp_err_t i2s_main(void)
{
example_i2s_init();
xTaskCreate(i2s_read_task, "i2s_read_task", 1024 * 2, NULL, 5, NULL);
xTaskCreate(i2s_write_task, "i2s_write_task", 1024 * 2, NULL, 5, NULL);
return ESP_OK;
}