Forum Rule: Always post complete source code & details to reproduce any issue!
Page 3 of 3 FirstFirst 1 2 3
Results 51 to 62 of 62

Thread: Reset audio board codec SGTL5000 in realtime processing

  1. #51
    There are multiple sources for the frac synth in Teensy - F_CPU, F_PLL etc. For 180MHz it is F_CPU (I think), so the default Mclk = 180MHz * (16 / 255) = ~11.29MHz, and the SR is ~11.29MHz / 256 = ~44.1ksps.

    Let's say you want ~92ksps, then Mclk = 92ksps*256 = ~23.5MHz, so you need a synth ratio close to 23.5/180, a good candidate would be 2/15 (MULT=2, DIV=15). So the exact SR will be 180MHz * (2 / 15) / 256 = 93.75ksps. It is the nominator (MULT), not the denominator that needs to be 1 or 2.

    I will be traveling for the next few days, should be back on Monday if you need more help.

  2. #52
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,366
    Frank,
    the numbers should only to be small, avoiding too high intermediate frequencies, I believe also an even DIV would be better than an odd one, but I have no proof.

    for SGTL500 you get 192 kHz you would need a MCLK of 49.152 MHz (192000*256)
    using F_CPU=240 MHz you would need MULT = 128 and DIV 625 but that is unrealistic

    now if you divide all by 18 and use MULT=8 and DIV=39 you get a MCLK of 49.2308 MHz and a sampling frequency of 192.3 kHz
    As DIV is an odd number let us try an odd MULT, say 7 then with DIC=34 you get a sampling frequency of 193.0147 kHz

    For 180 MHz the required scaling of 3.621 is easily achieved but rounding down to 3.62 one gets MULT = 50 and DIV=181 for a sampling frequency of 194.2 kHz
    dividing all by 10 one gets for a MULT=5 and DIV = 18 a sampling frequency of 195.3215 kHz
    etc. etc.
    a lot of possibilities to play.

    Edit: I see vladn has some other rules, but I agree the MULT should be as small as possible. After all the CPU has to generate the intermediate frequency that should not be too high

  3. #53
    Quote Originally Posted by WMXZ View Post
    I see vladn has some other rules, but I agree the MULT should be as small as possible.
    It is not my personal rule, it is in the K6x reference manual - only 1 and 2 in the MULT generate low jitter Mclk. In case MULT=2 the divider simply uses both edges of the reference clock. Any MULT > 2 requires true fractional synthesis. Just look at the Mclk on any decent scope (I did).

  4. #54
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,679
    This is the code (slightly modified) that generated the table for https://forum.pjrc.com/threads/38753...he-sample-rate

    (Dunno if it's useful here, but I think I have not published it so far, so anyway... maybe it can help to find better values by modfiying it ( as a starting point) )

    Code:
    /*
       (c) Frank Bösing
       Sketch to calculate I2S FRACT / DIVIDE values
    
    
    */
    
    
    /* Quote from manual:
    
    
       The MCLK fractional clock divider uses both clock edges from the input clock to
      generate a divided down clock that will approximate the output frequency, but without
      creating any new clock edges. Configuring FRACT and DIVIDE to the same value will
      result in a divide by 1 clock, while configuring FRACT higher than DIVIDE is not
      supported. The duty cycle can range from 66/33 when FRACT is set to one less than
      DIVIDE down to 50/50 for integer divide ratios, and will approach 50/50 for large noninteger
      divide ratios. There is no cycle to cycle jitter or duty cycle variance when the
      divide ratio is an integer or half integer, otherwise the divider output will oscillate
      between the two divided frequencies that are the closest integer or half integer divisors of
      the divider input clock frequency. The maximum jitter is therefore equal to half the
      divider input clock period, since both edges of the input clock are used in generating the
      divided clock.
    */
    
    
    const float pllfreqs[] = {16000000, 72000000, 96000000, 120000000, 144000000, 168000000, 180000000, 192000000, 216000000, 240000000};
    const float samplefreqs[] = { 8000, 11025, 16000, 22050, 32000, 44100, 44117.64706 , 48000, 88200, 44117.64706 * 2, 96000, 176400, 44117.64706 * 4, 192000/*, 200000, 210000, 220000, 230000, 240000, 250000, 260000, 270000, 280000, 290000, 300000*/};
    const int numpll = sizeof(pllfreqs) / sizeof(float);
    const int numfreqs = sizeof(samplefreqs) / sizeof(float);
    
    
    void calc(const float pll, const float freq) {
      float p = pll / 256.0;
      float err = 1e6;
      int mu = 0;
      int di = 0;
      for (int m = 1; m < 256 ; m++) {
        for (int d = m; d < 4096; d++) {
          float f = (p * m) / d;
          float e = fabs(freq - f);
          if (e < err) {
            mu = m;
            di = d;
            err = e;
          }
        }
      }
    #if 1
      Serial.printf("{%d, %d}", mu, di);
    #else
      Serial.printf("{%d, %d /* %.1fHz */}", mu, di, (pll * mu / di) / 256.0);
    #endif
    
    
    }
    
    
    void setup() {
      delay(1000);
    
    
      Serial.printf("const int numfreqs = %d;\n", numfreqs);
    
    
      Serial.print("const int samplefreqs[numfreqs] = {");
      for (int p = 0; p < numfreqs; p++)
        Serial.printf("%.0f%s", samplefreqs[p], (p <  numfreqs - 1) ? ", " : " " );
      Serial.println("};");
    
    
      Serial.println();
    
    
      for (int p = 0; p < numpll; p++) {
        Serial.printf("#%s (F_PLL==%.0f)\n", p == 0 ? "if" : "elif", pllfreqs[p] );
        Serial.printf(" const tmclk clkArr[numfreqs] = {");
        for (int s = 0; s < numfreqs; s++) {
          calc(pllfreqs[p], samplefreqs[s]);
          if (s < numfreqs - 1) Serial.print(", ");
        }
        Serial.println("};");
      }
      Serial.println("#endif");
    }
    
    
    void loop() {}
    Edit: Attention: bugfix in code

    It tries to generate the desired frequency as close as possible. Perhaps there is a better way to do this?


    The manual says:
    The MCLK fractional clock divider uses both clock edges from the input clock to
    generate a divided down clock that will approximate the output frequency, but without
    creating any new clock edges. Configuring FRACT and DIVIDE to the same value will
    result in a divide by 1 clock, while configuring FRACT higher than DIVIDE is not
    supported. The duty cycle can range from 66/33 when FRACT is set to one less than
    DIVIDE down to 50/50 for integer divide ratios, and will approach 50/50 for large noninteger
    divide ratios. There is no cycle to cycle jitter or duty cycle variance when the
    divide ratio is an integer or half integer, otherwise the divider output will oscillate
    between the two divided frequencies that are the closest integer or half integer divisors of
    the divider input clock frequency. The maximum jitter is therefore equal to half the
    divider input clock period, since both edges of the input clock are used in generating the
    divided clock.
    Last edited by Frank B; 05-17-2018 at 10:08 PM. Reason: Bugfix

  5. #55
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,679
    "there is no cycle to cycle jitter or duty cycle variance when the
    divide ratio is an integer or half integer, "

    - maybe it's possible to modify the program above to find jitter-free Samplerates?

  6. #56
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,679
    So, jitter-free freqs with 50%50 duty cycle are for example 175781Hz, 140625, 117188, 100446, 46875 Hz.
    Can someone confirm this ? I'm not sure if my calculation is right.

  7. #57
    Senior Member bmillier's Avatar
    Join Date
    Apr 2016
    Location
    Halifax, N.S. Canada
    Posts
    170
    Frank: here is the formula from the K66 datasheet (its in a table, but this is the gist of it):
    **********
    MCLK Divide
    Sets the MCLK divide ratio such that: MCLK output = MCLK input * ( (FRACT + 1) / (DIVIDE + 1) ).
    FRACT must be set equal or less than the value in the DIVIDE field.
    NOTE:
    When using fractional divide values, the MCLK duty cycle will not always be 50/50.
    *******
    What Vladn called MULT, Freescale labels FRACT+1. Note the "+1"s.
    MCLK input, in your case is 180 MHZ. Vladn has found that FRACT +1 needs to be 1 or two. Freescale mentions that they can use both edges of the input clock (i.e. basically doubling the clock frequency) , so that explains how you can use the "2" for FRACT+1. There is no PLL in this circuit, so you are not actually multiplying the 180 MHZ clock by what Vladn refers to as MULT. They are just using a fractional divider circuit (sometimes called a pulse swallowing divider) to simulate what would be an integer frequency multiplication followed by a subsequent integer division. This fractional divider will always have some jitter when it is not dividing by an integer value.
    That said, if you take the formula you derived: SR = 703125 * MULT /DIV
    and use 1 or 2 for MULT, you can find suitable DIV values easily to get SRs close to the ones you now use. i.e.
    703125 *1/7 = 100.466 KHz
    703125 *1/14 = 50.223 KHz
    703125 *2/6 = 234.375 KHz
    The "output_i2s.cpp" code takes into account the "+1"s stated in the Freescale formula which I noted above, so you can set the MULT and DIV values in output_i2s.cpp to the values of the 3 examples above.
    I don't know if this explains things better- I am basically agreeing with vladn's observations, but trying to explain them using Freescale's documentation and knowing something about the clock generation circuitry that I believe they are using in the K66.(Freescale is sketchy on details)
    PS- I wrote this before seeing your current post.

  8. #58
    "There is no cycle to cycle jitter or duty cycle variance when the divide ratio is an integer or half integer, otherwise..." If you reduce the fraction by the GCD that precisely means that MULT could be either 1 or 2.

    "703125 *2/6 = 234.375 KHz" - it makes sense to use irreducible fractions, 1 / 3 is better For example to get Mclk ~4096k (~16ksps) for my AF I/Q processing I use 2 / 47 ratio on a 96MHz system PLL clock reference (which covers F_CPU of 24, 48 and 96MHz).
    Last edited by vladn; 05-18-2018 at 12:31 AM.

  9. #59
    Senior Member DD4WH's Avatar
    Join Date
    Oct 2015
    Location
    Central Europe
    Posts
    492
    Hi Vlad, Walter, Frank, Brian,

    thanks a lot to you all for the excellent information and also your code, Frank B!

    I was confused by the nominator/denominator english terms . . . So now that is clear, thanks Vlad! And that hint on "+1" is also very helpful, Brian!

    Now it is time for me to carefully digest all that; an excellent opportunity with that longer weekend here in Central Europe ;-). I will be travelling, so time to experiment with real hardware will be the weekend after.

    I will report back with results then, however I am not sure whether I will be able to really measure the jitter. But I will have a close look on spurs in my receive spectrum, once I have incorporated all the info you gave me into the Teensy Convolution SDR.

    Thanks a lot again!

    All the best,

    Frank DD4WH

  10. #60
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,366
    Anyone has some figures or reference on the amount of jitter noise for fractional dividers?

  11. #61
    Sorry, can't help on this without digging into the math textbooks. There probably is a jitter calc somewhere for simple fractional dividers. But if I can clearly see the Mclk edge jitter on the scope it makes me uncomfortable.

    SiLabs uses more sophisticated fractional divider HW with some form of edge correction and their reference PLLs runs at much higher frequencies, so the jitter is 1..3 orders of magnitude smaller. For example Si5338 and Si514 reference is ~2.5GHz. They have even faster ICs, but they are not suitable for a battery powered project like mine. But even those can not compare to the properly designed crystal and analog LC oscillators (ignoring the heavy frequency drift of the latter).

    Also we should not forget that SDR community is a minority here. For some audio apps having a standard sampling rate is a must. For other audio apps (like synth) it is not that critical. My minor suggestion to Paul is to make AUDIO_SAMPLE_RATE_EXACT a class variable, rather than a #define constant. Then we can all be happy .
    Last edited by vladn; 05-21-2018 at 10:09 PM.

  12. #62
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,366
    Quote Originally Posted by vladn View Post
    Sorry, can't help on this without digging into the math textbooks. There probably is a jitter calc somewhere for simple fractional dividers. But if I can clearly see the Mclk edge jitter on the scope it makes me uncomfortable.
    What I was looking for is some graphs or formula that relate % of MCLK jitter to dB spectral noise level increase. I say spectral, as I would assume that spectral noise level are nor equally impacted by MCLK jitter.

    Edit:
    OK, I can myself use Google, so I found

    http://www.dsplog.com/2012/02/22/adc...ization-noise/
    http://www.analog.com/media/en/techn...tes/AN-756.pdf

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •