I'm modify code from i2s_std.
Code: Select all
/*
* SPDX-FileCopyrightText: 2021-2022 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"
/* Set 1 to allocate rx & tx channels in duplex mode on a same I2S controller, they will share the BCLK and WS signal
* Set 0 to allocate rx & tx channels in simplex mode, these two channels will be totally separated,
* Specifically, due to the hardware limitation, the simplex rx & tx channels can't be registered on the same controllers on ESP32 and ESP32-S2,
* and ESP32-S2 has only one I2S controller, so it can't allocate two simplex channels */
#define EXAMPLE_I2S_DUPLEX_MODE CONFIG_USE_DUPLEX
#define EXAMPLE_STD_BCLK_IO1 GPIO_NUM_2 // I2S bit clock io number
#define EXAMPLE_STD_WS_IO1 GPIO_NUM_3 // I2S word select io number
#define EXAMPLE_STD_DOUT_IO1 GPIO_NUM_4 // I2S data out io number
#define EXAMPLE_STD_DIN_IO1 GPIO_NUM_5 // I2S data in io number
#if !EXAMPLE_I2S_DUPLEX_MODE
#define EXAMPLE_STD_BCLK_IO2 GPIO_NUM_6 // I2S bit clock io number
#define EXAMPLE_STD_WS_IO2 GPIO_NUM_7 // I2S word select io number
#define EXAMPLE_STD_DOUT_IO2 GPIO_NUM_8 // I2S data out io number
#define EXAMPLE_STD_DIN_IO2 GPIO_NUM_9 // I2S data in io number
#endif
#define EXAMPLE_BUFF_SIZE 32
// i2s number
#define EXAMPLE_I2S_NUM (0)
// i2s sample rate
#define EXAMPLE_I2S_SAMPLE_RATE (32000)
// i2s data bits
#define EXAMPLE_I2S_SAMPLE_BITS (16)
// enable display buffer for debug
#define EXAMPLE_I2S_BUF_DEBUG (0)
// I2S read buffer length
#define EXAMPLE_I2S_READ_LEN (16 * 32)
static i2s_chan_handle_t tx_chan; // I2S tx channel handler
int wav_buffer[64] ;
const int audio_table[] = {
32500,33301,34101,34900,35698,36494,37287,38078,38865,39648,40427,41201,41970,42733,43490,44240,
44983,45719,46446,47165,47876,48576,49267,49948,50618,51278,51925,52562,53185,53797,54395,54980,
55552,56109,56652,57181,57694,58192,58675,59142,59592,60026,60443,60844,61227,61593,61941,62271,
62583,62877,63153,63409,63647,63867,64067,64248,64409,64552,64674,64778,64861,64925,64970,64994,
64999,64985,64950,64896,64822,64728,64615,64483,64331,64160,63969,63759,63531,63283,63017,62732,
62429,62108,61769,61412,61038,60646,60237,59811,59369,58910,58436,57945,57439,56918,56382,55832,
55268,54689,54098,53493,52875,52245,51603,50949,50285,49609,48923,48227,47522,46807,46084,45352,
44613,43866,43113,42352,41586,40815,40038,39257,38472,37683,36891,36096,35299,34501,33701,32900,
32100,31299,30499,29701,28904,28109,27317,26528,25743,24962,24185,23414,22648,21887,21134,20387,
19648,18916,18193,17478,16773,16077,15391,14715,14051,13397,12755,12125,11507,10902,10311,9732,
9168,8618,8082,7561,7055,6564,6090,5631,5189,4763,4354,3962,3588,3231,2892,2571,
2268,1983,1717,1469,1241,1031,840,669,517,385,272,178,104,50,15,1,
6,30,75,139,222,326,448,591,752,933,1133,1353,1591,1847,2123,2417,
2729,3059,3407,3773,4156,4557,4974,5408,5858,6325,6808,7306,7819,8348,8891,9448,
10020,10605,11203,11815,12438,13075,13722,14382,15052,15733,16424,17124,17835,18554,19281,20017,
20760,21510,22267,23030,23799,24573,25352,26135,26922,27713,28506,29302,30100,30899,31699,32500
};
/**
* @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( int *d_buff, int *s_buff, uint32_t len)
{
uint32_t j = 0;
for (int i = 0; i < len; i++)
{
d_buff[j++] = ((s_buff[i])-32500);
d_buff[j++] = ((s_buff[i])-32500);
}
return (len );
}
static void i2s_example_write_task(void *args)
{
size_t bytes_written;
int tot_size = sizeof(audio_table);
int* i2s_write_buff = (int*)calloc(2048, sizeof( int ));
int i2s_wr_len = example_i2s_dac_data_scale(i2s_write_buff, ( int *)(audio_table ), tot_size);
while (1)
{
i2s_channel_write(tx_chan, i2s_write_buff, 2048, &bytes_written, 1000);
}
// vTaskDelay(1 / portTICK_PERIOD_MS);
free(i2s_write_buff);
vTaskDelete(NULL);
}
static void i2s_example_init_std_simplex(void)
{
/* Setp 1: Determine the I2S channel configuration and allocate two channels one by one
* The default configuration can be generated by the helper macro,
* it only requires the I2S controller id and I2S role
* The tx and rx channels here are registered on different I2S controller,
* only ESP32-C3, ESP32-S3 and ESP32-H2 allow to register two separate tx & rx channels on a same controller */
i2s_chan_config_t tx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
ESP_ERROR_CHECK(i2s_new_channel(&tx_chan_cfg, &tx_chan, NULL));
// i2s_chan_config_t rx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
// ESP_ERROR_CHECK(i2s_new_channel(&rx_chan_cfg, NULL, &rx_chan));
/* Step 2: Setting the configurations of standard mode and initialize each channels one by one
* 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 tx_std_cfg = {
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(EXAMPLE_I2S_SAMPLE_RATE),
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
.gpio_cfg = {
.mclk = I2S_GPIO_UNUSED, // some codecs may require mclk signal, this example doesn't need it
.bclk = EXAMPLE_STD_BCLK_IO1,
.ws = EXAMPLE_STD_WS_IO1,
.dout = EXAMPLE_STD_DOUT_IO1,
.din = EXAMPLE_STD_DIN_IO1,
.invert_flags = {
.mclk_inv = false,
.bclk_inv = false,
.ws_inv = false,
},
},
};
ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &tx_std_cfg));
}
void app_main(void)
{
i2s_example_init_std_simplex();
/* Step 3: Enable the tx channels before writing */
ESP_ERROR_CHECK(i2s_channel_enable(tx_chan));
/* Step 4: Create writing task */
// printf("tot_size: i2s write %d \n", tot_size);
xTaskCreate(i2s_example_write_task, "i2s_example_write_task", 4096, NULL, 5, NULL);
}