Discussion about a simple way to change the sample-rate

Hi,

I just tried the code out in message #44 and received the following error message when. compiling.

'clkArr' was not declared in this scope

Any ideas?

Thanks!
 
Looking at the code its definition is based on the value of the F_PLL.

What Teensy and clock speed is in use?

Write a short sketch using the same compile params and speed and Serial.print( F_PLL ) and Serial.print( F_CPU )
 
Thanks for replying so quick!

I'm using T3.5 running at 168MHz. I just changed it to 120MHz and it compiled OK!!
 
Hi Frank,
I wanted to tryout your sample rate changing code for the Teensy 4, which I pulled from CorBee's Bat Detector repo on github. It seems that it's not perhaps compatible with the Teensy 4 as I2S0_MCR & I2S_MCR_DUF are showing up as undefined during compilation. On a more recent thread Paul mentioned that the 3.6 and 4 have different ways of using the MCLK as seen here. What changes should be needed for the Teensy 4? Any resources I should look into?
Thanks
-Akshay
 
Hi all

This is my first post on this forum and it touches on a subject that I am having difficulty getting my head around. I know this thread is now somewhat ancient history but it turned up when I was searching for a way of resolving my particular problem

Unlike some I am not interested in a high audio sample rate but in a relatively low one. The reason is that I want to play a simple WAV file that has been stored on the flash memory of an Adafruit Feather M4 Express. The 2MB of space available allows the storage of about 2 minutes an 8 bit mono audio with sample rate of 16000 Hz. I wish to play this over one of the internal DACs on the SAMD51.

I have used an updated version of the SamdAudio library to get it working on Feather M0 Express ( https://github.com/Gambalunga/Audio_FeatherM0 ) but that will not compile for the M4.

I have tried using the Adafruit fork of the Teensy Audio library and managed to get the example sketch WavFilePlayer.ino (with a tiny mod) to compile and load. Clearly, however, 2MB of on board flash is not going give any useful period of sound at stereo 44117 Hz. and I can get it playing about 11 seconds of music.

I noted the section of code below but I am not sure if it is relevant to my problem or even how to implement it in the sketch.
Here's the same for the internal DACs :

Code:
void setDACFreq(int freq) {
const unsigned config = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_CONT | PDB_SC_PDBIE | PDB_SC_DMAEN;
    PDB0_SC = 0;
    PDB0_IDLY = 1;
    PDB0_MOD = round((float)F_BUS / freq ) - 1;    
    PDB0_SC = config | PDB_SC_LDOK;
    PDB0_SC = config | PDB_SC_SWTRIG;
    PDB0_CH0C1 = 0x0101;    
}

edit: Added one line

I noticed the following section of code in AudioStream.h and wondered if it could be modified to give me the 16000 sample rate that I require.
Code:
#ifndef AUDIO_SAMPLE_RATE_EXACT
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define AUDIO_SAMPLE_RATE_EXACT 44117.64706 // 48 MHz / 1088, or 96 MHz * 2 / 17 / 256
#elif defined(__MKL26Z64__)
#define AUDIO_SAMPLE_RATE_EXACT 22058.82353 // 48 MHz / 2176, or 96 MHz * 1 / 17 / 256
#elif defined(__SAMD51__)

//#define AUDIO_CLKRATE (SystemCoreClock >> 6)
//#define AUDIO_PRESCALER TC_CTRLA_PRESCALER_DIV64
//#define AUDIO_SAMPLE_RATE_EXACT 22058.82353 // 120 MHz / 64 / 85 
//#define AUDIO_TC_FREQ 22000

#define AUDIO_CLKRATE (VARIANT_GCLK2_FREQ >> 4)
#define AUDIO_PRESCALER TC_CTRLA_PRESCALER_DIV16
#define AUDIO_SAMPLE_RATE_EXACT 44014.085 // 100 MHz / 16 / 142
#define AUDIO_TC_FREQ 44100

#endif // SAMD51
#endif // AUDIO_SAMPLE_RATE_EXACT

It seems to me that if the following were defined with different values I may be able to get the 16000 Hz that I require:

AUDIO_CLKRATE (VARIANT_GCLK2_FREQ >> 4)
AUDIO_PRESCALER TC_CTRLA_PRESCALER_DIV16
AUDIO_SAMPLE_RATE_EXACT 44014.085 // 100 MHz / 16 / 142
AUDIO_TC_FREQ 44100

Does anyone have any idea of how this may be made to function?

perhaps defining
AUDIO_SAMPLE_RATE_EXACT 16025.641 // 100 MHz / 16 / 390
and
AUDIO_TC_FREQ 16000

It seems too easy and I am not sure if that "390" has to be specified somewhere else or even if it can be used.
 
This forum is for Teensy. If you're using Adafruit's hardware (and their modified copies of Teensy's software), ask for support on Adafruit's forum.
 
@FrankB, I am having a hard time understanding how to change the sampling frequency of the PT8211 using your routines...
When I try to use your routines I2S_MDR_DIVIDE and I2S_MDR_FRACT are not defined.
These are my #include
#include <Arduino.h>
#include <Audio.h>
#include <AudioStream.h>
#include <DMAChannel.h>
What am I missing?
Thank you so much!
 
On a Teensy4?
Try this:
Code:
#include <utility/imxrt_hw.h> 


void setI2SFreq(int freq) { //Teensy 4
  // 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 
}
 
This works pretty good! thanks Frank B,
I'm getting some issues with abrupt changes to lower values, sound turns off if I switch from 44100 to 22050, but it works fine with other values ...and I have no idea why,

45100 -> 22550 ok
44100 -> 22050 no sound
43100 -> 21550 ok
 
I don't know, why. Maybe try to disable the interrupts when switching the rate. I have never tried that - But I know of an application that sets 176khZ in one step, without problems.
 
I don't know, why. Maybe try to disable the interrupts when switching the rate. I have never tried that - But I know of an application that sets 176khZ in one step, without problems.

that's the first thing I tried, with no luck. Indeed I can change the frequency from 44100 to 88200 with no problem, the 'no sound' issue occurs when jumping below 44100, anyway what I did is to disable 1 octave changes below 44k1,
 
Thanks Frank B. This is my first post. I want Teensy 4.0 to be the I2S master and to generate MCLK =12.288Mhz, BCLK=1.024Mhz (64xLRCLK) and LRCLK = 16khz to TI PCM5242 DAC. I used your code and I was able to generate the clocks.
Unfortunately, MCLK frequency is always fix ratio of 256 to LRCLK. Is there a simpler way to setup I2S clocks. I am guessing set_audioClock() sets the PLL frequency. I still do not understand where MCLK is selected and how BClk and LRClk are generated.
I tried to modify n1 and n2 and C in your code to make it work. But without understanding what the numbers mean, I was not able to make it work.
 
maybe this snippet helps
Code:
    //PLL:
        int fs = fsamp;
        int ovr = 2*(NCHAN_I2S*32);

        // PLL between 27*24 = 648MHz und 54*24=1296MHz
        int n0 = 26; // targeted PLL frequency (n0*24 MHz) n0>=27 && n0<54
        int n1, n2;
        do
        {   n0++;
            n1=0;
            do
            {   n1++; 
                n2 = 1 + (24'000'000 * n0) / (fs * ovr * n1);
            } while ((n2>64) && (n1<=8));
        } while ((n2>64 && n0<54));
        Serial.printf("fs=%d, n1=%d, n2=%d, %d (>=27 && <54) ", fs, n1,n2,n1*n2*(fs/1000)*ovr/24000);

        double C = ((double)fs * ovr * n1 * n2) / (24000000.0f);
        Serial.printf(" C=%f\r\n",C);
        int c0 = C;
        int c2 = 10'000;
        int c1 =  C * c2 - (c0 * c2);
        set_audioClock(c0, c1, c2, true);
this relates the MCLK to the sampling frequency by specifying the number of channels (NCHAN_I2S) and word size (32).
obviously, the allowed ratio MCLK / Fs is given in ADC datasheet
relating sampling frequency(framesync) and Bitclock must also be done in SAI configuration
 
maybe this snippet helps
Code:
    //PLL:
        int fs = fsamp;
        int ovr = 2*(NCHAN_I2S*32);

        // PLL between 27*24 = 648MHz und 54*24=1296MHz
        int n0 = 26; // targeted PLL frequency (n0*24 MHz) n0>=27 && n0<54
        int n1, n2;
        do
        {   n0++;
            n1=0;
            do
            {   n1++; 
                n2 = 1 + (24'000'000 * n0) / (fs * ovr * n1);
            } while ((n2>64) && (n1<=8));
        } while ((n2>64 && n0<54));
        Serial.printf("fs=%d, n1=%d, n2=%d, %d (>=27 && <54) ", fs, n1,n2,n1*n2*(fs/1000)*ovr/24000);

        double C = ((double)fs * ovr * n1 * n2) / (24000000.0f);
        Serial.printf(" C=%f\r\n",C);
        int c0 = C;
        int c2 = 10'000;
        int c1 =  C * c2 - (c0 * c2);
        set_audioClock(c0, c1, c2, true);
this relates the MCLK to the sampling frequency by specifying the number of channels (NCHAN_I2S) and word size (32).
obviously, the allowed ratio MCLK / Fs is given in ADC datasheet
relating sampling frequency(framesync) and Bitclock must also be done in SAI configuration


I modified Frank B's original code with the above snippet. NCHAN_I2S=2 and fs=16khz
I got MCLK=2Mhz, BCLK=510Khz and LRCLK=7.998Khz.
The sampling frequency went from 16khz to 8Khz. The BCLK to LRCLK ratio is the same at 64. MCLK to LRCLK ratio changed to 250 from 256.
There are only 5 parameters. c0, c1=0 (fix), c2=10,000, n1 and n2. c0 to c2 are used to set PLL frequency; n1 and n2 are dividers. I just could not figure out how these 5 parameters are used to setup the MCLK or where MCLK frequency is configured. There is no example in the ref manual. I know how the PLL frequency is setup by set_audioClock, but I do not understand how MCLK, BCLK and LRCLK are produced. Any help would be appreciated.
 
You can use the following example to adapt your program
Code:
//MCLK =12.288Mhz, BCLK=1.024Mhz (64xLRCLK) and LRCLK = 16khz (2 Bytes/word)

#define FSAMP 16000
#define NCHAN_I2S 2
#define N_BYTES 2

#define N_BITS (8*N_BYTES)
#if N_BITS==16
  typedef uint16_t data_t;
#elif N_BITS==32
  typedef uint32_t data_t;
#endif


#define RCR2_DIV 12
#define MCLK_OVR (RCR2_DIV*2*(NCHAN_I2S*N_BITS))

//Bitclock = MasterClock/(2*RCR2_DIV)
//Framclock = Bitclock/(NCHAN_I2S*NBITS)

float mclk,fclk,bclk;


#define NSAMP 128
#define NBUF_I2S (NCHAN_I2S*NSAMP)
DMAMEM data_t tdm_rx_buffer[2*NBUF_I2S] __attribute__((aligned(32)));
//int32_t acq_rx_buffer[NBUF_I2S];

volatile uint32_t acq_count=0;
static void acq_isr(void);

#ifndef I2S_DMA_PRIO
//  #define I2S_SAI_PRIO 4*16
  #define I2S_DMA_PRIO 5*16
#endif

// ACQ setup functions
    #include "DMAChannel.h"
    DMAChannel dma;
  
    #define IMXRT_CACHE_ENABLED 2 // 0=disabled, 1=WT, 2= WB

    PROGMEM
    void set_audioClock(int nfact, int32_t nmult, uint32_t ndiv, bool force) // sets PLL4
    {
        if (!force && (CCM_ANALOG_PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_ENABLE)) return;

        CCM_ANALOG_PLL_AUDIO = CCM_ANALOG_PLL_AUDIO_BYPASS | CCM_ANALOG_PLL_AUDIO_ENABLE
                    | CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2) // 0: 1/4; 1: 1/2; 2: 1/1
                    | CCM_ANALOG_PLL_AUDIO_DIV_SELECT(nfact);

        CCM_ANALOG_PLL_AUDIO_NUM   = nmult & CCM_ANALOG_PLL_AUDIO_NUM_MASK;
        CCM_ANALOG_PLL_AUDIO_DENOM = ndiv & CCM_ANALOG_PLL_AUDIO_DENOM_MASK;
        
        CCM_ANALOG_PLL_AUDIO &= ~CCM_ANALOG_PLL_AUDIO_POWERDOWN;//Switch on PLL
        while (!(CCM_ANALOG_PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_LOCK)) {}; //Wait for pll-lock
        
        const int div_post_pll = 1; // other values: 2,4
        CCM_ANALOG_MISC2 &= ~(CCM_ANALOG_MISC2_DIV_MSB | CCM_ANALOG_MISC2_DIV_LSB);
        if(div_post_pll>1) CCM_ANALOG_MISC2 |= CCM_ANALOG_MISC2_DIV_LSB;
        if(div_post_pll>3) CCM_ANALOG_MISC2 |= CCM_ANALOG_MISC2_DIV_MSB;
        
        CCM_ANALOG_PLL_AUDIO &= ~CCM_ANALOG_PLL_AUDIO_BYPASS;   //Disable Bypass
        Serial.printf("PLL %f\r\n",24.0f*((float)nfact+(float)nmult/(float)ndiv));
    }

    void acq_init(int fsamp)
    {
        CCM_CCGR5 |= CCM_CCGR5_SAI1(CCM_CCGR_ON);

        // if either transmitter or receiver is enabled, do nothing
        if (I2S1_RCSR & I2S_RCSR_RE) return;
        //PLL:
        int fs = fsamp;
        int ovr = MCLK_OVR;  

        // PLL between 27*24 = 648MHz und 54*24=1296MHz
        int n0 = 26; // targeted PLL frequency (n0*24 MHz) n0>=27 && n0<54
        int n1, n2;
        do
        {   n0++;
            n1=0;
            do
            {   n1++; 
                n2 = 1 + (24'000'000 * n0) / (fs * ovr * n1);
            } while ((n2>64) && (n1<=8));
        } while ((n2>64 && n0<54));
        Serial.printf("fs=%d, n1=%d, n2=%d, %d (>=27 && <54) ", fs, n1,n2,n1*n2*(fs/1000)*ovr/24000);

        double C = ((double)fs * ovr * n1 * n2) / (24000000.0f);
        Serial.printf(" C=%f\r\n",C);
        int c0 = C;
        int c2 = 10'000;
        int c1 =  C * c2 - (c0 * c2);
        set_audioClock(c0, c1, c2, true);

        mclk=C*24000000.0/n1/n2;
        
        // 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  // <8
            | CCM_CS1CDR_SAI1_CLK_PODF((n2-1)); // &0x3f // <64

        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));  //Select MCLK

  //configure I2S
        I2S1_RMR = 0;
        I2S1_RCR1 = I2S_RCR1_RFW(4);
        I2S1_RCR2 = I2S_RCR2_SYNC(0) | I2S_TCR2_BCP | I2S_RCR2_MSEL(1)
            | I2S_RCR2_BCD | I2S_RCR2_DIV((RCR2_DIV-1));

        I2S1_RCR3 = I2S_RCR3_RCE;

        I2S1_RCR4 = I2S_RCR4_FRSZ((NCHAN_I2S-1)) | I2S_RCR4_SYWD((NCHAN_I2S-1)) | I2S_RCR4_MF
            | I2S_RCR4_FSE | I2S_RCR4_FSD;
        I2S1_RCR5 = I2S_RCR5_WNW((N_BITS-1)) | I2S_RCR5_W0W((N_BITS-1)) | I2S_RCR5_FBT((N_BITS-1));

        // I2S pins
        CORE_PIN23_CONFIG = 3;  //1:MCLK 
        CORE_PIN21_CONFIG = 3;  //1:RX_BCLK
        CORE_PIN20_CONFIG = 3;  //1:RX_SYNC

        // I2S data pins
        CORE_PIN8_CONFIG = 3;   //RX_DATA0
        IOMUXC_SAI1_RX_DATA0_SELECT_INPUT = 2; // GPIO_B1_00_ALT3, pg 873

  // configure DMA

        dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE((N_BYTES/2)) | DMA_TCD_ATTR_DSIZE((N_BYTES/2));

        dma.TCD->SADDR = &I2S1_RDR0;
        dma.TCD->SOFF = 0;
        dma.TCD->SLAST = 0;
        dma.TCD->NBYTES_MLOFFNO = N_BYTES;

        dma.TCD->DADDR = tdm_rx_buffer;
        dma.TCD->DOFF = N_BYTES;
        dma.TCD->CITER_ELINKNO = 2*NBUF_I2S;
        dma.TCD->BITER_ELINKNO = dma.TCD->CITER_ELINKNO;
        dma.TCD->DLASTSGA = -sizeof(tdm_rx_buffer);
        dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;

        dma.triggerAtHardwareEvent(DMAMUX_SOURCE_SAI1_RX);
//        NVIC_SET_PRIORITY(DMAMUX_SOURCE_SAI1_RX,I2S_SAI_PRIO);

        dma.enable();
        //DMA_SERQ = dma.channel;

        I2S1_RCSR =  I2S_RCSR_FRDE | I2S_RCSR_FR;
        dma.attachInterrupt(acq_isr, I2S_DMA_PRIO); 

    }

    void acq_start(void)
    {
        //DMA_SERQ = dma.channel;
        I2S1_RCSR |= (I2S_RCSR_RE | I2S_RCSR_BCE);
    }

    void acq_stop(void)
    {
        I2S1_RCSR &= ~(I2S_RCSR_RE | I2S_RCSR_BCE);
        //DMA_CERQ = dma.channel;     
    }


    void acq_isr(void)
    {
        uint32_t daddr;
        data_t *src;

        dma.clearInterrupt();
        asm volatile("dsb");
        daddr = (uint32_t) dma.destinationAddress();

        if (daddr < ((uint32_t)tdm_rx_buffer + sizeof(tdm_rx_buffer) / 2)) {
            // DMA is receiving to the first half of the buffer
            // need to remove data from the second half
            src = (data_t*)&tdm_rx_buffer[NBUF_I2S];
        } else {
            // DMA is receiving to the second half of the buffer
            // need to remove data from the first half
            src = &tdm_rx_buffer[0];
        }

        #if IMXRT_CACHE_ENABLED >=1
            arm_dcache_delete((void*)src, sizeof(tdm_rx_buffer) / 2);
        #endif

        //memcpy(acq_rx_buffer,src,sizeof(acq_rx_buffer));
        // process data in acq_rx_buffer
        
        acq_count++;
    }


void setup() {
  // put your setup code here, to run once:
  while(!Serial);
  acq_init(FSAMP);
  
  bclk=mclk/(2*RCR2_DIV);
  fclk=bclk/(NCHAN_I2S*N_BITS);
  
  Serial.printf("MCLK = %.1f\n",mclk);
  Serial.printf("FCLK = %.1f\n",fclk);
  Serial.printf("BCLK = %.1f\n",bclk);


  acq_start();
}

void loop() {
  // put your main code here, to run repeatedly:
  static uint32_t ic=0;
  static uint32_t t0=0;
  if(millis()-t0>1000)
  { t0=millis();
    Serial.printf("%d %d \n",ic++,acq_count);
    acq_count=0;
  }
}
It configures an ADC, but you should be able to modify for a DAC
If you use the audio library, you should compare, understand the differences and modify accordingly.
 
I am looking to change the sample rate of ADC1 to 96khz to speed up the 256bin FFT. I am looking for a ~1ms turn around for knock sensor circuit.

I am running a 4 pole, 16Khz low pass MFB on a Teensy 3.6 with a broadband knock sensor.

How much of this can I apply?
 
Has anyone got this to work on a Teensy 4 with the Audio Shield?

I tried the code below and it compiled, but AUDIO_SAMPLE_RATE_EXACT is still showing up as 44100. I'm calling setI2SFreq(22050) in setup() after enabling the audio shield.


On a Teensy4?
Try this:
Code:
#include <utility/imxrt_hw.h> 


void setI2SFreq(int freq) { //Teensy 4
  // 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 
}
 
Has anyone got this to work on a Teensy 4 with the Audio Shield?

I tried the code below and it compiled, but AUDIO_SAMPLE_RATE_EXACT is still showing up as 44100. I'm calling setI2SFreq(22050) in setup() after enabling the audio shield.

As you can see from the code, it does NOT change AUDIO_SAMPLE_RATE_EXACT and in fact it cannot change this as it is a '#define' symbol.

You can change this symbol in 'hardware/teensy/avr/ boards.txt' by replacing
teensy41.build.flags.defs=-D__IMXRT1062__ -DTEENSYDUINO=158
with
teensy41.build.flags.defs=-D__IMXRT1062__ -DTEENSYDUINO=158 -DAUDIO_SAMPLE_RATE_EXACT=22050

and recompiling all.
NOTE: the usb-audio is hard-coded for 44100
 
I need simple way to change the sample rate and master clock at runtime :rolleyes:
Slowly going through the IMXRT1062 Teensy 4.x data sheets.
For 44,100kHz I need:
MCLK-22,579,200Mhz
BCLK---5,644,800Mhz -8ch-16b.
LRCLK-----44,100kHz -4ch stereo
Code:
___________________________________________ CCM ANALOG _________________________________________________________________________________________
>CCM_CLK1_(P+N)  NOTE:Teensy 4.1 NC                                                                                                    Alt+0175¯
^
| >OSC_24000000Mhz (XTAL-n)
| ^
| |                              
| |  PLL4_BYPASS_CLK_SCR
| |  |¯\            Audio PPL4                              PLL4_POST_DIV                   PLL4_BYPASS
| |->|<\\     |--------------------|                       |--------------|                 |¯\                 PLL4_AUDIO_DIV
| |  |  \|--->|24000000*(47+(2/50)=|-- 1,128,960,000Mhz -->|      /2     =|--564,480,000--->|<\\    |-------|  |--------------|   PPL4_MAIN_CLK
|-|->|  /  |  |--------------------|                       |--------------|                 |  \|-->|PLL4_EN|->|     /1       |--564,480,000-->|
| |  |_/   |                                                                            /-->|  /    |-------|  |--------------|                |
| |        |---------------------------------------------------------------------------/    |_/                                                |
| |                                                                                                                                            |
______________________________________________________________________________________________________________________________________________ | __
                                                                                                                                               |
______________________________________________ CCM ___________________________________________________________________________________________ | __
                                                                                                                                               |
|<-------564,480,000Mhz-----------------------------------------------------------------------------------------------------------------------<|
|
|
|                    SAI1_CLK_SEL
|                    |¯\
|                    |  \                 SAI1_CLK_PRED                  SAI1_CLK_PODF                             LRCLK-----44,100kHz -4ch stereo
|  --PLL3_PFD2_CLK-->|   |               |--------------|               |--------------|  SAI1_CLK_ROOT            BCLK---5,644,800Mhz -8ch-16b.
|>---[COLOR="#00FF00"]PLL4_MAIN_CLK[/COLOR]-->|<--|--564,480,000->|      /5     =|--112,896,000->|      /5     =|--22,579,200MHz--> ,       MCLK--22,579,200Mhz
   --PLL5_MAIN_CLK-->|   |               |--------------|               |--------------|
      Video PLL5     |  /
                     |_/ 
___________________________________________________________________________________________________________________________________________________
Code:
// Selector for sai1 clock multiplexer
CCM_CSCMR1 = (CCM_CSCMR1 & ~(CCM_CSCMR1_SAI1_CLK_SEL_MASK)) | CCM_CSCMR1_SAI1_CLK_SEL(2); // (0,1,2): PLL3_PFD2, PLL5, [COLOR="#00FF00"]PLL4[/COLOR]

EDIT 48,000kHz
Code:
___________________________________________ CCM ANALOG ________48,000kHz___________________________________________________________________________
>CCM_CLK1_(P+N)  NOTE:Teensy 4.1 NC                                                                                                    
^
| >OSC_24000000Mhz (XTAL-n)
| ^
| |                              
| |  PLL4_BYPASS_CLK_SCR
| |  |¯\            Audio PPL4                              PLL4_POST_DIV                   PLL4_BYPASS
| |->|<\\     |---------------------|                       |--------------|                 |¯\                 PLL4_AUDIO_DIV
| |  |  \|--->|24000000*(51+(10/50)=|-- 1,228,800,000Mhz -->|      /2     =|--614,400,000--->|<\\    |-------|  |--------------|   PPL4_MAIN_CLK
|-|->|  /  |  |---------------------|                       |--------------|                 |  \|-->|PLL4_EN|->|     /1       |--614,400,000-->|
| |  |_/   |                                                                            /--->|  /    |-------|  |--------------|                |
| |        |---------------------------------------------------------------------------/     |_/                                                |
| |                                                                                                                                             |
_______________________________________________________________________________________________________________________________________________ | __
                                                                                                                                                |
______________________________________________ CCM ____________________________________________________________________________________________ | __
                                                                                                                                                |
|<-------614,400,000Mhz------------------------------------------------------------------------------------------------------------------------<|
|
|
|                    SAI1_CLK_SEL
|                    |¯\
|                    |  \                 SAI1_CLK_PRED                  SAI1_CLK_PODF                             LRCLK-----48,000kHz -4ch stereo
|  --PLL3_PFD2_CLK-->|   |               |--------------|               |--------------|  SAI1_CLK_ROOT            BCLK---6,144,000Mhz -8ch-16b.
|>---[COLOR="#00FF00"]PLL4_MAIN_CLK[/COLOR]-->|<--|--614,400,000->|      /5     =|--122,880,000->|      /5     =|--24,576,000MHz--> ,       MCLK--24,576,000Mhz
   --PLL5_MAIN_CLK-->|   |               |--------------|               |--------------|
      Video PLL5     |  /
                     |_/ 
___________________________________________________________________________________________________________________________________________________
 
Last edited:
Thanks.
All this is new to me.
I will look at the code when I have a bit more time, basically I'm trying to recreate this device for my classic 1992 Atari falcon 030 with the Motorola DSP 56001 @ 32 MHz.
Falcon soundpool SPDIF.jpg

Edit: Added for complete example.
Code:
___________________________________________ CCM ANALOG ________48,000kHz___________________________________________________________________________
>CCM_CLK1_(P+N)  NOTE:Teensy 4.1 NC                                                                                                    
^
| >OSC_24000000Mhz (XTAL-n)
| ^
| |                              
| |  PLL4_BYPASS_CLK_SCR
| |  |¯\            Audio PPL4                              PLL4_POST_DIV                   PLL4_BYPASS
| |->|<\\     |---------------------|                       |--------------|                 |¯\                 PLL4_AUDIO_DIV
| |  |  \|--->|24000000*(51+(10/50)=|-- 1,228,800,000Mhz -->|      /2     =|--614,400,000--->|<\\    |-------|  |--------------|   PPL4_MAIN_CLK
|-|->|  /  |  |---------------------|                       |--------------|                 |  \|-->|PLL4_EN|->|     /1       |--614,400,000-->|
| |  |_/   |                                                                            /--->|  /    |-------|  |--------------|                |
| |        |---------------------------------------------------------------------------/     |_/                                                |
| |                                                                                                                                             |
_______________________________________________________________________________________________________________________________________________ | __
                                                                                                                                                |
______________________________________________ CCM ____________________________________________________________________________________________ | __
                                                                                                                                                |
|<-------614,400,000Mhz------------------------------------------------------------------------------------------------------------------------<|
|
|
|                    SAI1_CLK_SEL
|                    |¯\
|                    |  \                 SAI1_CLK_PRED                  SAI1_CLK_PODF                             LRCLK-----48,000kHz -4ch stereo
|  --PLL3_PFD2_CLK-->|   |               |--------------|               |--------------|  SAI1_CLK_ROOT            BCLK---6,144,000Mhz -8ch-16b.
|>---PLL4_MAIN_CLK-->|<--|--614,400,000->|      /5     =|--122,880,000->|      /5     =|--24,576,000MHz-->|,       MCLK--24,576,000Mhz
   --PLL5_MAIN_CLK-->|   |               |--------------|               |--------------|                  |
      Video PLL5     |  /                                                                                 |
                     |_/                                                                                  |
_________________________________________________________________________________________________________ | _______________________________________
                                                                                                          |
                                                                                                          | 
___________________________________________ IOMUXC_GPR __________________________________________________ | _______________________________________
                                                                                                          |
|<-------SAI1_CLK_ROOT-----------------------------------------------------------------------------------<|
|                       SAI1_MCLK1_SEL
|                       |¯\
|>------SAI1_CLK_ROOT-->|<\\
   -----SAI2_CLK_ROOT-->|  \\                                      
   -----SAI3_CLK_ROOT-->|   \|               
en/ds --SAI1_MCLK-----|>|    |------------------SAI1_MCLK1---------------------------------------> , MCLK1-- 24,576,000Mhz for 48,000kHz -4ch stereo
en/ds --SAI2_MCLK---|-->|    |               
en/ds --SAI3_MCLK-|---->|   /
                  | | | |  / 
                  | | | |_/
                  | | |
                  TO SAI1_MCLK2_SEL & SAI1_MCLK3_SEL + SAI2_MCLK3_SEL + SAI3_MCLK3_SEL
___________________________________________________________________________________________________________________________________________________
// 11.4.2 GPR1 General Purpose Register (IOMUXC_GPR_GPR1)
// SAI1_MCLK_DIR field descriptions 19
// 0 sai1.MCLK is input signal
// 1 sai1.MCLK is output signal
//
// SAI1_MCLK1_SEL field descriptions 3-0
// 000 ccm.ssi1_clk_root
// 001 ccm.ssi2_clk_root
// 010 ccm.ssi3_clk_root
// 011 iomux.sai1_ipg_clk_sai_mclk
// 100 iomux.sai2_ipg_clk_sai_mclk
// 101 iomux.sai3_ipg_clk_sai_mclk
// 110 Reserved
// 111 Reserved

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));	//Select MCLK
 
Last edited:
Back
Top