Post Go back to editing

BF706 2D DMA Audio Loopback

I am trying to get a basic loopback dma ping pong audio test to work with the ADSP-BF706 EZ-KIT-MINI. This supposed to be a 2d array to emulate a ping pong approach. I have everything working, but there seems to be a pop or glitch at the beginning or end of each block when being transmitted. I can't figure out what it is, but it seems like something is out of sync. Does my initialization code and interrupts look good? I have shown the relevant code below:

int32_t TX_buffer[BUFFER_SIZE*2];
int32_t RX_buffer[BUFFER_SIZE*2];
int32_t audio_buffer[BUFFER_SIZE];

volatile char RX_shift=0;
volatile char TX_shift=0;

void sport_init(void)
{
// SPORT0_A initialization
*pREG_SPORT0_CTL_A = ENUM_SPORT_CTL_TX
|ENUM_SPORT_CTL_CLK_RISE_EDGE
|ENUM_SPORT_CTL_I2S_MODE
|23<<4;
*pREG_SPORT0_DIV_A = (64<<BITP_SPORT_DIV_FSDIV)
|(1<<BITP_SPORT_DIV_CLKDIV);


// SPORT0_B initialization
*pREG_SPORT0_CTL2_A = ENUM_SPORT_CTL2_CLK_MUX_EN
|ENUM_SPORT_CTL2_FS_MUX_EN;
*pREG_SPORT0_CTL_B =
ENUM_SPORT_CTL_CLK_RISE_EDGE
|ENUM_SPORT_CTL_I2S_MODE
|23<<4;
*pREG_SPORT0_DIV_B = (64<<BITP_SPORT_DIV_FSDIV)
|(1<<BITP_SPORT_DIV_CLKDIV);

}

void dma_init(void)
{

//DMA0 initialization
*pREG_DMA0_CFG = ENUM_DMA_CFG_XCNT_INT
|ENUM_DMA_CFG_AUTO
|ENUM_DMA_CFG_ADDR2D
|ENUM_DMA_CFG_PSIZE04
|ENUM_DMA_CFG_MSIZE04;
*pREG_DMA0_ADDRSTART = TX_buffer;
*pREG_DMA0_XCNT = BUFFER_SIZE;
*pREG_DMA0_YCNT = 2;
*pREG_DMA0_XMOD = 4;
*pREG_DMA0_YMOD = 4;


// DMA1 initialization
*pREG_DMA1_CFG = ENUM_DMA_CFG_XCNT_INT
|ENUM_DMA_CFG_WRITE
|ENUM_DMA_CFG_AUTO
|ENUM_DMA_CFG_ADDR2D
|ENUM_DMA_CFG_PSIZE04
|ENUM_DMA_CFG_MSIZE04;
*pREG_DMA1_ADDRSTART = RX_buffer;
*pREG_DMA1_XCNT = BUFFER_SIZE;
*pREG_DMA1_YCNT = 2;
*pREG_DMA1_XMOD = 4;
*pREG_DMA1_YMOD = 4;
}

void DMA_RX_interrupt_handler(uint32_t iid, void *handlerArg)
{
if (*pREG_DMA1_STAT & ENUM_DMA_STAT_IRQDONE)
*pREG_DMA1_STAT = ENUM_DMA_STAT_IRQDONE;

for (int i = 0; i < BUFFER_SIZE; i++)
{
audio_buffer[i] = RX_buffer[i + RX_shift * BUFFER_SIZE];

}
RX_shift ^= 1;

}

void DMA_TX_interrupt_handler(uint32_t iid, void *handlerArg)
{
if (*pREG_DMA0_STAT & ENUM_DMA_STAT_IRQDONE)
*pREG_DMA0_STAT = ENUM_DMA_STAT_IRQDONE;

for (int i = 0; i < BUFFER_SIZE; i++)
{
TX_buffer[i + TX_shift * BUFFER_SIZE] = audio_buffer[i];

}
TX_shift ^= 1;

}

void main(void)
{
//INIT CLOCK AND EVERYTHING ELSE
*pREG_SEC0_GCTL = ENUM_SEC_GCTL_EN; // Enable the System Event Controller (SEC)
*pREG_SEC0_CCTL0 = ENUM_SEC_CCTL_EN; // Enable SEC Core Interface (SCI)
adi_int_InstallHandler(INTR_SPORT0_B_DMA, DMA_RX_interrupt_handler, 0, true);
adi_int_InstallHandler(INTR_SPORT0_A_DMA, DMA_TX_interrupt_handler, 0, true);
dma_init();
sport_init();

*pREG_DMA0_CFG |= ENUM_DMA_CFG_EN;
*pREG_DMA1_CFG |= ENUM_DMA_CFG_EN;
*pREG_SPORT0_CTL_B |= 1;
*pREG_SPORT0_CTL_A |= 1;


while (1) idle();
}

  • Can you please share us whole project file to replicate the issue on EZ-Kit?

  • Hi Mike,

    2D-DMA is an excellent idea for implementing double-buffering - and it works!
    Did you come to the same conclusion?
    You will find the full project in BF706_Audio_Filter_2018.zip
    I tested this with BLOCK_SIZE from 1 to 16384. It generates one DMA-interrupt

    per block and the audio processing can be done in the RX_interrupt_handler.
    Seems to be stable even for high computational load.
    I found the latency is lowest for TX_idx (Tx_shift) starting with 1.

    Best regards
    Uwe

  • Hello Jithul,

    this is the best solution I found for real-time audio processing so far

    (full project below). I did not use the ENUM_SORT_... macros because
    there seems to be an error in defBF706.h (CCES 2.7):

    #define ENUM_SPORT_CTL_FS_LO    (_ADI_MSK_3(0x00000000,0x00000000U,uint32_t))
    #define ENUM_SPORT_CTL_FS_HI      (_ADI_MSK_3(0x00010000,0x00010000U,uint32_t))

    ADSP-BF70x Blackfin+ Processor Hardware Reference 1.0, states on page 31-59
    that bit 16 (LFS) must 1 for active low frame sync (not 0 as in defBF706.h)
    LFS must be one to receive the data in the order left / right.

    Furthermore, in the processor selection table
    www.analog.com/en/products/processors-dsp/dsp/blackfin.html
    all Blackfin+ processors seem to have DDR2/LPDDR (16-bit) support.
    I think this is only true for the odd-numbered processors BF701 .. 707.

    Best regards
    Uwe

  • The information about LFS mentioned in the BF70x HRM rev 1.0 is correct. It seems the given name for the macro (ENUM_SPORT_CTL_FS_LO and  ENUM_SPORT_CTL_FS_HI) in the defBF706.h is confusing, but the comments  states the behaviour correctly.

     

    For Active Low FS you should use ENUM_SPORT_CTL_FS_HI

     

     

     

  • Ok, I agree. The macro definition is correct but somewhat confusing.

  • This is a slightly optimized version: audio_buffer[] is not necessary,
    the processing can be done in the receive buffer. The complete file
    main.cpp is attached.

    #define BLOCK_SIZE  1                       // Audio block size
    #define NUM_CHANS   2                       // Number of channels
    #define BUFFER_SIZE (BLOCK_SIZE*NUM_CHANS)  // DMA buffer size

    static int32_t TX_buffer[2][BUFFER_SIZE];   // SPORT 2D-DMA TX buffer
    static int32_t RX_buffer[2][BUFFER_SIZE];   // SPORT 2D-DMA RX buffer

    volatile int RX_idx = 0;
    volatile int TX_idx = 0;

    // Function SPORT0_RX_interrupt_handler is called after a complete
    // frame of input data has been received.
    void DMA_RX_interrupt_handler(uint32_t iid, void *handlerArg)
    {
        // Acknowledge interrupt
        if (*pREG_DMA1_STAT & ENUM_DMA_STAT_IRQDONE)
            *pREG_DMA1_STAT = ENUM_DMA_STAT_IRQDONE;

        for (int i=0; i<BUFFER_SIZE; i++)
            RX_buffer[RX_idx][i] <<= 8;

        audio_processing(RX_buffer[RX_idx], NUM_CHANS, BLOCK_SIZE);

        RX_idx ^= 1;
    }

    // Function SPORT0_TX_interrupt_handler is called after a complete
    // frame of input data has been received.
    void DMA_TX_interrupt_handler(uint32_t iid, void *handlerArg)
    {
        // Acknowledge interrupt
        if (*pREG_DMA0_STAT & ENUM_DMA_STAT_IRQDONE)
            *pREG_DMA0_STAT = ENUM_DMA_STAT_IRQDONE;

        for (int i=0; i<BUFFER_SIZE; i++)
            TX_buffer[TX_idx ^ 1][i] = RX_buffer[RX_idx ^ 1][i] >> 8;

        TX_idx ^= 1;
    }

    Some measurement results for the analog in to analog out latency:
    BLOCK_SIZE 128 at 48 kHz: 6.296 ms = 302 samples = 2* BLOCK_SIZE + CODEC
    BLOCK_SIZE  1   at  48 kHz: 1.198 ms * 48 = 57.5 samples
    BLOCK_SIZE  1   at  96 kHz: 0.463 ms * 96 = 44.5 samples

  • Hi Uwe Simmer,

     

    Thanks for sharing the optimised project here, appreciate it!

     

    Best Regards,

    Jithul

  • After some test with full computational load I found omitting

    the audio buffer and reducing the latency is not a good idea for
    the 2D-DMA software. BF706_Audio_2DDMA.zip is the fully tested
    latest version of this implementation.
    For a block size of 128 the measured analog in to analog out
    latency is 8.972 ms or 431 samples or 3 * BLOCK_SIZE + CODEC latency.

    I measured the same latency for the Audio Filter Callback example
    using ADAU1761 device driver (ADSP-BF706_EZ-KIT_Mini-Rel1.1.0).
    The input polarity seems to be reversed and left and right channel
    seem to be interchanged (right, left instead of left, right).

    If latency is a critical issue the older version BF706_Audio_DMA.zip
    (with double buffering by software) could be useful.
    The measured latency is 6.543 ms or 314 samples or 2 * BLOCK_SIZE + CODEC

  • This is a unified version: all methods for audio input and output in one project.
    BF706_Audio_2018 contains sample be sample processing, block processing
    2D-DMA and several sampling rates from 7350 to 88200 Hz and from 8000 to 96000 Hz.
    The options can be changed in config.h
    A batch file FLASH_BF706.cmd for flash programming is inluded in the project directory.

  • This question has been assumed as answered either offline via email or with a multi-part answer. This question has now been closed out. If you have an inquiry related to this topic please post a new question in the applicable product forum.

    Thank you,
    EZ Admin