Teensy 3.6 I2S input without board

Status
Not open for further replies.

gil

Member
Hi,
I'm trying to read data from I2S microphone without the audio board, but even though I checked all the posts and samples it still doesn't work.

I'm using the Teensy 3.6 and EMMIC-ICS43434 microphone.
Connected SCK (clock) to pin 15, SD (data) to 13, WS (word select) to 14, 3.3v and ground to their places.

this is the code I've tried:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2S            i2s1;           //xy=207.1999969482422,130.1999969482422
AudioRecordQueue         queue1;         //xy=281,63
AudioConnection          patchCord1(i2s1, 0, queue1, 0);
// GUItool: end automatically generated code


void setup() {

  Serial.begin(38400);

  AudioMemory(60);

  SIM_SCGC6 |= SIM_SCGC6_I2S;                // enable clock to the I2S module

  CORE_PIN13_CONFIG  = PORT_PCR_DSE | PORT_PCR_MUX(4);     // I2S0_TXD0 //13 - data
  CORE_PIN14_CONFIG  = PORT_PCR_DSE | PORT_PCR_MUX(4);     // I2S0_TX_FS //14 - frame sync
  CORE_PIN15_CONFIG  = PORT_PCR_DSE | PORT_PCR_MUX(4);     // I2S0_TX_BCLK //15 - clock

  queue1.begin();
}

void loop() {

  byte buffer[512];

  memcpy(buffer, queue1.readBuffer(), 256);
  queue1.freeBuffer();

  Serial.println(*buffer);

  delay(250);

}

I also tried to patch I2S -> Print or peak, but I see no values. Either the microphone has a problem or (more likely) I'm doing something wrong.

Thanks!
 
Hi,
I'm trying to read data from I2S microphone without the audio board, but even though I checked all the posts and samples it still doesn't work.

I'm using the Teensy 3.6 and EMMIC-ICS43434 microphone.
Connected SCK (clock) to pin 15, SD (data) to 13, WS (word select) to 14, 3.3v and ground to their places.

this is the code I've tried:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2S            i2s1;           //xy=207.1999969482422,130.1999969482422
AudioRecordQueue         queue1;         //xy=281,63
AudioConnection          patchCord1(i2s1, 0, queue1, 0);
// GUItool: end automatically generated code


void setup() {

  Serial.begin(38400);

  AudioMemory(60);

  SIM_SCGC6 |= SIM_SCGC6_I2S;                // enable clock to the I2S module

  CORE_PIN13_CONFIG  = PORT_PCR_DSE | PORT_PCR_MUX(4);     // I2S0_TXD0 //13 - data
  CORE_PIN14_CONFIG  = PORT_PCR_DSE | PORT_PCR_MUX(4);     // I2S0_TX_FS //14 - frame sync
  CORE_PIN15_CONFIG  = PORT_PCR_DSE | PORT_PCR_MUX(4);     // I2S0_TX_BCLK //15 - clock

  queue1.begin();
}

void loop() {

  byte buffer[512];

  memcpy(buffer, queue1.readBuffer(), 256);
  queue1.freeBuffer();

  Serial.println(*buffer);

  delay(250);

}

I also tried to patch I2S -> Print or peak, but I see no values. Either the microphone has a problem or (more likely) I'm doing something wrong.

Thanks!

User onehorse has a mems I2S micro discussed on this forum. I recall, that there is a test program on his tindie page.
Maybe the info there helps.

Suggest first t try onehorse SW
 
Already tried that. I'll give it another shot, but his code was for the teensy 3.1 and I'm using the 3.6. I'm new to teensy, perhaps the difference is not as important as I think, but I think the pins are different and so far couldn't make it work.
I guess someone with more experience can tell more easily what the changes I need to make or what I'm doing wrong in the short code I posted.
 
Already tried that. I'll give it another shot, but his code was for the teensy 3.1 and I'm using the 3.6. I'm new to teensy, perhaps the difference is not as important as I think, but I think the pins are different and so far couldn't make it work.
I guess someone with more experience can tell more easily what the changes I need to make or what I'm doing wrong in the short code I posted.

code for T3.1 or T3.2 should work also for T3.6 , differences are only if you wanted to connect 4 I2S devices, for 1-2 I2S devices code should be identical.

I have at the moment no I2S mic here, needs to wait for next week
but concerning your code
As far as I read the docimentation
TX_FS is on pin4 (alt6), pin23 (alt 6), pin30(alt4)
TX_BCLK is on pin9 (alt 6), pin25(alt6), pin26(alt6), pin29(alt4)
on pin 14,15 you were using are no I2S clocks
on pin15 is txd1 the second tx data port

digital pins above 23 are different for T3.1(T3.2) and T3.6
 
Thank you all for the clarification. I took the pins from the MK66FX1M0 Manual stated to fit the teensy 3.6, I don't understand why there is such a difference.

Anyway, I tried using existing code and explanations, like this one, but whether I run it without modifications (as it should be compatible) or try to change some parameters to make it work, it doesn't. The best I could get is static noise, the I2S receive callback is getting called but there is almost no data.

Any advice? BTW, I'm using 11, 12, 13 now as instructed on the tindie page.
 
Last edited:
Thank you all for the clarification. I took the pins from the MK66FX1M0 Manual stated to fit the teensy 3.6, I don't understand why there is such a difference.

Anyway, I tried using existing code and explanations, like this one, but whether I run it without modifications (as it should be compatible) or try to change some parameters to make it work, it doesn't. The best I could get is static noise, the I2S receive callback is getting called but there is almost no data.

Any advice? BTW, I'm using 11, 12, 13 now as instructed on the tindie page.

please provide the source code you are using to call Kris library!
 
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.
 
I was just browsing....I dont have one of these mics to try out, but am interested in getting one for a future project, so maybe can give some help...??? and am interested to see how it works....

Even you are not wanting to use the PJRC Audio Adaptor Board you can still use the same pins and configuration for the I2S signals.
On reading the datasheet for the EMMIC-ICS43434 and following the datasheet for the teensy audio board.... I think it should be connected as follows.....

Use Teensy pin24....3.3 volt to power mic on micpin...V+
Use Teensy GND and micpin G for ground.
Use Teensy pin9 BCLK...the bit clock....to micpin SCK.
Use Teensy pin23 LRCLK ...LeftRightClk...to micpin WS ....the word select.
Use Teensy pin13 RX data ...to micpin SD ...the serial data.
Simply connect (hardware control) micpin L/R to ground to give the mic I2S data out on left channel. It is only a mono mic.....one channel.

Teensy pin11 is MCLK ....this is master clock and not needed.

Use the example teensy sketches for the audio adaptor and take out the bits you dont need and use the audio GUI to get the required connections in the sketch etc......You can use the Teensy DAC output A14/DAC to monitor the mic audio signal.
 
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.
 
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.

Again, please provide the sketch you are running. the link to Kris i2s.h/cpp files is not sufficient to reproduce your issue or find the problem.
 
It works after all!

Just before giving up, I decided to check the wires again, although I checked many times before.
I guess it was both wires and a code problem.

So in the end it works with onehorse configuration and code. When I play the output in Audacity the talking is too slow, but I guess that's just configuration.

Thank you all very much for the help!
 
Good you got it working, now that you have checked your wiring did you try it again with my earlier post config and using the PJRC example (recorder) in the library folders.

This is line from the datasheet of your mic "The slave serial data port’s format is I²S, 24-bit, twos complement. There must be 64 SCK cycles in each WS stereo frame." ............ Teensy works as master I2S feeding BCLK and LRCLK to your mic as slave so if Teensy just supplies 16 bits per L/R word does the 24 bits get truncated and does it still work just as 16 bit audio..??????
 
Hello All,

I have the new ICS43434 mic and would like to understand a bit more how to use it.
The ultimate idea is to use it as a audio recorder with Teensy 3.6.

Have tested the onehorse code, could reproduce it and works ok thanks Gil for your inputs as I could follow all the track.

The first question is based on the L/R pin as far I can understand this is the left right channel correct?
If it is connect to ground should be one and suppose to be the other if it is connected to 3v3?
If I want to record stereo need to use this L/R pin or it is done in the software?

The second question is how to use this mic to build an audio recorder as the onehorse example is performing a refresh every second and this is not good for audio sample...

Thanks.
Timóteo
 
Refer to the datasheet on the link in earlier post....... Pages 1 and 12 and 13.....
****The first question is based on the L/R pin as far I can understand this is the left right channel correct?****
It is a mono mic.....one mic, one I2S port and one L/R pin. The state of L/R determines if audio is output when WS is High or WS is Low
.................If L/R=0 volt or Gnd then audio is output for the I2S Left channel when WS is Low......If L/R=1 3v3 volt then audio is output for I2S Right channel when WS is High...........

If it is connect to ground should be one and suppose to be the other if it is connected to 3v3?.......You need two mics to do this and the I2S connected as bus....

If I want to record stereo need to use this L/R pin or it is done in the software? .....Stereo needs two mics one with L/R=0 for Left and one with L/R=1 for Right and the I"S connected as bus ......see page 12 and page 13 of data sheet
 
Hello Teenfor3,

I know that for stereo will need 2 mics in fact I have already 4 boards soldered for tests :).
In the last line you say it must be on connect to vcc and the other to ground but before you also refer the WS high and low this is done on the software how, does it mean that the sample will be divided by 2?
If I would like to use the onehorse example what changes and connection do I need to do in order to have an stereo system?
Thanks,
Timóteo
 
You say you got it making sound so you must be using the correct pins ?????
I looked at the library files in version 1.8.2, some details as below....

Library File...Input_I2s_cpp ......

???? Do you have the following config lines????

AudioOutputI2S::config_i2s();

CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // pin 13, PTC5, I2S0_RXD0

also..........

AudioOutputI2Sslave::config_i2s();
CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // pin 13, PTC5, I2S0_RXD0

In 2 places in the file....that means teensy pin13 is the RX data pin...used for recording input. this is connected to mic SD.
.................................................

Library File...output_I2s_cpp ......

???? Do you have the following config lines????

config_i2s();

CORE_PIN22_CONFIG = PORT_PCR_MUX(6); // pin 22, PTC1, I2S0_TXD0

// configure pin mux for 3 clock signals// these appear in 2 places in the file

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 means pin22 is the teensy TX I2S data out from teensy as output
and pin23 is the LRCLK left right clock called mic WS so we know what data from which mic is on the line
and pin9 is the serial bit clock SCK to clock the bits in or out.
and pin11 is the Master clock....not used with this mic.

The above config is what is in the teensy audio library 1.8.2

Teensy as I2S master generates the clock signals for the mic as I2S slave and the mics are tristated so connect all in parallel as bus as shown on the diagram page 13.

Teensy will receive the combined I2S audio output from mic1 if L/R on mic1 is low, when WS is low and from mic2 if L/R on mic2 is high, when WS is high. Both received on the one SD data line connected to pin 13 if your config is as per 1.8.2.

If your config is different you may be using different pins but the idea is the same. I dont have the mic yet but intend to get some for use with a teensy 3.2. this is how I would plan to use it.
 
I've committed a change to the audio library to use 64 bit frame size for I2S master mode. Hopefully this will allow these microphone chips to work "out of the box".

https://github.com/PaulStoffregen/Audio/commit/dc825828e615cdf0cd6ee49d4a947343d3beaff4

Please give the latest code a try, if you're using any of these chips. Or if pulling from github isn't your thing, this change will be in 1.38-beta2 coming in a day or two.

Paul,
I guess you are right but what is the technical reason for increasing src and dest addresses by two words?
I thought base data address would remain the same. I did not change it for my ICS43432 mic interface.
 
Last edited:
The offset is 2 bytes, not 2 words. It's needed because we want the upper 16 bits of the 32 bit word. Teensy uses little endian format. If you don't use this offset (or some other way) you end up with the low 16 bits which is usually just 8 bits of noise and 8 zeros.
 
The offset is 2 bytes, not 2 words. It's needed because we want the upper 16 bits of the 32 bit word. Teensy uses little endian format. If you don't use this offset (or some other way) you end up with the low 16 bits which is usually just 8 bits of noise and 8 zeros.

OK,
understood. I was confused by the cast to uint32_t of the base address, but what you say makes sense.
I will stick to 32 bit as the ICS4343(2/4) is much better than 16 bit, more in the order of 18-20 bit.

In case someone is interested, the ICS4343x has the MSB after the first clock, so I do first a left shift by one to get the minus sign right.
 
Their web page says SNR is 65 dB, which is approx 11 bits.

Edit: the datasheet also mentions a -91 dB noise floor on page 4, so perhaps approx 15 bits, though this noise spec is A weighted.

Yes, the noise level is -26 dB (sensitivity) minus 65 dB (SNR) = -91 dB. (ignoring references)
Keep in mind noise level is broadband, so you can easily subtract 40 dB (10kHz effective bandwidth) for spectral noise level.
 
Thanks for the replies and the mod to the library.........
So to follow on from my original query in post #13 above........am I correct in thinking with the mod. teensy now works with a 64 bit frame, 32 bits for left and 32 bits for right, shifted by 2 bytes (16 bits) to leave the upper 16 bits for teensy to process 16 bit audio. and is ..... The data from the mic the lower 24 bits of the 32 bit word sent MSB first from the mic and we end up with the upper 16 bits of this received in teensy read in little endian (LSB first). So teensy will now cope with any 16 bit to 32 bit I2S data and process it as 16 bit audio. or do we need to we need to use the mod only for the longer data length data?.
 
Status
Not open for further replies.
Back
Top