Mercurial > hg > beaglert
comparison projects/cape_test/render.cpp @ 268:8d80eda512cd prerelease
Added new overlay for using PRU0 or PRU1, a script to halt board on button press, and several example projects
author | andrewm |
---|---|
date | Tue, 17 May 2016 14:46:26 +0100 |
parents | 3c3a1357657d |
children |
comparison
equal
deleted
inserted
replaced
267:247a182adb6d | 268:8d80eda512cd |
---|---|
12 #define ANALOG_LOW (2048.0 / 65536.0) | 12 #define ANALOG_LOW (2048.0 / 65536.0) |
13 #define ANALOG_HIGH (50000.0 / 65536.0) | 13 #define ANALOG_HIGH (50000.0 / 65536.0) |
14 | 14 |
15 const int gDACPinOrder[] = {6, 4, 2, 0, 1, 3, 5, 7}; | 15 const int gDACPinOrder[] = {6, 4, 2, 0, 1, 3, 5, 7}; |
16 | 16 |
17 enum { | |
18 kStateTestingAudioLeft = 0, | |
19 kStateTestingAudioRight, | |
20 kStateTestingAudioDone | |
21 }; | |
22 | |
17 uint64_t gLastErrorFrame = 0; | 23 uint64_t gLastErrorFrame = 0; |
18 uint32_t gEnvelopeSampleCount = 0; | 24 uint32_t gEnvelopeSampleCount = 0; |
19 float gEnvelopeValue = 0.5; | 25 float gEnvelopeValueL = 0.5, gEnvelopeValueR = 0.5; |
20 float gEnvelopeDecayRate = 0.9995; | 26 float gEnvelopeDecayRate = 0.9995; |
27 int gEnvelopeLastChannel = 0; | |
28 | |
29 float gPositivePeakLevels[2] = {0, 0}; | |
30 float gNegativePeakLevels[2] = {0, 0}; | |
31 float gPeakLevelDecayRate = 0.999; | |
32 const float gPeakLevelLowThreshold = 0.02; | |
33 const float gPeakLevelHighThreshold = 0.2; | |
34 const float gDCOffsetThreshold = 0.1; | |
35 int gAudioTestState = kStateTestingAudioLeft; | |
36 int gAudioTestStateSampleCount = 0; | |
37 int gAudioTestSuccessCounter = 0; | |
38 const int gAudioTestSuccessCounterThreshold = 64; | |
39 const int gAudioTestStateSampleThreshold = 16384; | |
21 | 40 |
22 // setup() is called once before the audio rendering starts. | 41 // setup() is called once before the audio rendering starts. |
23 // Use it to perform any initialisation and allocation which is dependent | 42 // Use it to perform any initialisation and allocation which is dependent |
24 // on the period size or sample rate. | 43 // on the period size or sample rate. |
25 // | 44 // |
45 static int invertChannel = 0; | 64 static int invertChannel = 0; |
46 float frequency = 0; | 65 float frequency = 0; |
47 | 66 |
48 // Play a sine wave on the audio output | 67 // Play a sine wave on the audio output |
49 for(unsigned int n = 0; n < context->audioFrames; n++) { | 68 for(unsigned int n = 0; n < context->audioFrames; n++) { |
50 context->audioOut[2*n] = context->audioOut[2*n + 1] = gEnvelopeValue * sinf(phase); | 69 |
51 | 70 // Peak detection on the audio inputs, with offset to catch |
52 // If one second has gone by with no error, play one sound, else | 71 // DC errors |
53 // play another | 72 for(int ch = 0; ch < 2; ch++) { |
54 if(context->audioSampleCount + n - gLastErrorFrame > 44100) { | 73 if(context->audioIn[2*n + ch] > gPositivePeakLevels[ch]) |
55 gEnvelopeValue *= gEnvelopeDecayRate; | 74 gPositivePeakLevels[ch] = context->audioIn[2*n + ch]; |
56 gEnvelopeSampleCount++; | 75 gPositivePeakLevels[ch] += 0.1; |
57 if(gEnvelopeSampleCount > 22050) { | 76 gPositivePeakLevels[ch] *= gPeakLevelDecayRate; |
58 gEnvelopeValue = 0.5; | 77 gPositivePeakLevels[ch] -= 0.1; |
59 gEnvelopeSampleCount = 0; | 78 if(context->audioIn[2*n + ch] < gNegativePeakLevels[ch]) |
60 } | 79 gNegativePeakLevels[ch] = context->audioIn[2*n + ch]; |
61 frequency = 880.0; | 80 gNegativePeakLevels[ch] -= 0.1; |
81 gNegativePeakLevels[ch] *= gPeakLevelDecayRate; | |
82 gNegativePeakLevels[ch] += 0.1; | |
83 } | |
84 | |
85 if(gAudioTestState == kStateTestingAudioLeft) { | |
86 context->audioOut[2*n] = 0.2 * sinf(phase); | |
87 context->audioOut[2*n + 1] = 0; | |
88 | |
89 frequency = 3000.0; | |
90 phase += 2.0 * M_PI * frequency / 44100.0; | |
91 if(phase >= 2.0 * M_PI) | |
92 phase -= 2.0 * M_PI; | |
93 | |
94 gAudioTestStateSampleCount++; | |
95 if(gAudioTestStateSampleCount >= gAudioTestStateSampleThreshold) { | |
96 // Check if we have the expected input: signal on the left but not | |
97 // on the right. Also check that there is not too much DC offset on the | |
98 // inactive signal | |
99 if((gPositivePeakLevels[0] - gNegativePeakLevels[0]) >= gPeakLevelHighThreshold | |
100 && (gPositivePeakLevels[1] - gNegativePeakLevels[1]) <= gPeakLevelLowThreshold && | |
101 fabsf(gPositivePeakLevels[1]) < gDCOffsetThreshold && | |
102 fabsf(gNegativePeakLevels[1]) < gDCOffsetThreshold) { | |
103 // Successful test: increment counter | |
104 gAudioTestSuccessCounter++; | |
105 if(gAudioTestSuccessCounter >= gAudioTestSuccessCounterThreshold) { | |
106 gAudioTestState = kStateTestingAudioRight; | |
107 gAudioTestStateSampleCount = 0; | |
108 gAudioTestSuccessCounter = 0; | |
109 } | |
110 | |
111 } | |
112 else { | |
113 if(!((context->audioSampleCount + n) % 22050)) { | |
114 // Debugging print messages | |
115 if((gPositivePeakLevels[0] - gNegativePeakLevels[0]) < gPeakLevelHighThreshold) | |
116 rt_printf("Left Audio In FAIL: insufficient signal: %f\n", | |
117 gPositivePeakLevels[0] - gNegativePeakLevels[0]); | |
118 else if(gPositivePeakLevels[1] - gNegativePeakLevels[1] > gPeakLevelLowThreshold) | |
119 rt_printf("Right Audio In FAIL: signal present when it should not be: %f\n", | |
120 gPositivePeakLevels[1] - gNegativePeakLevels[1]); | |
121 else if(fabsf(gPositivePeakLevels[1]) >= gDCOffsetThreshold || | |
122 fabsf(gNegativePeakLevels[1]) >= gDCOffsetThreshold) | |
123 rt_printf("Right Audio In FAIL: DC offset: (%f, %f)\n", | |
124 gPositivePeakLevels[1], gNegativePeakLevels[1]); | |
125 } | |
126 gAudioTestSuccessCounter--; | |
127 if(gAudioTestSuccessCounter <= 0) | |
128 gAudioTestSuccessCounter = 0; | |
129 } | |
130 } | |
131 } | |
132 else if(gAudioTestState == kStateTestingAudioRight) { | |
133 context->audioOut[2*n] = 0; | |
134 context->audioOut[2*n + 1] = 0.2 * sinf(phase); | |
135 | |
136 frequency = 3000.0; | |
137 phase += 2.0 * M_PI * frequency / 44100.0; | |
138 if(phase >= 2.0 * M_PI) | |
139 phase -= 2.0 * M_PI; | |
140 | |
141 gAudioTestStateSampleCount++; | |
142 if(gAudioTestStateSampleCount >= gAudioTestStateSampleThreshold) { | |
143 // Check if we have the expected input: signal on the left but not | |
144 // on the right | |
145 if((gPositivePeakLevels[1] - gNegativePeakLevels[1]) >= gPeakLevelHighThreshold | |
146 && (gPositivePeakLevels[0] - gNegativePeakLevels[0]) <= gPeakLevelLowThreshold && | |
147 fabsf(gPositivePeakLevels[0]) < gDCOffsetThreshold && | |
148 fabsf(gNegativePeakLevels[0]) < gDCOffsetThreshold) { | |
149 // Successful test: increment counter | |
150 gAudioTestSuccessCounter++; | |
151 if(gAudioTestSuccessCounter >= gAudioTestSuccessCounterThreshold) { | |
152 gAudioTestSuccessCounter = 0; | |
153 gAudioTestStateSampleCount = 0; | |
154 gAudioTestState = kStateTestingAudioDone; | |
155 } | |
156 } | |
157 else { | |
158 if(!((context->audioSampleCount + n) % 22050)) { | |
159 // Debugging print messages | |
160 if((gPositivePeakLevels[1] - gNegativePeakLevels[1]) < gPeakLevelHighThreshold) | |
161 rt_printf("Right Audio In FAIL: insufficient signal: %f\n", | |
162 gPositivePeakLevels[1] - gNegativePeakLevels[1]); | |
163 else if(gPositivePeakLevels[0] - gNegativePeakLevels[0] > gPeakLevelLowThreshold) | |
164 rt_printf("Left Audio In FAIL: signal present when it should not be: %f\n", | |
165 gPositivePeakLevels[0] - gNegativePeakLevels[0]); | |
166 else if(fabsf(gPositivePeakLevels[0]) >= gDCOffsetThreshold || | |
167 fabsf(gNegativePeakLevels[0]) >= gDCOffsetThreshold) | |
168 rt_printf("Left Audio In FAIL: DC offset: (%f, %f)\n", | |
169 gPositivePeakLevels[0], gNegativePeakLevels[0]); | |
170 } | |
171 gAudioTestSuccessCounter--; | |
172 if(gAudioTestSuccessCounter <= 0) | |
173 gAudioTestSuccessCounter = 0; | |
174 } | |
175 } | |
62 } | 176 } |
63 else { | 177 else { |
64 gEnvelopeValue = 0.5; | 178 // Audio input testing finished. Play tones depending on status of |
65 frequency = 220.0; | 179 // analog testing |
66 } | 180 context->audioOut[2*n] = gEnvelopeValueL * sinf(phase); |
67 | 181 context->audioOut[2*n + 1] = gEnvelopeValueR * sinf(phase); |
68 phase += 2.0 * M_PI * frequency / 44100.0; | 182 |
69 if(phase >= 2.0 * M_PI) | 183 // If one second has gone by with no error, play one sound, else |
70 phase -= 2.0 * M_PI; | 184 // play another |
185 if(context->audioSampleCount + n - gLastErrorFrame > 44100) { | |
186 gEnvelopeValueL *= gEnvelopeDecayRate; | |
187 gEnvelopeValueR *= gEnvelopeDecayRate; | |
188 gEnvelopeSampleCount++; | |
189 if(gEnvelopeSampleCount > 22050) { | |
190 if(gEnvelopeLastChannel == 0) | |
191 gEnvelopeValueR = 0.5; | |
192 else | |
193 gEnvelopeValueL = 0.5; | |
194 gEnvelopeLastChannel = !gEnvelopeLastChannel; | |
195 gEnvelopeSampleCount = 0; | |
196 } | |
197 frequency = 880.0; | |
198 } | |
199 else { | |
200 gEnvelopeValueL = gEnvelopeValueR = 0.5; | |
201 gEnvelopeLastChannel = 0; | |
202 frequency = 220.0; | |
203 } | |
204 | |
205 phase += 2.0 * M_PI * frequency / 44100.0; | |
206 if(phase >= 2.0 * M_PI) | |
207 phase -= 2.0 * M_PI; | |
208 } | |
71 } | 209 } |
72 | 210 |
73 for(unsigned int n = 0; n < context->analogFrames; n++) { | 211 for(unsigned int n = 0; n < context->analogFrames; n++) { |
74 // Change outputs every 512 samples | 212 // Change outputs every 512 samples |
75 if(sampleCounter < 512) { | 213 if(sampleCounter < 512) { |