This commit is contained in:
Ross Owen
2015-09-17 17:11:07 +01:00
13 changed files with 336 additions and 264 deletions

View File

@@ -1,6 +1,19 @@
sc_usb_audio Change Log
=======================
6.12.7
------
- ADDED: Device now uses implicit feedback when input stream is available (previously explicit
feedback pipe always used). This saves chanend/EP resources and means less processing
burden for the host. Previous behaviour available by enabling UAC_FORCE_FEEDBACK_EP
- CHANGE: Mixer and non-mixer channel comms scheme (decouple <-> audio path) now the identical
6.12.6
------
- RESOLVED: Build error when DFU is disabled
- RESOLVED: Build error when I2S_CHANS_ADC or I2S_CHANS_DAC set to 0 and CODEC_MASTER enabled
6.12.5
------
- RESOLVED: Stream issue when NUM_USB_CHAN_IN < I2S_CHANS_ADC

View File

@@ -256,33 +256,6 @@ static inline unsigned DoSampleTransfer(chanend c_out, int readBuffNo, unsigned
}
else
{
#ifndef MIXER // Interfaces straight to decouple()
inuint(c_out);
#if NUM_USB_CHAN_IN > 0
#pragma loop unroll
for(int i = 0; i < I2S_CHANS_ADC; i++)
{
if(readBuffNo)
outuint(c_out, samplesIn_1[i]);
else
outuint(c_out, samplesIn_0[i]);
}
/* Send over the digi channels - no odd buffering required */
#pragma loop unroll
for(int i = I2S_CHANS_ADC; i < NUM_USB_CHAN_IN; i++)
{
outuint(c_out, samplesIn_0[i]);
}
#endif
#if NUM_USB_CHAN_OUT > 0
#pragma loop unroll
for(int i = 0; i < NUM_USB_CHAN_OUT; i++)
{
samplesOut[i] = inuint(c_out);
}
#endif
#else /* ifndef MIXER */
#if NUM_USB_CHAN_OUT > 0
#pragma loop unroll
for(int i = 0; i < NUM_USB_CHAN_OUT; i++)
@@ -290,6 +263,8 @@ static inline unsigned DoSampleTransfer(chanend c_out, int readBuffNo, unsigned
int tmp = inuint(c_out);
samplesOut[i] = tmp;
}
#else
inuint(c_out);
#endif
#if NUM_USB_CHAN_IN > 0
#pragma loop unroll
@@ -310,7 +285,6 @@ static inline unsigned DoSampleTransfer(chanend c_out, int readBuffNo, unsigned
{
outuint(c_out, samplesIn_0[i]);
}
#endif
#endif
}
@@ -462,13 +436,8 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
chanend ?c_adc)
{
#if (I2S_CHANS_ADC != 0) || defined(SPDIF_TX)
unsigned sample;
#endif
//#if NUM_USB_CHAN_IN > 0
/* Since DAC and ADC buffered ports off by one sample we buffer previous ADC frame */
unsigned readBuffNo = 0;
//#endif
unsigned index;
#ifdef RAMP_CHECK
@@ -642,6 +611,7 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
{
// p_i2s_adc[index++] :> sample;
// Manual IN instruction since compiler generates an extra setc per IN (bug #15256)
unsigned sample;
asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++]));
/* Note the use of readBuffNo changes based on frameCount */
@@ -719,7 +689,7 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
#endif
#if defined(SPDIF_TX) && (NUM_USB_CHAN_OUT > 0)
outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX]); /* Forward sample to S/PDIF Tx thread */
sample = samplesOut[SPDIF_TX_INDEX + 1];
unsigned sample = samplesOut[SPDIF_TX_INDEX + 1];
outuint(c_spd_out, sample); /* Forward sample to S/PDIF Tx thread */
#endif
}
@@ -732,7 +702,9 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
for(int i = 0; i < I2S_CHANS_ADC; i += I2S_CHANS_PER_FRAME)
{
/* Manual IN instruction since compiler generates an extra setc per IN (bug #15256) */
unsigned sample;
asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++]));
if(buffIndex)
samplesIn_1[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i] = bitrev(sample); // channels 1, 3, 5.. on each line.
else
@@ -909,35 +881,28 @@ static void dummy_deliver(chanend c_out, unsigned &command)
}
else
{
#ifndef MIXER // Interfaces straight to decouple()
(void) inuint(c_out);
#if NUM_USB_CHAN_OUT > 0
#pragma loop unroll
for(int i = 0; i < NUM_USB_CHAN_OUT; i++)
{
int tmp = inuint(c_out);
samplesOut[i] = tmp;
}
#else
inuint(c_out);
#endif
#if NUM_USB_CHAN_IN > 0
#pragma loop unroll
for(int i = 0; i < NUM_USB_CHAN_IN; i++)
{
outuint(c_out, 0);
}
#pragma loop unroll
for(int i = 0; i < NUM_USB_CHAN_OUT; i++)
{
(void) inuint(c_out);
}
#else
#pragma loop unroll
for(int i = 0; i < NUM_USB_CHAN_OUT; i++)
{
(void) inuint(c_out);
}
#pragma loop unroll
for(int i = 0; i < NUM_USB_CHAN_IN; i++)
{
outuint(c_out, 0);
}
#endif
}
}
outuint(c_out, 0);
outuint(c_out, 0);
break;
}
}
@@ -1097,7 +1062,7 @@ chanend ?c_config, chanend ?c
{
/* Configure audio ports */
ConfigAudioPortsWrapper(
#if (I2S_CHANS_DAC != 0)
#if (I2S_CHANS_DAC != 0) || (DSD_CHANS_DAC != 0)
p_dsd_dac,
DSD_CHANS_DAC,
#endif

View File

@@ -1092,7 +1092,9 @@
enum USBEndpointNumber_In
{
ENDPOINT_NUMBER_IN_CONTROL, /* Endpoint 0 */
#if (NUM_USB_CHAN_IN == 0) || (defined UAC_FORCE_FEEDBACK_EP)
ENDPOINT_NUMBER_IN_FEEDBACK,
#endif
ENDPOINT_NUMBER_IN_AUDIO,
#if defined(SPDIF_RX) || defined(ADAT_RX)
ENDPOINT_NUMBER_IN_INTERRUPT, /* Audio interrupt/status EP */

View File

@@ -671,24 +671,30 @@ typedef struct
USB_Descriptor_Audio_Format_Type1_t Audio_Out_Format;
USB_Descriptor_Endpoint_t Audio_Out_Endpoint;
USB_Descriptor_Audio_Class_AS_Endpoint_t Audio_Out_ClassEndpoint;
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
USB_Descriptor_Endpoint_t Audio_Out_Fb_Endpoint;
#endif
#if (OUTPUT_FORMAT_COUNT > 1)
USB_Descriptor_Interface_t Audio_Out_StreamInterface_Alt2;
USB_Descriptor_Audio_Interface_AS_t Audio_Out_ClassStreamInterface_2;
USB_Descriptor_Audio_Format_Type1_t Audio_Out_Format_2;
USB_Descriptor_Endpoint_t Audio_Out_Endpoint_2;
USB_Descriptor_Audio_Class_AS_Endpoint_t Audio_Out_ClassEndpoint_2;
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
USB_Descriptor_Endpoint_t Audio_Out_Fb_Endpoint_2;
#endif
#endif
#if (OUTPUT_FORMAT_COUNT > 2)
USB_Descriptor_Interface_t Audio_Out_StreamInterface_Alt3;
USB_Descriptor_Audio_Interface_AS_t Audio_Out_ClassStreamInterface_3;
USB_Descriptor_Audio_Format_Type1_t Audio_Out_Format_3;
USB_Descriptor_Endpoint_t Audio_Out_Endpoint_3;
USB_Descriptor_Audio_Class_AS_Endpoint_t Audio_Out_ClassEndpoint_3;
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
USB_Descriptor_Endpoint_t Audio_Out_Fb_Endpoint_3;
#endif
#endif
#endif
#if (NUM_USB_CHAN_IN > 0)
/* Audio Streaming: Input stream */
USB_Descriptor_Interface_t Audio_In_StreamInterface_Alt0; /* Zero bandwith alternative */
@@ -1234,7 +1240,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
/* Output Terminal Descriptor (USB Streaming) */
.bLength = 0x0C,
.bDescriptorType = UAC_CS_DESCTYPE_INTERFACE,
.bDescriptorSubtype = UAC_CS_AC_INTERFACE_SUBTYPE_OUTPUT_TERMINAL,
.bDescriptorSubtype = UAC_CS_AC_INTERFACE_SUBTYPE_OUTPUT_TERMINAL,
.bTerminalID = ID_OT_USB,
.wTerminalType = USB_TERMTYPE_USB_STREAMING,
.bAssocTerminal = 0x00,
@@ -1382,7 +1388,11 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
USB_DESCTYPE_INTERFACE, /* 1 bDescriptorType: INTERFACE */
INTERFACE_NUMBER_AUDIO_OUTPUT, /* 2 bInterfaceNumber: Number of interface */
1, /* 3 bAlternateSetting */
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
2, /* 4 bNumEndpoints */
#else
1, /* 4 bNumEndpoints */
#endif
USB_CLASS_AUDIO, /* 5 bInterfaceClass: AUDIO */
UAC_INT_SUBCLASS_AUDIOSTREAMING, /* 6 bInterfaceSubClass: AUDIO_STREAMING */
UAC_INT_PROTOCOL_IP_VERSION_02_00,/* 7 bInterfaceProtocol: IP_VERSION_02_00 */
@@ -1407,12 +1417,12 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
/* Type 1 Format Type Descriptor */
.Audio_Out_Format =
{
0x06, /* 0 bLength (in bytes): 6 */
UAC_CS_DESCTYPE_INTERFACE, /* 1 bDescriptorType: 0x24 */
UAC_CS_AS_INTERFACE_SUBTYPE_FORMAT_TYPE, /* 2 bDescriptorSubtype: FORMAT_TYPE */
UAC_FORMAT_TYPE_I, /* 3 bFormatType: FORMAT_TYPE_1 */
.bSubslotSize = HS_STREAM_FORMAT_OUTPUT_1_SUBSLOT_BYTES,
.bBitResolution = HS_STREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS,
.bLength = 0x06,
.bDescriptorType = UAC_CS_DESCTYPE_INTERFACE,
.bDescriptorSubtype = UAC_CS_AS_INTERFACE_SUBTYPE_FORMAT_TYPE,
.bFormatType = UAC_FORMAT_TYPE_I,
.bSubslotSize = HS_STREAM_FORMAT_OUTPUT_1_SUBSLOT_BYTES,
.bBitResolution = HS_STREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS,
},
/* Standard AS Isochronous Audio Data Endpoint Descriptor (4.10.1.1) */
@@ -1420,7 +1430,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
{
.bLength = sizeof(USB_Descriptor_Endpoint_t),
.bDescriptorType = USB_DESCTYPE_ENDPOINT,
.bEndpointAddress = 0x01, /* (D7: 0:out, 1:in) */
.bEndpointAddress = ENDPOINT_ADDRESS_OUT_AUDIO,
.bmAttributes = 0x05, /* (bitmap) */
.wMaxPacketSize = HS_STREAM_FORMAT_OUTPUT_1_MAXPACKETSIZE,
.bInterval = 1,
@@ -1438,15 +1448,17 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
0x0008, /* 6:7 bLockDelay */
},
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
.Audio_Out_Fb_Endpoint =
{
0x07, /* 0 bLength: 7 */
USB_DESCTYPE_ENDPOINT, /* 1 bDescriptorType: ENDPOINT */
0x81, /* 2 bEndpointAddress (D7: 0:out, 1:in) */
17, /* 3 bmAttributes (bitmap) */
0x0004, /* 4 wMaxPacketSize */
4, /* 6 bInterval. Only values <= 1 frame (4) supported by MS */
.bLength = 0x07,
.bDescriptorType = USB_DESCTYPE_ENDPOINT,
.bEndpointAddress = ENDPOINT_ADDRESS_IN_FEEDBACK,
.bmAttributes = 17, /* (bitmap) */
.wMaxPacketSize = 0x0004,
.bInterval = 4, /* Only values <= 1 frame (4) supported by MS */
},
#endif
#if (OUTPUT_FORMAT_COUNT > 1)
/* Standard AS Interface Descriptor (4.9.1) (Alt) */
.Audio_Out_StreamInterface_Alt2 =
@@ -1455,7 +1467,11 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
USB_DESCTYPE_INTERFACE, /* 1 bDescriptorType: INTERFACE */
INTERFACE_NUMBER_AUDIO_OUTPUT, /* 2 bInterfaceNumber: Number of interface */
2, /* 3 bAlternateSetting */
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
2, /* 4 bNumEndpoints */
#else
1, /* 4 bNumEndpoints */
#endif
USB_CLASS_AUDIO, /* 5 bInterfaceClass: AUDIO */
UAC_INT_SUBCLASS_AUDIOSTREAMING, /* 6 bInterfaceSubClass: AUDIO_STREAMING */
UAC_INT_PROTOCOL_IP_VERSION_02_00,/* 7 bInterfaceProtocol: IP_VERSION_02_00 */
@@ -1492,7 +1508,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
{
.bLength = sizeof(USB_Descriptor_Endpoint_t),
.bDescriptorType = USB_DESCTYPE_ENDPOINT,
.bEndpointAddress = 0x01,
.bEndpointAddress = ENDPOINT_ADDRESS_OUT_AUDIO,
.bmAttributes = 0x05,
.wMaxPacketSize = HS_STREAM_FORMAT_OUTPUT_2_MAXPACKETSIZE,
.bInterval = 1,
@@ -1510,16 +1526,18 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
0x0008, /* 6:7 bLockDelay */
},
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
.Audio_Out_Fb_Endpoint_2 =
{
0x07, /* 0 bLength: 7 */
USB_DESCTYPE_ENDPOINT, /* 1 bDescriptorType: ENDPOINT */
0x81, /* 2 bEndpointAddress (D7: 0:out, 1:in) */
ENDPOINT_ADDRESS_IN_FEEDBACK, /* 2 bEndpointAddress (D7: 0:out, 1:in) */
17, /* 3 bmAttributes (bitmap) */
0x0004, /* 4 wMaxPacketSize */
4, /* 6 bInterval. Only values <= 1 frame (4) supported by MS */
},
#endif
#endif
#if (OUTPUT_FORMAT_COUNT > 2)
/* Standard AS Interface Descriptor (4.9.1) (Alt) */
.Audio_Out_StreamInterface_Alt3 =
@@ -1528,7 +1546,11 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
USB_DESCTYPE_INTERFACE, /* 1 bDescriptorType: INTERFACE */
INTERFACE_NUMBER_AUDIO_OUTPUT, /* 2 bInterfaceNumber: Number of interface */
3, /* 3 bAlternateSetting */
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
2, /* 4 bNumEndpoints */
#else
1, /* 4 bNumEndpoints */
#endif
USB_CLASS_AUDIO, /* 5 bInterfaceClass: AUDIO */
UAC_INT_SUBCLASS_AUDIOSTREAMING, /* 6 bInterfaceSubClass: AUDIO_STREAMING */
UAC_INT_PROTOCOL_IP_VERSION_02_00,/* 7 bInterfaceProtocol: IP_VERSION_02_00 */
@@ -1566,7 +1588,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
{
.bLength = 0x07,
.bDescriptorType = USB_DESCTYPE_ENDPOINT,
.bEndpointAddress = 0x01,
.bEndpointAddress = ENDPOINT_ADDRESS_OUT_AUDIO,
.bmAttributes = 0x05,
.wMaxPacketSize = HS_STREAM_FORMAT_OUTPUT_3_MAXPACKETSIZE,
.bInterval = 1,
@@ -1584,15 +1606,17 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
.wLockDelay = 0x0008,
},
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
.Audio_Out_Fb_Endpoint_3 =
{
.bLength = 0x07,
.bDescriptorType = USB_DESCTYPE_ENDPOINT,
.bEndpointAddress = 0x81,
.bEndpointAddress = ENDPOINT_ADDRESS_IN_FEEDBACK,
.bmAttributes = 17, /* (bitmap) */
.wMaxPacketSize = 0x0004,
.bInterval = 4, /* Only values <= 1 frame (4) supported by MS */
},
#endif
#endif /* OUTPUT_FORMAT_COUNT > 2 */
#endif /* OUTPUT */
#if (NUM_USB_CHAN_IN > 0)
@@ -1657,8 +1681,12 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
{
.bLength = 0x07,
.bDescriptorType = USB_DESCTYPE_ENDPOINT,
.bEndpointAddress = 0x82,
.bmAttributes = 5,
.bEndpointAddress = ENDPOINT_ADDRESS_IN_AUDIO,
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
.bmAttributes = 0x05, /* Iso, async, data endpoint */
#else
.bmAttributes = 0x25, /* Iso, async, implicit feedback data endpoint */
#endif
.wMaxPacketSize = HS_STREAM_FORMAT_INPUT_1_MAXPACKETSIZE,
.bInterval = 0x01,
},
@@ -1721,8 +1749,12 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
{
.bLength = 0x07,
.bDescriptorType = USB_DESCTYPE_ENDPOINT,
.bEndpointAddress = 0x82,
.bmAttributes = 5,
.bEndpointAddress = ENDPOINT_ADDRESS_IN_AUDIO,
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
.bmAttributes = 0x05, /* Iso, async, data endpoint */
#else
.bmAttributes = 0x25, /* Iso, async, implicit feedback data endpoint */
#endif
.wMaxPacketSize = HS_STREAM_FORMAT_INPUT_2_MAXPACKETSIZE,
.bInterval = 0x01,
},
@@ -1786,8 +1818,12 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
{
.bLength = 0x07,
.bDescriptorType = USB_DESCTYPE_ENDPOINT,
.bEndpointAddress = 0x82,
.bmAttributes = 5,
.bEndpointAddress = ENDPOINT_ADDRESS_IN_AUDIO,
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
.bmAttributes = 0x05, /* Iso, async, data endpoint */
#else
.bmAttributes = 0x25, /* Iso, async, implicit feedback data endpoint */
#endif
.wMaxPacketSize = HS_STREAM_FORMAT_INPUT_3_MAXPACKETSIZE,
.bInterval = 0x01,
},
@@ -2179,7 +2215,11 @@ unsigned char cfgDesc_Null[] =
/* Note, this is different that INTERFACE_COUNT since we dont support items such as MIDI, iAP etc in UAC1 mode */
#define NUM_INTERFACES_A1 (1+INPUT_INTERFACES_A1 + OUTPUT_INTERFACES_A1)
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
#define CFG_TOTAL_LENGTH_A1 (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES_A1 * 61) + (OUTPUT_INTERFACES_A1 * 70))
#else
#define CFG_TOTAL_LENGTH_A1 (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES_A1 * 61) + (OUTPUT_INTERFACES_A1 * 61))
#endif
/* In UAC1 supported sample rates are listed in descriptor */
/* Note, we always report 4 freqs, doing otherwise seems to cause an enumeration issue on Windows */
@@ -2317,7 +2357,11 @@ unsigned char cfgDesc_Audio1[] =
0x04, /* INTERFACE */
0x01, /* Interface no */
0x01, /* AlternateSetting */
0x02, /* num endpoints 2: audio EP and feedback EP */
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
0x02, /* bNumEndpoints 2: audio EP and feedback EP */
#else
0x01, /* bNumEndpoints */
#endif
0x01, /* Interface class - AUDIO */
0x02, /* subclass - AUDIO_STREAMING */
0x00, /* Unused */
@@ -2367,7 +2411,11 @@ unsigned char cfgDesc_Audio1[] =
(FS_STREAM_FORMAT_OUTPUT_1_MAXPACKETSIZE&0xff00)>>8, /* 5 wMaxPacketSize */
0x01, /* bInterval */
0x00, /* bRefresh */
0x81, /* bSynchAdddress - address of EP used to communicate sync info */
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
ENDPOINT_ADDRESS_IN_FEEDBACK, /* bSynchAdddress - address of EP used to communicate sync info */
#else
ENDPOINT_ADDRESS_IN_AUDIO,
#endif
/* CS_Endpoint Descriptor ?? */
0x07,
@@ -2377,16 +2425,18 @@ unsigned char cfgDesc_Audio1[] =
0x02, /* bLockDelayUnits */
0x00, 0x00, /* bLockDelay */
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
/* Feedback EP */
0x09,
0x05, /* bDescriptorType: ENDPOINT */
0x81, /* bEndpointAddress (D3:0 - EP no. D6:4 - reserved 0. D7 - 0:out, 1:in) */
ENDPOINT_ADDRESS_IN_FEEDBACK, /* bEndpointAddress (D3:0 - EP no. D6:4 - reserved 0. D7 - 0:out, 1:in) */
0x01, /* bmAttributes (bitmap) */
0x03,0x0, /* wMaxPacketSize */
0x01, /* bInterval - Must be 1 for compliance */
0x04, /* bRefresh 2^x */
0x0, /* bSynchAddress */
#endif
#endif
#if (NUM_USB_CHAN_IN > 0)
/* Standard Interface Descriptor - Audio streaming IN */
@@ -2447,8 +2497,12 @@ unsigned char cfgDesc_Audio1[] =
/* Standard Endpoint Descriptor */
0x09,
0x05, /* ENDPOINT */
0x82, /* EndpointAddress */
0x05, /* Attributes - isochronous async */
ENDPOINT_ADDRESS_IN_AUDIO, /* EndpointAddress */
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
0x05, /* Iso, async, data endpoint */
#else
0x25, /* Iso, async, implicit feedback data endpoint */
#endif
FS_STREAM_FORMAT_INPUT_1_MAXPACKETSIZE&0xff, /* 4 wMaxPacketSize (Typically 294 bytes)*/
(FS_STREAM_FORMAT_INPUT_1_MAXPACKETSIZE&0xff00)>>8, /* 5 wMaxPacketSize */
0x01, /* bInterval */

View File

@@ -525,7 +525,7 @@ void Endpoint0(chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
{
unsigned epNum = sp.wIndex & 0xff;
if ((epNum == 0x82) || (epNum == 0x01))
if ((epNum == ENDPOINT_ADDRESS_OUT_AUDIO) || (epNum == ENDPOINT_ADDRESS_IN_AUDIO))
{
#if (AUDIO_CLASS == 2) && defined(AUDIO_CLASS_FALLBACK)
if(g_curUsbSpeed == XUD_SPEED_FS)
@@ -586,8 +586,12 @@ void Endpoint0(chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
* - Audio STREAMING interface request (In or Out)
* - Audio endpoint request (Audio 1.0 Sampling freq requests are sent to the endpoint)
*/
if(((interfaceNum == 0) || (interfaceNum == 1) || (interfaceNum == 2)) && !DFU_mode_active)
{
if(((interfaceNum == 0) || (interfaceNum == 1) || (interfaceNum == 2))
#ifdef DFU
&& !DFU_mode_active
#endif
)
{
#if (AUDIO_CLASS == 2) && defined(AUDIO_CLASS_FALLBACK)
if(g_curUsbSpeed == XUD_SPEED_HS)
{

View File

@@ -212,16 +212,19 @@ XUD_EpType epTypeTableOut[ENDPOINT_COUNT_OUT] = { XUD_EPTYPE_CTL | XUD_STATUS_EN
XUD_EPTYPE_BUL, /* MIDI */
#endif
#ifdef IAP
XUD_EPTYPE_BUL, /* iAP */
XUD_EPTYPE_BUL, /* iAP */
#ifdef IAP_EA_NATIVE_TRANS
XUD_EPTYPE_BUL, /* EA Native Transport */
XUD_EPTYPE_BUL, /* EA Native Transport */
#endif
#endif
};
XUD_EpType epTypeTableIn[ENDPOINT_COUNT_IN] = { XUD_EPTYPE_CTL | XUD_STATUS_ENABLE,
XUD_EPTYPE_ISO,
XUD_EPTYPE_ISO,
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
XUD_EPTYPE_ISO, /* Async feedback endpoint */
#endif
#if defined (SPDIF_RX) || defined (ADAT_RX)
XUD_EPTYPE_BUL,
#endif
@@ -278,7 +281,7 @@ void usb_audio_core(chanend c_mix_out
#endif
, chanend ?c_clk_int
, chanend ?c_clk_ctl
, client interface i_dfu dfuInterface
, client interface i_dfu ?dfuInterface
)
{
chan c_sof;
@@ -330,12 +333,14 @@ void usb_audio_core(chanend c_mix_out
asm("setclk res[%0], %1"::"r"(p_for_mclk_count), "r"(x));
#endif
//:buffer
buffer(c_xud_out[ENDPOINT_NUMBER_OUT_AUDIO],/* Audio Out*/
c_xud_in[ENDPOINT_NUMBER_IN_AUDIO], /* Audio In */
buffer(c_xud_out[ENDPOINT_NUMBER_OUT_AUDIO], /* Audio Out*/
c_xud_in[ENDPOINT_NUMBER_IN_AUDIO], /* Audio In */
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
c_xud_in[ENDPOINT_NUMBER_IN_FEEDBACK], /* Audio FB */
#endif
#ifdef MIDI
c_xud_out[ENDPOINT_NUMBER_OUT_MIDI], /* MIDI Out */ // 2
c_xud_in[ENDPOINT_NUMBER_IN_MIDI], /* MIDI In */ // 4
c_xud_out[ENDPOINT_NUMBER_OUT_MIDI], /* MIDI Out */ // 2
c_xud_in[ENDPOINT_NUMBER_IN_MIDI], /* MIDI In */ // 4
c_midi,
#endif
#ifdef IAP
@@ -536,8 +541,10 @@ int main()
{
#if (XUD_TILE == 0)
/* Check if USB is on the flash tile (tile 0) */
#ifdef DFU
[[distribute]]
DFUHandler(dfuInterface, null);
#endif
#endif
usb_audio_core(c_mix_out
#ifdef MIDI

View File

@@ -203,6 +203,9 @@ static inline void GiveSamplesToHost(chanend c, xc_ptr ptr, xc_ptr multIn)
#pragma unsafe arrays
static inline void GetSamplesFromHost(chanend c)
{
#if (NUM_USB_CHAN_OUT == 0)
inuint(c);
#else
{
#pragma loop unroll
for (int i=0; i<NUM_USB_CHAN_OUT; i++)
@@ -238,6 +241,7 @@ static inline void GetSamplesFromHost(chanend c)
write_via_xc_ptr_indexed(samples_array, i, h);
#else
ptr_samples[i] = sample;
#endif
#endif
}
}
@@ -358,9 +362,10 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
/* Request from audio()/mixer2() */
request = inuint(c_mixer2);
/* Forward on Request for data to decouple thread */
outuint(c_host, request);
/* Between request to decouple and respose ~ 400nS latency for interrupt to fire */
select
{
@@ -531,7 +536,7 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
}
else
{
inuint(c_host);
#if MAX_MIX_COUNT > 0
outuint(c_mixer2, 0);
GiveSamplesToHost(c_host, samples_to_host_map, multIn);
@@ -559,11 +564,11 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
#if MAX_MIX_COUNT > 2
#ifdef FAST_MIXER
mixed = doMix2(samples, mix_mult_slice(2));
mixed = doMix2(samples, mix_mult_slice(2));
#else
mixed = doMix(samples, mix_map_slice(2),mix_mult_slice(2));
mixed = doMix(samples, mix_map_slice(2),mix_mult_slice(2));
#endif
write_via_xc_ptr_indexed(samples_array, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 2), mixed);
write_via_xc_ptr_indexed(samples_array, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 2), mixed);
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
ComputeMixerLevel(mixed, 2);
@@ -598,10 +603,13 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
}
#else /* IF MAX_MIX_COUNT > 0 */
/* No mixes, this thread runs on its own doing just volume */
#if(NUM_USB_CHAN_OUT == 0)
outuint(c_mixer2, 0);
#endif
GiveSamplesToDevice(c_mixer2, samples_to_device_map, multOut);
GetSamplesFromDevice(c_mixer2);
GiveSamplesToHost(c_host, samples_to_host_map, multIn);
GetSamplesFromHost(c_host);
GiveSamplesToHost(c_host, samples_to_host_map, multIn);
#endif
}
}

View File

@@ -31,7 +31,7 @@ void EnableBufferedPort(port p, unsigned transferWidth)
/* C wrapper for ConfigAudioPorts() to handle DSD ports */
void ConfigAudioPortsWrapper(
#if (I2S_CHANS_DAC != 0)
#if (I2S_CHANS_DAC != 0) || (DSD_CHANS_DAC != 0)
port p_dac[], int numPortsDac,
#endif
@@ -46,7 +46,7 @@ void ConfigAudioPortsWrapper(
unsigned int divide, unsigned int dsdMode)
{
ConfigAudioPorts(
#if (I2S_CHANS_DAC != 0)
#if (I2S_CHANS_DAC != 0) || (DSD_CHANS_DAC != 0)
p_dac,
numPortsDac,
#endif

View File

@@ -57,7 +57,7 @@ void ConfigAudioPorts(
#ifdef __XC__
void ConfigAudioPortsWrapper(
#if (I2S_CHANS_DAC != 0)
#if (I2S_CHANS_DAC != 0) || (DSD_CHANS_DAC != 0)
buffered out port:32 p_i2s_dac[], int numPortsDAC,
#endif
@@ -78,7 +78,7 @@ void ConfigAudioPortsWrapper(
#else
void ConfigAudioPortsWrapper(
#if (I2S_CHANS_DAC != 0)
#if (I2S_CHANS_DAC != 0) || (DSD_CHANS_DAC != 0)
port p_i2s_dac[], int numPortsDAC,
#endif

View File

@@ -110,17 +110,21 @@ unsigned int divide)
/* Clock bclk clock-block from bclk pin */
configure_clock_src(clk_audio_bclk, p_bclk);
#if (I2S_CHANS_DAC != 0)
/* Clock I2S output data ports from b-clock clock block */
for(int i = 0; i < I2S_WIRES_DAC; i++)
{
configure_out_port_no_ready(p_i2s_dac[i], clk_audio_bclk, 0);
}
#endif
#if (I2S_CHANS_ADC != 0)
/* Clock I2S input data ports from clock block */
for(int i = 0; i < I2S_WIRES_ADC; i++)
{
configure_in_port_no_ready(p_i2s_adc[i], clk_audio_bclk);
}
#endif
configure_in_port_no_ready(p_lrclk, clk_audio_bclk);

View File

@@ -131,161 +131,9 @@ void handle_audio_request(chanend c_mix_out)
/* Input word that triggered interrupt and handshake back */
unsigned underflowSample = inuint(c_mix_out);
#if (NUM_USB_CHAN_OUT == 0)
outuint(c_mix_out, 0);
/* If in overflow condition then receive samples and throw away */
if(inOverflow || sampsToWrite == 0)
{
#pragma loop unroll
for(int i = 0; i < NUM_USB_CHAN_IN; i++)
{
(void) inuint(c_mix_out);
}
/* Calculate how much space left in buffer */
space_left = g_aud_to_host_rdptr - g_aud_to_host_wrptr;
if (space_left <= 0)
{
space_left += BUFF_SIZE_IN*4;
}
/* Check if we can come out of overflow */
if (space_left > (BUFF_SIZE_IN*4/2))
{
inOverflow = 0;
}
}
else
{
/* Not in overflow, store samples from mixer into sample buffer */
switch(g_curSubSlot_In)
{
case 2:
#if (STREAM_FORMAT_INPUT_SUBSLOT_2_USED == 0)
__builtin_unreachable();
#endif
for(int i = 0; i < g_numUsbChan_In; i++)
{
/* Receive sample */
int sample = inuint(c_mix_out);
#if (INPUT_VOLUME_CONTROL == 1)
#if !defined(IN_VOLUME_IN_MIXER)
/* Apply volume */
int mult;
int h;
unsigned l;
asm volatile("ldw %0, %1[%2]":"=r"(mult):"r"(p_multIn),"r"(i));
{h, l} = macs(mult, sample, 0, 0);
sample = h << 3;
/* Note, in 2 byte sub slot - ignore lower bits of macs */
#elif defined(IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX)
sample = sample << 3;
#endif
#endif
write_short_via_xc_ptr(g_aud_to_host_dptr, sample>>16);
g_aud_to_host_dptr+=2;
}
break;
case 4:
{
#if (STREAM_FORMAT_INPUT_SUBSLOT_4_USED == 0)
__builtin_unreachable();
#endif
unsigned ptr = g_aud_to_host_dptr;
for(int i = 0; i < g_numUsbChan_In; i++)
{
/* Receive sample */
int sample = inuint(c_mix_out);
#if(INPUT_VOLUME_CONTROL == 1)
#if !defined(IN_VOLUME_IN_MIXER)
/* Apply volume */
int mult;
int h;
unsigned l;
asm volatile("ldw %0, %1[%2]":"=r"(mult):"r"(p_multIn),"r"(i));
{h, l} = macs(mult, sample, 0, 0);
sample = h << 3;
#if (STREAM_FORMAT_INPUT_RESOLUTION_32BIT_USED == 1)
sample |= (l >> 29) & 0x7; // Note, this step is not required if we assume sample depth is 24 (rather than 32)
#endif
#elif defined(IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX)
sample = sample << 3;
#endif
#endif
/* Write into fifo */
write_via_xc_ptr(ptr, sample);
ptr+=4;
}
/* Update global pointer */
g_aud_to_host_dptr = ptr;
break;
}
case 3:
#if (STREAM_FORMAT_INPUT_SUBSLOT_3_USED == 0)
__builtin_unreachable();
#endif
for(int i = 0; i < g_numUsbChan_In; i++)
{
/* Receive sample */
int sample = inuint(c_mix_out);
#if (INPUT_VOLUME_CONTROL) && !defined(IN_VOLUME_IN_MIXER)
/* Apply volume */
int mult;
int h;
unsigned l;
asm volatile("ldw %0, %1[%2]":"=r"(mult):"r"(p_multIn),"r"(i));
{h, l} = macs(mult, sample, 0, 0);
sample = h << 3;
#endif
/* Pack 3 byte samples */
switch (packState&0x3)
{
case 0:
packData = sample;
break;
case 1:
packData = (packData >> 8) | ((sample & 0xff00)<<16);
write_via_xc_ptr(g_aud_to_host_dptr, packData);
g_aud_to_host_dptr+=4;
write_via_xc_ptr(g_aud_to_host_dptr, sample>>16);
packData = sample;
break;
case 2:
packData = (packData>>16) | ((sample & 0xffff00) << 8);
write_via_xc_ptr(g_aud_to_host_dptr, packData);
g_aud_to_host_dptr+=4;
packData = sample;
break;
case 3:
packData = (packData >> 24) | (sample & 0xffffff00);
write_via_xc_ptr(g_aud_to_host_dptr, packData);
g_aud_to_host_dptr+=4;
break;
}
packState++;
}
break;
default:
__builtin_unreachable();
break;
}
/* Input any remaining channels - past this thread we always operate on max channel count */
for(int i = 0; i < NUM_USB_CHAN_IN - g_numUsbChan_In; i++)
{
inuint(c_mix_out);
}
sampsToWrite--;
}
#else
if(outUnderflow)
{
#pragma xta endpoint "out_underflow"
@@ -443,6 +291,164 @@ __builtin_unreachable();
aud_data_remaining_to_device -= (g_numUsbChan_Out * g_curSubSlot_Out);
}
#endif
/* If in overflow condition then receive samples and throw away */
if(inOverflow || sampsToWrite == 0)
{
#pragma loop unroll
for(int i = 0; i < NUM_USB_CHAN_IN; i++)
{
(void) inuint(c_mix_out);
}
/* Calculate how much space left in buffer */
space_left = g_aud_to_host_rdptr - g_aud_to_host_wrptr;
if (space_left <= 0)
{
space_left += BUFF_SIZE_IN*4;
}
/* Check if we can come out of overflow */
if (space_left > (BUFF_SIZE_IN*4/2))
{
inOverflow = 0;
}
}
else
{
/* Not in overflow, store samples from mixer into sample buffer */
switch(g_curSubSlot_In)
{
case 2:
#if (STREAM_FORMAT_INPUT_SUBSLOT_2_USED == 0)
__builtin_unreachable();
#endif
for(int i = 0; i < g_numUsbChan_In; i++)
{
/* Receive sample */
int sample = inuint(c_mix_out);
#if (INPUT_VOLUME_CONTROL == 1)
#if !defined(IN_VOLUME_IN_MIXER)
/* Apply volume */
int mult;
int h;
unsigned l;
asm volatile("ldw %0, %1[%2]":"=r"(mult):"r"(p_multIn),"r"(i));
{h, l} = macs(mult, sample, 0, 0);
sample = h << 3;
/* Note, in 2 byte sub slot - ignore lower bits of macs */
#elif defined(IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX)
sample = sample << 3;
#endif
#endif
write_short_via_xc_ptr(g_aud_to_host_dptr, sample>>16);
g_aud_to_host_dptr+=2;
}
break;
case 4:
{
#if (STREAM_FORMAT_INPUT_SUBSLOT_4_USED == 0)
__builtin_unreachable();
#endif
unsigned ptr = g_aud_to_host_dptr;
for(int i = 0; i < g_numUsbChan_In; i++)
{
/* Receive sample */
int sample = inuint(c_mix_out);
#if(INPUT_VOLUME_CONTROL == 1)
#if !defined(IN_VOLUME_IN_MIXER)
/* Apply volume */
int mult;
int h;
unsigned l;
asm volatile("ldw %0, %1[%2]":"=r"(mult):"r"(p_multIn),"r"(i));
{h, l} = macs(mult, sample, 0, 0);
sample = h << 3;
#if (STREAM_FORMAT_INPUT_RESOLUTION_32BIT_USED == 1)
sample |= (l >> 29) & 0x7; // Note, this step is not required if we assume sample depth is 24 (rather than 32)
#endif
#elif defined(IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX)
sample = sample << 3;
#endif
#endif
/* Write into fifo */
write_via_xc_ptr(ptr, sample);
ptr+=4;
}
/* Update global pointer */
g_aud_to_host_dptr = ptr;
break;
}
case 3:
#if (STREAM_FORMAT_INPUT_SUBSLOT_3_USED == 0)
__builtin_unreachable();
#endif
for(int i = 0; i < g_numUsbChan_In; i++)
{
/* Receive sample */
int sample = inuint(c_mix_out);
#if (INPUT_VOLUME_CONTROL) && !defined(IN_VOLUME_IN_MIXER)
/* Apply volume */
int mult;
int h;
unsigned l;
asm volatile("ldw %0, %1[%2]":"=r"(mult):"r"(p_multIn),"r"(i));
{h, l} = macs(mult, sample, 0, 0);
sample = h << 3;
#endif
/* Pack 3 byte samples */
switch (packState&0x3)
{
case 0:
packData = sample;
break;
case 1:
packData = (packData >> 8) | ((sample & 0xff00)<<16);
write_via_xc_ptr(g_aud_to_host_dptr, packData);
g_aud_to_host_dptr+=4;
write_via_xc_ptr(g_aud_to_host_dptr, sample>>16);
packData = sample;
break;
case 2:
packData = (packData>>16) | ((sample & 0xffff00) << 8);
write_via_xc_ptr(g_aud_to_host_dptr, packData);
g_aud_to_host_dptr+=4;
packData = sample;
break;
case 3:
packData = (packData >> 24) | (sample & 0xffffff00);
write_via_xc_ptr(g_aud_to_host_dptr, packData);
g_aud_to_host_dptr+=4;
break;
}
packState++;
}
break;
default:
__builtin_unreachable();
break;
}
/* Input any remaining channels - past this thread we always operate on max channel count */
for(int i = 0; i < NUM_USB_CHAN_IN - g_numUsbChan_In; i++)
{
inuint(c_mix_out);
}
sampsToWrite--;
}
if (!inOverflow)
{
if (sampsToWrite == 0)

View File

@@ -21,7 +21,9 @@
void buffer(chanend c_aud_out,
chanend c_aud_in,
#if (NUM_USB_CHAN_IN == 0) || defined (UAC_FORCE_FEEDBACK_EP)
chanend c_aud_fb,
#endif
#ifdef MIDI
chanend c_midi_from_host,
chanend c_midi_to_host,

View File

@@ -94,7 +94,10 @@ unsigned char fb_clocks[16];
* @param c_aud_fb chanend for feeback to xud
* @return void
*/
void buffer(register chanend c_aud_out, register chanend c_aud_in, chanend c_aud_fb,
void buffer(register chanend c_aud_out, register chanend c_aud_in,
#if (NUM_USB_CHAN_IN == 0) || defined (UAC_FORCE_FEEDBACK_EP)
chanend c_aud_fb,
#endif
#ifdef MIDI
chanend c_midi_from_host,
chanend c_midi_to_host,
@@ -131,7 +134,9 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in, chanend c_aud
{
XUD_ep ep_aud_out = XUD_InitEp(c_aud_out);
XUD_ep ep_aud_in = XUD_InitEp(c_aud_in);
#if (NUM_USB_CHAN_IN == 0) || defined (UAC_FORCE_FEEDBACK_EP)
XUD_ep ep_aud_fb = XUD_InitEp(c_aud_fb);
#endif
#ifdef MIDI
XUD_ep ep_midi_from_host = XUD_InitEp(c_midi_from_host);
XUD_ep ep_midi_to_host = XUD_InitEp(c_midi_to_host);
@@ -348,6 +353,7 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in, chanend c_aud
SET_SHARED_GLOBAL(g_formatChange_DataFormat, formatChange_DataFormat);
SET_SHARED_GLOBAL(g_formatChange_SampRes, formatChange_SampRes);
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
/* Host is starting up the output stream. Setup (or potentially resize) feedback packet based on bus-speed
* This is only really important on inital start up (when bus-speed
was unknown) and when changing bus-speeds */
@@ -361,7 +367,7 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in, chanend c_aud
{
XUD_SetReady_In(ep_aud_fb, fb_clocks, 3);
}
#endif
}
/* Pass on sample freq change to decouple() via global flag (saves a chanend) */
/* Note: freqChange flags now used to communicate other commands also */
@@ -464,6 +470,7 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in, chanend c_aud
#endif
#if (NUM_USB_CHAN_OUT > 0)
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
/* Feedback Pipe */
case XUD_SetData_Select(c_aud_fb, ep_aud_fb, result):
{
@@ -481,7 +488,7 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in, chanend c_aud
}
}
break;
#endif
/* Received Audio packet HOST -> DEVICE. Datalength written to length */
case XUD_GetData_Select(c_aud_out, ep_aud_out, length, result):
{