16k (and other) low sampling rates with T3.6

Status
Not open for further replies.

vladn

Well-known member
Hi,
I've returned back to a 3y.o. project - a low power DSP RX. In the original mk1 version I've used a mod from robsoles (which as far as I can remember used codec as the clock master on the I2S):
https://forum.pjrc.com/threads/24793-Audio-Library?p=47277&viewfull=1#post47277
which allowed me to get a clean 16ksps stereo sampling rate.

I've tried to add this code to the current audio library using T3.6 and it did not work :(. How can I get a low sampling rates with the current version of the audio library and T3.6 ?

Note - I have a high end synth chip on the board with one spare output, so I can generate any frequency with a sub 1ps jitter but that would require a change to the PCB. Hence, at least for testing, I would prefer the software method robsoles used before. But currently I can not get it to work on T3.6. Need some help please.
 
I can't remember where but there was a rather old thread talking about extremely poor jitter performance if MCLK is generated by Teensy 3.1/2 at non-standard sample rates. The solution by robsoles used codec PLL as a MCLK master instead and worked perfectly for me and did not require rewiring the connections. But this was 3 years ago and I do not remember the details :(

As I said above I have a spare, very low jitter clock source output on SI5338 that I could use, but rewiring a tiny QFN on the current version of the my RX PCB would be troublesome. Is there a working code that uses SGTL5000 PLL as a master for BCLK with the current audio library ? Similar to his master96k() routine.
 
you can search for Bob Larkins measurements here on the forum, he has some more details on performance with Frank Bs code.

To be honest, I do not think that jitter performance is an issue for a low power DSP rx like the one you are building . . . :).

The Teensy Convolution SDR uses Frank Bs code and has very nice performance for my purposes (and it has an Si5351 as the LO, which is really famous for its poor jitter performance, but my experience does not confirm that . . . BTW the Elecraft KX2 also uses the Si5351). So, I think jitter performance is really overrated for the kind of receivers we are talking about.

But your mileage may vary! Sorry I cant help with your approach, I would recommend using Frank Bs code, which is very easy to use.

All the best and good luck!

Frank
 
I got burned by horrible jitter using the CS2200 frac synth. On some HF bands it was very very quiet (as confirmed by my measurement setup, consisting of a QSD fed by a quality reference and a test input, fed to a pro audio 192ksps 24bit board). But on some frequency bands this frac synth was so bad that I can just see the jitter on the scope and the noise level made the the RX simply unusable there. I know very well that Si5351 is a much cleaner frac synth with the main PLL running at around 600MHz. Si514 and Si5338 are a "middle ground" range with the main PLL at ~2.5GHz. I had a very good experience with Si514 and now experimenting with the Si5338.

If I won't find a compatible version of the solution by robsoles, I'll try the code by Frank B. But I am inclined to eventually use the 4th clock output of the Si5338 as an I2S reference on a "beta" version of my RX PCB.
 
Shame on me :eek:. I forgot to call the master**k() function in the setup routine. Was too tired merging code. The SGTL5000 interface works now, so I have other issues to fix...
 
Hi vlad,

thanks a lot for your explanations! Now I understand it much better!

And glad to hear your approach is now working. Curious to hear further details about your progress !

Is your code in the public domain?

All the best, have fun!

Frank
 
Is your code in the public domain?
No, but not for any commercial reason. It is simply the worst example of the spaghetty code - unreadable and unmaintainable. I did not know what I want from the RX and UI when I started the project and piled one test feature on top of another... The worst problem is that I needed to modify the audio library for my needs (many files involved) and merging the new audio library with the old library mods and the new main code with the old one at the same time does not go smooth at all ! Once the feature set and UI stabilize a bit I will (hopefully) do a complete rewrite and then post the code.

I still have trouble with the codec interface. It is alive but not working as on the mk1/T3.1, so I am going to try Frank B code.
 
I did look at the noise/spur spectrum with low sampling rates, like 16kHz. The broad conclusion was that the noise is high and the big spur moves down close to 1 kHz where it is most audible; it is best in most cases to sample at 48 kHz, 96 kHz, or something else high and decimate. And live with the processing load. This applies specifically to the PJRC Audio Adapter and the Teensy 3.6. At least check it out before using anything like 16 kHz.

Happy code writing! Bob
 
With T3.1 and PJRC AA I've got very good results from robsoles code example (see the reference in my post #1) that uses codec as the clock master. I modified it for 16ksps. This was using a 3y.o. audio library. But now I have trouble with this code on T3.6 - at the very least I can not get the right DAC channel working. I've also tried calling Frank B routine to change the T3.6 master sampling clock but got nothing.

Mind you all of this happened after a monstrous merge of the main code bases and my changes to the audio library across several library revisions, so I may as well undo the library merge and start anew...
 
Thanks, I now understand! It would be interesting to sometime see measurements of the noise/spurs with the SGTL5000 as master.

GL, Bob
 
I've also tried calling Frank B routine to change the T3.6 master sampling clock but got nothing.
Fixed that - forgot to switch AudioInput(Output)I2Sslave to AudioInput(Output)I2S. Both DAC channels are working, but it is very noisy at 16ksps with the spectrum bar showing large audio spurs (not moving with tuning). It was not like that with the codec PLL used as a I2S clock master, but something prevents the right DAC channel from working with that old code.
 
Bob, the interesting thing is that my RX PCB has an extra synth output from Si5338 with a very low (sub 1ps) jitter. It is not a universal solution but I am inclined to use it as an I2S master clock somehow in the beta revision of the PCB.

Right now I want to repair the robsoles solution somehow, and this is not trivial - too many things changed in the audio library in the last 4 years.
 
Could anyone with some I2S knowledge (Teensy 3.x and SGTL5k) give me a hint/help on how to use an external low jitter programmable source for either BCLK or MCLK to bypass the internal fractional synth ? I have only one spare external synth output, so the rest of the timing signals have to be derived from this reference by either T3.x or SGTL (whatever is easier).

I can dig into the reference manuals myself but I am currently overwhelmed with other tasks related to the RX adapter. So I would appreciate any help on the I2S side of things.
 
Ok, here is my best guess how to use the external MCLK with minimal changes to the Audio library.

I am going to route the external synth clock to the existing MCLK pin on Teensy, then:
- set the MOE bit in the I2S0_MCR register to 0 (output_i2s.cpp file, config_i2s() function);
- remove the I2S0_MDR configuration line (same place);

I will be ordering the "beta" version PCBs for my RX fairly soon, so at least a "probably yes" or "probably no" answer would really, really help...
 
Since no suggestions came up so far, I'll share what I found:
1. Looking at the Mclk signal generated by K66 frac synth for 16ksps (Mclk=4.096MHz) causes tears in my eyes - the jitter is clearly visible on just a single period of the Mclk output. The scope even refuses to measure the frequency/period of the Mclk when used with a non-standard sampling frequency (it is visually clean at standard sampling frequencies).
2. Setting I2S0_MCR register MOE bit to 0 (in fact the entire register can be zeroed) and supplying an external 4.096MHz clock from an external SG works fine on the uP side, K66 generates proper frequencies on the Bclk and LRclk outputs, with no visible jitter on any of the 3 clocks.
3. But, the codec does not properly reset/initialize if the Mclk is present (supplied by a SG) at reboot/reload. The only "sequence" that consistently (100%) works is this:
- disconnect the external Mclk source (from a SG);
- compile and load a standard Audio library config with Teensy supplying all clocks;
- compile and load a modified Audio library config with I2S0_MCR set to 0;
- connect the external Mclk source (from a SG);
Any deviation from this sequence fails to init the codec properly. The Teensy audio isr/dma is working just fine but it gets 0s from the codec.
 
Maybe, hopefully, someone who has written a bit of code for SGTL5k will give a non-binding friendly hint perhaps :) ... Or am I alone here ?
 
If your oscilloscope cannot measure the 4 MHz MCLK, something is wrong with your oscilloscope (what is the bandwidth? below 100 MHz do not even think about measuring jitter 10%from 4 MHz is already 40 Mhz; IMHO, 1% jitter requires 1000Mhz bandwidth).

No problem using external clock, and using I2S in slave mode. It has been done and reported on this forum some time ago (https://forum.pjrc.com/threads/27215-24-bit-audio-boards) It uses an external clock to ave I2S is slave mode.
 
The jitter level at 4.096MHz MCLK has to be seen to be believed coming from the K66 fractional divider (and I am not a novice to digital design).

I've found a temporary workaround - if the K66 is set for 168MHz F_CPU, then an integer divider (1, 41) gives a ~4.098MHz MCLK that is perfectly clean visually. So for a "plan B" I can simply recompute Hilbert FIR coefficients plus few constants in my code and be set. The only downside is the loss of T3.2 compatibility.

I decided to wire the external synth clock to the MCLK pin via a 0ohm resistor on the next PCB revision (which is needed for other reasons). But soldering a jumper wire to a QFN synth chip on the existing "alpha" PCB for a proper test is extremely difficult. But since I have a workable plan B I think I am OK.
 
Just a minor update - Kinetis synth makes a visually clean Bclk with the mulitplier of 1 or 2 and this is consistent with the K66 reference manual, chapter 61.5.1.1

I would guess this is related to using a single or both edges of the selected clock source. However any non-reducible fraction with the multiplier >2 produce very large jitter on the Bclk that is "well beyond visible" on a 100MHz/1Gsps consumer grade DSO and on an old analog Tek 475A, something on an order of 5%.

For designs that require non-standard sampling frequencies this is usually not a fundamental problem - just deal with some deviation from the standard sampling frequency mathematically and set the I2S0_MDR to the closest MULT / DIV pair where MULT <= 2 (the actual register fields must be decremented by 1).

For designs that require a standard sampling frequency - use the Teensy frequency setting in the Arduino Tools menu that calls for a MCLK_MULT of 1 or 2 (check the output_i2s.cpp file in the Audio library).

For prosumer audio quality use an external Bclk, even a cheap, low end Silabs syth will give more flexibility on the sampling rate selection and a decent jitter control.

I am still a bit confused/frustrated why my 4 y.o. code based on the master96k function (Teensy as Bclk master, SGTL5k as the I2S master) refuses to work with the latest toolset (all the I2S clocks are present and visually clean), but it is not a priority for me any more. I have other solutions that work.
 
Status
Not open for further replies.
Back
Top