This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

EVMK2G: Audio Processing using AUDK2G Daughter card

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(&params);

    /* Create semaphores to wait for buffer reclaiming */
    semR = Semaphore_create(0, &params, &eb);
    semT = Semaphore_create(0, &params, &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 */

  • I think I figured out why. Let me know if I am wrong.

    Here's why I was facing the issue:
    The ADC on the audio daughtercard has a 24bit ADC. This means that values that I will get on the port will range from 0 to 2^24 - 1. Now if I simply typecast a 32 bit unsigned int value from the MCASP to 32 bit int, there will be no change in the waveform. Therefore, I explicitly need to convert the values considering a 24 bit ADC.

  • Hello,

    Yes, I think you've found the problem and your solution is a good one.

    Regards,

    Jianzhong