Merge branch 'master' of git://git.xmos.local/apps/sc_usb_audio

This commit is contained in:
Ross Owen
2017-01-17 14:44:36 +00:00
3 changed files with 135 additions and 92 deletions

View File

@@ -57,17 +57,28 @@ static unsigned samplesIn[2][MAX(NUM_USB_CHAN_IN, IN_CHAN_COUNT)];
#undef SPDIF_RX
#endif
static int downsamplingCounter = 0;
#if (I2S_DOWNSAMPLE_FACTOR > 1)
static int inDownsamplingCounter = 0;
static int outDownsamplingCounter = 0;
#if (I2S_DOWNSAMPLE_FACTOR_IN > 1) || (I2S_DOWNSAMPLE_FACTOR_OUT > 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];
/* delay lines = [Number of I2S channels][Number of samples/phases][Taps per phase] */
#if (I2S_DOWNSAMPLE_FACTOR_IN > 1)
int32_t inputDelayLine[I2S_DOWNSAMPLE_CHANS_IN][I2S_DOWNSAMPLE_FACTOR_IN][24];
#endif // (I2S_DOWNSAMPLE_FACTOR_IN > 1)
#if (I2S_DOWNSAMPLE_FACTOR_OUT > 1)
int32_t outputDelayLine[I2S_DOWNSAMPLE_CHANS_OUT][I2S_DOWNSAMPLE_FACTOR_OUT][24];
#endif // (I2S_DOWNSAMPLE_FACTOR_OUT > 1)
} ds3Data;
static int64_t ds3Sum[I2S_DOWNSAMPLE_CHANS];
#endif
#if (I2S_DOWNSAMPLE_FACTOR_IN > 1)
static int64_t inputDs3Sum[I2S_DOWNSAMPLE_CHANS_IN];
#endif // (I2S_DOWNSAMPLE_FACTOR_IN > 1)
#if (I2S_DOWNSAMPLE_FACTOR_OUT > 1)
static int64_t outputDs3Sum[I2S_DOWNSAMPLE_CHANS_OUT];
#endif // (I2S_DOWNSAMPLE_FACTOR_OUT > 1)
#endif // (I2S_DOWNSAMPLE_FACTOR_IN > 1) || (I2S_DOWNSAMPLE_FACTOR_OUT > 1)
#if (DSD_CHANS_DAC != 0)
extern buffered out port:32 p_dsd_dac[DSD_CHANS_DAC];
@@ -501,8 +512,8 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
}
#endif
#if (I2S_DOWNSAMPLE_FACTOR > 1)
memset(&ds3Data.delayLine, 0, sizeof ds3Data);
#if (I2S_DOWNSAMPLE_FACTOR_IN > 1)
memset(&ds3Data.inputDelayLine, 0, sizeof ds3Data);
#endif
unsigned command = DoSampleTransfer(c_out, readBuffNo, underflowWord, i_audMan);
@@ -519,7 +530,7 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
return command;
}
downsamplingCounter = 0;
inDownsamplingCounter = 0;
InitPorts(divide);
@@ -651,10 +662,10 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
else
#endif
{
#if (I2S_DOWNSAMPLE_FACTOR > 1)
if (0 == downsamplingCounter)
#if (I2S_DOWNSAMPLE_FACTOR_IN > 1)
if (0 == inDownsamplingCounter)
{
memset(&ds3Sum, 0, sizeof ds3Sum);
memset(&inputDs3Sum, 0, sizeof inputDs3Sum);
}
#endif
#if (I2S_CHANS_ADC != 0)
@@ -683,26 +694,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)
#if (I2S_DOWNSAMPLE_FACTOR_IN > 1)
if ((I2S_DOWNSAMPLE_FACTOR_IN - 1) == inDownsamplingCounter)
{
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],
inputDs3Sum[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i],
ds3Data.inputDelayLine[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i][inDownsamplingCounter],
src_ff3v_ds3_voice_coefs[inDownsamplingCounter],
samplesIn[readBuffNo][((frameCount-2)&(I2S_CHANS_PER_FRAME-1))]);
}
else
{
ds3Sum[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i] =
inputDs3Sum[((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],
inputDs3Sum[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i],
ds3Data.inputDelayLine[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i][inDownsamplingCounter],
src_ff3v_ds3_voice_coefs[inDownsamplingCounter],
samplesIn[readBuffNo][((frameCount-2)&(I2S_CHANS_PER_FRAME-1))]);
}
#endif // (I2S_DOWNSAMPLE_FACTOR > 1)
#endif // (I2S_DOWNSAMPLE_FACTOR_IN > 1)
}
#endif
@@ -723,20 +734,22 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
#pragma xta endpoint "i2s_output_l"
#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0)
index = 0;
#pragma loop unroll
/* Output "even" channel to DAC (i.e. left) */
for(int i = 0; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME)
if ((I2S_DOWNSAMPLE_FACTOR_OUT - 1) == outDownsamplingCounter)
{
p_i2s_dac[index++] <: bitrev(samplesOut[frameCount +i]);
}
index = 0;
#pragma loop unroll
/* Output "even" channel to DAC (i.e. left) */
for(int i = 0; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME)
{
p_i2s_dac[index++] <: bitrev(samplesOut[frameCount +i]);
}
#endif
#ifndef CODEC_MASTER
/* Clock out the LR Clock, the DAC data and Clock in the next sample into ADC */
doI2SClocks(divide);
/* Clock out the LR Clock, the DAC data and Clock in the next sample into ADC */
doI2SClocks(divide);
#endif
}
#ifdef ADAT_TX
TransferAdatTxSamples(c_adat_out, samplesOut, adatSmuxMode, 1);
#endif
@@ -776,7 +789,7 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
#endif
#if (NUM_PDM_MICS > 0)
if ((I2S_DOWNSAMPLE_FACTOR - 1) == downsamplingCounter)
if ((I2S_DOWNSAMPLE_FACTOR_IN - 1) == inDownsamplingCounter)
{
/* Get samples from PDM->PCM comverter */
c_pdm_pcm <: 1;
@@ -819,26 +832,26 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
#endif // CODEC_MASTER
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)
#if ((I2S_DOWNSAMPLE_FACTOR_IN > 1) && !I2S_DOWNSAMPLE_MONO_IN)
if ((I2S_DOWNSAMPLE_FACTOR_IN - 1) == inDownsamplingCounter)
{
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],
inputDs3Sum[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i],
ds3Data.inputDelayLine[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i][inDownsamplingCounter],
src_ff3v_ds3_voice_coefs[inDownsamplingCounter],
samplesIn[readBuffNo][((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i]);
}
else
{
ds3Sum[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i] =
inputDs3Sum[((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],
inputDs3Sum[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i],
ds3Data.inputDelayLine[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i][inDownsamplingCounter],
src_ff3v_ds3_voice_coefs[inDownsamplingCounter],
samplesIn[readBuffNo][((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i]);
}
#endif // ((I2S_DOWNSAMPLE_FACTOR > 1) && !I2S_DOWNSAMPLE_MONO)
#endif // ((I2S_DOWNSAMPLE_FACTOR_IN > 1) && !I2S_DOWNSAMPLE_MONO_IN)
}
#endif
@@ -857,19 +870,24 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
index = 0;
#pragma xta endpoint "i2s_output_r"
#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0)
/* Output "odd" channel to DAC (i.e. right) */
#pragma loop unroll
for(int i = 1; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME)
if ((I2S_DOWNSAMPLE_FACTOR_OUT - 1) == outDownsamplingCounter)
{
p_i2s_dac[index++] <: bitrev(samplesOut[frameCount + i]);
}
/* Output "odd" channel to DAC (i.e. right) */
#pragma loop unroll
for(int i = 1; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME)
{
p_i2s_dac[index++] <: bitrev(samplesOut[frameCount + i]);
}
#endif
#ifndef CODEC_MASTER
doI2SClocks(divide);
doI2SClocks(divide);
#endif
}
else
{
++outDownsamplingCounter;
}
} // !dsdMode
#if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0)
@@ -924,7 +942,7 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
if(frameCount == I2S_CHANS_PER_FRAME)
#endif
{
if ((I2S_DOWNSAMPLE_FACTOR - 1) == downsamplingCounter)
if ((I2S_DOWNSAMPLE_FACTOR_IN - 1) == inDownsamplingCounter)
{
/* Do samples transfer */
/* The below looks a bit odd but forces the compiler to inline twice */
@@ -940,13 +958,13 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
}
/* Reset frame counter and flip the ADC buffer */
downsamplingCounter = 0;
inDownsamplingCounter = 0;
frameCount = 0;
readBuffNo = !readBuffNo;
}
else
{
++downsamplingCounter;
++inDownsamplingCounter;
}
}
}
@@ -1063,7 +1081,7 @@ chanend ?c_config, chanend ?c
unsigned adatMultiple = 0;
#endif
unsigned curSamFreq = DEFAULT_FREQ * I2S_DOWNSAMPLE_FACTOR;
unsigned curSamFreq = DEFAULT_FREQ * I2S_DOWNSAMPLE_FACTOR_IN;
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;
@@ -1218,7 +1236,7 @@ chanend ?c_config, chanend ?c
{
/* TODO wait for good mclk instead of delay */
/* No delay for DFU modes */
if (((curSamFreq / I2S_DOWNSAMPLE_FACTOR) != AUDIO_REBOOT_FROM_DFU) && ((curSamFreq / I2S_DOWNSAMPLE_FACTOR) != AUDIO_STOP_FOR_DFU) && command)
if (((curSamFreq / I2S_DOWNSAMPLE_FACTOR_IN) != AUDIO_REBOOT_FROM_DFU) && ((curSamFreq / I2S_DOWNSAMPLE_FACTOR_IN) != AUDIO_STOP_FOR_DFU) && command)
{
#if 0
/* User should ensure MCLK is stable in AudioHwConfig */
@@ -1261,7 +1279,7 @@ chanend ?c_config, chanend ?c
#if NUM_PDM_MICS > 0
/* Send decimation factor to PDM task(s) */
c_pdm_in <: curSamFreq / I2S_DOWNSAMPLE_FACTOR;
c_pdm_in <: curSamFreq / I2S_DOWNSAMPLE_FACTOR_IN;
#endif
#ifdef ADAT_TX
@@ -1299,7 +1317,7 @@ chanend ?c_config, chanend ?c
if(command == SET_SAMPLE_FREQ)
{
curSamFreq = inuint(c_mix_out) * I2S_DOWNSAMPLE_FACTOR;
curSamFreq = inuint(c_mix_out) * I2S_DOWNSAMPLE_FACTOR_IN;
}
else if(command == SET_STREAM_FORMAT_OUT)
{
@@ -1312,7 +1330,7 @@ chanend ?c_config, chanend ?c
}
/* Currently no more audio will happen after this point */
if ((curSamFreq / I2S_DOWNSAMPLE_FACTOR) == AUDIO_STOP_FOR_DFU)
if ((curSamFreq / I2S_DOWNSAMPLE_FACTOR_IN) == AUDIO_STOP_FOR_DFU)
{
outct(c_mix_out, XS1_CT_END);

View File

@@ -126,21 +126,34 @@
*
* Default: 1 i.e. downsampling is disabled.
*/
#ifndef I2S_DOWNSAMPLE_FACTOR
#define I2S_DOWNSAMPLE_FACTOR (1)
#ifndef I2S_DOWNSAMPLE_FACTOR_IN
#define I2S_DOWNSAMPLE_FACTOR_IN (1)
#else
#if (I2S_DOWNSAMPLE_FACTOR != 3) && (I2S_DOWNSAMPLE_FACTOR != 1)
#error Unsupported I2S downsampling configuration
#if (I2S_DOWNSAMPLE_FACTOR_IN != 3) && (I2S_DOWNSAMPLE_FACTOR_IN != 1)
#error Unsupported I2S input downsampling configuration
#endif
#endif
/**
* @brief Only downsample one channel per I2S frame.
* @brief Output I2S (host to device) channels can be downsampled by a factor of 3.
*
* Default: 0 i.e. mono mode is disabled, all channels will be downsampled.
* Default: 1 i.e. downsampling is disabled.
*/
#ifndef I2S_DOWNSAMPLE_MONO
#define I2S_DOWNSAMPLE_MONO (0)
#ifndef I2S_DOWNSAMPLE_FACTOR_OUT
#define I2S_DOWNSAMPLE_FACTOR_OUT (1)
#else
#if (I2S_DOWNSAMPLE_FACTOR_OUT != 3) && (I2S_DOWNSAMPLE_FACTOR_OUT != 1)
#error Unsupported I2S output downsampling configuration
#endif
#endif
/**
* @brief Only downsample one channel per input I2S frame.
*
* Default: 0 i.e. mono mode is disabled, all input channels will be downsampled.
*/
#ifndef I2S_DOWNSAMPLE_MONO_IN
#define I2S_DOWNSAMPLE_MONO_IN (0)
#endif
/**
@@ -148,15 +161,22 @@
*
* 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
#if (I2S_DOWNSAMPLE_MONO_IN == 1)
#define I2S_DOWNSAMPLE_CHANS_IN (I2S_CHANS_ADC / 2)
#if ((I2S_DOWNSAMPLE_FACTOR_IN > 1) && (I2S_MODE_TDM == 1))
#error Mono I2S input downsampling is not avaliable in TDM mode
#endif
#else
#define I2S_DOWNSAMPLE_CHANS I2S_CHANS_ADC
#define I2S_DOWNSAMPLE_CHANS_IN I2S_CHANS_ADC
#endif
/**
* @brief Number of output (host to device) I2S channels to downsample.
*
* Default: The number of I2S output channels.
*/
#define I2S_DOWNSAMPLE_CHANS_OUT I2S_CHANS_ADC
/**
* @brief Max supported sample frequency for device (Hz). Default: 192000
*/