# PCM5102 Audio Codec: 32-Bit DAC and Volume Control in RPi Pico WAV Player

> Discover the PCM5102 audio codec powering the RPi Pico WAV Player. This 32-bit DAC offers volume control and high-quality WAV playback for your projects.

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

---

**The RPi Pico WAV Player uses the Texas Instruments PCM5102 audio codec, a 32-bit I²S DAC that receives software-scaled PCM samples with volume control implemented in the PlayAudio subsystem.**

The `elehobica/rpi_pico_wav_player` project leverages dedicated hardware and precision firmware to deliver high-quality audio playback on Raspberry Pi Pico. Understanding how the PCM5102 audio codec interfaces with the software volume control reveals the architecture behind the 32-bit audio pipeline.

## Understanding the PCM5102 Audio Codec Hardware

The PCM5102 is a stereo audio DAC that converts digital I²S signals into analog audio output. The codec operates as a slave device, receiving bit clock (BCK), word select (LRCK), and serial data (DIN) from the RP2040 microcontroller.

### Hardware Specifications and Pinout

According to the project documentation in [`README.md`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/README.md), the PCM5102 connects to specific GPIO pins on the Pico:

- **BCK** (Bit Clock): GPIO26
- **LRCK** (Left/Right Clock): GPIO27  
- **DIN** (Data In): GPIO28

The README describes the component as "*PCM5102 32bit I2S Audio DAC*" and confirms it handles the full 32-bit PCM range expected by the codec hardware.

## Software Volume Control Implementation

Volume management occurs entirely in software before samples reach the DAC. The `PlayAudio` class maintains a volume lookup table and applies scaling to 32-bit integers, ensuring the PCM5102 receives properly ranged data that utilizes its full dynamic range.

### Volume Scaling Algorithm

The volume system stores discrete levels in `vol_table` defined in [`lib/PlayAudio/PlayAudio.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/lib/PlayAudio/PlayAudio.cpp). The table maps user-facing volume levels (0-100) to fixed-point multipliers:

```cpp
// Volume table initialization in PlayAudio.cpp
static const uint16_t vol_table[] = {
    // ... lookup values for 0-100 range
};

```

When adjusting volume, the firmware retrieves the corresponding scalar from this table. The `setVolume()`, `volumeUp()`, and `volumeDown()` methods handle user input and clamp values between 0 and 100.

### 32-Bit Sample Processing

The actual scaling occurs in [`lib/PlayAudio/PlayWav.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/lib/PlayAudio/PlayWav.cpp) during the audio decoding loop. The firmware converts source samples to 32-bit integers, applies the volume multiplier, then adds the DAC zero-offset:

```cpp
// Inside PlayWav::decode() - sample scaling logic
int32_t scaled = static_cast<int32_t>(
        (static_cast<int64_t>(buf_s32) * vol_table[volume] / 65536)
    ) + DAC_ZERO;
samples[i*2 + j] = scaled; // 32-bit sample written to I²S buffer

```

This calculation ensures the PCM5102 receives 32-bit aligned data centered around `DAC_ZERO`, maximizing the codec's signal-to-noise ratio while preventing clipping at extreme volume levels.

## I²S Interface Configuration

The RP2040's I²S peripheral initialization occurs in [`lib/PlayAudio/i2s_audio_init.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/lib/PlayAudio/i2s_audio_init.cpp). The `i2s_setup()` function configures the PIO (Programmable I/O) state machines to generate the precise timing required by the PCM5102:

```cpp
// I²S initialization for PCM5102
i2s_setup(44100, ap);   // Default sample rate, PCM5102 expects I²S data

```

The PCM5102 operates in standard I²S mode, expecting the MSB of the 32-bit sample to be valid on the second rising edge of BCK following an LRCK transition. The firmware's PIO program generates this exact timing pattern, ensuring the codec correctly interprets the high-resolution audio data.

## Summary

- The **PCM5102** from Texas Instruments serves as the 32-bit I²S audio codec, converting digital PCM data to analog output.
- **Volume control** is implemented entirely in software within [`PlayAudio.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/PlayAudio.cpp) and [`PlayWav.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/PlayWav.cpp), using a lookup table to scale 32-bit samples before transmission.
- The **I²S interface** in [`i2s_audio_init.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/i2s_audio_init.cpp) drives the PCM5102 with precise PIO-generated timing at standard sample rates like 44.1 kHz.
- The **32-bit DAC output** utilizes the full dynamic range of the PCM5102 by applying a zero-offset (`DAC_ZERO`) to centered audio data.

## Frequently Asked Questions

### What audio codec does the RPi Pico WAV Player use?

The project uses the **Texas Instruments PCM5102**, a 32-bit stereo audio DAC that receives I²S signals from the RP2040 microcontroller. This codec is connected via GPIO pins 26 (BCK), 27 (LRCK), and 28 (DIN) according to the hardware documentation in [`README.md`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/README.md).

### How does the PCM5102 handle 32-bit audio output?

The PCM5102 accepts 32-bit PCM samples via its I²S input and converts them to analog voltages with high dynamic range. The firmware maximizes this capability by sending scaled 32-bit integers centered around `DAC_ZERO` (typically 0x80000000 for unsigned alignment), ensuring the codec utilizes its full-scale output without clipping.

### Where is volume control implemented in the code?

Volume control logic resides in two primary locations: [`lib/PlayAudio/PlayAudio.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/lib/PlayAudio/PlayAudio.cpp) defines the `vol_table` lookup array and volume setting methods (`setVolume()`, `volumeUp()`, `volumeDown()`), while [`lib/PlayAudio/PlayWav.cpp`](https://github.com/elehobica/rpi_pico_wav_player/blob/main/lib/PlayAudio/PlayWav.cpp) applies the actual scaling algorithm during sample decoding, multiplying 32-bit PCM values by the volume coefficient before adding the DAC zero-offset.

### What is the DAC zero-offset value used for?

The `DAC_ZERO` constant (defined in the audio library) represents the mid-scale value of the PCM5102's 32-bit input range, typically corresponding to 0x80000000 for unsigned 32-bit alignment. This offset centers the bipolar audio signal around the DAC's mid-point, ensuring that silence corresponds to the analog zero-voltage point and that negative sample values produce negative voltages while positive values produce positive voltages.