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...

Cheers, 

Mario G.

Firmware Engineer

dreamsmatrix@gmail.com

Audio_Filter_Control.rar
Parents
  • The reason you don't understand is because you are not using a logical method to understand the function of the registers and I cannot blame you for that! You have to have banged your head for years doing work with cryptic DSP registers to have a grasp about how to solve it! The reason those guys know is because they work in assembly and low level C using what they call register pointer casting. What page it is on is irrelevant. You will quickly realize that there are helpful flags inside the document you mention and that what matters. If the flag is on it is an one at that position, otherwise it is zero. You start to move your way up the register concatenating or flags moving up the register to the left using powers of two counting up from LSB position. Sometimes the powers of two have to be added a one two for the next position if the register position is set to a one (1). so thus become odd. ie. 1,3,5,7. A better way to visualize that I use often is to engage the calculator in windows in Programming mode! That makes it even easier...

    For example, taking Patrick's example above I can see that the register pointer 

    *pREG_SPORT0_CTL_A=0x2001973;

    that breaks out into the binary sequence above shown on my binary sequence of the calculator..

    If you were paying attention you could have easily have right clicked that register which is supported inside another header file and jumped straight to the register definition file and gotten something like this :

     

    /* =========================================================================
    SPORT0
    ========================================================================= */
    #define pREG_SPORT0_CTL_A ((volatile uint32_t *)REG_SPORT0_CTL_A) /* SPORT0 Half SPORT 'A' Control Register */
    #define pREG_SPORT0_DIV_A ((volatile uint32_t *)REG_SPORT0_DIV_A) /* SPORT0 Half SPORT 'A' Divisor Register */
    #define pREG_SPORT0_MCTL_A ((volatile uint32_t *)REG_SPORT0_MCTL_A) /* SPORT0 Half SPORT 'A' Multi-channel Control Register */
    #define pREG_SPORT0_CS0_A ((volatile uint32_t *)REG_SPORT0_CS0_A) /* SPORT0 Half SPORT 'A' Multi-channel 0-31 Select Register */
    #define pREG_SPORT0_CS1_A ((volatile uint32_t *)REG_SPORT0_CS1_A) /* SPORT0 Half SPORT 'A' Multi-channel 32-63 Select Register */
    #define pREG_SPORT0_CS2_A ((volatile uint32_t *)REG_SPORT0_CS2_A) /* SPORT0 Half SPORT 'A' Multi-channel 64-95 Select Register */
    #define pREG_SPORT0_CS3_A ((volatile uint32_t *)REG_SPORT0_CS3_A) /* SPORT0 Half SPORT 'A' Multi-channel 96-127 Select Register */
    #define pREG_SPORT0_ERR_A ((volatile uint32_t *)REG_SPORT0_ERR_A) /* SPORT0 Half SPORT 'A' Error Register */
    #define pREG_SPORT0_MSTAT_A ((volatile uint32_t *)REG_SPORT0_MSTAT_A) /* SPORT0 Half SPORT 'A' Multi-channel Status Register */
    #define pREG_SPORT0_CTL2_A ((volatile uint32_t *)REG_SPORT0_CTL2_A) /* SPORT0 Half SPORT 'A' Control 2 Register */
    #define pREG_SPORT0_TXPRI_A ((volatile uint32_t *)REG_SPORT0_TXPRI_A) /* SPORT0 Half SPORT 'A' Tx Buffer (Primary) Register */
    #define pREG_SPORT0_RXPRI_A ((volatile uint32_t *)REG_SPORT0_RXPRI_A) /* SPORT0 Half SPORT 'A' Rx Buffer (Primary) Register */
    #define pREG_SPORT0_TXSEC_A ((volatile uint32_t *)REG_SPORT0_TXSEC_A) /* SPORT0 Half SPORT 'A' Tx Buffer (Secondary) Register */
    #define pREG_SPORT0_RXSEC_A ((volatile uint32_t *)REG_SPORT0_RXSEC_A) /* SPORT0 Half SPORT 'A' Rx Buffer (Secondary) Register */
    #define pREG_SPORT0_CTL_B ((volatile uint32_t *)REG_SPORT0_CTL_B) /* SPORT0 Half SPORT 'B' Control Register */
    #define pREG_SPORT0_DIV_B ((volatile uint32_t *)REG_SPORT0_DIV_B) /* SPORT0 Half SPORT 'B' Divisor Register */
    #define pREG_SPORT0_MCTL_B ((volatile uint32_t *)REG_SPORT0_MCTL_B) /* SPORT0 Half SPORT 'B' Multi-channel Control Register */
    #define pREG_SPORT0_CS0_B ((volatile uint32_t *)REG_SPORT0_CS0_B) /* SPORT0 Half SPORT 'B' Multi-channel 0-31 Select Register */
    #define pREG_SPORT0_CS1_B ((volatile uint32_t *)REG_SPORT0_CS1_B) /* SPORT0 Half SPORT 'B' Multi-channel 32-63 Select Register */
    #define pREG_SPORT0_CS2_B ((volatile uint32_t *)REG_SPORT0_CS2_B) /* SPORT0 Half SPORT 'B' Multichannel 64-95 Select Register */
    #define pREG_SPORT0_CS3_B ((volatile uint32_t *)REG_SPORT0_CS3_B) /* SPORT0 Half SPORT 'B' Multichannel 96-127 Select Register */
    #define pREG_SPORT0_ERR_B ((volatile uint32_t *)REG_SPORT0_ERR_B) /* SPORT0 Half SPORT 'B' Error Register */
    #define pREG_SPORT0_MSTAT_B ((volatile uint32_t *)REG_SPORT0_MSTAT_B) /* SPORT0 Half SPORT 'B' Multi-channel Status Register */
    #define pREG_SPORT0_CTL2_B ((volatile uint32_t *)REG_SPORT0_CTL2_B) /* SPORT0 Half SPORT 'B' Control 2 Register */
    #define pREG_SPORT0_TXPRI_B ((volatile uint32_t *)REG_SPORT0_TXPRI_B) /* SPORT0 Half SPORT 'B' Tx Buffer (Primary) Register */
    #define pREG_SPORT0_RXPRI_B ((volatile uint32_t *)REG_SPORT0_RXPRI_B) /* SPORT0 Half SPORT 'B' Rx Buffer (Primary) Register */
    #define pREG_SPORT0_TXSEC_B ((volatile uint32_t *)REG_SPORT0_TXSEC_B) /* SPORT0 Half SPORT 'B' Tx Buffer (Secondary) Register */
    #define pREG_SPORT0_RXSEC_B ((volatile uint32_t *)REG_SPORT0_RXSEC_B) /* SPORT0 Half SPORT 'B' Rx Buffer (Secondary) Register */

    All of those register definitions are covered in detail inside the book you mentioned above. Blackfins are wonderfully similar, even if slightly different architecture wise...

    // Function configure_sport initializes the SPORT0. Refer to pages 31-55, 31-63,
    // 31-72 and 31-73 of the ADSP-BF70x Blackfin+ Processor Hardware Reference, Revision 1.0.
    void configure_SPORT()
    {
    *pREG_SPORT0_CTL_A = 0x02011972; // Set up SPORT0 (A) as TX to CODEC, I2S, 24 bits
    *pREG_SPORT0_DIV_A = 0x00400001; // 64 bits per frame, clock divisor of 1
    *pREG_SPORT0_CTL_B = 0x00011972; // Set up SPORT0 (B) as RX from CODEC, I2S, 24 bits
    *pREG_SPORT0_DIV_B = 0x00400001; // 64 bits per frame, clock divisor of 1
    }

    Look up the register definition inside the document you mentioned by simply invoking the search bar of the .PDF and type sport

    Lets go ahead and choose the one in question that you highlighted and lets click on it inside the .PDF

    Now those bit positions I have shown you on the calculator should become painfully obvious...They should map correctly into the refference doc as you see in the breakout diagram. I'm not going to get into the details for you, I'm only showing you the road map on how to decipher this stuff. What is left for you to do is pay attention to the book, because it gives detailed insight about how this SPORT perhipheral(s) and codec(s) work. It might take a few days of probing around to get it! What would be even more fun for you to do is to actually use that number shown above and interpret it as a collection of flags or(ed) together as shown by the professor inside the book! 

    HINT - Those are found inside the def files for the corresponding blackfin. Searching of some headers should get you there! For example right clicking on one particular flag name in the source code for the BF537 jumped to this def file...Doing a search in the PDF for that flag by scrolling down the peripheral page, I can get great detail as far as what that particular flag means...

    *pDMA3_CONFIG = WNR | WDSIZE_32 | DI_EN | FLOW_1 | DMA2D | DI_SEL;

    As you can see, doing your own investigation of those flags is way superior method of understanding rather than deciphering scribble that could have originated from an older document which you have no idea what it was and which version. I'm showing you how to drill down and find stuff faster and more accurately! The header files are your friend...

    Of course you can always take it by faith that those guys knew what they were doing when they set them up, but that won't help you understand! 

    You can find all the flag definitions for registers inside defBF706.h

    You don't even need a manual most of the time, but hey, it is good read! Happy digging...

    Mario

Reply
  • The reason you don't understand is because you are not using a logical method to understand the function of the registers and I cannot blame you for that! You have to have banged your head for years doing work with cryptic DSP registers to have a grasp about how to solve it! The reason those guys know is because they work in assembly and low level C using what they call register pointer casting. What page it is on is irrelevant. You will quickly realize that there are helpful flags inside the document you mention and that what matters. If the flag is on it is an one at that position, otherwise it is zero. You start to move your way up the register concatenating or flags moving up the register to the left using powers of two counting up from LSB position. Sometimes the powers of two have to be added a one two for the next position if the register position is set to a one (1). so thus become odd. ie. 1,3,5,7. A better way to visualize that I use often is to engage the calculator in windows in Programming mode! That makes it even easier...

    For example, taking Patrick's example above I can see that the register pointer 

    *pREG_SPORT0_CTL_A=0x2001973;

    that breaks out into the binary sequence above shown on my binary sequence of the calculator..

    If you were paying attention you could have easily have right clicked that register which is supported inside another header file and jumped straight to the register definition file and gotten something like this :

     

    /* =========================================================================
    SPORT0
    ========================================================================= */
    #define pREG_SPORT0_CTL_A ((volatile uint32_t *)REG_SPORT0_CTL_A) /* SPORT0 Half SPORT 'A' Control Register */
    #define pREG_SPORT0_DIV_A ((volatile uint32_t *)REG_SPORT0_DIV_A) /* SPORT0 Half SPORT 'A' Divisor Register */
    #define pREG_SPORT0_MCTL_A ((volatile uint32_t *)REG_SPORT0_MCTL_A) /* SPORT0 Half SPORT 'A' Multi-channel Control Register */
    #define pREG_SPORT0_CS0_A ((volatile uint32_t *)REG_SPORT0_CS0_A) /* SPORT0 Half SPORT 'A' Multi-channel 0-31 Select Register */
    #define pREG_SPORT0_CS1_A ((volatile uint32_t *)REG_SPORT0_CS1_A) /* SPORT0 Half SPORT 'A' Multi-channel 32-63 Select Register */
    #define pREG_SPORT0_CS2_A ((volatile uint32_t *)REG_SPORT0_CS2_A) /* SPORT0 Half SPORT 'A' Multi-channel 64-95 Select Register */
    #define pREG_SPORT0_CS3_A ((volatile uint32_t *)REG_SPORT0_CS3_A) /* SPORT0 Half SPORT 'A' Multi-channel 96-127 Select Register */
    #define pREG_SPORT0_ERR_A ((volatile uint32_t *)REG_SPORT0_ERR_A) /* SPORT0 Half SPORT 'A' Error Register */
    #define pREG_SPORT0_MSTAT_A ((volatile uint32_t *)REG_SPORT0_MSTAT_A) /* SPORT0 Half SPORT 'A' Multi-channel Status Register */
    #define pREG_SPORT0_CTL2_A ((volatile uint32_t *)REG_SPORT0_CTL2_A) /* SPORT0 Half SPORT 'A' Control 2 Register */
    #define pREG_SPORT0_TXPRI_A ((volatile uint32_t *)REG_SPORT0_TXPRI_A) /* SPORT0 Half SPORT 'A' Tx Buffer (Primary) Register */
    #define pREG_SPORT0_RXPRI_A ((volatile uint32_t *)REG_SPORT0_RXPRI_A) /* SPORT0 Half SPORT 'A' Rx Buffer (Primary) Register */
    #define pREG_SPORT0_TXSEC_A ((volatile uint32_t *)REG_SPORT0_TXSEC_A) /* SPORT0 Half SPORT 'A' Tx Buffer (Secondary) Register */
    #define pREG_SPORT0_RXSEC_A ((volatile uint32_t *)REG_SPORT0_RXSEC_A) /* SPORT0 Half SPORT 'A' Rx Buffer (Secondary) Register */
    #define pREG_SPORT0_CTL_B ((volatile uint32_t *)REG_SPORT0_CTL_B) /* SPORT0 Half SPORT 'B' Control Register */
    #define pREG_SPORT0_DIV_B ((volatile uint32_t *)REG_SPORT0_DIV_B) /* SPORT0 Half SPORT 'B' Divisor Register */
    #define pREG_SPORT0_MCTL_B ((volatile uint32_t *)REG_SPORT0_MCTL_B) /* SPORT0 Half SPORT 'B' Multi-channel Control Register */
    #define pREG_SPORT0_CS0_B ((volatile uint32_t *)REG_SPORT0_CS0_B) /* SPORT0 Half SPORT 'B' Multi-channel 0-31 Select Register */
    #define pREG_SPORT0_CS1_B ((volatile uint32_t *)REG_SPORT0_CS1_B) /* SPORT0 Half SPORT 'B' Multi-channel 32-63 Select Register */
    #define pREG_SPORT0_CS2_B ((volatile uint32_t *)REG_SPORT0_CS2_B) /* SPORT0 Half SPORT 'B' Multichannel 64-95 Select Register */
    #define pREG_SPORT0_CS3_B ((volatile uint32_t *)REG_SPORT0_CS3_B) /* SPORT0 Half SPORT 'B' Multichannel 96-127 Select Register */
    #define pREG_SPORT0_ERR_B ((volatile uint32_t *)REG_SPORT0_ERR_B) /* SPORT0 Half SPORT 'B' Error Register */
    #define pREG_SPORT0_MSTAT_B ((volatile uint32_t *)REG_SPORT0_MSTAT_B) /* SPORT0 Half SPORT 'B' Multi-channel Status Register */
    #define pREG_SPORT0_CTL2_B ((volatile uint32_t *)REG_SPORT0_CTL2_B) /* SPORT0 Half SPORT 'B' Control 2 Register */
    #define pREG_SPORT0_TXPRI_B ((volatile uint32_t *)REG_SPORT0_TXPRI_B) /* SPORT0 Half SPORT 'B' Tx Buffer (Primary) Register */
    #define pREG_SPORT0_RXPRI_B ((volatile uint32_t *)REG_SPORT0_RXPRI_B) /* SPORT0 Half SPORT 'B' Rx Buffer (Primary) Register */
    #define pREG_SPORT0_TXSEC_B ((volatile uint32_t *)REG_SPORT0_TXSEC_B) /* SPORT0 Half SPORT 'B' Tx Buffer (Secondary) Register */
    #define pREG_SPORT0_RXSEC_B ((volatile uint32_t *)REG_SPORT0_RXSEC_B) /* SPORT0 Half SPORT 'B' Rx Buffer (Secondary) Register */

    All of those register definitions are covered in detail inside the book you mentioned above. Blackfins are wonderfully similar, even if slightly different architecture wise...

    // Function configure_sport initializes the SPORT0. Refer to pages 31-55, 31-63,
    // 31-72 and 31-73 of the ADSP-BF70x Blackfin+ Processor Hardware Reference, Revision 1.0.
    void configure_SPORT()
    {
    *pREG_SPORT0_CTL_A = 0x02011972; // Set up SPORT0 (A) as TX to CODEC, I2S, 24 bits
    *pREG_SPORT0_DIV_A = 0x00400001; // 64 bits per frame, clock divisor of 1
    *pREG_SPORT0_CTL_B = 0x00011972; // Set up SPORT0 (B) as RX from CODEC, I2S, 24 bits
    *pREG_SPORT0_DIV_B = 0x00400001; // 64 bits per frame, clock divisor of 1
    }

    Look up the register definition inside the document you mentioned by simply invoking the search bar of the .PDF and type sport

    Lets go ahead and choose the one in question that you highlighted and lets click on it inside the .PDF

    Now those bit positions I have shown you on the calculator should become painfully obvious...They should map correctly into the refference doc as you see in the breakout diagram. I'm not going to get into the details for you, I'm only showing you the road map on how to decipher this stuff. What is left for you to do is pay attention to the book, because it gives detailed insight about how this SPORT perhipheral(s) and codec(s) work. It might take a few days of probing around to get it! What would be even more fun for you to do is to actually use that number shown above and interpret it as a collection of flags or(ed) together as shown by the professor inside the book! 

    HINT - Those are found inside the def files for the corresponding blackfin. Searching of some headers should get you there! For example right clicking on one particular flag name in the source code for the BF537 jumped to this def file...Doing a search in the PDF for that flag by scrolling down the peripheral page, I can get great detail as far as what that particular flag means...

    *pDMA3_CONFIG = WNR | WDSIZE_32 | DI_EN | FLOW_1 | DMA2D | DI_SEL;

    As you can see, doing your own investigation of those flags is way superior method of understanding rather than deciphering scribble that could have originated from an older document which you have no idea what it was and which version. I'm showing you how to drill down and find stuff faster and more accurately! The header files are your friend...

    Of course you can always take it by faith that those guys knew what they were doing when they set them up, but that won't help you understand! 

    You can find all the flag definitions for registers inside defBF706.h

    You don't even need a manual most of the time, but hey, it is good read! Happy digging...

    Mario

Children
No Data