Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 6 of 6

Thread: Change sample rate for Teensy 4 (vs Teensy 3)

  1. #1
    Senior Member
    Join Date
    Oct 2015
    Location
    Vermont, USA
    Posts
    189

    Change sample rate for Teensy 4 (vs Teensy 3)

    Hi All,

    Previously, I made an extension of the audio library to enable float32 audio processing for the Teensy 3.5/3.6 (see Tympan library here). With Teensy 4, a bunch of stuff has changed, which I'm working through.

    One troublesome area that I've hit is how to enable the user (me!) to change the sample rate of the audio system. Does anyone have suggestions on how to change the I2S bus rates for Teensy 4?

    For Teensy 3, I used the many helpful posts from @FrankB, including:

    https://forum.pjrc.com/threads/38753...l=1#post121365

    and

    https://forum.pjrc.com/threads/38753...l=1#post188812

    I shamelessly copied the examples above (with very modest additions) and turned it into the code below (again, for Teensy 3):

    Code:
    float AudioOutputI2S_F32::setI2SFreq(const float freq_Hz) {
    #if defined(KINETISK)
    	int freq = (int)freq_Hz;
      typedef struct {
        uint8_t mult;
        uint16_t div;
      } __attribute__((__packed__)) tmclk;
    
      const int numfreqs = 16;
      const int samplefreqs[numfreqs] = { 2000, 8000, 11025, 16000, 22050, 24000, 32000, 44100, (int)44117.64706 , 48000, 88200, (int)(44117.64706 * 2), 96000, 176400, (int)(44117.64706 * 4), 192000};
    
    #if (F_PLL==16000000)
      const tmclk clkArr[numfreqs] = {{4, 125}, {16, 125}, {148, 839}, {32, 125}, {145, 411}, {48, 125}, {64, 125}, {151, 214}, {12, 17}, {96, 125}, {151, 107}, {24, 17}, {192, 125}, {127, 45}, {48, 17}, {255, 83} };
    #elif (F_PLL==72000000)
      const tmclk clkArr[numfreqs] = {{832, 1125}, {32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {32, 375}, {128, 1125}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375}, {249, 397}, {32, 51}, {185, 271} };
    #elif (F_PLL==96000000)
      const tmclk clkArr[numfreqs] = {{2, 375},{8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {8, 125},  {32, 375}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125}, {151, 321}, {8, 17}, {64, 125} };
    #elif (F_PLL==120000000)
      const tmclk clkArr[numfreqs] = {{8, 1875},{32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {32, 625},  {128, 1875}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625}, {178, 473}, {32, 85}, {145, 354} };
    #elif (F_PLL==144000000)
      const tmclk clkArr[numfreqs] = {{4, 1125},{16, 1125}, {49, 2500}, {32, 1125}, {49, 1250}, {16, 375},  {64, 1125}, {49, 625}, {4, 51}, {32, 375}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375} };
    #elif (F_PLL==180000000)
      const tmclk clkArr[numfreqs] = {{23, 8086}, {46, 4043}, {49, 3125}, {73, 3208}, {98, 3125}, {37, 1084},  {183, 4021}, {196, 3125}, {16, 255}, {128, 1875}, {107, 853}, {32, 255}, {219, 1604}, {214, 853}, {64, 255}, {219, 802} };
    #elif (F_PLL==192000000)
      const tmclk clkArr[numfreqs] = {{1, 375}, {4, 375}, {37, 2517}, {8, 375}, {73, 2483}, {4, 125}, {16, 375}, {147, 2500}, {1, 17}, {8, 125}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125} };
    #elif (F_PLL==216000000)
      const tmclk clkArr[numfreqs] = {{8, 3375}, {32, 3375}, {49, 3750}, {64, 3375}, {49, 1875}, {32, 1125},  {128, 3375}, {98, 1875}, {8, 153}, {64, 1125}, {196, 1875}, {16, 153}, {128, 1125}, {226, 1081}, {32, 153}, {147, 646} };
    #elif (F_PLL==240000000)
      const tmclk clkArr[numfreqs] = {{4, 1875}, {16, 1875}, {29, 2466}, {32, 1875}, {89, 3784}, {16, 625}, {64, 1875}, {147, 3125}, {4, 85}, {32, 625}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625} };
    #endif
    
      for (int f = 0; f < numfreqs; f++) {
        if ( freq == samplefreqs[f] ) {
          while (I2S0_MCR & I2S_MCR_DUF) ;
    		I2S0_MDR = I2S_MDR_FRACT((clkArr[f].mult - 1)) | I2S_MDR_DIVIDE((clkArr[f].div - 1));
    		return (float)(F_PLL / 256 * clkArr[f].mult / clkArr[f].div);
        }
      }
    #endif
      return 0.0f;
    }
    Looking at Teensy 4, I'm not even quite sure where to begin. I looks like the Teensy 4 setup has some important differences...for example, the Teensy 4 compatible AudioOutputI2S class uses a function called set_audioClock(). If I want to change the sample rate, do I only need to call this function, or is this an unrelated function?

    Any guidance would be greatly appreciated!

    Chip

  2. #2
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,154
    This works for me on T4B2. It's a newer version from Frank B.

    Pete
    P.S. I've only used it for 12000Hz but it should be good for other rates.

    Code:
    #include <Audio.h>
    #include <utility/imxrt_hw.h>
      
    void setI2SFreq(int freq) {
      // PLL between 27*24 = 648MHz und 54*24=1296MHz
      int n1 = 4; //SAI prescaler 4 => (n1*n2) = multiple of 4
      int n2 = 1 + (24000000 * 27) / (freq * 256 * n1);
      double C = ((double)freq * 256 * n1 * n2) / 24000000;
      int c0 = C;
      int c2 = 10000;
      int c1 = C * c2 - (c0 * c2);
      set_audioClock(c0, c1, c2, true);
      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 
    //Serial.printf("SetI2SFreq(%d)\n",freq);
    }

  3. #3
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,530
    The basic difference is that the T3.x has a different way of generating the I2S master clock: as seen in post #1, the single T3 I2S has its own fractional divider to generate the MCLK, while the three SAIs in the T4 can each have a different clock source or use a common one. The preferred (and configured by the audio lib) clock source is PLL4, so the code in #2 might well be used to set it.

  4. #4
    Senior Member DD4WH's Avatar
    Join Date
    Oct 2015
    Location
    Central Europe
    Posts
    445
    Pete and FrankB, you saved my evening! :-)

    Thanks a lot for the code, works fine for the Teensy audio board and T4!

  5. #5
    Senior Member
    Join Date
    Oct 2015
    Location
    Vermont, USA
    Posts
    189
    Presumably, for this function: void setI2SFreq(int freq), the "freq" is the sample rate (in Hz) that I want?

    So, if I want 44100 (ie, the default), I would call setI2SFreq(44100)? But, if I wanted 48 kHz, I would call setI2SFreq(48000)?

    Do I have it right?

    Many thanks!

    Chip

  6. #6
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,154
    Yes, frequency is in Hz.

    Pete

Posting Permissions

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