# How to Connect and Configure a 32-bit PCM5102 DAC for I2S Audio Output on Raspberry Pi Pico

> Connect and configure a 32-bit PCM5102 DAC for I2S audio on Raspberry Pi Pico. Learn to wire GPIO, set PLL, initialize I2S driver, and control mute for high-quality audio output.

- Repository: [Elehobica/rpi_pico_wav_player](https://github.com/elehobica/rpi_pico_wav_player)
- Tags: how-to-guide
- Published: 2026-03-01

---

**The Raspberry Pi Pico drives a PCM5102 32-bit I2S DAC by wiring GPIO pins 16–18 for clock and data signals, switching the system PLL to 96 MHz for precise timing, initializing the PIO-based I2S driver with 32-bit signed PCM format, and controlling the DAC’s mute line via GPIO 27.**

The `elehobica/rpi_pico_wav_player` repository provides a complete reference implementation for high-resolution audio playback on the RP2040. This guide examines the hardware wiring and firmware configuration required to connect the PCM5102 32-bit DAC using the I2S protocol, based on the actual source implementation.

## Hardware Wiring of the PCM5102 DAC

The PCM5102 DAC connects to specific GPIO pins on the Raspberry Pi Pico (or Waveshare RP2040 board) according to the pinout defined in the project documentation. The wiring assigns distinct pins for bit-clock, word-clock, data, and mute control.

| PCM5102 Pin | Pico GPIO | Function |
|-------------|-----------|----------|
| BCK (Pin 13) | **GP16** | I2S bit-clock (part of clock pair) |
| LRCK (Pin 15) | **GP17** | I2S word-clock (left/right clock) |
| DIN (Pin 14) | **GP18** | I2S serial data input |
| XSMT (Pin 17) | **GP27** | DAC soft mute control (active high) |
| VCC | 3V3/VBUS | Power supply |

The pin assignments are documented in the README under the PCM5102 section【/README.md#L30-L38】. In the firmware, GP16 and GP17 serve as the clock base, while GP18 carries the audio data stream.

## System Clock Configuration for I2S Timing

The RP2040’s USB PLL is reconfigured to 96 MHz immediately after startup to generate the precise clock rates required for I2S audio transmission. This frequency supports standard sample rates like 44.1 kHz and 48 kHz when divided through the PIO peripheral.

In [`src/main.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/src/main.cpp), the initialization routine calls the PLL configuration helper:

```cpp
// src/main.cpp
pw_set_pll_usb_96MHz();   // Lines 44-45

```

The implementation of `pw_set_pll_usb_96MHz()` (lines 30–45) invokes `pll_init()` and reconfigures both `clk_sys` and `clk_peri` to operate at 96 MHz【/src/main.cpp#L30-L45】. This clock source feeds the PIO state machine driving the I2S signals.

## I2S Driver Setup and 32-bit Audio Format

The project utilizes the **PicoAudio** library to manage the PIO-based I2S peripheral. The driver configuration is statically defined in [`lib/PlayAudio/i2s_audio_init.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/lib/PlayAudio/i2s_audio_init.cpp), specifying the GPIO pins, DMA channels, and audio format.

The hardware configuration struct maps the previously discussed pins:

```cpp
// lib/PlayAudio/i2s_audio_init.cpp (Lines 27-32)
static audio_i2s_config_t i2s_config = {
    .data_pin = PICO_AUDIO_I2S_DATA_PIN,          // GP18
    .clock_pin_base = PICO_AUDIO_I2S_CLOCK_PIN_BASE, // GP16
    .dma_channel0 = 0,
    .dma_channel1 = 1,
    .pio_sm = 0
};

```

The audio format is explicitly set to **32-bit signed PCM (S32)** for high-resolution output:

```cpp
// lib/PlayAudio/i2s_audio_init.cpp (Lines 15-19)
static audio_format_t audio_format = {
    .sample_freq = 44100,
    .pcm_format = AUDIO_PCM_FORMAT_S32,   // 32-bit signed
    .channel_count = AUDIO_CHANNEL_STEREO
};

```

During the `i2s_audio_init()` routine (lines 45–71), the firmware performs the following sequence【/lib/PlayAudio/i2s_audio_init.cpp#L45-L71】:

1. Allocates a producer buffer pool for audio samples.
2. Calls `audio_i2s_setup()` with the format and config structs.
3. Connects the buffer pool to the hardware via `audio_i2s_connect()`.
4. Writes an initial zero-buffer (all samples set to `DAC_ZERO`) to prevent startup noise.
5. Enables the I2S engine with `audio_i2s_set_enabled(true)`.

## Controlling the DAC Mute Line

The PCM5102’s **XSMT** pin (soft mute control) is connected to **GP27** and managed through a dedicated power management interface. The firmware keeps the DAC muted during initialization and un-mutes it only when playback begins.

In [`src/power_manage.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/src/power_manage.cpp), the mute pin is defined and initialized:

```cpp
// src/power_manage.cpp (Lines 47-52)
static constexpr uint32_t PIN_AUDIO_DAC_ENABLE = 27;

gpio_init(PIN_AUDIO_DAC_ENABLE);                 // Line 140
gpio_set_dir(PIN_AUDIO_DAC_ENABLE, GPIO_OUT);    // Line 141
gpio_put(PIN_AUDIO_DAC_ENABLE, 0);               // Line 142 - initially muted

```

The helper function `pm_set_audio_dac_enable()` toggles the mute state by driving GP27 high (un-mute) or low (mute)【/src/power_manage.cpp#L209-L212】:

```cpp
void pm_set_audio_dac_enable(bool flag) {
    gpio_put(PIN_AUDIO_DAC_ENABLE, flag);
}

```

The UI layer registers this function and controls the DAC state during mode transitions. When entering play mode, the firmware calls `pm_set_audio_dac_enable(true)` to activate audio output【/src/UIMode.cpp#L294-L298】, and mutes the DAC during power-off or pause states【/src/UIMode.cpp#L1120】.

## Complete Initialization Sequence

To reproduce the player’s audio initialization flow in a custom application, execute the following sequence:

```cpp
// 1. Configure system clock for I2S timing
pw_set_pll_usb_96MHz();  // src/main.cpp lines 44-45

// 2. Initialize I2S driver with 32-bit format
audio_buffer_pool_t* producer_pool = nullptr;
i2s_setup(44100, producer_pool);  // lib/PlayAudio/i2s_audio_init.cpp lines 34-44

// 3. Register and enable the DAC mute control
audio_codec_set_dac_enable_func(pm_set_audio_dac_enable);
pm_set_audio_dac_enable(true);  // Un-mute the PCM5102

```

The `i2s_setup()` wrapper function handles the internal buffer allocation and driver configuration. Once enabled, the PIO state machine continuously streams 32-bit PCM samples from the buffer pool to the DAC via GPIO 18, synchronized to the bit-clock and word-clock signals on GPIO 16 and 17.

## Summary

- **Hardware Wiring**: The PCM5102 connects to GP16 (BCK), GP17 (LRCK), GP18 (DIN), and GP27 (XSMT mute).
- **Clock Requirement**: The system PLL must run at 96 MHz to generate valid I2S clock rates, configured in [`src/main.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/src/main.cpp).
- **Audio Format**: The driver uses 32-bit signed PCM (S32) stereo format as defined in [`i2s_audio_init.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/i2s_audio_init.cpp).
- **Mute Control**: GPIO 27 drives the DAC’s XSMT pin through `pm_set_audio_dac_enable()`, ensuring silent initialization and clean power transitions.
- **Driver Architecture**: The PicoAudio library abstracts the PIO and DMA configuration, providing a buffer-pool interface for audio streaming.

## Frequently Asked Questions

### Why does the RP2040 require a 96 MHz PLL for I2S audio?

The 96 MHz clock provides the necessary resolution to generate standard audio sample rates (44.1 kHz, 48 kHz, 96 kHz) when divided by the PIO state machine’s clock dividers. According to the source code in [`src/main.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/src/main.cpp), the `pw_set_pll_usb_96MHz()` function reconfigures the USB PLL to serve as the system clock source, ensuring the I2S bit-clock runs at precise multiples of the sample rate.

### What audio format does the firmware use for the 32-bit DAC?

The implementation uses **32-bit signed PCM (S32)** in stereo configuration. This is explicitly set in the `audio_format_t` struct within [`lib/PlayAudio/i2s_audio_init.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/lib/PlayAudio/i2s_audio_init.cpp) (line 17), where `.pcm_format` is assigned `AUDIO_PCM_FORMAT_S32`. The PCM5102 DAC natively supports this format, providing higher dynamic range compared to 16-bit audio.

### How is the DAC muted and un-muted during playback?

The DAC’s soft-mute pin (XSMT) is controlled via **GPIO 27**. The firmware defines `PIN_AUDIO_DAC_ENABLE` as 27 in [`src/power_manage.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/src/power_manage.cpp), and the function `pm_set_audio_dac_enable()` sets the pin high to un-mute and low to mute. The UI mode manager calls this function when entering play mode (un-mute) and when powering off or pausing (mute), preventing audible pops and clicks.

### Can the I2S configuration support sample rates other than 44.1 kHz?

Yes. The `i2s_setup()` function accepts any valid sample rate as its first parameter. The example code in the repository shows initialization at 44100 Hz, but the PIO-based driver can be reconfigured for 48000 Hz, 96000 Hz, or other rates by passing the desired value to `i2s_setup()` and ensuring the source audio files match the configured rate. The 96 MHz system clock provides sufficient headroom for higher sample rates.