Merge smart_mic_plus -> master
This commit is contained in:
@@ -1,10 +1,27 @@
|
||||
sc_usb_audio Change Log
|
||||
=======================
|
||||
|
||||
7.0.0
|
||||
------
|
||||
|
||||
6.30.0
|
||||
------
|
||||
- RESOLVED: Number of PDM microphone channels configured now based on
|
||||
NUM_PDM_MICS define (previously hard-coded)
|
||||
- RESOLVED: PDM microphone clock divide now based MCLK defines (previously hard-coded)
|
||||
- CHANGE: Second microphone decimation core only run if NUM_PDM_MICS > 4
|
||||
|
||||
6.20.0
|
||||
------
|
||||
- RESOLVED: Intra-frame sample delays of 1/2 samples on input streaming in TDM mode
|
||||
- RESOLVED: Build issue with NUM_USB_CHAN_OUT set to 0 and MIXER enabled
|
||||
- RESOLVED: SPDIF_TX_INDEX not defined build warning only emitted when SPDIF_TX defined
|
||||
- RESOLVED: Failure to enter DFU mode when configured without input volume control
|
||||
|
||||
6.19.0
|
||||
------
|
||||
- RESOLVED: SPDIF_TX_INDEX not defined build warning only emitted when SPDIF_TX defined
|
||||
- RESOLVED: Failure to enter DFU mode when configured without input volume control
|
||||
- RESOLVED: SPDIF_TX_INDEX not defined build warning only emitted when SPDIF_TX defined
|
||||
- RESOLVED: Failure to enter DFU mode when configured without input volume control
|
||||
|
||||
6.18.1
|
||||
------
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
USB Audio Shared
|
||||
................
|
||||
|
||||
:Latest release: 6.18.1alpha0
|
||||
:Latest release: 6.19.0alpha0
|
||||
:Maintainer: xross
|
||||
:Description: USB Audio Shared Components. For use in the XMOS USB Audio Refererence Designs.
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ static int DFU_Dnload(unsigned int request_len, unsigned int block_num, const un
|
||||
|
||||
static int DFU_Upload(unsigned int request_len, unsigned int block_num, unsigned data_out[16], unsigned &DFU_state)
|
||||
{
|
||||
unsigned int cmd_data[16];
|
||||
unsigned int cmd_data[1];
|
||||
unsigned int firstRead = 0;
|
||||
|
||||
// Start at flash address 0
|
||||
@@ -236,8 +236,8 @@ static int DFU_Upload(unsigned int request_len, unsigned int block_num, unsigned
|
||||
{
|
||||
cmd_data[0] = !firstRead;
|
||||
|
||||
// Read whole (256bytes) page from the image on the flash
|
||||
flash_cmd_read_page((cmd_data, unsigned char[64]));
|
||||
// Read whole (256bytes) page from the image on the flash into a memory buffer
|
||||
flash_cmd_read_page((cmd_data, unsigned char[1]));
|
||||
subPagesLeft = 4;
|
||||
|
||||
// If address out of range, terminate!
|
||||
|
||||
@@ -12,10 +12,11 @@
|
||||
#include <xs1.h>
|
||||
#include <xclib.h>
|
||||
#include <xs1_su.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "devicedefines.h"
|
||||
|
||||
#include "dfu_interface.h"
|
||||
#include "xua_audio.h"
|
||||
#include "audioports.h"
|
||||
#include "audiohw.h"
|
||||
#ifdef SPDIF_TX
|
||||
@@ -23,22 +24,50 @@
|
||||
#endif
|
||||
#ifdef ADAT_TX
|
||||
#include "adat_tx.h"
|
||||
|
||||
#ifndef ADAT_TX_USE_SHARED_BUFF
|
||||
#error Designed for ADAT tx shared buffer mode ONLY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "xua_audio.h"
|
||||
|
||||
#include "commands.h"
|
||||
#include "xc_ptr.h"
|
||||
|
||||
/* TODO 32 is max expected channels */
|
||||
static unsigned samplesOut[32];
|
||||
#define MAX(x,y) ((x)>(y) ? (x) : (y))
|
||||
|
||||
/* Two buffers for ADC data to allow for DAC and ADC ports being offset */
|
||||
static unsigned samplesIn[2][32];
|
||||
static unsigned samplesOut[MAX(NUM_USB_CHAN_OUT, I2S_CHANS_DAC)];
|
||||
|
||||
#ifndef ADAT_RX
|
||||
#define ADAT_RX 0
|
||||
#endif
|
||||
|
||||
#ifndef SPDIF_RX
|
||||
#define SPDIF_RX 0
|
||||
#endif
|
||||
|
||||
/* Two buffers for ADC data to allow for DAC and ADC I2S ports being offset */
|
||||
#define IN_CHAN_COUNT (I2S_CHANS_ADC + NUM_PDM_MICS + (8*ADAT_RX) + (2*SPDIF_RX))
|
||||
|
||||
static unsigned samplesIn[2][MAX(NUM_USB_CHAN_IN, IN_CHAN_COUNT)];
|
||||
|
||||
#if defined(ADAT_RX) && (ADAT_RX ==0)
|
||||
#undef ADAT_RX
|
||||
#endif
|
||||
|
||||
#if defined(SPDIF_RX) && (SPDIF_RX ==0)
|
||||
#undef SPDIF_RX
|
||||
#endif
|
||||
|
||||
static int downsamplingCounter = 0;
|
||||
#if (I2S_DOWNSAMPLE_FACTOR > 1)
|
||||
#include "src.h"
|
||||
static union ds3Data
|
||||
{
|
||||
long long doubleWordAlignmentEnsured;
|
||||
/* [Number of I2S channels][Number of samples/phases][Taps per phase] */
|
||||
int32_t delayLine[I2S_DOWNSAMPLE_CHANS][I2S_DOWNSAMPLE_FACTOR][24];
|
||||
} ds3Data;
|
||||
static int64_t ds3Sum[I2S_DOWNSAMPLE_CHANS];
|
||||
#endif
|
||||
|
||||
#if (DSD_CHANS_DAC != 0)
|
||||
extern buffered out port:32 p_dsd_dac[DSD_CHANS_DAC];
|
||||
@@ -222,7 +251,7 @@ static inline void TransferAdatTxSamples(chanend c_adat_out, const unsigned samp
|
||||
}
|
||||
#endif
|
||||
|
||||
/* sampsFromUsbToAudio: The sample frame the device has recived from the host and is going to play to the output audio interfaces */
|
||||
/* sampsFromUsbToAudio: The sample frame the device has received from the host and is going to play to the output audio interfaces */
|
||||
/* sampsFromAudioToUsb: The sample frame that was received from the audio interfaces and that the device is going to send to the host */
|
||||
void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[], client audManage_if i_audMan);
|
||||
|
||||
@@ -276,7 +305,7 @@ static inline unsigned DoSampleTransfer(chanend c_out, const int readBuffNo, con
|
||||
for(int i = 0; i < NUM_USB_CHAN_IN; i++)
|
||||
{
|
||||
outuint(c_out, samplesIn[readBuffNo][i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -468,6 +497,10 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (I2S_DOWNSAMPLE_FACTOR > 1)
|
||||
memset(&ds3Data.delayLine, 0, sizeof ds3Data);
|
||||
#endif
|
||||
|
||||
unsigned command = DoSampleTransfer(c_out, readBuffNo, underflowWord, i_audMan);
|
||||
|
||||
#ifdef ADAT_TX
|
||||
@@ -482,6 +515,8 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
|
||||
return command;
|
||||
}
|
||||
|
||||
downsamplingCounter = 0;
|
||||
|
||||
InitPorts(divide);
|
||||
|
||||
/* TODO In master mode, the i/o loop assumes L/RCLK = 32bit clocks. We should check this every interation
|
||||
@@ -597,11 +632,17 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#if (I2S_DOWNSAMPLE_FACTOR > 1)
|
||||
if (0 == downsamplingCounter)
|
||||
{
|
||||
memset(&ds3Sum, 0, sizeof ds3Sum);
|
||||
}
|
||||
#endif
|
||||
#if (I2S_CHANS_ADC != 0)
|
||||
/* Input previous L sample into L in buffer */
|
||||
index = 0;
|
||||
/* First input (i.e. frameCount == 0) we read last ADC channel of previous frame.. */
|
||||
unsigned buffIndex = (frameCount < 3) ? !readBuffNo : readBuffNo;
|
||||
unsigned buffIndex = (frameCount > 1) ? !readBuffNo : readBuffNo;
|
||||
|
||||
#pragma loop unroll
|
||||
/* First time around we get channel 7 of TDM8 */
|
||||
@@ -614,6 +655,26 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
|
||||
|
||||
/* Note the use of readBuffNo changes based on frameCount */
|
||||
samplesIn[buffIndex][((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i] = bitrev(sample); // channels 0, 2, 4.. on each line.
|
||||
#if (I2S_DOWNSAMPLE_FACTOR > 1)
|
||||
if ((I2S_DOWNSAMPLE_FACTOR - 1) == downsamplingCounter)
|
||||
{
|
||||
samplesIn[readBuffNo][((frameCount-2)&(I2S_CHANS_PER_FRAME-1))] =
|
||||
src_ds3_voice_add_final_sample(
|
||||
ds3Sum[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i],
|
||||
ds3Data.delayLine[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i][downsamplingCounter],
|
||||
src_ff3v_ds3_voice_coefs[downsamplingCounter],
|
||||
samplesIn[readBuffNo][((frameCount-2)&(I2S_CHANS_PER_FRAME-1))]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ds3Sum[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i] =
|
||||
src_ds3_voice_add_sample(
|
||||
ds3Sum[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i],
|
||||
ds3Data.delayLine[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i][downsamplingCounter],
|
||||
src_ff3v_ds3_voice_coefs[downsamplingCounter],
|
||||
samplesIn[readBuffNo][((frameCount-2)&(I2S_CHANS_PER_FRAME-1))]);
|
||||
}
|
||||
#endif // (I2S_DOWNSAMPLE_FACTOR > 1)
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -687,20 +748,22 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
|
||||
#endif
|
||||
|
||||
#if (NUM_PDM_MICS > 0)
|
||||
/* Get samples from PDM->PCM comverter */
|
||||
c_pdm_pcm <: 1;
|
||||
master
|
||||
if ((I2S_DOWNSAMPLE_FACTOR - 1) == downsamplingCounter)
|
||||
{
|
||||
/* Get samples from PDM->PCM comverter */
|
||||
c_pdm_pcm <: 1;
|
||||
master
|
||||
{
|
||||
#pragma loop unroll
|
||||
for(int i = 0; i < NUM_PDM_MICS; i++)
|
||||
{
|
||||
c_pdm_pcm :> samplesIn[readBuffNo][i];
|
||||
}
|
||||
for(int i = PDM_MIC_INDEX; i < (NUM_PDM_MICS + PDM_MIC_INDEX); i++)
|
||||
{
|
||||
c_pdm_pcm :> samplesIn[readBuffNo][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if (I2S_CHANS_ADC != 0)
|
||||
index = 0;
|
||||
/* Channels 0, 2, 4.. on each line */
|
||||
@@ -712,6 +775,26 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
|
||||
asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++]));
|
||||
|
||||
samplesIn[buffIndex][((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i] = bitrev(sample); // channels 1, 3, 5.. on each line.
|
||||
#if ((I2S_DOWNSAMPLE_FACTOR > 1) && !I2S_DOWNSAMPLE_MONO)
|
||||
if ((I2S_DOWNSAMPLE_FACTOR - 1) == downsamplingCounter)
|
||||
{
|
||||
samplesIn[buffIndex][((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i] =
|
||||
src_ds3_voice_add_final_sample(
|
||||
ds3Sum[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i],
|
||||
ds3Data.delayLine[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i][downsamplingCounter],
|
||||
src_ff3v_ds3_voice_coefs[downsamplingCounter],
|
||||
samplesIn[readBuffNo][((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ds3Sum[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i] =
|
||||
src_ds3_voice_add_sample(
|
||||
ds3Sum[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i],
|
||||
ds3Data.delayLine[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i][downsamplingCounter],
|
||||
src_ff3v_ds3_voice_coefs[downsamplingCounter],
|
||||
samplesIn[readBuffNo][((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i]);
|
||||
}
|
||||
#endif // ((I2S_DOWNSAMPLE_FACTOR > 1) && !I2S_DOWNSAMPLE_MONO)
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -797,22 +880,30 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
|
||||
if(frameCount == I2S_CHANS_PER_FRAME)
|
||||
#endif
|
||||
{
|
||||
/* Do samples transfer */
|
||||
/* The below looks a bit odd but forces the compiler to inline twice */
|
||||
unsigned command;
|
||||
if(readBuffNo)
|
||||
command = DoSampleTransfer(c_out, 1, underflowWord, i_audMan);
|
||||
else
|
||||
command = DoSampleTransfer(c_out, 0, underflowWord, i_audMan);
|
||||
|
||||
if(command)
|
||||
if ((I2S_DOWNSAMPLE_FACTOR - 1) == downsamplingCounter)
|
||||
{
|
||||
return command;
|
||||
}
|
||||
/* Do samples transfer */
|
||||
/* The below looks a bit odd but forces the compiler to inline twice */
|
||||
unsigned command;
|
||||
if(readBuffNo)
|
||||
command = DoSampleTransfer(c_out, 1, underflowWord, i_audMan);
|
||||
else
|
||||
command = DoSampleTransfer(c_out, 0, underflowWord, i_audMan);
|
||||
|
||||
/* Reset frame counter and flip the ADC buffer */
|
||||
frameCount = 0;
|
||||
readBuffNo = !readBuffNo;
|
||||
if(command)
|
||||
{
|
||||
return command;
|
||||
}
|
||||
|
||||
/* Reset frame counter and flip the ADC buffer */
|
||||
downsamplingCounter = 0;
|
||||
frameCount = 0;
|
||||
readBuffNo = !readBuffNo;
|
||||
}
|
||||
else
|
||||
{
|
||||
++downsamplingCounter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -927,7 +1018,7 @@ chanend ?c_config, chanend ?c
|
||||
unsigned adatMultiple = 0;
|
||||
#endif
|
||||
|
||||
unsigned curSamFreq = DEFAULT_FREQ;
|
||||
unsigned curSamFreq = DEFAULT_FREQ * I2S_DOWNSAMPLE_FACTOR;
|
||||
unsigned curSamRes_DAC = STREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS; /* Default to something reasonable */
|
||||
unsigned curSamRes_ADC = STREAM_FORMAT_INPUT_1_RESOLUTION_BITS; /* Default to something reasonable - note, currently this never changes*/
|
||||
unsigned command;
|
||||
@@ -1082,7 +1173,7 @@ chanend ?c_config, chanend ?c
|
||||
{
|
||||
/* TODO wait for good mclk instead of delay */
|
||||
/* No delay for DFU modes */
|
||||
if ((curSamFreq != AUDIO_REBOOT_FROM_DFU) && (curSamFreq != AUDIO_STOP_FOR_DFU) && command)
|
||||
if (((curSamFreq / I2S_DOWNSAMPLE_FACTOR) != AUDIO_REBOOT_FROM_DFU) && ((curSamFreq / I2S_DOWNSAMPLE_FACTOR) != AUDIO_STOP_FOR_DFU) && command)
|
||||
{
|
||||
#if 0
|
||||
/* User should ensure MCLK is stable in AudioHwConfig */
|
||||
@@ -1125,7 +1216,7 @@ chanend ?c_config, chanend ?c
|
||||
|
||||
#if NUM_PDM_MICS > 0
|
||||
/* Send decimation factor to PDM task(s) */
|
||||
c_pdm_in <: curSamFreq;
|
||||
c_pdm_in <: curSamFreq / I2S_DOWNSAMPLE_FACTOR;
|
||||
#endif
|
||||
|
||||
#ifdef ADAT_TX
|
||||
@@ -1158,15 +1249,12 @@ chanend ?c_config, chanend ?c
|
||||
#if (NUM_PDM_MICS > 0)
|
||||
c_pdm_in,
|
||||
#endif
|
||||
null
|
||||
//#ifdef RUN_DSP_TASK
|
||||
, i_audMan
|
||||
//#endif
|
||||
null, i_audMan
|
||||
);
|
||||
|
||||
if(command == SET_SAMPLE_FREQ)
|
||||
{
|
||||
curSamFreq = inuint(c_mix_out);
|
||||
curSamFreq = inuint(c_mix_out) * I2S_DOWNSAMPLE_FACTOR;
|
||||
}
|
||||
else if(command == SET_STREAM_FORMAT_OUT)
|
||||
{
|
||||
@@ -1179,7 +1267,7 @@ chanend ?c_config, chanend ?c
|
||||
}
|
||||
|
||||
/* Currently no more audio will happen after this point */
|
||||
if (curSamFreq == AUDIO_STOP_FOR_DFU)
|
||||
if ((curSamFreq / I2S_DOWNSAMPLE_FACTOR) == AUDIO_STOP_FOR_DFU)
|
||||
{
|
||||
outct(c_mix_out, XS1_CT_END);
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
/* Default implentation for UserBufferManagement() */
|
||||
void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[]
|
||||
, unsigned i_dsp
|
||||
, unsigned i_audMan
|
||||
) __attribute__ ((weak));
|
||||
void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[]
|
||||
, unsigned i_dsp
|
||||
, unsigned i_audMan
|
||||
)
|
||||
{
|
||||
/* Do nothing */
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
#ifndef __audio_h__
|
||||
#define __audio_h__
|
||||
|
||||
//#include "devicedefines.h"
|
||||
#include "dfu_interface.h"
|
||||
//#include "xua_dsp.h"
|
||||
|
||||
|
||||
typedef interface audManage_if
|
||||
{
|
||||
@@ -18,8 +15,6 @@ typedef interface audManage_if
|
||||
} audManage_if;
|
||||
|
||||
|
||||
|
||||
|
||||
/** The audio driver thread.
|
||||
*
|
||||
* This function drives I2S ports and handles samples to/from other digital
|
||||
@@ -46,9 +41,7 @@ void audio(chanend c_in,
|
||||
#if (NUM_PDM_MICS > 0)
|
||||
, chanend c_pdm_in
|
||||
#endif
|
||||
//#ifdef RUN_DSP_TASK
|
||||
, client audManage_if i_audMan
|
||||
//#endif
|
||||
);
|
||||
|
||||
void SpdifTxWrapper(chanend c_spdif_tx);
|
||||
|
||||
@@ -121,6 +121,41 @@
|
||||
#define I2S_WIRES_ADC (I2S_CHANS_ADC / I2S_CHANS_PER_FRAME)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Incoming I2S (device to host) channels can be downsampled by a factor of 3.
|
||||
*
|
||||
* Default: 1 i.e. downsampling is disabled.
|
||||
*/
|
||||
#ifndef I2S_DOWNSAMPLE_FACTOR
|
||||
#define I2S_DOWNSAMPLE_FACTOR (1)
|
||||
#else
|
||||
#if (I2S_DOWNSAMPLE_FACTOR != 3) && (I2S_DOWNSAMPLE_FACTOR != 1)
|
||||
#error Unsupported I2S downsampling configuration
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Only downsample one channel per I2S frame.
|
||||
*
|
||||
* Default: 0 i.e. mono mode is disabled, all channels will be downsampled.
|
||||
*/
|
||||
#ifndef I2S_DOWNSAMPLE_MONO
|
||||
#define I2S_DOWNSAMPLE_MONO (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Number of incoming (device to host) I2S channels to downsample.
|
||||
*
|
||||
* Default: The number of I2S incoming channels, or half this if mono downsampling is enabled.
|
||||
*/
|
||||
#if (I2S_DOWNSAMPLE_MONO == 1)
|
||||
#define I2S_DOWNSAMPLE_CHANS (I2S_CHANS_ADC / 2)
|
||||
#if ((I2S_DOWNSAMPLE_FACTOR > 1) && (I2S_MODE_TDM == 1))
|
||||
#error Mono I2S downsampling is not avaliable in TDM mode
|
||||
#endif
|
||||
#else
|
||||
#define I2S_DOWNSAMPLE_CHANS I2S_CHANS_ADC
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Max supported sample frequency for device (Hz). Default: 192000
|
||||
@@ -468,14 +503,14 @@
|
||||
* @brief Device firmware version number in Binary Coded Decimal format: 0xJJMN where JJ: major, M: minor, N: sub-minor version number.
|
||||
*/
|
||||
#ifndef BCD_DEVICE_J
|
||||
#define BCD_DEVICE_J 6
|
||||
#define BCD_DEVICE_J 7
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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 19
|
||||
#define BCD_DEVICE_M 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -1046,7 +1081,7 @@
|
||||
#undef OUT_VOLUME_IN_MIXER
|
||||
#else
|
||||
#if defined(MIXER)
|
||||
// Enabled by default
|
||||
// Disabled by default
|
||||
//#define OUT_VOLUME_IN_MIXER
|
||||
#endif
|
||||
#endif
|
||||
@@ -1066,7 +1101,7 @@
|
||||
#undef IN_VOLUME_IN_MIXER
|
||||
#else
|
||||
#if defined(MIXER)
|
||||
/* Enabled by default */
|
||||
/* Disabled by default */
|
||||
//#define IN_VOLUME_IN_MIXER
|
||||
#endif
|
||||
#endif
|
||||
@@ -1218,7 +1253,11 @@ enum USBEndpointNumber_Out
|
||||
#define DFU_VENDOR_ID VENDOR_ID
|
||||
#define DFU_BCD_DEVICE BCD_DEVICE
|
||||
#define DFU_MANUFACTURER_STR_INDEX offsetof(StringDescTable_t, vendorStr)/sizeof(char *)
|
||||
#if (AUDIO_CLASS == 2)
|
||||
#define DFU_PRODUCT_STR_INDEX offsetof(StringDescTable_t, productStr_Audio2)/sizeof(char *)
|
||||
#else
|
||||
#define DFU_PRODUCT_STR_INDEX offsetof(StringDescTable_t, productStr_Audio1)/sizeof(char *)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* USB test mode support enabled by default (Required for compliance testing) */
|
||||
|
||||
@@ -45,9 +45,9 @@ extern unsigned char mixSel[MAX_MIX_COUNT][MIX_INPUTS];
|
||||
|
||||
/* Global var for current frequency, set to default freq */
|
||||
unsigned int g_curSamFreq = DEFAULT_FREQ;
|
||||
//unsigned int g_curSamFreq48000Family = DEFAULT_FREQ % 48000 == 0;
|
||||
|
||||
#if 0
|
||||
unsigned int g_curSamFreq48000Family = DEFAULT_FREQ % 48000 == 0;
|
||||
|
||||
/* Original feedback implementation */
|
||||
long long g_curSamFreqMultiplier = (DEFAULT_FREQ * 512 * 4) / (DEFAULT_MCLK_FREQ);
|
||||
#endif
|
||||
@@ -131,6 +131,7 @@ static void setG_curSamFreqMultiplier(unsigned x)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (OUTPUT_VOLUME_CONTROL == 1) || (INPUT_VOLUME_CONTROL == 1)
|
||||
/* Update master volume i.e. i.e update weights for all channels */
|
||||
static void updateMasterVol( int unitID, chanend ?c_mix_ctl)
|
||||
{
|
||||
@@ -266,6 +267,7 @@ static void updateVol(int unitID, int channel, chanend ?c_mix_ctl)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Handles the audio class specific requests
|
||||
* returns: XUD_RES_OKAY if request dealt with successfully without error,
|
||||
@@ -275,7 +277,7 @@ static void updateVol(int unitID, int channel, chanend ?c_mix_ctl)
|
||||
int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl
|
||||
)
|
||||
{
|
||||
unsigned char buffer[512];
|
||||
unsigned char buffer[128];
|
||||
int unitID;
|
||||
XUD_Result_t result;
|
||||
unsigned datalength;
|
||||
@@ -312,6 +314,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
||||
return result;
|
||||
}
|
||||
|
||||
#if MAX_FREQ != MIN_FREQ
|
||||
if(datalength == 4)
|
||||
{
|
||||
/* Re-construct Sample Freq */
|
||||
@@ -369,7 +372,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
||||
/* Allow time for our feedback to stabilise*/
|
||||
FeedbackStabilityDelay();
|
||||
}
|
||||
|
||||
#endif /* MAX_FREQ != MIN_FREQ */
|
||||
/* Send 0 Length as status stage */
|
||||
XUD_DoSetRequestStatus(ep0_in);
|
||||
}
|
||||
@@ -514,6 +517,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
||||
break;
|
||||
}
|
||||
|
||||
#if (OUTPUT_VOLUME_CONTROL == 1) || (INPUT_VOLUME_CONTROL == 1)
|
||||
/* Feature Units */
|
||||
case FU_USBOUT:
|
||||
case FU_USBIN:
|
||||
@@ -629,6 +633,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
||||
}
|
||||
|
||||
break; /* FU_USBIN */
|
||||
#endif
|
||||
|
||||
#if defined(MIXER) && (MAX_MIX_COUNT > 0)
|
||||
case ID_XU_OUT:
|
||||
@@ -1076,7 +1081,7 @@ int AudioEndpointRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp
|
||||
*/
|
||||
|
||||
XUD_Result_t result;
|
||||
unsigned char buffer[1024];
|
||||
unsigned char buffer[128];
|
||||
unsigned length;
|
||||
|
||||
/* Host to Device */
|
||||
@@ -1094,7 +1099,7 @@ int AudioEndpointRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
#if (MAX_FREQ != MIN_FREQ)
|
||||
if(controlSelector == SAMPLING_FREQ_CONTROL)
|
||||
{
|
||||
/* Expect length 3 for sample rate */
|
||||
@@ -1116,22 +1121,6 @@ int AudioEndpointRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp
|
||||
if(curSamFreq48000Family || curSamFreq44100Family)
|
||||
{
|
||||
g_curSamFreq = newSampleRate;
|
||||
#if 0
|
||||
/* Original feedback implementation */
|
||||
|
||||
int newMasterClock;
|
||||
|
||||
if(g_curSamFreq48000Family)
|
||||
{
|
||||
newMasterClock = MCLK_48;
|
||||
}
|
||||
else
|
||||
{
|
||||
newMasterClock = MCLK_441;
|
||||
}
|
||||
|
||||
setG_curSamFreqMultiplier((g_curSamFreq*512*4)/newMasterClock);
|
||||
#endif
|
||||
|
||||
/* Instruct audio thread to change sample freq */
|
||||
outuint(c_audioControl, SET_SAMPLE_FREQ);
|
||||
@@ -1147,6 +1136,9 @@ int AudioEndpointRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp
|
||||
return XUD_SetBuffer(ep0_in, buffer, 0);
|
||||
}
|
||||
}
|
||||
#else
|
||||
return XUD_SetBuffer(ep0_in, buffer, 0);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1171,12 +1163,13 @@ int AudioEndpointRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp
|
||||
int AudioClassRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl
|
||||
)
|
||||
{
|
||||
unsigned char buffer[1024];
|
||||
unsigned char buffer[128];
|
||||
unsigned unitID;
|
||||
XUD_Result_t result;
|
||||
|
||||
/* Inspect request */
|
||||
/* Note we could check sp.bmRequestType.Direction if we wanted to be really careful */
|
||||
#if (OUTPUT_VOLUME_CONTROL == 1) || (INPUT_VOLUME_CONTROL == 1)
|
||||
switch(sp.bRequest)
|
||||
{
|
||||
case UAC_B_REQ_SET_CUR:
|
||||
@@ -1288,7 +1281,7 @@ int AudioClassRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
||||
buffer[1] = (VOLUME_RES_MIXER >> 8);
|
||||
return XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
|
||||
}
|
||||
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -35,13 +35,14 @@ typedef struct
|
||||
STR_TABLE_ENTRY(vendorStr);
|
||||
STR_TABLE_ENTRY(serialStr);
|
||||
|
||||
#if (AUDIO_CLASS == 2)
|
||||
/* Audio 2.0 Strings */
|
||||
STR_TABLE_ENTRY(productStr_Audio2); /* Product string for Audio 2 */
|
||||
STR_TABLE_ENTRY(outputInterfaceStr_Audio2); /* iInterface for streaming intefaces */
|
||||
STR_TABLE_ENTRY(inputInterfaceStr_Audio2); /* iInterface for streaming intefaces */
|
||||
STR_TABLE_ENTRY(usbInputTermStr_Audio2); /* Users sees as output from host */
|
||||
STR_TABLE_ENTRY(usbOutputTermStr_Audio2); /* User sees as input to host */
|
||||
|
||||
#endif
|
||||
#if defined (AUDIO_CLASS_FALLBACK) || (AUDIO_CLASS == 1)
|
||||
/* Audio 1.0 Strings */
|
||||
STR_TABLE_ENTRY(productStr_Audio1); /* Product string for Audio 1 */
|
||||
@@ -50,6 +51,7 @@ typedef struct
|
||||
STR_TABLE_ENTRY(usbInputTermStr_Audio1); /* Users sees as output from host */
|
||||
STR_TABLE_ENTRY(usbOutputTermStr_Audio1); /* User sees as input to host */
|
||||
#endif
|
||||
#if (AUDIO_CLASS == 2)
|
||||
STR_TABLE_ENTRY(clockSelectorStr); /* iClockSel */
|
||||
STR_TABLE_ENTRY(internalClockSourceStr); /* iClockSource for internal clock */
|
||||
#ifdef SPDIF_RX
|
||||
@@ -58,6 +60,7 @@ typedef struct
|
||||
#ifdef ADAT_RX
|
||||
STR_TABLE_ENTRY(adatClockSourceStr); /* iClockSource for external S/PDIF clock */
|
||||
#endif
|
||||
#endif
|
||||
#ifdef DFU
|
||||
STR_TABLE_ENTRY(dfuStr); /* iInterface for DFU interface */
|
||||
#endif
|
||||
@@ -291,7 +294,9 @@ typedef struct
|
||||
#if defined(MIXER) && (MAX_MIX_COUNT > 7)
|
||||
STR_TABLE_ENTRY(mixOutStr_8);
|
||||
#endif
|
||||
#ifdef IAP
|
||||
STR_TABLE_ENTRY(iAPInterfaceStr);
|
||||
#endif
|
||||
#ifdef IAP_EA_NATIVE_TRANS
|
||||
STR_TABLE_ENTRY(iAP_EANativeTransport_InterfaceStr);
|
||||
#endif
|
||||
@@ -302,12 +307,13 @@ StringDescTable_t g_strTable =
|
||||
.langID = "\x09\x04", /* US English */
|
||||
.vendorStr = VENDOR_STR,
|
||||
.serialStr = "",
|
||||
#if (AUDIO_CLASS == 2)
|
||||
.productStr_Audio2 = PRODUCT_STR_A2,
|
||||
.outputInterfaceStr_Audio2 = APPEND_PRODUCT_STR_A2(),
|
||||
.inputInterfaceStr_Audio2 = APPEND_PRODUCT_STR_A2(),
|
||||
.usbInputTermStr_Audio2 = APPEND_PRODUCT_STR_A2(),
|
||||
.usbOutputTermStr_Audio2 = APPEND_PRODUCT_STR_A2(),
|
||||
|
||||
#endif
|
||||
#if defined (AUDIO_CLASS_FALLBACK) || (AUDIO_CLASS == 1)
|
||||
.productStr_Audio1 = PRODUCT_STR_A1,
|
||||
.outputInterfaceStr_Audio1 = APPEND_PRODUCT_STR_A1(),
|
||||
@@ -315,6 +321,7 @@ StringDescTable_t g_strTable =
|
||||
.usbInputTermStr_Audio1 = APPEND_PRODUCT_STR_A1(),
|
||||
.usbOutputTermStr_Audio1 = APPEND_PRODUCT_STR_A1(),
|
||||
#endif
|
||||
#if (AUDIO_CLASS == 2)
|
||||
.clockSelectorStr = APPEND_VENDOR_STR(Clock Selector),
|
||||
.internalClockSourceStr = APPEND_VENDOR_STR(Internal Clock),
|
||||
#ifdef SPDIF_RX
|
||||
@@ -323,6 +330,7 @@ StringDescTable_t g_strTable =
|
||||
#ifdef ADAT_RX
|
||||
.adatClockSourceStr = APPEND_VENDOR_STR(ADAT Clock),
|
||||
#endif
|
||||
#endif
|
||||
#ifdef DFU
|
||||
.dfuStr = APPEND_VENDOR_STR(DFU),
|
||||
#endif
|
||||
@@ -368,7 +376,9 @@ StringDescTable_t g_strTable =
|
||||
#if defined(MIXER) && (MAX_MIX_COUNT > 8)
|
||||
#error
|
||||
#endif
|
||||
#ifdef IAP
|
||||
.iAPInterfaceStr = "iAP Interface",
|
||||
#endif
|
||||
#ifdef IAP_EA_NATIVE_TRANS
|
||||
.iAP_EANativeTransport_InterfaceStr = IAP2_EA_NATIVE_TRANS_PROTOCOL_NAME,
|
||||
#endif
|
||||
@@ -397,6 +407,7 @@ USB_Descriptor_Device_t devDesc_Audio1 =
|
||||
};
|
||||
#endif
|
||||
|
||||
#if (AUDIO_CLASS == 2)
|
||||
/* Device Descriptor for Audio Class 2.0 (Assumes High-Speed ) */
|
||||
USB_Descriptor_Device_t devDesc_Audio2 =
|
||||
{
|
||||
@@ -438,7 +449,7 @@ unsigned char devDesc_Null[] =
|
||||
0, /* 16 iSerialNumber : Index of serial number decriptor */
|
||||
0x01 /* 17 bNumConfigurations : Number of possible configs */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/****** Device Qualifier Descriptors *****/
|
||||
|
||||
@@ -751,7 +762,7 @@ typedef struct
|
||||
|
||||
}__attribute__((packed)) USB_Config_Descriptor_Audio2_t;
|
||||
|
||||
#if 1
|
||||
#if (AUDIO_CLASS == 2)
|
||||
USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
|
||||
{
|
||||
.Config =
|
||||
@@ -2252,7 +2263,10 @@ const unsigned num_freqs_a1 = MAX(3, (0
|
||||
#define NUM_CONTROL_INTERFACES 0
|
||||
#endif
|
||||
|
||||
#define AC_TOTAL_LENGTH (AC_LENGTH + (INPUT_INTERFACES_A1 * (17 + NUM_USB_CHAN_IN_FS + num_freqs_a1 * 3)) + (OUTPUT_INTERFACES_A1 * (17 + NUM_USB_CHAN_OUT_FS + (num_freqs_a1 *3))))
|
||||
#define AC_TOTAL_LENGTH (AC_LENGTH + \
|
||||
(INPUT_INTERFACES_A1 * (9 + (7* INPUT_VOLUME_CONTROL) + (NUM_USB_CHAN_IN_FS * INPUT_VOLUME_CONTROL) + num_freqs_a1 * 3)) +\
|
||||
(OUTPUT_INTERFACES_A1 * (9 + (7 * OUTPUT_VOLUME_CONTROL) + (NUM_USB_CHAN_OUT_FS * OUTPUT_VOLUME_CONTROL) + (num_freqs_a1 *3))))
|
||||
|
||||
#define STREAMING_INTERFACES (INPUT_INTERFACES_A1 + OUTPUT_INTERFACES_A1)
|
||||
|
||||
/* Number of interfaces for Audio 1.0 (+1 for control ) */
|
||||
@@ -2268,7 +2282,7 @@ const unsigned num_freqs_a1 = MAX(3, (0
|
||||
#define CHARIFY_SR(x) (x & 0xff),((x & 0xff00)>> 8),((x & 0xff0000)>> 16)
|
||||
|
||||
#if (MIN_FREQ_FS < 12000) && (MAX_FREQ_FS > 48000)
|
||||
#error SAMPLE RATE RANGE TO GREAT FOR UAC1 ON WINDOWS
|
||||
#error SAMPLE RATE RANGE TOO GREAT FOR UAC1 ON WINDOWS
|
||||
#endif
|
||||
|
||||
unsigned char cfgDesc_Audio1[] =
|
||||
@@ -2297,7 +2311,7 @@ unsigned char cfgDesc_Audio1[] =
|
||||
USB_CLASS_AUDIO,
|
||||
UAC_INT_SUBCLASS_AUDIOCONTROL,
|
||||
0x00, /* Unused */
|
||||
8, /* iInterface - re-use iProduct */
|
||||
offsetof(StringDescTable_t, productStr_Audio1)/sizeof(char *), /* iInterface - re-use iProduct */
|
||||
|
||||
/* CS (Class Specific) AudioControl interface header descriptor (4.3.2) */
|
||||
AC_LENGTH,
|
||||
@@ -2325,8 +2339,9 @@ unsigned char cfgDesc_Audio1[] =
|
||||
NUM_USB_CHAN_OUT_FS, /* bNrChannels */
|
||||
0x03, 0x00, /* wChannelConfig */
|
||||
offsetof(StringDescTable_t, outputChanStr_1)/sizeof(char *), /* iChannelNames */
|
||||
11, /* iTerminal */
|
||||
offsetof(StringDescTable_t, usbInputTermStr_Audio1)/sizeof(char *), /* iTerminal */
|
||||
|
||||
#if (OUTPUT_VOLUME_CONTROL == 1)
|
||||
/* CS_Interface class specific AC interface feature unit descriptor - mute & volume for dac */
|
||||
(8 + NUM_USB_CHAN_OUT_FS),
|
||||
UAC_CS_DESCTYPE_INTERFACE,
|
||||
@@ -2364,6 +2379,7 @@ unsigned char cfgDesc_Audio1[] =
|
||||
#error NUM_USB_CHAN_OUT_FS > 8 currently supported
|
||||
#endif
|
||||
0x00, /* String table index */
|
||||
#endif
|
||||
|
||||
/* CS_Interface Output Terminal Descriptor - Analogue out to speaker */
|
||||
0x09,
|
||||
@@ -2372,7 +2388,11 @@ unsigned char cfgDesc_Audio1[] =
|
||||
0x06, /* Terminal ID */
|
||||
0x01, 0x03, /* Type - streaming out, speaker */
|
||||
0x00, /* Associated terminal - unused */
|
||||
0x0A, /* sourceID */
|
||||
#if (OUTPUT_VOLUME_CONTROL == 1)
|
||||
0x0A, /* sourceID - FU */
|
||||
#else
|
||||
0x01, /* sourceID - IT */
|
||||
#endif
|
||||
0x00, /* Unused */
|
||||
#endif
|
||||
|
||||
@@ -2387,7 +2407,7 @@ unsigned char cfgDesc_Audio1[] =
|
||||
NUM_USB_CHAN_IN_FS, /* bNrChannels */
|
||||
0x03, 0x00, /* wChannelConfigs */
|
||||
offsetof(StringDescTable_t, inputChanStr_1)/sizeof(char *), /* iChannelNames */
|
||||
12, /* iTerminal */
|
||||
offsetof(StringDescTable_t, usbOutputTermStr_Audio1)/sizeof(char *), /* iTerminal */
|
||||
|
||||
/* CS_Interface Output Terminal Descriptor - USB Streaming Device to Host*/
|
||||
0x09,
|
||||
@@ -2396,9 +2416,14 @@ unsigned char cfgDesc_Audio1[] =
|
||||
0x07, /* Terminal ID */
|
||||
0x01, 0x01, /* Type - streaming */
|
||||
0x01, /* Associated terminal - unused */
|
||||
0x0B, /* sourceID - from selector unit ?? */
|
||||
#if INPUT_VOLUME_CONTROL
|
||||
0x0B, /* sourceID - FU */
|
||||
#else
|
||||
0x02, /* sourceID - IT */
|
||||
#endif
|
||||
0x00, /* Unused */
|
||||
|
||||
#if (INPUT_VOLUME_CONTROL == 1)
|
||||
/* CS_Interface class specific AC interface feature unit descriptor - mute & volume for adc */
|
||||
(8 + NUM_USB_CHAN_IN_FS),
|
||||
UAC_CS_DESCTYPE_INTERFACE,
|
||||
@@ -2436,6 +2461,7 @@ unsigned char cfgDesc_Audio1[] =
|
||||
#endif
|
||||
0x00, /* String table index */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (NUM_USB_CHAN_OUT > 0)
|
||||
/* Standard AS Interface Descriptor (4.5.1) */
|
||||
@@ -2447,7 +2473,7 @@ unsigned char cfgDesc_Audio1[] =
|
||||
0x01, /* bInterfaceClass - AUDIO */
|
||||
0x02, /* bInterfaceSubclass - AUDIO_STREAMING */
|
||||
0x00, /* bInterfaceProtocol - Not used */
|
||||
0x09, /* iInterface */
|
||||
offsetof(StringDescTable_t, outputInterfaceStr_Audio1)/sizeof(char *), /* iInterface */
|
||||
|
||||
/* Standard As Interface Descriptor (4.5.1) */
|
||||
0x09,
|
||||
@@ -2462,7 +2488,7 @@ unsigned char cfgDesc_Audio1[] =
|
||||
0x01, /* Interface class - AUDIO */
|
||||
0x02, /* subclass - AUDIO_STREAMING */
|
||||
0x00, /* Unused */
|
||||
0x09, /* String table index */
|
||||
offsetof(StringDescTable_t, outputInterfaceStr_Audio1)/sizeof(char *), /* iInterface */
|
||||
|
||||
/* Class-Specific AS Interface Descriptor (4.5.2) */
|
||||
0x07,
|
||||
@@ -2580,7 +2606,7 @@ unsigned char cfgDesc_Audio1[] =
|
||||
0x01, /* Interface class - AUDIO */
|
||||
0x02, /* subclass - AUDIO_STREAMING */
|
||||
0x00, /* Unused */
|
||||
0x0A, /* iInterface */
|
||||
offsetof(StringDescTable_t, inputInterfaceStr_Audio1)/sizeof(char *),
|
||||
|
||||
/* Standard Interface Descriptor - Audio streaming IN */
|
||||
0x09,
|
||||
@@ -2591,7 +2617,7 @@ unsigned char cfgDesc_Audio1[] =
|
||||
0x01, /* Interface class - AUDIO */
|
||||
0x02, /* Subclass - AUDIO_STREAMING */
|
||||
0x00, /* Unused */
|
||||
0x0A, /* iInterface*/
|
||||
offsetof(StringDescTable_t, inputInterfaceStr_Audio1)/sizeof(char *),
|
||||
|
||||
/* CS_Interface AC interface header descriptor */
|
||||
0x07,
|
||||
@@ -2688,7 +2714,7 @@ unsigned char cfgDesc_Audio1[] =
|
||||
|
||||
#ifdef XVSM
|
||||
/* 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) */
|
||||
(OUTPUT_INTERFACES_A1 + 2), /* bInterfaceNumber */
|
||||
0x00, /* 3 bAlternateSetting : Index of this setting. (field size 1 bytes) */
|
||||
|
||||
@@ -206,6 +206,8 @@ void Endpoint0(chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
|
||||
XUD_ep ep0_out = XUD_InitEp(c_ep0_out);
|
||||
XUD_ep ep0_in = XUD_InitEp(c_ep0_in);
|
||||
|
||||
#if 0
|
||||
/* Dont need to init globals.. */
|
||||
/* Init tables for volumes (+ 1 for master) */
|
||||
for(int i = 0; i < NUM_USB_CHAN_OUT + 1; i++)
|
||||
{
|
||||
@@ -218,7 +220,7 @@ void Endpoint0(chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
|
||||
volsIn[i] = 0;
|
||||
mutesIn[i] = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
VendorRequests_Init(VENDOR_REQUESTS_PARAMS);
|
||||
|
||||
#ifdef MIXER
|
||||
@@ -295,7 +297,7 @@ void Endpoint0(chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
|
||||
{
|
||||
/* Returns XUD_RES_OKAY for success, XUD_RES_RST for bus reset */
|
||||
XUD_Result_t result = USB_GetSetupPacket(ep0_out, ep0_in, &sp);
|
||||
|
||||
|
||||
if (result == XUD_RES_OKAY)
|
||||
{
|
||||
result = XUD_RES_ERR;
|
||||
@@ -311,7 +313,7 @@ void Endpoint0(chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
|
||||
switch (sp.wIndex)
|
||||
{
|
||||
/* Check for audio stream from host start/stop */
|
||||
#if (NUM_USB_CHAN_OUT > 0)
|
||||
#if (NUM_USB_CHAN_OUT > 0) && (AUDIO_CLASS == 2)
|
||||
case INTERFACE_NUMBER_AUDIO_OUTPUT:
|
||||
/* Check the alt is in range */
|
||||
if(sp.wValue <= OUTPUT_FORMAT_COUNT)
|
||||
@@ -346,7 +348,7 @@ void Endpoint0(chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if (NUM_USB_CHAN_IN > 0)
|
||||
#if (NUM_USB_CHAN_IN > 0) && (AUDIO_CLASS == 2)
|
||||
case INTERFACE_NUMBER_AUDIO_INPUT:
|
||||
/* Check the alt is in range */
|
||||
if(sp.wValue <= INPUT_FORMAT_COUNT)
|
||||
|
||||
@@ -19,9 +19,15 @@
|
||||
#define portout(a,b) {__asm__ __volatile__("out res[%0], %1": : "r" (a) , "r" (b));}
|
||||
|
||||
#ifdef DFU_FLASH_DEVICE
|
||||
|
||||
#ifdef QUAD_SPI_FLASH
|
||||
/* Using specified flash device rather than all supported in tools */
|
||||
fl_QuadDeviceSpec flash_devices[] = {DFU_FLASH_DEVICE};
|
||||
#else
|
||||
/* Using specified flash device rather than all supported in tools */
|
||||
fl_DeviceSpec flash_devices[] = {DFU_FLASH_DEVICE};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef QUAD_SPI_FLASH
|
||||
/*
|
||||
@@ -83,7 +89,11 @@ int flash_cmd_enable_ports()
|
||||
#endif
|
||||
|
||||
#ifdef DFU_FLASH_DEVICE
|
||||
#ifdef QUAD_SPI_FLASH
|
||||
result = fl_connectToDevice(&p_qflash, flash_devices, 1);
|
||||
#else
|
||||
result = fl_connectToDevice(&p_flash, flash_devices, 1);
|
||||
#endif
|
||||
#else
|
||||
/* Use default flash list */
|
||||
#ifdef QUAD_SPI_FLASH
|
||||
|
||||
@@ -317,9 +317,12 @@ VENDOR_REQUESTS_PARAMS_DEC_
|
||||
c_sof, epTypeTableOut, epTypeTableIn, p_usb_rst,
|
||||
clk, 1, XUD_SPEED_HS, XUD_PWR_CFG);
|
||||
#else
|
||||
{
|
||||
set_core_high_priority_on();
|
||||
XUD_Manager(c_xud_out, ENDPOINT_COUNT_OUT, c_xud_in, ENDPOINT_COUNT_IN,
|
||||
c_sof, epTypeTableOut, epTypeTableIn, p_usb_rst,
|
||||
clk, 1, XUD_SPEED_FS, XUD_PWR_CFG);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* USB Packet buffering Core */
|
||||
@@ -485,6 +488,8 @@ void usb_audio_io(chanend c_aud_in, chanend ?c_adc,
|
||||
#define USER_MAIN_CORES
|
||||
#endif
|
||||
|
||||
#ifndef EXCLUDE_USB_AUDIO_MAIN
|
||||
|
||||
/* Main for USB Audio Applications */
|
||||
int main()
|
||||
{
|
||||
@@ -558,6 +563,8 @@ int main()
|
||||
USER_MAIN_DECLARATIONS
|
||||
par
|
||||
{
|
||||
USER_MAIN_CORES
|
||||
|
||||
on tile[XUD_TILE]:
|
||||
par
|
||||
{
|
||||
@@ -668,17 +675,17 @@ int main()
|
||||
#ifdef MIC_PROCESSING_USE_INTERFACE
|
||||
on stdcore[PDM_TILE].core[0]: pdm_buffer(c_ds_output, c_pdm_pcm, i_mic_process);
|
||||
#else
|
||||
on stdcore[PDM_TILE]: pdm_buffer(c_ds_output, c_pdm_pcm);
|
||||
on stdcore[PDM_TILE].core[0]: pdm_buffer(c_ds_output, c_pdm_pcm);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
USER_MAIN_CORES
|
||||
}
|
||||
|
||||
#ifdef SU1_ADC_ENABLE
|
||||
xs1_su_adc_service(c_adc);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -241,10 +241,10 @@ static inline void GetSamplesFromHost(chanend c)
|
||||
write_via_xc_ptr_indexed(samples_array, i, h);
|
||||
#else
|
||||
ptr_samples[i] = sample;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma unsafe arrays
|
||||
@@ -366,7 +366,7 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
|
||||
/* Forward on Request for data to decouple thread */
|
||||
outuint(c_host, request);
|
||||
|
||||
/* Between request to decouple and respose ~ 400nS latency for interrupt to fire */
|
||||
/* Between request to decouple and response ~ 400nS latency for interrupt to fire */
|
||||
select
|
||||
{
|
||||
case inuint_byref(c_mix_ctl, cmd):
|
||||
|
||||
@@ -29,4 +29,7 @@
|
||||
#
|
||||
EXCLUDE_FILES += descriptors_2.rst
|
||||
|
||||
MODULE_XCC_FLAGS += $(XCC_FLAGS) -falways-inline
|
||||
#MODULE_XCC_FLAGS += $(XCC_FLAGS) -falways-inline
|
||||
|
||||
XCC_FLAGS_endpoint0.c = -Os -mno-dual-issue $(XCC_FLAGS)
|
||||
XCC_FLAGS_dbcalc.xc = -Os -mno-dual-issue $(XCC_FLAGS)
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#ifndef MIC_ARRAY_CONF_H_
|
||||
#define MIC_ARRAY_CONF_H_
|
||||
|
||||
#include "customdefines.h"
|
||||
|
||||
#define MIC_ARRAY_MAX_FRAME_SIZE_LOG2 0
|
||||
#define MIC_ARRAY_NUM_MICS 8
|
||||
#define MIC_ARRAY_NUM_MICS (NUM_PDM_MICS)
|
||||
|
||||
#endif /* MIC_ARRAY_CONF_H_ */
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
|
||||
#include "mic_array.h"
|
||||
|
||||
#ifdef MIC_PROCESSING_USE_INTERFACE
|
||||
/* Interface based user processing */
|
||||
typedef interface mic_process_if
|
||||
{
|
||||
void transfer_buffers(mic_array_frame_time_domain * unsafe audio, int output[]);
|
||||
void init();
|
||||
} mic_process_if;
|
||||
|
||||
|
||||
[[combinable]]
|
||||
void pdm_buffer(streaming chanend c_ds_output[2], chanend c_audio
|
||||
#ifdef MIC_PROCESSING_USE_INTERFACE
|
||||
, client mic_process_if i_mic_process
|
||||
#endif
|
||||
);
|
||||
|
||||
[[combinable]]
|
||||
void user_pdm_process(server mic_process_if i_mic_data);
|
||||
|
||||
/* PDM interface and decimation cores */
|
||||
void pdm_mic(streaming chanend c_ds_output[2]);
|
||||
|
||||
#else
|
||||
|
||||
/* Simple user hooks/call-backs */
|
||||
unsafe void user_pdm_process(mic_array_frame_time_domain * unsafe audio, int output[]);
|
||||
|
||||
void user_pdm_init();
|
||||
|
||||
/* PDM interface and decimation cores */
|
||||
void pdm_mic(streaming chanend c_ds_output[2]);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,11 +12,12 @@
|
||||
#include <string.h>
|
||||
#include <xclib.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mic_array.h"
|
||||
#include "xua_pdm_mic.h"
|
||||
|
||||
#define MAX_DECIMATION_FACTOR 12
|
||||
#define MAX_DECIMATION_FACTOR (96000/MIN_FREQ)
|
||||
|
||||
/* Hardware resources */
|
||||
in port p_pdm_clk = PORT_PDM_CLK;
|
||||
@@ -35,11 +36,11 @@ mic_array_frame_time_domain mic_audio[2];
|
||||
void pdm_buffer(streaming chanend c_ds_output[2], chanend c_audio, client mic_process_if i_mic_process)
|
||||
#else
|
||||
#pragma unsafe arrays
|
||||
[[combinable]]
|
||||
void pdm_buffer(streaming chanend c_ds_output[2], chanend c_audio)
|
||||
#endif
|
||||
{
|
||||
unsigned buffer;
|
||||
int output[NUM_PDM_MICS];
|
||||
unsigned samplerate;
|
||||
|
||||
#ifdef MIC_PROCESSING_USE_INTERFACE
|
||||
@@ -48,6 +49,12 @@ void pdm_buffer(streaming chanend c_ds_output[2], chanend c_audio)
|
||||
user_pdm_init();
|
||||
#endif
|
||||
|
||||
#if NUM_PDM_MICS > 4
|
||||
unsigned decimatorCount = 2;
|
||||
#else
|
||||
unsigned decimatorCount = 1;
|
||||
#endif
|
||||
|
||||
mic_array_decimator_conf_common_t dcc;
|
||||
const int * unsafe fir_coefs[7];
|
||||
mic_array_frame_time_domain * unsafe current;
|
||||
@@ -105,20 +112,21 @@ void pdm_buffer(streaming chanend c_ds_output[2], chanend c_audio)
|
||||
dc[1].mic_gain_compensation[3]=0;
|
||||
dc[1].channel_count = 4;
|
||||
|
||||
mic_array_decimator_configure(c_ds_output, 2, dc);
|
||||
mic_array_decimator_configure(c_ds_output, decimatorCount, dc);
|
||||
|
||||
mic_array_init_time_domain_frame(c_ds_output, 2, buffer, mic_audio, dc);
|
||||
mic_array_init_time_domain_frame(c_ds_output, decimatorCount, buffer, mic_audio, dc);
|
||||
|
||||
/* Grab a first frame of mic data */
|
||||
/* Note, loop is unrolled once - allows for while(1) select {} and thus combinable */
|
||||
current = mic_array_get_next_time_domain_frame(c_ds_output, 2, buffer, mic_audio, dc);
|
||||
current = mic_array_get_next_time_domain_frame(c_ds_output, decimatorCount, buffer, mic_audio, dc);
|
||||
}
|
||||
|
||||
/* Run user code */
|
||||
/* TODO ideally processing done inplace - it then doesn't matter if it is run or not */
|
||||
#ifdef MIC_PROCESSING_USE_INTERFACE
|
||||
i_mic_process.transfer_buffers(current, output);
|
||||
i_mic_process.transfer_buffers(current);
|
||||
#else
|
||||
user_pdm_process(current, output);
|
||||
user_pdm_process(current);
|
||||
#endif
|
||||
int req;
|
||||
while(1)
|
||||
@@ -135,18 +143,18 @@ void pdm_buffer(streaming chanend c_ds_output[2], chanend c_audio)
|
||||
#pragma loop unroll
|
||||
for(int i = 0; i < NUM_PDM_MICS; i++)
|
||||
{
|
||||
c_audio <: output[i];
|
||||
c_audio <: current->data[i][0];
|
||||
}
|
||||
}
|
||||
|
||||
/* Get a new frame of mic data */
|
||||
mic_array_frame_time_domain * unsafe current = mic_array_get_next_time_domain_frame(c_ds_output, 2, buffer, mic_audio, dc);
|
||||
mic_array_frame_time_domain * unsafe current = mic_array_get_next_time_domain_frame(c_ds_output, decimatorCount, buffer, mic_audio, dc);
|
||||
|
||||
/* Run user code */
|
||||
#ifdef MIC_PROCESSING_USE_INTERFACE
|
||||
i_mic_process.transfer_buffers(current, output);
|
||||
i_mic_process.transfer_buffers(current);
|
||||
#else
|
||||
user_pdm_process(current, output);
|
||||
user_pdm_process(current);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@@ -159,17 +167,17 @@ void pdm_buffer(streaming chanend c_ds_output[2], chanend c_audio)
|
||||
dcc.output_decimation_factor = decimationfactor;
|
||||
dcc.coefs=fir_coefs[decimationfactor/2];
|
||||
dcc.fir_gain_compensation = fir_gain_compen[decimationfactor/2];
|
||||
mic_array_decimator_configure(c_ds_output, 2, dc);
|
||||
mic_array_init_time_domain_frame(c_ds_output, 2, buffer, mic_audio, dc);
|
||||
mic_array_decimator_configure(c_ds_output, decimatorCount, dc);
|
||||
mic_array_init_time_domain_frame(c_ds_output, decimatorCount, buffer, mic_audio, dc);
|
||||
|
||||
/* Get a new mic data frame */
|
||||
mic_array_frame_time_domain * unsafe current = mic_array_get_next_time_domain_frame(c_ds_output, 2, buffer, mic_audio, dc);
|
||||
mic_array_frame_time_domain * unsafe current = mic_array_get_next_time_domain_frame(c_ds_output, decimatorCount, buffer, mic_audio, dc);
|
||||
|
||||
/* Run user code */
|
||||
#ifdef MIC_PROCESSING_USE_INTERFACE
|
||||
i_mic_process.transfer_buffers(current, output);
|
||||
i_mic_process.transfer_buffers(current);
|
||||
#else
|
||||
user_pdm_process(current, output);
|
||||
user_pdm_process(current);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
@@ -183,10 +191,23 @@ void pdm_buffer(streaming chanend c_ds_output[2], chanend c_audio)
|
||||
|
||||
void pdm_mic(streaming chanend c_ds_output[2])
|
||||
{
|
||||
streaming chan c_4x_pdm_mic_0, c_4x_pdm_mic_1;
|
||||
streaming chan c_4x_pdm_mic_0;
|
||||
#if (NUM_PDM_MICS > 4)
|
||||
streaming chan c_4x_pdm_mic_1;
|
||||
#else
|
||||
#define c_4x_pdm_mic_1 null
|
||||
#endif
|
||||
|
||||
/* Note, this divide should be based on master clock freq */
|
||||
configure_clock_src_divide(pdmclk, p_mclk, 2);
|
||||
/* Mics expect a clock in the 3Mhz range, calculate the divide based on mclk */
|
||||
/* e.g. For a 48kHz range mclk we expect a 3072000Hz mic clock */
|
||||
/* e.g. For a 44.1kHz range mclk we expect a 2822400Hz mic clock */
|
||||
|
||||
/* Note, codebase currently does not handle a different divide for each clock */
|
||||
assert((MCLK_48 / 3072000) == (MCLK_441 / 2822400));
|
||||
|
||||
unsigned micDiv = MCLK_48/3072000;
|
||||
|
||||
configure_clock_src_divide(pdmclk, p_mclk, micDiv/2);
|
||||
configure_port_clock_output(p_pdm_clk, pdmclk);
|
||||
configure_in_port(p_pdm_mics, pdmclk);
|
||||
start_clock(pdmclk);
|
||||
@@ -195,7 +216,9 @@ void pdm_mic(streaming chanend c_ds_output[2])
|
||||
{
|
||||
mic_array_pdm_rx(p_pdm_mics, c_4x_pdm_mic_0, c_4x_pdm_mic_1);
|
||||
mic_array_decimate_to_pcm_4ch(c_4x_pdm_mic_0, c_ds_output[0], MIC_ARRAY_NO_INTERNAL_CHANS);
|
||||
#if (NUM_PDM_MICS > 4)
|
||||
mic_array_decimate_to_pcm_4ch(c_4x_pdm_mic_1, c_ds_output[1], MIC_ARRAY_NO_INTERNAL_CHANS);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
22
module_usb_audio/pdm_mics/pdm_mic_user.c
Normal file
22
module_usb_audio/pdm_mics/pdm_mic_user.c
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
#include "devicedefines.h"
|
||||
|
||||
#if (NUM_PDM_MICS > 0) && !defined(MIC_PROCESSING_USE_INTERFACE)
|
||||
|
||||
#include "mic_array_frame.h"
|
||||
|
||||
/* Deafult implementations of user_pdm_init() and user_pdm_process(). Both can be over-ridden */
|
||||
void user_pdm_init() __attribute__ ((weak));
|
||||
void user_pdm_init()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void user_pdm_process() __attribute__ ((weak));
|
||||
void user_pdm_process(mic_array_frame_time_domain * audio)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Interface based user processing */
|
||||
typedef interface mic_process_if
|
||||
{
|
||||
void transfer_buffers(mic_array_frame_time_domain * unsafe audio, int output[]);
|
||||
void transfer_buffers(mic_array_frame_time_domain * unsafe audio);
|
||||
void init();
|
||||
} mic_process_if;
|
||||
|
||||
@@ -26,11 +26,12 @@ void pdm_mic(streaming chanend c_ds_output[2]);
|
||||
#else
|
||||
|
||||
/* Simple user hooks/call-backs */
|
||||
void user_pdm_process(mic_array_frame_time_domain * unsafe audio, int output[]);
|
||||
void user_pdm_process(mic_array_frame_time_domain * unsafe audio);
|
||||
|
||||
void user_pdm_init();
|
||||
|
||||
/* PDM interface and decimation cores */
|
||||
[[combinable]]
|
||||
void pdm_buffer(streaming chanend c_ds_output[2], chanend c_audio);
|
||||
|
||||
/* PDM interface and decimation cores */
|
||||
|
||||
@@ -14,25 +14,47 @@
|
||||
#endif
|
||||
#define MAX(x,y) ((x)>(y) ? (x) : (y))
|
||||
|
||||
#define HS_PACKET_SIZE ((((MAX_FREQ+7999)/8000))+3) // Samples per channel
|
||||
#define FS_PACKET_SIZE ((((MAX_FREQ_FS+999)/1000))+3) // Samples per channel
|
||||
|
||||
/* TODO use SLOTSIZE to potentially save memory */
|
||||
#define BUFF_SIZE_OUT MAX(4 * HS_PACKET_SIZE * NUM_USB_CHAN_OUT, 4 * FS_PACKET_SIZE * NUM_USB_CHAN_OUT_FS)
|
||||
#define BUFF_SIZE_IN MAX(4 * HS_PACKET_SIZE * NUM_USB_CHAN_IN, 4 * FS_PACKET_SIZE * NUM_USB_CHAN_IN_FS)
|
||||
/* Note we could improve on this, for one subslot is set to 4 */
|
||||
/* The *4 is conversion to bytes, note we're assuming a slotsize of 4 here whic is potentially as waste */
|
||||
#define MAX_DEVICE_AUD_PACKET_SIZE_MULT_HS ((MAX_FREQ/8000+1)*4)
|
||||
#define MAX_DEVICE_AUD_PACKET_SIZE_MULT_FS ((MAX_FREQ_FS/1000+1)*4)
|
||||
|
||||
/* Maximum USB buffer size (1024 bytes + 1 word to store length) */
|
||||
#define MAX_USB_AUD_PACKET_SIZE 1028
|
||||
/*** IN PACKET SIZES ***/
|
||||
/* Max packet sizes in bytes. Note the +4 is because we store packet lengths in the buffer */
|
||||
#define MAX_DEVICE_AUD_PACKET_SIZE_IN_HS (MAX_DEVICE_AUD_PACKET_SIZE_MULT_HS * NUM_USB_CHAN_IN + 4)
|
||||
#define MAX_DEVICE_AUD_PACKET_SIZE_IN_FS (MAX_DEVICE_AUD_PACKET_SIZE_MULT_FS * NUM_USB_CHAN_IN_FS + 4)
|
||||
|
||||
#define OUT_BUFFER_PREFILL (MAX(NUM_USB_CHAN_OUT_FS*FS_PACKET_SIZE*3+4,NUM_USB_CHAN_OUT*HS_PACKET_SIZE*4+4)*1)
|
||||
#define IN_BUFFER_PREFILL (MAX(FS_PACKET_SIZE*2+4, NUM_USB_CHAN_IN*HS_PACKET_SIZE*4+4)*2)
|
||||
#define MAX_DEVICE_AUD_PACKET_SIZE_IN (MAX(MAX_DEVICE_AUD_PACKET_SIZE_IN_FS, MAX_DEVICE_AUD_PACKET_SIZE_IN_HS))
|
||||
|
||||
/*** OUT PACKET SIZES ***/
|
||||
#define MAX_DEVICE_AUD_PACKET_SIZE_OUT_HS (MAX_DEVICE_AUD_PACKET_SIZE_MULT_HS * NUM_USB_CHAN_OUT + 4)
|
||||
#define MAX_DEVICE_AUD_PACKET_SIZE_OUT_FS (MAX_DEVICE_AUD_PACKET_SIZE_MULT_FS * NUM_USB_CHAN_OUT_FS + 4)
|
||||
|
||||
#define MAX_DEVICE_AUD_PACKET_SIZE_OUT (MAX(MAX_DEVICE_AUD_PACKET_SIZE_OUT_FS, MAX_DEVICE_AUD_PACKET_SIZE_OUT_HS))
|
||||
|
||||
/*** BUFFER SIZES ***/
|
||||
|
||||
#define BUFFER_PACKET_COUNT 3 /* How many packets too allow for in buffer - minimum is 3! */
|
||||
|
||||
#define BUFF_SIZE_OUT_HS MAX_DEVICE_AUD_PACKET_SIZE_OUT_HS * BUFFER_PACKET_COUNT
|
||||
#define BUFF_SIZE_OUT_FS MAX_DEVICE_AUD_PACKET_SIZE_OUT_FS * BUFFER_PACKET_COUNT
|
||||
|
||||
#define BUFF_SIZE_IN_HS MAX_DEVICE_AUD_PACKET_SIZE_IN_HS * BUFFER_PACKET_COUNT
|
||||
#define BUFF_SIZE_IN_FS MAX_DEVICE_AUD_PACKET_SIZE_IN_FS * BUFFER_PACKET_COUNT
|
||||
|
||||
#define BUFF_SIZE_OUT MAX(BUFF_SIZE_OUT_HS, BUFF_SIZE_OUT_FS)
|
||||
#define BUFF_SIZE_IN MAX(BUFF_SIZE_IN_HS, BUFF_SIZE_IN_FS)
|
||||
|
||||
#define OUT_BUFFER_PREFILL (MAX(MAX_DEVICE_AUD_PACKET_SIZE_OUT_HS, MAX_DEVICE_AUD_PACKET_SIZE_OUT_FS))
|
||||
#define IN_BUFFER_PREFILL (MAX(MAX_DEVICE_AUD_PACKET_SIZE_IN_HS, MAX_DEVICE_AUD_PACKET_SIZE_IN_FS)*2)
|
||||
|
||||
/* Volume and mute tables */
|
||||
#ifndef OUT_VOLUME_IN_MIXER
|
||||
#if !defined(OUT_VOLUME_IN_MIXER) && (OUTPUT_VOLUME_CONTROL == 1)
|
||||
unsigned int multOut[NUM_USB_CHAN_OUT + 1];
|
||||
static xc_ptr p_multOut;
|
||||
#endif
|
||||
#ifndef IN_VOLUME_IN_MIXER
|
||||
#if !defined(IN_VOLUME_IN_MIXER) && (INPUT_VOLUME_CONTROL == 1)
|
||||
unsigned int multIn[NUM_USB_CHAN_IN + 1];
|
||||
static xc_ptr p_multIn;
|
||||
#endif
|
||||
@@ -41,20 +63,12 @@ static xc_ptr p_multIn;
|
||||
unsigned g_numUsbChan_Out = NUM_USB_CHAN_OUT;
|
||||
unsigned g_numUsbChan_In = NUM_USB_CHAN_IN;
|
||||
|
||||
/* Note we could improve on this, for one subslot is set to 4 */
|
||||
#define MAX_DEVICE_AUD_PACKET_SIZE_MULT_HS ((MAX_FREQ/8000+1)*4)
|
||||
#define MAX_DEVICE_AUD_PACKET_SIZE_MULT_FS ((MAX_FREQ_FS/1000+1)*4)
|
||||
|
||||
#define MAX_DEVICE_AUD_PACKET_SIZE_HS ((MAX_FREQ/8000+1)*NUM_USB_CHAN_IN*4)
|
||||
#define MAX_DEVICE_AUD_PACKET_SIZE_FS ((MAX_FREQ_FS/1000+1)*NUM_USB_CHAN_IN_FS*4)
|
||||
|
||||
#define MAX_DEVICE_AUD_PACKET_SIZE (MAX(MAX_DEVICE_AUD_PACKET_SIZE_FS, MAX_DEVICE_AUD_PACKET_SIZE_HS))
|
||||
|
||||
/* Circular audio buffers */
|
||||
unsigned outAudioBuff[BUFF_SIZE_OUT + (MAX_USB_AUD_PACKET_SIZE>>2) + 4];
|
||||
unsigned audioBuffIn[BUFF_SIZE_IN + (MAX_DEVICE_AUD_PACKET_SIZE>>2) + 4];
|
||||
unsigned outAudioBuff[(BUFF_SIZE_OUT >> 2)+ (MAX_DEVICE_AUD_PACKET_SIZE_OUT >> 2)];
|
||||
unsigned audioBuffIn[(BUFF_SIZE_IN >> 2)+ (MAX_DEVICE_AUD_PACKET_SIZE_IN >> 2)];
|
||||
|
||||
unsigned inZeroBuff[(MAX_DEVICE_AUD_PACKET_SIZE>>2)+4];
|
||||
/* Shift down accounts for bytes -> words */
|
||||
unsigned inZeroBuff[(MAX_DEVICE_AUD_PACKET_SIZE_IN >> 2)];
|
||||
|
||||
void GetADCCounts(unsigned samFreq, int &min, int &mid, int &max);
|
||||
|
||||
@@ -91,8 +105,13 @@ xc_ptr g_aud_to_host_wrptr;
|
||||
xc_ptr g_aud_to_host_dptr;
|
||||
xc_ptr g_aud_to_host_rdptr;
|
||||
xc_ptr g_aud_to_host_zeros;
|
||||
#if (AUDIO_CLASS == 2)
|
||||
int sampsToWrite = DEFAULT_FREQ/8000; /* HS assumed here. Expect to be junked during a overflow before stream start */
|
||||
int totalSampsToWrite = DEFAULT_FREQ/8000;
|
||||
#else
|
||||
int sampsToWrite = DEFAULT_FREQ/1000; /* HS assumed here. Expect to be junked during a overflow before stream start */
|
||||
int totalSampsToWrite = DEFAULT_FREQ/1000;
|
||||
#endif
|
||||
int aud_data_remaining_to_device = 0;
|
||||
|
||||
/* Audio over/under flow flags */
|
||||
@@ -109,15 +128,21 @@ unsigned unpackData = 0;
|
||||
unsigned packState = 0;
|
||||
unsigned packData = 0;
|
||||
|
||||
/* Default to something sensible but the following are setup at stream start: */
|
||||
/* Default to something sensible but the following are setup at stream start (unless UAC1 only..) */
|
||||
#if (AUDIO_CLASS == 2)
|
||||
unsigned g_curSubSlot_Out = HS_STREAM_FORMAT_OUTPUT_1_SUBSLOT_BYTES;
|
||||
unsigned g_curSubSlot_In = HS_STREAM_FORMAT_INPUT_1_SUBSLOT_BYTES;
|
||||
|
||||
/* Init to something sensible, but expect to be re-set before stream start */
|
||||
#if (AUDIO_CLASS==2)
|
||||
int g_maxPacketSize = MAX_DEVICE_AUD_PACKET_SIZE_HS;
|
||||
#else
|
||||
int g_maxPacketSize = MAX_DEVICE_AUD_PACKET_SIZE_FS;
|
||||
unsigned g_curSubSlot_Out = FS_STREAM_FORMAT_OUTPUT_1_SUBSLOT_BYTES;
|
||||
unsigned g_curSubSlot_In = FS_STREAM_FORMAT_INPUT_1_SUBSLOT_BYTES;
|
||||
#endif
|
||||
|
||||
|
||||
/* IN packet size. Init to something sensible, but expect to be re-set before stream start */
|
||||
#if (AUDIO_CLASS==2)
|
||||
int g_maxPacketSize = MAX_DEVICE_AUD_PACKET_SIZE_IN_HS;
|
||||
#else
|
||||
int g_maxPacketSize = MAX_DEVICE_AUD_PACKET_SIZE_IN_FS;
|
||||
#endif
|
||||
|
||||
#pragma select handler
|
||||
@@ -146,7 +171,7 @@ void handle_audio_request(chanend c_mix_out)
|
||||
outSamps = g_aud_from_host_wrptr - g_aud_from_host_rdptr;
|
||||
if (outSamps < 0)
|
||||
{
|
||||
outSamps += BUFF_SIZE_OUT*4;
|
||||
outSamps += BUFF_SIZE_OUT;
|
||||
}
|
||||
|
||||
/* If we have a decent number of samples, come out of underflow cond */
|
||||
@@ -505,7 +530,7 @@ __builtin_unreachable();
|
||||
space_left += datalength;
|
||||
SET_SHARED_GLOBAL(g_aud_to_host_rdptr, rdPtr);
|
||||
|
||||
} while(space_left < (BUFF_SIZE_IN*4/2));
|
||||
} while(space_left < (BUFF_SIZE_IN/2));
|
||||
}
|
||||
|
||||
sampsToWrite = totalSampsToWrite;
|
||||
@@ -594,22 +619,22 @@ void decouple(chanend c_mix_out
|
||||
|
||||
int t = array_to_xc_ptr(outAudioBuff);
|
||||
|
||||
#ifndef OUT_VOLUME_IN_MIXER
|
||||
#if !defined(OUT_VOLUME_IN_MIXER) && (OUTPUT_VOLUME_CONTROL == 1)
|
||||
p_multOut = array_to_xc_ptr(multOut);
|
||||
#endif
|
||||
#ifndef IN_VOLUME_IN_MIXER
|
||||
#if !defined(IN_VOLUME_IN_MIXER) && (INPUT_VOLUME_CONTROL == 1)
|
||||
p_multIn = array_to_xc_ptr(multIn);
|
||||
#endif
|
||||
|
||||
aud_from_host_fifo_start = t;
|
||||
aud_from_host_fifo_end = aud_from_host_fifo_start + BUFF_SIZE_OUT*4;
|
||||
aud_from_host_fifo_end = aud_from_host_fifo_start + BUFF_SIZE_OUT;
|
||||
g_aud_from_host_wrptr = aud_from_host_fifo_start;
|
||||
g_aud_from_host_rdptr = aud_from_host_fifo_start;
|
||||
|
||||
t = array_to_xc_ptr(audioBuffIn);
|
||||
|
||||
aud_to_host_fifo_start = t;
|
||||
aud_to_host_fifo_end = aud_to_host_fifo_start + BUFF_SIZE_IN*4;
|
||||
aud_to_host_fifo_end = aud_to_host_fifo_start + BUFF_SIZE_IN;
|
||||
g_aud_to_host_wrptr = aud_to_host_fifo_start;
|
||||
g_aud_to_host_rdptr = aud_to_host_fifo_start;
|
||||
g_aud_to_host_dptr = aud_to_host_fifo_start + 4;
|
||||
@@ -622,14 +647,14 @@ void decouple(chanend c_mix_out
|
||||
g_aud_to_host_zeros = t;
|
||||
|
||||
/* Init vol mult tables */
|
||||
#ifndef OUT_VOLUME_IN_MIXER
|
||||
#if !defined(OUT_VOLUME_IN_MIXER) && (OUTPUT_VOLUME_CONTROL == 1)
|
||||
for (int i = 0; i < NUM_USB_CHAN_OUT + 1; i++)
|
||||
{
|
||||
asm volatile("stw %0, %1[%2]"::"r"(MAX_VOL),"r"(p_multOut),"r"(i));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef IN_VOLUME_IN_MIXER
|
||||
#if !defined(IN_VOLUME_IN_MIXER) && (INPUT_VOLUME_CONTROL == 1)
|
||||
for (int i = 0; i < NUM_USB_CHAN_IN + 1; i++)
|
||||
{
|
||||
asm volatile("stw %0, %1[%2]"::"r"(MAX_VOL),"r"(p_multIn),"r"(i));
|
||||
@@ -664,10 +689,16 @@ void decouple(chanend c_mix_out
|
||||
aud_to_host_flag = 0;
|
||||
SET_SHARED_GLOBAL(g_aud_to_host_flag, aud_to_host_flag);
|
||||
|
||||
/* NOTE: IN EP not marked ready at this point - Initial size of zero buffer not known
|
||||
/* NOTE: For UAC2 IN EP not marked ready at this point - Initial size of zero buffer not known
|
||||
* since we don't know the USB bus-speed yet.
|
||||
* The host will send a SetAltInterface before streaming which will lead to this core
|
||||
* getting a SET_CHANNEL_COUNT_IN. This will setup the EP for the first packet */
|
||||
#if (AUDIO_CLASS == 1)
|
||||
/* For UAC1 we know we only run at FS */
|
||||
/* Set buffer back to zeros buffer */
|
||||
SET_SHARED_GLOBAL(g_aud_to_host_buffer, g_aud_to_host_zeros);
|
||||
SetupZerosSendBuffer(aud_to_host_usb_ep, sampFreq, g_curSubSlot_In);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
while(1)
|
||||
@@ -687,12 +718,12 @@ void decouple(chanend c_mix_out
|
||||
/* Check for freq change or other update */
|
||||
|
||||
GET_SHARED_GLOBAL(tmp, g_freqChange_flag);
|
||||
#if (MIN_FREQ != MAX_FREQ)
|
||||
if (tmp == SET_SAMPLE_FREQ)
|
||||
{
|
||||
SET_SHARED_GLOBAL(g_freqChange_flag, 0);
|
||||
GET_SHARED_GLOBAL(sampFreq, g_freqChange_sampFreq);
|
||||
|
||||
|
||||
/* Pass on to mixer */
|
||||
DISABLE_INTERRUPTS();
|
||||
inuint(c_mix_out);
|
||||
@@ -734,7 +765,12 @@ void decouple(chanend c_mix_out
|
||||
speedRem = 0;
|
||||
continue;
|
||||
}
|
||||
else if(tmp == SET_STREAM_FORMAT_IN)
|
||||
#endif
|
||||
#if (AUDIO_CLASS == 2)
|
||||
#if (MIN_FREQ != MAX_FREQ)
|
||||
else
|
||||
#endif
|
||||
if(tmp == SET_STREAM_FORMAT_IN)
|
||||
{
|
||||
unsigned dataFormat, usbSpeed;
|
||||
|
||||
@@ -790,6 +826,7 @@ 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);
|
||||
|
||||
/* NOTE, this is potentially usefull for UAC1 */
|
||||
unpackState = 0;
|
||||
|
||||
outUnderflow = 1;
|
||||
@@ -819,6 +856,7 @@ void decouple(chanend c_mix_out
|
||||
SET_SHARED_GLOBAL(g_freqChange, 0);
|
||||
ENABLE_INTERRUPTS();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (NUM_USB_CHAN_OUT > 0)
|
||||
@@ -865,7 +903,7 @@ void decouple(chanend c_mix_out
|
||||
space_left = aud_from_host_fifo_end - g_aud_from_host_wrptr;
|
||||
}
|
||||
|
||||
if (space_left <= 0 || space_left >= MAX_USB_AUD_PACKET_SIZE)
|
||||
if (space_left <= 0 || space_left >= MAX_DEVICE_AUD_PACKET_SIZE_OUT)
|
||||
{
|
||||
SET_SHARED_GLOBAL(g_aud_from_host_buffer, aud_from_host_wrptr);
|
||||
XUD_SetReady_OutPtr(aud_from_host_usb_ep, aud_from_host_wrptr+4);
|
||||
@@ -890,8 +928,8 @@ void decouple(chanend c_mix_out
|
||||
GET_SHARED_GLOBAL(aud_from_host_rdptr, g_aud_from_host_rdptr);
|
||||
space_left = aud_from_host_rdptr - aud_from_host_wrptr;
|
||||
if (space_left <= 0)
|
||||
space_left += BUFF_SIZE_OUT*4;
|
||||
if (space_left >= (BUFF_SIZE_OUT*4/2))
|
||||
space_left += BUFF_SIZE_OUT;
|
||||
if (space_left >= (BUFF_SIZE_OUT/2))
|
||||
{
|
||||
/* Come out of OUT overflow state */
|
||||
outOverflow = 0;
|
||||
@@ -907,10 +945,10 @@ void decouple(chanend c_mix_out
|
||||
#if (NUM_USB_CHAN_IN > 0)
|
||||
{
|
||||
/* Check if buffer() has sent a packet to host - uses shared mem flag to save chanends */
|
||||
int tmp;
|
||||
GET_SHARED_GLOBAL(tmp, g_aud_to_host_flag);
|
||||
int sentPkt;
|
||||
GET_SHARED_GLOBAL(sentPkt, g_aud_to_host_flag);
|
||||
//case inuint_byref(c_buf_in, tmp):
|
||||
if (tmp)
|
||||
if (sentPkt)
|
||||
{
|
||||
/* Signals that the IN endpoint has sent data from the passed buffer */
|
||||
/* Reset flag */
|
||||
@@ -928,7 +966,7 @@ void decouple(chanend c_mix_out
|
||||
fill_level = aud_to_host_wrptr - aud_to_host_rdptr;
|
||||
|
||||
if (fill_level < 0)
|
||||
fill_level += BUFF_SIZE_IN*4;
|
||||
fill_level += BUFF_SIZE_IN;
|
||||
|
||||
if (fill_level >= IN_BUFFER_PREFILL)
|
||||
{
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
#define do_interrupt_handler(f,args) \
|
||||
asm(ISSUE_MODE_SINGLE\
|
||||
".align 4\n" \
|
||||
".cc_top __"#f"_handler.function,__"#f"_handler\n" \
|
||||
"__" #f "_handler:\n" \
|
||||
"ENTSP_lu6 0\n" \
|
||||
"kentsp " #args "/2*2 + 20\n" \
|
||||
@@ -91,7 +92,8 @@
|
||||
restore_state(f,args) \
|
||||
"krestsp " #args "/2*2 + 20 \n" \
|
||||
"__kret:\n" \
|
||||
"kret\n");
|
||||
"kret\n" \
|
||||
".cc_bottom __"#f"_handler.function");
|
||||
|
||||
#define register_interrupt_handler(f, args, nstackwords) \
|
||||
asm (" .section .dp.data, \"adw\", @progbits\n" \
|
||||
@@ -99,7 +101,7 @@
|
||||
" .globl __" #f "_handler\n" \
|
||||
" .align 8\n" \
|
||||
"__" #f "_kernel_stack:\n" \
|
||||
" .space " #nstackwords ", 0\n" \
|
||||
" .space " #nstackwords ", 0\n" \
|
||||
"__" #f "_kernel_stack_end:\n" \
|
||||
" .space 4\n"\
|
||||
" .text\n"); \
|
||||
|
||||
@@ -258,6 +258,11 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in,
|
||||
XUD_SetReady_In(ep_hid, g_hidData, 1);
|
||||
#endif
|
||||
|
||||
#if (AUDIO_CLASS == 1)
|
||||
/* In UAC1 we dont use a stream start event (and we are always FS) so mark FB EP ready now */
|
||||
XUD_SetReady_In(ep_aud_fb, fb_clocks, 3);
|
||||
#endif
|
||||
|
||||
while(1)
|
||||
{
|
||||
XUD_Result_t result;
|
||||
@@ -305,6 +310,7 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in,
|
||||
{
|
||||
unsigned cmd = inuint(c_aud_ctl);
|
||||
|
||||
#if (MAX_FREQ != MIN_FREQ)
|
||||
if(cmd == SET_SAMPLE_FREQ)
|
||||
{
|
||||
unsigned receivedSampleFreq = inuint(c_aud_ctl);
|
||||
@@ -344,7 +350,10 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in,
|
||||
* handshake elsewhere */
|
||||
SET_SHARED_GLOBAL(g_freqChange_sampFreq, receivedSampleFreq);
|
||||
}
|
||||
else if(cmd == SET_STREAM_FORMAT_IN)
|
||||
else
|
||||
#endif
|
||||
#if (AUDIO_CLASS == 2)
|
||||
if(cmd == SET_STREAM_FORMAT_IN)
|
||||
{
|
||||
unsigned formatChange_DataFormat = inuint(c_aud_ctl);
|
||||
unsigned formatChange_NumChans = inuint(c_aud_ctl);
|
||||
@@ -356,8 +365,10 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in,
|
||||
SET_SHARED_GLOBAL(g_formatChange_DataFormat, formatChange_DataFormat);
|
||||
SET_SHARED_GLOBAL(g_formatChange_SampRes, formatChange_SampRes);
|
||||
}
|
||||
/* FIXME when FB EP is enabled there is no inital XUD_SetReady */
|
||||
else if (cmd == SET_STREAM_FORMAT_OUT)
|
||||
{
|
||||
|
||||
XUD_BusSpeed_t busSpeed;
|
||||
unsigned formatChange_DataFormat = inuint(c_aud_ctl);
|
||||
unsigned formatChange_NumChans = inuint(c_aud_ctl);
|
||||
@@ -385,6 +396,7 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in,
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/* Pass on sample freq change to decouple() via global flag (saves a chanend) */
|
||||
/* Note: freqChange flags now used to communicate other commands also */
|
||||
SET_SHARED_GLOBAL0(g_freqChange, cmd); /* Set command */
|
||||
|
||||
@@ -65,11 +65,10 @@ Warnings relating to configuration defines located in this XC source file rather
|
||||
|
||||
/* Sanity check on FS channel counts */
|
||||
#if (NUM_USB_CHAN_OUT_FS > NUM_USB_CHAN_OUT)
|
||||
#error NUM_USB_CHAN_OUT expected to be less than or equal to NUM_USB_CHAN_OUT
|
||||
#error NUM_USB_CHAN_OUT_FS expected to be less than or equal to NUM_USB_CHAN_OUT
|
||||
#endif
|
||||
|
||||
#if (NUM_USB_CHAN_IN_FS > NUM_USB_CHAN_IN)
|
||||
#error NUM_USB_CHAN_IN expected to be less than or equal to NUM_USB_CHAN_IN
|
||||
#error NUM_USB_CHAN_IN_FS expected to be less than or equal to NUM_USB_CHAN_IN
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
5
xpd.xml
5
xpd.xml
@@ -15,7 +15,7 @@
|
||||
</component>
|
||||
<component description = "MIDI" type = "demoCode" scope = "General Use" path = "module_usb_midi" local = "false" id = "module_usb_midi" name = "MIDI Module for USB Audio Framework">
|
||||
<board></board>
|
||||
<componentDependency version = "6.18.0">module_queue</componentDependency>
|
||||
<componentDependency version = "6.18.1">module_queue</componentDependency>
|
||||
<keyword>MIDI</keyword>
|
||||
</component>
|
||||
</components>
|
||||
@@ -104,7 +104,8 @@
|
||||
<release parenthash = "136edf6bf7393d30e1f85197b72585c22611d94f" version = "6.15.2rc0" githash = "ef12c7afda6d448e22b7eb53c21d23e986db7b0d"></release>
|
||||
<release parenthash = "d0929ae0676896b94a119e4b7c44ffadec1471d8" version = "6.16.0alpha0" githash = "5f2fec1d2ab32999c69536635f21ca42312dc267"></release>
|
||||
<release parenthash = "60b6ca27825c4ab385fb945acf23089a4240a5ba" version = "6.18.0alpha0" githash = "37855df2f1b9a0c32d8c37e9c98853df4740e446"></release>
|
||||
<release parenthash = "f770595930dac7e19fce394908a5817c34a79cda" version = "6.18.1alpha0"></release>
|
||||
<release parenthash = "f770595930dac7e19fce394908a5817c34a79cda" version = "6.18.1alpha0" githash = "084863d720a4175b7248d68edb13f0d853321142"></release>
|
||||
<release parenthash = "c3cae7fe525f1470ffae49e1f0955324924a1947" version = "6.19.0alpha0"></release>
|
||||
<subpartnumber>XM-004720-SM</subpartnumber>
|
||||
<vendor>XMOS</vendor>
|
||||
<version_defines>
|
||||
|
||||
Reference in New Issue
Block a user