Teensy 4.0 I2S 96 kHz but no data

Gkatsos

Member
Hello

My first post. I am stuck.

I am using a Teensy 4.0, i have the LRCLK at 96 kHz BCLK at 6.144 mHz and MCLK at 24.576 Mhz.
The ADC is a WM8782.

I can use an I2S DAC and get the output from the ADC into the DAC and get sound, but the Teensy doesn't get a signal from the ADC.

Anyone who can help? as far as i understand the interrupt is tied to BCLK and the Teensy should get the data.
 
Code:
void AudioOutputI2S::config_i2s(bool only_bclk)
{
	CCM_CCGR5 |= CCM_CCGR5_SAI1(CCM_CCGR_ON);

	// if either transmitter or receiver is enabled, do nothing
	if ((I2S1_TCSR & I2S_TCSR_TE) != 0 || (I2S1_RCSR & I2S_RCSR_RE) != 0)
	{
	  if (!only_bclk) // if previous transmitter/receiver only activated BCLK, activate the other clock pins now
	  {
	    CORE_PIN23_CONFIG = 3;  //1:MCLK
	    CORE_PIN20_CONFIG = 3;  //1:RX_SYNC (LRCLK)
	  }
	  return ;
	}

	//PLL:
	int fs = 96000 + 202;
	int oversampling = 256;
	int clk = 24000000;
	// PLL between 27*24 = 648MHz und 54*24=1296MHz
	int n1 = 4; //SAI prescaler 4 => (n1*n2) = multiple of 4
	int n2 = 1 + (clk * 27) / (fs * oversampling * n1);

	double C = ((double)fs * oversampling * n1 * n2) / clk;
	int c0 = C; //28
	int c2 = 10000;
	int c1 = C * c2 - (c0 * c2);

	set_audioClock(c0, c1, c2); //set_audioClock(int nfact, int32_t nmult, uint32_t ndiv, bool force)

	// clear SAI1_CLK register locations
	CCM_CSCMR1 = (CCM_CSCMR1 & ~(CCM_CSCMR1_SAI1_CLK_SEL_MASK))
		   | CCM_CSCMR1_SAI1_CLK_SEL(2); // &0x03 // (0,1,2): PLL3PFD0, PLL5, PLL4
	CCM_CS1CDR = (CCM_CS1CDR & ~(CCM_CS1CDR_SAI1_CLK_PRED_MASK | CCM_CS1CDR_SAI1_CLK_PODF_MASK))
		   | CCM_CS1CDR_SAI1_CLK_PRED(n1-1) // &0x07
		   | CCM_CS1CDR_SAI1_CLK_PODF(n2-1); // &0x3f

	// Select MCLK
	IOMUXC_GPR_GPR1 = (IOMUXC_GPR_GPR1
		& ~(IOMUXC_GPR_GPR1_SAI1_MCLK1_SEL_MASK))
		| (IOMUXC_GPR_GPR1_SAI1_MCLK_DIR | IOMUXC_GPR_GPR1_SAI1_MCLK1_SEL(0));

	if (!only_bclk)
	{
	  CORE_PIN23_CONFIG = 3;  //1:MCLK
	  CORE_PIN20_CONFIG = 3;  //1:RX_SYNC  (LRCLK)
	}
	CORE_PIN21_CONFIG = 3;  //1:RX_BCLK

	int rsync = 0;
	int tsync = 1;

	I2S1_TMR = 0;
	//I2S1_TCSR = (1<<25); //Reset
	I2S1_TCR1 = I2S_TCR1_RFW(1);
	I2S1_TCR2 = I2S_TCR2_SYNC(tsync) | I2S_TCR2_BCP // sync=0; tx is async;
		    | (I2S_TCR2_BCD | I2S_TCR2_DIV((1)) | I2S_TCR2_MSEL(1));
	I2S1_TCR3 = I2S_TCR3_TCE;
	I2S1_TCR4 = I2S_TCR4_FRSZ((2-1)) | I2S_TCR4_SYWD((32-1)) | I2S_TCR4_MF
		    | I2S_TCR4_FSD | I2S_TCR4_FSE | I2S_TCR4_FSP;
	I2S1_TCR5 = I2S_TCR5_WNW((32-1)) | I2S_TCR5_W0W((32-1)) | I2S_TCR5_FBT((32-1));

	I2S1_RMR = 0;
	//I2S1_RCSR = (1<<25); //Reset
	I2S1_RCR1 = I2S_RCR1_RFW(1);
	I2S1_RCR2 = I2S_RCR2_SYNC(rsync) | I2S_RCR2_BCP  // sync=0; rx is async;
		    | (I2S_RCR2_BCD | I2S_RCR2_DIV((1)) | I2S_RCR2_MSEL(1));
	I2S1_RCR3 = I2S_RCR3_RCE;
	I2S1_RCR4 = I2S_RCR4_FRSZ((2-1)) | I2S_RCR4_SYWD((32-1)) | I2S_RCR4_MF
		    | I2S_RCR4_FSE | I2S_RCR4_FSP | I2S_RCR4_FSD;
	I2S1_RCR5 = I2S_RCR5_WNW((32-1)) | I2S_RCR5_W0W((32-1)) | I2S_RCR5_FBT((32-1));
}

this is the code I've changed (i just copied the entire function), I've only changed fs to get the clock frequencies mentioned. the rest of the code is also in "C:\Program Files (x86)\Arduino\hardware\teensy\avr".
 
Here are some of the code examples:

This will write "Done", if there is a sample
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2S            i2s;           //xy=619,408
AudioRecordQueue         queue;         //xy=786,408
AudioConnection          patchCord1(i2s, 0, queue, 0);
// GUItool: end automatically generated code



void setup() 
{ 
  queue.begin();
}

void loop() 
{  
  while (queue.available())
  {
    Serial.println("Done");
    queue.clear();
  }
}

This writes available packs, for me it writes 0.
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2S            i2s;           //xy=619,408
AudioRecordQueue         queue;         //xy=786,408
AudioConnection          patchCord1(i2s, 0, queue, 0);
// GUItool: end automatically generated code



void setup() 
{ 
  queue.begin();
}

void loop() 
{  
  Serial.println(queue.available());
}

This should just pass the data from ADC to DAC
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2S            i2s;           //xy=619,408
AudioOutputI2S           i2s2;           //xy=765,407
AudioConnection          patchCord1(i2s, 0, i2s2, 0);
AudioConnection          patchCord2(i2s, 1, i2s2, 1);
// GUItool: end automatically generated code


void setup() 
{ 
  
}

void loop() 
{  

}

For more information on how to use the audio lib: https://www.pjrc.com/teensy/td_libs_Audio.html
 
Back
Top