Mercurial > hg > beaglert
view examples/11-Extras/gpioAnalogLoopbackTest/render.cpp @ 464:8fcfbfb32aa0 prerelease
Examples reorder with subdirectories. Added header to each project. Moved Doxygen to bottom of render.cpp.
author | Robert Jack <robert.h.jack@gmail.com> |
---|---|
date | Mon, 20 Jun 2016 16:20:38 +0100 |
parents | |
children | 8f8809c77dda |
line wrap: on
line source
#include <Bela.h> #include <cmath> #include <rtdk.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> #include <stats.hpp> // setup() is called once before the audio rendering starts. // Use it to perform any initialisation and allocation which is dependent // on the period size or sample rate. // // userData holds an opaque pointer to a data structure that was passed // in from the call to initAudio(). // // Return true on success; returning false halts the program. // digital inputs can be changed at will (as they are all being processed at the same time) // analog channels must be as per below int gAnalogOutCh = 1; int gDigitalOutCh = 2; int gDigitalInACh = 0; int gDigitalInDCh = 3; int gAnalogOutLoopDelay; int gDigitalOutLoopDelay; bool setup(BelaContext *context, void *userData) { rt_printf("For this test you need the following connections:\n" "analog%d out->digital%d in, analog%d out->analog%d in, " "digital%d out -> digital%d in, digital%d out-> analog%d in\n", gAnalogOutCh, gDigitalInACh, gAnalogOutCh, 0, gDigitalOutCh, gDigitalInDCh, gDigitalOutCh, 0); rt_printf("Running test with %d analog channels and a buffer size of %d\n", context->analogChannels, context->audioFrames); for(unsigned int n = 0; n < context->digitalFrames; n++){ pinMode(context, n, gDigitalInACh, INPUT); pinMode(context, n, gDigitalInDCh, INPUT); pinMode(context, n, gDigitalOutCh, OUTPUT); } switch (context->analogChannels){ case 2: gAnalogOutLoopDelay = context->audioFrames*2 + 3; gDigitalOutLoopDelay = context->audioFrames*2 + 2; break; case 4: gAnalogOutLoopDelay = context->audioFrames*2 + 3; gDigitalOutLoopDelay = context->audioFrames*2 + 2; break; case 8: gAnalogOutLoopDelay = context->audioFrames + 3; gDigitalOutLoopDelay = context->audioFrames + 1; break; default: exit(2); } return true; } // render() is called regularly at the highest priority by the audio engine. // Input and output are given from the audio hardware and the other // ADCs and DACs (if available). If only audio is available, numAnalogFrames // will be 0. const int patternLength = 31; static int anaErrorCount = 0; static int digErrorCount = 0; void render(BelaContext *context, void *userData) { static bool writePattern[patternLength] = { 0,1,0,1,0,0,1,1, 0,0,0,1,1,1,0,0, 1,1,1,1,0,0,0,0, 1,1,1,1,1,0,0}; // for(int n = 0; n < patternLength; n++){ // writePattern[n]=1; // } static int inPointer = 0; static int outPointer = 0; static int digitalOutPointer = 0; static int digitalInPointer = 0; static int analogOut = 1; /** Checking offset between analog and digital * how it should be : * The PRU loop does the following (the loop runs at 88.2kHz): * - Read/write audio sample (once for the left channel, once for the right channel) * - Write DAC 0 or 0/2 or 0/2/4/6 * - Read ADC 0 or 0/2 or 0/2/4/6, 2 samples (@176.4) older than NOW * - /During/ the line above, every two loops we also Read/Write GPIO, * therefore reading on ADC 0/2/4/6 a value that is being output from GPIO will lead to undefined results * - Write DAC 1 or 1/3 or 1/3/5/7 * - Read ADC 1 or 1/3 or 1/3/5/7, 2 samples (@176.4) older than NOW */ if(1) for(unsigned int n = 0; n < context->audioFrames; n++){ static bool analog0In = false; static bool digitalAIn = false; static int count = 0; bool doReadWrite = context->analogChannels<=4 ? true : ((context->analogChannels == 8) && (n&1)==0); if(doReadWrite){ digitalAIn = digitalRead(context, n, gDigitalInACh); switch(context->analogChannels){ case 8: analog0In = analogRead(context, n/2, 0) > 0.5; analogWrite(context, n/2, analogOut, writePattern[outPointer]); break; case 4: analog0In = analogRead(context, n, 0) > 0.5; analogWrite(context, n, analogOut, writePattern[outPointer]); break; case 2: analog0In = analogRead(context, n * 2 + 1, 0) > 0.5; analogWrite(context, 2 * n, analogOut, writePattern[outPointer]); analogWrite(context, 2 * n + 1, analogOut, writePattern[outPointer]); break; } gAnalogOutLoopDelay--; outPointer++; if(gAnalogOutLoopDelay <= 0){ if(++inPointer == patternLength){ inPointer = 0; } } } bool expectedIn = writePattern[inPointer]; if(gAnalogOutLoopDelay <= 0 && doReadWrite == true){ if(analog0In != expectedIn || digitalAIn != expectedIn){ rt_printf("expected: %d, received: %d %d, pointer: %d, delay: %d, count: %d\n", expectedIn, analog0In, digitalAIn, inPointer, gAnalogOutLoopDelay, count); anaErrorCount++; } } count++; if(analog0In != digitalAIn){ // at any time the analog and digital in should be the same rt_printf("ana %d_%d %d,\n", analog0In, digitalAIn, n); } if(outPointer == patternLength){ outPointer = 0; } } if(1) for(unsigned int n = 0; n < context->audioFrames; n++){ static int count = 0; static bool analog1In = false; static bool digitalDIn = false; /* we need to remember the pastAnalog1In because * reading GPIO takes place before writing to it, therefore * when reading a GPIOout, the GPIOin samples will always be one sample late */ bool doReadWrite = false; static bool pastAnalog1In = false; digitalWriteOnce(context, n, gDigitalOutCh, writePattern[digitalOutPointer]); if(context->analogChannels == 8){ if((n&1) == 0){ //do it every other sample pastAnalog1In = analogRead(context, n/2, 1) > 0.5; digitalDIn = digitalRead(context, n, gDigitalInDCh); doReadWrite = true; } } if(context->analogChannels == 4){ pastAnalog1In = analogRead(context, n, 1) > 0.5; digitalDIn = digitalRead(context, n, gDigitalInDCh); digitalWriteOnce(context, n, gDigitalOutCh, writePattern[digitalOutPointer]); doReadWrite = true; } if(context->analogChannels == 2){ pastAnalog1In = analogRead(context, n * 2, 1) > 0.5; digitalDIn = digitalRead(context, n, gDigitalInDCh); digitalWriteOnce(context, n, gDigitalOutCh, writePattern[digitalOutPointer]); doReadWrite = true; } bool expectedDigitalIn = writePattern[digitalInPointer]; if(doReadWrite == true){ gDigitalOutLoopDelay--; if(gDigitalOutLoopDelay <= 0){ if(expectedDigitalIn != pastAnalog1In || expectedDigitalIn != digitalDIn){ rt_printf("D expected: %d, received: %d %d, pointer: %d, delay: %d, count: %d\n", expectedDigitalIn, pastAnalog1In, digitalDIn, inPointer, gDigitalOutLoopDelay, count); digErrorCount++; } if(++digitalInPointer == patternLength){ digitalInPointer = 0; } } pastAnalog1In = analog1In; if(++digitalOutPointer == patternLength){ digitalOutPointer = 0; } } count++; } if(context->audioFramesElapsed > 30000){ gShouldStop = true; } } void cleanup(BelaContext *context, void *userData) { if(anaErrorCount == 0 && digErrorCount == 0){ rt_printf("Test was succesful with %d analog channels and a buffer size of %d\n", context->analogChannels, context->audioFrames); } else { rt_printf("------------------------\n%danalog %ddigital errors over %dsamples while running test with ", anaErrorCount, digErrorCount, context->audioFramesElapsed); rt_printf("%d analog channels and a buffer size of %d \n\n\n", context->analogChannels, context->audioFrames); exit(1); } }