Teensy 3.6 I2S input without board

Status
Not open for further replies.
I can't find i2s.h library in teensiduino. I took the file from here, and running your code I get the same output on initialization but then only '0 0'.

I tries Teenfor3 suggestion also, nothing.

Perhaps the mics are malfunction after all, although I just bought them and there are 4 so it's really weird.

seems that I'm also getting this 0 0 as output issue and it seems like it was solved with wiring but I've check, double-checked and fiddled for a while now with no luck.

of course...the issue could be that I'm using a different MEMS mic - the SPH0641 with PDM output which is connected to an ADAU7002 to convert to I2S which is then connected to my Teensy 3.6 on pins 11, 12, 13 for BCLK, LRCLK, and SD respectively (also tried pins 9, 23, 13).

Any thoughts re troubleshooting?
 
Test with the latest beta. Recently the I2S was changed to improve compatibility with these chips, which expect a ratio of 64 between BCLK and LRCLK. The audio lib in 1.37 and earlier used a ratio of 32. You need 1.38-beta2 or newer (or the audio lib pulled from github) to get the 64 ratio this chip requires.

To check which version you have, in Arduino click Help > About. Or on Macintosh, Arduino > About.
 
thanks Paul, just updated everything but no luck... getting the same serial print:
Code:
Pin configuration: 11
Initializing.
Initialized I2C Codec
Initialized I2S RX without DMA
Started I2S RX
0  0
0  0
0  0
0  0
0  0
0  0
...

though occasionally I'll get this below which leads me to believe that the Rx callback is not letting the setup function complete:
Code:
Initialized I2S RX with0  0
0  0
0  0
...
(missing the prior initialize prints as well as "out DMA \n" on line 1)


I'm using the same bit of code onehorse provided earlier without the Tx parts (and on a Teensy 3.6):
Code:
/*
  was:
  I2S digital audio demonstrator for Teensy 3.0
  Interfaces using Wolfson WM8731 codec.

  now: experimental code for prototype development nixie, teensy 3.1 <> INMP 441
*/

/*
pins:       
Rx pin 11 : I2S0_RX_BCLK  <--> "CLK", Output
Rx pin 12 : I2S0_RX_FS    <--> originally to WS, but due to board error: "SD" on affected boards, output
Rx pin 13 : RX pin        <--> originally to SD, but due to board error: "WS" on affected boards, input
*/

// aim at 48kHz sampling rate
#define CLOCK_TYPE                  (I2S_CLOCK_48K_INTERNAL)

#include <Wire.h>
/* I2S digital audio */
#include <i2s.h>

/* Circular buffer for audio samples, interleaved left & right channel */
/*const uint16_t buffersize = DMA_BUFFER_SIZE; // must be a multiple of DMA_BUFFER_SIZE
volatile int16_t buffer[buffersize];
uint16_t nTX = 0;
uint16_t nRX = 0;*/

// allocate 32kB of data buffer
const uint16_t buffersize = 1024; // 2048;
volatile int32_t buffer[buffersize];
uint32_t nRX = 0;

// added during debugging, neccessary?
uint32_t counter = 0;


/* --------------------- Direct I2S Receive, we get callback to read 2 words from the FIFO ----- */

void i2s_rx_callback( int32_t *pBuf )
{
  // Read the data
  buffer[nRX++] = pBuf[0];
  buffer[nRX++] = pBuf[1];
   
  if( nRX>=buffersize ) {
    nRX=0;
    counter++;
  }
}


/* ----------------------- begin -------------------- */
void setup()
{
  // << nothing before the first delay will be printed to the serial
  Serial.begin(9600);
  delay(1000);  

  Serial.print("Pin configuration: ");
  Serial.println( I2S_PIN_PATTERN , HEX );
  Serial.println( "Initializing." );

  delay(100);
  Serial.println( "Initialized I2C Codec" );
  
  delay(100);
  I2SRx0.begin( CLOCK_TYPE, i2s_rx_callback );
  Serial.println( "Initialized I2S RX without DMA" );

  // Before starting tx/rx, set the buffer pointers
  nRX = 0;
  
  // fill the buffer with something to see if the RX callback is activated at all
  buffer[0] = 0x42424242;
    
  // enable I2S RX
  I2SRx0.start();
  Serial.println( "Started I2S RX" );

  // quick check how often the callback will be called, we expect 48000 times per second
  // but: this is no gurantee for correct output clocks / presence of input data (!)
  // counter = 0;
  // delay(1000);
  // Serial.println(counter * buffersize / 2);
}


/* --------------------- main loop ------------------ */
void loop()
{
  delay(1000);
  Serial.print(buffer[0], HEX);
  Serial.print("  ");
  Serial.print(buffer[1], HEX);

  Serial.print("\r\n");
}


Checked the MK66FX1M0 manual for some helpful info re pins on the Teensy 3.6:
I2S0_RX_BCLK: [pin 11 (alt 4), pin 36/A17 (alt 4), pin 26 (alt 6)]
I2S0_RX_FS: [pin 28 (alt 6), pin 12 (alt 4), pin 37/A18 (alt 4)]
I2S0_RXD0: [pin 27 (alt 6), pin 13 (alt 4)]
I2S0_RXD1: [pin 28 (alt 7), pin 38/A19 (alt 4)]

I do see how pins 11, 12, and 13 could be used but I'm thinking to try using different I2S0_RX_BCLK, I2S_RX_FS, and I2S0_RXD0 pin options since the Teensy 3.6 has multiple. It seems that the I2S library is targeting the 3.0/3.1 mk20dx128 chip? See line 28.

Getting a little over my head, but perhaps I can change the pin configuration in the I2S library at the I2S.cpp file? I can see how the pins and alt/mux is being set at line 211. thoughts?
 
Last edited:
Please keep in mind that the Audio I2S library (input/output_I2S) is using
Code:
	// configure pin mux for 3 clock signals
	CORE_PIN23_CONFIG = PORT_PCR_MUX(6); // pin 23, PTC2, I2S0_TX_FS (LRCLK)
	CORE_PIN9_CONFIG  = PORT_PCR_MUX(6); // pin  9, PTC3, I2S0_TX_BCLK
	CORE_PIN11_CONFIG = PORT_PCR_MUX(6); // pin 11, PTC6, I2S0_MCLK
That is, Bit and LRclock is set for tx, the rx path is slaved to tx.
changes pins only does no help, the rest of the program must also be adapted.

you can write your own i2s driver, where you can chose the pins you want, as long as they are allowed and available.
 
You should use the audio library I2S code as-is, with the documented pins. It really does work. I know you're stuck and looking for things to troubleshoot, but directing your efforts towards the I2S code is barking up the wrong tree. The Teensy Audio library is very mature and has been used by many thousands of people.

If you want to sanity check, look at the 3 clock signals. LRCLK should be 44.1 kHz. BCLK (with the latest betas) should be 2.8 MHz. MCLK should be 11.3 MHz. Remember, in master mode Teensy generates all the clocks. The RX pin is the only input. All the clocks are outputs from Teensy.

As a further sanity check, you can try shorting the RX pin (without your hardware connected) to GND and 3.3V. You should receive all zeros when it's grounded, and all -1. If printing as floats, remember -1 translates -0.00003, so make sure you're printing enough digits.

These simple tests can at least help you build confidence whether the I2S is actually working.
 
Last edited:
Agreed - must be something wrong w my wiring. Just gave it a go with a Teensy 3.1 and am getting the same results.. likely the tiny ADAU7002 (PDM to I2S converter) breakout I made. Will report back eventually. Thanks for the help!
 
Hello all,

After a long time without internet access I am back to this project.
But still not that much progress as would like...
For now have tested the onehorse code and worked ok, just using one mic as just need to record the landscape base sound to try to identify some birds species.
But the refresh is about 1 sample per second does it make sense to change this delay to have more samples and send then to the in build sd?
Paul have already download the latest Audio lib, tanks for the link, but the record example you have is for the audioboard and I would like to avoid extra hardware using the ICS43434, what changes should be done to have a simple recorder to test this mic performance?
Does anyone have used this mics with teensy as a audio recorder?
This is mics uses a much more complex way of code far from my knowledge.
Any help is appreciate.

Thanks,
Timóteo
 
Hello Paul,

Some time ago I have tested the recorder bu with some modification to record 1 minute files to be easier to analise.
But in that time I used theSGTL5000 and from a brief circuit analise I could conclude my connection and the SGTL5000 are diferent...
Have a protoboard fisicaly solder all my setup by this way I know the connections are solid:
SCK to pin 11
WS to pin 12
SD to pin 13
to my ICS43434
and the SGTL5000 uses this
MCLK to pin 11
BCLK to pin 9
LRCLK to pin 23
TX to pin 22
RX to pin 13
This I do understand now what is suposed to be connect where is a ???
after some search could understant that:
PIN13 in my setup is the same RX in the audioboard
PIN 11 SCK is the same as MCLK
WS is the same as the BCLK?
And the LRCLK is the same as the L/R that is tied to GND in my setup?
Can you please clarify me, another question I have is the sketch supposed to work with the ICS43434 without any modification besides the phisical connections?
Thanks

By the way as suspectd after tested the sketch it does not record any sound...
 
Last edited:
I can tell you what I do to get 32-bit data out of the ICS43432 I2S microphone using the Teensy 3.1/2, which is quite similar to the ICS43434. First, connect 3V3/GND and then bitclock goes to pin 11, word select to pin 12, and data out to pin 13.

This is the program I run, which depends on the i2s.h library in teensiduino:

Code:
/*
  was:
  I2S digital audio demonstrator for Teensy 3.0
  Interfaces using Wolfson WM8731 codec.

  now: experimental code for prototype development nixie, teensy 3.1 <> INMP 441
*/

/*
pins:       
Rx pin 11 : I2S0_RX_BCLK  <--> "CLK", Output
Rx pin 12 : I2S0_RX_FS    <--> originally to WS, but due to board error: "SD" on affected boards, output
Rx pin 13 : RX pin        <--> originally to SD, but due to board error: "WS" on affected boards, input
*/

// aim at 48kHz sampling rate
#define CLOCK_TYPE                  (I2S_CLOCK_48K_INTERNAL)

#include <Wire.h>
/* I2S digital audio */
#include <i2s.h>

/* Circular buffer for audio samples, interleaved left & right channel */
/*const uint16_t buffersize = DMA_BUFFER_SIZE; // must be a multiple of DMA_BUFFER_SIZE
volatile int16_t buffer[buffersize];
uint16_t nTX = 0;
uint16_t nRX = 0;*/

// allocate 32kB of data buffer
const uint16_t buffersize = 1024; // 2048;
volatile int32_t buffer[buffersize];
uint32_t nTX = 0;
uint32_t nRX = 0;

// added during debugging, neccessary?
uint32_t counter = 0;


/* --------------------- Direct I2S Receive, we get callback to read 2 words from the FIFO ----- */

void i2s_rx_callback( int32_t *pBuf )
{
  // Read the data
  buffer[nRX++] = pBuf[0];
  buffer[nRX++] = pBuf[1];
   
  if( nRX>=buffersize ) {
    nRX=0;
    counter++;
  }
}


/* --------------------- Direct I2S Transmit, we get callback to put 2 words into the FIFO ----- */

void i2s_tx_callback( int32_t *pBuf )
{
  // Send the data
  pBuf[0] = buffer[nTX++];
  pBuf[1] = buffer[nTX++];
  if( nTX>=buffersize ) nTX=0;
}

/* ----------------------- begin -------------------- */

void setup()
{
  // << nothing before the first delay will be printed to the serial
  Serial.begin(9600);
  delay(1500);  

  Serial.print("Pin configuration: ");
  Serial.println( I2S_PIN_PATTERN , HEX );
  Serial.println( "Initializing." );

  delay(100);
  Serial.println( "Initialized I2C Codec" );
  
  delay(100);
  I2SRx0.begin( CLOCK_TYPE, i2s_rx_callback );
  Serial.println( "Initialized I2S RX without DMA" );
  
  // I2STx0.begin( CLOCK_TYPE, i2s_tx_callback );
  // Serial.println( "Initialized I2S TX without DMA" );
  
  // Before starting tx/rx, set the buffer pointers
  nRX = 0;
  nTX = 0;
  
  // fill the buffer with something to see if the RX callback is activated at all
  buffer[0] = 0x42424242;
  
  //I2STx0.start();
  
  // enable I2S RX
  I2SRx0.start();
  Serial.println( "Started I2S RX" );

  // quick check how often the callback will be called, we expect 48000 times per second
  // but: this is no gurantee for correct output clocks / presence of input data (!)
  // counter = 0;
  // delay(1000);
  // Serial.println(counter * buffersize / 2);
}


/* --------------------- main loop ------------------ */
void loop()
{
  /* quick debug print */
  delay(1000);
  Serial.print(buffer[0], HEX);
  Serial.print("  ");
  Serial.print(buffer[1], HEX);
  
/* debugging: print RX counters for sec and sef FIFO errors
  Serial.print("   c:");
  Serial.print(I2SRx0.fec_counter);
  Serial.print("-");
  Serial.print(I2SRx0.sef_counter); */

  Serial.print("\r\n");
}

And this is the output I get:

Code:
Pin configuration: 11
Initializing.
Initialized I2C Codec
Initialized I2S RX without DMA
Started I2S RX
75C0  0
FFFBB800  0
FFFDDBC0  0
FFFEC600  0
FFFF3E00  0
14000  0
FFF98FC0  0
FFFF29C0  0
8600  0
FFFE4C00  0
FFE6BBC0  0
6E4000  0
42600  0
FFFDE7C0  0
59DC0  0
FFFF09C0  0
26FC0  0
FFFD1600  0

You can use serial.write instead of serial.print to write the data to the pc to play back using audacity.

How do I write the data to pc?
 
Hmm.. I can receive the serial data from teensy but what type of file do I save it in so that I can play back using audacity?
 
If you are watching the data on a terminal, save it to a text file eg "audiodata.txt", and import into Audacity as import.....raw data.....
You should see the waveform of the data.....does it look anything like the expected waveform...if so...play it........does it sound like as expected...???
You may need to parse it first in a spreadsheet to get rid of unwanted data....the column of zeros to the right......or...... only every other row if it is stereo....???
 
If you are watching the data on a terminal, save it to a text file eg "audiodata.txt", and import into Audacity as import.....raw data.....
You should see the waveform of the data.....does it look anything like the expected waveform...if so...play it........does it sound like as expected...???
You may need to parse it first in a spreadsheet to get rid of unwanted data....the column of zeros to the right......or...... only every other row if it is stereo....???

Hi, thanks for the reply. But the serial.write writes every second, but I need 48k samples per second to hear the audio? Must I modify the code in order to serial.write 48k samples per second?
 
Hi, thanks for the reply. But the serial.write writes every second, but I need 48k samples per second to hear the audio? Must I modify the code in order to serial.write 48k samples per second?
maybe you could look into

Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2S            i2s1;           //xy=346,91
AudioOutputUSB           usb1;           //xy=530,91
AudioConnection          patchCord1(i2s1, 0, usb1, 0);
AudioConnection          patchCord2(i2s1, 1, usb1, 1);
// GUItool: end automatically generated code

void c_myApp::setup()
{
   AudioMemory(8);
   
}

void c_myApp::loop()
{ 
}

and simply use audacity to listen to the audio
(you may have to speak somewhat loud into microphone)
 
cp061.......You haven't said what you are trying to do......you just posted earlier code originally posted by onehorse and wondered how to save the data to PC
If you see text on a screen you can capture it to a textfile and read it later.......but it is not Audio.......
If you want audio...you need to decide how to get audio in and how to get audio out......
Below is copy on PassthroAudio sketch for teensy audio library.....It is about a simple as you can get..... ADC in direct to teensy pin A2 and Audio out from teensy DAC pin
No other boards involved. But connect analogue mic or line in as described in the GUI tool...it gives 0,6 volt bias to make input all +ve instead of +/- ac.
And put 100 uf cap on output to amp speaker or to Linein on amp

Code:
/*
 * A simple hardware test which receives audio on the A2 analog pin
 * and sends it to the PWM (pin 3) output and DAC (A14 pin) output.
 *
 * This example code is in the public domain.
 */

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputAnalog         adc1;           //xy=161,80
AudioOutputAnalog        dac1;           //xy=329,47
//AudioOutputPWM           pwm1;           //xy=331,125
AudioConnection          patchCord1(adc1, dac1);
//AudioConnection          patchCord2(adc1, pwm1);
// GUItool: end automatically generated code

void setup() {
  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(12);
}

void loop() {
  // Do nothing here.  The Audio flows automatically

  // When AudioInputAnalog is running, analogRead() must NOT be used.
}
 
This line in last post.........
If you see text on a screen you can capture it to a textfile and read it later.......but it is not Audio.......

Should read.....as below.........
If you see text on a screen you can capture it to a textfile and read it later.......but it is NOT Audio.......

since posting this...I figured out I can edit apost.....so its now edited...
 
Hi.....WMXZ..........................

I thought I would try the USB audio....I hadn't tried it before......and I thought I would try the most basic setup, ADC in, and USB out only.

I didnt understand the c_myApp bit.......is that because you use a different compiler...????

I used the code below as generated by the GUI tools, in the standard Arduino 1.8.5 IDE with the standard setup and loop and your value for AudioMmemory (8).

I got the audio breaking up at intervals of about 1196 samples when recorded in Audacity.

I changed the memory to AudioMemory(20) an all is fine.....good clean sound

Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputAnalog         adc1;           //xy=137,212
AudioOutputUSB           usb1;           //xy=530,91
AudioConnection          patchCord1(adc1, 0, usb1, 0);
AudioConnection          patchCord2(adc1, 0, usb1, 1);
// GUItool: end automatically generated code


void setup() {
  // put your setup code here, to run once:
  AudioMemory(20);   // needs at least 20 memory
}

void loop() {
  // put your main code here, to run repeatedly:

}
 
I didnt understand the c_myApp bit.......is that because you use a different compiler...????
Sorry, the class was a cut and past error.
not sure if it needs really 20 buffers, but when it works...

the corrected code from post 41 is
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2S            i2s1;           //xy=346,91
AudioOutputUSB           usb1;           //xy=530,91
AudioConnection          patchCord1(i2s1, 0, usb1, 0);
AudioConnection          patchCord2(i2s1, 1, usb1, 1);
// GUItool: end automatically generated code

void setup()
{
   AudioMemory(8);
   
}

void loop()
{ 
}
 
Last edited:
cp061.......You haven't said what you are trying to do......you just posted earlier code originally posted by onehorse and wondered how to save the data to PC
If you see text on a screen you can capture it to a textfile and read it later.......but it is not Audio.......
If you want audio...you need to decide how to get audio in and how to get audio out......
Below is copy on PassthroAudio sketch for teensy audio library.....It is about a simple as you can get..... ADC in direct to teensy pin A2 and Audio out from teensy DAC pin
No other boards involved. But connect analogue mic or line in as described in the GUI tool...it gives 0,6 volt bias to make input all +ve instead of +/- ac.
And put 100 uf cap on output to amp speaker or to Linein on amp

Code:
/*
 * A simple hardware test which receives audio on the A2 analog pin
 * and sends it to the PWM (pin 3) output and DAC (A14 pin) output.
 *
 * This example code is in the public domain.
 */

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputAnalog         adc1;           //xy=161,80
AudioOutputAnalog        dac1;           //xy=329,47
//AudioOutputPWM           pwm1;           //xy=331,125
AudioConnection          patchCord1(adc1, dac1);
//AudioConnection          patchCord2(adc1, pwm1);
// GUItool: end automatically generated code

void setup() {
  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(12);
}

void loop() {
  // Do nothing here.  The Audio flows automatically

  // When AudioInputAnalog is running, analogRead() must NOT be used.
}

Hi Teenfor3,
I just want to playback the audio received from the digital mic. I was thinking of just using the code from onehorse to get the input and save it to play it back later. Are there other ways to do this? Thanks.
 
Hi Teenfor3,
I just want to playback the audio received from the digital mic. I was thinking of just using the code from onehorse to get the input and save it to play it back later. Are there other ways to do this? Thanks.

The one I posted is for digital (i.e. I2S) microphones.
 
where do you want to save it...??
If to PC....then as WMXZ says .....I2S in and USB out to PC and save it as wav file etc using Audacity etc for playback later

OR I2S in and DAC out to Linein on PC and save to audio WAV files etc on PC

OR do you want to save it to SD card on teensy...????
 
To add to Teenfor3's comment:
use first the Audio toolbox to come as close as possible to the solution you want with minimal coding.
 
where do you want to save it...??
If to PC....then as WMXZ says .....I2S in and USB out to PC and save it as wav file etc using Audacity etc for playback later

OR I2S in and DAC out to Linein on PC and save to audio WAV files etc on PC

OR do you want to save it to SD card on teensy...????

I want to save it to pc. Noted. I will try it out. Thanks!
 
Status
Not open for further replies.
Back
Top