Part Number: EVMK2G
Other Parts Discussed in Thread: AUDK2G
I have been stuck on this for long. I am making changes to the loopback example provided for AUDK2G, the audio daughter card for K2G - I get my input audio input which is a 500Hz sine wave and store it in an int32_t array. I plot this data (real-time) on CCS graph and this is what I see:
As seen, the negative part of the waveform appears in the positive part on the top. FYI - I have also made sure that I am plotting the data correctly, i.e, as a 32 bit signed integer. I am not sure why my data is getting written into the input buffer in this way? As a result, when I try to perform any audio processing, things go bad. I need help to know what's going on.
I have followed steps discussed on this post to make sure I am fetching audio samples correctly. I have been able to successfully de-interleave data and I am also able to direct audio from different input channels to the output ports that I desire (this proves that I am indeed reading the data correctly).
I am providing my code below for reference. It is the mcasp_cfg.c file. To find my lines of code, go to line 549. I am plotting the err_block array in the figure above. This array is assigned in line 554.
// Current version
/*
* Copyright (c) 2015, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* \file mcasp_config.c
*
* \brief Configures McASP module
*
*/
#include "mcasp_cfg.h"
#include <ti/drv/uart/UART.h>
#include <ti/drv/uart/UART_stdio.h>
/* Frame index for Rx and Tx buffers */
uint8_t rxFrameIndex = 1;
uint8_t txFrameIndex = 1;
uint32_t gtxFrameIndexCount = 0;
uint32_t grxFrameIndexCount = 0;
/* Flags for counting Rx and Tx interrupts */
volatile uint32_t rxFlag = 0;
volatile uint32_t txFlag = 0;
/* Semaphore handle for Tx and Rx */
Semaphore_Handle semR;
Semaphore_Handle semT;
Semaphore_Params params;
/* McASP device handles */
Ptr hMcaspDevTx;
Ptr hMcaspDevRx;
/* McASP channel handles */
Ptr hMcaspTxChan;
Ptr hMcaspRxChan;
/* McASP channel parameters */
Mcasp_Params mcaspTxParams;
Mcasp_Params mcaspRxParams;
/* McASP Callback function argument */
uint32_t txChanMode;
uint32_t rxChanMode;
uint32_t mcaspRxChanArg = 1;
uint32_t mcaspTxChanArg = 2;
/* McASP Tx and Rx frame buffers */
MCASP_Packet rxFrame[NUM_BUFS];
MCASP_Packet txFrame[NUM_BUFS];
/* McASP Tx and Rx frame buffer pointers */
Ptr txBuf[NUM_BUFS];
Ptr rxBuf[NUM_BUFS];
/* Adaptive Filtering: Variables and Arrays */
#define REF_BLOCK_SIZE 512
#define ERR_BLOCK_SIZE 256
#define SINGLE_CH_BUF_SIZE 256
int32_t ref_block[REF_BLOCK_SIZE];
int32_t err_block[ERR_BLOCK_SIZE];
int32_t *input;
int32_t *output;
volatile uint32_t antinoise_block[SINGLE_CH_BUF_SIZE];
#define h_af_SIZE 96
volatile float h_af[h_af_SIZE] = {0.0};
double error=0.0, alpha = 0.0000000000000003;
/* Error flag */
uint32_t gblErrFlag = 0;
Error_Block eb;
/* Handle to heap object */
extern HeapMem_Handle heapHandle;
/* Mcasp IOM function object */
extern IOM_Fxns Mcasp_IOMFXNS;
/* External function declarations */
void McaspDevice_init(void);
void GblErr(int arg);
signed char* getGlobalAddr(signed char* addr);
void aud_write(const char *fmt, ... );
#define TX_FIFO_EVENT_DMA_RATIO 2
#define RX_FIFO_EVENT_DMA_RATIO 2
/* McASP HW setup for receive */
Mcasp_HwSetupData mcaspRcvSetup = {
/* .rmask = */ 0xFFFFFFFF, /* 16 bits are to be used */
/* .rfmt = */ 0x000180F2, /*
* 0 bit delay from framesync
* MSB first
* No extra bit padding
* Padding bit (ignore)
* slot Size is 32
* Reads from DMA port
* NO rotation
*/
/* .afsrctl = */ 0X00000112, /* I2S mode - 2 slot TDM
* Frame sync is one word
* Internally generated frame sync
* Rising edge is start of frame
*/
/* .rtdm = */ 0x00000003, /* slot 1 and 2 are active (I2S) */
/* .rintctl = */ 0x00000000, /* sync error and overrun error */
/* .rstat = */ 0x000001FF, /* reset any existing status bits */
/* .revtctl = */ 0x00000000, /* DMA request is enabled */
{
/* .aclkrctl = */ 0x000000A7,
/* .ahclkrctl = */ 0x0000C000,
/* .rclkchk = */ 0x00000000
}
};
/* McASP HW setup for transmit */
Mcasp_HwSetupData mcaspXmtSetup = {
/* .xmask = */ 0xFFFFFFFF, /* 16 bits are to be used */
/* .xfmt = */ 0x000180F6, /*
* 0 bit delay from framesync
* MSB first
* No extra bit padding
* Padding bit (ignore)
* slot Size is 32
* Reads from DMA port
* NO rotation
*/
/* .afsxctl = */ 0x00000112, /* I2S mode - 2 slot TDM
* Frame sync is one word
* Rising edge is start of frame
* Internally generated frame sync
*/
/* .xtdm = */ 0x00000003, /* slot 1 and 2 are active (I2S) */
/* .xintctl = */ 0x00000000, /* sync error,overrun error,clK error */
/* .xstat = */ 0x000001FF, /* reset any existing status bits */
/* .xevtctl = */ 0x00000000, /* DMA request is enabled or disabled */
{
/* .aclkxctl = */ 0X000000A7,
/* .ahclkxctl = */ 0x0000C000,
/* .xclkchk = */ 0x00000000
},
};
/* McAsp channel parameters for receive */
Mcasp_ChanParams mcaspRxChanParam =
{
0x0004, /* number of serializers */
{Mcasp_SerializerNum_0,
Mcasp_SerializerNum_1,
Mcasp_SerializerNum_2,
Mcasp_SerializerNum_3 }, /* serializer index */
&mcaspRcvSetup,
TRUE,
Mcasp_OpMode_TDM, /* Mode (TDM/DIT) */
Mcasp_WordLength_32,
NULL,
0,
NULL,
GblErr,
2, /* number of TDM channels */
Mcasp_BufferFormat_MULTISER_MULTISLOT_SEMI_INTERLEAVED_1,
TRUE,
RX_FIFO_EVENT_DMA_RATIO,
TRUE,
Mcasp_WordBitsSelect_LSB
};
/* McAsp channel parameters for transmit - DAC0 */
Mcasp_ChanParams mcaspTx0ChanParam =
{
0x0004, /* number of serializers */
{Mcasp_SerializerNum_0,
Mcasp_SerializerNum_1,
Mcasp_SerializerNum_2,
Mcasp_SerializerNum_3 }, /* serializer index for DAC0 */
&mcaspXmtSetup,
TRUE,
Mcasp_OpMode_TDM,
Mcasp_WordLength_32, /* word width */
NULL,
0,
NULL,
GblErr,
2, /* number of TDM channels */
Mcasp_BufferFormat_MULTISER_MULTISLOT_SEMI_INTERLEAVED_1,
TRUE,
TX_FIFO_EVENT_DMA_RATIO,
TRUE,
Mcasp_WordBitsSelect_LSB
};
/* McAsp channel parameters for transmit - DAC1 */
Mcasp_ChanParams mcaspTx1ChanParam =
{
0x0004, /* number of serializers */
{Mcasp_SerializerNum_4,
Mcasp_SerializerNum_5,
Mcasp_SerializerNum_6,
Mcasp_SerializerNum_7 }, /* serializer index for DAC0 */
&mcaspXmtSetup,
TRUE,
Mcasp_OpMode_TDM,
Mcasp_WordLength_32, /* word width */
NULL,
0,
NULL,
GblErr,
2, /* number of TDM channels */
Mcasp_BufferFormat_MULTISER_MULTISLOT_SEMI_INTERLEAVED_1,
TRUE,
TX_FIFO_EVENT_DMA_RATIO,
TRUE,
Mcasp_WordBitsSelect_LSB
};
/* Handle to eDMA */
extern EDMA3_DRV_Handle hEdma0;
extern EDMA3_DRV_Handle hEdma1;
extern uint32_t sineData[];
extern uint32_t sineData_4ch[];
/**
* \brief Function called by McASP driver in case of error
*
* \return None
*/
void GblErr(int arg)
{
gblErrFlag = 1;
}
/**
* \brief McASP callback function called up on the data transfer completion
*
* \param arg [IN] - Application specific callback argument
* \param ioBuf [IN] - McASP IO buffer
*
* \return None
*/
void mcaspAppCallback(void *arg, MCASP_Packet *ioBuf)
{
/* Callback is triggered by Rx completion */
if(ioBuf->cmd == MCASP_READ)
{
rxFlag++;
if(rxFrameIndex == 0)
{
rxFrameIndex = 1;
}
else
{
rxFrameIndex = 0;
}
/* Post semaphore */
Semaphore_post(semR);
}
/* Callback is triggered by Tx completion */
if(ioBuf->cmd == MCASP_WRITE)
{
if(txFrameIndex == 0)
{
txFrameIndex = 1;
}
else
{
txFrameIndex = 0;
}
txFlag++;
/* Post semaphore */
Semaphore_post(semT);
}
}
/**
* \brief Initializes McASP data buffers and submits to McASP driver
*
* \return Aud_EOK on Success or error code
*/
Aud_STATUS initBuffers(void)
{
Error_Block eb;
uint32_t count = 0;
IHeap_Handle iheap;
Int status;
iheap = HeapMem_Handle_to_xdc_runtime_IHeap(heapHandle);
Error_init(&eb);
/* Allocate buffers for the McASP data exchanges */
for(count = 0; count < NUM_BUFS; count++)
{
rxBuf[count] = Memory_calloc(iheap, (BUFSIZE * RX_NUM_SERIALIZER),
BUFALIGN, &eb);
if(NULL == rxBuf[count])
{
IFPRINT(aud_write("\r\nMEM_calloc failed for Rx\n"));
}
}
/* Allocate buffers for the McASP data exchanges */
for(count = 0; count < NUM_BUFS; count++)
{
txBuf[count] = Memory_calloc(iheap, (BUFSIZE * TX_NUM_SERIALIZER),
BUFALIGN, &eb);
if(NULL == txBuf[count])
{
IFPRINT(aud_write("\r\nMEM_calloc failed for Tx\n"));
}
}
for(count = 0; count < NUM_BUFS; count++)
{
/* Issue the first & second empty buffers to the input stream */
memset((uint8_t *)rxBuf[count], 0xFF, (BUFSIZE * RX_NUM_SERIALIZER));
/* RX frame processing */
rxFrame[count].cmd = MCASP_READ;
rxFrame[count].addr = (void*)(getGlobalAddr(rxBuf[count]));
rxFrame[count].size = BUFSIZE*RX_NUM_SERIALIZER;
rxFrame[count].arg = (uint32_t) mcaspRxChanArg;
rxFrame[count].status = 0;
rxFrame[count].misc = 1; /* reserved - used in callback to indicate asynch packet */
/* Submit McASP packet for Rx */
status = mcaspSubmitChan(hMcaspRxChan, &rxFrame[count]);
if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))
{
IFPRINT(aud_write("mcaspSubmitChan for Rx Failed\n"));
return (Aud_EFAIL);
}
}
for(count = 0; count < NUM_BUFS; count++)
{
memset((uint8_t *)txBuf[count], 0xCC, (BUFSIZE * TX_NUM_SERIALIZER));
/* TX frame processing */
txFrame[count].cmd = MCASP_WRITE;
txFrame[count].addr = (void*)(getGlobalAddr(txBuf[count]));
txFrame[count].size = BUFSIZE*TX_NUM_SERIALIZER;
txFrame[count].arg = (uint32_t) mcaspTxChanArg;
txFrame[count].status = 0;
txFrame[count].misc = 1; /* reserved - used in callback to indicate asynch packet */
/* Submit McASP packet for Tx */
status = mcaspSubmitChan(hMcaspTxChan, &txFrame[count]);
if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))
{
IFPRINT(aud_write("mcaspSubmitChan for Tx Failed\n"));
return (Aud_EFAIL);
}
}
return (Aud_EOK);
}
/**
* \brief Configures McASP module and creates the channel
* for audio Tx and Rx
*
* \return Aud_EOK on Success or error code
*/
Aud_STATUS mcaspAudioConfig(void)
{
Int status;
hMcaspDevTx = NULL;
hMcaspDevRx = NULL;
hMcaspTxChan = NULL;
hMcaspRxChan = NULL;
/* Initialize McASP Tx and Rx parameters */
mcaspTxParams = Mcasp_PARAMS;
mcaspRxParams = Mcasp_PARAMS;
mcaspTxParams.mcaspHwSetup.tx.clk.clkSetupClk = 0x63;
mcaspTxParams.mcaspHwSetup.rx.clk.clkSetupClk = 0x23;
mcaspRxParams.mcaspHwSetup.rx.clk.clkSetupClk = 0x23;
mcaspRxParams.mcaspHwSetup.tx.clk.clkSetupClk = 0x63;
mcaspTxParams.mcaspHwSetup.glb.pdir |= 0x2000000; //Set Amute pin as output for Tx channel
/* Initialize eDMA handle */
mcaspRxChanParam.edmaHandle = hEdma1;
mcaspTx0ChanParam.edmaHandle = hEdma0;
mcaspTx1ChanParam.edmaHandle = hEdma0;
/* Bind McASP0 for Tx */
status = mcaspBindDev(&hMcaspDevTx, CSL_MCASP_0, &mcaspTxParams);
if((status != MCASP_COMPLETED) || (hMcaspDevTx == NULL))
{
IFPRINT(aud_write("mcaspBindDev for Tx Failed\n"));
return (Aud_EFAIL);
}
/* Bind McASP1 for Rx */
status = mcaspBindDev(&hMcaspDevRx, CSL_MCASP_1, &mcaspRxParams);
if((status != MCASP_COMPLETED) || (hMcaspDevRx == NULL))
{
IFPRINT(aud_write("mcaspBindDev for Rx Failed\n"));
return (Aud_EFAIL);
}
#ifdef AUDIO_DAC0_TEST
/* Create McASP channel for Tx */
status = mcaspCreateChan(&hMcaspTxChan, hMcaspDevTx,
MCASP_OUTPUT,
&mcaspTx0ChanParam,
mcaspAppCallback, &txChanMode);
if((status != MCASP_COMPLETED) || (hMcaspTxChan == NULL))
{
IFPRINT(aud_write("mcaspCreateChan for Tx Failed\n"));
return (Aud_EFAIL);
}
#else
/* Create McASP channel for Tx */
status = mcaspCreateChan(&hMcaspTxChan, hMcaspDevTx,
MCASP_OUTPUT,
&mcaspTx1ChanParam,
mcaspAppCallback, &txChanMode);
if((status != MCASP_COMPLETED) || (hMcaspTxChan == NULL))
{
IFPRINT(aud_write("mcaspCreateChan for Tx Failed\n"));
return (Aud_EFAIL);
}
#endif
configAudioDAC();
/* Create McASP channel for Rx */
status = mcaspCreateChan(&hMcaspRxChan, hMcaspDevRx,
MCASP_INPUT,
&mcaspRxChanParam,
mcaspAppCallback, &rxChanMode);
if((status != MCASP_COMPLETED) || (hMcaspRxChan == NULL))
{
IFPRINT(aud_write("mcaspCreateChan for Rx Failed\n"));
return (Aud_EFAIL);
}
/* Initialize the buffers and submit for McASP Tx/Rx */
if(initBuffers() != Aud_EOK)
{
IFPRINT(aud_write("McASP Buffer Initialization Failed\n"));
return (Aud_EFAIL);
}
return (Aud_EOK);
}
/**
* \brief Function to exit the test
*
* \return None
*/
void testRet(uint32_t status)
{
aud_write("\n\nAudio DC Analog Interface Test Completed!\n");
testExit(status);
}
int total_audio_frame_num = 0;
/**
* \brief Task to echo the input data to output
*
* Waits for the McASP data transfer completion and copies the
* Rx data to Tx buffers
*
* \return Aud_EOK on Success or error code
*/
Void Audio_echo_Task(void)
{
int32_t count;
Semaphore_Params_init(¶ms);
/* Create semaphores to wait for buffer reclaiming */
semR = Semaphore_create(0, ¶ms, &eb);
semT = Semaphore_create(0, ¶ms, &eb);
/* Forever loop to continuously receive and transmit audio data */
while (1)
{
if(gblErrFlag)
{
break;
}
/* Reclaim full buffer from the input stream */
Semaphore_pend(semR, BIOS_WAIT_FOREVER);
Semaphore_pend(semT, BIOS_WAIT_FOREVER);
/* Reclaim full buffer from the input stream */
gtxFrameIndexCount = txFrameIndex;
grxFrameIndexCount = rxFrameIndex;
for(count = 0; count < 0; count++)
{
asm("* Comment to maintain loops through compiler optimization");
}
/* Reclaim empty buffer from the output stream to be reused */
/* Copy the receive information to the transmit buffer */
// memcpy(txBuf[gtxFrameIndexCount], rxBuf[grxFrameIndexCount], (BUFSIZE * RX_NUM_SERIALIZER)); // This line uncommented in original code
// memcpy(txBuf[gtxFrameIndexCount], (const void *)sineData, (BUFSIZE * RX_NUM_SERIALIZER));
// memcpy(txBuf[gtxFrameIndexCount], (const void *)sineData_4ch, (BUFSIZE * RX_NUM_SERIALIZER));
input = (int32_t *)rxBuf[grxFrameIndexCount];
output = (int32_t *)txBuf[gtxFrameIndexCount];
int i, j=0;
for(i=0; i<BUFSIZE * RX_NUM_SERIALIZER/sizeof(int32_t); i++){
if (i%8 == 0){
err_block[j] = input[i];
output[i] = input[i];
// aud_write("%d \n", BUFSIZE);
j++;
}
// else{
// output[i] = 0;
// }
}
/* Issue full buffer to the output stream */
/* TX frame processing */
txFrame[gtxFrameIndexCount].cmd = MCASP_READ;
txFrame[gtxFrameIndexCount].addr = (void*)(getGlobalAddr(txBuf[gtxFrameIndexCount]));
txFrame[gtxFrameIndexCount].size = (BUFSIZE*TX_NUM_SERIALIZER);
txFrame[gtxFrameIndexCount].arg = (uint32_t) mcaspTxChanArg;
txFrame[gtxFrameIndexCount].status = 0;
txFrame[gtxFrameIndexCount].misc = 1; /* reserved - used in callback to indicate asynch packet */
mcaspSubmitChan(hMcaspTxChan, &txFrame[gtxFrameIndexCount]);
/* Issue an empty buffer to the input stream */
rxFrame[grxFrameIndexCount].cmd = MCASP_WRITE;
rxFrame[grxFrameIndexCount].addr = (void*)(getGlobalAddr(rxBuf[grxFrameIndexCount]));
rxFrame[grxFrameIndexCount].size = (BUFSIZE*RX_NUM_SERIALIZER);
rxFrame[grxFrameIndexCount].arg = (uint32_t) mcaspRxChanArg;
rxFrame[grxFrameIndexCount].status = 0;
rxFrame[grxFrameIndexCount].misc = 1; /* reserved - used in callback to indicate asynch packet */
mcaspSubmitChan(hMcaspRxChan, &rxFrame[grxFrameIndexCount]);
total_audio_frame_num++;
// if (total_audio_frame_num==500)
// {
// aud_write("\nTest Passed\n");
// UART_printf("\nTest Passed\n");
// }
}
testRet(0);
}
/* Nothing past this point */