I'm using the slicekit with app_usb_aud_skc_u16_audio8 project from USB-Audio-2.0-Device-Software_6.12.6 set to target 2io_spdifout_spdifin, connected to a powerbook, OSX Yosemite 10.10.5.
When I select SPDIF In as the clock source, the sample rate doesn't change. E.g. I'll set internal sample rate 88.2K, and have a 48K spdif input, and select SPDIF clock, and the sample rate doesn't change to 48K. Also the output sample rate of the board doesn't change. The clock stays on SPDIF input in the Mac's AudioMIDI control panel - if I unplug the spdif cable, it reverts to internal. So it seems the board's happy with the input stream.
I figured there was only one clock domain at a time and it should update to the SPDIF sample rate... what am I missing?
isn't sample rate supposed to change when locked to SPDIF?
-
- Active Member
- Posts: 40
- Joined: Mon Dec 30, 2013 7:29 am
isn't sample rate supposed to change when locked to SPDIF?
You do not have the required permissions to view the files attached to this post.
-
- XCore Expert
- Posts: 966
- Joined: Thu Dec 10, 2009 9:20 pm
- Location: Bristol, UK
Hi,
No, it doesn't by default - that was a design decision based on customer feedback in the musical instrument space where having the device rate change without user interaction is seen as a bad thing.
You could modify the code, but note, this is just a notification that something has changed, the host most query as to the reason and perform any appropriate action. The device must continue to operate at its original sample rate until the host instructs otherwise - failing to do so is going to cause problems with the async clocking scheme and the host driver.
No, it doesn't by default - that was a design decision based on customer feedback in the musical instrument space where having the device rate change without user interaction is seen as a bad thing.
You could modify the code, but note, this is just a notification that something has changed, the host most query as to the reason and perform any appropriate action. The device must continue to operate at its original sample rate until the host instructs otherwise - failing to do so is going to cause problems with the async clocking scheme and the host driver.
-
- Active Member
- Posts: 40
- Joined: Mon Dec 30, 2013 7:29 am
OK... now I'm really confused.
What actually does the clock source select box do in the firmware? (from trying to trace through the source, it seems like it's actually changing the clock source to the digital input)
Which sample clock is the hardware/firmware following when you select SPDIF in clock?
If the hardware/firmware is tracking the external digital in's sample clock, then which sample rate is the USB driver (host) following?
Thanks
What actually does the clock source select box do in the firmware? (from trying to trace through the source, it seems like it's actually changing the clock source to the digital input)
Which sample clock is the hardware/firmware following when you select SPDIF in clock?
If the hardware/firmware is tracking the external digital in's sample clock, then which sample rate is the USB driver (host) following?
Thanks
-
- XCore Legend
- Posts: 1126
- Joined: Thu May 27, 2010 10:08 am
It selects the reference for the PLL to be either a fixed square wave generated by a timer off the local processor clock or a toggle signal derived from SPDIF receive.OK... now I'm really confused.
What actually does the clock source select box do in the firmware? (from trying to trace through the source, it seems like it's actually changing the clock source to the digital input)
The one generated by receiving SPDIF frames by the code in clockgen.xc.Which sample clock is the hardware/firmware following when you select SPDIF in clock?
i.e. use the clock recovered from SPDIF rx
The one selected by the host. So the user needs to ensure fs spdif = fs host else you will get lots of noiseIf the hardware/firmware is tracking the external digital in's sample clock, then which sample rate is the USB driver (host) following?
Edit... The host sample rate tracks the device sample rate because we use asynchronous USB audio where the device provides feedback about the local mclk to the host. However the nominal sample rate (fs) must be correctly selected so that the clock calculation on the host is correct.
-
- Active Member
- Posts: 40
- Joined: Mon Dec 30, 2013 7:29 am
Thanks for the reply!
It ultimately calls AudioHwConfig() in audiohw.xc to change the clock source, correct?infiniteimprobability wrote:It selects the reference for the PLL to be either a fixed square wave generated by a timer off the local processor clock or a toggle signal derived from SPDIF receive.OK... now I'm really confused.
What actually does the clock source select box do in the firmware? (from trying to trace through the source, it seems like it's actually changing the clock source to the digital input)
So how can the xmos firmware force a sample rate change on the host (assume CoreAudio here where there's no ability to alter the drivers) so everything's peachy without explicit user intervention?infiniteimprobability wrote:The one selected by the host. So the user needs to ensure fs spdif = fs host else you will get lots of noiseIf the hardware/firmware is tracking the external digital in's sample clock, then which sample rate is the USB driver (host) following?
Edit... The host sample rate tracks the device sample rate because we use asynchronous USB audio where the device provides feedback about the local mclk to the host. However the nominal sample rate (fs) must be correctly selected so that the clock calculation on the host is correct.
-
- XCore Legend
- Posts: 1126
- Joined: Thu May 27, 2010 10:08 am
No - audiohw.xc handles the user part of setting up the audio hardware on a sample rate or stream format change initiated by the host.It ultimately calls AudioHwConfig() in audiohw.xc to change the clock source, correct?
clockgen.xc handles the audio clock selection.
I haven't done it so cannot say for sure, but here are some pointers / ideas / things to try.So how can the xmos firmware force a sample rate change on the host (assume CoreAudio here where there's no ability to alter the drivers) so everything's peachy without explicit user intervention?
You need to get the host to recognise that something has changed and for it to change the sample rate (everything in USB is host initiated, even interrupts which are just a regular poll really).
The interrupt mechanism is already in the firmware and are certainly in the UAC2 spec "..inform the host about dynamic changes that occur on the different addressable Entities"
I couldn't see mention of an interrupt for the Clock entity however section 6.2 states "Any Control within an addressable Entity of the audio function can be the source of an interrupt. The interrupt message contains enough information to determine exactly which Control caused the interrupt. The Host can then issue the normal Control requests to further qualify the cause of the interrupt."
The question is, will the host driver see this and then do something? I can't see what it could do exactly because how would it know which sample rate to choose from the list? - What should it do precisely? Perhaps you could restrict the range reported...or maybe have multiple clock sources (each being an entity) and use the clock selector to switch between them using an interrupt. I am not sure without some investigation work...
What I'd recommend to do next is have a play with generating an interrupt from the following code (which sends the entity ID across to usb_buffer.xc to report the interrupt to the host).
See what actually happens from the host side. It looks like this code is sending an interrupt message which is the entity ID of the relevant clock source.
Code: Select all
static int clockFreq[NUM_CLOCKS]; /* Store current clock freq for each clock unit */
static int clockValid[NUM_CLOCKS]; /* Store current validity of each clock unit */
static int clockInt[NUM_CLOCKS]; /* Interupt flag for clocks */
static int clockId[NUM_CLOCKS];
Code: Select all
#if defined(SPDIF_RX) || defined(ADAT_RX)
static inline void setClockValidity(chanend c_interruptControl, int clkIndex, int valid, int currentClkMode)
{
if (clockValid[clkIndex] != valid)
{
clockValid[clkIndex] = valid;
outInterrupt(c_interruptControl, clockId[clkIndex]);
#ifdef CLOCK_VALIDITY_CALL
#ifdef ADAT_RX
if (currentClkMode == CLOCK_ADAT && clkIndex == CLOCK_ADAT_INDEX)
{
VendorClockValidity(valid);
}
#endif
#ifdef SPDIF_RX
if (currentClkMode == CLOCK_SPDIF && clkIndex == CLOCK_SPDIF_INDEX)
{
VendorClockValidity(valid);
}
#endif
#endif
}
}
There is also an interesting section in the spec worth reading: 5.2.6.1.1 Active Alternate Setting Control
"This Control is used to inform Host software which Alternate Setting of an AudioStreaming interface is currently active. The main purpose of this Control is to notify the Host (through an interrupt) that the last selected Alternate Setting is no longer valid. There can be a variety of reasons why this could happen. For instance, increasing the sampling frequency of a Clock Source Entity might render the current Alternate Setting of an interface connected to that Clock Source invalid because more bandwidth is now needed than is available in the current Alternate Setting."
Again, I am not sure if the driver in OSX supports this..
Edit.
One further thought, and something I would try first in your shoes... the current code reports the following after a clock interupt:
Code: Select all
case ID_CLKSRC_INT:
/* Always report our current operating frequency */
(buffer, unsigned[])[0] = g_curSamFreq;
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 4, sp.wLength );
break;
You can issue an interrupt request in clockgen by running the helper
Code: Select all
outInterrupt(chanend c_interruptControl, int value)
-
- Active Member
- Posts: 40
- Joined: Mon Dec 30, 2013 7:29 am
After spending quite some time with clockgen.xc I still can't figure out where that is happening.... I get that clockGen() has some token streams to select the clock that come from endpoint0, but I don't get how it's actually changing the clock source. (I need to select from a variety of hardware clocks and inputs when this happens, eventually)infiniteimprobability wrote:No - audiohw.xc handles the user part of setting up the audio hardware on a sample rate or stream format change initiated by the host.It ultimately calls AudioHwConfig() in audiohw.xc to change the clock source, correct?
clockgen.xc handles the audio clock selection.
Those look like good avenues for exploration, and I appreciate the thought that went into them, and I'll bookmark this page, but honestly, I can't get into fixing what in my opinion, as a long time designer of digital pro audio gear, is a wrong design choice in this firmware. We'll see if the users agree with the decision if I don't have time to fix it before it ships. I can't really afford to go down the rabbit hole at the moment. I think xmos should look at this again, and at the very least provide an option to do it either way.infiniteimprobability wrote:I haven't done it so cannot say for sure, but here are some pointers / ideas / things to try.So how can the xmos firmware force a sample rate change on the host (assume CoreAudio here where there's no ability to alter the drivers) so everything's peachy without explicit user intervention?
-
- XCore Legend
- Posts: 1126
- Joined: Thu May 27, 2010 10:08 am
I hear you and I can see the point - I'm an apps engineer so don't make the resource/project decisions so will pass on your comments to the product guys. As ever, it helps to have an idea about opportunity size to help them make the priority calls. Feel free to PM me with these so I can pass them on.I think xmos should look at this again, and at the very least provide an option to do it either way.
-
- Active Member
- Posts: 40
- Joined: Mon Dec 30, 2013 7:29 am
Thanks I will. They seemed to like my SMUX standard, as it's in the driver... I came up with that a long time ago while at Sonorus.infiniteimprobability wrote: I hear you and I can see the point - I'm an apps engineer so don't make the resource/project decisions so will pass on your comments to the product guys. As ever, it helps to have an idea about opportunity size to help them make the priority calls. Feel free to PM me with these so I can pass them on.
Any clue about my clocking question above? Or should I start another thread for that?
-
- XCore Legend
- Posts: 1126
- Joined: Thu May 27, 2010 10:08 am
Do you mean
In clockgen, the reference for the CS2100 is driven by port p. So whereever you see
or similar, it's sending an edge for the ref clock.
The code sending the edges is guarded by or the timer comparing against timeNextEdge. If the clock is recovered, timeNextEdge is set far enough in the future that it doesn't fire
This is all controlled via endpoint zero which handles the USB audio control entities.
?I don't get how it's actually changing the clock source.
In clockgen, the reference for the CS2100 is driven by port p. So whereever you see
Code: Select all
p <: pinVal;
The code sending the edges is guarded by
Code: Select all
clkMode
This is all controlled via endpoint zero which handles the USB audio control entities.