Module Audio integrates an STM32 main controller to handle headset standard switching, LED control, headphone insertion detection (Channel 2 only), microphone input mode configuration, and other functions.
device.setHPMode(AUDIO_HPMODE_NATIONAL);
or device.setHPMode(AUDIO_HPMODE_AMERICAN);
to switch between OMTP (AUDIO_HPMODE_NATIONAL) and CTIA (AUDIO_HPMODE_AMERICAN) for compatibility.#include "M5Unified.h"#include "audio_i2c.hpp"#include "es8388.hpp"#include "driver/i2s.h" #define SYS_I2C_SDA_PIN 21#define SYS_I2C_SCL_PIN 22#define SYS_I2S_MCLK_PIN 0#define SYS_I2S_SCLK_PIN 19#define SYS_I2S_LRCK_PIN 27#define SYS_I2S_DOUT_PIN 2#define SYS_I2S_DIN_PIN 34#define SYS_SPI_MISO_PIN 38#define SYS_SPI_MOSI_PIN 23#define SYS_SPI_CLK_PIN 18#define SYS_SPI_CS_PIN 4 AudioI2c device;ES8388 es8388(&Wire, SYS_I2C_SDA_PIN, SYS_I2C_SCL_PIN); void setup(){ M5.begin(); Serial.begin(115200); device.begin(&Wire, SYS_I2C_SDA_PIN, SYS_I2C_SCL_PIN); device.setHPMode(AUDIO_HPMODE_NATIONAL); // device.setHPMode(AUDIO_HPMODE_AMERICAN); device.setMICStatus(AUDIO_MIC_OPEN); device.setRGBBrightness(100); for (int i = 0; i <= 2; i++) { device.setRGBLED(i, 0x0000ff); }} void loop(){ bool isHPInsert = device.getHPInsertStatus(); if (isHPInsert) { Serial.println("Headphone Inserted"); } else { Serial.println("Headphone Removed"); } delay(500);}
After initialization, call the following APIs to select ADC/DAC channels and set volume/gain:
// Use input 1 for both channelses8388.setADCInput(ADC_INPUT_LINPUT1_RINPUT1); // Use input 2 for both channels// es8388.setADCInput(ADC_INPUT_LINPUT2_RINPUT2); es8388.setDACOutput(DAC_OUTPUT_OUT1);es8388.setADCVolume(100);es8388.setDACVolume(40);es8388.setMicGain(MIC_GAIN_24DB);es8388.setBitsSample(ES_MODULE_ADC, BIT_LENGTH_16BITS);es8388.setSampleRate(SAMPLE_RATE_44K);
Using the TRS wiring method, configure Channel 1 for MIC input and Channel 2 for audio output to read MIC input data in real time and play it back.
#include "M5Unified.h"#include "audio_i2c.hpp"#include "es8388.hpp"#include "driver/i2s.h" AudioI2c device;ES8388 es8388(&Wire, SYS_I2C_SDA_PIN, SYS_I2C_SCL_PIN); uint16_t rxbuf[256], txbuf[256];size_t readsize = 0; i2s_config_t i2s_config = { .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX), .sample_rate = 44100, .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, .communication_format = I2S_COMM_FORMAT_STAND_I2S, .intr_alloc_flags = 0, .dma_buf_count = 8, .dma_buf_len = 512, .use_apll = false, .tx_desc_auto_clear = true, .fixed_mclk = 0}; i2s_pin_config_t pin_config = { .mck_io_num = SYS_I2S_MCLK_PIN, .bck_io_num = SYS_I2S_SCLK_PIN, .ws_io_num = SYS_I2S_LRCK_PIN, .data_out_num = SYS_I2S_DOUT_PIN, .data_in_num = SYS_I2S_DIN_PIN,}; void setup(){ M5.begin(); Serial.begin(115200); device.begin(&Wire, SYS_I2C_SDA_PIN, SYS_I2C_SCL_PIN); device.setHPMode(AUDIO_HPMODE_NATIONAL); device.setMICStatus(AUDIO_MIC_OPEN); device.setRGBBrightness(100); // Initialize ES8388 if (!es8388.init()) Serial.println("Init Fail"); es8388.setADCInput(ADC_INPUT_LINPUT1_RINPUT1); es8388.setMicGain(MIC_GAIN_24DB); es8388.setADCVolume(100); es8388.setDACVolume(40); es8388.setDACOutput(DAC_OUTPUT_OUT1); es8388.setBitsSample(ES_MODULE_ADC, BIT_LENGTH_16BITS); es8388.setSampleRate(SAMPLE_RATE_44K); // Install I2S driver i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); i2s_set_pin(I2S_NUM_0, &pin_config);} void loop(){ i2s_read(I2S_NUM_0, &rxbuf[0], 256 * 2, &readsize, portMAX_DELAY); for (int i = 0; i < 256; i++) { txbuf[i] = rxbuf[i]; } i2s_write(I2S_NUM_0, &txbuf[0], 256 * 2, &readsize, portMAX_DELAY);}
Configure Channel 2 for audio output, load a WAV file from the MicroSD card, and play it. Ensure the WAV file is copied to the MicroSD card and the card is inserted into the host device.
#include "M5Unified.h"#include "audio_i2c.hpp"#include "es8388.hpp"#include "driver/i2s.h"#include <SPI.h>#include <SD.h> AudioI2c device;ES8388 es8388(&Wire, SYS_I2C_SDA_PIN, SYS_I2C_SCL_PIN); void i2s_write_task(void *arg); i2s_config_t i2s_config = { /* same as above */ };i2s_pin_config_t pin_config = { /* same as above */ }; void setup(){ M5.begin(); Serial.begin(115200); device.begin(&Wire, SYS_I2C_SDA_PIN, SYS_I2C_SCL_PIN); device.setHPMode(AUDIO_HPMODE_NATIONAL); device.setMICStatus(AUDIO_MIC_OPEN); device.setRGBBrightness(100); // Initialize ES8388 if (!es8388.init()) Serial.println("Init Fail"); es8388.setADCVolume(100); es8388.setDACVolume(80); es8388.setDACOutput(DAC_OUTPUT_OUT1); es8388.setBitsSample(ES_MODULE_ADC, BIT_LENGTH_16BITS); es8388.setSampleRate(SAMPLE_RATE_44K); i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); i2s_set_pin(I2S_NUM_0, &pin_config); if (SD.begin(SYS_SPI_CS_PIN)) { Serial.println("SD card initialized successfully"); } else { Serial.println("Failed to initialize SD card. Retrying..."); } xTaskCreate(i2s_write_task, "i2s_write_task", 1024 * 8, NULL, 6, NULL);} void loop() { } void i2s_write_task(void *arg){ File file = SD.open("/hello.wav", FILE_READ); if (!file) { Serial.println("Failed to open WAV file for reading"); vTaskDelete(NULL); } file.seek(44); // Skip WAV header uint8_t buf[1024]; size_t bytesRead, bytesWritten; while (true) { if (file.available() == 0) { file.seek(44); } bytesRead = file.read(buf, sizeof(buf)); if (bytesRead > 0) { esp_err_t res = i2s_write(I2S_NUM_0, buf, bytesRead, &bytesWritten, portMAX_DELAY); if (res != ESP_OK) { Serial.printf("I2S write error: %d\n", res); } } else { break; } } file.close(); vTaskDelete(NULL);}
Module Audio integrates three programmable RGB LEDs on its side. Refer to the example below for control.
#include "M5Unified.h"#include "audio_i2c.hpp" #define SYS_I2C_SDA_PIN 21#define SYS_I2C_SCL_PIN 22 AudioI2c device; void setup(){ M5.begin(); Serial.begin(115200); while (!device.begin(&Wire, SYS_I2C_SDA_PIN, SYS_I2C_SCL_PIN)) { delay(1000); } device.setRGBBrightness(100);} void loop(){ for (int i = 0; i <= 2; i++) { device.setRGBLED(i, 0xff0000); } delay(1000); for (int i = 0; i <= 2; i++) { device.setRGBLED(i, 0x00ff00); } delay(1000); for (int i = 0; i <= 2; i++) { device.setRGBLED(i, 0x0000ff); } delay(1000);}