annotate examples/11-Extras/gpioAnalogLoopbackTest/render.cpp @ 543:8f8809c77dda prerelease

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