Forum Rule: Always post complete source code & details to reproduce any issue!
Page 4 of 4 FirstFirst ... 2 3 4
Results 76 to 98 of 98

Thread: Discussion about a simple way to change the sample-rate

  1. #76
    Junior Member
    Join Date
    Jan 2019
    Posts
    11
    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!

  2. #77
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,137
    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 )

  3. #78
    Junior Member
    Join Date
    Jan 2019
    Posts
    11
    Thanks for replying so quick!

    I'm using T3.5 running at 168MHz. I just changed it to 120MHz and it compiled OK!!

  4. #79
    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

  5. #80
    Good day,

    I encounter the same issue as mentioned in the last post. How can we adapt the code for the Teensy 4.1?

    Thank you,
    Jaco

  6. #81
    Junior Member
    Join Date
    Aug 2020
    Posts
    1
    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.
    Quote Originally Posted by Frank B View Post
    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.

  7. #82
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    27,982
    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.

  8. #83
    @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!

  9. #84
    Senior Member
    Join Date
    Apr 2014
    Location
    -
    Posts
    9,735
    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 
    }

  10. #85
    Thank you for all your great contributions to the Forum, @frankB

  11. #86
    Senior Member
    Join Date
    Sep 2019
    Location
    Sevilla, Spain
    Posts
    101
    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

  12. #87
    Senior Member
    Join Date
    Apr 2014
    Location
    -
    Posts
    9,735
    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.

  13. #88
    Senior Member
    Join Date
    Sep 2019
    Location
    Sevilla, Spain
    Posts
    101
    Quote Originally Posted by Frank B View Post
    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,

  14. #89
    Junior Member
    Join Date
    May 2021
    Posts
    2
    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.

  15. #90
    Senior Member
    Join Date
    Jul 2014
    Posts
    3,497
    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

  16. #91
    Junior Member
    Join Date
    May 2021
    Posts
    2
    Quote Originally Posted by WMXZ View Post
    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.

  17. #92
    Senior Member
    Join Date
    Jul 2014
    Posts
    3,497
    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.

  18. #93
    Member
    Join Date
    Oct 2021
    Location
    Australia
    Posts
    20
    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?

  19. #94
    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.


    Quote Originally Posted by Frank B View Post
    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 
    }

  20. #95
    Senior Member
    Join Date
    Jul 2014
    Posts
    3,497
    Quote Originally Posted by gatheround View Post
    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

  21. #96
    Senior Member
    Join Date
    Dec 2013
    Location
    East Stroudsburg PA.
    Posts
    339
    I need simple way to change the sample rate and master clock at runtime
    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.
    |>---PLL4_MAIN_CLK-->|<--|--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, PLL4
    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.
    |>---PLL4_MAIN_CLK-->|<--|--614,400,000->|      /5     =|--122,880,000->|      /5     =|--24,576,000MHz--> ,       MCLK--24,576,000Mhz
       --PLL5_MAIN_CLK-->|   |               |--------------|               |--------------|
          Video PLL5     |  /
                         |_/ 
    ___________________________________________________________________________________________________________________________________________________
    Last edited by Chris O.; 03-14-2023 at 04:12 AM.

  22. #97
    Senior Member
    Join Date
    Jul 2014
    Posts
    3,497
    Quote Originally Posted by Chris O. View Post
    I need simple way to change the sample rate and master clock at runtime
    I do it as follows
    stop I2S (I assume you are using I2S)
    modify frequency
    restart frequency
    code: e.g.: https://github.com/WMXZ-EU/record_sg...ter/i2s_mods.h

  23. #98
    Senior Member
    Join Date
    Dec 2013
    Location
    East Stroudsburg PA.
    Posts
    339
    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.
    Click image for larger version. 

Name:	Falcon soundpool SPDIF.jpg 
Views:	14 
Size:	167.6 KB 
ID:	30608

    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 by Chris O.; 03-14-2023 at 02:02 PM.

Posting Permissions

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