Teensy 3.6 overclocked to 216-240MHz and audio adapter board -> LRCLK jitter

Status
Not open for further replies.

neurofun

Well-known member
Hello everyone,

The facts:

My current setup is Teensy3.6, arduino 1.8.5, Teensyduino 1.40, osx.
Compiling for cpu speeds 24-192MHz everything works fine.
Compiling for 216-240MHz and the audio from the adapter board is distorted.
You can clearly see the jitter on LRCLK with a scope.
Audio from the dac is not distorted.
For those who don't have acces to a scope, I have included a small program to demonstrate the effect.
You can also use it to compare the outputs of the adapter board and the dac with a scope.

The questions:

Is this a hardware limitation due to some kind of clock divider stuff or is it some software problem?
And how can we solve this?

The code:

generate a 4400Hz sine for 2 secs and then sweep to 8800Hz in 4 secs, rinse and repeat.
Comment everything in the main loop to disable the sweep if you want to compare the 2 outputs on your scope.
Now compile for 192MHz cpu speed and listen. This is smooth.
Now compile for 240MHz cpu speed and listen. What is happening?
Now compile for 216MHz cpu speed and listen. Oh the horror!
*warning*: your pet(s) may not like this sound.

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

// GUItool: begin automatically generated code
AudioSynthWaveformSine   sine1;          //xy=71,83
AudioSynthWaveformSineModulated sine_fm1;       //xy=199,83
AudioOutputI2S           i2s1;           //xy=370,58
AudioOutputAnalogStereo  dacs1;          //xy=380,119
AudioConnection          patchCord1(sine1, sine_fm1);
AudioConnection          patchCord2(sine_fm1, 0, i2s1, 0);
AudioConnection          patchCord3(sine_fm1, 0, i2s1, 1);
AudioConnection          patchCord4(sine_fm1, 0, dacs1, 0);
AudioConnection          patchCord5(sine_fm1, 0, dacs1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=73,34
// GUItool: end automatically generated code

void setup() {
	AudioMemory(2);
	sgtl5000_1.enable();
	sgtl5000_1.volume(0.5);

	sine1.frequency(.0625);
	sine_fm1.frequency(4400);
	sine1.amplitude(0);
	sine_fm1.amplitude(1);
}

void loop() {
	delay(2000);
	sine1.phase(0);
	sine1.amplitude(1);
	delay(4000);
	sine1.amplitude(0);
}


One final thought, long time ago I once told myself(luckily I didnt swear) I would never use arduino and here I am admitting defeat thanks to Paul's Teensys and audio library.
Great stuff, thank you very much!
 
Is this a hardware limitation due to some kind of clock divider stuff

Yes, pretty sure it's a hardware limitation with the I2S MCLK fractional divider. This has come up several times. It's the one part of the chip which really doesn't seem to overclock beyond 192 MHz.
 
Yes, pretty sure it's a hardware limitation with the I2S MCLK fractional divider. This has come up several times. It's the one part of the chip which really doesn't seem to overclock beyond 192 MHz.

It is nor really the overclocking per se, but the 'difficulty' of the chip to generate the clocks for the desired sampling frequency.
changing the sampling frequency such that the different multiplier and dividers are more 'chip-friendly' (i.e. smaller multipliers) removed the problem in my applications.
@neurofun, if you need the CPU speed, check the forum on how to change the sampling frequency, say to 48 kHz, or even to som non-standard rate.
 
Thanks for your quick replies. I think I'll be fine for a while @192MHz but it's good to know that I can get more oomph by changing the sample rate.
 
Yes, pretty sure it's a hardware limitation with the I2S MCLK fractional divider.

Good news, it is not. LRCLK is now steady as a rock, compiled at 216MHz and 240MHz.
Here is the fix for output_i2s.cpp and output_i2s_quad.cpp:
Code:
/* fix for LRCLK jitter on Teensy 3.6, neurofun */
// #elif F_CPU == 216000000
//   #define MCLK_MULT 8
//   #define MCLK_DIV  153
//   #define MCLK_SRC  0
// #elif F_CPU == 240000000
//   #define MCLK_MULT 4
//   #define MCLK_DIV  85
#elif F_CPU == 216000000
  #define MCLK_MULT 36
  #define MCLK_DIV  153
#elif F_CPU == 240000000
  #define MCLK_MULT 2
  #define MCLK_DIV  85
  #define MCLK_SRC  0
/* end of fix */
Yeah! 25% more oomph for audio applications.
 
just wanted to bump this up, because @neurofun's fix totally worked for me (tested with a custom SGTL5000 based board, 240mhz works now, previously limited to 192mhz)
the code around the fix in output_i2s.cpp seems to have changed slightly in the order of #ifs, so I put neurofun's fix first in the if/else if chain, thus:
Code:
// MCLK needs to be 48e6 / 1088 * 256 = 11.29411765 MHz -> 44.117647 kHz sample rate
//
/* FIX STARTS HERE fix for LRCLK jitter on Teensy 3.6, neurofun */
#if F_CPU == 216000000
  #define MCLK_MULT 36
  #define MCLK_DIV  153
#elif F_CPU == 240000000
  #define MCLK_MULT 2
  #define MCLK_DIV  85
  #define MCLK_SRC  0
/* end of fix */
#elif F_CPU == 96000000 || F_CPU == 48000000 || F_CPU == 24000000
// ... as before ...

not sure why it wasn't merged yet, I wonder if there's some dragon lurking. but in case it was an oversight, @PaulStoffregen - this fix is awesome! seems to let me run i2s audio stabley at high overclock.
thankyou neurofun!
 
just wanted to bump this up, because @neurofun's fix totally worked for me (tested with a custom SGTL5000 based board, 240mhz works now, previously limited to 192mhz)
the code around the fix in output_i2s.cpp seems to have changed slightly in the order of #ifs, so I put neurofun's fix first in the if/else if chain, thus:
Code:
// MCLK needs to be 48e6 / 1088 * 256 = 11.29411765 MHz -> 44.117647 kHz sample rate
//
/* FIX STARTS HERE fix for LRCLK jitter on Teensy 3.6, neurofun */
#if F_CPU == 216000000
  #define MCLK_MULT 36
  #define MCLK_DIV  153
#elif F_CPU == 240000000
  #define MCLK_MULT 2
  #define MCLK_DIV  85
  #define MCLK_SRC  0
/* end of fix */
#elif F_CPU == 96000000 || F_CPU == 48000000 || F_CPU == 24000000
// ... as before ...

not sure why it wasn't merged yet, I wonder if there's some dragon lurking. but in case it was an oversight, @PaulStoffregen - this fix is awesome! seems to let me run i2s audio stabley at high overclock.
thankyou neurofun!

Hi mmalex,
I have just found this post (shame on me... so much time I would have saved If I had found it before!!) and I'm happy that issue of overclock has been solved; recently I wrote a post about the problem, and the different behaves of different Teensy 3.6 boards:
https://forum.pjrc.com/threads/57382-Malfunction-with-Teensy-3-6-in-an-audio-project

Ok, now there is a fix and I'm going to apply it soon, and will relax..... But.. I'm so curious to understand why on my Teensy 3.6 board bought in june 2018 (and ONLY on this board!!), all these sound applications work perfecly at all overclock frequencies!:D
Thank you
Sandro
 
Last edited:
Committed faster clock speed support.

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

I did not go with use of IRC48MCLK, as above on this thread, since it won't stay in sync if a project uses both I2S and Teensy 3.6's DACs. Also IRC48MCLK varies quite a lot when there's no USB connection.

Great!!! Thank you so much Paul!! I'm testing the updated AudioMaster library on my "Lilla" midi expander, using a new Teensy 3.6 board and overclock @216MHz: no "pitch fluttering"!! It's also time to share my project.
 
thanks so much paul! could you clarify what you mean by 'out of sync if use both I2S and teensy 3.6 dacs'. I was planning to use quad I2S (2x SGTL5000) but then write to the DACs at audio block rate (ie a call to analogWrite once per audio block) - I hope you were referring to using the DAC in DMA/audio output mode at the same time as I2S?

also, if I wanted to change the sample rate of audio.h, (I know its not tested/expected), and wasnt using any blocks except the SGTL I2S inputs & output hardware blocks, are there any other points of edit apart from these clock dividers? Thanks again
 
I hope you were referring to using the DAC in DMA/audio output mode at the same time as I2S?

Yes, exactly.

If you write to the DACs with analogWrite() or other non-DMA, not audio library code, then this has no bearing. In that case, you're in control of the DAC with your code and it's up to you how you write to it.

It's only a matter of the audio library using 2 (or more) different hardware interfaces simultaneously. The audio library currently does not have any resampling. If 2 hardware interfaces are not perfectly in sync from the same clock, one or both will eventually have trouble like dropouts or skipped samples.

also, if I wanted to change the sample rate of audio.h, (I know its not tested/expected), and wasnt using any blocks except the SGTL I2S inputs & output hardware blocks, are there any other points of edit apart from these clock dividers? Thanks again

Those constants apply to Teensy 3.x, but not Teensy 4.0. Just something keep that in mind if you ever upgrade to 4.0 (or for anyone else who finds this message).

You'd probably also want to change the sample rate constants in AudioStream.h.
 
Status
Not open for further replies.
Back
Top