Raspberry Pi I2S Audio Interface

This post looks at how to use a cheap I2S digital to analog converter as the audio output interface for a Raspberry Pi V1 model B and a Raspberry Pi Zero V1.

As I mentioned last time, there are a number of ready-made “off the shelf” add-on boards you can get for the Raspberry Pi to provide I2S DAC output, including the following (I have the Pimoroni Audio DAC SHIM):

For the initial experiments I’m using a cheap PCM5102 board (the same one I’ve used with my Clumsy MIDI interface) that looks like the one shown below.  For later experiments, I’m using a Pimoroni Audio DAC SHIM.

IMG_5588

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

These are the key tutorials for the main concepts used in this project:

If you are new to microcontrollers and single board computers, see the Getting Started pages.

Parts list

  • Raspberry Pi Zero (any version, but I’m using the original “non wireless” v1) or Raspberry Pi V1 Model B (Revision 2)
  • PCM5102 I2S DAC module or I2S DAC “hat” or equivalent module
  • 6×6 hole protoboard (optional)
  • Male and female header pins as required (optional)
  • Connecting wires

I2S DAC SHIM or Hat

IMG_5591

I have a Pimoroni Audio DAC SHIM with a line-out socket (there is a version with a small amplifier for direct connection to speakers too).  This uses I2S and sits very nicely on a Pi Zero by simply being pushed over the GPIO pins, leaving enough of them poking out the top to connection an addition HAT or module.

IMG_5595

It is a very neat idea and by far the simples way to get an audio output jack on your Pi Zero!

The PCM5102 Circuit

The PCM5102 module has six connections: power, ground and four signal pins, one of which (SCK) is not required and should be connected to GND.

If your module was like mine, it came “unconfigured” and needs some solder bridges making on the underside of the board.  I’ve used the same configuration as required for the Clumsy MIDI interface.  Full details can be found here: https://github.com/gmcn42/clumsyMIDI (see the IMPORTANT section for the “DAC board solder bridges”).

The I2S interface is often listed in the various Raspberry Pi datasheets as the PCM pins: PCM_CLK, PCM_FS, PCM_DIN, PCM_DOUT.  These need to be hooked up to the PCM5102 as follows.

  • PCM_CLK -> BCK
  • PCM_FS -> LCK
  • PCM_DOUT -> DIN
  • 5V -> VIN
  • GND -> SCK and GND

Where the PCM function “breaks out” depends on the type of Raspberry Pi you’re using.

Note that the PCM5102 is powered from 5V as although the Pi requires 3V3 logic connections, the PCM5102 module has a built-in regulator to take the 5V VIN to 3V3, so the signals should all be fine.

I2S Output on the Pi Zero

Raspberry Pi Zero I2S PCM5102_bb

For versions of the Pi with the 40-pin GPIO header (V1 Model B+ onwards, including the Pi Zero) these can be found on the following pins:

  • GPIO 18: PCM_CLK
  • GPIO 19: PCM_FS
  • GPIO 20: PCM_DIN
  • GPIO 21: PCM_DOUT

You can find more details here: https://pinout.xyz/pinout/pcm.  Just hook up CLK, FS and DOUT along with power and ground (recall SCK on the PCM5102 also goes to ground) and it should be good to go.

I2S Output on the Pi V1 Model B (Rev 2)

Raspberry Pi V1 P5 I2S PCM5102_bb

For versions of the Pi with the 26-pin GPIO header (V1 Model B) I2S does not make it to the GPIO header so things are a little more complicated.  But happily they can be found on the additional “P5” header (the unpopulated 8-way header just next to the main GPIO) that was introduced with Revision 2 of the V1 Model B PCB. It can be found on the following pins as one of their “alternative functions” (on ALT 2):

  • GPIO 28: PCM_CLK
  • GPIO 29: PCM_FS
  • GPIO 30: PCM_DIN
  • GPIO 31: PCM_DOUT

You can read about the P5 header here: https://www.raspberrypi-spy.co.uk/2012/09/raspberry-pi-p5-header/.  The general idea is that header pins would be soldered on, poking out on the underside of the board, so as not to interfere with the main GPIO header.

Once again hook up CLK, FS, DOUT, power and ground with SCK also to ground.

Pi V1 Model B Rev 2 P5 Header Breakout

I’ve put together a simple breakout board that will plug directly (with soldering) into the Pi P5 header and provide the right 6-way header for the PCM5102 module.  You can see the design in the Fritzing diagram above.  The PCM5102 breakout is the stripboard design top left.  There is also a P5 to 8-way header generic breakout (that I haven’t built, but might in the future).

Note that in both cases the stripboard needs the copper strips cutting between the two rows of four of the header pins.  The PCM5102 has other cuts too, but hopefully they are more obvious in the diagram.

Here are a couple of build photos.

With hindsight, I think I’d solder an 8-way (4×2) male header on the underside of the Pi and add an 8-way (4×2) female header on this breakout.

The Code

I’m using the same “miniorgan” sample code as described previously but we need to build it to output audio over I2S rather than PWM.  To do that, there is a in the miniorgan.h file that needs uncommenting:

// define only one
#define USE_I2S
//#define USE_HDMI

This is all that is required to use this with the Raspberry Pi Zero and I2S audio of any sort.

However to use it with the v1 Pi via the P5 header the I2S sound device support needs updating to use the new range of GPIO pins (as describe above).

Update: At the time of writing, the main circle code is being updated to support the use of either GPIO mode depending on the Pi model number.  You can follow the development of the code here: https://github.com/rsta2/circle/issues/267Read on for what had to change, but there is every chance that by the time you read this it might be supported “out of the box” on a V1 model B revision 2 via P5 too.

I’ve added a configuration option into include/circle/sysconfig.h as follows:

// Raspberry Pi V1 Model B has I2S on GPIO 28-31 available via
// the P5 additional GPIO header
#define USE_I2S_AUDIO_ON_P5

Then I’ve added some conditional code in lib/i2ssoundbasedevice.cpp, in the method CI2SSoundBaseDevice::RunI2S as follows:

  // init GPIO pins
#ifdef USE_I2S_AUDIO_ON_P5
  m_PCMCLKPin.AssignPin (28);
  m_PCMCLKPin.SetMode (GPIOModeAlternateFunction2);
  m_PCMFSPin.AssignPin (29);
  m_PCMFSPin.SetMode (GPIOModeAlternateFunction2);

  if (m_DeviceMode != DeviceModeTXOnly)
  {
    m_PCMDINPin.AssignPin (30);
    m_PCMDINPin.SetMode (GPIOModeAlternateFunction2);
  }

  if (m_DeviceMode != DeviceModeRXOnly)
  {
    m_PCMDOUTPin.AssignPin (31);
    m_PCMDOUTPin.SetMode (GPIOModeAlternateFunction2);
  }
#else
  m_PCMCLKPin.AssignPin (18);
  m_PCMCLKPin.SetMode (GPIOModeAlternateFunction0);
  m_PCMFSPin.AssignPin (19);
  m_PCMFSPin.SetMode (GPIOModeAlternateFunction0);

  if (m_DeviceMode != DeviceModeTXOnly)
  {
    m_PCMDINPin.AssignPin (20);
    m_PCMDINPin.SetMode (GPIOModeAlternateFunction0);
  }

  if (m_DeviceMode != DeviceModeRXOnly)
  {
    m_PCMDOUTPin.AssignPin (21);
    m_PCMDOUTPin.SetMode (GPIOModeAlternateFunction0);
  }
#endif

At this point the circle environment needs rebuilding and then the sample application can be rebuilt again to allow the use of GPIO 28-31 for I2S.

Closing Thoughts

You get a better quality audio signal using I2S and adding a cheap module isn’t particularly difficult.  I have plans for my Pimoroni Audio DAC SHIM with my AnalogZero.

Also, I should note that Rene Stange, the author of the circle environment, is great and actively continuing to develop circle.  We’ve had a bit of an exchange after I reported an issue requesting the P5 header support and it will soon be included in the main circle branch of code.

Kevin

9 thoughts on “Raspberry Pi I2S Audio Interface

  1. Thank you for your article. I want to connect Pi Rev.2 to my DAC. I am using PicorePlayer as OS. Do you know if your wiring has made into the driver? Is it located in the kernel or in which module (can you tell me the name)? Do you know? I am asking, cause I found an older hint connecting a Hifiberry DAC nearly exact the same way (some extra wirings to GPIO 2 and 3 needed here extra), and there was no hint of editing and compiling the sources again…
    Cause honestly I do not know how to build and change the PicorePlayer system. Do you know if the driver maybe has a switch for the different Pi versions? Any help appreciated!

    Liked by 1 person

    1. Great! Yes, the above is all about enabling the I2S interface really, so I don’t think it matters what I2S thing is on the end of it… and I think I2S is a common driver element in anything that proports to produce audio.

      I could imagine some devices may include extra IO for special configuration modes or some such, but I believe I2S itself is a relatively simple hardware streaming interface. It just has to be low latency and jitter free as I understand things.

      Very glad to hear you got it working 🙂

      Like

  2. Hi,

    is it possible to get eight (!) 🙂 I²S busses running on a pi?

    Need that for a project feeding directly some (let’s say eight…) transoders from one raspberry.

    Thanks for your work!

    Cheers

    Like

    1. I don’t actually know if I’m honest, but seeing as there is only a single hardware I2S connection, I suspect not.

      It might be possible to “bitbang” other GPIO pins to act as a software-driven I2S interface, but that would need the CPU to be continually sending out data by updating the GPIO at I2S bus speeds.

      I know the GPIO can be multiplexed onto different peripherals which allows alternative functions, so I2S may appear on other GPIO, especially on later Pis, but it would still need several I2S peripherals built into the chips, and I don’t think they have that.

      There may be a possibility to use the RPi Pico with PIO as a multi-I2S interface – the I2S support is all PIO in the first place, but I can’t imagine how that would work with the provided Pico audio library, so it would need some serious playing around.

      So as I say, I don’t know, but nothing I’ve seen so far would lead me to think it was possible. You might squeeze two out of it, but I don’t see how you’d do much more than that if that was even possible.

      But do let me know if you find out any more 🙂

      Kevin

      Like

  3. Kevin,

    Thanks for the amazing tutorial!

    Is there any reason why I couldn’t connect my Pi to a board like this (or similar) https://www.aliexpress.com/item/1005006301383113.html

    Even though it is a 9028, would I just select 9023 in the SqueezePlayer settings?

    Also, if I just want to use this with LMS and SqueezePlayer, do I need to make the code changes you’ve listed above? If so, where exactly are the files that need changing.

    Thanks again – you’re a legend!

    Like

    1. I seem unable to find very much information about that board online at all, so I can’t really comment I’m afraid. I’d imagine that if it supports I2S, then it ought to be a case of matching up the appropriate signals (3V3 vs 5V logic levels not withstanding), but as I say, I can’t even find out what the pinouts of those connectors are or what it does or how it is powered so in truth, I’ve no idea!

      The code changes are related to the circle bare-metal environment application, so would be irrelevant if you’re using a standard operating system and normal applications. I don’t know anything about the applications you’re asking about though, sorry.

      Kevin

      Liked by 1 person

Leave a comment