BF706 UART DMA Terminal for Audio and FIR filter Control

This has yet to be my most complex Tutorial and I hope not the final one...I call it Audio Filter control. In fact it is many things in one. I have finally achieved UART immortality by being able to control everything from it. I can turn LED on and OFF. Set the BLINK Rate among many different rates, turn Audio ON and OFF and lastly, turn a Cross-Over filter ON or OFF. You might want to turn the LED OFF while the filter is executing or you might get weird feedback. I guess I'm not perfect, so nothing is stopping you from correcting my quickly written code that included the work of brilliant people here on the Forum. @PatrickG and @UweS to mention a few great minds...Lets move on, shall we ?!

This example can be a bit daunting, but it is really quite simple even underneath the surface. I have used Will Pirkle's excellent software called RackAFX to test my prototype whose simple parameters are passed passed in at the console. The only commands you need to know in this incarnation of the software are really: aud on / aud off /filt on / filt off.

Check out my other indepth tutorials for the other commands which are clearly obtained by typing term at the PUTTY terminal i.e.

The terminal is very self explanatory, so go ahead and experiment with the different terminal commands. The neat thing in this version is that you can simply engage a mode of the terminal that works for you by commenting or un-commenting one line at the top of the source! If you used the definition as you see below, it means you are running UART as DMA interrupt device. If you comment the line out you are only running interrupts RX and TX without DMA. The choice is yours! 

 // Comment out #define USE_UART_DMA to only engage UART in interrupt mode!
#define USE_UART_DMA


One you turn audio on via terminal command aud on you are on your way to play around with various instruments to feed audio into the line intput port and feed the output port to a scope, or head phones...

while the aud on or filt on is immediately typed at the PUTTY terminal console, you should see something on your scope that looks similar to either an audio signal passed in or perhaps an oscillator pulse from RackAFX.

If you engage UweS cross-over FIR filters, it can be done with filt on / filt off

I hope you found this tutorial useful. Let me know how it works out for you. As always I have attached the source code for it. If you can improve it and make it better also let me know how! I will evolve the terminal so that filter coefficients can be passed in automatically from a graphic environment. More on this later...


Mario G.

Firmware Engineer

  • Almost correct, only the sign of a2 is wrong and the coefficients a very unprecise
    (many trailing zeros). Please use these Matlab lines to create the coefficients:
    % conversion to Q2.30
    coeff1 = round( [ b(1) b(2) b(3) -a(2) -a(3) ] * 2^30 );
    fprintf(1, '%d\n', coeff1);

    The correct coefficients are:

    notch 1:

    notch 2:

  • Setting parameters via UART is a very usefull!
    A drawback of the ADI UART SSDD API seems to be that polling has to used
    to check for new input by calling adi_uart_IsRxBufferAvailable() in a loop.
    I did not find a documented method to install a receive callback function.
    BF609 UART DMA mode examples? 
    This is my workaround:

    result = adi_uart_SetMode(hDevice, ADI_UART_MODE_UART);
    result = adi_uart_SetBaudRate(hDevice, baud_rate);
    result = adi_uart_SetNumStopBits(hDevice, ADI_UART_ONE_STOPBIT);
    result = adi_uart_SetWordLen(hDevice, ADI_UART_WORDLEN_8BITS);
    result = adi_uart_SetParity(hDevice, ADI_UART_NO_PARITY);
    result = adi_uart_EnableTx(hDevice, true);
    result = adi_uart_EnableDMAMode(hDevice, true);
    result = adi_uart_SubmitRxBuffer(hDevice, rxBuffer, RX_BUFFER_SIZE);
    result = adi_uart_EnableRx(hDevice, true);

    if (uart_number == 0)
        *pREG_DMA11_CFG       = 0x00101002;     // UART0 RX, autobuffer mode
        *pREG_DMA11_ADDRSTART = rxBuffer;       // Points to start of RX buffer
        *pREG_DMA11_XCNT      = RX_BUFFER_SIZE; // Number of words to receive
        *pREG_DMA11_XMOD      = 1;              // Word size
        adi_int_InstallHandler(INTR_UART0_RXDMA, UART0_rx_interrupt_handler, this, true);

        *pREG_DMA11_CFG |= ENUM_DMA_CFG_EN;

    if (uart_number == 1)
        *pREG_DMA13_CFG       = 0x00101002;     // UART1 RX, autobuffer mode
        *pREG_DMA13_ADDRSTART = rxBuffer;       // Points to start of RX buffer
        *pREG_DMA13_XCNT      = RX_BUFFER_SIZE; // Number of words to receive
        *pREG_DMA13_XMOD      = 1;              // Word size
        adi_int_InstallHandler(INTR_UART1_RXDMA, UART1_rx_interrupt_handler, this, true);

        *pREG_DMA13_CFG |= ENUM_DMA_CFG_EN;
  • Cool! Signaling on one byte from the DMA transfer...Put up the source and

    I'll check it out...Its an elegant way to do it UweS!

    On Sun, Jul 15, 2018, 3:59 AM UweS <>

  • Mario, thanks for your feedback your enthusiasm and for sharing your knowledge!
    My example projects has a bug in audioprocessing.cpp (statesR[0] should be statesR[n])
    The UART software seems to be correct. There is also a little improvement in main.cpp:
    I remove audio_buffer[] saving some memory. I think you are right: circular buffers are
    more flexible and efficient than double buffering. I will try this later... contains the revised example.
  • Oh nice UweS...I appreciate all you do for the dsp community...Very helpful

    indeed...I will try your new improvements tonight after my daily firmware


    On Tue, Jul 17, 2018, 11:17 AM UweS <