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

@@ -1,9 +1,14 @@
sc_usb_audio Change Log sc_usb_audio Change Log
======================= =======================
7.0.2
-----
- ADDED: I2S output down-sampling (I2S_DOWNSAMPLE_FACTOR_OUT)
- CHANGE: Rename I2S input down-sampling (I2S_DOWNSAMPLE_FACTOR to I2S_DOWNSAMPLE_FACTOR_IN)
7.0.1 7.0.1
----- -----
- RESOLVED: PDM microphone decimation issue at some samplerates caused by integration - RESOLVED: PDM microphone decimation issue at some sample rates caused by integration
7.0.0 7.0.0
------ ------
@@ -14,7 +19,7 @@ sc_usb_audio Change Log
- CHANGE: Various memory optimisations in UAC1 mode - CHANGE: Various memory optimisations in UAC1 mode
- CHANGE: user_pdm_process() API change - CHANGE: user_pdm_process() API change
- CHANGE: PDM Mic decimator table now related to MIN_FREQ (memory optimisation) - CHANGE: PDM Mic decimator table now related to MIN_FREQ (memory optimisation)
- RESOLVED: Audio request interrupt handler properly elminated - RESOLVED: Audio request interrupt handler properly eliminated
6.30.0 6.30.0
------ ------
@@ -25,7 +30,7 @@ sc_usb_audio Change Log
6.20.0 6.20.0
------ ------
- RESOLVED: Intra-frame sample delays of 1/2 samples on input streaming in TDM mode - 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: 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: 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: Failure to enter DFU mode when configured without input volume control
@@ -51,7 +56,7 @@ sc_usb_audio Change Log
------ ------
- ADDED: Call to UserBufferManagement() - ADDED: Call to UserBufferManagement()
- ADDED: PDM_MIC_INDEX in devicedefines.h and usage - ADDED: PDM_MIC_INDEX in devicedefines.h and usage
- CHANGE: pdm_buffer() task now combinable - CHANGE: pdm_buffer() task now combinable
- CHANGE: Audio I/O task now takes i_dsp interface as a parameter - CHANGE: Audio I/O task now takes i_dsp interface as a parameter
- CHANGE: Removed built-in support for A/U series internal ADC - CHANGE: Removed built-in support for A/U series internal ADC
- CHANGE: User PDM Microphone processing now uses an interface (previously function call) - CHANGE: User PDM Microphone processing now uses an interface (previously function call)
@@ -67,45 +72,45 @@ sc_usb_audio Change Log
6.15.0 6.15.0
------ ------
- RESOLVED: UAC 1.0 descriptors now support multi-channel volume control (previously were - RESOLVED: UAC 1.0 descriptors now support multi-channel volume control (previously were
hard-coded as stereo) hard-coded as stereo)
- CHANGE: Removed 32kHz sample-rate support when PDM microphones enabled (lib_mic_array - CHANGE: Removed 32kHz sample-rate support when PDM microphones enabled (lib_mic_array
currently does not support non-integer decimation factors) currently does not support non-integer decimation factors)
6.14.0 6.14.0
------ ------
- ADDED: Support for for master-clock/sample-rate divides that are not a power of 2 - ADDED: Support for for master-clock/sample-rate divides that are not a power of 2
(i.e. 32kHz from 24.567MHz) (i.e. 32kHz from 24.567MHz)
- ADDED: Extended available sample-rate/master-clock ratios. Previous restriction was <= - ADDED: Extended available sample-rate/master-clock ratios. Previous restriction was <=
512x (i.e. could not support 1024x and above e.g. 49.152MHz MCLK for Sample Rates 512x (i.e. could not support 1024x and above e.g. 49.152MHz MCLK for Sample Rates
below 96kHz) (#13893) below 96kHz) (#13893)
- ADDED: Support for various "low" sample rates (i.e. < 44100) into UAC 2.0 sample rate - ADDED: Support for various "low" sample rates (i.e. < 44100) into UAC 2.0 sample rate
list and UAC 1.0 descriptors list and UAC 1.0 descriptors
- ADDED: Support for the use and integration of PDM microphones (including PDM to PCM - ADDED: Support for the use and integration of PDM microphones (including PDM to PCM
conversion) via lib_mic_array conversion) via lib_mic_array
- RESOLVED: MIDI data not accepted after "sleep" in OSX 10.11 (El Capitan) - related to sc_xud - RESOLVED: MIDI data not accepted after "sleep" in OSX 10.11 (El Capitan) - related to sc_xud
issue #17092 issue #17092
- CHANGE: Asynchronous feedback system re-implemented to allow for the first two ADDED - CHANGE: Asynchronous feedback system re-implemented to allow for the first two ADDED
changelog items changelog items
- CHANGE: Hardware divider used to generate bit-clock from master clock (xCORE-200 only). - CHANGE: Hardware divider used to generate bit-clock from master clock (xCORE-200 only).
Allows easy support for greater number of master-clock to sample-rate ratios. Allows easy support for greater number of master-clock to sample-rate ratios.
- CHANGE: module_queue no longer uses any assert module/lib - CHANGE: module_queue no longer uses any assert module/lib
6.13.0 6.13.0
------ ------
- ADDED: Device now uses implicit feedback when input stream is available (previously explicit - ADDED: Device now uses implicit feedback when input stream is available (previously explicit
feedback pipe always used). This saves chanend/EP resources and means less processing feedback pipe always used). This saves chanend/EP resources and means less processing
burden for the host. Previous behaviour available by enabling UAC_FORCE_FEEDBACK_EP burden for the host. Previous behaviour available by enabling UAC_FORCE_FEEDBACK_EP
- RESOLVED: Exception when SPDIF_TX and ADAT_TX both enabled due to clock-block being configured - RESOLVED: Exception when SPDIF_TX and ADAT_TX both enabled due to clock-block being configured
after already started. Caused by SPDIF_TX define check typo after already started. Caused by SPDIF_TX define check typo
- RESOLVED: DFU flag address changed to properly conform to memory address range allocated to - RESOLVED: DFU flag address changed to properly conform to memory address range allocated to
apps by tools apps by tools
- RESOLVED: Build failure when DFU disabled - RESOLVED: Build failure when DFU disabled
- RESOLVED: Build issue when I2S_CHANS_ADC/DAC set to 0 and CODEC_MASTER enabled - RESOLVED: Build issue when I2S_CHANS_ADC/DAC set to 0 and CODEC_MASTER enabled
- RESOLVED: Typo in MCLK_441 checking for MIN_FREQ define - RESOLVED: Typo in MCLK_441 checking for MIN_FREQ define
- CHANGE: Mixer and non-mixer channel comms scheme (decouple <-> audio path) now identical - CHANGE: Mixer and non-mixer channel comms scheme (decouple <-> audio path) now identical
- CHANGE: Input stream buffering modified such that during overflow older samples are removed - CHANGE: Input stream buffering modified such that during overflow older samples are removed
rather than ignoring most recent samples. Removes any chance of stale input packets rather than ignoring most recent samples. Removes any chance of stale input packets
being sent to host being sent to host
- CHANGE: module_queue (in sc_usb_audio) now uses lib_xassert rather than module_xassert - CHANGE: module_queue (in sc_usb_audio) now uses lib_xassert rather than module_xassert
@@ -116,17 +121,17 @@ sc_usb_audio Change Log
- RESOLVED: Build error when I2S_CHANS_ADC or I2S_CHANS_DAC set to 0 and CODEC_MASTER enabled - RESOLVED: Build error when I2S_CHANS_ADC or I2S_CHANS_DAC set to 0 and CODEC_MASTER enabled
6.12.5 6.12.5
------ ------
- RESOLVED: Stream issue when NUM_USB_CHAN_IN < I2S_CHANS_ADC - RESOLVED: Stream issue when NUM_USB_CHAN_IN < I2S_CHANS_ADC
6.12.4 6.12.4
------ ------
- RESOLVED: DFU fail when DSD enabled and USB library not running on tile[0] - RESOLVED: DFU fail when DSD enabled and USB library not running on tile[0]
6.12.3 6.12.3
------ ------
- RESOLVED: Method for storing persistent state over a DFU reboot modified to improve resilience - RESOLVED: Method for storing persistent state over a DFU reboot modified to improve resilience
against code-base and tools changes against code-base and tools changes
6.12.2 6.12.2
------ ------

View File

@@ -57,17 +57,28 @@ static unsigned samplesIn[2][MAX(NUM_USB_CHAN_IN, IN_CHAN_COUNT)];
#undef SPDIF_RX #undef SPDIF_RX
#endif #endif
static int downsamplingCounter = 0; static int inDownsamplingCounter = 0;
#if (I2S_DOWNSAMPLE_FACTOR > 1) static int outDownsamplingCounter = 0;
#if (I2S_DOWNSAMPLE_FACTOR_IN > 1) || (I2S_DOWNSAMPLE_FACTOR_OUT > 1)
#include "src.h" #include "src.h"
static union ds3Data static union ds3Data
{ {
long long doubleWordAlignmentEnsured; long long doubleWordAlignmentEnsured;
/* [Number of I2S channels][Number of samples/phases][Taps per phase] */ /* delay lines = [Number of I2S channels][Number of samples/phases][Taps per phase] */
int32_t delayLine[I2S_DOWNSAMPLE_CHANS][I2S_DOWNSAMPLE_FACTOR][24]; #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; } ds3Data;
static int64_t ds3Sum[I2S_DOWNSAMPLE_CHANS]; #if (I2S_DOWNSAMPLE_FACTOR_IN > 1)
#endif 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) #if (DSD_CHANS_DAC != 0)
extern buffered out port:32 p_dsd_dac[DSD_CHANS_DAC]; 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 #endif
#if (I2S_DOWNSAMPLE_FACTOR > 1) #if (I2S_DOWNSAMPLE_FACTOR_IN > 1)
memset(&ds3Data.delayLine, 0, sizeof ds3Data); memset(&ds3Data.inputDelayLine, 0, sizeof ds3Data);
#endif #endif
unsigned command = DoSampleTransfer(c_out, readBuffNo, underflowWord, i_audMan); 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; return command;
} }
downsamplingCounter = 0; inDownsamplingCounter = 0;
InitPorts(divide); InitPorts(divide);
@@ -651,10 +662,10 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
else else
#endif #endif
{ {
#if (I2S_DOWNSAMPLE_FACTOR > 1) #if (I2S_DOWNSAMPLE_FACTOR_IN > 1)
if (0 == downsamplingCounter) if (0 == inDownsamplingCounter)
{ {
memset(&ds3Sum, 0, sizeof ds3Sum); memset(&inputDs3Sum, 0, sizeof inputDs3Sum);
} }
#endif #endif
#if (I2S_CHANS_ADC != 0) #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 */ /* 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. 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_IN > 1)
if ((I2S_DOWNSAMPLE_FACTOR - 1) == downsamplingCounter) if ((I2S_DOWNSAMPLE_FACTOR_IN - 1) == inDownsamplingCounter)
{ {
samplesIn[readBuffNo][((frameCount-2)&(I2S_CHANS_PER_FRAME-1))] = samplesIn[readBuffNo][((frameCount-2)&(I2S_CHANS_PER_FRAME-1))] =
src_ds3_voice_add_final_sample( src_ds3_voice_add_final_sample(
ds3Sum[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i], inputDs3Sum[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i],
ds3Data.delayLine[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i][downsamplingCounter], ds3Data.inputDelayLine[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i][inDownsamplingCounter],
src_ff3v_ds3_voice_coefs[downsamplingCounter], src_ff3v_ds3_voice_coefs[inDownsamplingCounter],
samplesIn[readBuffNo][((frameCount-2)&(I2S_CHANS_PER_FRAME-1))]); samplesIn[readBuffNo][((frameCount-2)&(I2S_CHANS_PER_FRAME-1))]);
} }
else else
{ {
ds3Sum[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i] = inputDs3Sum[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i] =
src_ds3_voice_add_sample( src_ds3_voice_add_sample(
ds3Sum[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i], inputDs3Sum[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i],
ds3Data.delayLine[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i][downsamplingCounter], ds3Data.inputDelayLine[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i][inDownsamplingCounter],
src_ff3v_ds3_voice_coefs[downsamplingCounter], src_ff3v_ds3_voice_coefs[inDownsamplingCounter],
samplesIn[readBuffNo][((frameCount-2)&(I2S_CHANS_PER_FRAME-1))]); samplesIn[readBuffNo][((frameCount-2)&(I2S_CHANS_PER_FRAME-1))]);
} }
#endif // (I2S_DOWNSAMPLE_FACTOR > 1) #endif // (I2S_DOWNSAMPLE_FACTOR_IN > 1)
} }
#endif #endif
@@ -723,20 +734,22 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
#pragma xta endpoint "i2s_output_l" #pragma xta endpoint "i2s_output_l"
#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) #if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0)
index = 0; if ((I2S_DOWNSAMPLE_FACTOR_OUT - 1) == outDownsamplingCounter)
#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]); 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 #endif
#ifndef CODEC_MASTER #ifndef CODEC_MASTER
/* Clock out the LR Clock, the DAC data and Clock in the next sample into ADC */ /* Clock out the LR Clock, the DAC data and Clock in the next sample into ADC */
doI2SClocks(divide); doI2SClocks(divide);
#endif #endif
}
#ifdef ADAT_TX #ifdef ADAT_TX
TransferAdatTxSamples(c_adat_out, samplesOut, adatSmuxMode, 1); TransferAdatTxSamples(c_adat_out, samplesOut, adatSmuxMode, 1);
#endif #endif
@@ -776,7 +789,7 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
#endif #endif
#if (NUM_PDM_MICS > 0) #if (NUM_PDM_MICS > 0)
if ((I2S_DOWNSAMPLE_FACTOR - 1) == downsamplingCounter) if ((I2S_DOWNSAMPLE_FACTOR_IN - 1) == inDownsamplingCounter)
{ {
/* Get samples from PDM->PCM comverter */ /* Get samples from PDM->PCM comverter */
c_pdm_pcm <: 1; c_pdm_pcm <: 1;
@@ -819,26 +832,26 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
#endif // CODEC_MASTER #endif // CODEC_MASTER
samplesIn[buffIndex][((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i] = bitrev(sample); // channels 1, 3, 5.. on each line. 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_IN > 1) && !I2S_DOWNSAMPLE_MONO_IN)
if ((I2S_DOWNSAMPLE_FACTOR - 1) == downsamplingCounter) if ((I2S_DOWNSAMPLE_FACTOR_IN - 1) == inDownsamplingCounter)
{ {
samplesIn[buffIndex][((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i] = samplesIn[buffIndex][((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i] =
src_ds3_voice_add_final_sample( src_ds3_voice_add_final_sample(
ds3Sum[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i], inputDs3Sum[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i],
ds3Data.delayLine[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i][downsamplingCounter], ds3Data.inputDelayLine[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i][inDownsamplingCounter],
src_ff3v_ds3_voice_coefs[downsamplingCounter], src_ff3v_ds3_voice_coefs[inDownsamplingCounter],
samplesIn[readBuffNo][((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i]); samplesIn[readBuffNo][((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i]);
} }
else else
{ {
ds3Sum[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i] = inputDs3Sum[((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i] =
src_ds3_voice_add_sample( src_ds3_voice_add_sample(
ds3Sum[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i], inputDs3Sum[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i],
ds3Data.delayLine[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i][downsamplingCounter], ds3Data.inputDelayLine[((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i][inDownsamplingCounter],
src_ff3v_ds3_voice_coefs[downsamplingCounter], src_ff3v_ds3_voice_coefs[inDownsamplingCounter],
samplesIn[readBuffNo][((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i]); 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 #endif
@@ -857,19 +870,24 @@ unsigned static deliver(chanend c_out, chanend ?c_spd_out,
index = 0; index = 0;
#pragma xta endpoint "i2s_output_r" #pragma xta endpoint "i2s_output_r"
#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) #if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0)
/* Output "odd" channel to DAC (i.e. right) */ if ((I2S_DOWNSAMPLE_FACTOR_OUT - 1) == outDownsamplingCounter)
#pragma loop unroll
for(int i = 1; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME)
{ {
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 #endif
#ifndef CODEC_MASTER #ifndef CODEC_MASTER
doI2SClocks(divide); doI2SClocks(divide);
#endif #endif
}
else
{
++outDownsamplingCounter;
}
} // !dsdMode } // !dsdMode
#if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) #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) if(frameCount == I2S_CHANS_PER_FRAME)
#endif #endif
{ {
if ((I2S_DOWNSAMPLE_FACTOR - 1) == downsamplingCounter) if ((I2S_DOWNSAMPLE_FACTOR_IN - 1) == inDownsamplingCounter)
{ {
/* Do samples transfer */ /* Do samples transfer */
/* The below looks a bit odd but forces the compiler to inline twice */ /* 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 */ /* Reset frame counter and flip the ADC buffer */
downsamplingCounter = 0; inDownsamplingCounter = 0;
frameCount = 0; frameCount = 0;
readBuffNo = !readBuffNo; readBuffNo = !readBuffNo;
} }
else else
{ {
++downsamplingCounter; ++inDownsamplingCounter;
} }
} }
} }
@@ -1063,7 +1081,7 @@ chanend ?c_config, chanend ?c
unsigned adatMultiple = 0; unsigned adatMultiple = 0;
#endif #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_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 curSamRes_ADC = STREAM_FORMAT_INPUT_1_RESOLUTION_BITS; /* Default to something reasonable - note, currently this never changes*/
unsigned command; unsigned command;
@@ -1218,7 +1236,7 @@ chanend ?c_config, chanend ?c
{ {
/* TODO wait for good mclk instead of delay */ /* TODO wait for good mclk instead of delay */
/* No delay for DFU modes */ /* 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 #if 0
/* User should ensure MCLK is stable in AudioHwConfig */ /* User should ensure MCLK is stable in AudioHwConfig */
@@ -1261,7 +1279,7 @@ chanend ?c_config, chanend ?c
#if NUM_PDM_MICS > 0 #if NUM_PDM_MICS > 0
/* Send decimation factor to PDM task(s) */ /* Send decimation factor to PDM task(s) */
c_pdm_in <: curSamFreq / I2S_DOWNSAMPLE_FACTOR; c_pdm_in <: curSamFreq / I2S_DOWNSAMPLE_FACTOR_IN;
#endif #endif
#ifdef ADAT_TX #ifdef ADAT_TX
@@ -1299,7 +1317,7 @@ chanend ?c_config, chanend ?c
if(command == SET_SAMPLE_FREQ) 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) 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 */ /* 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); outct(c_mix_out, XS1_CT_END);

View File

@@ -126,21 +126,34 @@
* *
* Default: 1 i.e. downsampling is disabled. * Default: 1 i.e. downsampling is disabled.
*/ */
#ifndef I2S_DOWNSAMPLE_FACTOR #ifndef I2S_DOWNSAMPLE_FACTOR_IN
#define I2S_DOWNSAMPLE_FACTOR (1) #define I2S_DOWNSAMPLE_FACTOR_IN (1)
#else #else
#if (I2S_DOWNSAMPLE_FACTOR != 3) && (I2S_DOWNSAMPLE_FACTOR != 1) #if (I2S_DOWNSAMPLE_FACTOR_IN != 3) && (I2S_DOWNSAMPLE_FACTOR_IN != 1)
#error Unsupported I2S downsampling configuration #error Unsupported I2S input downsampling configuration
#endif #endif
#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 #ifndef I2S_DOWNSAMPLE_FACTOR_OUT
#define I2S_DOWNSAMPLE_MONO (0) #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 #endif
/** /**
@@ -148,15 +161,22 @@
* *
* Default: The number of I2S incoming channels, or half this if mono downsampling is enabled. * Default: The number of I2S incoming channels, or half this if mono downsampling is enabled.
*/ */
#if (I2S_DOWNSAMPLE_MONO == 1) #if (I2S_DOWNSAMPLE_MONO_IN == 1)
#define I2S_DOWNSAMPLE_CHANS (I2S_CHANS_ADC / 2) #define I2S_DOWNSAMPLE_CHANS_IN (I2S_CHANS_ADC / 2)
#if ((I2S_DOWNSAMPLE_FACTOR > 1) && (I2S_MODE_TDM == 1)) #if ((I2S_DOWNSAMPLE_FACTOR_IN > 1) && (I2S_MODE_TDM == 1))
#error Mono I2S downsampling is not avaliable in TDM mode #error Mono I2S input downsampling is not avaliable in TDM mode
#endif #endif
#else #else
#define I2S_DOWNSAMPLE_CHANS I2S_CHANS_ADC #define I2S_DOWNSAMPLE_CHANS_IN I2S_CHANS_ADC
#endif #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 * @brief Max supported sample frequency for device (Hz). Default: 192000
*/ */