ESP32s3 with ES8388 and PCM5102

natee.th
Posts: 26
Joined: Fri Feb 10, 2023 5:25 pm

ESP32s3 with ES8388 and PCM5102

Postby natee.th » Mon Sep 11, 2023 3:05 am

I'm beginning to not be sure. Is my board broken? I can control i2c on the es8388 board and can control the volume, but the sound comes out abnormally. I tried using only the DATAOUT BCK LCK signal to use with the PCM5102 and found that the sound worked normally. Completely confused or do I need to manage other parameters?


Yellow is ES8388.
Blue is PCM5102.
Image
For me it was the first time. It's still difficult for me.



ES8388 Board https://pcbartists.com/product/es8388-module/
ES8388 Datasheet https://datasheet.lcsc.com/lcsc/1912111 ... 365736.pdf


PCM5102 https://www.ti.com/lit/ds/symlink/pcm51 ... 52FPCM5102

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/i2c.h"
#include "driver/gpio.h"
#include "esp_check.h"
#include "sdkconfig.h"
#include "codec_es8388.h"
#include "math.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 */

#include "codec_es8388.h"
#include "math.h"

#define I2C_MASTER_NUM 0
#define ACK_CHECK_EN 0x1
#define ACK_CHECK_DIS 0x0
#define ACK_VAL I2C_MASTER_ACK
#define NACK_VAL I2C_MASTER_NACK

#define ES8388_ADDR 0b0010000

#define VOL_DEFAULT 70

#define SAMPLE_RATE (44100)
#define I2S_NUM (0)
#define WAVE_FREQ_HZ (700)
#define PI (3.14159265)

#define I2C_MASTER_SCL_IO GPIO_NUM_16
#define I2C_MASTER_SDA_IO GPIO_NUM_17

#define I2S_BCK_IO (GPIO_NUM_4)
#define I2S_WS_IO (GPIO_NUM_5)
#define I2S_DO_IO (GPIO_NUM_18)
#define I2S_DI_IO (GPIO_NUM_19)
#define IS2_MCLK_PIN (GPIO_NUM_0)

#define EXAMPLE_STD_BCLK_IO1 GPIO_NUM_4  // I2S bit clock io number
#define EXAMPLE_STD_WS_IO1 GPIO_NUM_5    // I2S word select io number
#define EXAMPLE_STD_DOUT_IO1 GPIO_NUM_18 // I2S data out io number

#define SAMPLE_PER_CYCLE (SAMPLE_RATE / WAVE_FREQ_HZ)

#define SAMPLES SAMPLE_PER_CYCLE // Total number of samples left and right
#define BUF_SAMPLES SAMPLES * 4  // Size of DMA tx/rx buffer samples * left/right * 2 for 32 bit samples

// DMA Buffers
int16_t rxBuf[BUF_SAMPLES];
int16_t txBuf[BUF_SAMPLES];

static const char *ES_TAG = "ES8388_DRIVER";

#define EXAMPLE_BUFF_SIZE 16

// i2s sample rate
// #define EXAMPLE_I2S_SAMPLE_RATE (32000)

static i2s_chan_handle_t tx_chan; // I2S tx channel handler
static i2s_chan_handle_t rx_chan; // I2S tx channel handler

static i2s_chan_handle_t tx_handle;
static i2s_chan_handle_t rx_handle;

short mainaudio;

const short audio_table[] = {0, 391, 782, 1166, 1557, 1948, 2332, 2723, 3107, 3486, 3870, 4249, 4621, 4993, 5365, 5731, 6090, 6450, 6810, 7157, 7504, 7845, 8187, 8515, 8844, 9166, 9483, 9793, 10097, 10394, 10692, 10977, 11256, 11529, 11790, 12050, 12298, 12546, 12782, 13005, 13228, 13439, 13644, 13842, 14028, 14208, 14376, 14537, 14692, 14835, 14971, 15095, 15213, 15318, 15418, 15504, 15585, 15653, 15715, 15765, 15802, 15839, 15858, 15870, 15870, 15864, 15852, 15821, 15790, 15740, 15684, 15622, 15548, 15467, 15374, 15269, 15157, 15039, 14909, 14773, 14624, 14469, 14301, 14128, 13942, 13756, 13551, 13346, 13129, 12906, 12676, 12435, 12187, 11932, 11672, 11405, 11132, 10847, 10556, 10264, 9960, 9656, 9340, 9024, 8695, 8366, 8031, 7697, 7349, 7002, 6649, 6289, 5929, 5563, 5197, 4825, 4453, 4075, 3697, 3318, 2934, 2549, 2159, 1774, 1383, 993, 602, 211, -179, -570, -961, -1351, -1742, -2127, -2517, -2902, -3286, -3665, -4043, -4421, -4793, -5165, -5538, -5897, -6263, -6617, -6970, -7324, -7665, -8006, -8341, -8669, -8998, -9314, -9631, -9941, -10238, -10536, -10827, -11107, -11386, -11652, -11913, -12167, -12415, -12657, -12886, -13116, -13333, -13538, -13736, -13928, -14114, -14288, -14455, -14610, -14759, -14902, -15032, -15150, -15268, -15367, -15460, -15547, -15621, -15689, -15745, -15789, -15826, -15851, -15869, -15875, -15875, -15863, -15844, -15813, -15776, -15727, -15665, -15596, -15516, -15429, -15330, -15224, -15113, -14989, -14852, -14710, -14561, -14400, -14226, -14052, -13866, -13668, -13463, -13252, -13035, -12806, -12570, -12328, -12080, -11826, -11559, -11286, -11007, -10722, -10431, -10133, -9829, -9519, -9203, -8880, -8558, -8223, -7888, -7547, -7200, -6846, -6493, -6133, -5773, -5407, -5035, -4663, -4291, -3913, -3528, -3150, -2765, -2381, -1990, -1600, -1215, -824, -434, -43};

uint8_t i2c_write_bulk(uint8_t i2c_bus_addr, uint8_t reg, uint8_t bytes, uint8_t *data)
{
    /*
    printf( "Writing [%02x]=", reg );
    for ( int i = 0 ; i < bytes ; i++ )
        printf( "%02x:", data[i] );
    printf( "\n");
*/

    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, i2c_bus_addr << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write(cmd, &reg, 1, ACK_CHECK_EN);
    i2c_master_write(cmd, data, bytes, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    int ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK)
    {
        return ret;
    }

    return 0;
}

uint8_t i2c_write(uint8_t i2c_bus_addr, uint8_t reg, uint8_t value)
{
    return i2c_write_bulk(i2c_bus_addr, reg, 1, &value);
}

uint8_t i2c_read(uint8_t i2c_bus_addr, uint8_t reg)
{
    uint8_t buffer[2];
    // printf( "Addr: [%d] Reading register: [%d]\n", i2c_bus_addr, reg );

    buffer[0] = reg;

    int ret;
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();

    // Write the register address to be read
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, i2c_bus_addr << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, buffer[0], ACK_CHECK_EN);

    // Read the data for the register from the slave
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, i2c_bus_addr << 1 | I2C_MASTER_READ, ACK_CHECK_EN);
    i2c_master_read_byte(cmd, &buffer[0], NACK_VAL);
    i2c_master_stop(cmd);

    ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);

    // printf( "Read: [%02x]=[%02x]\n", reg, buffer[0] );

    return (buffer[0]);
}

static esp_err_t i2c_master_init(void)
{
    int i2c_master_port = I2C_MASTER_NUM;
    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = 100000,
        // .clk_flags = 0,
    };

    // i2c_config_t conf = {
    //     .mode = I2C_MODE_MASTER,
    //     .sda_io_num = I2C_MASTER_SDA_IO,
    //     .scl_io_num = I2C_MASTER_SCL_IO,
    //     .sda_pullup_en = GPIO_PULLUP_ENABLE,
    //     .scl_pullup_en = GPIO_PULLUP_ENABLE,
    //     .master.clk_speed = I2C_MASTER_FREQ_HZ,
    // };

    i2c_param_config(i2c_master_port, &conf);

    return i2c_driver_install(i2c_master_port, conf.mode, 0, 0, 0);
}

static esp_err_t es_write_reg(uint8_t slave_addr, uint8_t reg_add, uint8_t data)
{
    return i2c_write(ES8388_ADDR, reg_add, data);
}

static esp_err_t es_read_reg(uint8_t reg_add, uint8_t *p_data)
{
    *p_data = i2c_read(ES8388_ADDR, reg_add);
    // ESP_LOGE(ES_TAG, "i2c_read : %02x", *p_data);
    return ESP_OK;
}

void es8388_read_all()
{
    printf("\n\n===================\n\n");
    for (int i = 0; i < 50; i++)
    {
        uint8_t reg = 0;
        es_read_reg(i, &reg);
        // ESP_LOGW(ES_TAG, es_read_reg(i, &reg));
        // printf(es_read_reg(i, &reg));
    }
    printf("\n\n===================\n\n");
}

static int es8388_set_adc_dac_volume(int mode, int volume, int dot)
{
    int res = 0;
    if (volume < -96 || volume > 0)
    {
        ESP_LOGW(ES_TAG, "Warning: volume < -96! or > 0!\n");
        if (volume < -96)
            volume = -96;
        else
            volume = 0;
    }
    dot = (dot >= 5 ? 1 : 0);
    volume = (-volume << 1) + dot;
    if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC)
    {
        res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL8, volume);
        res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL9, volume); // ADC Right Volume=0db
    }
    if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC)
    {
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL5, volume);
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL4, volume);
    }
    return res;
}

esp_err_t es8388_init(es_dac_output_t output, es_adc_input_t input)
{
    int res = 0;

    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL3, 0x00); // 0x04 mute/0x00 unmute&ramp;DAC unmute and  disabled digital volume control soft ramp

    res |= es_write_reg(ES8388_ADDR, ES8388_CONTROL2, 0x50);
    res |= es_write_reg(ES8388_ADDR, ES8388_CHIPPOWER, 0x00);           // normal all and power up all
    res |= es_write_reg(ES8388_ADDR, ES8388_MASTERMODE, ES_MODE_SLAVE); // CODEC IN I2S SLAVE MODE

    res |= es_write_reg(ES8388_ADDR, ES8388_DACPOWER, 0xC0);     // disable DAC and disable Lout/Rout/1/2
    res |= es_write_reg(ES8388_ADDR, ES8388_CONTROL1, 0x12);     // Enfr=0,Play&Record Mode,(0x17-both of mic&paly)
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL1, 0x18);  // 1a 0x18:16bit iis , 0x00:24
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL2, 0x02);  // DACFsMode,SINGLE SPEED; DACFsRatio,256
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL16, 0x00); // 0x00 audio on LIN1&RIN1,  0x09 LIN2&RIN2
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL17, 0x90); // only left DAC to left mixer enable 0db
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL20, 0x90); // only right DAC to right mixer enable 0db
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21, 0x80); // set internal ADC and DAC use the same LRCK clock, ADC LRCK as internal LRCK
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL23, 0x00); // vroi=0
    res |= es8388_set_adc_dac_volume(ES_MODULE_DAC, 0, 0);       // 0db

    ESP_LOGE(ES_TAG, "Setting DAC Output: %02x", output);
    res |= es_write_reg(ES8388_ADDR, ES8388_DACPOWER, output);
    res |= es_write_reg(ES8388_ADDR, ES8388_ADCPOWER, 0xFF);
    res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL1, 0xbb); // MIC Left and Right channel PGA gain

    ESP_LOGE(ES_TAG, "Setting ADC Input: %02x", input);
    res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL2, input);

    res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL3, 0x02);
    res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL4, 0x0c); // Left/Right data, Left/Right justified mode, Bits length, I2S format
    res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL5, 0x02); // ADCFsMode,singel SPEED,RATIO=256
    // ALC for Microphone
    res |= es8388_set_adc_dac_volume(ES_MODULE_ADC, 0, 0);   // 0db
    res |= es_write_reg(ES8388_ADDR, ES8388_ADCPOWER, 0x09); // Power on ADC, Enable LIN&RIN, Power off MICBIAS, set int1lp to low power mode

    return res;
}

esp_err_t es8388_config_i2s(es_bits_length_t bits_length, es_module_t mode, es_format_t fmt)
{
    esp_err_t res = ESP_OK;
    uint8_t reg = 0;

    // Set the Format
    if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC)
    {
        printf("Setting I2S ADC Format\n");
        res = es_read_reg(ES8388_ADCCONTROL4, &reg);
        reg = reg & 0xfc;
        res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL4, reg | fmt);
    }
    if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC)
    {
        printf("Setting I2S DAC Format\n");
        res = es_read_reg(ES8388_DACCONTROL1, &reg);
        reg = reg & 0xf9;
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL1, reg | (fmt << 1));
        // res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL1, reg | (0b00000000));
    }

    // Set the Sample bits length
    int bits = (int)bits_length;
    if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC)
    {
        printf("Setting I2S ADC Bits: %d\n", bits);
        res = es_read_reg(ES8388_ADCCONTROL4, &reg);
        reg = reg & 0xe3;
        res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL4, reg | (bits << 2));
    }
    if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC)
    {
        ESP_LOGE(ES_TAG, "Setting I2S DAC Bits: %d\n", bits);
        res = es_read_reg(ES8388_DACCONTROL1, &reg);
        ESP_LOGE(ES_TAG, "Setting I2S DAC Bits: %d\n", res);
        reg = reg & 0xc7;
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL1, reg | (bits << 3));
    }
    return res;
}

esp_err_t es8388_set_voice_mute(bool enable)
{
    esp_err_t res = ESP_OK;
    uint8_t reg = 0;
    res = es_read_reg(ES8388_DACCONTROL3, &reg);
    reg = reg & 0xFB;
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL3, reg | (((int)enable) << 2));
    return res;
}

esp_err_t es8388_start(es_module_t mode)
{
    esp_err_t res = ESP_OK;
    uint8_t prev_data = 0, data = 0;
    es_read_reg(ES8388_DACCONTROL21, &prev_data);
    if (mode == ES_MODULE_LINE)
    {
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL16, 0x00); // 0x00 audio on LIN1&RIN1,  0x09 LIN2&RIN2 by pass enable
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL17, 0x50); // left DAC to left mixer enable  and  LIN signal to left mixer enable 0db  : bupass enable
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL20, 0x50); // right DAC to right mixer enable  and  LIN signal to right mixer enable 0db : bupass enable
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21, 0xC0); // enable adc
    }
    else
    {
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21, 0x80); // enable dac
    }
    es_read_reg(ES8388_DACCONTROL21, &data);
    if (prev_data != data)
    {
        printf("Resetting State Machine\n");

        res |= es_write_reg(ES8388_ADDR, ES8388_CHIPPOWER, 0xF0); // start state machine
        // res |= es_write_reg(ES8388_ADDR, ES8388_CONTROL1, 0x16);
        // res |= es_write_reg(ES8388_ADDR, ES8388_CONTROL2, 0x50);
        res |= es_write_reg(ES8388_ADDR, ES8388_CHIPPOWER, 0x00); // start state machine
    }
    if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC || mode == ES_MODULE_LINE)
    {
        printf("Powering up ADC\n");
        res |= es_write_reg(ES8388_ADDR, ES8388_ADCPOWER, 0x00); // power up adc and line in
    }
    if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC || mode == ES_MODULE_LINE)
    {
        printf("Powering up DAC\n");
        res |= es_write_reg(ES8388_ADDR, ES8388_DACPOWER, 0x3c); // power up dac and line out
        res |= es8388_set_voice_mute(false);
    }

    return res;
}

esp_err_t es8388_set_voice_volume(int volume)
{
    esp_err_t res = ESP_OK;
    if (volume < 0)
        volume = 0;
    else if (volume > 100)
        volume = 100;
    volume /= 3;
    res = es_write_reg(ES8388_ADDR, ES8388_DACCONTROL24, volume);
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL25, volume);
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL26, volume);
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL27, volume);
    return res;
}

void es8388_config()
{
    // Input/Output Modes
    //
    //	es_dac_output_t output = DAC_OUTPUT_LOUT1 | DAC_OUTPUT_LOUT2 | DAC_OUTPUT_ROUT1 | DAC_OUTPUT_ROUT2;
    //	es_adc_input_t input = ADC_INPUT_LINPUT1_RINPUT1;
    // 	es_adc_input_t input = ADC_INPUT_LINPUT2_RINPUT2;

    es_dac_output_t output = DAC_OUTPUT_LOUT1 | DAC_OUTPUT_LOUT2 | DAC_OUTPUT_ROUT1 | DAC_OUTPUT_ROUT2;
    // es_dac_output_t output = DAC_OUTPUT_LOUT1  | DAC_OUTPUT_ROUT1;
    // es_dac_output_t output = DAC_OUTPUT_LOUT2  | DAC_OUTPUT_ROUT2;

    // es_dac_output_t output = 0;
    es_adc_input_t input = ADC_INPUT_LINPUT1_RINPUT1;

    es8388_init(output, input);

    // Modes Available
    //
    //	es_mode_t  = ES_MODULE_ADC;
    //	es_mode_t  = ES_MODULE_LINE;
    //	es_mode_t  = ES_MODULE_DAC;
    //	es_mode_t  = ES_MODULE_ADC_DAC;

    es_bits_length_t bits_length = BIT_LENGTH_16BITS;
    es_module_t module = ES_MODULE_DAC;
    es_format_t fmt = I2S_LEFT;

    es8388_config_i2s(bits_length, ES_MODULE_ADC_DAC, fmt);
    es8388_set_voice_volume(100);
    es8388_start(module);
}

static void i2s_example_write_task(void *args)
{

    size_t bytes_written;
    float OSC1, OSC1_B = 0;

    uint16_t j = 0;
    short *i2s_write_buff = (short *)calloc(EXAMPLE_BUFF_SIZE * 2, sizeof(short));

    OSC1 = 1;


    while (1)
    {

        j = 0;
        for (int i = 0; i < EXAMPLE_BUFF_SIZE; i++)
        {
            OSC1_B += OSC1;
            if (OSC1_B > 255)
            {
                OSC1_B -= 255;
            }
        


            mainaudio = (audio_table[(int)OSC1_B]);

            i2s_write_buff[j++] = (short)mainaudio;
            i2s_write_buff[j++] = (short)mainaudio;

            // i2s_write_buff[j++] = 0xFF00;
            // i2s_write_buff[j++] = 0xFFAA;
        }

        i2s_channel_write(tx_handle, i2s_write_buff, EXAMPLE_BUFF_SIZE * 4, &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 = -1,
    //         .invert_flags = {
    //             .mclk_inv = false,
    //             .bclk_inv = false,
    //             .ws_inv = false,
    //         },
    //     },
    // };
    // ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &tx_std_cfg));

    i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM, I2S_ROLE_MASTER);
    chan_cfg.auto_clear = true; // Auto clear the legacy data in the DMA buffer
    ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle));
    i2s_std_config_t std_cfg = {
        .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE),
        .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
        .gpio_cfg = {
            .mclk = IS2_MCLK_PIN,
            .bclk = I2S_BCK_IO,
            .ws = I2S_WS_IO,
            .dout = I2S_DO_IO,
            .din = I2S_DI_IO,
            .invert_flags = {
                .mclk_inv = false,
                .bclk_inv = false,
                .ws_inv = false,
            },
        },
    };
    // std_cfg.clk_cfg.mclk_multiple = I2S_MCLK_MULTIPLE_256;

    ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle, &std_cfg));
    ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle, &std_cfg));
    ESP_ERROR_CHECK(i2s_channel_enable(tx_handle));
    ESP_ERROR_CHECK(i2s_channel_enable(rx_handle));
}

void app_main(void)
{

    i2c_master_init();
    es8388_config();

    // es8388_read_all();
    i2s_example_init_std_simplex();

    /* Step 3: Enable the tx channels before writing */
    // ESP_ERROR_CHECK(i2s_channel_enable(tx_handle));

    /* 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);


}

natee.th
Posts: 26
Joined: Fri Feb 10, 2023 5:25 pm

Re: ESP32s3 with ES8388 and PCM5102

Postby natee.th » Mon Sep 11, 2023 3:20 am

This code is same result.

Code: Select all

#include "freertos/FreeRTOS.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "driver/i2c.h"
#include "driver/gpio.h"
#include "driver/i2s.h"
#include "soc/gpio_sig_map.h"
#include "codec_es8388.h"
#include "math.h"

#define I2C_MASTER_NUM 0
#define ACK_CHECK_EN 0x1
#define ACK_CHECK_DIS 0x0
#define ACK_VAL I2C_MASTER_ACK
#define NACK_VAL I2C_MASTER_NACK

#define ES8388_ADDR 0b0010000

#define VOL_DEFAULT 70

#define SAMPLE_RATE (44100)
#define I2S_NUM (0)
#define WAVE_FREQ_HZ (700)
#define PI (3.14159265)

// #define I2S_BCK_IO (GPIO_NUM_27)
// #define I2S_WS_IO (GPIO_NUM_25)
// #define I2S_DO_IO (GPIO_NUM_26)
// #define I2S_DI_IO (GPIO_NUM_35)
// #define IS2_MCLK_PIN (GPIO_NUM_0)

// #define I2C_MASTER_SDA_IO 33
// #define I2C_MASTER_SCL_IO 32

#define I2C_MASTER_SCL_IO GPIO_NUM_16
#define I2C_MASTER_SDA_IO GPIO_NUM_17

#define I2S_BCK_IO (GPIO_NUM_4)
#define I2S_WS_IO (GPIO_NUM_5)
#define I2S_DO_IO (GPIO_NUM_18)
#define I2S_DI_IO (GPIO_NUM_19)
#define IS2_MCLK_PIN (GPIO_NUM_0)

/*
#define I2S_BCK_IO      (GPIO_NUM_5)
#define I2S_WS_IO       (GPIO_NUM_25)
#define I2S_DO_IO       (GPIO_NUM_26)
#define I2S_DI_IO       (GPIO_NUM_35)
#define I2C_MASTER_SDA_IO 18
#define I2C_MASTER_SCL_IO 23
#define IS2_MCLK_PIN	(GPIO_NUM_0)
*/

#define SAMPLE_PER_CYCLE (SAMPLE_RATE / WAVE_FREQ_HZ)

#define SAMPLES SAMPLE_PER_CYCLE // Total number of samples left and right
#define BUF_SAMPLES SAMPLES * 4  // Size of DMA tx/rx buffer samples * left/right * 2 for 32 bit samples

// DMA Buffers
int16_t rxBuf[BUF_SAMPLES];
int16_t txBuf[BUF_SAMPLES];

static const char *ES_TAG = "ES8388_DRIVER";

esp_err_t event_handler(void *ctx, i2s_event_t *event)
{
    return ESP_OK;
}

uint8_t i2c_write_bulk(uint8_t i2c_bus_addr, uint8_t reg, uint8_t bytes, uint8_t *data)
{
    /*
    printf( "Writing [%02x]=", reg );
    for ( int i = 0 ; i < bytes ; i++ )
        printf( "%02x:", data[i] );
    printf( "\n");
*/

    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, i2c_bus_addr << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write(cmd, &reg, 1, ACK_CHECK_EN);
    i2c_master_write(cmd, data, bytes, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    int ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK)
    {
        return ret;
    }

    return 0;
}

uint8_t i2c_write(uint8_t i2c_bus_addr, uint8_t reg, uint8_t value)
{
    return i2c_write_bulk(i2c_bus_addr, reg, 1, &value);
}

uint8_t i2c_read(uint8_t i2c_bus_addr, uint8_t reg)
{
    uint8_t buffer[2];
    // printf( "Addr: [%d] Reading register: [%d]\n", i2c_bus_addr, reg );

    buffer[0] = reg;

    int ret;
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();

    // Write the register address to be read
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, i2c_bus_addr << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, buffer[0], ACK_CHECK_EN);

    // Read the data for the register from the slave
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, i2c_bus_addr << 1 | I2C_MASTER_READ, ACK_CHECK_EN);
    i2c_master_read_byte(cmd, &buffer[0], NACK_VAL);
    i2c_master_stop(cmd);

    ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);

    // printf( "Read: [%02x]=[%02x]\n", reg, buffer[0] );

    return (buffer[0]);
}

static esp_err_t i2c_master_init(void)
{
    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_ENABLE;
    conf.scl_io_num = I2C_MASTER_SCL_IO;
    conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
    conf.master.clk_speed = 100000;
    conf.clk_flags = 0;

    ESP_ERROR_CHECK(i2c_param_config(i2c_master_port, &conf));
    return i2c_driver_install(i2c_master_port, conf.mode, 0, 0, 0);
}

static esp_err_t es_write_reg(uint8_t slave_addr, uint8_t reg_add, uint8_t data)
{
    return i2c_write(ES8388_ADDR, reg_add, data);
}

static esp_err_t es_read_reg(uint8_t reg_add, uint8_t *p_data)
{
    *p_data = i2c_read(ES8388_ADDR, reg_add);
    return ESP_OK;
}

void es8388_read_all()
{
    // printf( "\n\n===================\n\n");
    for (int i = 0; i < 50; i++)
    {
        uint8_t reg = 0;
        es_read_reg(i, &reg);
    }
    // printf( "\n\n===================\n\n");
}

static int es8388_set_adc_dac_volume(int mode, int volume, int dot)
{
    int res = 0;
    if (volume < -96 || volume > 0)
    {
        ESP_LOGW(ES_TAG, "Warning: volume < -96! or > 0!\n");
        if (volume < -96)
            volume = -96;
        else
            volume = 0;
    }
    dot = (dot >= 5 ? 1 : 0);
    volume = (-volume << 1) + dot;
    if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC)
    {
        res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL8, volume);
        res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL9, volume); // ADC Right Volume=0db
    }
    if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC)
    {
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL5, volume);
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL4, volume);
    }
    return res;
}

esp_err_t es8388_init(es_dac_output_t output, es_adc_input_t input)
{
    int res = 0;

    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL3, 0x04); // 0x04 mute/0x00 unmute&ramp;DAC unmute and  disabled digital volume control soft ramp

    res |= es_write_reg(ES8388_ADDR, ES8388_CONTROL2, 0x50);
    res |= es_write_reg(ES8388_ADDR, ES8388_CHIPPOWER, 0x00);           // normal all and power up all
    res |= es_write_reg(ES8388_ADDR, ES8388_MASTERMODE, ES_MODE_SLAVE); // CODEC IN I2S SLAVE MODE

    res |= es_write_reg(ES8388_ADDR, ES8388_DACPOWER, 0xC0);     // disable DAC and disable Lout/Rout/1/2
    res |= es_write_reg(ES8388_ADDR, ES8388_CONTROL1, 0x12);     // Enfr=0,Play&Record Mode,(0x17-both of mic&paly)
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL1, 0x18);  // 1a 0x18:16bit iis , 0x00:24
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL2, 0x02);  // DACFsMode,SINGLE SPEED; DACFsRatio,256
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL16, 0x00); // 0x00 audio on LIN1&RIN1,  0x09 LIN2&RIN2
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL17, 0x90); // only left DAC to left mixer enable 0db
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL20, 0x90); // only right DAC to right mixer enable 0db
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21, 0x80); // set internal ADC and DAC use the same LRCK clock, ADC LRCK as internal LRCK
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL23, 0x00); // vroi=0
    res |= es8388_set_adc_dac_volume(ES_MODULE_DAC, 0, 0);       // 0db

    ESP_LOGE(ES_TAG, "Setting DAC Output: %02x", output);
    res |= es_write_reg(ES8388_ADDR, ES8388_DACPOWER, output);
    res |= es_write_reg(ES8388_ADDR, ES8388_ADCPOWER, 0xFF);
    res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL1, 0xbb); // MIC Left and Right channel PGA gain

    ESP_LOGE(ES_TAG, "Setting ADC Input: %02x", input);
    res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL2, input);

    res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL3, 0x02);
    res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL4, 0x0d); // Left/Right data, Left/Right justified mode, Bits length, I2S format
    res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL5, 0x02); // ADCFsMode,singel SPEED,RATIO=256
    // ALC for Microphone
    res |= es8388_set_adc_dac_volume(ES_MODULE_ADC, 0, 0);   // 0db
    res |= es_write_reg(ES8388_ADDR, ES8388_ADCPOWER, 0x09); // Power on ADC, Enable LIN&RIN, Power off MICBIAS, set int1lp to low power mode

    return res;
}

// This function sets the I2S format which can be one of
//		I2S_NORMAL
//		I2S_LEFT		Left Justified
//		I2S_RIGHT,      Right Justified
//		I2S_DSP,        dsp/pcm format
//
// and the bits per sample which must be one of
//		BIT_LENGTH_16BITS
//		BIT_LENGTH_18BITS
//		BIT_LENGTH_20BITS
//		BIT_LENGTH_24BITS
//		BIT_LENGTH_32BITS
//
// Note the above must match the ESP-IDF I2S configuration which is set separately

esp_err_t es8388_config_i2s(es_bits_length_t bits_length, es_module_t mode, es_format_t fmt)
{
    esp_err_t res = ESP_OK;
    uint8_t reg = 0;

    // Set the Format
    if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC)
    {
        printf("Setting I2S ADC Format\n");
        res = es_read_reg(ES8388_ADCCONTROL4, &reg);
        reg = reg & 0xfc;
        res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL4, reg | fmt);
    }
    if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC)
    {
        printf("Setting I2S DAC Format\n");
        res = es_read_reg(ES8388_DACCONTROL1, &reg);
        reg = reg & 0xf9;
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL1, reg | (fmt << 1));
    }

    // Set the Sample bits length
    int bits = (int)bits_length;
    if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC)
    {
        printf("Setting I2S ADC Bits: %d\n", bits);
        res = es_read_reg(ES8388_ADCCONTROL4, &reg);
        reg = reg & 0xe3;
        res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL4, reg | (bits << 2));
    }
    if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC)
    {
        ESP_LOGE(ES_TAG, "Setting I2S DAC Bits: %d\n", bits);
        res = es_read_reg(ES8388_DACCONTROL1, &reg);
        reg = reg & 0xc7;
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL1, reg | (bits << 3));
    }
    return res;
}

esp_err_t es8388_set_voice_mute(bool enable)
{
    esp_err_t res = ESP_OK;
    uint8_t reg = 0;
    res = es_read_reg(ES8388_DACCONTROL3, &reg);
    reg = reg & 0xFB;
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL3, reg | (((int)enable) << 2));
    return res;
}

esp_err_t es8388_start(es_module_t mode)
{
    esp_err_t res = ESP_OK;
    uint8_t prev_data = 0, data = 0;
    es_read_reg(ES8388_DACCONTROL21, &prev_data);
    if (mode == ES_MODULE_LINE)
    {
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL16, 0x09); // 0x00 audio on LIN1&RIN1,  0x09 LIN2&RIN2 by pass enable
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL17, 0x50); // left DAC to left mixer enable  and  LIN signal to left mixer enable 0db  : bupass enable
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL20, 0x50); // right DAC to right mixer enable  and  LIN signal to right mixer enable 0db : bupass enable
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21, 0xC0); // enable adc
    }
    else
    {
        res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21, 0x80); // enable dac
    }
    es_read_reg(ES8388_DACCONTROL21, &data);
    if (prev_data != data)
    {
        printf("Resetting State Machine\n");

        res |= es_write_reg(ES8388_ADDR, ES8388_CHIPPOWER, 0xF0); // start state machine
        // res |= es_write_reg(ES8388_ADDR, ES8388_CONTROL1, 0x16);
        // res |= es_write_reg(ES8388_ADDR, ES8388_CONTROL2, 0x50);
        res |= es_write_reg(ES8388_ADDR, ES8388_CHIPPOWER, 0x00); // start state machine
    }
    if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC || mode == ES_MODULE_LINE)
    {
        printf("Powering up ADC\n");
        res |= es_write_reg(ES8388_ADDR, ES8388_ADCPOWER, 0x00); // power up adc and line in
    }
    if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC || mode == ES_MODULE_LINE)
    {
        printf("Powering up DAC\n");
        res |= es_write_reg(ES8388_ADDR, ES8388_DACPOWER, 0x3c); // power up dac and line out
        res |= es8388_set_voice_mute(false);
    }

    return res;
}

esp_err_t es8388_set_voice_volume(int volume)
{
    esp_err_t res = ESP_OK;
    if (volume < 0)
        volume = 0;
    else if (volume > 100)
        volume = 100;
    volume /= 3;
    res = es_write_reg(ES8388_ADDR, ES8388_DACCONTROL24, volume);
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL25, volume);
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL26, volume);
    res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL27, volume);
    return res;
}

void es8388_config()
{
    // Input/Output Modes
    //
    //	es_dac_output_t output = DAC_OUTPUT_LOUT1 | DAC_OUTPUT_LOUT2 | DAC_OUTPUT_ROUT1 | DAC_OUTPUT_ROUT2;
    //	es_adc_input_t input = ADC_INPUT_LINPUT1_RINPUT1;
    // 	es_adc_input_t input = ADC_INPUT_LINPUT2_RINPUT2;

    es_dac_output_t output = DAC_OUTPUT_LOUT1 | DAC_OUTPUT_LOUT2 | DAC_OUTPUT_ROUT1 | DAC_OUTPUT_ROUT2;
    // es_dac_output_t output = DAC_OUTPUT_LOUT1  | DAC_OUTPUT_ROUT1;
    // es_dac_output_t output = DAC_OUTPUT_LOUT2  | DAC_OUTPUT_ROUT2;

    // es_dac_output_t output = 0;
    es_adc_input_t input = ADC_INPUT_LINPUT1_RINPUT1;

    es8388_init(output, input);

    // Modes Available
    //
    //	es_mode_t  = ES_MODULE_ADC;
    //	es_mode_t  = ES_MODULE_LINE;
    //	es_mode_t  = ES_MODULE_DAC;
    //	es_mode_t  = ES_MODULE_ADC_DAC;

    es_bits_length_t bits_length = BIT_LENGTH_16BITS;
    es_module_t module = ES_MODULE_DAC;
    es_format_t fmt = I2S_NORMAL;

    es8388_config_i2s(bits_length, ES_MODULE_ADC_DAC, fmt);
    es8388_set_voice_volume(70);
    es8388_start(module);
}

esp_err_t i2s_mclk_gpio_select(i2s_port_t i2s_num, gpio_num_t gpio_num)
{

    // Ignore whatever is sent in and fix to Pin 3

    //	gpio_num = GPIO_NUM_3;

    if (i2s_num >= I2C_NUM_MAX)
    {
        ESP_LOGE(ES_TAG, "Does not support i2s number(%d)", i2s_num);
        return ESP_ERR_INVALID_ARG;
    }
    if (gpio_num != GPIO_NUM_0 && gpio_num != GPIO_NUM_1 && gpio_num != GPIO_NUM_3)
    {
        ESP_LOGE(ES_TAG, "Only support GPIO0/GPIO1/GPIO3, gpio_num:%d", gpio_num);
        return ESP_ERR_INVALID_ARG;
    }
    ESP_LOGI(ES_TAG, "I2S%d, MCLK output by GPIO%d", i2s_num, gpio_num);
    // if (i2s_num == I2S_NUM_0)
    // {
    //     if (gpio_num == GPIO_NUM_0)
    //     {
    // PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
    // WRITE_PERI_REG(PIN_CTRL, 0xFFF0);
    //     }
    //     else if (gpio_num == GPIO_NUM_1)
    //     {
    //         PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_CLK_OUT3);
    //         WRITE_PERI_REG(PIN_CTRL, 0xF0F0);
    //     }
    //     else
    //     {
    //         PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_CLK_OUT2);
    //         WRITE_PERI_REG(PIN_CTRL, 0xFF00);
    //     }
    // }
    // else if (i2s_num == I2S_NUM_1)
    // {
    //     if (gpio_num == GPIO_NUM_0)
    //     {
    //         PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
    //         WRITE_PERI_REG(PIN_CTRL, 0xFFFF);
    //     }
    //     else if (gpio_num == GPIO_NUM_1)
    //     {
    //         PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_CLK_OUT3);
    //         WRITE_PERI_REG(PIN_CTRL, 0xF0FF);
    //     }
    //     else
    //     {
    //         PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_CLK_OUT2);
    //         WRITE_PERI_REG(PIN_CTRL, 0xFF0F);
    //     }
    // }
    return ESP_OK;
}

void i2s_init()
{

    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_buf_count = 3,
        .dma_buf_len = 300,
        .use_apll = true,
        .tx_desc_auto_clear = true,
        .fixed_mclk = 0,
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1};

    i2s_pin_config_t pin_config = {
        .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
        .mck_io_num = IS2_MCLK_PIN

    };
    i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
    i2s_set_pin(I2S_NUM, &pin_config);

    i2s_mclk_gpio_select(I2S_NUM, (gpio_num_t)IS2_MCLK_PIN);

    i2s_set_clk(I2S_NUM, SAMPLE_RATE, 16, 2);
}

static void setup_sine_waves16(int amplitude)
{
    double sin_float;

    size_t i2s_bytes_write = 0;

    // printf("\r\nFree mem=%d, written data=%d\n", esp_get_free_heap_size(), BUF_SAMPLES*2 );

    for (int pos = 0; pos < BUF_SAMPLES; pos += 2)
    {
        sin_float = amplitude * sin(pos / 2 * 2 * PI / SAMPLE_PER_CYCLE);

        int lval = sin_float;
        int rval = sin_float;

        txBuf[pos] = lval & 0xFFFF;
        txBuf[pos + 1] = rval & 0xFFFF;

        // printf( "%d  %04x:%04x\n", lval, txBuf[pos],txBuf[pos+1] );
    }
}

void app_main(void)
{
    i2c_master_init();
    es8388_config();

    es8388_read_all();

    i2s_init();

    size_t i2s_bytes_write = 0;

    int amplitude = 8000;
    int start_dir = 50;
    int dir = start_dir;

    while (1)
    {

        /*    	amplitude -= dir;
                if ( amplitude <= start_dir || amplitude >= 15000 )
                    dir *= -1;
        */
        setup_sine_waves16(amplitude);

        // i2s_write(I2S_NUM, txBuf, BUF_SAMPLES*2, &i2s_bytes_write, -1);
        i2s_write(I2S_NUM, txBuf, BUF_SAMPLES * 2, &i2s_bytes_write, -1);
        // printf( "Bytes: %d\n", i2s_bytes_write );
        // vTaskDelay(10/portTICK_RATE_MS);
    }
}

natee.th
Posts: 26
Joined: Fri Feb 10, 2023 5:25 pm

Re: ESP32s3 with ES8388 and PCM5102

Postby natee.th » Mon Sep 11, 2023 3:45 am

I'm curious about this line. What does it do?

Code: Select all

PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_CLK_OUT3);
WRITE_PERI_REG(PIN_CTRL, 0xF0F0);

ESP_Sprite
Posts: 9766
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32s3 with ES8388 and PCM5102

Postby ESP_Sprite » Mon Sep 11, 2023 9:16 am

natee.th wrote:
Mon Sep 11, 2023 3:45 am
I'm curious about this line. What does it do?

Code: Select all

PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_CLK_OUT3);
WRITE_PERI_REG(PIN_CTRL, 0xF0F0);
It outputs the I2S CLK on that pin. See the trm, page 75.

Who is online

Users browsing this forum: No registered users and 96 guests