Enabling DoP 256 in USB-Audio 2.0 Device Software (AN00103) Topic is solved

If you have a simple question and just want an answer.
jannis
Junior Member
Posts: 6
Joined: Mon Mar 07, 2016 11:42 am

Enabling DoP 256 in USB-Audio 2.0 Device Software (AN00103)

Post by jannis »

I'm using an XS1-L8 on a custom hardware with a firmware based on the USB Audio 2.0 Device Software (v6.12.5). I just changed a few things in the DFU section, so the audio section shouldn't be affected by my changes.
I'm able to use DSD256 (native) and DoP128 on this hardware and everything works fine.

Now I'm trying to support DoP256 in this software as well.
But when I'm adding the suggestions of the application note AN00103 the FW becomes instable and I'm not able to use DoP128 anymore.
Is it possible to use DoP256 with the USB Audio 2.0 software?
Is the AN00103 still compatible with version 6.12.5 of the device software?

Thanks
View Solution
User avatar
Ross
Verified
XCore Legend
Posts: 1185
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

DoP256 is going to require that the design can handle an effective PCM rate of 352.8kHz (thats just how the spec works im afraid.. ).

Does you DAC and the rest of your hardware support this?
jannis
Junior Member
Posts: 6
Joined: Mon Mar 07, 2016 11:42 am

Post by jannis »

Yes, the design should be able to handle PCM 352.8kHz.
There's a 22.5792MHz / 24.576MHz oscillator on the board and the DAC can handle the
required sample rate.
But the XMOS software converts the DoP data (coming from USB) to native DSD.
So the DAC has to handle native DSD256 in the end, right?
I don't want to use the I2S interface in this case.

I guess I have to set the MAX_FREQ (in customdefines.h) to 705.6kHz.
Could this be a problem, because the software perhaps expects an audio clock of 45.1584MHz?

edit:
I think I've found the problem.
Adding the lines below (as mentioned in AN00103), also mutes the DSD data to the DAC.
I thought it's only triggered when using PCM data.

Code: Select all

if (curSamFreq > 192000){ //Maximum PCM sample rate supported by the DAC.
samplesOut[0] = 0; //Above this, any DAC data will be zero
samplesOut[1] = 0;
}
If I set the maximum PCM rate in the if-statement to 352800 I can measure DSD clock and data at the XMOS.
At the moment it's very noisy, but there may be a problem in configuring the DAC.


Thanks for your help.
jannis
Junior Member
Posts: 6
Joined: Mon Mar 07, 2016 11:42 am

Post by jannis »

I guess I was a bit too hasty, it's still not working.
I measured the DSD clock again and saw that the clock isn't a continuous 11.2896MHz signal.
It puts out 15 clocks at 11.2896MHz and then stays high for a while (see attached picture).
091119_094317008077.jpg
Has somebody a idea what's going wrong?
You do not have the required permissions to view the files attached to this post.
User avatar
infiniteimprobability
Verified
XCore Legend
Posts: 1164
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

I'm not sure of the exact cause, but what you are seeing is blocking of the main audio loop (called deliver() in audio.xc)

The DSD clocks are generated by outputting patterns:

Code: Select all

   /* Output DSD data to ports then 32 clocks */
            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;
            }
So the above bit is working at least once but things are going wrong after that.

Do you get multiple bursts of DSD clock or just one instance?

If just one, then you are seeing audio block on something (port or channel probably), but if you see bursts then you are getting temporary blocking causing a timing failure.

If you are getting just one burst, what does the debugger say about where the audio.xc task is when it freezes?
jannis
Junior Member
Posts: 6
Joined: Mon Mar 07, 2016 11:42 am

Post by jannis »

I can see bursts of the DSD clock. I should have used a different time scale for the picture.
Btw. the blocking time isn't always the same. It seems to be between 216ns and 396ns (approximately).

I created a new project from the original reference design software sources to eliminate problems
which I might have caused thru my own changes.
Sadly I still see the interrupted DSD clock.

Just out of curiosity. If I'm not mistaken the code below is used if the audio source is DoP.

Code: Select all

else if(dsdMode == DSD_MODE_DOP)
 {
        if(!everyOther)
        {
                ...
        }
        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)));
                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;
                }
        }
}
I think this would match the DSD clock I'm seeing.
Every loop cycle 16 clocks are generated (case 2) and then something takes too long and blocks the punctual generation of the DSD clock.

Thanks again for your help.
User avatar
infiniteimprobability
Verified
XCore Legend
Posts: 1164
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

It seems to be between 216ns and 396ns (approximately).
OK - so this is definitely a timing issue..

At DSD256 (11.2896Mhz DSD clock), for DoP where you only get 16b of data, you have an effective sample rate of 705.6KHz. This gives a sample period of 1.41723us.. Which is going some, but has been tested to work previously.

If we assume that this works, then we have to find out what has happened to make your case fail..

Firstly - can you say how many cores are running on the L8 and what core frequency you are using. This is to find out how many MIPS are available to the audio task..

Secondly, please confirm which sample rates are working? (DSD64/128 OK?)

Thirdly, can you try adding the following to customdefines.h:
#define MIXER 1
#define MAX_MIX_COUNT 0

This will insert a task between decouple and audio which should ease timing on audio (it hides the interrupt latency in decouple from audio which saves about 400ns, at the cost of an extra task).

Finally, yes, that's the DoP bit. It build a complete 32b DSD word from two 16b packets, each of which arrives in a single PCM sample. As you say, it also outputs 16 clocks on each sample. This code has been tested to support DSD256 though so should meet timing OK..
jannis
Junior Member
Posts: 6
Joined: Mon Mar 07, 2016 11:42 am

Post by jannis »

There are 5 cores running and the system frequency is 500MHz.

The following sample rates are working:
- DSD64, DSD128, DSD256 (all native DSD)
- DoP64, DoP128

I added the suggestions you made for the customdefines.h.
The good news is it seems to fix the timing issue related to the DSD clock, but it also freezes the computer (win7) every time the audio format is DoP256 (all other sample rates seem to work).
The player (Foobar2000, JRiver) crashes (no respond), keyboard and mouse (both are USB devices) are not working anymore.
The strange thing is, I can still see the DSD clock and something at the DSD data outputs.
The DSD clock is not interrupted anymore.
User avatar
infiniteimprobability
Verified
XCore Legend
Posts: 1164
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

HI,
OK well that's helpful to know - confirms we definitely have a timing issue. However, what is strange is that the timing issue didn't exist before - the app note worked fine on the MFA board (similar processor to the one you are using). Something is different about your setup from the App note .. You shouldn't have to enable mixer actually...

What are you customdefines.h settings? What other changes have you made?
The player (Foobar2000, JRiver) crashes (no respond), keyboard and mouse (both are USB devices) are not working anymore.
This normally means endpoint zero has been blocked somehow. When you change sample rates, the code waits until audio (I2S/DSD) has completely finished it's sample rate change and signalled back, before sending the ACK back to the host via EP0. This is good as the host knows for sure when the sample rate change has completed.

However, what I don't understand is that your audio task seems to be looping OK, which must mean the ACK has been sent back.. so should be communicating OK.

Do you have a USB analyser? It would be interesting to see where the host thinks things are when it hangs..

However, like I say, the app note works so something is different to cause this....
User avatar
infiniteimprobability
Verified
XCore Legend
Posts: 1164
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

One other question - if you attempt to stream PCM at 705.6KHz (which the host will be told it can in fact do) as opposed to an actual DoP256 file, then do you still get the freeze?