Splitting Channel of ICS52000 with Teensy3.6

Status
Not open for further replies.

netengineer

New member
------------------------------------
Admin Edit: ICS-52000 microphones do not appear to work well with Teensy at 44100 Hz sample rate.
------------------------------------




Hi. Is there any way to retrieve recording from the channel of each microphone?

I am looking to get the recording of individual microphones from a daisy chain connection

I am using daisy chain of 3 mics ( ICS-52000) with a Teensy 3.6.

I am currently using the latest code from member amperwest1

https://forum.pjrc.com/threads/5341...-with-Invensense-ics-52000?highlight=ics52000

Code:
#if F_CPU == 96000000 || F_CPU == 48000000 || F_CPU == 24000000
  // PLL is at 96 MHz in these modes
  #define MCLK_MULT 4
  #define MCLK_DIV  17
#elif F_CPU == 72000000
  #define MCLK_MULT 16
  #define MCLK_DIV  51
#elif F_CPU == 120000000
  #define MCLK_MULT 16
  #define MCLK_DIV  85
#elif F_CPU == 144000000
  #define MCLK_MULT 8
  #define MCLK_DIV  51
#elif F_CPU == 168000000
  #define MCLK_MULT 16
  #define MCLK_DIV  119
#elif F_CPU == 180000000
  #define MCLK_MULT 32
  #define MCLK_DIV  255
  #define MCLK_SRC  0
#elif F_CPU == 192000000
  #define MCLK_MULT 2
  #define MCLK_DIV  17
#elif F_CPU == 216000000
  #define MCLK_MULT 16
  #define MCLK_DIV  153
  #define MCLK_SRC  0
#elif F_CPU == 240000000
 //#define MCLK_MULT 8            //original for 44.1kHz
 //#define MCLK_DIV  85
  #define MCLK_MULT 8            //edit for 10kHz sample
  #define MCLK_DIV  375
//#define MCLK_MULT 32            //edit for 8kHz sample
//#define MCLK_DIV  1875
//#define MCLK_MULT 4            //edit for 5kHz sample
//#define MCLK_DIV  375
#else
  #error "This CPU Clock Speed is not supported by the Audio library";
#endif

Code:
// Record TDM input sound as raw data (16ch, Signed 24-bit little-endian PCM, 44.1kHz, little-endian) to a SD card.
// Note: Format is modified so that mics align their 24 bit data to 32 bit slots, half of the 16 bit
// channels end up being the 8 low bits, and 8 more zeros which are discarded.
//
// Hardware:
//   Mic Pin 6  (SD_O)  to Teensy Pin  13 SDATA  (Input, 11.3 Mbit/sec)
//   Mic Pin 8  (SCK_I) to Teensy Pin  9 SCK     (Output, 11.3 MHz, Checked)
//   Mic Pin 10 (WS_I)  to Teensy Pin  23 FS     (Output, 44100 Hz, Checked)
//
//   Mic GND Pins (1, 3, 5, 7 and 9) to Teensy GND
//   Mic VDD to Teensy 3.3V

//   At startup of the ICS-52000, the start of the frame sync (WS_I) signal should be delayed from the start of the serial clock (SCK_I) by at
//   least 10 ms. This enables the microphone’s internal circuits to completely initialize before starting the synchronization sequence
//   with other microphones in the TDM array. This delay can be implemented either by enabling the WS output (FS) on the clock master at
//   least 10 ms after the SCK_I is enabled, or by externally controlling the signals given to the ICS-52000s.
//
//
// This example code is in the public domain.

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

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

// GUItool: begin automatically generated code
AudioInputTDM            tdm1;           //xy=151,223
AudioRecordQueue         queue4;         //xy=416,221
AudioRecordQueue         queue5;         //xy=416,254
AudioRecordQueue         queue6;         //xy=416,287
AudioRecordQueue         queue7;         //xy=416,320
AudioRecordQueue         queue3;         //xy=417,187
AudioRecordQueue         queue8;         //xy=417,353
AudioRecordQueue         queue2;         //xy=418,154
AudioRecordQueue         queue1;         //xy=419,120
AudioConnection          patchCord1(tdm1, 0, queue1, 0);
AudioConnection          patchCord2(tdm1, 1, queue2, 0);
AudioConnection          patchCord3(tdm1, 2, queue3, 0);
AudioConnection          patchCord4(tdm1, 3, queue4, 0);
AudioConnection          patchCord5(tdm1, 4, queue5, 0);
AudioConnection          patchCord6(tdm1, 5, queue6, 0);
AudioConnection          patchCord7(tdm1, 6, queue7, 0);
AudioConnection          patchCord8(tdm1, 7, queue8, 0);
// GUItool: end automatically generated code

// GUItool: end automatically generated code

// Use these with the Teensy Audio Shield
//#define SDCARD_CS_PIN    10
//#define SDCARD_MOSI_PIN  7
//#define SDCARD_SCK_PIN   14

// Use these with the Teensy 3.5 & 3.6 SD card
#define SDCARD_CS_PIN    BUILTIN_SDCARD
#define SDCARD_MOSI_PIN  11  // not actually used
#define SDCARD_SCK_PIN   13  // not actually used

// Use these for the SD+Wiz820 or other adaptors
//#define SDCARD_CS_PIN    4
//#define SDCARD_MOSI_PIN  11
//#define SDCARD_SCK_PIN   13

// Remember which mode we're doing
int mode = 0;  // 0=stopped, 1=recording
int choice = 0;
int sample_number = 0;

unsigned int tsamplemillis = 10000;

String typeofsound;

int16_t* buffer1;
int16_t* buffer2;
int16_t* buffer3;
int16_t* buffer4;
int16_t* buffer5;
int16_t* buffer6;
int16_t* buffer7;
int16_t* buffer8;

// The file where data is recorded
File frec;

void setup() {

  Serial.begin(115200);
  // Audio connections require memory, and the record queue
  // uses this memory to buffer incoming audio.
  AudioMemory(512);

  // Initialize the SD card
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
    // stop here if no SD card, but print a message
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
  while (!Serial);
  Serial.println("Welcome to the 4-channel TDM recording test bench");
}

void loop() {

  if (choice == 0) {
    Serial.println("\nEnter new filename for sound archive: ");
    while (!Serial.available());
    typeofsound = Serial.readString();
    sample_number = 0;
    record(typeofsound, sample_number);
  } else if (choice == 1) {
    sample_number++;
    record(typeofsound, sample_number);
  } else {
    //Do nothing
  }

  Serial.print("\nEnter 1 to take another sample in this archive or 0 to enter a new file archive: ");
  while (!Serial.available());
  choice = Serial.readString().toInt();
  Serial.println(choice);
}

void record(String type, int number)
{
  Serial.println("Recording " + type + String(number) + "...");
  String sname = type + number + ".RAW";
  String path = type + "/" + type + number + ".RAW";
  startRecording(sname, path, type);
  continueRecording();
  stopRecording();
}

void startRecording(String sname, String path, String type)
{
  int str_len = path.length() + 1;
  char charpath[str_len];
  path.toCharArray(charpath, str_len);

  if (SD.exists(charpath)) {
    // The SD library writes new data to the end of the
    // file, so to start a new recording, the old file
    // must be deleted before new data is written.
    SD.remove(charpath);
  }

  str_len = type.length() + 1;
  char chartype[str_len];
  type.toCharArray(chartype, str_len);

  if (!SD.exists(chartype)) {
    SD.mkdir(chartype);
  }

  frec = SD.open(charpath, FILE_WRITE);
  if (frec) {
    Serial.println("File Open");
  }
}

void continueRecording() {
  int data = 0, num = 0;
  elapsedMillis recordingTime = 0;
  queue1.begin();
  queue2.begin();
  queue3.begin();
  queue4.begin();
  queue5.begin();
  queue6.begin();
  queue7.begin();
  queue8.begin();
  mode = 1;
  while (recordingTime < tsamplemillis)
  {
    data = queue1.available();
    if (data > 0)
    {
      buffer1 = queue1.readBuffer();      //read all queue buffers in sets of 128 16bit num
      buffer2 = queue2.readBuffer();
      buffer3 = queue3.readBuffer();
      buffer4 = queue4.readBuffer();
      buffer5 = queue5.readBuffer();
      buffer6 = queue6.readBuffer();
      buffer7 = queue7.readBuffer();
      buffer8 = queue8.readBuffer();
      queue1.freeBuffer();                //free queue buffers to allow system to re issue storage
      queue2.freeBuffer();
      queue3.freeBuffer();
      queue4.freeBuffer();
      queue5.freeBuffer();
      queue6.freeBuffer();
      queue7.freeBuffer();
      queue8.freeBuffer();
      if (data > 48)        //test if queue buffers are getting too full, the serial write will probably cause a back log if it does happen.
      {
        Serial.write('.');    //dots in the serial monitor mean that the system isnt processing data fast enough
      }
      for (int i = 0; i < 128; i ++)                        //write data to sd card in 24bit signed pcm format (i think) (audacity seems to accept it)
      { //frames are built of 2 16 bit numbers where only 24 bits are useful, so only 3 bytes are saved to save space. Frames are little endian
        frec.write(highByte(buffer2[i])); // LSB            //<---------------------sample 1---------------------><---------------------sample n--------------------->
        frec.write(lowByte(buffer1[i])); // Middle Byte     //<----ch1----><----ch2----><----ch3----><----ch4----><----ch1----><----ch2----><----ch3----><----ch4---->
        frec.write(highByte(buffer1[i])); // MSB            //<LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB>
        frec.write(highByte(buffer4[i])); // LSB
        frec.write(lowByte(buffer3[i])); // Middle Byte
        frec.write(highByte(buffer3[i])); // MSB
        frec.write(highByte(buffer6[i])); // LSB
        frec.write(lowByte(buffer5[i])); // Middle Byte
        frec.write(highByte(buffer5[i])); // MSB
        frec.write(highByte(buffer8[i])); // LSB
        frec.write(lowByte(buffer7[i])); // Middle Byte
        frec.write(highByte(buffer7[i])); // MSB
        num++;
      }
    }
  }
  queue1.end();     //stop the background sampling
  queue2.end();
  queue3.end();
  queue4.end();
  queue5.end();
  queue6.end();
  queue7.end();
  queue8.end();
  Serial.print("num of samples written per channel:");
  Serial.println(num);
}


void stopRecording() {
  Serial.println("Finished recording.");
  queue1.end();
  queue2.end();
  queue3.end();
  queue4.end();
  queue5.end();
  queue6.end();
  queue7.end();
  queue8.end();
  queue1.clear();
  queue2.clear();
  queue3.clear();
  queue4.clear();
  queue5.clear();
  queue6.clear();
  queue7.clear();;
  queue8.clear();
  frec.close();
  mode = 0;
}

But I am getting very weird results from the raw files when exported to Audacity.

I was speaking to directly to the 3 mics individually during the recording, but the only channel that displays a change in amplitude is always the same channel.

sample.png
 
Last edited by a moderator:
Status
Not open for further replies.
Back
Top