Hi all,
I'm a student and I've written a driver to allow me to communicate
between my DSK C6711 and my AIC23EVM codec. All is working fine but
I've noticed that when I output samples to my DAC and read the
resulting analog signal back via my ADC, I'm not getting back the
expected samples every time I execute my program - there is a varing
phase difference between what I output and what I read back. I've
spent a week now with this problem to no avail, so I'm hoping now that
I've done something obvious that you guys will notice.
The signal I'm outputting is cyclical over 5 samples -
for(i=0;i<50;i++)
demodulated[i] = 0.1*cos( (2*PI*1600.0*i)/(float)(SR));
where my sample rate is 8k.
When I run my program, I watch the -
25600th
76800th
128000th
153600th and
179200th
samples returned by the ADC. These sample should have roughly the same
value, But this is not what I'm getting when I run the program
multiple times.
Heres what I am getting for 5 executions of my program -
First Second Third Forth Fifth
25600 -0.1417649 -0.1395805 -0.2302676 -0.1459084 -0.2332552
76800 -0.1426323 -0.1460696 -0.2242603 -0.1463084 -0.2283723
128000 -0.1407369 -0.1437245 -0.2315847 -0.1436323 -0.2332552
153600 -0.1468084 -0.1434675 -0.2263806 -0.1417349 -0.2270552
179200 -0.1434996 -0.1417328 -0.2280189 -0.1427328 -0.2293681
Notice the -0.14 samples and the -0.23 samples. They are out of phase.
When I watched the -
25600th
25601st
25602nd
25603rd and
25604th
samples, I got -
First Execution Third Execution
25600 -0.1417649 -0.2302676
25601 0.2298179 0.1561888
25602 0.2857464 0.3114138
25603 -0.04211507 0.05596068
25604 -0.3294998 -0.2970542
I'm getting back a consistent sine wave with respect to amplitude, but
I'm not getting a consistent phase and it is important that I know the
phase of the incoming signal - as I'm mixing it with a local
oscillator. I must point out at this point that the ougoing signal is
passing through an analog circuit so ignore the differene in amplitude
between what is going out and what I'm reading in.
I'm using EDMA to complete the transfer to and from the DAC and ADC.
I've set the PIP frame size to 512 and the number of frames to 2 for
the RX and TX pipes repectfully, for the results above.
I then repeated the above experiment with a frame size of 256, and I
got the following -
First Second Third Forth Fifth
12800 0.05191301 -0.04208295 -0.04166533 -0.04108709 0.05663529
38400 0.0548042 -0.03784253 -0.03710367 -0.03832439 0.05377622
64000 0.05377622 -0.03835652 -0.03960937 -0.0404446 0.05310161
89600 0.05515757 -0.04079797 -0.04301455 -0.03999486 0.05323011
115200 0.05499695 -0.0417617 -0.04015549 -0.0398946 0.0578239
This time I'm getting samples of the order 0.05 or -0.04, while with a
frame length of 512 I was getting -0.14 or -0.23. Any idea why this
might be? Also, I've stripped down my original code in order to find
this error. With my original code I was also losing (I think) the odd
sample sometimes, for example I might have got back something like
this -
First
12800 0.05191301
38400 0.2298179
64000 0.2298179
89600 0.2298179
115200 0.2298179
Anyway, I'll post my stripped down code below with the hope that
someone might spot what I'm doing wrong. Remember I'm a student and I
don't have anyone experienced to help me so I've been working with the
TI examples.
I'll post this on c6x yahoo groups also.
Cheers,
Joseph.
/*
* Copyright 2001 by Texas Instruments Incorporated.
* All rights reserved. Property of Texas Instruments Incorporated.
* Restricted rights to use, duplicate or disclose this code are
* granted through contract.
*
*/
/* "@(#) DSP/BIOS 4.60.22 12-07-01 (barracuda-j15)" */
/*
* ======== audio.c ========
*/
#include <rtdx.h>
#include <stdarg.h> /* var arg stuff */
#include <std.h>
#include <pip.h>
#include <trc.h>
#include <hst.h>
#include <time.h>
#include <math.h>
#include <dspf_sp_fircirc.h>
#include <csl_cache.h>
#include "dss.h"
#include "audiocfg.h"
#include "audio.h"
#include "dss_priv.h"
#include "audiocfg.h"
#include "mcbsp.h"
#include "edma.h"
#define PI (3.141592653589793)
#define SR (8000)
#pragma DATA_SECTION(semaphore, "SEMAPHORE")
Uns semaphore = 0;
static Uns allocBuf(PIP_Obj *out, Uns **buf);
static Void freeBuf(PIP_Obj *out);
static Uns getBuf(PIP_Obj *in, Uns **buf);
static Void putBuf(PIP_Obj *out, Uns size);
static Void process(Uns *src, Int size, Uns *dst);
static Float demodulated[50];
static float tempTBDetected[800];
static float div = (float)(0x7999);
static Int i,j=0,j_2=0,l;
static Uns t1;
static Uns t2;
static long count=0;
static Int c1=0;
static float f1,f2;
static Int cc=0;
Void main()
{
Int i;
for(i=0;i<50;i++)
demodulated[i] = 0.1*cos( (2*PI*1600.0*i)/(float)(SR) );
McBSP_Init();
EDMA_Init();
return;
}
Void audio(PIP_Obj *in, PIP_Obj *out)
{
Uns *src, *dst;
Uns size;
size = getBuf(in, &src);
allocBuf(out, &dst);
process(src, size, dst);
putBuf(out, size);
freeBuf(in);
}
static Void process(Uns *src, Int size, Uns *dst)
{
if(count==(long)(200*size/2)) // 200*size/2 = 51200 samples
for a frame length of 512
{
count=0;
c1 = 0;
}
for (l=0; l < size/2; j++,l++) // size/2 -> 32-bit samples
returned by Codec
{
if(j==50)
j=0;
t1 = src[l] &0xffff; // convert incoming ADC samples to floating
point (f1 and f2)
t2 = (src[l]>>16) & 0xffff;
if(t1 & 0x8000)
t1 |= 0xFFFF0000;
if(t2 & 0x8000)
t2 |= 0xFFFF0000;
f1 = (((Float)((Int)(t1)))/div);
f2 = (((Float)((Int)(t2)))/div);
f1=-f1;
f2=-f2;
if(cc==0)
if(count>=size/2*100 && count<size/2*100 +100)
tempTBDetected[count-(size/2*100)] = f2;
if(cc==1)
if(count>=size/2*100 && count<size/2*100 +100)
tempTBDetected[count-(size/2*100)+100] = f2;
if(cc==2)
if(count>=size/2*100 && count<size/2*100 +100)
tempTBDetected[count-(size/2*100)+200] = f2;
if(cc==3)
if(count>=size/2*100 && count<size/2*100 +100)
tempTBDetected[count-(size/2*100)+300] = f2;
if(cc==4)
if(count>=size/2*100 && count<size/2*100 +100)
tempTBDetected[count-(size/2*100)+400] = f2;
count++;
f1 = demodulated[j]; //output to DAC
f1 = f1;
t1 = f1 * div;
t1 &= 0xffff;
t2 = f2 * div;
t2 &= 0xffff;
t2 <<= 16;
t1 = t1 | t2;
dst[l]=t1;
}
if(count==size/2*200)
{
if(cc==5)
{
cc=10;
semaphore++; //SET BREAKPOINT HERE (RUN TO HERE)!
}
cc++;
}
}
static Uns allocBuf(PIP_Obj *out, Uns **buf)
{
PIP_alloc(out);
*buf = PIP_getWriterAddr(out);;
return (PIP_getWriterSize(out));
}
static Void freeBuf(PIP_Obj *out)
{
PIP_free(out);
}
static Uns getBuf(PIP_Obj *in, Uns **buf)
{
PIP_get(in);
*buf = PIP_getReaderAddr(in);;
return (PIP_getReaderSize(in));
}
static Void putBuf(PIP_Obj *out, Uns size)
{
PIP_setWriterSize(out, size);
PIP_put(out);
}
///////////////////////////////////////////////////////////////
///////////////////////// DSS.c
///////////////////////////////////////////////////////////////
#include <std.h>
#include <pip.h>
#include <log.h>
#include <trc.h>
#include <clk.h>
#include "dss.h"
#include "dss_priv.h"
#include "audiocfg.h"
#include "audio.h"
#include <csl_cache.h>
Int DSS_error = 0;
Int DSS_rxCnt = 0;
Int DSS_txCnt = 0;
Int *DSS_rxPtr = NULL;
Int *DSS_txPtr = NULL;
DSS_Obj DSS_config = {
0 /* enable tracing */
};
/*
* ======= DSS_txPrime ========
* Called when DSS_txPipe has a full buffer to be transmitted
* (i.e., when notifyReader() is called) and when the DSS ISR
* is ready for more data.
*/
void DSS_txPrime(Bool calledByISR)
{
PIP_Obj *txPipe = &DSS_txPipe;
static Int nested = 0;
if(nested)
return;
nested = 1;
if (DSS_txCnt == 0 && PIP_getReaderNumFrames(txPipe) > 0)
{
PIP_get(txPipe);
/* must set 'Ptr' before 'Cnt' to synchronize with isr() */
DSS_txPtr = PIP_getReaderAddr(txPipe);
DSS_txCnt = PIP_getReaderSize(txPipe)/2;
DSS_dmaTxStart(DSS_txPtr, DSS_txCnt);
}
else if (calledByISR && (DSS_error & DSS_TXERR) == 0)
{
if (DSS_config.enable)
TRC_disable(TRC_GBLTARG);
DSS_error |= DSS_TXERR;
}
nested = 0;
}
/*
* ======= DSS_rxPrime ========
* Called when DSS_rxPipe has an empty buffer to be filled;
* e.g., when notifyWriter() is called) and when the DSS ISR
* is ready to fill another buffer.
*/
void DSS_rxPrime(Bool calledByISR)
{
PIP_Obj *rxPipe = &DSS_rxPipe;
static Int nested = 0;
if(nested)
return;
nested = 1;
if (DSS_rxCnt == 0 && PIP_getWriterNumFrames(rxPipe) > 0)
{
PIP_alloc(rxPipe);
DSS_rxPtr = PIP_getWriterAddr(rxPipe);
DSS_rxCnt = PIP_getWriterSize(rxPipe)/2;
DSS_dmaRxStart(DSS_rxPtr, DSS_rxCnt);
}
else if(calledByISR && (DSS_error & DSS_RXERR) == 0)
{
if(DSS_config.enable)
TRC_disable(TRC_GBLTARG);
DSS_error |= DSS_RXERR;
}
nested = 0;
}
/*
* ======== DSS_dmaInit ========
* Initialise EDMA Controller
*/
Void DSS_dmaInit(Void)
{
/* General EDMA Initialization */
EDMA_RSET(EER, 0x0000); /* Disable all events */
EDMA_RSET(ECR, 0xffff); /* Clear all pending events */
EDMA_RSET(CIER, 0x0000); /* Disable all events to Interrupt */
EDMA_RSET(CIPR, 0xffff); /* Clear all pending Queued EDMA ints
*/
/* Enable Rx/Tx DMA Complete Interrupts to the CPU */
EDMA_RSET(CIER, DSS_RXDONE | DSS_TXDONE);
}
/*
* ======= DSS_dmaRxStart ========
*/
Void DSS_dmaRxStart(Void *dst, Int nsamps)
{
CACHE_clean(CACHE_L2, dst, nsamps);
/* Reconfig EDMA channel for next receive buffer */
EDMA_RSETH(DSS_hEdmaRint0, CNT, (Uns) nsamps);
EDMA_RSETH(DSS_hEdmaRint0, DST, (Uns) dst);
EDMA_RSET(EER, 0x3000); /* Enable McBSP0 Rx/Tx Events to the
DMA */
}
/*
* ======= DSS_dmaTxStart ========
*/
Void DSS_dmaTxStart(Void *src, Int nsamps)
{
static Int startup = 1;
/* Uns temp[32];
static Uns t1;
static Uns t2;
static Float f1;
static Float f2;
static Float div = (float)(0x7fff);
temp[0] = *(Uns *)(src);
temp[1] = *((Uns *)(src)+1);
temp[2] = *((Uns *)(src)+2);
temp[3] = *((Uns *)(src)+3);
t1 = temp[0] &0xffff;
t2 = (temp[0]>>16) & 0xffff;
if(t1 & 0x8000)
t1 |= 0xFFFF0000;
if(t2 & 0x8000)
t2 |= 0xFFFF0000;
f1 = (((Float)((Int)(t1)))/div);
f2 = (((Float)((Int)(t2)))/div);*/
CACHE_flush(CACHE_L2, src, nsamps);
if (startup)
{
startup = 0;
EDMA_RSET(ECR, 0x3000); /*Clear any previous McBSP Events
*/
}
/* Reconfig EDMA channel for next transmit buffer */
EDMA_RSETH(DSS_hEdmaXint0, SRC, (Uns) src);
EDMA_RSETH(DSS_hEdmaXint0, CNT, (Uns) nsamps);
EDMA_RSET(EER, 0x3000); /* Enable McBSP0 Rx/Tx Events to the
DMA */
}
///////////////////////////////////////////////////////////////
///////////////////////// DSSEDMA_IRC.c
///////////////////////////////////////////////////////////////
#include <std.h>
#include <log.h>
#include <pip.h>
#include "audiocfg.h"
#include "audio.h"
#include "dss.h"
#include "dss_priv.h"
/*
* ======== DSS_edmaIsr ========
*
* This ISR is called under 2 conditions. Either when EDMA has
received a
* complete buffer of samples from Serial Port (Codec) or when a EDMA
has
* completed transmission of a buffer to the Serial Port (Codec).
This
* ISR must configure the next buffer to be filled by the EDMA in
each
* case.
*/
Void DSS_edmaIsr(Void)
{
Int channel = EDMA_RGET(CIPR); /* get Channel Interrupt Pending
bits */
if (channel & DSS_TXDONE) { /* Channel = McBSP Buffer Tx'ed */
PIP_free(&DSS_txPipe);
DSS_txCnt = 0; /* Reset Buffer Count for sync
*/
EDMA_RSET(CIPR, DSS_TXDONE); /* Reset EDMA Channel Flag */
DSS_txPrime(TRUE);
}
if (channel & DSS_RXDONE) { /* Channel = McBSP Buffer Rx'ed */
PIP_put(&DSS_rxPipe);
DSS_rxCnt = 0; /* Reset Buffer Count for sync
*/
EDMA_RSET(CIPR, DSS_RXDONE); /* Reset EDMA Channel Flag */
DSS_rxPrime(TRUE);
}
}
///////////////////////////////////////////////////////////////
///////////////////////// EDMA.c
///////////////////////////////////////////////////////////////
#include <std.h>
#include "dss_priv.h"
#include "edma.h"
Void EDMA_Init(Void)
{
EDMA_RSET(EER, 0x0000); /* Disable all events */
EDMA_RSET(ECR, 0xffff); /* Clear all pending events */
EDMA_RSET(CIER, 0x0000); /* Disable all events to Interrupt */
EDMA_RSET(CIPR, 0xffff); /* Clear all pending Queued EDMA ints
*/
/* Enable Rx/Tx DMA Complete Interrupts to the CPU */
EDMA_RSET(CIER, DSS_RXDONE | DSS_TXDONE);
/* Enable EDMA interrupt */
IER |= DSS_IERDMABIT;
}
///////////////////////////////////////////////////////////////
///////////////////////// Mc_BSP.c
///////////////////////////////////////////////////////////////
#include <std.h>
#include <log.h>
#include "dss_priv.h"
#include "audiocfg.h"
#include "mcbsp.h"
/* function prototypes ... */
Void spWrite(MCBSP_Handle hMcBsp, Uns data);
Void aic23_write_reg(Uns uiAddress, Uns uiData);
/*
* ======== DSS_init ========
*/
Void McBSP_Init(Void)
{
MCBSP_RSETH(DSS_hMcbsp1, SPCR, 0x02001000);
MCBSP_RSETH(DSS_hMcbsp1, SPCR, 0x02C01000);
MCBSP_RSETH(DSS_hMcbsp1, SPCR, 0x02C11000);
MCBSP_RSETH(DSS_hMcbsp0, SPCR, 0x02010001);
spWrite(DSS_hMcbsp1, 0);
aic23_write_reg(0x0F, 0x00);
aic23_write_reg(0x06, 0x00);
aic23_write_reg(0x00, 0x17);
aic23_write_reg(0x01, 0x17);
aic23_write_reg(0x02, 0xF9);
aic23_write_reg(0x03, 0xF9);
aic23_write_reg(0x04, 0x10);
aic23_write_reg(0x05, 0x00);
aic23_write_reg(0x07, 0x53);
// aic23_write_reg(0x08, 0x2c); //2
aic23_write_reg(0x08, 0x2c); //2
// aic23_write_reg(0x08, 0x2c); //2
aic23_write_reg(0x09, 0x01);
/* Enable EDMA interrupt */
IER |= DSS_IERDMABIT;
}
// Write from McBsp to AIC23
Void spWrite(MCBSP_Handle hMcBsp, Uns data)
{
// Poll until ready to transmit
while (( (MCBSP_RGETH(hMcBsp, SPCR)) & 0x20000) == 0);
MCBSP_write(hMcBsp,data);
}
// Write to Control Reg on AIC23
Void aic23_write_reg(Uns uiAddress, Uns uiData)
{
spWrite(DSS_hMcbsp1, ((uiAddress << 9) | uiData) );
}