comparison projects/gpioAnalogLoopbackTest/render.cpp @ 189:7144c5594d16

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