diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e7dae4d2..3905a2b7 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,9 +1,29 @@ sc_usb_audio Change Log ======================= -6.7.0 +HEAD +---- + - CHANGE: Modifying mix map now only affects specified mix, previous was applied to all + mixes. CS_XU_MIXSEL control selector now takes values 0 to MAX_MIX_COUNT + 1 + (with 0 affecting all mixes). + +6.8.0 ----- + - ADDED: Evaluation support for iAP EA Native Transport endpoints + - RESOLVED: (Minor) Reverted change in 6.5.1 release where sample rate listing in Audio Class + 1.0 descriptors was trimmed (previously 4 rates were always reported). This change + appears to highlight a Windows (only) enumeration issue with the Input & Output + configs + - RESOLVED: (Major) Mixer functionality re-instated, including descriptors and various required + updates compatibility with 13 tools + - RESOLVED: (Major) Endpoint 0 was requesting an out of bounds channel whilst requesting level data + - RESOLVED: (Major) Fast mix code not operates correctly in 13 tools, assembler inserting long jmp + instructions + - RESOLVED: (Minor) LED level meter code now compatible with 13 tools (shared mem access) + - RESOLVED (Minor) Ordering of level data from the device now matches channel ordering into + mixer (previously the device input data and the stream from host were swapped) + - CHANGE: Level meter buffer naming now resemble functionality - * see sw_usb_audio for changelog - + +Please see changelog in sw_usb_audio for changes prior to 6.8.0 release. diff --git a/README.rst b/README.rst index 707f6941..b1c3de00 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,7 @@ USB Audio Shared ................ -:Latest release: 6.7.0alpha0 +:Latest release: 6.8.0alpha2 :Maintainer: xross :Description: USB Audio Shared Components. For use in the XMOS USB Audio Refererence Designs. diff --git a/module_usb_audio/clocking/clockgen.xc b/module_usb_audio/clocking/clockgen.xc index d2b430eb..4046e328 100644 --- a/module_usb_audio/clocking/clockgen.xc +++ b/module_usb_audio/clocking/clockgen.xc @@ -194,7 +194,7 @@ static inline int badParity(unsigned x) void VendorLedRefresh(unsigned levelData[]); unsigned g_inputLevelData[NUM_USB_CHAN_IN]; extern int samples_to_host_inputs[NUM_USB_CHAN_IN]; -extern int samples_to_host_inputs_buff[NUM_USB_CHAN_IN]; /* Audio transmitted to host i.e. dev inputs */ +extern int samples_to_host_inputs_buff[NUM_USB_CHAN_IN]; #endif int VendorAudCoreReqs(unsigned cmd, chanend c); @@ -326,17 +326,24 @@ void clockGen (streaming chanend c_spdif_rx, chanend ?c_adat_rx, out port p, cha for(int i = 0; i< NUM_USB_CHAN_IN; i++) { int tmp; + + /* Read level data */ //g_inputLevelData[i] = samples_to_host_inputs[i]; - asm("ldw %0, %1[%2]":"=r"(tmp):"r"(samples_to_host_inputs),"r"(i)); + asm volatile("ldw %0, %1[%2]":"=r"(tmp):"r"((const int *)samples_to_host_inputs),"r"(i)); g_inputLevelData[i] = tmp; + /* Reset level data */ //samples_to_host_inputs[i] = 0; - asm("stw %0, %1[%2]"::"r"(0),"r"(samples_to_host_inputs),"r"(i)); + asm volatile("stw %0, %1[%2]"::"r"(0),"r"((const int *)samples_to_host_inputs),"r"(i)); /* Guard against host polling slower than timer and missing peaks */ - if(g_inputLevelData[i] > samples_to_host_inputs_buff[i]) + asm volatile("ldw %0, %1[%2]":"=r"(tmp):"r"((const int *)samples_to_host_inputs_buff),"r"(i)); + + if (g_inputLevelData[i] > tmp) + //if(g_inputLevelData[i] > samples_to_host_inputs_buff[i]) { - samples_to_host_inputs_buff[i] = g_inputLevelData[i]; + //samples_to_host_inputs_buff[i] = g_inputLevelData[i]; + asm volatile("stw %0, %1[%2]"::"r"(tmp),"r"((const int *)samples_to_host_inputs),"r"(i)); } } diff --git a/module_usb_audio/devicedefines.h b/module_usb_audio/devicedefines.h index 079ffbd8..ab7d95a9 100644 --- a/module_usb_audio/devicedefines.h +++ b/module_usb_audio/devicedefines.h @@ -390,7 +390,7 @@ * @brief Device firmware version number in Binary Coded Decimal format: 0xJJMN where JJ: major, M: minor, N: sub-minor version number. */ #ifndef BCD_DEVICE_M -#define BCD_DEVICE_M 7 +#define BCD_DEVICE_M 8 #endif /** @@ -930,6 +930,27 @@ #undef IAP_INT_EP #endif +/* IAP EA Native Transport */ +#if defined(IAP_EA_NATIVE_TRANS) && (IAP_EA_NATIVE_TRANS == 0) +#undef IAP_EA_NATIVE_TRANS +#endif + +#if defined(IAP_EA_NATIVE_TRANS) || defined(__DOXYGEN__) +/** + * @brief Number of supported EA Native Interface Alternative settings. + * + * Only 1 supported + */ +#ifndef IAP_EA_NATIVE_TRANS_ALT_COUNT + #define IAP_EA_NATIVE_TRANS_ALT_COUNT 1 +#endif + +#if (IAP_EA_NATIVE_TRANS_ALT_COUNT > 1) + /* Only 1 supported */ + #error +#endif +#endif + /* Endpoint addresses enums */ enum USBEndpointNumber_In { @@ -950,6 +971,9 @@ enum USBEndpointNumber_In ENDPOINT_NUMBER_IN_IAP_INT, #endif ENDPOINT_NUMBER_IN_IAP, +#ifdef IAP_EA_NATIVE_TRANS + ENDPOINT_NUMBER_IN_IAP_EA_NATIVE_TRANS, +#endif #endif ENDPOINT_COUNT_IN /* End marker */ }; @@ -963,6 +987,9 @@ enum USBEndpointNumber_Out #endif #ifdef IAP ENDPOINT_NUMBER_OUT_IAP, +#ifdef IAP_EA_NATIVE_TRANS + ENDPOINT_NUMBER_OUT_IAP_EA_NATIVE_TRANS, +#endif #endif ENDPOINT_COUNT_OUT /* End marker */ }; diff --git a/module_usb_audio/endpoint0/audiorequests.xc b/module_usb_audio/endpoint0/audiorequests.xc index 6accd883..087bf8d7 100644 --- a/module_usb_audio/endpoint0/audiorequests.xc +++ b/module_usb_audio/endpoint0/audiorequests.xc @@ -36,15 +36,11 @@ extern unsigned char mixer1Crossbar[]; extern short mixer1Weights[]; /* Device channel mapping */ -#if NUM_USB_CHAN_OUT > 0 extern unsigned char channelMapAud[NUM_USB_CHAN_OUT]; -#endif -#if NUM_USB_CHAN_IN > 0 extern unsigned char channelMapUsb[NUM_USB_CHAN_IN]; -#endif /* Mixer input mapping */ -extern unsigned char mixSel[MIX_INPUTS]; +extern unsigned char mixSel[MAX_MIX_COUNT][MIX_INPUTS]; #endif /* Global var for current frequency, set to default freq */ @@ -605,10 +601,11 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c unsigned volume = 0; int c = sp.wValue & 0xff; - loop = XUD_GetBuffer(ep0_out, buffer); - if(loop < 0) - return loop; + if((result = XUD_GetBuffer(ep0_out, buffer, datalength)) != XUD_RES_OKAY) + { + return result; + } channelMapAud[c] = buffer[0] | buffer[1] << 8; @@ -643,10 +640,10 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c unsigned volume = 0; int c = sp.wValue & 0xff; - loop = XUD_GetBuffer(ep0_out, buffer); - - if(loop < 0) - return loop; + if((result = XUD_GetBuffer(ep0_out, buffer, datalength)) != XUD_RES_OKAY) + { + return result; + } channelMapUsb[c] = buffer[0] | buffer[1] << 8; @@ -677,37 +674,55 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c int cn = sp.wValue & 0xff; /* Channel number */ /* Check for Get or Set */ - if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_OUT) + if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D) { /* Direction: Host-to-device */ /* Host-to-device */ - datalength = XUD_GetBuffer(ep0_out, buffer); - - /* Check for reset */ - if(datalength < 0) - return datalength; + if((result = XUD_GetBuffer(ep0_out, buffer, datalength)) != XUD_RES_OKAY) + { + return result; + } if(datalength > 0) { /* cn bounds check for safety..*/ if(cn < MIX_INPUTS) { - if(cs == CS_XU_MIXSEL) + //if(cs == CS_XU_MIXSEL) + /* cs now contains mix number */ + if(cs < (MAX_MIX_COUNT + 1)) { /* Check for "off" - update local state */ if(buffer[0] == 0xFF) - mixSel[cn] = (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT); - else - mixSel[cn] = buffer[0]; - - /* Update all mix maps */ - for (int i = 0; i < MAX_MIX_COUNT; i++) { - outuint(c_mix_ctl, SET_MIX_MAP); - outuint(c_mix_ctl, i); /* Mix bus */ - outuint(c_mix_ctl, cn); /* Mixer input */ - outuint(c_mix_ctl, (int) mixSel[cn]); /* Source */ - outct(c_mix_ctl, XS1_CT_END); + mixSel[cs][cn] = (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT); } + else + { + mixSel[cs][cn] = buffer[0]; + } + + if(cs == 0) + { + /* Update all mix maps */ + for (int i = 0; i < MAX_MIX_COUNT; i++) + { + outuint(c_mix_ctl, SET_MIX_MAP); + outuint(c_mix_ctl, i); /* Mix bus */ + outuint(c_mix_ctl, cn); /* Mixer input */ + outuint(c_mix_ctl, (int) mixSel[cn]); /* Source */ + outct(c_mix_ctl, XS1_CT_END); + } + } + else + { + /* Update relevant mix map */ + outuint(c_mix_ctl, SET_MIX_MAP); /* Command */ + outuint(c_mix_ctl, (cs-1)); /* Mix bus */ + outuint(c_mix_ctl, cn); /* Mixer input */ + outuint(c_mix_ctl, (int) mixSel[cs][cn]); /* Source */ + outct(c_mix_ctl, XS1_CT_END); /* Wait for handshake back */ + } + return XUD_DoSetRequestStatus(ep0_in); } } @@ -722,9 +737,10 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c if(cn < MIX_INPUTS) { /* Inspect control selector */ - if(cs == CS_XU_MIXSEL) + /* TODO ideally have a return for cs = 0. I.e all mix maps */ + if((cs > 0) && (cs < (MAX_MIX_COUNT+1))) { - buffer[0] = mixSel[cn]; + buffer[0] = mixSel[cs-1][cn]; return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, 1 ); } } @@ -734,14 +750,15 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c case ID_MIXER_1: - if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_OUT) /* Direction: Host-to-device */ + if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D) /* Direction: Host-to-device */ { unsigned volume = 0; /* Expect OUT here with mute */ - loop = XUD_GetBuffer(ep0_out, buffer); - if(loop < 0) - return loop; + if((result = XUD_GetBuffer(ep0_out, buffer, datalength)) != XUD_RES_OKAY) + { + return result; + } mixer1Weights[sp.wValue & 0xff] = buffer[0] | buffer[1] << 8; @@ -906,7 +923,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c { case ID_MIXER_1: - if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_IN) + if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_D2H) { int length = 0; @@ -919,14 +936,14 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c for(int i = 0; i < (NUM_USB_CHAN_IN + NUM_USB_CHAN_OUT); i++) { /* Get the level and truncate to 16-bit */ - if(i < NUM_USB_CHAN_IN) + if(i < NUM_USB_CHAN_OUT) { if (!isnull(c_mix_ctl)) { - outuint(c_mix_ctl, GET_INPUT_LEVELS); - outuint(c_mix_ctl, (i - NUM_USB_CHAN_IN)); + outuint(c_mix_ctl, GET_STREAM_LEVELS); + outuint(c_mix_ctl, i); outct(c_mix_ctl, XS1_CT_END); - storeShort(buffer, i*2, (inuint(c_mix_ctl)>>15)); + storeShort(buffer, i*2, (inuint(c_mix_ctl) >> 15)); chkct(c_mix_ctl, XS1_CT_END); } else @@ -938,8 +955,8 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c { if (!isnull(c_mix_ctl)) { - outuint(c_mix_ctl, GET_STREAM_LEVELS); - outuint(c_mix_ctl, (i - NUM_USB_CHAN_IN)); + outuint(c_mix_ctl, GET_INPUT_LEVELS); + outuint(c_mix_ctl, (i - NUM_USB_CHAN_OUT)); outct(c_mix_ctl, XS1_CT_END); storeShort(buffer, i*2, (inuint(c_mix_ctl) >> 15)); chkct(c_mix_ctl, XS1_CT_END); diff --git a/module_usb_audio/endpoint0/descriptors.h b/module_usb_audio/endpoint0/descriptors.h index ab8648dd..dd5b38bd 100644 --- a/module_usb_audio/endpoint0/descriptors.h +++ b/module_usb_audio/endpoint0/descriptors.h @@ -12,6 +12,19 @@ #include "usbaudiocommon.h" #include "usb_std_descriptors.h" +#ifdef IAP_EA_NATIVE_TRANS +/* + * FIXME currently this will not build if IAP_EA_NATIVE_TRANS_PROTOCOL_NAME is not defined in iap_conf.h, + * would be nice if a default string was used instead, and a warning issued. + * + * Could get a default define by including the following line, but iap2.h cannot currently be included from C + */ +//#include "iap2.h" /* Defines iAP EA Native Transport protocol name */ +#ifdef __iap_conf_h_exists__ +#include "iap_conf.h" +#endif +#endif + #define APPEND_VENDOR_STR(x) VENDOR_STR" "#x #define APPEND_PRODUCT_STR_A2(x) PRODUCT_STR_A2 " "#x @@ -170,8 +183,36 @@ typedef struct #endif #if (NUM_USB_CHAN_IN > 18) #error NUM_USB_CHAN > 18 +#endif + +#if defined(MIXER) && (MAX_MIX_COUNT > 0) + STR_TABLE_ENTRY(mixOutStr_1); +#endif +#if defined(MIXER) && (MAX_MIX_COUNT > 1) + STR_TABLE_ENTRY(mixOutStr_2); +#endif +#if defined(MIXER) && (MAX_MIX_COUNT > 2) + STR_TABLE_ENTRY(mixOutStr_3); +#endif +#if defined(MIXER) && (MAX_MIX_COUNT > 3) + STR_TABLE_ENTRY(mixOutStr_4); +#endif +#if defined(MIXER) && (MAX_MIX_COUNT > 4) + STR_TABLE_ENTRY(mixOutStr_5); +#endif +#if defined(MIXER) && (MAX_MIX_COUNT > 5) + STR_TABLE_ENTRY(mixOutStr_6); +#endif +#if defined(MIXER) && (MAX_MIX_COUNT > 6) + STR_TABLE_ENTRY(mixOutStr_7); +#endif +#if defined(MIXER) && (MAX_MIX_COUNT > 7) + STR_TABLE_ENTRY(mixOutStr_8); #endif STR_TABLE_ENTRY(iAPInterfaceStr); +#ifdef IAP_EA_NATIVE_TRANS + STR_TABLE_ENTRY(iAP_EANativeTransport_InterfaceStr); +#endif } StringDescTable_t; StringDescTable_t g_strTable = @@ -180,17 +221,17 @@ StringDescTable_t g_strTable = .vendorStr = VENDOR_STR, .serialStr = "", .productStr_Audio2 = PRODUCT_STR_A2, - .outputInterfaceStr_Audio2 = APPEND_PRODUCT_STR_A2(Output), - .inputInterfaceStr_Audio2 = APPEND_PRODUCT_STR_A2(Input), - .usbInputTermStr_Audio2 = APPEND_PRODUCT_STR_A2(Output), - .usbOutputTermStr_Audio2 = APPEND_PRODUCT_STR_A2(Input), + .outputInterfaceStr_Audio2 = APPEND_PRODUCT_STR_A2(), + .inputInterfaceStr_Audio2 = APPEND_PRODUCT_STR_A2(), + .usbInputTermStr_Audio2 = APPEND_PRODUCT_STR_A2(), + .usbOutputTermStr_Audio2 = APPEND_PRODUCT_STR_A2(), #if defined (AUDIO_CLASS_FALLBACK) || (AUDIO_CLASS == 1) .productStr_Audio1 = PRODUCT_STR_A1, - .outputInterfaceStr_Audio1 = APPEND_PRODUCT_STR_A1(Output), - .inputInterfaceStr_Audio1 = APPEND_PRODUCT_STR_A1(Input), - .usbInputTermStr_Audio1 = APPEND_PRODUCT_STR_A1(Output), - .usbOutputTermStr_Audio1 = APPEND_PRODUCT_STR_A1(Input), + .outputInterfaceStr_Audio1 = APPEND_PRODUCT_STR_A1(), + .inputInterfaceStr_Audio1 = APPEND_PRODUCT_STR_A1(), + .usbInputTermStr_Audio1 = APPEND_PRODUCT_STR_A1(), + .usbOutputTermStr_Audio1 = APPEND_PRODUCT_STR_A1(), #endif .clockSelectorStr = APPEND_VENDOR_STR(Clock Selector), .internalClockSourceStr = APPEND_VENDOR_STR(Internal Clock), @@ -851,8 +892,37 @@ StringDescTable_t g_strTable = #error NUM_USB_CHAN_IN > 18 #endif +#if defined(MIXER) && (MAX_MIX_COUNT > 0) + .mixOutStr_1 = "Mix 1", +#endif +#if defined(MIXER) && (MAX_MIX_COUNT > 0) + .mixOutStr_2 = "Mix 2", +#endif +#if defined(MIXER) && (MAX_MIX_COUNT > 0) + .mixOutStr_3 = "Mix 3", +#endif +#if defined(MIXER) && (MAX_MIX_COUNT > 0) + .mixOutStr_4 = "Mix 4", +#endif +#if defined(MIXER) && (MAX_MIX_COUNT > 0) + .mixOutStr_5 = "Mix 5", +#endif +#if defined(MIXER) && (MAX_MIX_COUNT > 0) + .mixOutStr_6 = "Mix 6", +#endif +#if defined(MIXER) && (MAX_MIX_COUNT > 0) + .mixOutStr_7 = "Mix 7", +#endif +#if defined(MIXER) && (MAX_MIX_COUNT > 0) + .mixOutStr_8 = "Mix 8", +#endif +#if defined(MIXER) && (MAX_MIX_COUNT > 8) +#error +#endif .iAPInterfaceStr = "iAP Interface", - +#ifdef IAP_EA_NATIVE_TRANS + .iAP_EANativeTransport_InterfaceStr = IAP2_EA_NATIVE_TRANS_PROTOCOL_NAME, +#endif }; /* Interface numbers enum */ @@ -862,7 +932,7 @@ enum USBInterfaceNumber #if (NUM_USB_CHAN_OUT > 0) INTERFACE_NUMBER_AUDIO_OUTPUT, #endif -#if (NUM_USB_CHAN_IN > 0) +#if (NUM_USB_CHAN_IN > 0) INTERFACE_NUMBER_AUDIO_INPUT, #endif #if defined(MIDI) && (MIDI != 0) @@ -874,6 +944,9 @@ enum USBInterfaceNumber #endif #if defined(IAP) && (IAP != 0) INTERFACE_NUMBER_IAP, +#if defined(IAP_EA_NATIVE_TRANS) && (IAP_EA_NATIVE_TRANS != 0) + INTERFACE_NUMBER_IAP_EA_NATIVE_TRANS, +#endif #endif #if defined(HID_CONTROLS) && (HID_CONTROLS != 0) INTERFACE_NUMBER_HID, @@ -890,19 +963,21 @@ enum USBInterfaceNumber #endif /* Endpoint address defines */ -#define ENDPOINT_ADDRESS_IN_CONTROL (ENDPOINT_NUMBER_IN_CONTROL | 0x80) -#define ENDPOINT_ADDRESS_IN_FEEDBACK (ENDPOINT_NUMBER_IN_FEEDBACK | 0x80) -#define ENDPOINT_ADDRESS_IN_AUDIO (ENDPOINT_NUMBER_IN_AUDIO | 0x80) -#define ENDPOINT_ADDRESS_IN_INTERRUPT (ENDPOINT_NUMBER_IN_INTERRUPT | 0x80) -#define ENDPOINT_ADDRESS_IN_MIDI (ENDPOINT_NUMBER_IN_MIDI | 0x80) -#define ENDPOINT_ADDRESS_IN_HID (ENDPOINT_NUMBER_IN_HID | 0x80) -#define ENDPOINT_ADDRESS_IN_IAP_INT (ENDPOINT_NUMBER_IN_IAP_INT | 0x80) -#define ENDPOINT_ADDRESS_IN_IAP (ENDPOINT_NUMBER_IN_IAP | 0x80) +#define ENDPOINT_ADDRESS_IN_CONTROL (ENDPOINT_NUMBER_IN_CONTROL | 0x80) +#define ENDPOINT_ADDRESS_IN_FEEDBACK (ENDPOINT_NUMBER_IN_FEEDBACK | 0x80) +#define ENDPOINT_ADDRESS_IN_AUDIO (ENDPOINT_NUMBER_IN_AUDIO | 0x80) +#define ENDPOINT_ADDRESS_IN_INTERRUPT (ENDPOINT_NUMBER_IN_INTERRUPT | 0x80) +#define ENDPOINT_ADDRESS_IN_MIDI (ENDPOINT_NUMBER_IN_MIDI | 0x80) +#define ENDPOINT_ADDRESS_IN_HID (ENDPOINT_NUMBER_IN_HID | 0x80) +#define ENDPOINT_ADDRESS_IN_IAP_INT (ENDPOINT_NUMBER_IN_IAP_INT | 0x80) +#define ENDPOINT_ADDRESS_IN_IAP (ENDPOINT_NUMBER_IN_IAP | 0x80) +#define ENDPOINT_ADDRESS_IN_IAP_EA_NATIVE_TRANS (ENDPOINT_NUMBER_IN_IAP_EA_NATIVE_TRANS | 0x80) -#define ENDPOINT_ADDRESS_OUT_CONTROL (ENDPOINT_NUMBER_OUT_CONTROL) -#define ENDPOINT_ADDRESS_OUT_AUDIO (ENDPOINT_NUMBER_OUT_AUDIO) -#define ENDPOINT_ADDRESS_OUT_MIDI (ENDPOINT_NUMBER_OUT_MIDI) -#define ENDPOINT_ADDRESS_OUT_IAP (ENDPOINT_NUMBER_OUT_IAP) +#define ENDPOINT_ADDRESS_OUT_CONTROL (ENDPOINT_NUMBER_OUT_CONTROL) +#define ENDPOINT_ADDRESS_OUT_AUDIO (ENDPOINT_NUMBER_OUT_AUDIO) +#define ENDPOINT_ADDRESS_OUT_MIDI (ENDPOINT_NUMBER_OUT_MIDI) +#define ENDPOINT_ADDRESS_OUT_IAP (ENDPOINT_NUMBER_OUT_IAP) +#define ENDPOINT_ADDRESS_OUT_IAP_EA_NATIVE_TRANS (ENDPOINT_NUMBER_OUT_IAP_EA_NATIVE_TRANS) /***** Device Descriptors *****/ @@ -1021,7 +1096,7 @@ unsigned char devQualDesc_Null[] = #if defined(MIXER) && !defined(AUDIO_PATH_XUS) && (MAX_MIX_COUNT > 0) -#warning Extention units on the audio path are required for mixer. Enabling them now. +//#warning Extension units on the audio path are required for mixer. Enabling them now. #define AUDIO_PATH_XUS #endif @@ -1037,6 +1112,18 @@ unsigned char devQualDesc_Null[] = #define DFU_LENGTH (0) #endif +#ifdef MIXER + #define MIX_BMCONTROLS_LEN_TMP ((MAX_MIX_COUNT * MIX_INPUTS) / 8) + + #if ((MAX_MIX_COUNT * MIX_INPUTS)%8)==0 + #define MIX_BMCONTROLS_LEN (MIX_BMCONTROLS_LEN_TMP) + #else + #define MIX_BMCONTROLS_LEN (MIX_BMCONTROLS_LEN_TMP+1) + #endif + #define MIXER_LENGTH (13+1+MIX_BMCONTROLS_LEN) +#else + #define MIXER_LENGTH (0) +#endif #ifdef HID_CONTROLS @@ -1106,6 +1193,9 @@ typedef struct #if (NUM_USB_CHAN_OUT > 0) /* Output path */ USB_Descriptor_Audio_InputTerminal_t Audio_Out_InputTerminal; +#if defined(MIXER) && (MAX_MIX_COUNT > 0) + USB_Descriptor_Audio_ExtensionUnit_t Audio_Out_ExtensionUnit; +#endif #if(OUTPUT_VOLUME_CONTROL == 1) USB_Descriptor_Audio_FeatureUnit_Out_t Audio_Out_FeatureUnit; #endif @@ -1114,12 +1204,22 @@ typedef struct #if (NUM_USB_CHAN_IN > 0) /* Input path */ USB_Descriptor_Audio_InputTerminal_t Audio_In_InputTerminal; +#if defined(MIXER) && (MAX_MIX_COUNT > 0) + USB_Descriptor_Audio_ExtensionUnit_t Audio_In_ExtensionUnit; +#endif #if(INPUT_VOLUME_CONTROL == 1) USB_Descriptor_Audio_FeatureUnit_In_t Audio_In_FeatureUnit; #endif USB_Descriptor_Audio_OutputTerminal_t Audio_In_OutputTerminal; #endif +#if defined(MIXER) && (MAX_MIX_COUNT > 0) + USB_Descriptor_Audio_ExtensionUnit2_t Audio_Mix_ExtensionUnit; + // Currently no struct for mixer unit + // USB_Descriptor_Audio_MixerUnit_t Audio_MixerUnit; + unsigned char configDesc_MixerUnit[MIXER_LENGTH]; +#endif #if defined (SPDIF_RX) || defined (ADAT_RX) + /* Interrupt EP */ USB_Descriptor_Endpoint_t Audio_Int_Endpoint; #endif } __attribute__((packed)) USB_CfgDesc_Audio2_CS_Control_Int; @@ -1187,6 +1287,12 @@ typedef struct #ifdef IAP_INT_EP USB_Descriptor_Endpoint_t iAP_Interrupt_Endpoint; #endif +#ifdef IAP_EA_NATIVE_TRANS + USB_Descriptor_Interface_t iAP_EANativeTransport_Interface_Alt0; + USB_Descriptor_Interface_t iAP_EANativeTransport_Interface_Alt1; + USB_Descriptor_Endpoint_t iAP_EANativeTransport_Out_Endpoint; + USB_Descriptor_Endpoint_t iAP_EANativeTransport_In_Endpoint; +#endif #endif #ifdef HID_CONTROLS @@ -1369,6 +1475,23 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2= .iTerminal = offsetof(StringDescTable_t, usbInputTermStr_Audio2)/sizeof(char *) }, +#if defined (MIXER) && (MAX_MIX_COUNT > 0) + .Audio_Out_ExtensionUnit = + { + .bLength = sizeof(USB_Descriptor_Audio_ExtensionUnit_t), + .bDescriptorType = UAC_CS_DESCTYPE_INTERFACE, + .bDescriptorSubtype = UAC_CS_AC_INTERFACE_SUBTYPE_EXTENSION_UNIT, + .bUnitID = ID_XU_OUT, + .wExtensionCode = 0x00, + .bNrInPins = 1, + .baSourceID[0] = ID_IT_USB, + .bNrChannels = NUM_USB_CHAN_OUT, + .bmChannelConfig = 0x00000000, + .bmControls = 0x03, + .iExtension = 0 + }, +#endif + #if(OUTPUT_VOLUME_CONTROL == 1) /* Feature Unit Descriptor */ .Audio_Out_FeatureUnit = @@ -1377,7 +1500,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2= 0x24, /* 1 bDescriptorType: CS_INTERFACE */ 0x06, /* 2 bDescriptorSubType: FEATURE_UNIT */ FU_USBOUT, /* 3 bUnitID */ -#ifdef AUDIO_PATH_XUS +#if defined (MIXER) && (MAX_MIX_COUNT > 0) ID_XU_OUT, /* 4 bSourceID */ #else ID_IT_USB, /* 4 bSourceID */ @@ -1465,6 +1588,9 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2= 0, /* 11 iTerminal */ }, #endif + + + #if (NUM_USB_CHAN_IN > 0) /* Input Terminal Descriptor (Analogue Input Terminal) */ .Audio_In_InputTerminal = @@ -1483,6 +1609,23 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2= .iTerminal = 0, }, +#if defined (MIXER) && (MAX_MIX_COUNT > 0) + .Audio_In_ExtensionUnit = + { + .bLength = sizeof(USB_Descriptor_Audio_ExtensionUnit_t), + .bDescriptorType = UAC_CS_DESCTYPE_INTERFACE, + .bDescriptorSubtype = UAC_CS_AC_INTERFACE_SUBTYPE_EXTENSION_UNIT, + .bUnitID = ID_XU_IN, + .wExtensionCode = 0x00, + .bNrInPins = 1, + .baSourceID[0] = ID_IT_AUD, + .bNrChannels = NUM_USB_CHAN_IN, + .bmChannelConfig = 0x00000000, + .bmControls = 0x03, + .iExtension = 0 + }, +#endif + #if (INPUT_VOLUME_CONTROL == 1) .Audio_In_FeatureUnit = { @@ -1490,7 +1633,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2= UAC_CS_DESCTYPE_INTERFACE, /* 1 bDescriptorType: CS_INTERFACE */ UAC_CS_AC_INTERFACE_SUBTYPE_FEATURE_UNIT, /* 2 bDescriptorSubType: FEATURE_UNIT */ FU_USBIN, /* 3 bUnitID */ -#ifdef AUDIO_PATH_XUS +#if defined(MIXER) && (MAX_MIX_COUNT > 0) ID_XU_IN, /* 4 bSourceID */ #else ID_IT_AUD, /* 4 bSourceID */ @@ -1580,6 +1723,100 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2= }, #endif +#if defined(MIXER) && (MAX_MIX_COUNT > 0) + /* Extension Unit Descriptor (4.7.2.12) */ + .Audio_Mix_ExtensionUnit = + { + .bLength = sizeof(USB_Descriptor_Audio_ExtensionUnit2_t), + .bDescriptorType = UAC_CS_DESCTYPE_INTERFACE, + .bDescriptorSubtype = UAC_CS_AC_INTERFACE_SUBTYPE_EXTENSION_UNIT, + .bUnitID = ID_XU_MIXSEL, + .wExtensionCode = 0x00, + .bNrInPins = 2, + .baSourceID[0] = ID_IT_USB, + .baSourceID[1] = ID_IT_AUD, + .bNrChannels = MIX_INPUTS, + .bmChannelConfig = 0x00000000, + .bmControls = 0x03, + .iExtension = 0 + }, + + /* Mixer Unit Descriptors */ + /* N = 144 (18 * 8) */ + /* Mixer Unit Bitmap - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff */ + { + MIXER_LENGTH, /* 0 bLength : 13 + num inputs + bit map (inputs * outputs) */ + UAC_CS_DESCTYPE_INTERFACE, /* bDescriptorType */ + 0x04, /* bDescriptorSubtype: MIXER_UNIT */ + ID_MIXER_1, /* Mixer unit id */ + 0x01, /* Number of input pins */ + ID_XU_MIXSEL, /* Connected terminal or unit id for input pin */ + MAX_MIX_COUNT, /* Number of mixer output channels */ + 0x00, 0x00, 0x00, 0x00, /* Spacial location ???? */ + offsetof(StringDescTable_t, mixOutStr_1)/sizeof(char *), /* iChannelNames */ +#if MIX_BMCONTROLS_LEN > 0 /* Mixer programmable control bitmap */ + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 1 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 2 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 3 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 4 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 5 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 6 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 7 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 8 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 9 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 10 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 11 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 12 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 13 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 14 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 15 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 16 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 17 + 0xff, +#endif +#if MIX_BMCONTROLS_LEN > 18 +#error unxpected BMCONTROLS_LEN +#endif + 0x00, /* bmControls */ + 0 /* Mixer unit string descriptor index */ + }, +#endif + #if defined(SPDIF_RX) || defined(ADAT_RX) /* Standard AS Interrupt Endpoint Descriptor (4.8.2.1): */ .Audio_Int_Endpoint = @@ -2120,6 +2357,58 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2= 0x08, /* 6 bInterval : (2^(bInterval-1))/8 ms. Must be between 4 and 32ms (field size 1 bytes) */ }, #endif +#ifdef IAP_EA_NATIVE_TRANS + /* iAP EA Native Transport Interface descriptor */ + /* Zero bandwidth alternative 0 */ + .iAP_EANativeTransport_Interface_Alt0 = + { + .bLength = sizeof(USB_Descriptor_Interface_t), + .bDescriptorType = USB_DESCTYPE_INTERFACE, + .bInterfaceNumber = INTERFACE_NUMBER_IAP_EA_NATIVE_TRANS, + .bAlternateSetting = 0x00, + .bNumEndpoints = 0x00, + .bInterfaceClass = USB_CLASS_VENDOR_SPECIFIC, + .bInterfaceSubClass = 0xF0, /* MFI Accessory (Table 21-2) */ + .bInterfaceProtocol = 0x01, + .iInterface = offsetof(StringDescTable_t, iAP_EANativeTransport_InterfaceStr)/sizeof(char *), + }, + + /* Alternative 1 */ + .iAP_EANativeTransport_Interface_Alt1 = + { + .bLength = sizeof(USB_Descriptor_Interface_t), + .bDescriptorType = USB_DESCTYPE_INTERFACE, + .bInterfaceNumber = INTERFACE_NUMBER_IAP_EA_NATIVE_TRANS, + .bAlternateSetting = 0x01, + .bNumEndpoints = 0x02, + .bInterfaceClass = USB_CLASS_VENDOR_SPECIFIC, + .bInterfaceSubClass = 0xF0, /* MFI Accessory (Table 21-1) */ + .bInterfaceProtocol = 0x01, + .iInterface = offsetof(StringDescTable_t, iAP_EANativeTransport_InterfaceStr)/sizeof(char *), + }, + + /* iAP EA Native Transport Bulk OUT Endpoint Descriptor */ + .iAP_EANativeTransport_Out_Endpoint = + { + 0x07, /* 0 bLength : Size of this descriptor, in bytes. (field size 1 bytes) */ + 0x05, /* 1 bDescriptorType : ENDPOINT descriptor. (field size 1 bytes) */ + ENDPOINT_ADDRESS_OUT_IAP_EA_NATIVE_TRANS, /* 2 bEndpointAddress : OUT Endpoint 3. High bit isIn (field size 1 bytes) */ + 0x02, /* 3 bmAttributes : Bulk, not shared. (field size 1 bytes) */ + 0x0200, /* 4 wMaxPacketSize : Has to be 0x200 for compliance*/ + 0x00, /* 6 bInterval : Ignored for Bulk. Set to zero. (field size 1 bytes) */ + }, + + /* iAP EA Native Transport Bulk IN Endpoint Descriptor */ + .iAP_EANativeTransport_In_Endpoint = + { + 0x07, /* 0 bLength : Size of this descriptor, in bytes. (field size 1 bytes) */ + 0x05, /* 1 bDescriptorType : ENDPOINT descriptor. (field size 1 bytes) */ + ENDPOINT_ADDRESS_IN_IAP_EA_NATIVE_TRANS, /* 2 bEndpointAddress : OUT Endpoint 3. High bit isIn (field size 1 bytes) */ + 0x02, /* 3 bmAttributes : Bulk, not shared. (field size 1 bytes) */ + 0x0200, /* 4 wMaxPacketSize : Has to be 0x200 for compliance*/ + 0x00, /* 6 bInterval : Ignored for Bulk. Set to zero. (field size 1 bytes) */ + }, +#endif #endif /* IAP */ #ifdef HID_CONTROLS @@ -2236,17 +2525,8 @@ unsigned char cfgDesc_Null[] = #define CFG_TOTAL_LENGTH_A1 (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES_A1 * 61) + (OUTPUT_INTERFACES_A1 * 70)) /* In UAC1 supported sample rates are listed in descriptor */ -#if (MAX_FREQ_FS == 96000) +/* Note, we always report 4 freqs, doing otherwise seems to cause an enumeration issue on Windows */ #define NUM_FREQS_A1 (4) -#elif (MAX_FREQ_FS == 88200) -#define NUM_FREQS_A1 (3) -#elif (MAX_FREQ_FS == 48000) -#define NUM_FREQS_A1 (2) -#elif (MAX_FREQ_FS == 44100) -#define NUM_FREQS_A1 (1) -#else -#error -#endif unsigned char cfgDesc_Audio1[] = { @@ -2407,12 +2687,18 @@ unsigned char cfgDesc_Audio1[] = 0x44, 0xAC, 0x00, /* sampleFreq - 44.1Khz */ #if (MAX_FREQ_FS > 44100) 0x80, 0xBB, 0x00, /* sampleFreq - 48KHz */ +#else + 0x44, 0xAC, 0x00, /* sampleFreq - 44.1Khz */ #endif #if (MAX_FREQ_FS > 48000) 0x88, 0x58, 0x01, /* sampleFreq - 88.2KHz */ +#else + 0x44, 0xAC, 0x00, /* sampleFreq - 44.1Khz */ #endif #if (MAX_FREQ_FS > 88200) 0x00, 0x77, 0x01, /* sampleFreq - 96KHz */ +#else + 0x44, 0xAC, 0x00, /* sampleFreq - 44.1Khz */ #endif /* Standard AS Isochronous Audio Data Endpoint Descriptor 4.6.1.1 */ @@ -2488,12 +2774,18 @@ unsigned char cfgDesc_Audio1[] = 0x44, 0xAC, 0x00, /* sampleFreq - 44.1Khz */ #if (MAX_FREQ_FS > 44100) 0x80, 0xBB, 0x00, /* sampleFreq - 48KHz */ +#else + 0x44, 0xAC, 0x00, /* sampleFreq - 44.1Khz */ #endif #if (MAX_FREQ_FS > 48000) 0x88, 0x58, 0x01, /* sampleFreq - 88.2KHz */ +#else + 0x44, 0xAC, 0x00, /* sampleFreq - 44.1Khz */ #endif #if (MAX_FREQ_FS > 88200) 0x00, 0x77, 0x01, /* sampleFreq - 96KHz */ +#else + 0x44, 0xAC, 0x00, /* sampleFreq - 44.1Khz */ #endif /* Standard Endpoint Descriptor */ 0x09, diff --git a/module_usb_audio/endpoint0/endpoint0.c b/module_usb_audio/endpoint0/endpoint0.c index cbc9d77c..5c70df08 100755 --- a/module_usb_audio/endpoint0/endpoint0.c +++ b/module_usb_audio/endpoint0/endpoint0.c @@ -76,13 +76,9 @@ unsigned char mixer1Crossbar[18]; short mixer1Weights[18*8]; unsigned char channelMap[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT]; -#if (NUM_USB_CHAN_OUT > 0) unsigned char channelMapAud[NUM_USB_CHAN_OUT]; -#endif -#if (NUM_USB_CHAN_IN > 0) unsigned char channelMapUsb[NUM_USB_CHAN_IN]; -#endif -unsigned char mixSel[MIX_INPUTS]; +unsigned char mixSel[MAX_MIX_COUNT][MIX_INPUTS]; #endif int min(int x, int y); @@ -159,7 +155,7 @@ const unsigned g_dataFormat_In[INPUT_FORMAT_COUNT] = {STREAM_FORMAT_INPUT_1_DATA /* Endpoint 0 function. Handles all requests to the device */ void Endpoint0(chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, - chanend c_mix_ctl, chanend c_clk_ctl) + chanend c_mix_ctl, chanend c_clk_ctl, chanend c_EANativeTransport_ctrl) { USB_SetupPacket_t sp; XUD_ep ep0_out = XUD_InitEp(c_ep0_out); @@ -225,9 +221,10 @@ void Endpoint0(chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, #endif /* Init mixer inputs */ + for(int j = 0; j < MAX_MIX_COUNT; j++) for(int i = 0; i < MIX_INPUTS; i++) { - mixSel[i] = i; + mixSel[j][i] = i; } #endif @@ -268,100 +265,149 @@ void Endpoint0(chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, /* Over-riding USB_StandardRequests implementation */ if(sp.bRequest == USB_SET_INTERFACE) { - /* Check for audio stream from host start/stop */ - if(sp.wIndex == 1) /* Output interface */ + switch (sp.wIndex) { - /* Check the alt is in range */ - if(sp.wValue <= OUTPUT_FORMAT_COUNT) - { - /* Alt 0 is stream stop */ - /* Only send change if we need to */ - if((sp.wValue > 0) && (g_curStreamAlt_Out != sp.wValue)) + /* Check for audio stream from host start/stop */ +#if (NUM_USB_CHAN_OUT > 0) + case INTERFACE_NUMBER_AUDIO_OUTPUT: + /* Check the alt is in range */ + if(sp.wValue <= OUTPUT_FORMAT_COUNT) { - g_curStreamAlt_Out = sp.wValue; - - /* Send format of data onto buffering */ - outuint(c_audioControl, SET_STREAM_FORMAT_OUT); - outuint(c_audioControl, g_dataFormat_Out[sp.wValue-1]); /* Data format (PCM/DSD) */ - - if(g_curUsbSpeed == XUD_SPEED_HS) + /* Alt 0 is stream stop */ + /* Only send change if we need to */ + if((sp.wValue > 0) && (g_curStreamAlt_Out != sp.wValue)) { - outuint(c_audioControl, NUM_USB_CHAN_OUT); /* Channel count */ - outuint(c_audioControl, g_subSlot_Out_HS[sp.wValue-1]); /* Subslot */ - outuint(c_audioControl, g_sampRes_Out_HS[sp.wValue-1]); /* Resolution */ - } - else - { - outuint(c_audioControl, NUM_USB_CHAN_OUT_FS); /* Channel count */ - outuint(c_audioControl, g_subSlot_Out_FS[sp.wValue-1]); /* Subslot */ - outuint(c_audioControl, g_sampRes_Out_FS[sp.wValue-1]); /* Resolution */ - } + g_curStreamAlt_Out = sp.wValue; - /* Handshake */ - chkct(c_audioControl, XS1_CT_END); + /* Send format of data onto buffering */ + outuint(c_audioControl, SET_STREAM_FORMAT_OUT); + outuint(c_audioControl, g_dataFormat_Out[sp.wValue-1]); /* Data format (PCM/DSD) */ + + if(g_curUsbSpeed == XUD_SPEED_HS) + { + outuint(c_audioControl, NUM_USB_CHAN_OUT); /* Channel count */ + outuint(c_audioControl, g_subSlot_Out_HS[sp.wValue-1]); /* Subslot */ + outuint(c_audioControl, g_sampRes_Out_HS[sp.wValue-1]); /* Resolution */ + } + else + { + outuint(c_audioControl, NUM_USB_CHAN_OUT_FS); /* Channel count */ + outuint(c_audioControl, g_subSlot_Out_FS[sp.wValue-1]); /* Subslot */ + outuint(c_audioControl, g_sampRes_Out_FS[sp.wValue-1]); /* Resolution */ + } + + /* Handshake */ + chkct(c_audioControl, XS1_CT_END); + } } - } - } - else if(sp.wIndex == 2) /* Input interface */ - { - /* Check the alt is in range */ - if(sp.wValue <= INPUT_FORMAT_COUNT) - { - /* Alt 0 is stream stop */ - /* Only send change if we need to */ - if((sp.wValue > 0) && (g_curStreamAlt_In != sp.wValue)) + break; +#endif + +#if (NUM_USB_CHAN_IN > 0) + case INTERFACE_NUMBER_AUDIO_INPUT: + /* Check the alt is in range */ + if(sp.wValue <= INPUT_FORMAT_COUNT) { - g_curStreamAlt_In = sp.wValue; - - /* Send format of data onto buffering */ - outuint(c_audioControl, SET_STREAM_FORMAT_IN); - outuint(c_audioControl, g_dataFormat_In[sp.wValue-1]); /* Data format (PCM/DSD) */ - - if(g_curUsbSpeed == XUD_SPEED_HS) + /* Alt 0 is stream stop */ + /* Only send change if we need to */ + if((sp.wValue > 0) && (g_curStreamAlt_In != sp.wValue)) { - outuint(c_audioControl, NUM_USB_CHAN_IN); /* Channel count */ - outuint(c_audioControl, g_subSlot_In_HS[sp.wValue-1]); /* Subslot */ - outuint(c_audioControl, g_sampRes_In_HS[sp.wValue-1]); /* Resolution */ - } - else - { - outuint(c_audioControl, NUM_USB_CHAN_IN_FS); /* Channel count */ - outuint(c_audioControl, g_subSlot_In_FS[sp.wValue-1]); /* Subslot */ - outuint(c_audioControl, g_sampRes_In_FS[sp.wValue-1]); /* Resolution */ - } + g_curStreamAlt_In = sp.wValue; - /* Handshake */ - chkct(c_audioControl, XS1_CT_END); + /* Send format of data onto buffering */ + outuint(c_audioControl, SET_STREAM_FORMAT_IN); + outuint(c_audioControl, g_dataFormat_In[sp.wValue-1]); /* Data format (PCM/DSD) */ + + if(g_curUsbSpeed == XUD_SPEED_HS) + { + outuint(c_audioControl, NUM_USB_CHAN_IN); /* Channel count */ + outuint(c_audioControl, g_subSlot_In_HS[sp.wValue-1]); /* Subslot */ + outuint(c_audioControl, g_sampRes_In_HS[sp.wValue-1]); /* Resolution */ + } + else + { + outuint(c_audioControl, NUM_USB_CHAN_IN_FS); /* Channel count */ + outuint(c_audioControl, g_subSlot_In_FS[sp.wValue-1]); /* Subslot */ + outuint(c_audioControl, g_sampRes_In_FS[sp.wValue-1]); /* Resolution */ + } + + /* Wait for handshake */ + chkct(c_audioControl, XS1_CT_END); + } } - } + break; +#endif + +#ifdef IAP_EA_NATIVE_TRANS + case INTERFACE_NUMBER_IAP_EA_NATIVE_TRANS: + /* Check the alt is in range */ + if (sp.wValue <= IAP_EA_NATIVE_TRANS_ALT_COUNT) + { + /* Reset all state of endpoints associated with this interface + * when changing an alternative setting. See USB 2.0 Spec 9.1.1.5 */ + XUD_ResetEpStateByAddr(ENDPOINT_ADDRESS_IN_IAP_EA_NATIVE_TRANS); + XUD_ResetEpStateByAddr(ENDPOINT_ADDRESS_OUT_IAP_EA_NATIVE_TRANS); + + /* Send selected Alt interface number onto EA Native EP manager */ + outuint(c_EANativeTransport_ctrl, (unsigned)sp.wValue); + + /* Wait for handshake */ + chkct(c_EANativeTransport_ctrl, XS1_CT_END); + } + break; +#endif + default: + /* Unhandled interface */ + break; } + #if (NUM_USB_CHAN_OUT > 0) && (NUM_USB_CHAN_IN > 0) - /* Check for stream start stop on output and input audio interfaces */ - if(sp.wValue && !g_interfaceAlt[1] && !g_interfaceAlt[2]) + if ((sp.wIndex == INTERFACE_NUMBER_AUDIO_OUTPUT) || (sp.wIndex == INTERFACE_NUMBER_AUDIO_INPUT)) { - /* If start and input AND output not currently running */ - UserAudioStreamStart(); + /* Check for stream start stop on output and input audio interfaces */ + if(sp.wValue && !g_interfaceAlt[INTERFACE_NUMBER_AUDIO_OUTPUT] && !g_interfaceAlt[INTERFACE_NUMBER_AUDIO_INPUT]) + { + /* If start and input AND output not currently running */ + UserAudioStreamStart(); + } + else if(((sp.wIndex == 1) && (!sp.wValue)) && g_interfaceAlt[INTERFACE_NUMBER_AUDIO_OUTPUT] && (!g_interfaceAlt[INTERFACE_NUMBER_AUDIO_INPUT])) + { + /* if output stop and output running and input not running */ + UserAudioStreamStop(); + } + else if(((sp.wIndex == 2) && (!sp.wValue)) && g_interfaceAlt[INTERFACE_NUMBER_AUDIO_INPUT] && (!g_interfaceAlt[INTERFACE_NUMBER_AUDIO_OUTPUT])) + { + /* if input stop and input running and output not running */ + UserAudioStreamStop(); + } } - else if(((sp.wIndex == 1) && (!sp.wValue)) && g_interfaceAlt[1] && (!g_interfaceAlt[2])) +#elif (NUM_USB_CHAN_OUT > 0) + if(sp.wIndex == INTERFACE_NUMBER_AUDIO_OUTPUT) { - /* if output stop and output running and input not running */ - UserAudioStreamStop(); + if(sp.wValue && (!g_interfaceAlt[INTERFACE_NUMBER_AUDIO_OUTPUT])) + { + /* if start and not currently running */ + UserAudioStreamStart(); + } + else if (!sp.wValue && g_interfaceAlt[INTERFACE_NUMBER_AUDIO_OUTPUT]) + { + /* if stop and currently running */ + UserAudioStreamStop(); + } } - else if(((sp.wIndex == 2) && (!sp.wValue)) && g_interfaceAlt[2] && (!g_interfaceAlt[1])) +#elif (NUM_USB_CHAN_IN > 0) + if(sp.wIndex == INTERFACE_NUMBER_AUDIO_INPUT) { - /* if input stop and input running and output not running */ - UserAudioStreamStop(); - } -#elif (NUM_USB_CHAN_OUT > 0) || (NUM_USB_CHAN_IN > 0) - if(sp.wValue && (!g_interfaceAlt[1])) - { - /* if start and not currently running */ - UserAudioStreamStart(); - } - else if (!sp.wValue && g_interfaceAlt[1]) - { - /* if stop and currently running */ - UserAudioStreamStop(); + if(sp.wValue && (!g_interfaceAlt[INTERFACE_NUMBER_AUDIO_INPUT])) + { + /* if start and not currently running */ + UserAudioStreamStart(); + } + else if (!sp.wValue && g_interfaceAlt[INTERFACE_NUMBER_AUDIO_INPUT]) + { + /* if stop and currently running */ + UserAudioStreamStop(); + } } #endif } /* if(sp.bRequest == SET_INTERFACE) */ diff --git a/module_usb_audio/endpoint0/endpoint0.h b/module_usb_audio/endpoint0/endpoint0.h index be2171fa..778d0937 100644 --- a/module_usb_audio/endpoint0/endpoint0.h +++ b/module_usb_audio/endpoint0/endpoint0.h @@ -14,8 +14,11 @@ * \param c_clk_ctl Optional chanend to be connected to the clockgen thread if * present. * \param c_usb_test Optional chanend to be connected to XUD if test modes required. + * + * \param c_EANativeTransport_ctrl Optional chanend to be connected to EA Native + * endpoint manager if present */ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioCtrl, - chanend ?c_mix_ctl,chanend ?c_clk_ctl); + chanend ?c_mix_ctl,chanend ?c_clk_ctl, chanend ?c_EANativeTransport_ctrl); #endif diff --git a/module_usb_audio/main.xc b/module_usb_audio/main.xc index d5a3ff67..7eab2e7f 100755 --- a/module_usb_audio/main.xc +++ b/module_usb_audio/main.xc @@ -214,7 +214,10 @@ 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 */ +#endif #endif }; @@ -235,6 +238,9 @@ XUD_EpType epTypeTableIn[ENDPOINT_COUNT_IN] = { XUD_EPTYPE_CTL | XUD_STATUS_ENAB #ifdef IAP_INT_EP XUD_EPTYPE_BUL | XUD_STATUS_ENABLE, #endif +#ifdef IAP_EA_NATIVE_TRANS + XUD_EPTYPE_BUL | XUD_STATUS_ENABLE, +#endif #endif }; @@ -265,6 +271,9 @@ void usb_audio_core(chanend c_mix_out #endif #ifdef IAP , chanend c_iap +#ifdef IAP_EA_NATIVE_TRANS +, chanend c_ea_data +#endif #endif #ifdef MIXER , chanend c_mix_ctl @@ -284,6 +293,12 @@ void usb_audio_core(chanend c_mix_out #ifndef MIXER #define c_mix_ctl null +#endif + +#ifdef IAP_EA_NATIVE_TRANS + chan c_EANativeTransport_ctrl; +#else +#define c_EANativeTransport_ctrl null #endif par @@ -351,7 +366,7 @@ void usb_audio_core(chanend c_mix_out /* Endpoint 0 Core */ { thread_speed(); - Endpoint0( c_xud_out[0], c_xud_in[0], c_aud_ctl, c_mix_ctl, c_clk_ctl); + Endpoint0( c_xud_out[0], c_xud_in[0], c_aud_ctl, c_mix_ctl, null, c_EANativeTransport_ctrl); } /* Decoupling core */ @@ -363,6 +378,18 @@ void usb_audio_core(chanend c_mix_out #endif ); } + +#if defined(IAP_EA_NATIVE_TRANS) + /* EA Native Transport Endpoint manager */ + /* TODO This core can be merged with buffer() */ + { + thread_speed(); + iAP2_EANativeTransport_EPManager( + c_xud_out[ENDPOINT_NUMBER_OUT_IAP_EA_NATIVE_TRANS], + c_xud_in[ENDPOINT_NUMBER_IN_IAP_EA_NATIVE_TRANS], + c_EANativeTransport_ctrl, c_ea_data); + } +#endif //: } } @@ -381,7 +408,11 @@ chanend ?c_clk_int chan c_mix_out; #endif +#if defined(SPDIF_RX) || defined(ADAT_RX) chan c_dig_rx; +#else + #define c_dig_rx null +#endif par { @@ -431,6 +462,9 @@ int main() #endif #ifdef IAP chan c_iap; +#ifdef IAP_EA_NATIVE_TRANS + chan c_ea_data; +#endif #endif #ifdef SU1_ADC_ENABLE chan c_adc; @@ -453,7 +487,6 @@ int main() chan c_clk_ctl; chan c_clk_int; #else -#define c_dig_rx null #define c_clk_int null #define c_clk_ctl null #define c_spdif_rx null @@ -469,6 +502,9 @@ int main() #endif #ifdef IAP , c_iap +#ifdef IAP_EA_NATIVE_TRANS + , c_ea_data +#endif #endif #ifdef MIXER , c_mix_ctl diff --git a/module_usb_audio/mixer/fastmix.S b/module_usb_audio/mixer/fastmix.S index db4c31ee..0047a1d3 100644 --- a/module_usb_audio/mixer/fastmix.S +++ b/module_usb_audio/mixer/fastmix.S @@ -144,10 +144,12 @@ setPtr: shl r2, r2, 1 .xtabranch .label_0 bru r2 +.syntax architectural #define BODY(i) \ - ldap r11, .label_##i; \ - bu setPtr_go + LDAPF_u10 .label_##i; \ + BRFU_u6 setPtr_go #include "repeat.h" +.syntax default setPtr_go: shl r0, r0, 3; ldc r2, 0x80; diff --git a/module_usb_audio/mixer/mixer.xc b/module_usb_audio/mixer/mixer.xc index f85aefe9..3e7df51d 100644 --- a/module_usb_audio/mixer/mixer.xc +++ b/module_usb_audio/mixer/mixer.xc @@ -6,6 +6,7 @@ #include "devicedefines.h" #include "xc_ptr.h" #include "commands.h" +#include "dbcalc.h" #ifdef MIXER @@ -60,14 +61,18 @@ xc_ptr mix_map; #endif /* Arrays for level data */ -int samples_to_host_inputs[NUM_USB_CHAN_IN]; /* Audio transmitted to host i.e. dev inputs */ +int samples_to_host_inputs[NUM_USB_CHAN_IN]; /* Audio transmitted to host i.e. device inputs */ +xc_ptr samples_to_host_inputs_ptr; + #ifdef LEVEL_METER_LEDS -int samples_to_host_inputs_buff[NUM_USB_CHAN_IN]; /* Audio transmitted to host i.e. dev inputs */ -#endif -static int samples_to_host_streams[NUM_USB_CHAN_OUT]; /* Audio stream to host from host */ -#if (MAX_MIX_COUNT > 0) -static int samples_to_host_outputs[NUM_USB_CHAN_OUT]; /* Device outputs */ +int samples_to_host_inputs_buff[NUM_USB_CHAN_IN]; /* Audio transmitted to host i.e. dev inputs */ +xc_ptr samples_to_host_inputs_buff_ptr; #endif +static int samples_from_host_streams[NUM_USB_CHAN_OUT]; /* Peak samples for audio stream from host */ + +static int samples_mixer_outputs[MAX_MIX_COUNT]; /* Peak samples out of the mixer */ +xc_ptr samples_mixer_outputs_ptr; + #if 0 #pragma xta command "add exclusion mixer1_rate_change" #pragma xta command "analyse path mixer1_req mixer1_req" @@ -87,18 +92,15 @@ static inline void ComputeMixerLevel(int sample, int i) int y; xc_ptr ptr; - x = abs(sample); - /* y = samples_to_host_outputs[i] */ - asm("ldaw %0, dp[samples_to_host_outputs]":"=r"(ptr):); /* Might want to hoist this */ - asm("ldw %0, %1[%2]":"=r"(y):"r"(ptr),"r"(i)); + /* y = samples_mixer_outputs[i] */ + read_via_xc_ptr_indexed(y, samples_mixer_outputs_ptr, i); if(x > y) { /* samples_to_host_outputs[i] = x; */ - write_via_xc_ptr_indexed(ptr,i,y); - //asm("stw %0, %1[%2]"::"r"(y),"r"(ptr),"r"(i)); + write_via_xc_ptr_indexed(samples_mixer_outputs_ptr,i,x); } } #endif @@ -117,7 +119,7 @@ int doMix8(xc_ptr samples, xc_ptr mult); /* DO NOT inline, causes 10.4.2 tools to add extra loads in loop */ /* At 18 x 12dB we could get 64 x bigger */ #pragma unsafe arrays -static int doMix(xc_ptr samples, xc_ptr ptr, xc_ptr mult) +static inline int doMix(xc_ptr samples, xc_ptr ptr, xc_ptr mult) { int h=0; int l=0; @@ -153,7 +155,7 @@ static int doMix(xc_ptr samples, xc_ptr ptr, xc_ptr mult) #endif #pragma unsafe arrays -static void giveSamplesToHost(chanend c, xc_ptr samples, xc_ptr ptr, xc_ptr multIn) +static inline void giveSamplesToHost(chanend c, xc_ptr samples, xc_ptr ptr, xc_ptr multIn) { #if defined(IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX) int mult; @@ -186,7 +188,7 @@ static void giveSamplesToHost(chanend c, xc_ptr samples, xc_ptr ptr, xc_ptr mult } #pragma unsafe arrays -static void getSamplesFromHost(chanend c, xc_ptr samples, int base, unsigned underflow) +static inline void getSamplesFromHost(chanend c, xc_ptr samples, int base, unsigned underflow) { if(!underflow) { @@ -205,8 +207,10 @@ static void getSamplesFromHost(chanend c, xc_ptr samples, int base, unsigned und #if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) /* Compute peak level data */ x = abs(sample); - if(x > samples_to_host_streams[i]) - samples_to_host_streams[i] = x; + if(x > samples_from_host_streams[i]) + { + samples_from_host_streams[i] = x; + } #endif #if defined(OUT_VOLUME_IN_MIXER) && !defined(OUT_VOLUME_AFTER_MIX) @@ -227,7 +231,7 @@ static void getSamplesFromHost(chanend c, xc_ptr samples, int base, unsigned und } #pragma unsafe arrays -static void giveSamplesToDevice(chanend c, xc_ptr samples, xc_ptr ptr, xc_ptr multOut, unsigned underflow) +static inline void giveSamplesToDevice(chanend c, xc_ptr samples, xc_ptr ptr, xc_ptr multOut, unsigned underflow) { outuint(c, underflow); @@ -265,7 +269,7 @@ static void giveSamplesToDevice(chanend c, xc_ptr samples, xc_ptr ptr, xc_ptr mu } #pragma unsafe arrays -static void getSamplesFromDevice(chanend c, xc_ptr samples, int base) +static inline void getSamplesFromDevice(chanend c, xc_ptr samples, int base) { #if defined(IN_VOLUME_IN_MIXER) && !defined(IN_VOLUME_AFTER_MIX) int mult; @@ -278,13 +282,20 @@ static void getSamplesFromDevice(chanend c, xc_ptr samples, int base) { int sample; int x; + int old_x; sample = inuint(c); #if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) /* Compute peak level data */ x = abs(sample); - if(x > samples_to_host_inputs[i]) - samples_to_host_inputs[i] = x; + + // old_x = samples_to_host_inputs[i] + read_via_xc_ptr_indexed(old_x, samples_to_host_inputs_ptr, i); + if(x > old_x) + { + //samples_to_host_inputs[i] = x; + write_via_xc_ptr_indexed(samples_to_host_inputs_ptr, i, x); + } #endif #if defined(IN_VOLUME_IN_MIXER) && !defined(IN_VOLUME_AFTER_MIX) @@ -300,7 +311,6 @@ static void getSamplesFromDevice(chanend c, xc_ptr samples, int base) static int mixer1_mix2_flag = (DEFAULT_FREQ > 96000); - #pragma unsafe arrays static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) { @@ -387,12 +397,13 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) break; #endif + /* Peak samples of stream from host to device (via USB) */ case GET_STREAM_LEVELS: index = inuint(c_mix_ctl); chkct(c_mix_ctl, XS1_CT_END); - outuint(c_mix_ctl, samples_to_host_streams[index]); + outuint(c_mix_ctl, samples_from_host_streams[index]); outct(c_mix_ctl, XS1_CT_END); - samples_to_host_streams[index] = 0; + samples_from_host_streams[index] = 0; break; case GET_INPUT_LEVELS: @@ -401,23 +412,32 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) #ifdef LEVEL_METER_LEDS /* Level LEDS process reseting samples_to_host_inputs * Other side makes sure we don't miss a peak */ - read_via_xc_ptr_indexed(val, samples_to_host_inputs_buff, index); - write_via_xc_ptr_indexed(samples_to_host_inputs_buff, index, 0); + //val = samples_to_host_inputs_buff[index]; + //samples_to_host_inputs_buff[index] = 0; + /* Access funcs used to avoid disjointness check */ + read_via_xc_ptr_indexed(val, samples_to_host_inputs_buff_ptr, index); + write_via_xc_ptr_indexed(samples_to_host_inputs_buff_ptr, index, 0); #else /* We dont have a level LEDs process, so reset ourselves */ - read_via_xc_ptr_indexed(val, samples_to_host_inputs, index); - write_via_xc_ptr_indexed(samples_to_host_inputs, index, 0); + //val = samples_to_host_inputs[index]; + //samples_to_host_inputs[index] = 0; + /* Access funcs used to avoid disjointness check */ + read_via_xc_ptr_indexed(val, samples_to_host_inputs_ptr, index); + write_via_xc_ptr_indexed(samples_to_host_inputs_ptr, index, 0); #endif outuint(c_mix_ctl, val); outct(c_mix_ctl, XS1_CT_END); break; -#if MAX_MIX_COUNT > 0 +#if (MAX_MIX_COUNT > 0) + /* Peak samples of the mixer outputs */ case GET_OUTPUT_LEVELS: index = inuint(c_mix_ctl); chkct(c_mix_ctl, XS1_CT_END); - read_via_xc_ptr_indexed(val, samples_to_host_outputs, index); - write_via_xc_ptr_indexed(samples_to_host_outputs, index, mix); + read_via_xc_ptr_indexed(val, samples_mixer_outputs, index); + write_via_xc_ptr_indexed(samples_mixer_outputs, index, 0); + //val = samples_mixer_outputs[index]; + //samples_mixer_outputs[index] = 0; outuint(c_mix_ctl, val); outct(c_mix_ctl, XS1_CT_END); break; @@ -475,12 +495,12 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2) { unsigned underflow = inuint(c_host); #if MAX_MIX_COUNT > 0 - outuint(c_mixer2, 0); + outuint(c_mixer2, underflow); giveSamplesToHost(c_host, samples, samples_to_host_map, multIn); outuint(c_mixer2, 0); inuint(c_mixer2); - getSamplesFromHost(c_host, samples, 0); + getSamplesFromHost(c_host, samples, 0, underflow); outuint(c_mixer2, 0); inuint(c_mixer2); #ifdef FAST_MIXER @@ -555,44 +575,65 @@ static int mixer2_mix2_flag = (DEFAULT_FREQ > 96000); #pragma unsafe arrays static void mixer2(chanend c_mixer1, chanend c_audio) { - int mixed; + int mixed; + unsigned underflow = 0; - while (1) { - outuint(c_mixer1, 0); -#pragma xta endpoint "mixer2_req" - inuint(c_audio); - if(testct(c_mixer1)) + while (1) { - int sampFreq; -#pragma xta endpoint "mixer2_rate_change" - inct(c_mixer1); - sampFreq = inuint(c_mixer1); - - - mixer2_mix2_flag = sampFreq > 96000; - - for (int i=0;i 96000; + + /* Inform mixer2 (or audio()) about freq change */ + outct(c_audio, command); + outuint(c_audio, sampFreq); + break; + + case SET_STREAM_FORMAT_OUT: + case SET_STREAM_FORMAT_IN: + /* Inform mixer2 (or audio()) about format change */ + outct(c_audio, command); + outuint(c_audio, inuint(c_mixer1)); + outuint(c_audio, inuint(c_mixer1)); + break; + + default: + break; + } + + for (int i=0;i 1 #ifdef FAST_MIXER mixed = doMix1(samples, mix_mult_slice(1)); @@ -668,9 +709,14 @@ void mixer(chanend c_mix_in, chanend c_mix_out, chanend c_mix_ctl) multIn = array_to_xc_ptr((multIn_array,unsigned[])); samples = array_to_xc_ptr((samples_array,unsigned[])); samples_to_host_map = array_to_xc_ptr((samples_to_host_map_array,unsigned[])); - samples_to_device_map = array_to_xc_ptr((samples_to_device_map_array,unsigned[])); + samples_to_host_inputs_ptr = array_to_xc_ptr((samples_to_host_inputs, unsigned[])); +#ifdef LEVEL_METER_LEDS + samples_to_host_inputs_buff_ptr = array_to_xc_ptr((samples_to_host_inputs, unsigned[])); +#endif + samples_mixer_outputs_ptr = array_to_xc_ptr((samples_mixer_outputs, unsigned[])); + #if MAX_MIX_COUNT >0 mix_mult = array_to_xc_ptr((mix_mult_array,unsigned[])); #ifndef FAST_MIXER @@ -718,7 +764,7 @@ void mixer(chanend c_mix_in, chanend c_mix_out, chanend c_mix_ctl) #ifndef FAST_MIXER write_word_to_mix_map(i,j, j < 16 ? j : j + 2); #endif - write_word_to_mix_mult(i,j, i==j ? MAX_VOL >> 3 : 0); + write_word_to_mix_mult(i,j, i==j ? db_to_mult(0, 8, 25) : 0); } #endif diff --git a/xpd.xml b/xpd.xml index 1a5dea56..5099f87f 100644 --- a/xpd.xml +++ b/xpd.xml @@ -20,7 +20,7 @@ - module_queue + module_queue module_xassert MIDI @@ -70,7 +70,11 @@ - + + + + + XM-004720-SM XMOS