A2DP-sink to I2S PCM5102
Posted: Thu Dec 12, 2024 11:15 am
This code sets up an ESP32 to act as a Bluetooth A2DP sink, receiving audio from Bluetooth devices and streaming it to an external audio system via I2S. It uses Direct Memory Access (DMA) for efficient audio data transfer. The code configures the I2S interface for audio communication and includes a callback function to handle the streaming of audio data.
Code: Select all
#include "BluetoothA2DPSink.h" // Include the A2DP sink library
#include "driver/i2s.h" // Include the I2S driver library
BluetoothA2DPSink a2dp_sink; // Create A2DP sink instance
// I2S configuration constants
#define I2S_NUM I2S_NUM_0 // Use I2S peripheral 0
#define I2S_SAMPLE_RATE 44100 // Set audio sample rate to 44.1kHz
#define I2S_BITS I2S_BITS_PER_SAMPLE_16BIT // Set 16-bit audio depth
#define I2S_CHANNELS I2S_CHANNEL_FMT_RIGHT_LEFT // Set stereo (2 channels)
#define I2S_PIN_DATA 33 // Set I2S data pin (GPIO 33)
#define I2S_PIN_BCLK 25 // Set I2S bit clock pin (GPIO 25)
#define I2S_PIN_LRCLK 26 // Set I2S left-right clock pin (GPIO 26)
#define NMUTE_PIN 32 // Pin to control mute functionality
// Function to configure I2S interface
void setup_i2s() {
// Configure I2S with required settings
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), // I2S as master and transmitter
.sample_rate = I2S_SAMPLE_RATE, // Set sample rate
.bits_per_sample = I2S_BITS, // Set bits per sample
.channel_format = I2S_CHANNELS, // Set stereo channel format
.communication_format = I2S_COMM_FORMAT_I2S_MSB, // Set MSB communication format
.intr_alloc_flags = 0, // No interrupt flags
.dma_buf_count = 8, // DMA buffer count
.dma_buf_len = 64, // DMA buffer length
.use_apll = false // Do not use APLL (Audio PLL)
};
// Configure I2S pin assignments
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_PIN_BCLK, // Bit clock pin
.ws_io_num = I2S_PIN_LRCLK, // Word select pin
.data_out_num = I2S_PIN_DATA, // Data output pin
.data_in_num = I2S_PIN_NO_CHANGE // No input data pin
};
// Install I2S driver and configure the pins
i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM, &pin_config);
}
// Callback function to process incoming audio data and send it to I2S
void read_data_stream(const uint8_t *data, uint32_t length) {
size_t bytes_written;
// Write received audio data to I2S for output
i2s_write(I2S_NUM, data, length, &bytes_written, portMAX_DELAY);
// Serial debug print statements have been removed to reduce output noise
}
void setup() {
// Set up mute control pin
pinMode(NMUTE_PIN, OUTPUT);
digitalWrite(NMUTE_PIN, HIGH); // Enable audio output by setting pin high
setCpuFrequencyMhz(80); // Reduce CPU frequency to 80 MHz for power saving
// Initialize the I2S interface
setup_i2s();
// Start A2DP sink with the name "GOLF G60" and no authentication (false)
a2dp_sink.set_stream_reader(read_data_stream, false);
a2dp_sink.start("GOLF G60", false);
}
void loop() {
delay(1000); // Main loop does nothing; just delays to keep the program running
}