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