annotate projects/gpioAnalogLoopbackTest/render.cpp @ 269:ac8eb07afcf5

Oxygen text added to each render.cpp file for the default projects. Text includes project explanation from Wiki, edited in places. Empty project added as a default project. Doxyfile updated. Each of the project locations added to INPUT configuration option. Consider just watching the whole project file so all new projects are automatically pulled through.
author Robert Jack <robert.h.jack@gmail.com>
date Tue, 17 May 2016 15:40:16 +0100
parents 7144c5594d16
children
rev   line source
giuliomoro@189 1 #include <BeagleRT.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@189 27 bool setup(BeagleRTContext *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++){
giuliomoro@189 37 pinModeFrame(context, n, gDigitalInACh, INPUT);
giuliomoro@189 38 pinModeFrame(context, n, gDigitalInDCh, INPUT);
giuliomoro@189 39 pinModeFrame(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@189 69 void render(BeagleRTContext *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){
giuliomoro@189 102 digitalAIn = digitalReadFrame(context, n, gDigitalInACh);
giuliomoro@189 103 switch(context->analogChannels){
giuliomoro@189 104 case 8:
giuliomoro@189 105 analog0In = analogReadFrame(context, n/2, 0) > 0.5;
giuliomoro@189 106 analogWriteFrame(context, n/2, analogOut, writePattern[outPointer]);
giuliomoro@189 107 break;
giuliomoro@189 108 case 4:
giuliomoro@189 109 analog0In = analogReadFrame(context, n, 0) > 0.5;
giuliomoro@189 110 analogWriteFrame(context, n, analogOut, writePattern[outPointer]);
giuliomoro@189 111 break;
giuliomoro@189 112 case 2:
giuliomoro@189 113 analog0In = analogReadFrame(context, n * 2 + 1, 0) > 0.5;
giuliomoro@189 114 analogWriteFrame(context, 2 * n, analogOut, writePattern[outPointer]);
giuliomoro@189 115 analogWriteFrame(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;
giuliomoro@189 153 digitalWriteFrameOnce(context, n, gDigitalOutCh, writePattern[digitalOutPointer]);
giuliomoro@189 154 if(context->analogChannels == 8){
giuliomoro@189 155 if((n&1) == 0){ //do it every other sample
giuliomoro@189 156 pastAnalog1In = analogReadFrame(context, n/2, 1) > 0.5;
giuliomoro@189 157 digitalDIn = digitalReadFrame(context, n, gDigitalInDCh);
giuliomoro@189 158 doReadWrite = true;
giuliomoro@189 159 }
giuliomoro@189 160 }
giuliomoro@189 161 if(context->analogChannels == 4){
giuliomoro@189 162 pastAnalog1In = analogReadFrame(context, n, 1) > 0.5;
giuliomoro@189 163 digitalDIn = digitalReadFrame(context, n, gDigitalInDCh);
giuliomoro@189 164 digitalWriteFrameOnce(context, n, gDigitalOutCh, writePattern[digitalOutPointer]);
giuliomoro@189 165 doReadWrite = true;
giuliomoro@189 166 }
giuliomoro@189 167 if(context->analogChannels == 2){
giuliomoro@189 168 pastAnalog1In = analogReadFrame(context, n * 2, 1) > 0.5;
giuliomoro@189 169 digitalDIn = digitalReadFrame(context, n, gDigitalInDCh);
giuliomoro@189 170 digitalWriteFrameOnce(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@189 199 void cleanup(BeagleRTContext *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 }