XIAO ESP32C3 and I2S. How to?

I have many ESP32 variants and have been able to get I2S working on all of them but I can’t seem to get it working on the XIAO ESP32C3.
I’ve tried different I/O pins since reading about the multiplexed pins but… nothing so far.
Has anyone been able to get I2S working on the XIAO ESP32C3 ??

As confirmed by our engineer, Xiao ESP32C3 does not have I2S pins for direct use. We apologize for the inconvenience. We will also update the Wiki as soon as possible.

GPIO 25 & 26 do not exist on the Seeed Studio ESP32-C3, I want to connect an iis sound card to the ESP32-C3, apparently the IIS is supported but I’ve found no documentation or pinouts for it

https://files.seeedstudio.com/wiki/XIAO_WiFi/Resources/XIAO-ESP32C3-pinout_sheet.xlsx

i dont know much about it… but apparently according to this document
the ESP32C3 internal chip pins 25 & 26 are connected on the board to GPIO 18 & 19 which is USB D- and USB D+

so i think you have to use the usb cable connected to these pins to access IIS
seems like i read something about this somewhere else i will try to see if i can find a reference

I‘m sorry to tell you that Xiao ESP32C3 does not have I2S pins for direct use.

Yes,that was my initial thoughts when examining the pinout and to say it’s on the usb c pinout is not really practical. I have seem some coding examples where the spi pins have been assigned to i2s support, it wouldn’t take long to breadboard my design with a dac card to test it I guess and I will report back.

1 Like

this should not be true… the product data for the S3 and C3
interface is 1xIIS

the data is incorrect or their must be a way to assign IIS to the IIC ports or some other way

https://espressif-docs.readthedocs-hosted.com/projects/arduino-esp32/en/latest/api/i2s.html

apparently

I do not have I2S hardware to test
but check this link… some data copied below

The I²S bus consists of at least three lines:

Note

All lines can be attached to almost any pin and this change can occur even during operation.

  • Bit clock line
    • Officially “continuous serial clock (SCK)”. Typically written “bit clock (BCLK)”.
    • In this library function parameter sckPin or constant PIN_I2S_SCK.
  • Word clock line
    • Officially “word select (WS)”. Typically called “left-right clock (LRCLK)” or “frame sync (FS)”.
    • 0 = Left channel, 1 = Right channel
    • In this library function parameter fsPin or constant PIN_I2S_FS.
  • Data line
    • Officially “serial data (SD)”, but can be called SDATA, SDIN, SDOUT, DACDAT, ADCDAT, etc.
    • Unlike Arduino I2S with single data pin switching between input and output, in ESP core driver use separate data line for input and output.
    • For backward compatibility, the shared data pin is sdPin or constant PIN_I2S_SD when using simplex mode.
    • When using in duplex mode, there are two data lines:
      • Output data line is called outSdPin for function parameter, or constant PIN_I2S_SD_OUT
      • Input data line is called inSdPin for function parameter, or constant PIN_I2S_SD_IN

Pin setup

Pins can be changed in two ways- 1st constants, 2nd functions.

Note

Shared data pin can be equal to any other data pin, but must not be equal to clock pin nor frame sync pin! Input and Output pins must not be equal, but one of them can be equal to shared data pin!

sckPin != fsPin != outSdPin != inSdPin

Copy to clipboard

sckPin != fsPin != sdPin

Copy to clipboard

By default, the pin numbers are defined in constants in the header file. You can redefine any of those constants before including I2S.h. This way the driver will use these new default values and you will not need to specify pins in your code. The constants and their default values are:

  • PIN_I2S_SCK 14
  • PIN_I2S_FS 25
  • PIN_I2S_SD 26
  • PIN_I2S_SD_OUT 26
  • PIN_I2S_SD_IN 35

The second option to change pins is using the following functions. These functions can be called on either on initialized or uninitialized object.

setAllPins

Set all pins using given values in parameters. This is simply a wrapper of four functions mentioned above.

int setAllPins(int sckPin, int fsPin, int sdPin, int outSdPin, int inSdPin)

Copy to clipboard

Set all pins to default i.e. take values from constants mentioned above. This simply calls the the function with the following constants.

  • PIN_I2S_SCK 14
  • PIN_I2S_FS 25
  • PIN_I2S_SD 26
  • PIN_I2S_SD_OUT 26
  • PIN_I2S_SD_IN 35

int setAllPins()

I got this reply from Seeed after questioning about i2s support…

Hello.
Thank you for your feedback, this is an error and we will remove the description about IIS immediately.

Regards!

EICO
Seeed Technical Support Team


This seems a little strange as a guy on another forum is running i2s on pins 2,3,4,5 to a sound card and recording audio from it.

Hi, just to let you know, despite the comments on here I have this very device working with a PCM5102A using I2S. I set it up as an internet radio but it doesn’t really have the power and the sound is a bit choppy. I think I have it working at 22khz as I’m guessing that is what is coming from the radio station stream but it may be ok at lower speeds. I found your question by accident while I was trying to find I2S details for the Seeed XIAO ESP32S3 which I’m hoping will be more capable. Anyway, below is a program that I’m using for testing and also some notes on connection.

/*
 * Seeed_esp32-radio
 * esp32-c3 is too slow - chops up output - reduce sample rate?
 * esp32-s3 ???
 */
#include "Arduino.h"   
#include "WiFi.h"
#include "Audio.h"

#define I2S_DOUT      4 // 26  // connect to DAC pin DIN
#define I2S_BCLK      3 // 27  // connect to DAC pin BCK
#define I2S_LRC       2 // 25  // connect to DAC pin LCK

Audio audio;

const char* ssid =     "Your-SSID";
const char* password = "Your Network Password";

void setup() {
    Serial.begin(115200);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
      Serial.println("Waiting for network ...");
      delay(1500);
    }
    Serial.println("Connected.");
    
    audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
    audio.connecttohost("http://s1.knixx.fm/dein_webradio_64.aac"); // 64 kbp/s aac+
}

void loop() {
    audio.loop();
}

// optional
void audio_info(const char *info){
    Serial.print("info        "); Serial.println(info);
}
void audio_id3data(const char *info){  //id3 metadata
    Serial.print("id3data     ");Serial.println(info);
}
void audio_eof_mp3(const char *info){  //end of file
    Serial.print("eof_mp3     ");Serial.println(info);
}
void audio_showstation(const char *info){
    Serial.print("station     ");Serial.println(info);
}
void audio_showstreaminfo(const char *info){
    Serial.print("streaminfo  ");Serial.println(info);
}
void audio_showstreamtitle(const char *info){
    Serial.print("streamtitle ");Serial.println(info);
}
void audio_bitrate(const char *info){
    Serial.print("bitrate     ");Serial.println(info);
}
void audio_commercial(const char *info){  //duration in sec
    Serial.print("commercial  ");Serial.println(info);
}
void audio_icyurl(const char *info){  //homepage
    Serial.print("icyurl      ");Serial.println(info);
}
void audio_lasthost(const char *info){  //stream URL played
    Serial.print("lasthost    ");Serial.println(info);
}
void audio_eof_speech(const char *info){
    Serial.print("eof_speech  ");Serial.println(info);
}

PCM5102A connections:

VCC > 3.3v
3.3V > 3.3v
GND > GND
FLT > GND
DMP > GND
SCL > GND
BCK > D1
DIN > D2
LCK > D0
FMT > GND
XMT > 3.3v

I was puzzled by the pin allocations in the code but I think the pins are assigned by Seeed’s implementation. If you look at the pin diagram on the Pimoroni website you’ll see the IIS pins are clearly shown. This link:

Hope this is of help.

Thank you for that, I will configure my sound card accordingly and report back. It’s a pcm1502, I have also ordered some uda1334a boards as well.

I think you have missed BCK so the connections are not correct. Maybe SCL should be GND or +3.3v

Correct. Sorry about that. By the way, I looked at the github info for the audio library and it says it doesn’t work for single core devices (eg. esp32c3) but doesn’t say why. However, there is someone complaining about choppy audio and the answer seems to be that the tcp end of things is unable to fill the audio buffers fast enough. I intend to try it out as an mp3 player with an SD card to see if it can cope with that but I haven’t had time yet. Trying to get the esp32s3 to work at the moment. Let me know how you get on.

I have SCL connected to GND, BCK connected to D1. I’ll amend my original entry for anyone following this.

Thanks, I have SCL to ground, but I’m having a conflict with audio.h, I use the Teensy Library and I think that its picking up the audio.h from that. But I notice these are local libraries “audio.h” suggests its located in the same folder as your build

Hi.
I’m using this audio library:
https://github.com/schreibfaul1/ESP32-audioI2S

Also, I have tested the same code on the Seeed XIAO esp32-s3 and it works very well (not a single glitch on a 44khz stream) though instead of D0,D1,D2 its D1,D2,D3. They seem to be hard-wired on this board also.

By the way, I had problems with the url for the boards in the “Getting started” info - it didn’t seem to have the right entries so I stuck with this one:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json
from previous installation work I’d done (note the “dev” bit).

Hope it works out for you.

I’m sorry to tell you that you are wrong. Please look through the rest of this thread and then perhaps get your technical expert to review it.

Best wishes.

Hi im really struggling to get the dac working at all would you mind writing some really basic esp32s3 code that plays a sine wave to the i2s dac

Hi there, So check these out. :wink: :ok_hand:

Application Notes

Espressif has their usual excellent documentation for I2S on the ESP32, it can link you to more information.

How to Prevent Data Lost

For applications that need a high frequency sample rate, the massive data throughput may cause data lost. Users can receive data lost event by registering the ISR callback function to receive the event queue:

also these guys have a good thread on the subject.https://dronebotworkshop.com/esp32-i2s/

HTH
GL :slight_smile: PJ

the reason i asked here is because the person I asked specifically got working code with the xiao esp23s3 and I was wondering how because I cannot. the docs cant seem to help me D:

Hi. Compiled this code again yesterday and it works fine for me. I am using a PCM5102 i2s board rather than the MAX …

/*
 * seeed_esp32_tone2 (SimpleTone from I2S library)
 This example generates a square wave based tone at a specified frequency
 and sample rate. Then outputs the data using the I2S interface to a
 MAX08357 I2S Amp Breakout board.

 I2S Circuit:
 * Arduino/Genuino Zero, MKR family and Nano 33 IoT
 * MAX08357:
   * GND connected GND
   * VIN connected 5V
   * LRC connected to pin 0 (Zero) or 3 (MKR), A2 (Nano) or 25 (ESP32)
   * BCLK connected to pin 1 (Zero) or 2 (MKR), A3 (Nano) or 5 (ESP32)
   * DIN connected to pin 9 (Zero) or A6 (MKR), 4 (Nano) or 26 (ESP32)

 DAC Circuit:
 * ESP32 or ESP32-S2
 * Audio amplifier
   - Note:
     - ESP32 has DAC on GPIO pins 25 and 26.
     - ESP32-S2 has DAC on GPIO pins 17 and 18.
  - Connect speaker(s) or headphones.

 created 17 November 2016
 by Sandeep Mistry
 For ESP extended
 Tomas Pilny
 2nd September 2021
 */
//  These pins work for XIAO esp32c3 and esp32s3
 
#define PIN_I2S_FS      2  //LCK - Word Select
#define PIN_I2S_SCK     3  //BCK - Bit Clock
#define PIN_I2S_SD_OUT  4  //DIN - Data stream
#define PIN_I2S_SD      4

#include <I2S.h>

const int frequency = 440; // frequency of square wave in Hz
const int amplitude = 500; // amplitude of square wave
const int sampleRate = 8000; // sample rate in Hz
const int bps = 16;

const int halfWavelength = (sampleRate / frequency); // half wavelength of square wave

short sample = amplitude; // current sample value
int32_t rightleft;  // sample right and left channels
int count = 0;

i2s_mode_t mode = I2S_PHILIPS_MODE; // I2S decoder is needed
// i2s_mode_t mode = ADC_DAC_MODE; // Audio amplifier is needed

// Mono channel input
// This is ESP specific implementation -
//   samples will be automatically copied to both channels inside I2S driver
//   If you want to have true mono output use I2S_PHILIPS_MODE and interlay
//   second channel with 0-value samples.
//   The order of channels is RIGHT followed by LEFT
//i2s_mode_t mode = I2S_RIGHT_JUSTIFIED_MODE; // I2S decoder is needed

void setup() {
  Serial.begin(115200);
  delay(5000);
  Serial.println("I2S simple tone");
  Serial.println(__DATE__);
  Serial.println(__TIME__);
  Serial.println(__FILE__);
  Serial.println(PIN_I2S_FS);   //     D0  gpio02 //LCK - Word Select
  Serial.println(PIN_I2S_SCK);  //     D1  gpio03 //BCK - Bit Clock
  Serial.println(PIN_I2S_SD_OUT);  //  D2  gpio04 //DIN - Data stream
  Serial.println(PIN_I2S_SD);   //     D2
  Serial.println(sizeof(short)); //  check the num of bits in short integer.

  // start I2S at the sample rate with 16-bits per sample
  
  I2S.setAllPins(PIN_I2S_SCK, PIN_I2S_FS, PIN_I2S_SD, PIN_I2S_SD_OUT, -1);
  if (!I2S.begin(mode, sampleRate, bps)) {
    Serial.println("Failed to initialize I2S!");
    while (1); // do nothing
  }

  Serial.println("Starting tone generation");
}

void loop() {
    if (count % halfWavelength == 0 ) {
      // invert the sample every half wavelength count multiple to generate square wave
      sample = -1 * sample;
    }

    if(mode == I2S_PHILIPS_MODE || mode == ADC_DAC_MODE){ // write the same sample twice, once for Right and once for Left channel
      rightleft = sample;           // right channel
      rightleft = rightleft << 16;
      rightleft += sample;          // left channel
      I2S.write(rightleft);
    }

    // increment the counter for the next sample
    count++;
}