lib_i2s I2S/TDM clocked from _internal_ source?

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
aclassifier
Respected Member
Posts: 487
Joined: Wed Apr 25, 2012 8:52 pm

lib_i2s I2S/TDM clocked from _internal_ source?

Post by aclassifier »

I don't have any external clock source (xCORE-200 Explorer board) but still need to do TDM and I2S.

In lib_i2s [1] (doc I2S/TDM Library XM007055) I see that

MCLK: Clock line, driven by external oscillator
BCLK: Bit clock. This is a fixed divide of the MCLK and is driven by the master.

For i2s both are clock blocks:
clock mclk = XS1_CLKBLK_1;
clock bclk = XS1_CLKBLK_2;

but mclk is controlled by port p_mclk (neither in or out in the code) and init:
configure_clock_src(mclk, p_mclk);
Both clocks are needed by i2s_master

For TDM we only have the
clock bclk = XS1_CLKBLK_1;
but also this is conrolled by in port p_bclk (obs in) and init:
configure_clock_src(bclk, p_bclk);
bclk only is needed by tdm_master

HOWEVER
would it be possible (for the TDM case) to go:

configure_clock_ref(bclk,0)
and then
configure_clock_rate_at_least (bclk, 1024, 1000); // 1.042 MHz (??)
I have tested and scoped and stared out of the window; then (perhaps) in a brighter moment my feelings sent me to writing this post.

I come from the mic array board, which does have an external to the processor PLL. I am as usual rather confused, but wonder more and more whether I should try to write my own handler with select timerafter and then exercising the ports. But I need 16000 Hz * 64 = 1.024 MHz which I don't think I'll come to precisely, but maybe good enough for the TDK/InvenSense ICS-52000 mic array board. Plus, I may run out of time when my round trip of 1.024 MHz * 2 = 2.048 MHz only would allow for 62.5 MHz / 2.048 MHz = 30 instructions to do the stuff..

Edit. PS. The Adafruit Clock Generator Breakout Board - 8KHz to 160MHz may come me to the rescue..

[1] https://github.com/xmos/lib_i2s I use 5.0.0 and xC with xTIMEcomposer 14.4.1
Last edited by aclassifier on Mon Jul 03, 2023 2:09 pm, edited 1 time in total.


--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
MaximLiadov
XCore Addict
Posts: 130
Joined: Mon Apr 16, 2018 9:14 am

Post by MaximLiadov »

Being an audio developer, I guess the most confusing part is internal/external substance. In terms of ADC/DAC, there is an internal onboard crystal oscillator for USB data playback/recording and an external clock source for other digital signals (like SPDIF). In terms of XMOS chip there is an internal system clock (500/100 MHz) driven by 24 MHz and an external (onboard) crystal oscillator with audio frequency (mostly used pair 22.5/24.5 MHz TCXOs or dedicated programmable PLL). So for ADC/DAC the onboard XO is internal clock source. For XMOS XS2 family chip this signal is external. It comes to some XMOS <MCLK input port> and is used in clock block to synchronize all I2S signals. But it's the same (internal) onboard clock source.
User avatar
aclassifier
Respected Member
Posts: 487
Joined: Wed Apr 25, 2012 8:52 pm

Post by aclassifier »

I think you are saying that the trigger of of the bclk has to be external, like the in port p_mclk - and that this input is coming from some external oscillator, and that this signal is also externally directly used as SCK of the TDM device, since tdm_master does not itself exercise the SCK?

So even if the clock could be triggered internally, then tdm_master and lib_i2s could not be used since SCK is not set, but used (indirectly throught the clock block).

So my "HOWEVER" alternative will not work because of what I said. But for some other case, yes a clock block may be triggered by the internal system clock. Does that sound right?
Off Topic
I have ordered some Si5351A PLLs from Adafruit, but I am also testing hardcoding the stuff while I wait..
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
User avatar
akp
XCore Expert
Posts: 579
Joined: Thu Nov 26, 2015 11:47 pm

Post by akp »

You can use the internal tile clock (500 MHz) or Ref clock (100 MHz) to generate your TDM bit clock when you run in TDM master mode. However, it won't be possible to generate a standard sampling rate. That's why people always use an external MCLK reference, typically something like 24.576 MHz to generate 48 kHz family.

Like you said you need a bit clock (aka SCK) of 32 bits/sample * 2 ch * 16000 samples/sec = 1.024MHz.
  • You could use the tile clock with the configure_clock_xcore() function. This supports divide values of 1 to 255, where the actual divider is 2*divide. Therefore, the closest you can get to 1.024 MHz is 500 MHz / (2*244) = 1.02459 MHz which would give you a sampling rate of 16.009 kHz. That's actually pretty terrible but maybe you could use it.
  • You could use the reference clock with the configure_clock_ref() function. This supports divide values of 0 to 255, where the actual divider is 2*divide (or 1 if divide is 0). Therefore, the closest you can get to 1.024 MHz is 100 MHz / (2*49) = 1.0204 MHz which would give you a sampling rate of 15.944 kHz which is really far from 16 kHz
If you do any of this you'll have to dig into the TDM and I2S code and probably change some of it, I am just saying what's possible with the xCORE-200 chip, not the existing libraries that were designed for external clock source. It should be pretty straightforward to change.

An alternative is if you don't need exactly 500 MHz tile clock and 100 MHz reference clock you could adjust the XMOS internal PLL to give you something closer to 1.024 MHz. With a 24 MHz oscillator it's possible to get a tile clock of 499.7143MHz which you could use to get 16000.1 Hz. Not recommending this just putting it out there.
User avatar
aclassifier
Respected Member
Posts: 487
Joined: Wed Apr 25, 2012 8:52 pm

Post by aclassifier »

Thanks a lot! The configure_clock_xcore is not in https://www.xmos.ai/download/xTIMEcompo ... (14.x).pdf page 354ff, but it's still all around in xs1.h and also in the lib_mic_array docs (that board I'm moving away from).

16.009 kHz would be ok for me. I'm doing FFT and getting a spectrum delta of bin 15.625 Hz and comparing against recorded sounds' qualities with three bins accuracy.

I'm trying a hard coded version now, and if I get it right I'll get skew for the 32 bits but waiting a little longer before the next 32 bits from the mic.

With 1.024 MHz on the average I get this closest that's faster: 1.0309278350515 MHz with 47 and 50 timer ticks alternating. Then I need to wait a little more to get it exactly at 16.000 kHz. At least that's what my staring at my screen has given me so far. But I don't know if the ICS-52000 would appreciate this.

I am impressed by the quality of your answers, guys! Thanks a lot! I'll first test the hard coded, then perhaps do your 16.009 kHz and change some in lib_i2s ("straightforward", well.. ) or use the 16.009 kHz and try to do it myself or go for the Adafruit board with the Si5351A and write some I2C code for it.
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
MaximLiadov
XCore Addict
Posts: 130
Joined: Mon Apr 16, 2018 9:14 am

Post by MaximLiadov »

I see no big problem in setting the system frequency to be proportional to 16 kHz.
In my real XU216 USB audio device with 5 cores per tile, I set these modes on the fly:

Code: Select all

unsigned pllCtrlReadData, pllCtrlWriteData, F, R, OD;

            switch (sys_clock_mode)
            {
                case 0:         // 480 : 96
                    R = 0;
                    F = 39;
                    OD = 0;
                    break;
                case 1:         // 500 : 100
                    R = 2;
                    F = 124;
                    OD = 0;
                    break;
                case 2:         // 600 : 120
                    R = 0;
                    F = 49;
                    OD = 0;
                    break;
                case 3:         // 720 : 144
                    R = 0;
                    F = 59;
                    OD = 0;
                    break;
            }

        pllCtrlWriteData = R + (F<<8) + (OD<<23) + (1<<30) + (1<<31);

        write_node_config_reg ( tile[0] , XS1_SSWITCH_PLL_CTL_NUM , pllCtrlWriteData);
        write_node_config_reg ( tile[1] , XS1_SSWITCH_PLL_CTL_NUM , pllCtrlWriteData);
Works fine for me.
User avatar
aclassifier
Respected Member
Posts: 487
Joined: Wed Apr 25, 2012 8:52 pm

Post by aclassifier »

Maxim, this is _so_ interesting! You are really placing a bait before me!

I find no document whatsoever where this is described, and I have been searching (just now). In the xTIMEcomposer user guide page 415 chapter "Node" I see configuration mentioned, and two links to older documents that I could find no trace of (X3221 and X1433). And some description of setting up these like in config.xscope or even the .xn file (for permanent change, I'd assume).

All your divisions yield 5. Saying A (metaphorically) I'd also like to hear F (and R and OD).

I need to get some defintions clear. When you say "system frequency" I assume it's the "timer (system) frequency". For a tile with a "system frequency" of 500 MHz each core gets cycles at a rate of 1/8 = 62.5 MHz, which ticks along independently. But the timer clock is always (=most often) 10 ns @ 100 MHz. I assume it's this one you are able to change on the fly, and that this goes for a full tile.

The 500 MHz clock, I wouldn't be surprised if it's possible to set it as well, since XTA tells me which frequency to use, which might come in handy if one need to go down, to save some power I'd assume. Perhaps the .xn file is the place.

But I didn't actually ask for 16 kHz. That's the sampling rate of the mics, and the rate I use for the input to my DSP stuff. For a two channel TDM mics system I need 32*2 plus some for WS (0 I think) and delay (0), according to the data sheet [1] if I understand it correctly, SCK needs to go fs * 64 = 16 kHz * 64 = 1024 kHz.

[1] https://invensense.tdk.com/products/ics-52000/
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
MaximLiadov
XCore Addict
Posts: 130
Joined: Mon Apr 16, 2018 9:14 am

Post by MaximLiadov »

Hi Øyvind,
Here is a PDF: https://www.xmos.ai/download/xCORE-200- ... l(1.0).pdf
Look at Figure 1 to understand what is R, F, OD.
I think system frequency/system clock is the correct term, isn't it?
XMOS uses it on the figure and throughout the text.
User avatar
aclassifier
Respected Member
Posts: 487
Joined: Wed Apr 25, 2012 8:52 pm

Post by aclassifier »

THANK YOU, Maxim! All these great XMOS documents!
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/