CircuitPython Wiring & Test

CircuitPython 3.0 and higher has I2S built in which means you can use this breakout super easily with the supported M0 and M4 Express CircuitPython boards! Supported boards are Feather M0 Express, Feather M4 Express, Metro M0 Express, Metro M4 Express, and ItsyBitsy M0 Express.

Note that Trinket M0, Gemma M0 and ItsyBitsy M4 do not support I2S (the last one is not a typo!)

The M0 boards have multiple I2S pin combinations available. We're going to demonstrate a single pin combination for each board.

Wiring

The following wiring diagrams show how to connect the UDA1334 breakout to your CircuitPython board. You'll be using voltage in, ground, bit clock, word select and data pins.

  • VIN is the red wire.
  • GND is the black wire.
  • BCLK is the blue wire.
  • WSEL is the yellow wire.
  • DIN is the green wire.

For Feather M0 Express, ItsyBitsy M0 Express and Metro M0 Express:

  • Connect VIN on the breakout to 3V/3.3 on the board.
  • Connect GND on the breakout to G/GND on the board.
  • Connect BCLK on the breakout to D1/TX on the board.
  • Connect WSEL on the breakout to D0/RX on the board.
  • Connect DIN on the breakout to D9 on the board.

For Feather M4 Express:

  • Connect VIN on the breakout to 3V on the board.
  • Connect GND on the breakout to Gnd on the board.
  • Connect BCLK on the breakout to TX on the board.
  • Connect WSEL on the breakout to D10 on the board.
  • Connect DIN on the breakout to D11 on the board.

For Metro M4 Express:

  • Connect VIN on the breakout to 3.3 on the board.
  • Connect GND on the breakout to GND on the board.
  • Connect BCLK on the breakout to D3 on the board.
  • Connect WSEL on the breakout to D9 on the board.
  • Connect DIN on the breakout to D8 on the board.

Code Examples

We have two CircuitPython code examples. The first plays a generated tone through the audio jack on the breakout. The second plays a wave file. Let's take a look!

The default volume of the audio in the following code is very high. Do put on plugged in headpones before first running the code to check the volume.

Tone Generation

The first example generates one period of a sine wave and then loops it to generate a tone. You can change the volume and the Hz of the tone by changing the associated variables. Inside the loop, we play the tone for one second and stop it for one second.

import time
import array
import math
import audioio
import board
import audiobusio

tone_volume = 0.1  # Increase this to increase the volume of the tone.
frequency = 440  # Set this to the Hz of the tone you want to generate.
length = 8000 // frequency
sine_wave = array.array("h", [0] * length)
for i in range(length):
    sine_wave[i] = int((math.sin(math.pi * 2 * i / length)) * tone_volume * (2 ** 15 -1))

# For Feather M0 Express, ItsyBitsy M0 Express, Metro M0 Express
audio = audiobusio.I2SOut(board.D1, board.D0, board.D9)
# For Feather M4 Express
# audio = audiobusio.I2SOut(board.D1, board.D10, board.D11)
# For Metro M4 Express
# audio = audiobusio.I2SOut(board.D3, board.D9, board.D8)
sine_wave_sample = audioio.RawSample(sine_wave)

while True:
    audio.play(sine_wave_sample, loop=True)
    time.sleep(1)
    audio.stop()
    time.sleep(1)

For Feather M0 Express, ItsyBitsy M0 Express and Metro M0 Express, no changes are needed for the code to work.

For Feather M4 Express, comment out audio = audiobusio.I2SOut(board.D1, board.D0, board.D9) and uncomment # audio = audiobusio.I2SOut(board.D1, board.D10, board.D11).

For Metro M4 Express, comment out audio = audiobusio.I2SOut(board.D1, board.D0, board.D9) and uncomment # audio = audiobusio.I2SOut(board.D3, board.D3, board.D8).

Now you'll hear one second of a 440Hz tone, and one second of silence. Remember, listen for it without headphones on your ears first as the volume is quite high.

You can try changing the Hz of the tone to produce different tones. Try changing the number of seconds in time.sleep() to produce longer or shorter tones.

Wave File

The second example plays a wave file. We open the file in a readable format. Then inside the loop, we play the file and tell the code to continue playing the file until it's completed. You can use any supported wave file. We've included the wave file used in the code.

import audioio
import board
import audiobusio

wave_file = open("StreetChicken.wav", "rb")
wave = audioio.WaveFile(wave_file)

# For Feather M0 Express, ItsyBitsy M0 Express, Metro M0 Express
audio = audiobusio.I2SOut(board.D1, board.D0, board.D9)
# For Feather M4 Express
# audio = audiobusio.I2SOut(board.D1, board.D10, board.D11)
# For Metro M4 Express
# audio = audiobusio.I2SOut(board.D3, board.D9, board.D8)

while True:
    audio.play(wave)
    while audio.playing:
        pass

The object setup in the code is the same as above.

For Feather M0 Express, ItsyBitsy M0 Express and Metro M0 Express, no changes are needed for the code to work.

For Feather M4 Express, comment out audio = audiobusio.I2SOut(board.D1, board.D0, board.D9) and uncomment # audio = audiobusio.I2SOut(board.D1, board.D10, board.D11).

For Metro M4 Express, comment out audio = audiobusio.I2SOut(board.D1, board.D0, board.D9) and uncomment # audio = audiobusio.I2SOut(board.D3, board.D3, board.D8).

Now you'll hear the wave file play through and loop. Remember, listen for it without headphones on your ears first as the volume is quite high.

There's plenty you can do with this example. Try playing a different wave file, or, instead of including while audio.playing: pass, include a time.sleep() to have it play for a specified number of seconds. Check out the Audio Out page in the CircuitPython Essentials guide for pause and resume features.

Where's my I2S?

We mentioned earlier that the supported M0 boards have multiple I2S pin combinations available to you. The M4 boards have one option. Either way, if you'd like to know what options are available to you, copy the following code into your code.py, connect to the serial console, and check out the output.

These are the results from the ItsyBitsy M0 Express.

import board
import audiobusio
from microcontroller import Pin


def is_hardware_i2s(bit_clock, word_select, data):
    try:
        p = audiobusio.I2SOut(bit_clock, word_select, data)
        p.deinit()
        return True
    except ValueError:
        return False


def get_unique_pins():
    exclude = ['NEOPIXEL', 'APA102_MOSI', 'APA102_SCK']
    pins = [pin for pin in [
        getattr(board, p) for p in dir(board) if p not in exclude]
            if isinstance(pin, Pin)]
    unique = []
    for p in pins:
        if p not in unique:
            unique.append(p)
    return unique


for bit_clock_pin in get_unique_pins():
    for word_select_pin in get_unique_pins():
        for data_pin in get_unique_pins():
            if bit_clock_pin is word_select_pin or bit_clock_pin is data_pin or word_select_pin\
                    is data_pin:
                continue
            else:
                if is_hardware_i2s(bit_clock_pin, word_select_pin, data_pin):
                    print("Bit clock pin:", bit_clock_pin, "\t Word select pin:", word_select_pin,
                          "\t Data pin:", data_pin)
                else:
                    pass
This guide was first published on Nov 21, 2017. It was last updated on Nov 21, 2017. This page (CircuitPython Wiring & Test) was last updated on Nov 17, 2019.