Add DS3 to I2S input

- I2S downsampling is disabled by default.

- I2S rate is always scaled up:
  The host may not issue a SET_SAMPLE_FREQ command so always scale up,
  and back down where the value may be a another command.
This commit is contained in:
Sam Chesney
2016-11-11 17:10:27 +00:00
parent 22ee710f01
commit 020cf2dad7

View File

@@ -31,11 +31,31 @@
#include "commands.h"
#include "xc_ptr.h"
#ifndef I2S_DOWNSAMPLE_FACTOR
#define I2S_DOWNSAMPLE_FACTOR (1)
#endif
#define I2S_RATE_SCALING (I2S_DOWNSAMPLE_FACTOR)
#if I2S_RATE_SCALING != I2S_DOWNSAMPLE_FACTOR
#error "Unsupported I2S rate scaling and downsampling configuration"
#endif
// I2S channels for stereo AEC reference input
#define I2S_CHANS_DIGI_IN (2)
// The PDM mic channels start after the I2S AEC reference channels
#define PDM_RX_INDEX (I2S_CHANS_DIGI_IN)
#if (NUM_USB_CHAN_IN < (I2S_CHANS_DIGI_IN + NUM_PDM_MICS))
#error "Not enough USB input channels to support number of I2S and PDM inputs"
#endif
/* TODO 32 is max expected channels */
static unsigned samplesOut[32];
/* Two buffers for ADC data to allow for DAC and ADC ports being offset */
static unsigned samplesIn[2][32];
static unsigned samplesIn[2][I2S_DOWNSAMPLE_FACTOR][32];
static int downsamplingCounter = 0;
#if (DSD_CHANS_DAC != 0)
extern buffered out port:32 p_dsd_dac[DSD_CHANS_DAC];
@@ -266,16 +286,24 @@ static inline unsigned DoSampleTransfer(chanend c_out, const int readBuffNo, con
#else
inuint(c_out);
#endif
UserBufferManagement(samplesOut, samplesIn[readBuffNo], i_audMan);
}
unsigned downsampledI2S[2];
// TODO: run ds3 here
// Pass samplesIn[readBuffNo][0,I2S_DOWNSAMPLE_FACTOR][i]) to ds3()
UserBufferManagement(samplesOut, samplesIn[readBuffNo][downsamplingCounter], i_audMan);
#if NUM_USB_CHAN_IN > 0
#pragma loop unroll
for(int i = 0; i < NUM_USB_CHAN_IN; i++)
{
outuint(c_out, samplesIn[readBuffNo][i]);
}
#endif
for(int i = 0; i < I2S_CHANS_DIGI_IN; i++)
{
outuint(c_out, downsampledI2S[i]);
}
#pragma loop unroll
for (int i = PDM_RX_INDEX; i < (NUM_PDM_MICS + PDM_RX_INDEX); i++)
{
outuint(c_out, samplesIn[readBuffNo][downsamplingCounter][i]);
}
#endif
return 0;
}
@@ -479,6 +507,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
@@ -684,20 +714,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_RX_INDEX; i < (NUM_PDM_MICS + PDM_RX_INDEX); i++)
{
c_pdm_pcm :> samplesIn[readBuffNo][downsamplingCounter][i];
}
}
}
#endif
}
#if (I2S_CHANS_ADC != 0)
index = 0;
/* Channels 0, 2, 4.. on each line */
@@ -794,22 +826,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;
}
}
}
@@ -924,7 +964,7 @@ chanend ?c_config, chanend ?c
unsigned adatMultiple = 0;
#endif
unsigned curSamFreq = DEFAULT_FREQ;
unsigned curSamFreq = DEFAULT_FREQ * I2S_RATE_SCALING;
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;
@@ -1079,7 +1119,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_RATE_SCALING) != AUDIO_REBOOT_FROM_DFU) && ((curSamFreq / I2S_RATE_SCALING) != AUDIO_STOP_FOR_DFU) && command)
{
#if 0
/* User should ensure MCLK is stable in AudioHwConfig */
@@ -1122,7 +1162,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
@@ -1163,7 +1203,7 @@ chanend ?c_config, chanend ?c
if(command == SET_SAMPLE_FREQ)
{
curSamFreq = inuint(c_mix_out);
curSamFreq = inuint(c_mix_out) * I2S_RATE_SCALING;
}
else if(command == SET_STREAM_FORMAT_OUT)
{
@@ -1176,7 +1216,7 @@ chanend ?c_config, chanend ?c
}
/* Currently no more audio will happen after this point */
if (curSamFreq == AUDIO_STOP_FOR_DFU)
if ((curSamFreq / I2S_RATE_SCALING) == AUDIO_STOP_FOR_DFU)
{
outct(c_mix_out, XS1_CT_END);