diff --git a/module_usb_aud_shared/audio.h b/module_usb_aud_shared/audio.h index 77da8b77..8fc0568d 100644 --- a/module_usb_aud_shared/audio.h +++ b/module_usb_aud_shared/audio.h @@ -12,9 +12,7 @@ * receiving/transmitting samples * \param c_config An optional channel that will be passed on to the * CODEC configuration functions. - * \param c_i2c An optional channel that will be passed on to the - * functions requiring i2c. */ -void audio(chanend c_in, chanend ?c_dig, chanend ?c_config, chanend ?c_i2c); +void audio(chanend c_in, chanend ?c_dig, chanend ?c_config); #endif // __audio_h__ diff --git a/module_usb_aud_shared/audio.xc b/module_usb_aud_shared/audio.xc index 2d67d51c..4e7d11cc 100755 --- a/module_usb_aud_shared/audio.xc +++ b/module_usb_aud_shared/audio.xc @@ -12,7 +12,6 @@ #include #include #include -#include #include "clocking.h" #include "audioports.h" @@ -64,8 +63,12 @@ extern void device_reboot(void); unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_dig_rx) { unsigned sample; +#if NUM_USB_CHAN_OUT > 0 unsigned samplesOut[NUM_USB_CHAN_OUT]; +#endif +#if NUM_USB_CHAN_IN > 0 unsigned samplesIn[NUM_USB_CHAN_IN]; +#endif unsigned samplesInPrev[NUM_USB_CHAN_IN]; unsigned tmp; unsigned index; @@ -73,15 +76,14 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_ unsigned prev=0; int started = 0; #endif -#ifndef CODEC_SLAVE - int oldtime; -#endif +#if NUM_USB_CHAN_IN > 0 for (int i=0;i 0 #pragma loop unroll for(int i = 0; i < NUM_USB_CHAN_IN; i++) { outuint(c_out, samplesIn[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 #pragma loop unroll for(int i = 0; i < NUM_USB_CHAN_OUT; i++) @@ -201,6 +208,7 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_ tmp += 33; #if (I2S_CHANS_DAC != 0) +#pragma loop unroll for(int i = 0; i < I2S_WIRES_DAC; i++) { p_i2s_dac[i] @ tmp <: 0; @@ -214,7 +222,6 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_ { clearbuf(p_i2s_adc[i]); } - oldtime = tmp-1+32; /* TODO In master mode, the i/o loop assumes L/RCLK = 32bit clocks. We should check this every interation * and resync if we got a bclk glitch */ @@ -237,17 +244,22 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_ { #ifndef MIXER // Interfaces straight to decouple() (void) inuint(c_out); + +#if NUM_USB_CHAN_IN > 0 #pragma loop unroll for(int i = 0; i < NUM_USB_CHAN_IN; i++) { outuint(c_out, samplesIn[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 #pragma loop unroll for(int i = 0; i < NUM_USB_CHAN_OUT; i++) @@ -297,7 +309,7 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_ #pragma xta endpoint "i2s_output_l" -#if (I2S_CHANS_DAC != 0) +#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) #pragma loop unroll for(int i = 0; i < I2S_CHANS_DAC; i+=2) { @@ -355,14 +367,16 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_ for(int i = 1; i < I2S_CHANS_ADC; i += 2) { p_i2s_adc[index++] :> sample; +#if NUM_USB_CHAN_IN > 0 samplesIn[i] = bitrev(sample); /* Store the previous left in left */ samplesIn[i-1] = samplesInPrev[i]; +#endif } #endif -#ifdef SPDIF +#if defined(SPDIF) && (NUM_USB_CHAN_OUT > 0) outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX]); /* Forward sample to SPDIF txt thread */ sample = samplesOut[SPDIF_TX_INDEX + 1]; outuint(c_spd_out, sample); /* Forward sample to SPDIF txt thread */ @@ -385,7 +399,7 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_ tmp = 0; #pragma xta endpoint "i2s_output_r" -#if (I2S_CHANS_DAC != 0) +#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) #pragma loop unroll for(int i = 1; i < I2S_CHANS_DAC; i+=2) { @@ -440,7 +454,10 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_ for(int i = 1; i < I2S_CHANS_ADC; i += 2) { p_i2s_adc[index++] :> sample; + +#if NUM_USB_CHAN_IN > 0 samplesInPrev[i] = bitrev(sample); +#endif } @@ -496,7 +513,7 @@ static unsigned dummy_deliver(chanend c_out) { return 0; } -void audio(chanend c_mix_out, chanend ?c_dig_rx, chanend ?c_config, chanend ?c_i2c) +void audio(chanend c_mix_out, chanend ?c_dig_rx, chanend ?c_config) { #ifdef SPDIF chan c_spdif_out; @@ -511,10 +528,10 @@ void audio(chanend c_mix_out, chanend ?c_dig_rx, chanend ?c_config, chanend ?c_i #endif /* Initialise master clock generation */ - ClockingInit(c_i2c); + ClockingInit(); /* Perform required CODEC/ADC/DAC initialisation */ - CodecInit(c_config, c_i2c); + CodecInit(c_config); while(1) { @@ -533,7 +550,7 @@ void audio(chanend c_mix_out, chanend ?c_dig_rx, chanend ?c_config, chanend ?c_i divide = mClk / ( curSamFreq * 64 ); /* Configure clocking for required master clock */ - ClockingConfig(mClk, c_i2c); + ClockingConfig(mClk); if(!firstRun) { @@ -553,7 +570,7 @@ void audio(chanend c_mix_out, chanend ?c_dig_rx, chanend ?c_config, chanend ?c_i firstRun = 0; /* Configure CODEC/DAC/ADC for SampleFreq/MClk */ - CodecConfig(curSamFreq, mClk, c_config, c_i2c); + CodecConfig(curSamFreq, mClk, c_config); /* Configure audio ports */ ConfigAudioPorts(divide); diff --git a/module_usb_aud_shared/clocking/clocking.h b/module_usb_aud_shared/clocking/clocking.h index a02ebf15..88fc786b 100644 --- a/module_usb_aud_shared/clocking/clocking.h +++ b/module_usb_aud_shared/clocking/clocking.h @@ -5,10 +5,10 @@ /* Functions that handle master clock generation. These need modifying for an existing design */ /* Any initialisation required for master clock generation - run once at start up */ -void ClockingInit(chanend ?c); +void ClockingInit(void); /* Configuration for a specific master clock frequency - run every sample frequency change */ -void ClockingConfig(unsigned mClkFreq, chanend ?c); +void ClockingConfig(unsigned mClkFreq); /** Clock generation and digital audio I/O handling. diff --git a/module_usb_aud_shared/codec/codec.h b/module_usb_aud_shared/codec/codec.h index c97662ec..452ac900 100644 --- a/module_usb_aud_shared/codec/codec.h +++ b/module_usb_aud_shared/codec/codec.h @@ -6,9 +6,9 @@ /* TODO Are the channel args required? */ /* Any required CODEC initialisation - run once at start up */ -void CodecInit(chanend ?c_codec, chanend ?c_i2c); +void CodecInit(chanend ?c_codec); /* Configure condec for a specific mClk/Sample frquency - run on every sample frequency change */ -void CodecConfig(unsigned samFreq, unsigned mClk, chanend ?c_codec, chanend ?c_i2c); +void CodecConfig(unsigned samFreq, unsigned mClk, chanend ?c_codec); #endif diff --git a/module_usb_aud_shared/devicedefines.h b/module_usb_aud_shared/devicedefines.h index 1e7ff0ad..3cca2435 100644 --- a/module_usb_aud_shared/devicedefines.h +++ b/module_usb_aud_shared/devicedefines.h @@ -9,6 +9,27 @@ #include "customdefines.h" +/* Tidy up historical INPUT/OUTPUT defines. INPUT/OUTPUT now enabled based on channel count defines */ +#if !defined(NUM_USB_CHAN_IN) + #error NUM_USB_CHAN_IN must be defined! +#else + #if (NUM_USB_CHAN_IN == 0) + #undef INPUT + #else + #define INPUT 1 + #endif +#endif + +#if !defined(NUM_USB_CHAN_OUT) + #error NUM_USB_CHAN_OUT must be defined! +#else + #if (NUM_USB_CHAN_OUT == 0) + #undef OUTPUT + #else + #define OUTPUT 1 + #endif +#endif + #if defined(IO_EXPANSION) && (IO_EXPANSION == 0) #undef IO_EXPANSION #endif @@ -207,18 +228,18 @@ #define ID_CLKSRC_EXT 42 /* Clock source ID (external) */ #define ID_CLKSRC_ADAT 43 /* Clock source ID (external) */ -#define ID_XU_MIXSEL 50 -#define ID_XU_OUT 51 -#define ID_XU_IN 52 +#define ID_XU_MIXSEL 50 +#define ID_XU_OUT 51 +#define ID_XU_IN 52 -#define ID_MIXER_1 60 +#define ID_MIXER_1 60 #ifndef SERIAL_STR -#define SERIAL_STR "0000" /* Serial number string */ +#define SERIAL_STR "0000" /* Serial number string */ #endif -#define SERIAL_STR_INDEX 0x03 -#define MANUFACTURER_STR_INDEX 0x01 +#define SERIAL_STR_INDEX 0x03 +#define MANUFACTURER_STR_INDEX 0x01 #define PRODUCT_STR_INDEX 0x02 /* Mixer defines */ diff --git a/module_usb_aud_shared/endpoint0/audiorequests.xc b/module_usb_aud_shared/endpoint0/audiorequests.xc index 19d8fd96..2cde9948 100644 --- a/module_usb_aud_shared/endpoint0/audiorequests.xc +++ b/module_usb_aud_shared/endpoint0/audiorequests.xc @@ -40,8 +40,12 @@ 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]; @@ -52,10 +56,6 @@ extern unsigned int g_curSamFreq; extern unsigned int g_curSamFreq48000Family; extern unsigned int g_curSamFreqMultiplier; -/* Global level data */ -//unsigned short g_lvlMixOut[MAX_MIX_COUNT]; -//unsigned short g_lvlMixIn[NUM_USB_CHAN_IN + NUM_USB_CHAN_OUT]; - /* Store an int into a char array: Note this allows non-word aligned access unlike reinerpret cast */ void storeInt(unsigned char buffer[], int index, int val) { diff --git a/module_usb_aud_shared/endpoint0/descriptors_2.h b/module_usb_aud_shared/endpoint0/descriptors_2.h index 02fe3e8c..567ee1d6 100644 --- a/module_usb_aud_shared/endpoint0/descriptors_2.h +++ b/module_usb_aud_shared/endpoint0/descriptors_2.h @@ -170,12 +170,6 @@ unsigned char devQualDesc_Null[] = #define MIDI_LENGTH (0) #endif -#ifdef MIXER -#define MIXER_LENGTH (13+1+18) -#else -#define MIXER_LENGTH (0) -#endif - #ifdef IAP #define IAP_LENGTH (30) #else @@ -191,9 +185,18 @@ unsigned char devQualDesc_Null[] = #endif #ifdef MIXER -#define LEN_XU_MIX (17) + #define LEN_XU_MIX (17) + #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 LEN_XU_MIX (0) + #define LEN_XU_MIX (0) + #define MIXER_LENGTH (0) #endif #define LEN_CLK (8) @@ -219,7 +222,7 @@ unsigned char devQualDesc_Null[] = /* Total length of config descriptor */ -#define CFG_TOTAL_LENGTH_A2 (7 + 26 + (INPUT_INTERFACES * 55) + (OUTPUT_INTERFACES * 62) + (MIDI_LENGTH) + (DFU_INTERFACES * 16) + TLEN_AC + (MIXER_LENGTH) + IAP_LENGTH + INPUT_ALT_LENGTH + OUTPUT_ALT_LENGTH) +#define CFG_TOTAL_LENGTH_A2 (7 + 26 + (INPUT_INTERFACES * 55) + (OUTPUT_INTERFACES * 62) + (MIDI_LENGTH) + (DFU_INTERFACES * 18) + TLEN_AC + (MIXER_LENGTH) + IAP_LENGTH + INPUT_ALT_LENGTH + OUTPUT_ALT_LENGTH) /* Define for number of audio interfaces (+1 for mandatory control interface) */ #define AUDIO_INTERFACES (INPUT_INTERFACES + OUTPUT_INTERFACES + 1) @@ -365,7 +368,7 @@ unsigned char cfgDesc_Audio2[] = ID_CLKSEL, /* 7 bCSourceID: ID of Clock Entity */ NUM_USB_CHAN_OUT, /* 8 bNrChannels */ 0,0,0,0, /* 9 bmChannelConfig */ - 13, /* 13 iChannelNames */ + 15, /* 13 iChannelNames */ 0x00, 0x00, /* 14 bmControls */ 6, /* 16 iTerminal */ @@ -484,7 +487,7 @@ unsigned char cfgDesc_Audio2[] = ID_CLKSEL, /* 7 bCSourceID: ID of Clock Entity */ NUM_USB_CHAN_IN, /* 8 bNrChannels */ 0,0,0,0, /* 9 bmChannelConfig */ - 31, /* 13 iChannelNames */ + 33, /* 13 iChannelNames */ 0x00, 0x00, /* 14 bmControls */ 0, /* 16 iTerminal */ @@ -604,7 +607,7 @@ unsigned char cfgDesc_Audio2[] = 2, /* 6 bNrPins */ ID_IT_USB, /* 7 baSourceId(1) */ ID_IT_AUD, /* 7 baSourceId(2) */ - MIX_INPUTS, /* 8+p bNrChannels */ + MIX_INPUTS, /* 8+p bNrChannels */ 0, /* 9+p bmChannelConfig */ 0, /* 10+p bmChannelConfig */ 0, /* 11+p bmChannelConfig */ @@ -621,20 +624,72 @@ unsigned char cfgDesc_Audio2[] = /* 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 */ - 0x0D+0x01+0x12, /* 0 bLength : 13 + num inputs + bit map (inputs * outputs) */ + MIXER_LENGTH, /* 0 bLength : 13 + num inputs + bit map (inputs * outputs) */ CS_INTERFACE, /* 1 bDescriptorType: 0x24 */ 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*/ - 0x08, /* Number of mixer output channels */ + 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 ???? */ - 49, /* Channel name index */ - 0xff, 0xff, 0xff, 0xff, /* Mixer programmable control bitmap */ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, + 49, /* Channel name index */ +#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 @@ -680,7 +735,7 @@ unsigned char cfgDesc_Audio2[] = 0x00, /* 4 bmControls */ 0x01, /* 5 bFormatType */ PCM, 0x00, 0x00, 0x00, /* 6:10 bmFormats (note this is a bitmap) */ - NUM_USB_CHAN_OUT, /* 11 bNrChannels */ + NUM_USB_CHAN_OUT, /* 11 bNrChannels */ 0,0,0,0, /* 12:14: bmChannelConfig */ 13, /* 15 iChannelNames */ @@ -715,7 +770,7 @@ unsigned char cfgDesc_Audio2[] = 0x81, /* 2 bEndpointAddress (D7: 0:out, 1:in) */ 17, /* 3 bmAttributes (bitmap) */ 4,0, /* 4 wMaxPacketSize */ - 8, /* 6 bInterval */ + 4, /* 6 bInterval. Only values <= 1 frame (8) supported by MS */ #ifdef ADAT_TX /* Standard AS Interface Descriptor (4.9.1) (Alt) */ @@ -739,7 +794,7 @@ unsigned char cfgDesc_Audio2[] = PCM, 0x00, 0x00, 0x00, /* 6:10 bmFormats (note this is a bitmap) */ NUM_USB_CHAN_OUT, /* 11 bNrChannels */ 0,0,0,0, /* 12:14: bmChannelConfig */ - 13, /* 15 iChannelNames */ + 15, /* 15 iChannelNames */ /* Type 1 Format Type Descriptor */ 0x06, /* 0 bLength (in bytes): 6 */ @@ -810,7 +865,7 @@ unsigned char cfgDesc_Audio2[] = PCM, 0x00, 0x00, 0x00, /* 6:10 bmFormats (note this is a bitmap) */ NUM_USB_CHAN_IN, /* 11 bNrChannels */ 0,0,0,0, /* 12:14: bmChannelConfig */ - 31, /* 15 iChannelNames */ + 33, /* 15 iChannelNames */ /* Type 1 Format Type Descriptor */ 0x06, /* 0 bLength (in bytes): 6 */ @@ -859,7 +914,7 @@ unsigned char cfgDesc_Audio2[] = PCM, 0x00, 0x00, 0x00, /* 6:10 bmFormats (note this is a bitmap) */ NUM_USB_CHAN_IN - 4, /* 11 bNrChannels */ 0,0,0,0, /* 12:14: bmChannelConfig */ - 31, /* 15 iChannelNames */ + 33, /* 15 iChannelNames */ /* Type 1 Format Type Descriptor */ 0x06, /* 0 bLength (in bytes): 6 */ @@ -998,7 +1053,7 @@ unsigned char cfgDesc_Audio2[] = 0x02, /* 2 bDescriptorSubtype : MIDI_IN_JACK subtype. (field size 1 bytes) */ 0x02, /* 3 bJackType : EXTERNAL. (field size 1 bytes) */ 0x02, /* 4 bJackID : ID of this Jack. (field size 1 bytes) */ - 0x00, /* 5 iJack : Unused. (field size 1 bytes) */ + 0x14, /* 5 iJack : Unused. (field size 1 bytes) */ /* Table B-9: MIDI Adapter MIDI OUT Jack Descriptor (Embedded) */ 0x09, /* 0 bLength : Size of this descriptor, in bytes. (field size 1 bytes) */ @@ -1020,7 +1075,7 @@ unsigned char cfgDesc_Audio2[] = 0x01, /* 5 bNrInputPins : Number of Input Pins of this Jack. (field size 1 bytes) */ 0x01, /* 6 BaSourceID(1) : ID of the Entity to which this Pin is connected. (field size 1 bytes) */ 0x01, /* 7 BaSourcePin(1) : Output Pin number of the Entity to which this Input Pin is connected. */ - 0x00, /* 8 iJack : Unused. (field size 1 bytes) */ + 0x13, /* 8 iJack : Unused. (field size 1 bytes) */ /* Table B-11: MIDI Adapter Standard Bulk OUT Endpoint Descriptor */ 0x09, /* 0 bLength : Size of this descriptor, in bytes. (field size 1 bytes) */ @@ -1068,17 +1123,31 @@ unsigned char cfgDesc_Audio2[] = 0x00, /* 4 bNumEndpoints : 0 endpoints. (field size 1 bytes) */ 0xFE, /* 5 bInterfaceClass : DFU. (field size 1 bytes) */ 0x01, /* 6 bInterfaceSubclass : (field size 1 bytes) */ - 0x00, /* 7 bInterfaceProtocol : Unused. (field size 1 bytes) */ - 12, /* 8 iInterface : Used. (field size 1 bytes) */ + 0x01, /* 7 bInterfaceProtocol : Unused. (field size 1 bytes) */ + 8, /* 8 iInterface : Used. (field size 1 bytes) */ - /* Standard DFU class functional descriptor */ - 0x07, +#if 0 + /* DFU 1.0 Run-Time DFU Functional Descriptor */ + 0x07, 0x21, 0x07, 0xFA, 0x00, 0x40, 0x00, +#else + /* DFU 1.1 Run-Time DFU Functional Descriptor */ + 0x09, /* 0 Size */ + 0x21, /* 1 bDescriptorType : DFU FUNCTIONAL */ + 0x07, /* 2 bmAttributes */ + 0xFA, /* 3 wDetachTimeOut */ + 0x00, /* 4 wDetachTimeOut */ + 0x40, /* 5 wTransferSize */ + 0x00, /* 6 wTransferSize */ + 0x10, /* 7 bcdDFUVersion */ + 0x01, /* 7 bcdDFUVersion */ + +#endif #endif #ifdef IAP @@ -1092,7 +1161,7 @@ unsigned char cfgDesc_Audio2[] = 0xFF, /* 5 bInterfaceClass : DFU. (field size 1 bytes) */ 0xF0, /* 6 bInterfaceSubclass : (field size 1 bytes) */ 0x00, /* 7 bInterfaceProtocol : Unused. (field size 1 bytes) */ - 57, /* 8 iInterface : Used. (field size 1 bytes) */ + 59, /* 8 iInterface : Used. (field size 1 bytes) */ /* iAP Bulk OUT Endpoint Descriptor */ 0x07, /* 0 bLength : Size of this descriptor, in bytes. (field size 1 bytes) */ @@ -1145,6 +1214,9 @@ static unsigned char strDescs_Audio2[][40] = APPEND_VENDOR_STR(S/PDIF Clock), // 10 iClockSource APPEND_VENDOR_STR(ADAT Clock), // 11 iClockSource APPEND_VENDOR_STR(DFU), // 12 iInterface for DFU interface + + APPEND_VENDOR_STR(MIDI Out), + APPEND_VENDOR_STR(MIDI In ), "Analogue 1", // 13 Output channel name place holders - Get customised at runtime based on device config "Analogue 2", // 14 @@ -1257,7 +1329,7 @@ unsigned char oSpeedCfgDesc[] = #define STREAMING_INTERFACES (INPUT_INTERFACES + OUTPUT_INTERFACES) -#define CFG_TOTAL_LENGTH_A1 (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES * 61) + (OUTPUT_INTERFACES * 70) + (DFU_INTERFACES * 16)) +#define CFG_TOTAL_LENGTH_A1 (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES * 61) + (OUTPUT_INTERFACES * 70) + (DFU_INTERFACES * 18)) #ifdef AUDIO_CLASS_FALLBACK unsigned char cfgDesc_Audio1[] = { @@ -1536,19 +1608,19 @@ unsigned char cfgDesc_Audio1[] = 0x00, 0x00, /* Unused */ #endif -#ifdef DFU /* Standard DFU class Interface descriptor */ 0x09, /* 0 bLength : Size of this descriptor, in bytes. (field size 1 bytes) */ 0x04, /* 1 bDescriptorType : INTERFACE descriptor. (field size 1 bytes) */ - (INPUT_INTERFACES+OUTPUT_INTERFACES+1), /* 2 bInterfaceNumber : Index of this interface. (field size 1 bytes) */ + (INPUT_INTERFACES+OUTPUT_INTERFACES+1), /* 2 bInterfaceNumber : Index of this interface. (field size 1 bytes) */ 0x00, /* 3 bAlternateSetting : Index of this setting. (field size 1 bytes) */ 0x00, /* 4 bNumEndpoints : 0 endpoints. (field size 1 bytes) */ 0xFE, /* 5 bInterfaceClass : DFU. (field size 1 bytes) */ 0x01, /* 6 bInterfaceSubclass : (field size 1 bytes) */ - 0x00, /* 7 bInterfaceProtocol : Unused. (field size 1 bytes) */ - 0x08, /* 8 iInterface : Unused. (field size 1 bytes) */ + 0x01, /* 7 bInterfaceProtocol : Unused. (field size 1 bytes) */ + 12, /* 8 iInterface : Unused. (field size 1 bytes) */ - /* Standard DFU class functional descriptor */ +#if 0 + /* DFU 1.0 Run-Time DFU Functional Descriptor */ 0x07, 0x21, 0x07, @@ -1556,6 +1628,18 @@ unsigned char cfgDesc_Audio1[] = 0x00, 0x40, 0x00 +#else + /* DFU 1.1 Run-Time DFU Functional Descriptor */ + 0x09, /* 0 Size */ + 0x21, /* 1 bDescriptorType : DFU FUNCTIONAL */ + 0x07, /* 2 bmAttributes */ + 0xFA, /* 3 wDetachTimeOut */ + 0x00, /* 4 wDetachTimeOut */ + 0x40, /* 5 wTransferSize */ + 0x00, /* 6 wTransferSize */ + 0x10, /* 7 bcdDFUVersion */ + 0x01, /* 7 bcdDFUVersion */ + #endif }; diff --git a/module_usb_aud_shared/endpoint0/endpoint0.xc b/module_usb_aud_shared/endpoint0/endpoint0.xc index 4dcf1918..75ca5148 100755 --- a/module_usb_aud_shared/endpoint0/endpoint0.xc +++ b/module_usb_aud_shared/endpoint0/endpoint0.xc @@ -21,7 +21,7 @@ #include "dfu_types.h" #include "xc_ptr.h" -/* Windows does not have a built in DFU driver (windows will prompt), so warn that DFU will not be functional in Audio 1.0 mode. +/* Windows does not have a built in DFU driver (windows will prompt), so warn that DFU will not be functional in Audio 1.0 mode.Udi * Of course, OSX is unaffected. */ #if ((AUDIO_CLASS==1) || defined(AUDIO_CLASS_FALLBACK)) && defined(DFU) @@ -70,9 +70,12 @@ short mixer1Weights[18*8]; //#define MAX_MIX_COUNT 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]; #endif @@ -180,16 +183,20 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, mixer1Weights[54] = 0; mixer1Weights[63] = 0; +#if NUM_USB_CHAN_OUT > 0 /* Setup up audio output channel mapping */ for(int i = 0; i < NUM_USB_CHAN_OUT; i++) { channelMapAud[i] = i; } +#endif +#if NUM_USB_CHAN_IN > 0 for(int i = 0; i < NUM_USB_CHAN_IN; i++) { channelMapUsb[i] = i + NUM_USB_CHAN_OUT; } +#endif /* Set up channel mapping default */ @@ -223,33 +230,33 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, /* Build up channel string table - By default all channels are marked as analogue * TODO We really want to do this an build time... */ #if defined(SPDIF_RX) && (SPDIF_RX_INDEX != 0) - safestrcpy(strDescs_Audio2[SPDIF_RX_INDEX + 31], "S/PDIF 1"); - safestrcpy(strDescs_Audio2[SPDIF_RX_INDEX + 32], "S/PDIF 2"); + safestrcpy(strDescs_Audio2[SPDIF_RX_INDEX + 33], "S/PDIF 1"); + safestrcpy(strDescs_Audio2[SPDIF_RX_INDEX + 34], "S/PDIF 2"); #endif #if defined(ADAT_RX) && (ADAT_RX_INDEX != 0) - safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 31], "ADAT 1"); - safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 32], "ADAT 2"); - safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 33], "ADAT 3"); - safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 34], "ADAT 4"); - safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 35], "ADAT 5"); - safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 36], "ADAT 6"); - safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 37], "ADAT 7"); - safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 38], "ADAT 8"); + safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 33], "ADAT 1"); + safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 34], "ADAT 2"); + safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 35], "ADAT 3"); + safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 36], "ADAT 4"); + safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 37], "ADAT 5"); + safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 38], "ADAT 6"); + safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 39], "ADAT 7"); + safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 40], "ADAT 8"); #endif #if defined(SPDIF) && (SPDIF_TX_INDEX != 0) /* "Analogue naming gets priority */ - safestrcpy(strDescs_Audio2[SPDIF_TX_INDEX + 13], "S/PDIF 1"); - safestrcpy(strDescs_Audio2[SPDIF_TX_INDEX + 14], "S/PDIF 2"); + safestrcpy(strDescs_Audio2[SPDIF_TX_INDEX + 15], "S/PDIF 1"); + safestrcpy(strDescs_Audio2[SPDIF_TX_INDEX + 16], "S/PDIF 2"); #endif #if defined(ADAT_TX) && (ADAT_TX_INDEX != 0) - safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 13], "ADAT 1"); - safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 14], "ADAT 2"); - safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 15], "ADAT 3"); - safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 16], "ADAT 4"); - safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 17], "ADAT 5"); - safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 18], "ADAT 6"); - safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 19], "ADAT 7"); - safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 20], "ADAT 8"); + safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 15], "ADAT 1"); + safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 16], "ADAT 2"); + safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 17], "ADAT 3"); + safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 18], "ADAT 4"); + safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 19], "ADAT 5"); + safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 20], "ADAT 6"); + safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 21], "ADAT 7"); + safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 22], "ADAT 8"); #endif #ifdef VENDOR_AUDIO_REQS @@ -494,7 +501,6 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, // Handshake //chkct(c_audioControl, XS1_CT_END); - //printint(8); break; #endif @@ -736,7 +742,7 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, device_reboot(); } - /* TODO we should not make the assumtion that all DFU requests are handled */ + /* TODO we should not make the assumption that all DFU requests are handled */ retVal = 0; } /* Check for: - Audio CONTROL interface request - always 0, note we check for DFU first @@ -748,6 +754,7 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, || (request == CLASS_ENDPOINT_REQUEST && ((interfaceNum == 0x82) || (interfaceNum == 0x01)))) { #endif + #if (AUDIO_CLASS == 2) && defined(AUDIO_CLASS_FALLBACK) if(g_curUsbSpeed == XUD_SPEED_HS) { @@ -780,7 +787,6 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, break; default: - // TODO: STALL //printstr("unrecognised request\n"); //printhexln(sp.bRequest); //printhexln(sp.bmRequestType.Type); @@ -802,7 +808,9 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, transfer, and the STALL condition terminates at the beginning of the next control transfer (Setup). The remainder of this section refers to the general case of a functional stall */ - //XUD_ProtocolStall(ep0_out, ep0_in): + XUD_SetStall_Out(0); + XUD_SetStall_In(0); + } if (retVal < 0) diff --git a/module_usb_aud_shared/i2c/i2c.h b/module_usb_aud_shared/i2c/i2c.h index 9c10f969..6248e914 100644 --- a/module_usb_aud_shared/i2c/i2c.h +++ b/module_usb_aud_shared/i2c/i2c.h @@ -1,10 +1,4 @@ -// Channel interface -void I2cRegWriteC(int deviceAdrs, int Adrs, int WrData, chanend c); - -int I2cRegReadC(int deviceAdrs, int Adrs, chanend c); - -// Function interface void I2cRegWrite(int deviceAdrs, int Adrs, int WrData, port AUD_SCLK, port AUD_SDIN); int I2cRegRead(int deviceAdrs, int Adrs, port AUD_SCLK, port AUD_SDIN); diff --git a/module_usb_aud_shared/i2c/i2c.xc b/module_usb_aud_shared/i2c/i2c.xc index 48632445..fd252260 100755 --- a/module_usb_aud_shared/i2c/i2c.xc +++ b/module_usb_aud_shared/i2c/i2c.xc @@ -1,28 +1,6 @@ #include #include -int I2cRegReadC(int device, int addr, chanend c) { - int read; - int retVal; - c <: 0; // isWrite - c <: device; - c <: addr; - c <: 1; // only ever one byte - c :> read; - c :> retVal; - return read; -} - -void I2cRegWriteC(int device, int addr, int data, chanend c) { - int retVal; - c <: 1; // isWrite - c <: device; - c <: addr; - c <: 1; // only ever one byte - c <: data; - c :> retVal; -} - int I2cRegRead(int device, int addr, port scl, port sda) { //int Result; diff --git a/module_usb_aud_shared/pll/pll.h b/module_usb_aud_shared/pll/pll.h index bc555fcf..d79ca14f 100644 --- a/module_usb_aud_shared/pll/pll.h +++ b/module_usb_aud_shared/pll/pll.h @@ -1,4 +1,4 @@ -void PllInit(chanend c); +void PllInit(void); -void PllMult(unsigned mult, chanend c); +void PllMult(unsigned mult); diff --git a/module_usb_aud_shared/usb_buffer/decouple.xc b/module_usb_aud_shared/usb_buffer/decouple.xc index b8a5826d..89ef9d61 100644 --- a/module_usb_aud_shared/usb_buffer/decouple.xc +++ b/module_usb_aud_shared/usb_buffer/decouple.xc @@ -1,6 +1,5 @@ #include #include -#include #include "xc_ptr.h" #define NO_INLINE_MIDI_SELECT_HANDLER 1 #include "usb_midi.h" @@ -58,11 +57,8 @@ inline void XUD_Change_ReadyIn_Buffer(XUD_ep e, unsigned bufferPtr, int len) #define BUFF_SIZE_OUT MAX(4 * CLASS_TWO_PACKET_SIZE * NUM_USB_CHAN_OUT, 4 * CLASS_ONE_PACKET_SIZE * MAX_CLASS_ONE_CHAN) #define BUFF_SIZE_IN MAX(4 * CLASS_TWO_PACKET_SIZE * NUM_USB_CHAN_IN, 4 * CLASS_ONE_PACKET_SIZE * MAX_CLASS_ONE_CHAN) #define MAX_USB_AUD_PACKET_SIZE 1028 -//#define OUT_BUFFER_PREFILL (2*4*BUFF_SIZE_OUT/3) -//#define OUT_BUFFER_PREFILL MAX(CLASS_ONE_PACKET_SIZE*3+4,CLASS_TWO_PACKET_SIZE*4+4)*2 -//#define IN_BUFFER_PREFILL MAX(CLASS_ONE_PACKET_SIZE*3+4,CLASS_TWO_PACKET_SIZE*4+4)*2 -#define OUT_BUFFER_PREFILL (MAX(MAX_CLASS_ONE_CHAN*CLASS_ONE_PACKET_SIZE*3+4,NUM_USB_CHAN_OUT*CLASS_TWO_PACKET_SIZE*4+4)*1) -#define IN_BUFFER_PREFILL (MAX(CLASS_ONE_PACKET_SIZE*3+4,CLASS_TWO_PACKET_SIZE*4+4)*2) +#define NUM_PACKETS_PREFILL (1) + //#pragma xta command "add exclusion out_underflow" //#pragma xta command "add exclusion freq_change" //#pragma xta command "add exclusion print_err"is_as @@ -93,6 +89,9 @@ unsigned audioBuffIn[BUFF_SIZE_IN + (MAX_DEVICE_AUD_PACKET_SIZE>>2) + 4]; unsigned inZeroBuff[(MAX_DEVICE_AUD_PACKET_SIZE>>2)+4]; +unsigned g_in_buffer_prefill = 0; +unsigned g_out_buffer_prefill = 0; + unsigned ledVal = 1; unsigned dir = 0; @@ -139,6 +138,41 @@ void led(chanend ?c_led) void GetADCCounts(unsigned samFreq, int &min, int &mid, int &max); + + +/* This function sets the prefill levels for the in and out buffers, + it needs to be changed for a different sample rate or number of channels. + The amount set here is what determines the latency of the buffering. +*/ +static void set_prefills(unsigned int sampFreq) +{ + int usb_speed; + unsigned prefill; + int bytes_per_sample; + int num_channels; + int frame; + int packet_size; + GET_SHARED_GLOBAL(usb_speed, g_curUsbSpeed); + + frame = usb_speed == XUD_SPEED_HS ? 8000 : 1000; + packet_size = ((((sampFreq+frame-1)/frame))+3); + + bytes_per_sample = usb_speed == XUD_SPEED_HS ? 4 : 3; + + GET_SHARED_GLOBAL(num_channels, g_numUsbChanOut); + prefill = ((packet_size * num_channels * bytes_per_sample + 4) * NUM_PACKETS_PREFILL); + SET_SHARED_GLOBAL(g_out_buffer_prefill, prefill); + + GET_SHARED_GLOBAL(num_channels, g_numUsbChanIn); + prefill = ((packet_size * num_channels * bytes_per_sample + 4) * NUM_PACKETS_PREFILL); + SET_SHARED_GLOBAL(g_in_buffer_prefill, prefill); + return; +} + + + + +#if defined(MIDI) || defined(IAP) static inline void swap(xc_ptr &a, xc_ptr &b) { xc_ptr tmp; @@ -147,6 +181,7 @@ static inline void swap(xc_ptr &a, xc_ptr &b) b = tmp; return; } +#endif // shared global midi buffering variables #ifdef MIDI @@ -283,6 +318,15 @@ void handle_audio_request(chanend c_mix_out, chanend ?c_led) if (space_left > (BUFF_SIZE_IN*4/2)) { inOverflow = 0; + // When we come out of overflow we clear the buffer and + // go into underflow and do a prefill again - this is to + // get a low latency and to ensure consistency between + // coming out of underflow or overflow + inUnderflow = 1; + SET_SHARED_GLOBAL(g_aud_to_host_rdptr, + aud_to_host_fifo_start); + SET_SHARED_GLOBAL(g_aud_to_host_wrptr, + aud_to_host_fifo_start); } } else @@ -370,6 +414,7 @@ void handle_audio_request(chanend c_mix_out, chanend ?c_led) if(outUnderflow) { + unsigned prefill; #pragma xta endpoint "out_underflow" /* We're still pre-buffering, send out 0 samps */ for(int i = 0; i < NUM_USB_CHAN_OUT; i++) @@ -384,8 +429,9 @@ void handle_audio_request(chanend c_mix_out, chanend ?c_led) outSamps += BUFF_SIZE_OUT*4; } + GET_SHARED_GLOBAL(prefill, g_out_buffer_prefill); /* If we have a decent number of samples, come out of underflow cond */ - if (outSamps >= (OUT_BUFFER_PREFILL)) + if (outSamps >= prefill) { outUnderflow = 0; } @@ -799,6 +845,8 @@ void decouple(chanend c_mix_out, } #endif + set_prefills(sampFreq); + while(1) { if (!isnull(c_clk_int)) @@ -854,13 +902,14 @@ void decouple(chanend c_mix_out, SET_SHARED_GLOBAL(g_aud_from_host_rdptr, aud_from_host_fifo_start); SET_SHARED_GLOBAL(g_aud_from_host_wrptr, aud_from_host_fifo_start); SET_SHARED_GLOBAL(aud_data_remaining_to_device, 0); - /* Wait for handshake back and pass back up */ chkct(c_mix_out, XS1_CT_END); SET_SHARED_GLOBAL(g_freqChange, 0); asm("outct res[%0],%1"::"r"(buffer_aud_ctl_chan),"r"(XS1_CT_END)); + set_prefills(sampFreq); + ENABLE_INTERRUPTS(); speedRem = 0; @@ -883,6 +932,7 @@ void decouple(chanend c_mix_out, SET_SHARED_GLOBAL(g_aud_to_host_buffer, g_aud_to_host_zeros); SET_SHARED_GLOBAL(g_freqChange, 0); + set_prefills(sampFreq); ENABLE_INTERRUPTS(); } } @@ -959,9 +1009,22 @@ void decouple(chanend c_mix_out, if (space_left >= (BUFF_SIZE_OUT*4/2)) { /* Come out of OUT overflow state */ - outOverflow = 0; + DISABLE_INTERRUPTS(); + outOverflow = 0; + // When we come out of overflow we clear the buffer and + // go into underflow and do a prefill again - this is to + // get a low latency and to ensure consistency between + // coming out of underflow or overflow + outUnderflow = 1; + SET_SHARED_GLOBAL(g_aud_from_host_rdptr, + aud_from_host_fifo_start); + SET_SHARED_GLOBAL(g_aud_from_host_wrptr, + aud_from_host_fifo_start); + SET_SHARED_GLOBAL(aud_data_remaining_to_device, 0); + SET_SHARED_GLOBAL(g_aud_from_host_buffer, aud_from_host_wrptr); XUD_SetReady(aud_from_host_usb_ep, 1); + ENABLE_INTERRUPTS(); #ifdef DEBUG_LEDS led(c_led); #endif @@ -988,6 +1051,7 @@ void decouple(chanend c_mix_out, int aud_to_host_wrptr; int aud_to_host_rdptr; int fill_level; + unsigned prefill; GET_SHARED_GLOBAL(aud_to_host_wrptr, g_aud_to_host_wrptr); GET_SHARED_GLOBAL(aud_to_host_rdptr, g_aud_to_host_rdptr); @@ -997,7 +1061,8 @@ void decouple(chanend c_mix_out, if (fill_level < 0) fill_level += BUFF_SIZE_IN*4; - if (fill_level >= IN_BUFFER_PREFILL) + GET_SHARED_GLOBAL(prefill, g_in_buffer_prefill); + if (fill_level >= prefill) { inUnderflow = 0; SET_SHARED_GLOBAL(g_aud_to_host_buffer, aud_to_host_rdptr);