Timing and IO in Bela » History » Version 1
Version 1/5
-
Next » -
Current version
Andrew McPherson, 2015-07-18 02:23 AM
Timing and I/O in BeagleRT¶
All I/O in BeagleRT -- audio, analog and digital -- is synchronised to the same master clock. This means that audio and sensor data is always strongly aligned with no latency or jitter. It also means that programming conventions for handling I/O are somewhat different from other platforms.
Functions in a BeagleRT project¶
Every BeagleRT project must declare three functions: setup()
, render()
and cleanup()
.
setup(BeagleRTContext *context, void *userData)
runs once at the beginning of the program, before any audio or sensor processing has taken place. It is analogous to the setup()
function in the Arduino environment. Your code here should allocate any needed memory and initialise program state.
render(BeagleRTContext *context, void *userData)
runs regularly, in a loop as long as the program is running. It is called by the BeagleRT system. Your code within render()
should process one buffer worth of audio, analog and digital data, using the information stored in the context
data structure. For further information, see Tutorial Sketches - Explanations .
cleanup(BeagleRTContext *context, void *userData)
runs once at the end of the program, after audio and sensor processing has finished. Use it to clean up resources allocated in setup()
.
Working with I/O¶
All audio processing, as well as all analog and digital I/O, should be handled from render()
. Every call to render()
represents a small slice of time:
(image to go here)
On BeagleRT, analog and digital I/Os are sampled at a constant rate, regardless of whether you use the samples or not. All I/O is held within the context
data structure. For example, if the buffer size is 8 audio samples, then the structure will contain:
context->audioIn
is an array of 8 frames * 2 channels = 16 audio input samples. These samples were read by the hardware beforerender()
began.context->audioOut
is an array of 8 frames * 2 channels = 16 audio output samples which your program should write. They will be sent to the hardware afterrender()
has finished.context->analogIn
is an array of 4 frames * 8 channels = 32 analog input samples. (4 frames because analog I/O runs at half the sample rate of audio I/O.) These samples were read by the hardware beforerender()
began.context->analogOut
is an array of 4 frames * 8 channels = 32 analog output samples which your program should write.
This is a contrast to Arduino and similar environments. For example, calling analogRead()
on Arduino would cause the analog pin to be read at the moment the function runs. The rest of the code will stop until the analog to digital conversion has finished and analogRead()
returns. On BeagleRT, the analog input data is already present in the buffer. Calling analogReadFrame()
will retrieve the sample from the buffer. Your code does not need to wait for the conversion to happen.
Understanding the "frame" argument¶
All the I/O functions in BeagleRT (digitalReadFrame()
, analogWriteFrame()
, etc.) take an argument for which frame to read or write the I/O pin. The frame indicates exactly what time the read/write should take place. The number of frames in any given call to render()
depends on the BeagleRT buffer size (which can be changed with the - p
command line argument). By default, the buffer size is 8 analog frames or 16 audio frames. Valid frame numbers will range from 0 to (context->analogFrames - 1)
for analog, (context->digitalFrames - 1)
for digital and (context->audioFrames - 1)
for audio.
Remember when calling analogWriteFrame()
or digitalWriteFrame()
that the value will not be updated immediately upon returning from the function. Instead, the output will be buffered and will change when the designated frame arrives.
I/O Functions¶
BeagleRT provides a number of I/O functions. Your files should contain #include <Utilities.h>
in order to use these functions. See the code docs for detailed usage: https://code.soundsoftware.ac.uk/projects/beaglert/embedded/Utilities_8h.html
digitalReadFrame
-- read a digital pindigitalWriteFrame
-- write a digital pin, and hold the value going forwarddigitalWriteFrameOnce
-- write a digital pin for one frame onlypinModeFrame
-- change a digital pin to an input or output and maintain this going forwardpinModeFrameOnce
-- change a digital pin to an input or output for one frame onlyanalogReadFrame
-- read an analog pinanalogWriteFrame
-- write an analog pin, and (depending on system setting) hold the value going forwardanalogWriteFrameOnce
-- write an analog pin for one frame only
Example: int digitalReadFrame(BeagleRTContext *context, int frame, int channel)
¶
This function works like digitalRead()
on Arduino, but it takes two extra arguments. The first argument is the context
data structure which is passed in to render()
. This is needed because context
holds all the references to the I/O buffers. The second argument is the frame (i.e. the time) at which to read the pin. The third argument, channel
, is the pin to read, similar to the Arduino function. The value of the pin (HIGH
or LOW
) is returned.