Merge branch 'iosaudioaccessory' of git://git/apps/sc_usb_audio into iosaudioaccessory

This commit is contained in:
Ross Owen
2011-11-18 11:54:34 +00:00
12 changed files with 301 additions and 136 deletions

View File

@@ -12,9 +12,7 @@
* receiving/transmitting samples * receiving/transmitting samples
* \param c_config An optional channel that will be passed on to the * \param c_config An optional channel that will be passed on to the
* CODEC configuration functions. * 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__ #endif // __audio_h__

View File

@@ -12,7 +12,6 @@
#include <xs1.h> #include <xs1.h>
#include <xclib.h> #include <xclib.h>
#include <print.h> #include <print.h>
#include <assert.h>
#include "clocking.h" #include "clocking.h"
#include "audioports.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 deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_dig_rx)
{ {
unsigned sample; unsigned sample;
#if NUM_USB_CHAN_OUT > 0
unsigned samplesOut[NUM_USB_CHAN_OUT]; unsigned samplesOut[NUM_USB_CHAN_OUT];
#endif
#if NUM_USB_CHAN_IN > 0
unsigned samplesIn[NUM_USB_CHAN_IN]; unsigned samplesIn[NUM_USB_CHAN_IN];
#endif
unsigned samplesInPrev[NUM_USB_CHAN_IN]; unsigned samplesInPrev[NUM_USB_CHAN_IN];
unsigned tmp; unsigned tmp;
unsigned index; unsigned index;
@@ -73,15 +76,14 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_
unsigned prev=0; unsigned prev=0;
int started = 0; int started = 0;
#endif #endif
#ifndef CODEC_SLAVE
int oldtime;
#endif
#if NUM_USB_CHAN_IN > 0
for (int i=0;i<NUM_USB_CHAN_IN;i++) for (int i=0;i<NUM_USB_CHAN_IN;i++)
{ {
samplesIn[i] = 0; samplesIn[i] = 0;
samplesInPrev[i] = 0; samplesInPrev[i] = 0;
} }
#endif
outuint(c_out, 0); outuint(c_out, 0);
/* Check for sample freq change or new samples from mixer*/ /* Check for sample freq change or new samples from mixer*/
@@ -96,16 +98,21 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_
#ifndef MIXER // Interfaces straight to decouple() #ifndef MIXER // Interfaces straight to decouple()
(void) inuint(c_out); (void) inuint(c_out);
#if NUM_USB_CHAN_IN > 0
#pragma loop unroll #pragma loop unroll
for(int i = 0; i < NUM_USB_CHAN_IN; i++) for(int i = 0; i < NUM_USB_CHAN_IN; i++)
{ {
outuint(c_out, samplesIn[i]); outuint(c_out, samplesIn[i]);
} }
#endif
#if NUM_USB_CHAN_OUT > 0
#pragma loop unroll #pragma loop unroll
for(int i = 0; i < NUM_USB_CHAN_OUT; i++) for(int i = 0; i < NUM_USB_CHAN_OUT; i++)
{ {
samplesOut[i] = inuint(c_out); samplesOut[i] = inuint(c_out);
} }
#endif
#else #else
#pragma loop unroll #pragma loop unroll
for(int i = 0; i < NUM_USB_CHAN_OUT; i++) 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; tmp += 33;
#if (I2S_CHANS_DAC != 0) #if (I2S_CHANS_DAC != 0)
#pragma loop unroll
for(int i = 0; i < I2S_WIRES_DAC; i++) for(int i = 0; i < I2S_WIRES_DAC; i++)
{ {
p_i2s_dac[i] @ tmp <: 0; 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]); 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 /* 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 */ * 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() #ifndef MIXER // Interfaces straight to decouple()
(void) inuint(c_out); (void) inuint(c_out);
#if NUM_USB_CHAN_IN > 0
#pragma loop unroll #pragma loop unroll
for(int i = 0; i < NUM_USB_CHAN_IN; i++) for(int i = 0; i < NUM_USB_CHAN_IN; i++)
{ {
outuint(c_out, samplesIn[i]); outuint(c_out, samplesIn[i]);
} }
#endif
#if NUM_USB_CHAN_OUT > 0
#pragma loop unroll #pragma loop unroll
for(int i = 0; i < NUM_USB_CHAN_OUT; i++) for(int i = 0; i < NUM_USB_CHAN_OUT; i++)
{ {
samplesOut[i] = inuint(c_out); samplesOut[i] = inuint(c_out);
} }
#endif
#else #else
#pragma loop unroll #pragma loop unroll
for(int i = 0; i < NUM_USB_CHAN_OUT; i++) 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" #pragma xta endpoint "i2s_output_l"
#if (I2S_CHANS_DAC != 0) #if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0)
#pragma loop unroll #pragma loop unroll
for(int i = 0; i < I2S_CHANS_DAC; i+=2) 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) for(int i = 1; i < I2S_CHANS_ADC; i += 2)
{ {
p_i2s_adc[index++] :> sample; p_i2s_adc[index++] :> sample;
#if NUM_USB_CHAN_IN > 0
samplesIn[i] = bitrev(sample); samplesIn[i] = bitrev(sample);
/* Store the previous left in left */ /* Store the previous left in left */
samplesIn[i-1] = samplesInPrev[i]; samplesIn[i-1] = samplesInPrev[i];
#endif
} }
#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 */ outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX]); /* Forward sample to SPDIF txt thread */
sample = samplesOut[SPDIF_TX_INDEX + 1]; sample = samplesOut[SPDIF_TX_INDEX + 1];
outuint(c_spd_out, sample); /* Forward sample to SPDIF txt thread */ 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; tmp = 0;
#pragma xta endpoint "i2s_output_r" #pragma xta endpoint "i2s_output_r"
#if (I2S_CHANS_DAC != 0) #if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0)
#pragma loop unroll #pragma loop unroll
for(int i = 1; i < I2S_CHANS_DAC; i+=2) 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) for(int i = 1; i < I2S_CHANS_ADC; i += 2)
{ {
p_i2s_adc[index++] :> sample; p_i2s_adc[index++] :> sample;
#if NUM_USB_CHAN_IN > 0
samplesInPrev[i] = bitrev(sample); samplesInPrev[i] = bitrev(sample);
#endif
} }
@@ -496,7 +513,7 @@ static unsigned dummy_deliver(chanend c_out) {
return 0; 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 #ifdef SPDIF
chan c_spdif_out; 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 #endif
/* Initialise master clock generation */ /* Initialise master clock generation */
ClockingInit(c_i2c); ClockingInit();
/* Perform required CODEC/ADC/DAC initialisation */ /* Perform required CODEC/ADC/DAC initialisation */
CodecInit(c_config, c_i2c); CodecInit(c_config);
while(1) 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 ); divide = mClk / ( curSamFreq * 64 );
/* Configure clocking for required master clock */ /* Configure clocking for required master clock */
ClockingConfig(mClk, c_i2c); ClockingConfig(mClk);
if(!firstRun) if(!firstRun)
{ {
@@ -553,7 +570,7 @@ void audio(chanend c_mix_out, chanend ?c_dig_rx, chanend ?c_config, chanend ?c_i
firstRun = 0; firstRun = 0;
/* Configure CODEC/DAC/ADC for SampleFreq/MClk */ /* Configure CODEC/DAC/ADC for SampleFreq/MClk */
CodecConfig(curSamFreq, mClk, c_config, c_i2c); CodecConfig(curSamFreq, mClk, c_config);
/* Configure audio ports */ /* Configure audio ports */
ConfigAudioPorts(divide); ConfigAudioPorts(divide);

View File

@@ -5,10 +5,10 @@
/* Functions that handle master clock generation. These need modifying for an existing design */ /* 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 */ /* 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 */ /* 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. /** Clock generation and digital audio I/O handling.

View File

@@ -6,9 +6,9 @@
/* TODO Are the channel args required? */ /* TODO Are the channel args required? */
/* Any required CODEC initialisation - run once at start up */ /* 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 */ /* 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 #endif

View File

@@ -9,6 +9,27 @@
#include "customdefines.h" #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) #if defined(IO_EXPANSION) && (IO_EXPANSION == 0)
#undef IO_EXPANSION #undef IO_EXPANSION
#endif #endif
@@ -207,18 +228,18 @@
#define ID_CLKSRC_EXT 42 /* Clock source ID (external) */ #define ID_CLKSRC_EXT 42 /* Clock source ID (external) */
#define ID_CLKSRC_ADAT 43 /* Clock source ID (external) */ #define ID_CLKSRC_ADAT 43 /* Clock source ID (external) */
#define ID_XU_MIXSEL 50 #define ID_XU_MIXSEL 50
#define ID_XU_OUT 51 #define ID_XU_OUT 51
#define ID_XU_IN 52 #define ID_XU_IN 52
#define ID_MIXER_1 60 #define ID_MIXER_1 60
#ifndef SERIAL_STR #ifndef SERIAL_STR
#define SERIAL_STR "0000" /* Serial number string */ #define SERIAL_STR "0000" /* Serial number string */
#endif #endif
#define SERIAL_STR_INDEX 0x03 #define SERIAL_STR_INDEX 0x03
#define MANUFACTURER_STR_INDEX 0x01 #define MANUFACTURER_STR_INDEX 0x01
#define PRODUCT_STR_INDEX 0x02 #define PRODUCT_STR_INDEX 0x02
/* Mixer defines */ /* Mixer defines */

View File

@@ -40,8 +40,12 @@ extern unsigned char mixer1Crossbar[];
extern short mixer1Weights[]; extern short mixer1Weights[];
/* Device channel mapping */ /* Device channel mapping */
#if NUM_USB_CHAN_OUT > 0
extern unsigned char channelMapAud[NUM_USB_CHAN_OUT]; extern unsigned char channelMapAud[NUM_USB_CHAN_OUT];
#endif
#if NUM_USB_CHAN_IN > 0
extern unsigned char channelMapUsb[NUM_USB_CHAN_IN]; extern unsigned char channelMapUsb[NUM_USB_CHAN_IN];
#endif
/* Mixer input mapping */ /* Mixer input mapping */
extern unsigned char mixSel[MIX_INPUTS]; extern unsigned char mixSel[MIX_INPUTS];
@@ -52,10 +56,6 @@ extern unsigned int g_curSamFreq;
extern unsigned int g_curSamFreq48000Family; extern unsigned int g_curSamFreq48000Family;
extern unsigned int g_curSamFreqMultiplier; 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 */ /* 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) void storeInt(unsigned char buffer[], int index, int val)
{ {

View File

@@ -170,12 +170,6 @@ unsigned char devQualDesc_Null[] =
#define MIDI_LENGTH (0) #define MIDI_LENGTH (0)
#endif #endif
#ifdef MIXER
#define MIXER_LENGTH (13+1+18)
#else
#define MIXER_LENGTH (0)
#endif
#ifdef IAP #ifdef IAP
#define IAP_LENGTH (30) #define IAP_LENGTH (30)
#else #else
@@ -191,9 +185,18 @@ unsigned char devQualDesc_Null[] =
#endif #endif
#ifdef MIXER #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 #else
#define LEN_XU_MIX (0) #define LEN_XU_MIX (0)
#define MIXER_LENGTH (0)
#endif #endif
#define LEN_CLK (8) #define LEN_CLK (8)
@@ -219,7 +222,7 @@ unsigned char devQualDesc_Null[] =
/* Total length of config descriptor */ /* 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 for number of audio interfaces (+1 for mandatory control interface) */
#define AUDIO_INTERFACES (INPUT_INTERFACES + OUTPUT_INTERFACES + 1) #define AUDIO_INTERFACES (INPUT_INTERFACES + OUTPUT_INTERFACES + 1)
@@ -365,7 +368,7 @@ unsigned char cfgDesc_Audio2[] =
ID_CLKSEL, /* 7 bCSourceID: ID of Clock Entity */ ID_CLKSEL, /* 7 bCSourceID: ID of Clock Entity */
NUM_USB_CHAN_OUT, /* 8 bNrChannels */ NUM_USB_CHAN_OUT, /* 8 bNrChannels */
0,0,0,0, /* 9 bmChannelConfig */ 0,0,0,0, /* 9 bmChannelConfig */
13, /* 13 iChannelNames */ 15, /* 13 iChannelNames */
0x00, 0x00, /* 14 bmControls */ 0x00, 0x00, /* 14 bmControls */
6, /* 16 iTerminal */ 6, /* 16 iTerminal */
@@ -484,7 +487,7 @@ unsigned char cfgDesc_Audio2[] =
ID_CLKSEL, /* 7 bCSourceID: ID of Clock Entity */ ID_CLKSEL, /* 7 bCSourceID: ID of Clock Entity */
NUM_USB_CHAN_IN, /* 8 bNrChannels */ NUM_USB_CHAN_IN, /* 8 bNrChannels */
0,0,0,0, /* 9 bmChannelConfig */ 0,0,0,0, /* 9 bmChannelConfig */
31, /* 13 iChannelNames */ 33, /* 13 iChannelNames */
0x00, 0x00, /* 14 bmControls */ 0x00, 0x00, /* 14 bmControls */
0, /* 16 iTerminal */ 0, /* 16 iTerminal */
@@ -604,7 +607,7 @@ unsigned char cfgDesc_Audio2[] =
2, /* 6 bNrPins */ 2, /* 6 bNrPins */
ID_IT_USB, /* 7 baSourceId(1) */ ID_IT_USB, /* 7 baSourceId(1) */
ID_IT_AUD, /* 7 baSourceId(2) */ ID_IT_AUD, /* 7 baSourceId(2) */
MIX_INPUTS, /* 8+p bNrChannels */ MIX_INPUTS, /* 8+p bNrChannels */
0, /* 9+p bmChannelConfig */ 0, /* 9+p bmChannelConfig */
0, /* 10+p bmChannelConfig */ 0, /* 10+p bmChannelConfig */
0, /* 11+p bmChannelConfig */ 0, /* 11+p bmChannelConfig */
@@ -621,20 +624,72 @@ unsigned char cfgDesc_Audio2[] =
/* N = 144 (18 * 8) */ /* N = 144 (18 * 8) */
/* Mixer Unit Bitmap - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* Mixer Unit Bitmap - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
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 */ CS_INTERFACE, /* 1 bDescriptorType: 0x24 */
0x04, /* bDescriptorSubtype: MIXER_UNIT */ 0x04, /* bDescriptorSubtype: MIXER_UNIT */
ID_MIXER_1, /* Mixer unit id */ ID_MIXER_1, /* Mixer unit id */
0x01, /* Number of input pins */ 0x01, /* Number of input pins */
ID_XU_MIXSEL, /* Connected terminal or unit id for input pin*/ ID_XU_MIXSEL, /* Connected terminal or unit id for input pin*/
0x08, /* Number of mixer output channels */ MAX_MIX_COUNT, /* Number of mixer output channels */
0x00, 0x00, 0x00, 0x00, /* Spacial location ???? */ 0x00, 0x00, 0x00, 0x00, /* Spacial location ???? */
49, /* Channel name index */ 49, /* Channel name index */
0xff, 0xff, 0xff, 0xff, /* Mixer programmable control bitmap */ #if MIX_BMCONTROLS_LEN > 0 /* Mixer programmable control bitmap */
0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, #endif
0xff, 0xff, 0xff, 0xff, #if MIX_BMCONTROLS_LEN > 1
0xff, 0xff, 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 */ 0x00, /* bmControls */
0, /* Mixer unit string descriptor index */ 0, /* Mixer unit string descriptor index */
#endif #endif
@@ -680,7 +735,7 @@ unsigned char cfgDesc_Audio2[] =
0x00, /* 4 bmControls */ 0x00, /* 4 bmControls */
0x01, /* 5 bFormatType */ 0x01, /* 5 bFormatType */
PCM, 0x00, 0x00, 0x00, /* 6:10 bmFormats (note this is a bitmap) */ 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 */ 0,0,0,0, /* 12:14: bmChannelConfig */
13, /* 15 iChannelNames */ 13, /* 15 iChannelNames */
@@ -715,7 +770,7 @@ unsigned char cfgDesc_Audio2[] =
0x81, /* 2 bEndpointAddress (D7: 0:out, 1:in) */ 0x81, /* 2 bEndpointAddress (D7: 0:out, 1:in) */
17, /* 3 bmAttributes (bitmap) */ 17, /* 3 bmAttributes (bitmap) */
4,0, /* 4 wMaxPacketSize */ 4,0, /* 4 wMaxPacketSize */
8, /* 6 bInterval */ 4, /* 6 bInterval. Only values <= 1 frame (8) supported by MS */
#ifdef ADAT_TX #ifdef ADAT_TX
/* Standard AS Interface Descriptor (4.9.1) (Alt) */ /* 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) */ 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 */ 0,0,0,0, /* 12:14: bmChannelConfig */
13, /* 15 iChannelNames */ 15, /* 15 iChannelNames */
/* Type 1 Format Type Descriptor */ /* Type 1 Format Type Descriptor */
0x06, /* 0 bLength (in bytes): 6 */ 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) */ PCM, 0x00, 0x00, 0x00, /* 6:10 bmFormats (note this is a bitmap) */
NUM_USB_CHAN_IN, /* 11 bNrChannels */ NUM_USB_CHAN_IN, /* 11 bNrChannels */
0,0,0,0, /* 12:14: bmChannelConfig */ 0,0,0,0, /* 12:14: bmChannelConfig */
31, /* 15 iChannelNames */ 33, /* 15 iChannelNames */
/* Type 1 Format Type Descriptor */ /* Type 1 Format Type Descriptor */
0x06, /* 0 bLength (in bytes): 6 */ 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) */ PCM, 0x00, 0x00, 0x00, /* 6:10 bmFormats (note this is a bitmap) */
NUM_USB_CHAN_IN - 4, /* 11 bNrChannels */ NUM_USB_CHAN_IN - 4, /* 11 bNrChannels */
0,0,0,0, /* 12:14: bmChannelConfig */ 0,0,0,0, /* 12:14: bmChannelConfig */
31, /* 15 iChannelNames */ 33, /* 15 iChannelNames */
/* Type 1 Format Type Descriptor */ /* Type 1 Format Type Descriptor */
0x06, /* 0 bLength (in bytes): 6 */ 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, /* 2 bDescriptorSubtype : MIDI_IN_JACK subtype. (field size 1 bytes) */
0x02, /* 3 bJackType : EXTERNAL. (field size 1 bytes) */ 0x02, /* 3 bJackType : EXTERNAL. (field size 1 bytes) */
0x02, /* 4 bJackID : ID of this Jack. (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) */ /* Table B-9: MIDI Adapter MIDI OUT Jack Descriptor (Embedded) */
0x09, /* 0 bLength : Size of this descriptor, in bytes. (field size 1 bytes) */ 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, /* 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, /* 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. */ 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 */ /* Table B-11: MIDI Adapter Standard Bulk OUT Endpoint Descriptor */
0x09, /* 0 bLength : Size of this descriptor, in bytes. (field size 1 bytes) */ 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) */ 0x00, /* 4 bNumEndpoints : 0 endpoints. (field size 1 bytes) */
0xFE, /* 5 bInterfaceClass : DFU. (field size 1 bytes) */ 0xFE, /* 5 bInterfaceClass : DFU. (field size 1 bytes) */
0x01, /* 6 bInterfaceSubclass : (field size 1 bytes) */ 0x01, /* 6 bInterfaceSubclass : (field size 1 bytes) */
0x00, /* 7 bInterfaceProtocol : Unused. (field size 1 bytes) */ 0x01, /* 7 bInterfaceProtocol : Unused. (field size 1 bytes) */
12, /* 8 iInterface : Used. (field size 1 bytes) */ 8, /* 8 iInterface : Used. (field size 1 bytes) */
/* Standard DFU class functional descriptor */ #if 0
0x07, /* DFU 1.0 Run-Time DFU Functional Descriptor */
0x07,
0x21, 0x21,
0x07, 0x07,
0xFA, 0xFA,
0x00, 0x00,
0x40, 0x40,
0x00, 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 #endif
#ifdef IAP #ifdef IAP
@@ -1092,7 +1161,7 @@ unsigned char cfgDesc_Audio2[] =
0xFF, /* 5 bInterfaceClass : DFU. (field size 1 bytes) */ 0xFF, /* 5 bInterfaceClass : DFU. (field size 1 bytes) */
0xF0, /* 6 bInterfaceSubclass : (field size 1 bytes) */ 0xF0, /* 6 bInterfaceSubclass : (field size 1 bytes) */
0x00, /* 7 bInterfaceProtocol : Unused. (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 */ /* iAP Bulk OUT Endpoint Descriptor */
0x07, /* 0 bLength : Size of this descriptor, in bytes. (field size 1 bytes) */ 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(S/PDIF Clock), // 10 iClockSource
APPEND_VENDOR_STR(ADAT Clock), // 11 iClockSource APPEND_VENDOR_STR(ADAT Clock), // 11 iClockSource
APPEND_VENDOR_STR(DFU), // 12 iInterface for DFU interface 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 1", // 13 Output channel name place holders - Get customised at runtime based on device config
"Analogue 2", // 14 "Analogue 2", // 14
@@ -1257,7 +1329,7 @@ unsigned char oSpeedCfgDesc[] =
#define STREAMING_INTERFACES (INPUT_INTERFACES + OUTPUT_INTERFACES) #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 #ifdef AUDIO_CLASS_FALLBACK
unsigned char cfgDesc_Audio1[] = unsigned char cfgDesc_Audio1[] =
{ {
@@ -1536,19 +1608,19 @@ unsigned char cfgDesc_Audio1[] =
0x00, 0x00, /* Unused */ 0x00, 0x00, /* Unused */
#endif #endif
#ifdef DFU
/* Standard DFU class Interface descriptor */ /* Standard DFU class Interface descriptor */
0x09, /* 0 bLength : Size of this descriptor, in bytes. (field size 1 bytes) */ 0x09, /* 0 bLength : Size of this descriptor, in bytes. (field size 1 bytes) */
0x04, /* 1 bDescriptorType : INTERFACE descriptor. (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, /* 3 bAlternateSetting : Index of this setting. (field size 1 bytes) */
0x00, /* 4 bNumEndpoints : 0 endpoints. (field size 1 bytes) */ 0x00, /* 4 bNumEndpoints : 0 endpoints. (field size 1 bytes) */
0xFE, /* 5 bInterfaceClass : DFU. (field size 1 bytes) */ 0xFE, /* 5 bInterfaceClass : DFU. (field size 1 bytes) */
0x01, /* 6 bInterfaceSubclass : (field size 1 bytes) */ 0x01, /* 6 bInterfaceSubclass : (field size 1 bytes) */
0x00, /* 7 bInterfaceProtocol : Unused. (field size 1 bytes) */ 0x01, /* 7 bInterfaceProtocol : Unused. (field size 1 bytes) */
0x08, /* 8 iInterface : 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, 0x07,
0x21, 0x21,
0x07, 0x07,
@@ -1556,6 +1628,18 @@ unsigned char cfgDesc_Audio1[] =
0x00, 0x00,
0x40, 0x40,
0x00 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
}; };

View File

@@ -21,7 +21,7 @@
#include "dfu_types.h" #include "dfu_types.h"
#include "xc_ptr.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. * Of course, OSX is unaffected.
*/ */
#if ((AUDIO_CLASS==1) || defined(AUDIO_CLASS_FALLBACK)) && defined(DFU) #if ((AUDIO_CLASS==1) || defined(AUDIO_CLASS_FALLBACK)) && defined(DFU)
@@ -70,9 +70,12 @@ short mixer1Weights[18*8];
//#define MAX_MIX_COUNT 8 //#define MAX_MIX_COUNT 8
unsigned char channelMap[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT]; 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]; unsigned char channelMapAud[NUM_USB_CHAN_OUT];
#endif
#if NUM_USB_CHAN_IN > 0
unsigned char channelMapUsb[NUM_USB_CHAN_IN]; unsigned char channelMapUsb[NUM_USB_CHAN_IN];
#endif
unsigned char mixSel[MIX_INPUTS]; unsigned char mixSel[MIX_INPUTS];
#endif #endif
@@ -180,16 +183,20 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
mixer1Weights[54] = 0; mixer1Weights[54] = 0;
mixer1Weights[63] = 0; mixer1Weights[63] = 0;
#if NUM_USB_CHAN_OUT > 0
/* Setup up audio output channel mapping */ /* Setup up audio output channel mapping */
for(int i = 0; i < NUM_USB_CHAN_OUT; i++) for(int i = 0; i < NUM_USB_CHAN_OUT; i++)
{ {
channelMapAud[i] = i; channelMapAud[i] = i;
} }
#endif
#if NUM_USB_CHAN_IN > 0
for(int i = 0; i < NUM_USB_CHAN_IN; i++) for(int i = 0; i < NUM_USB_CHAN_IN; i++)
{ {
channelMapUsb[i] = i + NUM_USB_CHAN_OUT; channelMapUsb[i] = i + NUM_USB_CHAN_OUT;
} }
#endif
/* Set up channel mapping default */ /* 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 /* Build up channel string table - By default all channels are marked as analogue
* TODO We really want to do this an build time... */ * TODO We really want to do this an build time... */
#if defined(SPDIF_RX) && (SPDIF_RX_INDEX != 0) #if defined(SPDIF_RX) && (SPDIF_RX_INDEX != 0)
safestrcpy(strDescs_Audio2[SPDIF_RX_INDEX + 31], "S/PDIF 1"); safestrcpy(strDescs_Audio2[SPDIF_RX_INDEX + 33], "S/PDIF 1");
safestrcpy(strDescs_Audio2[SPDIF_RX_INDEX + 32], "S/PDIF 2"); safestrcpy(strDescs_Audio2[SPDIF_RX_INDEX + 34], "S/PDIF 2");
#endif #endif
#if defined(ADAT_RX) && (ADAT_RX_INDEX != 0) #if defined(ADAT_RX) && (ADAT_RX_INDEX != 0)
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 31], "ADAT 1"); safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 33], "ADAT 1");
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 32], "ADAT 2"); safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 34], "ADAT 2");
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 33], "ADAT 3"); safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 35], "ADAT 3");
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 34], "ADAT 4"); safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 36], "ADAT 4");
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 35], "ADAT 5"); safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 37], "ADAT 5");
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 36], "ADAT 6"); safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 38], "ADAT 6");
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 37], "ADAT 7"); safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 39], "ADAT 7");
safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 38], "ADAT 8"); safestrcpy(strDescs_Audio2[ADAT_RX_INDEX + 40], "ADAT 8");
#endif #endif
#if defined(SPDIF) && (SPDIF_TX_INDEX != 0) /* "Analogue naming gets priority */ #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 + 15], "S/PDIF 1");
safestrcpy(strDescs_Audio2[SPDIF_TX_INDEX + 14], "S/PDIF 2"); safestrcpy(strDescs_Audio2[SPDIF_TX_INDEX + 16], "S/PDIF 2");
#endif #endif
#if defined(ADAT_TX) && (ADAT_TX_INDEX != 0) #if defined(ADAT_TX) && (ADAT_TX_INDEX != 0)
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 13], "ADAT 1"); safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 15], "ADAT 1");
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 14], "ADAT 2"); safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 16], "ADAT 2");
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 15], "ADAT 3"); safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 17], "ADAT 3");
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 16], "ADAT 4"); safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 18], "ADAT 4");
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 17], "ADAT 5"); safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 19], "ADAT 5");
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 18], "ADAT 6"); safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 20], "ADAT 6");
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 19], "ADAT 7"); safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 21], "ADAT 7");
safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 20], "ADAT 8"); safestrcpy(strDescs_Audio2[ADAT_TX_INDEX + 22], "ADAT 8");
#endif #endif
#ifdef VENDOR_AUDIO_REQS #ifdef VENDOR_AUDIO_REQS
@@ -494,7 +501,6 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
// Handshake // Handshake
//chkct(c_audioControl, XS1_CT_END); //chkct(c_audioControl, XS1_CT_END);
//printint(8);
break; break;
#endif #endif
@@ -736,7 +742,7 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
device_reboot(); 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; retVal = 0;
} }
/* Check for: - Audio CONTROL interface request - always 0, note we check for DFU first /* 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)))) || (request == CLASS_ENDPOINT_REQUEST && ((interfaceNum == 0x82) || (interfaceNum == 0x01))))
{ {
#endif #endif
#if (AUDIO_CLASS == 2) && defined(AUDIO_CLASS_FALLBACK) #if (AUDIO_CLASS == 2) && defined(AUDIO_CLASS_FALLBACK)
if(g_curUsbSpeed == XUD_SPEED_HS) if(g_curUsbSpeed == XUD_SPEED_HS)
{ {
@@ -780,7 +787,6 @@ void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
break; break;
default: default:
// TODO: STALL
//printstr("unrecognised request\n"); //printstr("unrecognised request\n");
//printhexln(sp.bRequest); //printhexln(sp.bRequest);
//printhexln(sp.bmRequestType.Type); //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 transfer, and the STALL condition terminates at the beginning of the
next control transfer (Setup). The remainder of this section refers to next control transfer (Setup). The remainder of this section refers to
the general case of a functional stall */ the general case of a functional stall */
//XUD_ProtocolStall(ep0_out, ep0_in): XUD_SetStall_Out(0);
XUD_SetStall_In(0);
} }
if (retVal < 0) if (retVal < 0)

View File

@@ -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); 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); int I2cRegRead(int deviceAdrs, int Adrs, port AUD_SCLK, port AUD_SDIN);

View File

@@ -1,28 +1,6 @@
#include <xs1.h> #include <xs1.h>
#include <print.h> #include <print.h>
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 I2cRegRead(int device, int addr, port scl, port sda)
{ {
//int Result; //int Result;

View File

@@ -1,4 +1,4 @@
void PllInit(chanend c); void PllInit(void);
void PllMult(unsigned mult, chanend c); void PllMult(unsigned mult);

View File

@@ -1,6 +1,5 @@
#include <xs1.h> #include <xs1.h>
#include <print.h> #include <print.h>
#include <assert.h>
#include "xc_ptr.h" #include "xc_ptr.h"
#define NO_INLINE_MIDI_SELECT_HANDLER 1 #define NO_INLINE_MIDI_SELECT_HANDLER 1
#include "usb_midi.h" #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_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 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 MAX_USB_AUD_PACKET_SIZE 1028
//#define OUT_BUFFER_PREFILL (2*4*BUFF_SIZE_OUT/3) #define NUM_PACKETS_PREFILL (1)
//#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)
//#pragma xta command "add exclusion out_underflow" //#pragma xta command "add exclusion out_underflow"
//#pragma xta command "add exclusion freq_change" //#pragma xta command "add exclusion freq_change"
//#pragma xta command "add exclusion print_err"is_as //#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 inZeroBuff[(MAX_DEVICE_AUD_PACKET_SIZE>>2)+4];
unsigned g_in_buffer_prefill = 0;
unsigned g_out_buffer_prefill = 0;
unsigned ledVal = 1; unsigned ledVal = 1;
unsigned dir = 0; unsigned dir = 0;
@@ -139,6 +138,41 @@ void led(chanend ?c_led)
void GetADCCounts(unsigned samFreq, int &min, int &mid, int &max); 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) static inline void swap(xc_ptr &a, xc_ptr &b)
{ {
xc_ptr tmp; xc_ptr tmp;
@@ -147,6 +181,7 @@ static inline void swap(xc_ptr &a, xc_ptr &b)
b = tmp; b = tmp;
return; return;
} }
#endif
// shared global midi buffering variables // shared global midi buffering variables
#ifdef MIDI #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)) if (space_left > (BUFF_SIZE_IN*4/2))
{ {
inOverflow = 0; 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 else
@@ -370,6 +414,7 @@ void handle_audio_request(chanend c_mix_out, chanend ?c_led)
if(outUnderflow) if(outUnderflow)
{ {
unsigned prefill;
#pragma xta endpoint "out_underflow" #pragma xta endpoint "out_underflow"
/* We're still pre-buffering, send out 0 samps */ /* We're still pre-buffering, send out 0 samps */
for(int i = 0; i < NUM_USB_CHAN_OUT; i++) 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; 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 we have a decent number of samples, come out of underflow cond */
if (outSamps >= (OUT_BUFFER_PREFILL)) if (outSamps >= prefill)
{ {
outUnderflow = 0; outUnderflow = 0;
} }
@@ -799,6 +845,8 @@ void decouple(chanend c_mix_out,
} }
#endif #endif
set_prefills(sampFreq);
while(1) while(1)
{ {
if (!isnull(c_clk_int)) 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_rdptr, aud_from_host_fifo_start);
SET_SHARED_GLOBAL(g_aud_from_host_wrptr, 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(aud_data_remaining_to_device, 0);
/* Wait for handshake back and pass back up */ /* Wait for handshake back and pass back up */
chkct(c_mix_out, XS1_CT_END); chkct(c_mix_out, XS1_CT_END);
SET_SHARED_GLOBAL(g_freqChange, 0); SET_SHARED_GLOBAL(g_freqChange, 0);
asm("outct res[%0],%1"::"r"(buffer_aud_ctl_chan),"r"(XS1_CT_END)); asm("outct res[%0],%1"::"r"(buffer_aud_ctl_chan),"r"(XS1_CT_END));
set_prefills(sampFreq);
ENABLE_INTERRUPTS(); ENABLE_INTERRUPTS();
speedRem = 0; 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_aud_to_host_buffer, g_aud_to_host_zeros);
SET_SHARED_GLOBAL(g_freqChange, 0); SET_SHARED_GLOBAL(g_freqChange, 0);
set_prefills(sampFreq);
ENABLE_INTERRUPTS(); ENABLE_INTERRUPTS();
} }
} }
@@ -959,9 +1009,22 @@ void decouple(chanend c_mix_out,
if (space_left >= (BUFF_SIZE_OUT*4/2)) if (space_left >= (BUFF_SIZE_OUT*4/2))
{ {
/* Come out of OUT overflow state */ /* 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); SET_SHARED_GLOBAL(g_aud_from_host_buffer, aud_from_host_wrptr);
XUD_SetReady(aud_from_host_usb_ep, 1); XUD_SetReady(aud_from_host_usb_ep, 1);
ENABLE_INTERRUPTS();
#ifdef DEBUG_LEDS #ifdef DEBUG_LEDS
led(c_led); led(c_led);
#endif #endif
@@ -988,6 +1051,7 @@ void decouple(chanend c_mix_out,
int aud_to_host_wrptr; int aud_to_host_wrptr;
int aud_to_host_rdptr; int aud_to_host_rdptr;
int fill_level; int fill_level;
unsigned prefill;
GET_SHARED_GLOBAL(aud_to_host_wrptr, g_aud_to_host_wrptr); GET_SHARED_GLOBAL(aud_to_host_wrptr, g_aud_to_host_wrptr);
GET_SHARED_GLOBAL(aud_to_host_rdptr, g_aud_to_host_rdptr); 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) if (fill_level < 0)
fill_level += BUFF_SIZE_IN*4; 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; inUnderflow = 0;
SET_SHARED_GLOBAL(g_aud_to_host_buffer, aud_to_host_rdptr); SET_SHARED_GLOBAL(g_aud_to_host_buffer, aud_to_host_rdptr);