Skip to content
Snippets Groups Projects
Name Last commit Last update
img
rp2040-USB-I2S-speaker
README.md

USB I2S Speaker

This code implements a USB speaker streaming audio to an I2S device, based on Phil Schatzmann's port of the TinyUSB Audio class for the rp2040.

An example board is available on How to Make (Almost) Anything's website (hello.MAX98357A.RP2040): https://academy.cba.mit.edu/classes/output_devices/

Dependencies

This code uses the Arduino pico core, and two libraries:

  • Adafruit TinyUSB: this is the version modified by Phil Schatzmann to handle the Audio class on the rp2040.
  • I2S: Arduino's standard I2S library.

Code

#include <Adafruit_TinyUSB.h>
#include <I2S.h>

#define I2S_CLK 1
#define I2S_FRAME (I2S_CLK+1)
#define I2S_DATA 4
#define SAMPLE_RATE 44100
#define SAMPLE_BITS 16

Adafruit_USBD_Audio usb;

I2S i2s(OUTPUT);

size_t writeCB(const uint8_t* data, size_t len, Adafruit_USBD_Audio& ref) {
  int16_t* data16 = (int16_t*)data;

  size_t n_written = i2s.write(data, len);

  // returns the amount written (and convert to bytes)
  return n_written * 2 *  sizeof(int16_t);
}

void setup() {
  // init USB
  if (!TinyUSBDevice.isInitialized()) {
    TinyUSBDevice.begin(0);
  }

  Serial.begin(115200);

  // reconfigure USB
  usb.setWriteCallback(writeCB);
  usb.begin(SAMPLE_RATE, 2, SAMPLE_BITS);
  if (TinyUSBDevice.mounted()) {
    TinyUSBDevice.detach();
    delay(10);
    TinyUSBDevice.attach();
  }

  // start I2S
  i2s.setBCLK(I2S_CLK);
  i2s.setDATA(I2S_DATA);
  i2s.setBitsPerSample(SAMPLE_BITS);
  i2s.begin(SAMPLE_RATE);
}

void loop() {
  #ifdef TINYUSB_NEED_POLLING_TASK
  TinyUSBDevice.task();
  #endif
}