54
54
55
55
#define VCO_GAIN 0.5f
56
56
57
- #define AGC_FILTER_CUTOFF_FREQUENCY 20
57
+ #define USE_AGC true
58
+ #define MANUAL_GAIN_DIVISOR 5000.0f
59
+ #define AGC_MINIMUM_AMPLITUDE 100.0f
60
+ #define AGC_FILTER_CUTOFF_FREQUENCY 1000
61
+
58
62
#define CHANNEL_FILTER_CUTOFF_FREQUENCY 100
59
63
#define CHANNEL_FILTER_BANDWIDTH 2.0f
60
64
#define CARRIER_FILTER_CUTOFF_FREQUENCY 1000
75
79
76
80
#define MIN (a , b ) ((a) < (b) ? (a) : (b))
77
81
82
+ #define MAX (a , b ) ((a) > (b) ? (a) : (b))
83
+
78
84
/* Sine table */
79
85
80
86
static const float sineTable [SINE_TABLE_LENGTH ] = {0.000000000000f , 0.024541229010f , 0.049067676067f , 0.073564566672f , 0.098017141223f , 0.122410677373f , 0.146730467677f , 0.170961901546f , \
@@ -150,7 +156,7 @@ static BQ_filterCoefficients_t channelFilterCoefficients;
150
156
151
157
/* Carrier generation variable */
152
158
153
- float omegaT = 0.0f ;
159
+ static float omegaT = 0.0f ;
154
160
155
161
/* Configuration variables */
156
162
@@ -170,7 +176,7 @@ typedef enum {NONE, HIGH_BIT, LOW_BIT} receivedBit_t;
170
176
171
177
/* CRC functions */
172
178
173
- static uint16_t updateCRC (uint16_t crc_in , int incr ) {
179
+ static inline uint16_t updateCRC (uint16_t crc_in , int incr ) {
174
180
175
181
uint16_t xor = crc_in >> 15 ;
176
182
uint16_t out = crc_in << 1 ;
@@ -187,7 +193,7 @@ static uint16_t updateCRC(uint16_t crc_in, int incr) {
187
193
188
194
}
189
195
190
- static uint16_t calculateCRC (const uint8_t * data , uint32_t size ) {
196
+ static inline uint16_t calculateCRC (const uint8_t * data , uint32_t size ) {
191
197
192
198
uint16_t crc , i ;
193
199
@@ -205,7 +211,7 @@ static uint16_t calculateCRC(const uint8_t *data, uint32_t size) {
205
211
206
212
}
207
213
208
- static bool checkCRC (const uint8_t * data , uint32_t size ) {
214
+ static inline bool checkCRC (const uint8_t * data , uint32_t size ) {
209
215
210
216
uint16_t crc = calculateCRC (data , size - CRC_SIZE_IN_BYTES );
211
217
@@ -218,15 +224,25 @@ static bool checkCRC(const uint8_t *data, uint32_t size) {
218
224
219
225
/* Function to perform Costas loop */
220
226
221
- float updateCostasLoop (float sample ) {
227
+ static inline float updateCostasLoop (float sample ) {
222
228
223
229
/* Apply gain control */
224
230
225
231
float filteredSample = Butterworth_applyBandPassFilter (sample , & carrierFilter , & carrierFilterCoefficients );
226
232
227
- float agcOutput = Butterworth_applyLowPassFilter (filteredSample > 0 ? filteredSample : - filteredSample , & agcFilter , & agcFilterCoefficients );
233
+ if (USE_AGC ) {
234
+
235
+ float regulatedFilteredSample = filteredSample > 0.0f ? filteredSample : - filteredSample ;
236
+
237
+ float agcOutput = Butterworth_applyLowPassFilter (regulatedFilteredSample , & agcFilter , & agcFilterCoefficients );
238
+
239
+ filteredSample /= MAX (agcOutput , AGC_MINIMUM_AMPLITUDE );
228
240
229
- if (agcOutput != 0 ) filteredSample /= agcOutput ;
241
+ } else {
242
+
243
+ filteredSample /= MANUAL_GAIN_DIVISOR ;
244
+
245
+ }
230
246
231
247
/* Demodulate input sound */
232
248
@@ -258,10 +274,10 @@ float updateCostasLoop(float sample) {
258
274
259
275
inline void AudioMoth_handleMicrophoneInterrupt (int16_t sample ) {
260
276
261
- configSample = sample ;
262
-
263
277
configSampleReady = true;
264
278
279
+ configSample = sample ;
280
+
265
281
}
266
282
267
283
/* Functions to handle audio configuration */
@@ -272,28 +288,30 @@ void AudioConfig_enableAudioConfiguration() {
272
288
273
289
AudioMoth_enableMicrophone (CONFIG_GAIN_RANGE , CONFIG_GAIN , CONFIG_CLOCK_DIVIDER , CONFIG_ACQUISITION_CYCLES , CONFIG_OVERSAMPLE_RATE );
274
290
275
- AudioMoth_startMicrophoneSamples (CONFIG_SAMPLE_RATE );
276
-
277
- AudioMoth_initialiseMicrophoneInterupts ();
291
+ AudioMoth_initialiseMicrophoneInterrupts ();
278
292
279
293
/* Design filters */
280
294
281
- Butterworth_designLowPassFilter (& agcFilterCoefficients , CONFIG_SAMPLE_RATE , SPEED_FACTOR * AGC_FILTER_CUTOFF_FREQUENCY );
282
-
283
295
Butterworth_designBandPassFilter (& carrierFilterCoefficients , CONFIG_SAMPLE_RATE , CONFIG_CARRIER_FREQUENCY - CARRIER_FILTER_CUTOFF_FREQUENCY , CONFIG_CARRIER_FREQUENCY + CARRIER_FILTER_CUTOFF_FREQUENCY );
284
296
297
+ if (USE_AGC ) Butterworth_designLowPassFilter (& agcFilterCoefficients , CONFIG_SAMPLE_RATE , SPEED_FACTOR * AGC_FILTER_CUTOFF_FREQUENCY );
298
+
285
299
Biquad_designLowPassFilter (& channelFilterCoefficients , CONFIG_SAMPLE_RATE , SPEED_FACTOR * CHANNEL_FILTER_CUTOFF_FREQUENCY , CHANNEL_FILTER_BANDWIDTH );
286
300
287
301
/* Initialise filters */
288
302
289
- Butterworth_initialise (& agcFilter );
290
-
291
303
Butterworth_initialise (& carrierFilter );
292
304
305
+ if (USE_AGC ) Butterworth_initialise (& agcFilter );
306
+
293
307
Biquad_initialise (& channel1Filter );
294
308
295
309
Biquad_initialise (& channel2Filter );
296
310
311
+ /* Start the microphone samples */
312
+
313
+ AudioMoth_startMicrophoneSamples (CONFIG_SAMPLE_RATE );
314
+
297
315
}
298
316
299
317
void AudioConfig_disableAudioConfiguration () {
@@ -344,7 +362,7 @@ bool AudioConfig_listenForAudioConfigurationTone(uint32_t milliseconds) {
344
362
345
363
/* Check thresholds */
346
364
347
- if ((lastValue > 0 && costasLoopOutput < 0 ) || (lastValue < 0 && costasLoopOutput > 0 )) {
365
+ if ((lastValue >= 0 && costasLoopOutput < 0 ) || (lastValue < 0 && costasLoopOutput >= 0 )) {
348
366
349
367
uint32_t period = counter - lastCrossing ;
350
368
@@ -368,20 +386,16 @@ bool AudioConfig_listenForAudioConfigurationTone(uint32_t milliseconds) {
368
386
369
387
}
370
388
389
+ /* Update counters and status */
390
+
371
391
lastValue = costasLoopOutput ;
372
392
393
+ configSampleReady = false;
394
+
373
395
counter += 1 ;
374
396
375
397
}
376
398
377
- /* Wait for next sample */
378
-
379
- configSampleReady = false;
380
-
381
- /* Sleep until next interrupt occurs */
382
-
383
- AudioMoth_sleep ();
384
-
385
399
}
386
400
387
401
return false;
@@ -434,7 +448,7 @@ bool AudioConfig_listenForAudioConfigurationPackets(bool timeout, uint32_t milli
434
448
435
449
/* Check thresholds */
436
450
437
- if ((lastValue > 0 && costasLoopOutput < 0 ) || (lastValue < 0 && costasLoopOutput > 0 )) {
451
+ if ((lastValue >= 0 && costasLoopOutput < 0 ) || (lastValue < 0 && costasLoopOutput >= 0 )) {
438
452
439
453
uint32_t period = counter - lastCrossing ;
440
454
@@ -606,20 +620,16 @@ bool AudioConfig_listenForAudioConfigurationPackets(bool timeout, uint32_t milli
606
620
607
621
}
608
622
623
+ /* Update counters and status */
624
+
609
625
lastValue = costasLoopOutput ;
610
626
627
+ configSampleReady = false;
628
+
611
629
counter += 1 ;
612
630
613
631
}
614
632
615
- /* Wait for next sample */
616
-
617
- configSampleReady = false;
618
-
619
- /* Sleep until next interrupt occurs */
620
-
621
- AudioMoth_sleep ();
622
-
623
633
}
624
634
625
635
return cancel == false;
0 commit comments