annotate examples/gpioAnalogLoopbackTest/render.cpp @ 310:02c4ca0e3718 prerelease

Renamed pinModeFrame -> pinMode
author andrewm
date Fri, 27 May 2016 18:29:20 +0100
parents 1feb9c23ac57
children 493a07f6ec09
rev   line source
giuliomoro@301 1 #include <Bela.h>
giuliomoro@189 2 #include <Utilities.h>
giuliomoro@189 3 #include <cmath>
giuliomoro@189 4 #include <rtdk.h>
giuliomoro@189 5 #include <sys/time.h>
giuliomoro@189 6 #include <sys/types.h>
giuliomoro@189 7 #include <unistd.h>
giuliomoro@189 8 #include <stats.hpp>
giuliomoro@189 9 // setup() is called once before the audio rendering starts.
giuliomoro@189 10 // Use it to perform any initialisation and allocation which is dependent
giuliomoro@189 11 // on the period size or sample rate.
giuliomoro@189 12 //
giuliomoro@189 13 // userData holds an opaque pointer to a data structure that was passed
giuliomoro@189 14 // in from the call to initAudio().
giuliomoro@189 15 //
giuliomoro@189 16 // Return true on success; returning false halts the program.
giuliomoro@189 17
giuliomoro@189 18
giuliomoro@189 19 // digital inputs can be changed at will (as they are all being processed at the same time)
giuliomoro@189 20 // analog channels must be as per below
giuliomoro@189 21 int gAnalogOutCh = 1;
giuliomoro@189 22 int gDigitalOutCh = 2;
giuliomoro@189 23 int gDigitalInACh = 0;
giuliomoro@189 24 int gDigitalInDCh = 3;
giuliomoro@189 25 int gAnalogOutLoopDelay;
giuliomoro@189 26 int gDigitalOutLoopDelay;
giuliomoro@301 27 bool setup(BelaContext *context, void *userData)
giuliomoro@189 28 {
giuliomoro@189 29 rt_printf("For this test you need the following connections:\n"
giuliomoro@189 30 "analog%d out->digital%d in, analog%d out->analog%d in, "
giuliomoro@189 31 "digital%d out -> digital%d in, digital%d out-> analog%d in\n",
giuliomoro@189 32 gAnalogOutCh, gDigitalInACh, gAnalogOutCh, 0, gDigitalOutCh, gDigitalInDCh, gDigitalOutCh, 0);
giuliomoro@189 33 rt_printf("Running test with %d analog channels and a buffer size of %d\n",
giuliomoro@189 34 context->analogChannels, context->audioFrames);
giuliomoro@189 35
giuliomoro@189 36 for(unsigned int n = 0; n < context->digitalFrames; n++){
andrewm@310 37 pinMode(context, n, gDigitalInACh, INPUT);
andrewm@310 38 pinMode(context, n, gDigitalInDCh, INPUT);
andrewm@310 39 pinMode(context, n, gDigitalOutCh, OUTPUT);
giuliomoro@189 40 }
giuliomoro@189 41 switch (context->analogChannels){
giuliomoro@189 42 case 2:
giuliomoro@189 43 gAnalogOutLoopDelay = context->audioFrames*2 + 3;
giuliomoro@189 44 gDigitalOutLoopDelay = context->audioFrames*2 + 2;
giuliomoro@189 45 break;
giuliomoro@189 46 case 4:
giuliomoro@189 47 gAnalogOutLoopDelay = context->audioFrames*2 + 3;
giuliomoro@189 48 gDigitalOutLoopDelay = context->audioFrames*2 + 2;
giuliomoro@189 49 break;
giuliomoro@189 50 case 8:
giuliomoro@189 51 gAnalogOutLoopDelay = context->audioFrames + 3;
giuliomoro@189 52 gDigitalOutLoopDelay = context->audioFrames + 1;
giuliomoro@189 53 break;
giuliomoro@189 54 default:
giuliomoro@189 55 exit(2);
giuliomoro@189 56 }
giuliomoro@189 57
giuliomoro@189 58 return true;
giuliomoro@189 59 }
giuliomoro@189 60
giuliomoro@189 61 // render() is called regularly at the highest priority by the audio engine.
giuliomoro@189 62 // Input and output are given from the audio hardware and the other
giuliomoro@189 63 // ADCs and DACs (if available). If only audio is available, numAnalogFrames
giuliomoro@189 64 // will be 0.
giuliomoro@189 65
giuliomoro@189 66 const int patternLength = 31;
giuliomoro@189 67 static int anaErrorCount = 0;
giuliomoro@189 68 static int digErrorCount = 0;
giuliomoro@301 69 void render(BelaContext *context, void *userData)
giuliomoro@189 70 {
giuliomoro@189 71 static bool writePattern[patternLength] = {
giuliomoro@189 72 0,1,0,1,0,0,1,1,
giuliomoro@189 73 0,0,0,1,1,1,0,0,
giuliomoro@189 74 1,1,1,1,0,0,0,0,
giuliomoro@189 75 1,1,1,1,1,0,0};
giuliomoro@189 76 // for(int n = 0; n < patternLength; n++){
giuliomoro@189 77 // writePattern[n]=1;
giuliomoro@189 78 // }
giuliomoro@189 79 static int inPointer = 0;
giuliomoro@189 80 static int outPointer = 0;
giuliomoro@189 81 static int digitalOutPointer = 0;
giuliomoro@189 82 static int digitalInPointer = 0;
giuliomoro@189 83 static int analogOut = 1;
giuliomoro@189 84 /** Checking offset between analog and digital
giuliomoro@189 85 * how it should be :
giuliomoro@189 86 * The PRU loop does the following (the loop runs at 88.2kHz):
giuliomoro@189 87 * - Read/write audio sample (once for the left channel, once for the right channel)
giuliomoro@189 88 * - Write DAC 0 or 0/2 or 0/2/4/6
giuliomoro@189 89 * - Read ADC 0 or 0/2 or 0/2/4/6, 2 samples (@176.4) older than NOW
giuliomoro@189 90 * - /During/ the line above, every two loops we also Read/Write GPIO,
giuliomoro@189 91 * therefore reading on ADC 0/2/4/6 a value that is being output from GPIO will lead to undefined results
giuliomoro@189 92 * - Write DAC 1 or 1/3 or 1/3/5/7
giuliomoro@189 93 * - Read ADC 1 or 1/3 or 1/3/5/7, 2 samples (@176.4) older than NOW
giuliomoro@189 94 */
giuliomoro@189 95 if(1)
giuliomoro@189 96 for(unsigned int n = 0; n < context->audioFrames; n++){
giuliomoro@189 97 static bool analog0In = false;
giuliomoro@189 98 static bool digitalAIn = false;
giuliomoro@189 99 static int count = 0;
giuliomoro@189 100 bool doReadWrite = context->analogChannels<=4 ? true : ((context->analogChannels == 8) && (n&1)==0);
giuliomoro@189 101 if(doReadWrite){
andrewm@308 102 digitalAIn = digitalRead(context, n, gDigitalInACh);
giuliomoro@189 103 switch(context->analogChannels){
giuliomoro@189 104 case 8:
andrewm@308 105 analog0In = analogRead(context, n/2, 0) > 0.5;
andrewm@308 106 analogWrite(context, n/2, analogOut, writePattern[outPointer]);
giuliomoro@189 107 break;
giuliomoro@189 108 case 4:
andrewm@308 109 analog0In = analogRead(context, n, 0) > 0.5;
andrewm@308 110 analogWrite(context, n, analogOut, writePattern[outPointer]);
giuliomoro@189 111 break;
giuliomoro@189 112 case 2:
andrewm@308 113 analog0In = analogRead(context, n * 2 + 1, 0) > 0.5;
andrewm@308 114 analogWrite(context, 2 * n, analogOut, writePattern[outPointer]);
andrewm@308 115 analogWrite(context, 2 * n + 1, analogOut, writePattern[outPointer]);
giuliomoro@189 116 break;
giuliomoro@189 117 }
giuliomoro@189 118 gAnalogOutLoopDelay--;
giuliomoro@189 119 outPointer++;
giuliomoro@189 120 if(gAnalogOutLoopDelay <= 0){
giuliomoro@189 121 if(++inPointer == patternLength){
giuliomoro@189 122 inPointer = 0;
giuliomoro@189 123 }
giuliomoro@189 124 }
giuliomoro@189 125 }
giuliomoro@189 126 bool expectedIn = writePattern[inPointer];
giuliomoro@189 127 if(gAnalogOutLoopDelay <= 0 && doReadWrite == true){
giuliomoro@189 128 if(analog0In != expectedIn || digitalAIn != expectedIn){
giuliomoro@189 129 rt_printf("expected: %d, received: %d %d, pointer: %d, delay: %d, count: %d\n",
giuliomoro@189 130 expectedIn, analog0In, digitalAIn, inPointer, gAnalogOutLoopDelay, count);
giuliomoro@189 131 anaErrorCount++;
giuliomoro@189 132 }
giuliomoro@189 133 }
giuliomoro@189 134 count++;
giuliomoro@189 135 if(analog0In != digitalAIn){ // at any time the analog and digital in should be the same
giuliomoro@189 136 rt_printf("ana %d_%d %d,\n", analog0In, digitalAIn, n);
giuliomoro@189 137 }
giuliomoro@189 138 if(outPointer == patternLength){
giuliomoro@189 139 outPointer = 0;
giuliomoro@189 140 }
giuliomoro@189 141 }
giuliomoro@189 142 if(1)
giuliomoro@189 143 for(unsigned int n = 0; n < context->audioFrames; n++){
giuliomoro@189 144 static int count = 0;
giuliomoro@189 145 static bool analog1In = false;
giuliomoro@189 146 static bool digitalDIn = false;
giuliomoro@189 147 /* we need to remember the pastAnalog1In because
giuliomoro@189 148 * reading GPIO takes place before writing to it, therefore
giuliomoro@189 149 * when reading a GPIOout, the GPIOin samples will always be one sample late
giuliomoro@189 150 */
giuliomoro@189 151 bool doReadWrite = false;
giuliomoro@189 152 static bool pastAnalog1In = false;
andrewm@308 153 digitalWriteOnce(context, n, gDigitalOutCh, writePattern[digitalOutPointer]);
giuliomoro@189 154 if(context->analogChannels == 8){
giuliomoro@189 155 if((n&1) == 0){ //do it every other sample
andrewm@308 156 pastAnalog1In = analogRead(context, n/2, 1) > 0.5;
andrewm@308 157 digitalDIn = digitalRead(context, n, gDigitalInDCh);
giuliomoro@189 158 doReadWrite = true;
giuliomoro@189 159 }
giuliomoro@189 160 }
giuliomoro@189 161 if(context->analogChannels == 4){
andrewm@308 162 pastAnalog1In = analogRead(context, n, 1) > 0.5;
andrewm@308 163 digitalDIn = digitalRead(context, n, gDigitalInDCh);
andrewm@308 164 digitalWriteOnce(context, n, gDigitalOutCh, writePattern[digitalOutPointer]);
giuliomoro@189 165 doReadWrite = true;
giuliomoro@189 166 }
giuliomoro@189 167 if(context->analogChannels == 2){
andrewm@308 168 pastAnalog1In = analogRead(context, n * 2, 1) > 0.5;
andrewm@308 169 digitalDIn = digitalRead(context, n, gDigitalInDCh);
andrewm@308 170 digitalWriteOnce(context, n, gDigitalOutCh, writePattern[digitalOutPointer]);
giuliomoro@189 171 doReadWrite = true;
giuliomoro@189 172 }
giuliomoro@189 173 bool expectedDigitalIn = writePattern[digitalInPointer];
giuliomoro@189 174 if(doReadWrite == true){
giuliomoro@189 175 gDigitalOutLoopDelay--;
giuliomoro@189 176 if(gDigitalOutLoopDelay <= 0){
giuliomoro@189 177 if(expectedDigitalIn != pastAnalog1In || expectedDigitalIn != digitalDIn){
giuliomoro@189 178 rt_printf("D expected: %d, received: %d %d, pointer: %d, delay: %d, count: %d\n",
giuliomoro@189 179 expectedDigitalIn, pastAnalog1In, digitalDIn, inPointer, gDigitalOutLoopDelay, count);
giuliomoro@189 180 digErrorCount++;
giuliomoro@189 181 }
giuliomoro@189 182 if(++digitalInPointer == patternLength){
giuliomoro@189 183 digitalInPointer = 0;
giuliomoro@189 184 }
giuliomoro@189 185 }
giuliomoro@189 186 pastAnalog1In = analog1In;
giuliomoro@189 187 if(++digitalOutPointer == patternLength){
giuliomoro@189 188 digitalOutPointer = 0;
giuliomoro@189 189 }
giuliomoro@189 190 }
giuliomoro@189 191 count++;
giuliomoro@189 192 }
giuliomoro@189 193 if(context->audioSampleCount > 30000){
giuliomoro@189 194 gShouldStop = true;
giuliomoro@189 195 }
giuliomoro@189 196 }
giuliomoro@189 197
giuliomoro@189 198
giuliomoro@301 199 void cleanup(BelaContext *context, void *userData)
giuliomoro@189 200 {
giuliomoro@189 201 if(anaErrorCount == 0 && digErrorCount == 0){
giuliomoro@189 202 rt_printf("Test was succesful with %d analog channels and a buffer size of %d\n", context->analogChannels, context->audioFrames);
giuliomoro@189 203 } else {
giuliomoro@189 204 rt_printf("------------------------\n%danalog %ddigital errors over %dsamples while running test with ",
giuliomoro@189 205 anaErrorCount, digErrorCount, context->audioSampleCount);
giuliomoro@189 206 rt_printf("%d analog channels and a buffer size of %d \n\n\n",
giuliomoro@189 207 context->analogChannels, context->audioFrames);
giuliomoro@189 208 exit(1);
giuliomoro@189 209 }
giuliomoro@189 210 }