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
}