TDM code made a bit more generic. Fixed issue with multiple TDM input lines missing channels.

This commit is contained in:
Ross Owen
2014-11-20 17:28:48 +00:00
parent d26f478835
commit 69f8e83cc7

View File

@@ -23,6 +23,13 @@
#include "xc_ptr.h" #include "xc_ptr.h"
#ifdef I2S_MODE_TDM
#define I2S_CHANS_PER_FRAME 8
#else
#error
#define I2S_CHANS_PER_FRAME 2
#endif
unsigned testsamples[100]; unsigned testsamples[100];
int p = 0; int p = 0;
@@ -300,7 +307,7 @@ static inline void InitPorts(unsigned divide)
} }
#endif #endif
} }
else else /* Divide != 1 */
{ {
#if (I2S_CHANS_DAC != 0) #if (I2S_CHANS_DAC != 0)
/* Pre-fill the DAC ports */ /* Pre-fill the DAC ports */
@@ -309,8 +316,11 @@ static inline void InitPorts(unsigned divide)
p_i2s_dac[i] <: 0; p_i2s_dac[i] <: 0;
} }
#endif #endif
/* Pre-fill the LR clock output port */
p_lrclk <: 0x0; p_lrclk <: 0x0;
doI2SClocks(divide); doI2SClocks(divide);
} }
#if (DSD_CHANS_DAC > 0) #if (DSD_CHANS_DAC > 0)
} /* if (!dsdMode) */ } /* if (!dsdMode) */
@@ -345,7 +355,6 @@ static inline void InitPorts(unsigned divide)
} }
#endif #endif
#endif #endif
} }
@@ -366,13 +375,13 @@ chanend ?c_adc)
unsigned samplesOut[NUM_USB_CHAN_OUT]; unsigned samplesOut[NUM_USB_CHAN_OUT];
#endif #endif
//#if NUM_USB_CHAN_IN > 0 //#if NUM_USB_CHAN_IN > 0
//unsigned samplesIn[NUM_USB_CHAN_IN]; /* Since DAC and ADC buffered ports off by one sample we buffer previous ADC frame */
unsigned samplesIn[2][NUM_USB_CHAN_IN]; unsigned samplesIn[2][NUM_USB_CHAN_IN];
unsigned readBuffNo = 0; unsigned readBuffNo = 0;
//unsigned samplesInPrev[NUM_USB_CHAN_IN]; /* Since DAC and ADC buffered ports off by one sample we buffer previous ADC frame */
//#endif //#endif
unsigned tmp; unsigned tmp;
unsigned index; unsigned index;
#ifdef RAMP_CHECK #ifdef RAMP_CHECK
unsigned prev=0; unsigned prev=0;
int started = 0; int started = 0;
@@ -387,13 +396,12 @@ chanend ?c_adc)
#endif #endif
unsigned underflowWord = 0; unsigned underflowWord = 0;
unsigned tdmCount = 0; unsigned frameCount = 0;
#if NUM_USB_CHAN_IN > 0 #if NUM_USB_CHAN_IN > 0
/* Initialise buffers to 0 */ /* Initialise input buffers. Note two buffers due to offset between ADC and DAC ports */
for (int i=0;i<NUM_USB_CHAN_IN;i++) for (int i=0;i<NUM_USB_CHAN_IN;i++)
{ {
//samplesIn[i] = 0;
samplesIn[0][i] = 0; samplesIn[0][i] = 0;
samplesIn[1][i] = 0; samplesIn[1][i] = 0;
} }
@@ -430,7 +438,6 @@ chanend ?c_adc)
while (1) while (1)
{ {
#if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0) #if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0)
if(dsdMode == DSD_MODE_NATIVE) if(dsdMode == DSD_MODE_NATIVE)
{ {
@@ -559,7 +566,7 @@ chanend ?c_adc)
#ifdef I2S_MODE_TDM #ifdef I2S_MODE_TDM
for(int i = 0; i < I2S_CHANS_DAC; i+=8) for(int i = 0; i < I2S_CHANS_DAC; i+=8)
{ {
p_i2s_dac[index++] <: bitrev(samplesOut[(2*tdmCount)+i]); p_i2s_dac[index++] <: bitrev(samplesOut[(frameCount)+i]);
} }
#else #else
for(int i = 0; i < I2S_CHANS_DAC; i+=2) for(int i = 0; i < I2S_CHANS_DAC; i+=2)
@@ -576,29 +583,22 @@ chanend ?c_adc)
index = 0; index = 0;
#pragma loop unroll #pragma loop unroll
#ifdef I2S_MODE_TDM #ifdef I2S_MODE_TDM
if(tdmCount == 0) /* First input (i.e. frameCoint == 0) we read last ADC channel of previous frame.. */
{ unsigned buffIndex = frameCount ? !readBuffNo : readBuffNo;
/* First time around we get channel 7 of TDM8 */ /* First time around we get channel 7 of TDM8 */
for(int i = 0; i < I2S_CHANS_ADC; i += 8) for(int i = 0; i < I2S_CHANS_ADC; i+=I2S_CHANS_PER_FRAME)
{ {
asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++]));
samplesIn[readBuffNo][7] = bitrev(sample);
} /* Note the use of readBuffNo changes based on frameCount */
} samplesIn[buffIndex][((frameCount-1)&(I2S_CHANS_PER_FRAME-1))+i] = bitrev(sample); // channels 1, 3, 5.. on each line.
else
{
for(int i = 0; i < I2S_CHANS_ADC; i += 8)
{
asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++]));
samplesIn[!readBuffNo][(2*tdmCount)+i-1] = bitrev(sample); // channels 1, 3, 5.. on each line.
}
} }
#else #else
for(int i = 0; i < I2S_CHANS_ADC; i += 2) for(int i = 0; i < I2S_CHANS_ADC; i += 2)
{ {
// Manual IN instruction since compiler generates an extra setc per IN (bug #15256) /* Manual IN instruction since compiler generates an extra setc per IN (bug #15256) */
asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++]));
samplesIn[i] = bitrev(sample); samplesIn[i] = bitrev(sample);
samplesIn[i-1] = samplesInPrev[i]; samplesIn[i-1] = samplesInPrev[i];
} }
@@ -638,7 +638,7 @@ chanend ?c_adc)
#ifndef CODEC_MASTER #ifndef CODEC_MASTER
#ifdef I2S_MODE_TDM #ifdef I2S_MODE_TDM
if(tdmCount == 3) if(frameCount == (I2S_CHANS_PER_FRAME-2))
p_lrclk <: 0x80000000; p_lrclk <: 0x80000000;
else else
p_lrclk <: 0x00000000; p_lrclk <: 0x00000000;
@@ -652,9 +652,9 @@ chanend ?c_adc)
#if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0) #if (I2S_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT != 0)
#pragma loop unroll #pragma loop unroll
#ifdef I2S_MODE_TDM #ifdef I2S_MODE_TDM
for(int i = 0; i < I2S_CHANS_DAC; i+=8) for(int i = 0; i < I2S_CHANS_DAC; i+=I2S_CHANS_PER_FRAME)
{ {
p_i2s_dac[index++] <: bitrev(samplesOut[(2*tdmCount)+1+i]); p_i2s_dac[index++] <: bitrev(samplesOut[frameCount+1+i]);
} }
#else #else
for(int i = 1; i < I2S_CHANS_DAC; i+=2) for(int i = 1; i < I2S_CHANS_DAC; i+=2)
@@ -667,21 +667,20 @@ chanend ?c_adc)
doI2SClocks(divide); doI2SClocks(divide);
#if (I2S_CHANS_ADC != 0) #if (I2S_CHANS_ADC != 0)
/* Input previous right ADC sample */
index = 0; index = 0;
#pragma loop unroll #pragma loop unroll
#ifdef I2S_MODE_TDM #ifdef I2S_MODE_TDM
for(int i = 0; i < I2S_CHANS_ADC; i += 8) /* Channels 0, 2, 4.. on each line */
for(int i = 0; i < I2S_CHANS_ADC; i += I2S_CHANS_PER_FRAME)
{ {
asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++]));
//samplesIn[(2*tdmCount)+i+1] = bitrev(sample); samplesIn[!readBuffNo][frameCount+i] = bitrev(sample);
samplesIn[!readBuffNo][2*tdmCount+i] = bitrev(sample); // Channels 0, 2, 4.. on each line.
} }
#else #else
/* Input previous right ADC sample */
for(int i = 0; i < I2S_CHANS_ADC; i += 2) for(int i = 0; i < I2S_CHANS_ADC; i += 2)
{ {
// p_i2s_adc[index++] :> sample; /* Manual IN instruction since compiler generates an extra setc per IN (bug #15256) */
// Manual IN instruction since compiler generates an extra setc per IN (bug #15256)
asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++])); asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++]));
samplesInPrev[i] = bitrev(sample); samplesInPrev[i] = bitrev(sample);
} }
@@ -690,7 +689,6 @@ chanend ?c_adc)
#ifdef SU1_ADC_ENABLE #ifdef SU1_ADC_ENABLE
{ {
unsigned x; unsigned x;
x = inuint(c_adc); x = inuint(c_adc);
inct(c_adc); inct(c_adc);
asm("stw %0, dp[g_adcVal]"::"r"(x)); asm("stw %0, dp[g_adcVal]"::"r"(x));
@@ -748,10 +746,12 @@ chanend ?c_adc)
#endif #endif
#ifdef I2S_MODE_TDM #ifdef I2S_MODE_TDM
tdmCount++; /* Increase frameCount by 2 since we have output two channels (per data line) */
if(tdmCount == 4) frameCount+=2;
if(frameCount == I2S_CHANS_PER_FRAME)
#endif #endif
{ {
/* Do samples transfer */
unsigned command = DoSampleTransfer(c_out, samplesOut, unsigned command = DoSampleTransfer(c_out, samplesOut,
#if NUM_USB_CHAN_IN > 0 #if NUM_USB_CHAN_IN > 0
samplesIn[readBuffNo], samplesIn[readBuffNo],
@@ -759,9 +759,12 @@ chanend ?c_adc)
underflowWord); underflowWord);
if(command) if(command)
{
return command; return command;
}
tdmCount = 0; /* Reset frame counter and flip the ADC buffer */
frameCount = 0;
readBuffNo = !readBuffNo; readBuffNo = !readBuffNo;
} }
} }