About xCORE200 extending the reference design to higher sample rates

Sub forums for various specialist XMOS applications. e.g. USB audio, motor control and robotics.
Edward Wood
Junior Member
Posts: 6
Joined: Sun Dec 24, 2017 4:10 pm

About xCORE200 extending the reference design to higher sample rates

Postby Edward Wood » Mon Dec 25, 2017 2:58 pm

I was a XMOS user form china.I have a few problems about the software reference design,my hardware platforms: XU208-128-c10,software: sw_usb_audio-[sw]_6.15.2rc1.
It can good warking at MCLK@512Fs,rates up to 384K/32Bit DOP 128, but when i change to 1024Fs (45.1548M and 49.152M) ,the clock generator was error,BCLK frequency started Instable,cause the LRCK error too. when playback 192KHz signal,the LRCK frequency was 170KHz,as rates higher the clock generator error is more obvious.

In softeare i changed some plases:
------------------------------------
/* Master clock defines (in Hz) */
#define MCLK_441 (1024*44100) /* 44.1, 88.2 etc */
#define MCLK_48 (1024*48000) /* 48, 96 etc */

/* Maximum frequency device runs at */
#ifndef MAX_FREQ
#define MAX_FREQ (768000)
#endif
----------------------------------------
#ifndef CODEC_MASTER
static inline void doI2SClocks(unsigned divide)
{
switch (divide)
{
#if (MAX_DIVIDE > 32)
#error MCLK/BCLK Ratio not supported!!
#endif
#if (MAX_DIVIDE > 16) //For 1/16 mclks
case 32:
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;

p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
p_bclk <: 0xffff0000;
break;
#endif
-----------------------------------------------------------------------
There is something i missing to changed,i think. And the FAE of china can't give any help also there is no application note support.
So could anyone please tell me what's wrong with the software? Should i have to change which place ?
User avatar
infiniteimprobability
XCore Legend
Posts: 1120
Joined: Thu May 27, 2010 10:08 am

Postby infiniteimprobability » Wed Dec 27, 2017 10:18 pm

How many channels are you trying to drive? The design is good for 384kHz stereo but I understand it may be possible to push to 768kHz with some tweaks...

First thing is that the doI2SClocks() function is actually compiled away for the XU208 so making changes here will have no effect- the BCLK is hardware divided from MCLK inside the clock block. The clock block can divide down to 255*2 so I don't think a higher MCLK alone is the issue, unless you have a SI issue with the clock feeding the MCLK pin.

I am surprised that it starts breaking at 192kHz (it should work out of the box to 384kHz at least). Can you confirm what the BCLK frequency is? (I would expect it to be OK) Is it just the LRCLK that is getting slowed?

The LRCLK (and data) being pushed out is due to the I2S loop not being fast enough. It's very optimal so I don't immediately know what the issue is. Have you made any other changes? Please confirm the channel count.

One trick you can do (and may well need) is to split DoSampleTransfer(). The first line outuint(c_out, underflowWord); causes an interrupt to fire in the decouple. This has a 400ns latency which can cause the I2S loop timing to be pushed out as you increase the rate. So what you can do is take this line out and put it just before the ADC port read:

Code: Select all

#if (NUM_PDM_MICS > 0)
            /* Get samples from PDM->PCM comverter */
            c_pdm_pcm <: 1;
#pragma loop unroll
            for(int i = 0; i < NUM_PDM_MICS; i++)
            {
                c_pdm_pcm :> samplesIn_0[i];
            }
#endif
        }

<<<<<HERE

#if (I2S_CHANS_ADC != 0)
            index = 0;
            /* Channels 0, 2, 4.. on each line */
#pragma loop unroll


Does that help?
Edward Wood
Junior Member
Posts: 6
Joined: Sun Dec 24, 2017 4:10 pm

Postby Edward Wood » Sun Dec 31, 2017 4:06 pm

Oh! Hello,i'm very glad to receive your reply and best wishes for a happy New Year!
Several days passed, i've changed the software several times, and now it's new.Let me make a clear situation.:
hardware platforms: XU208-128-c10
software: sw_usb_audio-[sw]_6.15.2rc1.
support: IIS: 44.1K-768KHz 32BIT
DSD_DOP: DSD64-DSD256
DSD_NATIVE: DSD64-DSD256

Now,there is only one problem : when playback PCM 705/768KHz rates,the BLCK no signal output,os playback DSD_DOP 256 with noise.In normal BCLK=MCLK at this time.
One unusual thing is the LRCK was good warking,also the DATA is right.
I was using the [sw]_6.12 before,the same setting,when playback PCM 705/768KHz rates,BCLK was OK. I don't know where is the problem.

In [customdefines.h] used this defines:

#ifndef MIXER
#define MIXER (1)
#endif

#ifndef MAX_MIX_COUNT
#define MAX_MIX_COUNT (0)
#endif

whould you offer some solutions?
Once again, thank you so much.
User avatar
infiniteimprobability
XCore Legend
Posts: 1120
Joined: Thu May 27, 2010 10:08 am

Postby infiniteimprobability » Tue Jan 02, 2018 9:17 am

Hi,
Thanks for the info - you didn't mention channel count but I can deduce that it must be stereo because 32b @ 768000Hz can only support 2 channels before exceeding the bandwidth of an ISO endpoint.

I think with the device you have it should be possible to support your requirements but, as you have seen, you will need to make some modifications because the standard reference design does not support the higher data rates as standard.

What other changes have you made other than MCLK, MAX_FREQ and MIXER?

The trick I mentioned about DoSampleTransfer() is to hide the interrupt latency in decouple. However I can see that you have enabled mixer with 0 mixers specified. This enables the mixer core in between audio and decouple. It will only pass samples on but because it buffers, it should do the job of hiding the latency for you. So please ignore my suggestion about DoSampleTransfer() as it does the same thing.

What I am not understanding currently is why PCM at 7xxkHz it outputs the LRCLK at the data at the correct rate but no BCLK. The LRCLK port and Data ports are both clocked by BCLK and so BCLK must be operating to enable that to happen.

Please can you confirm that at 7xxkHz the LRCLK frequency is *exactly* as you expect?
User avatar
infiniteimprobability
XCore Legend
Posts: 1120
Joined: Thu May 27, 2010 10:08 am

Postby infiniteimprobability » Wed Jan 03, 2018 5:15 pm

Hi,
an update for you. I took the clean 6.15.2 USB audio reference design and made the following changes:

Code: Select all

#define MAX_FREQ           (768000)
#define MCLK_441           (1024*44100)   /* 44.1, 88.2 etc */
#define MCLK_48            (1024*48000)   /* 48, 96 etc */
#define NUM_USB_CHAN_OUT   (2)         /* Host to Device */
#define NUM_USB_CHAN_IN    (0)         /* Device to Host */
#define I2S_CHANS_DAC      (2)
#define I2S_CHANS_ADC      (0)


..and the DSD fix to audio.xc (see below)
Obviously I also applied a physical MCLK to match the above frequencies.

Results:
- PCM works fine from 44.1 right up to 768kHz
- DSD works fine from DSD64 to DSD256
- I also found that MIXER can be 0 or 1, which I was surprised at. I recommend keeping it to 1 though for performance reasons.

So we can be reassured by this and it proves your desired configuration is workable. What have you done that is different from this?

<change to audio.xc to fix the DSD issue- diff>

Code: Select all

--- a/uac2_6_15_2_bugs/a_dir/sc_usb_audio/module_usb_audio/audio.xc
+++ b/uac2_6_15_2_bugs/a_dir/sc_usb_audio/module_usb_audio/audio.xc
@@ -513,6 +513,7 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
             dsdSample_l = bitrev(byterev(dsdSample_l));
 
             /* Output DSD data to ports then 32 clocks */
+#ifndef __XS2A__
             switch (divide)
             {
                 case 4:
@@ -545,6 +546,7 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
                     p_dsd_clk <: 0xF0F0F0F0;
                     break;
             }
+#endif
 
         }
         else if(dsdMode == DSD_MODE_DOP)
@@ -556,6 +558,7 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
 
                 everyOther = 1;
 
+#ifndef __XS2A__
                 switch (divide)
                 {
                     case 8:
@@ -574,6 +577,7 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
                     p_dsd_clk <: 0xAAAAAAAA;
                     break;
                 }
+#endif
             }
             else // everyOther
             {
@@ -586,6 +590,7 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
                 //p_dsd_dac[1] <: bitrev(dsdSample_r);
                 asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(bitrev(dsdSample_l)));
                 asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(bitrev(dsdSample_r)));
+#ifndef __XS2A__
                 switch (divide)
                 {
                     case 8:
@@ -604,7 +609,7 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
                     p_dsd_clk <: 0xAAAAAAAA;
                     break;
                 }
-
+#endif
             }
         }
         else
--
Edward Wood
Junior Member
Posts: 6
Joined: Sun Dec 24, 2017 4:10 pm

Postby Edward Wood » Fri Jan 05, 2018 3:25 pm

Hi, i checked again.Now the audio data formats and timing seems right.

Set in customdefines.h: the MIXER and MAX_MIX_COUNT not define
-------------------------------------------------------------------------------------------------------------------------------------------
/* Enable/Disable MIDI - Default is MIDI off */
#ifndef MIDI
#define MIDI 0
#endif

#ifndef DSD_CHANS_DAC
#define DSD_CHANS_DAC 2
#endif

/* Enable/Disable SPDIF output - Default is S/PDIF on */
#ifndef SPDIF
#define SPDIF 0
#endif

#ifndef SPDIF_TX
#define SPDIF_TX 0
#endif

/* Mixer core enabled by default */(not used)
//#ifndef MIXER
//#define MIXER 1
//#endif

/* Mixing disabled by default */(not used)
//#ifndef MAX_MIX_COUNT
//#define MAX_MIX_COUNT 0
//#endif

/* Audio class version to run in - Default is 2.0 */
#ifndef AUDIO_CLASS
#define AUDIO_CLASS (2)
#endif

/* Enable/disable fall back to Audio Class 1.0 when connected to FS hub. */
#ifndef AUDIO_CLASS_FALLBACK
#define AUDIO_CLASS_FALLBACK 0
#endif

/* Defines relating to channel count and channel arrangement (Set to 0 for disable) */
//:audio_defs
/* Number of USB streaming channels - Default is 4 in 4 out */
#ifndef NUM_USB_CHAN_IN
#define NUM_USB_CHAN_IN (0) /* Device to Host */
#endif
#ifndef NUM_USB_CHAN_OUT
#define NUM_USB_CHAN_OUT (2) /* Host to Device */
#endif


/* Number of IS2 chans to DAC..*/
#ifndef I2S_CHANS_DAC
#define I2S_CHANS_DAC (2)
#endif

/* Number of I2S chans from ADC */
#ifndef I2S_CHANS_ADC
#define I2S_CHANS_ADC (0)
#endif

/* Enable DFU interface, Note, requires a driver for Windows */
#define DFU 1

/* Master clock defines (in Hz) */
#define MCLK_441 (1024*44100) /* 44.1, 88.2 etc */
#define MCLK_48 (1024*48000) /* 48, 96 etc */

/* Maximum frequency device runs at */
#ifndef MAX_FREQ
#define MAX_FREQ (768000)
#endif

/* Index of SPDIF TX channel (duplicated DAC channels 1/2) */
#define SPDIF_TX_INDEX (0)

/* Default frequency device reports as running at */
/* Audio Class 1.0 friendly freq */
#define DEFAULT_FREQ (44100)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Your <change to audio.xc to fix the DSD issue- diff> in Code are display disorder code.Can't see the content,so you can chack this:
my audio.xc about the DSD part:
#if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0)
if(dsdMode == DSD_MODE_NATIVE)
{
/* 8 bits per chan, 1st 1-bit sample in MSB */
dsdSample_l = samplesOut[0];
dsdSample_r = samplesOut[1];
dsdSample_r = bitrev(byterev(dsdSample_r));
dsdSample_l = bitrev(byterev(dsdSample_l));

/* Output DSD data to ports then 32 clocks */
#if defined(__XS2A__)
asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(dsdSample_l));
asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(dsdSample_r));
#else
switch (divide)
{
case 4:
asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(dsdSample_l));
asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(dsdSample_r));
p_dsd_clk <: 0xCCCCCCCC;
p_dsd_clk <: 0xCCCCCCCC;
p_dsd_clk <: 0xCCCCCCCC;
p_dsd_clk <: 0xCCCCCCCC;
break;

case 2:
asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(dsdSample_l));
asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(dsdSample_r));
p_dsd_clk <: 0xAAAAAAAA;
p_dsd_clk <: 0xAAAAAAAA;
break;

default:
/* Do some clocks anyway - this will stop us interrupting decouple too much */
asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(dsdSample_l));
asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(dsdSample_r));
p_dsd_clk <: 0xF0F0F0F0;
p_dsd_clk <: 0xF0F0F0F0;
p_dsd_clk <: 0xF0F0F0F0;
p_dsd_clk <: 0xF0F0F0F0;
p_dsd_clk <: 0xF0F0F0F0;
p_dsd_clk <: 0xF0F0F0F0;
p_dsd_clk <: 0xF0F0F0F0;
p_dsd_clk <: 0xF0F0F0F0;
break;
}
#endif
}
else if(dsdMode == DSD_MODE_DOP)
{
if(!everyOther)
{
dsdSample_l = ((samplesOut[0] & 0xffff00) << 8);
dsdSample_r = ((samplesOut[1] & 0xffff00) << 8);

everyOther = 1;

#if !defined(__XS2A__)
switch (divide)
{
case 8:
p_dsd_clk <: 0xF0F0F0F0;
p_dsd_clk <: 0xF0F0F0F0;
p_dsd_clk <: 0xF0F0F0F0;
p_dsd_clk <: 0xF0F0F0F0;
break;

case 4:
p_dsd_clk <: 0xCCCCCCCC;
p_dsd_clk <: 0xCCCCCCCC;
break;

case 2:
p_dsd_clk <: 0xAAAAAAAA;
break;
}
#endif
}
else // everyOther
{
everyOther = 0;
dsdSample_l = dsdSample_l | ((samplesOut[0] & 0xffff00) >> 8);
dsdSample_r = dsdSample_r | ((samplesOut[1] & 0xffff00) >> 8);

// Output 16 clocks DSD to all
//p_dsd_dac[0] <: bitrev(dsdSample_l);
//p_dsd_dac[1] <: bitrev(dsdSample_r);
asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(bitrev(dsdSample_l)));
asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(bitrev(dsdSample_r)));

#if !defined(__XS2A__)
switch (divide)
{
case 8:
p_dsd_clk <: 0xF0F0F0F0;
p_dsd_clk <: 0xF0F0F0F0;
p_dsd_clk <: 0xF0F0F0F0;
p_dsd_clk <: 0xF0F0F0F0;
break;

case 4:
p_dsd_clk <: 0xCCCCCCCC;
p_dsd_clk <: 0xCCCCCCCC;
break;

case 2:
p_dsd_clk <: 0xAAAAAAAA;
break;
}
#endif
}
}
else
#endif

The BCLK output are stable now.
I used ES9038PRO to playback the DOP_DSD_256 DATA were noises,but playback the same in NATIVE_DSD_256 wear OK.
The DOP_DSD_256 formats and timing seems right
Image

Image

Is there any other problem?
User avatar
infiniteimprobability
XCore Legend
Posts: 1120
Joined: Thu May 27, 2010 10:08 am

Postby infiniteimprobability » Fri Jan 05, 2018 4:51 pm

Native DSD should be like below. (basically for the case of XS2 you need to compile away the p_dsd_clk port outputs because the clock is generated in hardware). I think DoP looks OK.

Code: Select all

     /* 8 bits per chan, 1st 1-bit sample in MSB */
    dsdSample_l =  samplesOut[0];
    dsdSample_r =  samplesOut[1];
    dsdSample_r = bitrev(byterev(dsdSample_r));
    dsdSample_l = bitrev(byterev(dsdSample_l));

    asm volatile("out res[%0], %1"::"r"(p_dsd_dac[0]),"r"(dsdSample_l));
    asm volatile("out res[%0], %1"::"r"(p_dsd_dac[1]),"r"(dsdSample_r));

#ifndef __XS2A__
    /* Output DSD data to ports then 32 clocks */
    switch (divide)
    {
        case 4:
            p_dsd_clk <: 0xCCCCCCCC;
            p_dsd_clk <: 0xCCCCCCCC;
            p_dsd_clk <: 0xCCCCCCCC;
            p_dsd_clk <: 0xCCCCCCCC;
            break;

        case 2:
            p_dsd_clk <: 0xAAAAAAAA;
            p_dsd_clk <: 0xAAAAAAAA;
            break;

        default:
            /* Do some clocks anyway - this will stop us interrupting decouple too much */
            p_dsd_clk <: 0xF0F0F0F0;
            p_dsd_clk <: 0xF0F0F0F0;
            p_dsd_clk <: 0xF0F0F0F0;
            p_dsd_clk <: 0xF0F0F0F0;
            p_dsd_clk <: 0xF0F0F0F0;
            p_dsd_clk <: 0xF0F0F0F0;
            p_dsd_clk <: 0xF0F0F0F0;
            p_dsd_clk <: 0xF0F0F0F0;
            break;
    }
#endif // __XS2A__
dweeb4
Active Member
Posts: 52
Joined: Mon Jan 19, 2015 12:47 pm

Postby dweeb4 » Mon Feb 12, 2018 1:35 am

Can I ask a different but related question?
I know DSD samples are composed of High sample or Low sample - a sample being the duration of X number of master clock cycles. In other words a DSD64 high sample is high for 8 clock cycles.
I wanted to be able to change all the High DSD64 samples to high for 7 clock cycles & 1 clock cycle Low. Still a Bit period of 8 clock cycles but all highs treated in this way.

I want to do this for DSD128, DSD256 & DSD512

Is it just a matter of changing the bit mask in Audio_XC ?
But you say "for the case of XS2 you need to compile away the p_dsd_clk port outputs because the clock is generated in hardware" & I'm intending to use hardware platforms: XU208-128-c10

Code: Select all

 case 4:
            p_dsd_clk <: 0xCCCCCCCC;
            p_dsd_clk <: 0xCCCCCCCC;
            p_dsd_clk <: 0xCCCCCCCC;
            p_dsd_clk <: 0xCCCCCCCC;
            break;

        case 2:
            p_dsd_clk <: 0xAAAAAAAA;
            p_dsd_clk <: 0xAAAAAAAA;
            break;
Last edited by dweeb4 on Mon Feb 12, 2018 9:05 pm, edited 1 time in total.
User avatar
infiniteimprobability
XCore Legend
Posts: 1120
Joined: Thu May 27, 2010 10:08 am

Postby infiniteimprobability » Mon Feb 12, 2018 10:22 am

Is it just a matter of changing the bit mask in Audio_XC ?


I am not 100% sure because we have never pushed it that far (for xCORE200 or XS1). I believe others have tried and succeeded though. It's certainly the first thing to do. I recommend putting some prints in there (enable xscope for that otherwise you will kill USB) to check thing.

Be careful about the following:
- At DSD512, DSD CLK = MCLK so the "divide" ratio will be 1. This means the code should use the MCLK directly and you will not need to output p_dsd_clk
- The throughput limit is 64Mbps. So at 768kHz PCM @ 24b (which is carried using 32b slots) the bandwidth is 50Mbps. For DoP you need 8b marker + 16b data. DoP512 would need 1536kHz 24b audio minimum, so that is not achievable on this platform. DoP256 is OK though.
dweeb4
Active Member
Posts: 52
Joined: Mon Jan 19, 2015 12:47 pm

Postby dweeb4 » Mon Feb 12, 2018 2:00 pm

infiniteimprobability wrote:
Is it just a matter of changing the bit mask in Audio_XC ?


I am not 100% sure because we have never pushed it that far (for xCORE200 or XS1). I believe others have tried and succeeded though. It's certainly the first thing to do. I recommend putting some prints in there (enable xscope for that otherwise you will kill USB) to check thing.

Be careful about the following:
- At DSD512, DSD CLK = MCLK so the "divide" ratio will be 1. This means the code should use the MCLK directly and you will not need to output p_dsd_clk
- The throughput limit is 64Mbps. So at 768kHz PCM @ 24b (which is carried using 32b slots) the bandwidth is 50Mbps. For DoP you need 8b marker + 16b data. DoP512 would need 1536kHz 24b audio minimum, so that is not achievable on this platform. DoP256 is OK though.

Thanks for your informative reply.
Yes, I was somewhat worried about the restrictions in data throughput - I even want to do this for DSD512 so I meant to say I'd be using 45.xxxx clock
My only focus was on DSD native output, not DOP which I guess will simplify matters in both coding & testing? I envisage reading in ordinary DOP (not modified) & outputting this modified native DSD so reading DOP DSD512 would not be feasible for these XMOS uCs?
Can you, if possible, point me to the "others" who have "tried and succeeded "?

Who is online

Users browsing this forum: No registered users and 0 guests