<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.squirrelslair.ca/index.php?action=history&amp;feed=atom&amp;title=Raspberry_Pi_Pico_%28RP2040%29_I2S_WAV_Sound_Player</id>
	<title>Raspberry Pi Pico (RP2040) I2S WAV Sound Player - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.squirrelslair.ca/index.php?action=history&amp;feed=atom&amp;title=Raspberry_Pi_Pico_%28RP2040%29_I2S_WAV_Sound_Player"/>
	<link rel="alternate" type="text/html" href="https://wiki.squirrelslair.ca/index.php?title=Raspberry_Pi_Pico_(RP2040)_I2S_WAV_Sound_Player&amp;action=history"/>
	<updated>2026-04-30T04:32:27Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://wiki.squirrelslair.ca/index.php?title=Raspberry_Pi_Pico_(RP2040)_I2S_WAV_Sound_Player&amp;diff=3449&amp;oldid=prev</id>
		<title>Hal: Created page with &quot;{{TidBit |shortDescription=Play WAV files over I2S using a Raspberry Pi Pico (RP2040) and MAX98357A |skillSet=Arduino; Electronics; Python; Raspberry Pi |featured=Yes }} The Raspberry Pi Pico is a very capable device but it doesn&#039;t have an I2S bus. That&#039;s where its PIO capabilities come in handy. There don&#039;t seem to be as much information out there for PIO in MicroPython but it wasn&#039;t hard to adapt it from the C/C++ examples.    Learned a lot doing this - got a basic gra...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.squirrelslair.ca/index.php?title=Raspberry_Pi_Pico_(RP2040)_I2S_WAV_Sound_Player&amp;diff=3449&amp;oldid=prev"/>
		<updated>2022-02-01T23:28:32Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;{{TidBit |shortDescription=Play WAV files over I2S using a Raspberry Pi Pico (RP2040) and MAX98357A |skillSet=Arduino; Electronics; Python; Raspberry Pi |featured=Yes }} The Raspberry Pi Pico is a very capable device but it doesn&amp;#039;t have an I2S bus. That&amp;#039;s where its PIO capabilities come in handy. There don&amp;#039;t seem to be as much information out there for PIO in MicroPython but it wasn&amp;#039;t hard to adapt it from the C/C++ examples.    Learned a lot doing this - got a basic gra...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{TidBit&lt;br /&gt;
|shortDescription=Play WAV files over I2S using a Raspberry Pi Pico (RP2040) and MAX98357A&lt;br /&gt;
|skillSet=Arduino; Electronics; Python; Raspberry Pi&lt;br /&gt;
|featured=Yes&lt;br /&gt;
}}&lt;br /&gt;
The Raspberry Pi Pico is a very capable device but it doesn&amp;#039;t have an I2S bus. That&amp;#039;s where its PIO capabilities come in handy. There don&amp;#039;t seem to be as much information out there for PIO in MicroPython but it wasn&amp;#039;t hard to adapt it from the C/C++ examples.&lt;br /&gt;
&lt;br /&gt;
Learned a lot doing this - got a basic grasp of the PIO and its instruction set and how sideset works.&lt;br /&gt;
&lt;br /&gt;
[[File:20220201 171620.jpg|alt=Not much to it|300px|Not much to it]]&lt;br /&gt;
&lt;br /&gt;
This program will load a small WAV file (&amp;lt;50k) from the Pico&amp;#039;s flash into memory, then play it through a PIO block that&amp;#039;s acting as an I2S interface, to a generic MAX98357A mono output board.&lt;br /&gt;
&lt;br /&gt;
Requirements:&lt;br /&gt;
* MicroPython (tested with v1.17 and 1.18)&lt;br /&gt;
* Raspberry Pi Pico (or other RP2040 board) with enough free flash space &lt;br /&gt;
* Three available GPIO pins (the program below uses GP15-17)&lt;br /&gt;
* MAX98357A board&lt;br /&gt;
* Speaker **DO NOT USE HEADPHONES, SEE PROGRAM COMMENTS FOR WARNING**&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
# SL-pico-play-i2s.py&lt;br /&gt;
#&lt;br /&gt;
# Written by the Squirrel&amp;#039;s Lair on 2022-02-01&lt;br /&gt;
#&lt;br /&gt;
# Uses Raspberry Pi Pico (RP2040) and a generic MAX98357A mono output&lt;br /&gt;
# board to play short WAV files saved on the Pico&amp;#039;s internal flash.&lt;br /&gt;
#&lt;br /&gt;
# Currently limited to amount of available heap space but should be&lt;br /&gt;
# able to use other core to help load larger files.&lt;br /&gt;
#&lt;br /&gt;
# Tested with signed 16-bit PCM mono files @ 16kHz.&lt;br /&gt;
# Works with higher sample rates but heap space becomes a problem.&lt;br /&gt;
#&lt;br /&gt;
# Adapted from the Raspberry Pi Pico pico-extras C/C++ library:&lt;br /&gt;
# https://github.com/raspberrypi/pico-extras/blob/master/src/rp2_common/pico_audio_i2s/audio_i2s.pio&lt;br /&gt;
#&lt;br /&gt;
# Additional information from the Raspberry Pi Pico C/C++ SDK:&lt;br /&gt;
# https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf&lt;br /&gt;
#&lt;br /&gt;
# and the Raspberry Pi Pi Python SDK:&lt;br /&gt;
# https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-python-sdk.pdf&lt;br /&gt;
#&lt;br /&gt;
# and the RP2040 Datasheet:&lt;br /&gt;
# https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf&lt;br /&gt;
#&lt;br /&gt;
# and the Maxim MAX98357 datasheet:&lt;br /&gt;
# https://datasheets.maximintegrated.com/en/ds/MAX98357A-MAX98357B.pdf&lt;br /&gt;
#&lt;br /&gt;
# and WAV file documentation from FILEFORMAT:&lt;br /&gt;
# https://docs.fileformat.com/audio/wav/&lt;br /&gt;
#&lt;br /&gt;
# and Wikipedia:&lt;br /&gt;
# https://en.wikipedia.org/wiki/WAV&lt;br /&gt;
#&lt;br /&gt;
# MAX98357 supports sample rates of:&lt;br /&gt;
# 8, 16, 32, 44.1, 48, 88.2, and 96kHz&lt;br /&gt;
# 8kHz has additional timing requirements, so avoiding it for now&lt;br /&gt;
#&lt;br /&gt;
# MAX98357A DOES NOT SUPPORT LJM&lt;br /&gt;
#&lt;br /&gt;
# Also, BCLK must be 32, 48, or 64x the rate of LRCLK&lt;br /&gt;
# BCLK minimum is 0.2432MHz, max is 25.804MHz&lt;br /&gt;
#&lt;br /&gt;
# The frequency for BCLK is calculated by:&lt;br /&gt;
# sample rate * bits/channel * number of channels&lt;br /&gt;
#&lt;br /&gt;
# So, starting with, let&amp;#039;s try:&lt;br /&gt;
# Mono (L/2 + R/2), 16-bit, 16kHz&lt;br /&gt;
# For that setup, BCLK must run at 16kHz*16*2 = 512kHz, so need&lt;br /&gt;
# PIO clock set to 1.024MHz&lt;br /&gt;
#&lt;br /&gt;
# WAV files:&lt;br /&gt;
# -if RIFF (most of them), they&amp;#039;re little-endian. Who knew?&lt;br /&gt;
# -if RIFX, they&amp;#039;re big-endian&lt;br /&gt;
#&lt;br /&gt;
# *****WARNING*****&lt;br /&gt;
# MAX98357 boards (like many others) can put out a surprising amount of&lt;br /&gt;
# sound - more than enough to damage your hearing if you&amp;#039;re not careful.&lt;br /&gt;
# Sudden, unexpected, and VERY LOUD sounds can come out of them when&lt;br /&gt;
# you&amp;#039;re working with software that&amp;#039;s not robust or fully tested (like&lt;br /&gt;
# this software, for example).&lt;br /&gt;
&lt;br /&gt;
import time&lt;br /&gt;
from machine import Pin&lt;br /&gt;
import machine&lt;br /&gt;
import rp2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@rp2.asm_pio(autopull=True, pull_thresh=32, out_shiftdir=rp2.PIO.SHIFT_LEFT, out_init=(rp2.PIO.OUT_LOW), sideset_init=(rp2.PIO.OUT_HIGH, rp2.PIO.OUT_LOW))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def i2s_interface():&lt;br /&gt;
    &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
    # LRCLK FREQUENCY: 16kHz&lt;br /&gt;
    # BCLK FREQUENCY: 512kHz&lt;br /&gt;
    # SYS FREQUENCY: 1024kHz&lt;br /&gt;
    # DATA is on GP15 (pins)&lt;br /&gt;
    # LRCLK is on GP16 (sideset)&lt;br /&gt;
    # BCLK is on GP17 (sideset)&lt;br /&gt;
    &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
    set(x, 14)        .side(0b11) # sideset bits are LRCLK and BCLK&lt;br /&gt;
&lt;br /&gt;
    label(&amp;quot;loop_left&amp;quot;)&lt;br /&gt;
    out(pins, 1)                      .side(0b10)&lt;br /&gt;
    jmp(x_dec, &amp;quot;loop_left&amp;quot;)    .side(0b11)&lt;br /&gt;
    out(pins, 1)                      .side(0b00)&lt;br /&gt;
    &lt;br /&gt;
    set(x, 14)                          .side(0b01)&lt;br /&gt;
&lt;br /&gt;
    label(&amp;quot;loop_right&amp;quot;)&lt;br /&gt;
    out(pins, 1)                      .side(0b00)&lt;br /&gt;
    jmp(x_dec, &amp;quot;loop_right&amp;quot;)  .side(0b01)&lt;br /&gt;
    out(pins, 1)                      .side(0b10)&lt;br /&gt;
&lt;br /&gt;
# State machine instantiation&lt;br /&gt;
sm = rp2.StateMachine(0, i2s_interface, freq=1024000, sideset_base=Pin(16), out_base=Pin(15))&lt;br /&gt;
&lt;br /&gt;
sm.active(1) # Turn on the state machine&lt;br /&gt;
&lt;br /&gt;
filename = &amp;quot;FILENAME.wav&amp;quot; # File to read from the internal flash&lt;br /&gt;
file = open(filename, &amp;quot;rb&amp;quot;)&lt;br /&gt;
wav_data = file.read()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
    for i in range(0, len(wav_data), 2): # Go through 2 bytes at a time&lt;br /&gt;
        word_out = (wav_data[i+1]&amp;lt;&amp;lt;8) | (wav_data[i]) # Change to big-endian&lt;br /&gt;
        sm.put(word_out) # Send the data to the state machine for output&lt;br /&gt;
&lt;br /&gt;
    time.sleep(2)&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Hal</name></author>
	</entry>
</feed>