Mercurial > hg > beaglert
diff include/Bela.h @ 301:e4392164b458 prerelease
RENAMED BeagleRT to Bela AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, scripts probably not working
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Fri, 27 May 2016 14:34:41 +0100 |
parents | include/BeagleRT.h@c55c6f6c233c |
children | 421a69d42943 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/Bela.h Fri May 27 14:34:41 2016 +0100 @@ -0,0 +1,621 @@ +/** + * @file + * @brief Main Bela public API + * + * Central control code for hard real-time audio on BeagleBone Black + * using PRU and Xenomai Linux extensions. This code began as part + * of the Hackable Instruments project (EPSRC) at Queen Mary University + * of London, 2013-14. + * + * (c) 2014-15 Andrew McPherson, Victor Zappi and Giulio Moro, + * Queen Mary University of London + */ + +/** + * \mainpage + * + * Bela is a hard-real-time, ultra-low latency audio and sensor environment for + * BeagleBone Black, which works with the BeagleBone Audio Cape or a custom "Bela Cape" + * which incorporates stereo audio with 8x, 16-bit analog inputs and outputs. + * + * Bela is based on the Xenomai real-time Linux extensions (http://xenomai.org) and + * uses the BeagleBone %PRU subsystem to address the audio and sensor hardware. + * + * Further information can be found at http://beaglert.cc + */ + + +#ifndef BEAGLERT_H_ +#define BEAGLERT_H_ + +#include <stdint.h> +#include <unistd.h> +#include <rtdk.h> +#include "digital_gpio_mapping.h" +#include <GPIOcontrol.h> + +// Useful constants + +/** \cond PRIVATE */ +#define DBOX_CAPE // New custom cape +#ifdef DBOX_CAPE +#define CODEC_I2C_ADDRESS 0x18 // Address of TLV320AIC3104 codec +#else +#define CODEC_I2C_ADDRESS 0x1B // Address of TLV320AIC3106 codec +#endif + +#define MAX_PRU_FILENAME_LENGTH 256 +#define MAX_SERVERNAME_LENGTH 256 +/** \endcond */ + +/** + * \ingroup auxtask + * + * Xenomai priority level for audio processing. Maximum possible priority is 99. + * In general, all auxiliary tasks should have a level lower than this unless for\ + * special purposes where the task needs to interrupt audio processing. + */ +#define BEAGLERT_AUDIO_PRIORITY 95 + +// Default volume levels + +/** + * \addtogroup levels + * + * @{ + */ + +/** + * Default level of the audio DAC in decibels. See Bela_setDACLevel(). + */ +#define DEFAULT_DAC_LEVEL 0.0 + +/** + * Default level of the audio ADC in decibels. See Bela_setADCLevel(). + */ +#define DEFAULT_ADC_LEVEL -6.0 + + +/** + * Default level of the Programmable Gain Amplifier in decibels. + */ +#define DEFAULT_PGA_GAIN 16 + +/** + * Default level of the headphone output in decibels. See Bela_setHeadphoneLevel(). + */ +#define DEFAULT_HP_LEVEL -6.0 +/** @} */ + +/** + * Flag for BelaContext. If set, indicates the audio and analog buffers are interleaved. + */ +#define BEAGLERT_FLAG_INTERLEAVED (1 << 0) // Set if buffers are interleaved +/** + * Flag for BelaContext. If set, indicates analog outputs persist for future frames. + */ +#define BEAGLERT_FLAG_ANALOG_OUTPUTS_PERSIST (1 << 1) // Set if analog/digital outputs persist for future buffers + +/** + * \ingroup control + * \brief Structure containing initialisation parameters for the real-time + * audio control system. + * + * This structure is initialised using Bela_defaultSettings(). Its contents + * are used up through the point of calling + * Bela_initAudio() at which point it is no longer needed. + */ +typedef struct { + // These items might be adjusted by the user: + + /// \brief Number of (analog) frames per period. + /// + /// Number of audio frames depends on relative sample rates of the two. By default, + /// audio is twice the sample rate, so has twice the period size. + int periodSize; + /// Whether to use the analog input and output + int useAnalog; + /// Whether to use the 16 programmable GPIOs + int useDigital; + /// How many channels for the ADC and DAC + int numAnalogChannels; + /// How many channels for the GPIOs + int numDigitalChannels; + + /// Whether to begin with the speakers muted + int beginMuted; + /// Level for the audio DAC output + float dacLevel; + /// Level for the audio ADC input + float adcLevel; + /// Gains for the PGA, left and right channels + float pgaGain[2]; + /// Level for the headphone output + float headphoneLevel; + /// How many channels to use on the multiplexer capelet, if enabled + int numMuxChannels; + + /// Which PRU (0 or 1) the code should run on + int pruNumber; + /// The external .bin file to load. If empty will use PRU code from pru_rtaudio_bin.h + char pruFilename[MAX_PRU_FILENAME_LENGTH]; + /// Whether to use verbose logging + int verbose; + + // These items are application-dependent but should probably be + // determined by the programmer rather than the user + + /// Whether audio/analog data should be interleaved + int interleave; + /// \brief Whether analog outputs should persist to future frames. + /// + /// n.b. digital pins always persist, audio never does + int analogOutputsPersist; + + // These items are hardware-dependent and should only be changed + // to run on different hardware + + /// Where the codec can be found on the I2C bus + int codecI2CAddress; + /// Pin where amplifier mute can be found + int ampMutePin; + /// Port where the UDP server will listen + int receivePort; + /// Port where the UDP client will transmit + int transmitPort; + char serverName[MAX_SERVERNAME_LENGTH]; +} BelaInitSettings; + + +/** + * \ingroup render + * \brief Structure holding current audio and sensor settings and pointers to data buffers. + * + * This structure is passed to setup(), render() and cleanup(). It is + * initialised in Bela_initAudio() based on the contents of the BelaInitSettings + * structure. + */ +typedef struct { + /// \brief Buffer holding audio input samples + /// + /// This buffer may be in either interleaved or non-interleaved format, + /// depending on the contents of the BelaInitSettings structure. + /// \b Note: this element is available in render() only. + float *audioIn; + + /// \brief Buffer holding audio output samples + /// + /// This buffer may be in either interleaved or non-interleaved format, + /// depending on the contents of the BelaInitSettings structure. + /// \b Note: this element is available in render() only. + float *audioOut; + + /// \brief Buffer holding analog input samples + /// + /// This buffer may be in either interleaved or non-interleaved format, + /// depending on the contents of the BelaInitSettings structure. + /// \b Note: this element is available in render() only. + float *analogIn; + + /// \brief Buffer holding analog output samples + /// + /// This buffer may be in either interleaved or non-interleaved format, + /// depending on the contents of the BelaInitSettings structure. + /// \b Note: this element is available in render() only. + float *analogOut; + + /// \brief Buffer holding digital input/output samples + /// + /// \b Note: this element is available in render() only. + uint32_t *digital; + + /// Number of audio frames per period + uint32_t audioFrames; + /// Number of audio channels (currently always 2) + uint32_t audioChannels; + /// Audio sample rate in Hz (currently always 44100.0) + float audioSampleRate; + + /// \brief Number of analog frames per period + /// + /// This will be 0 if analog I/O is disabled. + uint32_t analogFrames; + + /// \brief Number of analog channels + /// + /// This could take a value of 8, 4 or 2. This will be 0 if analog I/O is disabled. + uint32_t analogChannels; + + /// \brief Analog sample rate in Hz + /// + /// The analog sample rate depends on the number of analog channels used. If + /// 8 channels are used, the sample rate is 22050. If 4 channels are used, the sample + /// rate is 44100. If 2 channels are used, the sample rate is 88200. If analog I/O + /// is disabled, the sample rate is 0. + float analogSampleRate; + + /// Number of digital frames per period + uint32_t digitalFrames; + /// \brief Number of digital channels + /// + /// Currently this will always be 16, unless digital I/O is disabled, in which case it will be 0. + uint32_t digitalChannels; + /// Digital sample rate in Hz (currently always 44100.0) + float digitalSampleRate; + + /// \brief Number of elapsed audio samples since the start of rendering. + /// + /// This holds the total number of audio samples as of the beginning of the current period. To + /// find the current number of analog or digital samples elapsed, multiply by the ratio of the + /// sample rates (e.g. half the number of analog samples will have elapsed if the analog sample + /// rate is 22050). + uint64_t audioSampleCount; + + /// \brief Other audio/sensor settings + /// + /// Binary combination of flags including: + /// + /// BEAGLERT_FLAG_INTERLEAVED: indicates the audio and analog buffers are interleaved + /// + /// BEAGLERT_FLAG_ANALOG_OUTPUTS_PERSIST: indicates that writes to the analog outputs will + /// persist for future frames. If not set, writes affect one frame only. + uint32_t flags; +} BelaContext; + +/** \ingroup auxtask + * + * Auxiliary task variable. Auxiliary tasks are created using createAuxiliaryTask() and + * automatically cleaned up after cleanup() finishes. + */ +typedef void* AuxiliaryTask; // Opaque data type to keep track of aux tasks + +/** \ingroup render + * + * Flag that indicates when the audio will stop. Threads can poll this variable to indicate when + * they should stop. Additionally, a program can set this to \c true + * to indicate that audio processing should terminate. Calling Bela_stopAudio() + * has the effect of setting this to \c true. + */ +extern int gShouldStop; + +// *** User-defined render functions *** + +/** + * \defgroup render User-defined render functions + * + * These three functions must be implemented by the developer in every Bela program. + * Typically they appear in their own .cpp source file. + * + * @{ + */ + +/** + * \brief User-defined initialisation function which runs before audio rendering begins. + * + * This function runs once at the beginning of the program, after most of the system + * initialisation has begun but before audio rendering starts. Use it to prepare any + * memory or resources that will be needed in render(). + * + * \param context Data structure holding information on sample rates, numbers of channels, + * frame sizes and other state. Note: the buffers for audio, analog and digital data will + * \b not yet be available to use. Do not attempt to read or write audio or sensor data + * in setup(). + * \param userData An opaque pointer to an optional user-defined data structure. Whatever + * is passed as the second argument to Bela_initAudio() will appear here. + * + * \return true on success, or false if an error occurred. If no initialisation is + * required, setup() should return true. + */ +bool setup(BelaContext *context, void *userData); + +/** + * \brief User-defined callback function to process audio and sensor data. + * + * This function is called regularly by the system every time there is a new block of + * audio and/or sensor data to process. Your code should process the requested samples + * of data, store the results within \c context, and return. + * + * \param context Data structure holding buffers for audio, analog and digital data. The + * structure also holds information on numbers of channels, frame sizes and sample rates, + * which are guaranteed to remain the same throughout the program and to match what was + * passed to setup(). + * \param userData An opaque pointer to an optional user-defined data structure. Will + * be the same as the \c userData parameter passed to setup(). + */ +void render(BelaContext *context, void *userData); + +/** + * \brief User-defined cleanup function which runs when the program finishes. + * + * This function is called by the system once after audio rendering has finished, before the + * program quits. Use it to release any memory allocated in setup() and to perform + * any other required cleanup. If no initialisation is performed in setup(), then + * this function will usually be empty. + * + * \param context Data structure holding information on sample rates, numbers of channels, + * frame sizes and other state. Note: the buffers for audio, analog and digital data will + * no longer be available to use. Do not attempt to read or write audio or sensor data + * in cleanup(). + * \param userData An opaque pointer to an optional user-defined data structure. Will + * be the same as the \c userData parameter passed to setup() and render(). + */ +void cleanup(BelaContext *context, void *userData); + +/** @} */ + +/** + * \defgroup control Control and command line functions + * + * These functions are used to initialise the Bela settings, process arguments + * from the command line, and start/stop the audio and sensor system. + * + * @{ + */ + +// *** Command-line settings *** + +/** + * \brief Initialise the data structure containing settings for Bela. + * + * This function should be called in main() before parsing any command-line arguments. It + * sets default values in the data structure which specifies the Bela settings, including + * frame sizes, numbers of channels, volume levels and other parameters. + * + * \param settings Structure holding initialisation data for Bela. + */ +void Bela_defaultSettings(BelaInitSettings *settings); + +/** + * \brief Get long options from command line argument list, including Bela standard options + * + * This function should be used in main() to process command line options, in place of the + * standard library getopt_long(). Internally, it parses standard Bela command-line options, + * storing the results in the settings data structure. Any options which are not part of the + * Bela standard options will be returned, as they would normally be in getopt_long(). + * + * \param argc Number of command line options, as passed to main(). + * \param argv Array of command line options, as passed to main(). + * \param customShortOptions List of short options to be parsed, analogous to getopt_long(). This + * list should not include any characters already parsed as part of the Bela standard options. + * \param customLongOptions List of long options to parsed, analogous to getopt_long(). This + * list should not include any long options already parsed as part of the Bela standard options. + * \param settings Data structure holding initialisation settings for Bela. Any standard options + * parsed will automatically update this data structure. + * + * \return Value of the next option parsed which is not a Bela standard option, or -1 when the + * argument list has been exhausted. Similar to the return value of getopt_long() except that Bela + * standard options are handled internally and not returned. + */ +int Bela_getopt_long(int argc, char *argv[], const char *customShortOptions, + const struct option *customLongOptions, BelaInitSettings *settings); + +/** + * \brief Print usage information for Bela standard options. + * + * This function should be called from your code wherever you wish to print usage information for the + * user. It will print usage information on Bela standard options, after which you can print usage + * information for your own custom options. + */ +void Bela_usage(); + +/** + * \brief Set level of verbose (debugging) printing. + * + * \param level Verbosity level of the internal Bela system. 0 by default; higher values will + * print more information. Presently all positive numbers produce the same level of printing. + */ +void Bela_setVerboseLevel(int level); + + +// *** Audio control functions *** + +/** + * \brief Initialise audio and sensor rendering environment. + * + * This function prepares audio rendering in Bela. It should be called from main() sometime + * after command line option parsing has finished. It will initialise the rendering system, which + * in the process will result in a call to the user-defined setup() function. + * + * \param settings Data structure holding system settings, including numbers of channels, frame sizes, + * volume levels and other information. + * \param userData An opaque pointer to a user-defined data structure which will be passed to + * setup(), render() and cleanup(). You can use this to pass custom information + * to the rendering functions, as an alternative to using global variables. + * + * \return 0 on success, or nonzero if an error occurred. + */ +int Bela_initAudio(BelaInitSettings *settings, void *userData); + +/** + * \brief Begin processing audio and sensor data. + * + * This function will start the Bela audio/sensor system. After this function is called, the + * system will make periodic calls to render() until Bela_stopAudio() is called. + * + * \return 0 on success, or nonzero if an error occurred. + */ +int Bela_startAudio(); + +/** + * \brief Stop processing audio and sensor data. + * + * This function will stop the Bela audio/sensor system. After this function returns, no further + * calls to render() will be issued. + */ +int Bela_startAuxiliaryTask(AuxiliaryTask it); +void Bela_stopAudio(); + +/** + * \brief Clean up resources from audio and sensor processing. + * + * This function should only be called after Bela_stopAudio(). It will release any + * internal resources for audio and sensor processing. In the process, it will call the + * user-defined cleanup() function. + */ +void Bela_cleanupAudio(); + +/** @} */ + +/** + * \defgroup levels Audio level controls + * + * These functions control the input and output levels for the audio codec. If a Bela program + * does not call these functions, sensible default levels will be used. + * + * @{ + */ + +// *** Volume and level controls *** + +/** + * \brief Set the level of the audio DAC. + * + * This function sets the level of all audio outputs (headphone, line, speaker). It does + * not affect the level of the (non-audio) analog outputs. + * + * \b Important: do not call this function from within render(), as it does not make + * any guarantees on real-time performance. + * + * \param decibels Level of the DAC output. Valid levels range from -63.5 (lowest) to + * 0 (highest) in steps of 0.5dB. Levels between increments of 0.5 will be rounded down. + * + * \return 0 on success, or nonzero if an error occurred. + */ +int Bela_setDACLevel(float decibels); + +/** + * \brief Set the level of the audio ADC. + * + * This function sets the level of the audio input. It does not affect the level of the + * (non-audio) analog inputs. + * + * \b Important: do not call this function from within render(), as it does not make + * any guarantees on real-time performance. + * + * \param decibels Level of the ADC input. Valid levels range from -12 (lowest) to + * 0 (highest) in steps of 1.5dB. Levels between increments of 1.5 will be rounded down. + * + * \return 0 on success, or nonzero if an error occurred. + */ +int Bela_setADCLevel(float decibels); + + +/** + * \brief Set the gain of the audio preamplifier. + * + * This function sets the level of the Programmable Gain Amplifier(PGA), which + * amplifies the signal before the ADC. + * + * \b Important: do not call this function from within render(), as it does not make + * any guarantees on real-time performance. + * + * \param decibels Level of the PGA Valid levels range from 0 (lowest) to + * 59.5 (highest) in steps of 0.5dB. Levels between increments of 0.5 will be rounded. + * \param channel Specifies which channel to apply the gain to. Channel 0 is left, + * channel 1 is right + * + * \return 0 on success, or nonzero if an error occurred. + */ +int Bela_setPgaGain(float decibels, int channel); + +/** + * \brief Set the level of the onboard headphone amplifier. + * + * This function sets the level of the headphone output only (3-pin connector on the Bela + * cape or the output jack on the BeagleBone Audio Cape). It does not affect the level of the + * speakers or the line out pads on the cape. + * + * \b Important: do not call this function from within render(), as it does not make + * any guarantees on real-time performance. + * + * \param decibels Level of the DAC output. Valid levels range from -63.5 (lowest) to + * 0 (highest) in steps of 0.5dB. Levels between increments of 0.5 will be rounded down. + * + * \return 0 on success, or nonzero if an error occurred. + */ +int Bela_setHeadphoneLevel(float decibels); + +/** + * \brief Mute or unmute the onboard speaker amplifiers. + * + * This function mutes or unmutes the amplifiers on the Bela cape. Whether the speakers begin + * muted or unmuted depends on the BelaInitSettings structure passed to Bela_initAudio(). + * + * \b Important: do not call this function from within render(), as it does not make + * any guarantees on real-time performance. + * + * \param mute 0 to enable the speakers, nonzero to mute the speakers. + * + * \return 0 on success, or nonzero if an error occurred. + */ +int Bela_muteSpeakers(int mute); + +/** @} */ + +/** + * \defgroup auxtask Auxiliary task support + * + * These functions are used to create separate real-time tasks (threads) which run at lower + * priority than the audio processing. They can be used, for example, for large time-consuming + * calculations which would take more than one audio frame length to process, or they could be + * used to communicate with external hardware when that communication might block or be delayed. + * + * All auxiliary tasks used by the program should be created in setup(). The tasks + * can then be scheduled at will within the render() function. + * + * @{ + */ + +// *** Functions for creating auxiliary tasks *** + +/** + * \brief Create a new auxiliary task. + * + * This function creates a new auxiliary task which, when scheduled, runs the function specified + * in the first argument. Note that the task does not run until scheduleAuxiliaryTask() is called. + * Auxiliary tasks should be created in setup() and never in render() itself. + * + * The second argument specifies the real-time priority. Valid values are between 0 + * and 99, and usually should be lower than \ref BEAGLERT_AUDIO_PRIORITY. Tasks with higher priority always + * preempt tasks with lower priority. + * + * \param functionToCall Function which will run each time the auxiliary task is scheduled. + * \param priority Xenomai priority level at which the task should run. + * \param name Name for this task, which should be unique system-wide (no other running program should use this name). + */ +AuxiliaryTask Bela_createAuxiliaryTask(void (*functionToCall)(void*), int priority, const char *name, void* args, bool autoSchedule = false); +AuxiliaryTask Bela_createAuxiliaryTask(void (*functionToCall)(void), int priority, const char *name, bool autoSchedule = false); + +/** + * \brief Start an auxiliary task so that it can be run. + * + * This function will start an auxiliary task but will NOT schedule it. + * It will also set a flag in the associate InternalAuxiliaryTask to flag the + * task as "started", so that successive calls to the same function for a given AuxiliaryTask + * have no effect. + * The user should never be required to call this function directly, as it is called + * by Bela_scheduleAuxiliaryTask if needed (e.g.: if a task is scheduled in setup() ) + * or immediately after starting the audio thread. + * +* \param task Task to start. + */ + +int Bela_startAuxiliaryTask(AuxiliaryTask task); +/** + * \brief Run an auxiliary task which has previously been created. + * + * This function will schedule an auxiliary task to run. When the task runs, the function in the first + * argument of createAuxiliaryTaskLoop() will be called. + * + * scheduleAuxiliaryTask() is typically called from render() to start a lower-priority task. The function + * will not run immediately, but only once any active higher priority tasks have finished. + * + * \param task Task to schedule for running. + */ +void Bela_scheduleAuxiliaryTask(AuxiliaryTask task); +void Bela_autoScheduleAuxiliaryTasks(); + +/** @} */ +#include <Utilities.h> + +#endif /* BEAGLERT_H_ */