/PRU-Audio-Processing

Implement a CIC filter running on the PRUs of the BeagleBone Black with a 1-bit wide input

Primary LanguageTeX

PRU-Audio-Processing (in progress!)

This is the repository of my bachelor's project. The project aims to run a microphone array on the BeagleBone Black, using the PRU Sub System to process the raw data from the microphones and offload it from the main ARM CPU. We also aim to provide an C API around the core audio processing core.

Interface

The host interface is written in C in the interface.h and interface.c files. It is currently very simple and provides the following functions :

/**
 * @brief Very basic interface for reading audio using the PRU firmware.
 * 
 */

#include "ringbuffer.h"
#include "loader.h"

#define SAMPLE_SIZE_BYTES 4

typedef struct pcm_t {
    // Number of channels
    size_t nchan;
    // *Per-channel* sample rate of the PCM signal in Hz
    size_t sample_rate;
    // The buffer accessed by the PRU, mapped by prussdrv, and its length
    volatile void * PRU_buffer;
    // Length of the aforementioned buffer
    unsigned int PRU_buffer_len;
    // The ring buffer which is the main place for storing data
    ringbuffer_t * main_buffer;
} pcm_t;

/**
 * @brief Initialize PRU processing. 
 *        Must be called before any other function of this file.
 * 
 * @return pcm_t* A pointer to a new pcm object in case of success, NULL otherwise.
 */
pcm_t * pru_processing_init(void);

/**
 * @brief Stop processing and free/close all resources.
 * 
 * @param pcm The pcm object containing the resources.
 */
void pru_processing_close(pcm_t * pcm);

/**
 * @brief Read a given number of blocks of given size 
 *        and output them to the user provided buffer.
 * 
 * @param src The source pcm from which to read.
 * @param dst The buffer to which we want to write data.
 * @param nsamples The number of samples to read from each channel.
 * @param nchan The number of channels to read.
 * @return int The number of samples effectively written.
 */
size_t pcm_read(pcm_t * src, void * dst, size_t nsamples, size_t nchan);

/**
 * @brief Get the current length of the circular buffer holding the recorded samples.
 * 
 * @param void 
 * @return size_t The length of the buffer.
 */
size_t pcm_buffer_length(void);

/**
 * @brief Get the max length of the circular buffer holding the recorded samples.
 * 
 * @param void 
 * @return size_t The max length of the buffer.
 */
size_t pcm_buffer_maxlength(void);

/**
 * @brief Enable recording of the audio to the ringbuffer.
 * 
 * Once this function is called, the interface will start copying
 * from the buffer the PRU writes to, to the main ringbuffer of the interface. 
 * In order to avoid a ringbuffer overflow, the user must therefore start 
 * reading using pcm_read quickly after this function had been called.
 * 
 */
void enable_recording(void);

/**
 * @brief Disable recording of the audio to the ringbuffer.
 * 
 * Once this function is called, the interface will stop copying data 
 * to the main ringbuffer. This means only the samples remaining in 
 * the ringbuffer after this function was called can be read.
 * 
 */
void disable_recording(void);

Getting Started

Get UIO to work and free the GPIO pins for the PRU (in progress)

Note: this was tested on this kernel: Linux beaglebone 4.4.91-ti-r133 #1 SMP Tue Oct 10 05:18:08 UTC 2017 armv7l GNU/Linux

In order to run the filter, we need to be able to use the input and output pins from the PRUs. Some of them can be multiplexed to the PRUs. However, by default, some pins cannot be reassigned to something else. To correct this, we need to load a cape. To do so, open the /boot/uEnv.txt file on the board (backup it first!) and do the following modifications :

Add the following line :

cape_enable=bone_capemgr.enable_partno=cape-universala

And comment the following line :

enable_uboot_cape_universal=1

You should now be able to multiplex a pin to the PRUs using the config-pin command (see these instructions for more details). We still have to enable the UIO driver, which is disabled in favor of remoteproc on this kernel. To do so, still in the /boot/uEnv.txt file, comment that line :

uboot_overlay_pru=/lib/firmware/AM335X-PRU-RPROC-4-4-TI-00A0.dtbo

And uncomment this one :

uboot_overlay_pru=/lib/firmware/AM335X-PRU-UIO-00A0.dtbo

Then :

$ cd /opt/source/dtb-4.4-ti
$ sudo nano src/arm/am335x-boneblack.dts

Comment that line :

#include "am33xx-pruss-rproc.dtsi"

And uncomment this one :

#include "am33xx-pruss-uio.dtsi"

Then close nano and run the following commands :

$ make
$ sudo make install

This is the final step. Run sudo nano /etc/modprobe.d/pruss-blacklist.conf and add the following lines :

blacklist pruss
blacklist pruss_intc
blacklist pru-rproc

Now reboot the board, and you should be able to run commands such as config-pin -q P8.45 without trouble.

Install PRUSS Driver Library (prussdrv) and PRU Assembler (pasm)

In order to install the PRUSS driver on the host side, first clone this repo. Then cd into the cloned repository and run the following commands :

$ make
$ sudo make install
$ sudo ldconfig

If everything went well, the prussdrv library and the pasm assembler should be installed on your board and ready to be used.

Useful links

Sharing internet with the BeagleBone : http://www.dangtrinh.com/2015/05/sharing-internet-with-beaglebone-black.html

Sources

UIO : http://catch22.eu/beaglebone/beaglebone-pru-uio/