As part of our development efforts, we depend on a clear understanding of the timing issues associated with the BELA computation and functionalities.
The development process calls for some of the signals and computation derivatives to be output to external files, using the libraries and functions built-in to the BELA program.
Inconsistencies were discovered in the data that was registered in these files. These test procedures were designed to ascertain whether there are, in fact, anomalies in the data accumulated in these log files.
The test was carried out using a BELA unit running dedicated programs to carry the tests out and an external oscilloscope that measured the realtime signals output from the BELA. The internal BELA scope (BELA-scope) and the file logging features of the BELA were also used.
The test program created a repetitive series of equal steps, rising from a minimal to a maximal value. 10 such steps per cycle were implemented, creating a “staircase” as shown in the attached diagrams below.
The anomalous results are evident in the following log output:
Sample Time Increment Value Analog Out
0.000000 0.000000 1.000000 -0.600000 0.097000
1.000000 0.000068 2.000000 -0.400000 0.194000
2.000000 0.000091 3.000000 -0.200000 0.291000
3.000000 0.000159 4.000000 0.000000 0.388000
4.000000 0.000181 5.000000 0.200000 0.485000
5.000000 0.000249 6.000000 0.400000 0.582000
6.000000 0.000272 7.000000 0.600000 0.679000
7.000000 0.000340 8.000000 0.800000 0.776000
8.000000 0.000363 9.000000 1.000000 0.873000
9.000000 0.000431 0.000000 -0.800000 0.970000
10.000000 0.000454 1.000000 -0.600000 0.097000
11.000000 0.000522 2.000000 -0.400000 0.194000
12.000000 0.000544 3.000000 -0.200000 0.291000
Each row represents an output of a discrete level in the cyclic staircase.
The Time column should have shown a linear and constant 23 uSec. time difference, but the time increments logged are alternatively 23 and 68 uSec. The issue is demonstrated by the following data graphs:
Other data elements are correct, as expected.
I would appreciate help in pinpointing the reason for the irregularities in the logged timing outputs
The program run was as follows:
/*
____ _____ _ _
| __ )| ____| | / \
| _ \| _| | | / _ \
| |_) | |___| |___ / ___ \
|____/|_____|_____/_/ \_\
The platform for ultra-low latency audio and sensor processing
Incremental Steps Example 1 -- Example with Output to Analog channel, measured via external oscilloscope.
A series of 9 steps of equal height are issued from the analog output of the BELA.
The output is also applied to the BELA scope, and 5 cycles are logged onto an external file.
*/
#include <Bela.h>
#include <Scope.h>
#include <cmath>
#include <WriteFile.h>
#include <Gpio.h>
//======================================
// logging moved here!!
extern const bool TURN_ON_SCOPE = true;
//const bool TURN_ON_SCOPE = false;
//extern const bool SAVE_RESULTS = false; //saves data to files
extern const bool SAVE_RESULTS = true; //saves data to files
//int PRINT_RESOLUTION = 10; // Number of gCounter samples between print lines
int PRINT_RESOLUTION = 1; // Number of gCounter samples between print lines
int k=0;
//WriteFile summary;
WriteFile Sin_Gen;
float gLogFileValues[6];
int channel=0; // Set channel # for output
float gDstate=0.0;
float gCounter;
bool gStatus1 = 0;
int cycles = 0;
unsigned int n;
float SPEAKER_AMP = 1.0;
const float INTERVAL_LENGTH = 2.0f; // in seconds
const float gNumberOfSteps = 10;
float out;
float y=0.0;
float gStepAmplitude = 0.2;
float offset = -0.8;
// instantiate the scope
Scope scope;
inline float analogToAudio(float x){
return map(x, 0.0f, 0.837f, -1.0f, 1.0f); // analog values ranges from 0 to 0.837
}
inline float audioToAnalog(float x){
return map(x, -1.0f, 1.0f, 0.0f, 0.97f); // analog output ranges from 0 to 1
}
bool setup(BelaContext *context, void *userData)
{
// tell the scope how many channels and the sample rate
scope.setup(2, context->analogSampleRate);
if(SAVE_RESULTS == true){
Sin_Gen.init("BELA Analog Signals.txt"); //set the file name to write to
Sin_Gen.setHeader("Sample\t\tTime\tIncrement\tValue\tAnalog Out\n"); //set one or more lines to be printed at the beginning of the file
Sin_Gen.setFooter(""); //set one or more lines to be printed at the end of the file
Sin_Gen.setFormat("%lf\t%lf\t%lf\t%lf\t%lf\t\n"); // set the format that you want to use for your output. Please use %f only (with modifiers)
Sin_Gen.setFileType(kText);
Sin_Gen.setEchoInterval(100000000); // only print to the console 1 line every other 10000
gLogFileValues[0] = 0.0f; gLogFileValues[1] = 0.0f; gLogFileValues[2] = 0.0f; gLogFileValues[3] = 0.0f; gLogFileValues[4] = 0.0f; gLogFileValues[5] = 0.0f;
}
gCounter=0.0;
return true;
}
void render(BelaContext *context, void *userData)
{
if(gCounter <= float(INTERVAL_LENGTH*context->analogSampleRate)){ // Operation interval Scan Loop
for (n=0; n<context->analogFrames; n++) // Analog Frame Scan Loop
{
out = gStepAmplitude * y + offset;
y = y + 1.0;
if (y >= gNumberOfSteps)
{
y = 0.0;
cycles++;
}
out = SPEAKER_AMP*audioToAnalog(out);
analogWrite(context, n, channel, out);
if(TURN_ON_SCOPE)
{
scope.log(out);
}
k++;
if (k==PRINT_RESOLUTION) // Print only every k records
{
k = 0;
if (SAVE_RESULTS && (cycles < 5))
{
gLogFileValues[0] = gCounter;
gLogFileValues[1] = ((gCounter*context->analogFrames) + n)/context->analogSampleRate;
gLogFileValues[2] = n;
gLogFileValues[3] = gStepAmplitude * y + offset;
gLogFileValues[4] = out;
Sin_Gen.log(gLogFileValues, 5);
}
}
gCounter++;
} // End of Analog Frame Scan
} // End of Operation interval Scan Loop: if(gCounter <= INTERVAL_LENGTH*context->analogSampleRate)
else // if(gCounter > INTERVAL_LENGTH*context->analogSampleRate) then Operation Scan Interval is over!
{
rt_printf("Time elapsed: %f %f %f %f\n",context->digitalSampleRate,context->analogSampleRate, context->analogFrames, gCounter);
gShouldStop = true;
}
if (gStatus1 == 0)
{
rt_printf("Time elapsed: %f %f %f %f\n",context->digitalSampleRate,context->analogSampleRate, context->analogFrames, gCounter);
gStatus1 = 1;
}
}
void cleanup(BelaContext *context, void *userData)
{
}