-
Notifications
You must be signed in to change notification settings - Fork 39
/
Copy pathExample2_ConfigureMic.ino
215 lines (181 loc) · 5.52 KB
/
Example2_ConfigureMic.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/* Author: Nathan Seidle
Created: July 24, 2019
This example shows how to modify the various PDM interface settings.
*/
/*
// This file is subject to the terms and conditions defined in
// file 'LICENSE.md', which is part of this source code package.
*/
//Global variables needed for PDM library
#define pdmDataBufferSize 4096 //Default is array of 4096 * 32bit
uint16_t pdmDataBuffer[pdmDataBufferSize];
//Global variables needed for the FFT in this sketch
float g_fPDMTimeDomain[pdmDataBufferSize * 2];
float g_fPDMFrequencyDomain[pdmDataBufferSize * 2];
float g_fPDMMagnitudes[pdmDataBufferSize * 2];
uint32_t sampleFreq;
//Enable these defines for additional debug printing
#define PRINT_PDM_DATA 0
#define PRINT_FFT_DATA 0
#include <PDM.h> //Include PDM library included with the Aruino_Apollo3 core
AP3_PDM myPDM; //Create instance of PDM class
//Math library needed for FFT
#include <arm_math.h>
void setup()
{
Serial.begin(115200);
Serial.println("SparkFun PDM Example");
// The variant files for Artemis carrier boards have Mic data and clock pins defined
// but these pins can be passed to the the .begin function
if (myPDM.begin() == false) //Use Data, clock defines from variant file
//if (myPDM.begin(22, 23) == false) //Data, clock on Artemis Nano - These are the pin names from variant file, not pad names
{
Serial.println("PDM Init failed. Are you sure these pins are PDM capable?");
while (1)
;
}
Serial.println("PDM Initialized");
//Note: The following settings will modifying the settings from default
//and therefore the loudest freq will be 1/2 of what is really happening
//For more AM_HAL_... defines see the am_hal_pdm.h file in the core (/mcu/apollo3/hal/)
myPDM.setClockSpeed(AM_HAL_PDM_CLK_3MHZ);
myPDM.setClockDivider(AM_HAL_PDM_MCLKDIV_1);
myPDM.setGain(AM_HAL_PDM_GAIN_P210DB);
myPDM.setChannel(AM_HAL_PDM_CHANNEL_STEREO);
//The equivalent getGain(), getClockSpeed(), etc are available
printPDMConfig();
}
void loop()
{
if (myPDM.available())
{
myPDM.getData(pdmDataBuffer, pdmDataBufferSize);
printLoudest();
}
// Go to Deep Sleep until the PDM ISR or other ISR wakes us.
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
}
//*****************************************************************************
//
// Analyze and print frequency data.
//
//*****************************************************************************
void printLoudest(void)
{
float fMaxValue;
uint32_t ui32MaxIndex;
int16_t *pi16PDMData = (int16_t *)pdmDataBuffer;
uint32_t ui32LoudestFrequency;
//
// Convert the PDM samples to floats, and arrange them in the format
// required by the FFT function.
//
for (uint32_t i = 0; i < pdmDataBufferSize; i++)
{
if (PRINT_PDM_DATA)
{
Serial.printf("%d\n", pi16PDMData[i]);
}
g_fPDMTimeDomain[2 * i] = pi16PDMData[i] / 1.0;
g_fPDMTimeDomain[2 * i + 1] = 0.0;
}
if (PRINT_PDM_DATA)
{
Serial.printf("END\n");
}
//
// Perform the FFT.
//
arm_cfft_radix4_instance_f32 S;
arm_cfft_radix4_init_f32(&S, pdmDataBufferSize, 0, 1);
arm_cfft_radix4_f32(&S, g_fPDMTimeDomain);
arm_cmplx_mag_f32(g_fPDMTimeDomain, g_fPDMMagnitudes, pdmDataBufferSize);
if (PRINT_FFT_DATA)
{
for (uint32_t i = 0; i < pdmDataBufferSize / 2; i++)
{
Serial.printf("%f\n", g_fPDMMagnitudes[i]);
}
Serial.printf("END\n");
}
//
// Find the frequency bin with the largest magnitude.
//
arm_max_f32(g_fPDMMagnitudes, pdmDataBufferSize / 2, &fMaxValue, &ui32MaxIndex);
ui32LoudestFrequency = (sampleFreq * ui32MaxIndex) / pdmDataBufferSize;
if (PRINT_FFT_DATA)
{
Serial.printf("Loudest frequency bin: %d\n", ui32MaxIndex);
}
Serial.printf("Loudest frequency: %d \n", ui32LoudestFrequency);
}
//*****************************************************************************
//
// Print PDM configuration data.
//
//*****************************************************************************
void printPDMConfig(void)
{
uint32_t PDMClk;
uint32_t MClkDiv;
float frequencyUnits;
//
// Read the config structure to figure out what our internal clock is set
// to.
//
switch (myPDM.getClockDivider())
{
case AM_HAL_PDM_MCLKDIV_4:
MClkDiv = 4;
break;
case AM_HAL_PDM_MCLKDIV_3:
MClkDiv = 3;
break;
case AM_HAL_PDM_MCLKDIV_2:
MClkDiv = 2;
break;
case AM_HAL_PDM_MCLKDIV_1:
MClkDiv = 1;
break;
default:
MClkDiv = 0;
}
switch (myPDM.getClockSpeed())
{
case AM_HAL_PDM_CLK_12MHZ:
PDMClk = 12000000;
break;
case AM_HAL_PDM_CLK_6MHZ:
PDMClk = 6000000;
break;
case AM_HAL_PDM_CLK_3MHZ:
PDMClk = 3000000;
break;
case AM_HAL_PDM_CLK_1_5MHZ:
PDMClk = 1500000;
break;
case AM_HAL_PDM_CLK_750KHZ:
PDMClk = 750000;
break;
case AM_HAL_PDM_CLK_375KHZ:
PDMClk = 375000;
break;
case AM_HAL_PDM_CLK_187KHZ:
PDMClk = 187000;
break;
default:
PDMClk = 0;
}
//
// Record the effective sample frequency. We'll need it later to print the
// loudest frequency from the sample.
//
sampleFreq = (PDMClk / (MClkDiv * 2 * myPDM.getDecimationRate()));
frequencyUnits = (float)sampleFreq / (float)pdmDataBufferSize;
Serial.printf("Settings:\n");
Serial.printf("PDM Clock (Hz): %12d\n", PDMClk);
Serial.printf("Decimation Rate: %12d\n", myPDM.getDecimationRate());
Serial.printf("Effective Sample Freq.: %12d\n", sampleFreq);
Serial.printf("FFT Length: %12d\n\n", pdmDataBufferSize);
Serial.printf("FFT Resolution: %15.3f Hz\n", frequencyUnits);
}