Mercurial > hg > beaglert
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 } |