Skip to content

Commit 893f103

Browse files
authored
Merge pull request #44 from sparkfun/PDM
PDM library with examples
2 parents a17accd + 79bb745 commit 893f103

File tree

14 files changed

+3060
-2298
lines changed

14 files changed

+3060
-2298
lines changed

cores/arduino/am_sdk_ap3/CMSIS/ARM/Include/arm_math.h

Lines changed: 1962 additions & 2293 deletions
Large diffs are not rendered by default.

cores/arduino/ard_sup/Arduino.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ extern "C"
3333
#ifdef OVERFLOW
3434
#define ARDUINO_REDEFINE_OVERFLOW OVERFLOW
3535
#undef OVERFLOW
36-
#warning "OVERFLOW is defined already... trying to save it, include Apollo3 headers, then restore it"
36+
// #warning "OVERFLOW is defined already... trying to save it, include Apollo3 headers, then restore it"
3737
#endif
3838

3939
// Include Apollo headers
@@ -44,7 +44,7 @@ extern "C"
4444
#include <math.h> //Gets us pow()
4545

4646
#ifdef ARDUINO_REDEFINE_OVERFLOW
47-
#warning "restoring OVERFLOW from value in ARDUINO_REDEFINE_OVERFLOW"
47+
// #warning "restoring OVERFLOW from value in ARDUINO_REDEFINE_OVERFLOW"
4848
#define OVERFLOW ARDUINO_REDEFINE_OVERFLOW
4949
#undef ARDUINO_REDEFINE_OVERFLOW
5050
#endif
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/* Author: Nathan Seidle
2+
Created: July 24, 2019
3+
License: MIT. See SparkFun Arduino Apollo3 Project for more information
4+
5+
This example demonstrates how to use the pulse density microphone (PDM) on Artemis boards.
6+
This library and example are heavily based on the Apollo3 pdm_fft example.
7+
*/
8+
9+
//Global variables needed for PDM library
10+
#define pdmDataBufferSize 4096 //Default is array of 4096 * 32bit
11+
uint32_t pdmDataBuffer[pdmDataBufferSize];
12+
13+
//Global variables needed for the FFT in this sketch
14+
float g_fPDMTimeDomain[pdmDataBufferSize * 2];
15+
float g_fPDMFrequencyDomain[pdmDataBufferSize * 2];
16+
float g_fPDMMagnitudes[pdmDataBufferSize * 2];
17+
uint32_t sampleFreq;
18+
19+
//Enable these defines for additional debug printing
20+
#define PRINT_PDM_DATA 0
21+
#define PRINT_FFT_DATA 0
22+
23+
#include <PDM.h> //Include PDM library included with the Aruino_Apollo3 core
24+
AP3_PDM myPDM; //Create instance of PDM class
25+
26+
//Math library needed for FFT
27+
#define ARM_MATH_CM4
28+
#include <arm_math.h>
29+
30+
void setup()
31+
{
32+
Serial.begin(9600);
33+
Serial.println("SparkFun PDM Example");
34+
35+
if (myPDM.begin() == false) // Turn on PDM with default settings
36+
{
37+
Serial.println("PDM Init failed. Are you sure these pins are PDM capable?");
38+
while (1);
39+
}
40+
Serial.println("PDM Initialized");
41+
42+
printPDMConfig();
43+
44+
myPDM.getData(pdmDataBuffer, pdmDataBufferSize); //This clears the current PDM FIFO and starts DMA
45+
}
46+
47+
void loop()
48+
{
49+
noInterrupts();
50+
51+
if (myPDM.available())
52+
{
53+
printLoudest();
54+
55+
while (PRINT_PDM_DATA || PRINT_FFT_DATA);
56+
57+
// Start converting the next set of PCM samples.
58+
myPDM.getData(pdmDataBuffer, pdmDataBufferSize);
59+
}
60+
61+
// Go to Deep Sleep until the PDM ISR or other ISR wakes us.
62+
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
63+
64+
interrupts();
65+
}
66+
67+
//*****************************************************************************
68+
//
69+
// Analyze and print frequency data.
70+
//
71+
//*****************************************************************************
72+
void printLoudest(void)
73+
{
74+
float fMaxValue;
75+
uint32_t ui32MaxIndex;
76+
int16_t *pi16PDMData = (int16_t *) pdmDataBuffer;
77+
uint32_t ui32LoudestFrequency;
78+
79+
//
80+
// Convert the PDM samples to floats, and arrange them in the format
81+
// required by the FFT function.
82+
//
83+
for (uint32_t i = 0; i < pdmDataBufferSize; i++)
84+
{
85+
if (PRINT_PDM_DATA)
86+
{
87+
Serial.printf("%d\n", pi16PDMData[i]);
88+
}
89+
90+
g_fPDMTimeDomain[2 * i] = pi16PDMData[i] / 1.0;
91+
g_fPDMTimeDomain[2 * i + 1] = 0.0;
92+
}
93+
94+
if (PRINT_PDM_DATA)
95+
{
96+
Serial.printf("END\n");
97+
}
98+
99+
//
100+
// Perform the FFT.
101+
//
102+
arm_cfft_radix4_instance_f32 S;
103+
arm_cfft_radix4_init_f32(&S, pdmDataBufferSize, 0, 1);
104+
arm_cfft_radix4_f32(&S, g_fPDMTimeDomain);
105+
arm_cmplx_mag_f32(g_fPDMTimeDomain, g_fPDMMagnitudes, pdmDataBufferSize);
106+
107+
if (PRINT_FFT_DATA)
108+
{
109+
for (uint32_t i = 0; i < pdmDataBufferSize / 2; i++)
110+
{
111+
Serial.printf("%f\n", g_fPDMMagnitudes[i]);
112+
}
113+
114+
Serial.printf("END\n");
115+
}
116+
117+
//
118+
// Find the frequency bin with the largest magnitude.
119+
//
120+
arm_max_f32(g_fPDMMagnitudes, pdmDataBufferSize / 2, &fMaxValue, &ui32MaxIndex);
121+
122+
ui32LoudestFrequency = (sampleFreq * ui32MaxIndex) / pdmDataBufferSize;
123+
124+
if (PRINT_FFT_DATA)
125+
{
126+
Serial.printf("Loudest frequency bin: %d\n", ui32MaxIndex);
127+
}
128+
129+
Serial.printf("Loudest frequency: %d \n", ui32LoudestFrequency);
130+
}
131+
132+
//*****************************************************************************
133+
//
134+
// Print PDM configuration data.
135+
//
136+
//*****************************************************************************
137+
void printPDMConfig(void)
138+
{
139+
uint32_t PDMClk;
140+
uint32_t MClkDiv;
141+
float frequencyUnits;
142+
143+
//
144+
// Read the config structure to figure out what our internal clock is set
145+
// to.
146+
//
147+
switch (myPDM.getClockDivider())
148+
{
149+
case AM_HAL_PDM_MCLKDIV_4: MClkDiv = 4; break;
150+
case AM_HAL_PDM_MCLKDIV_3: MClkDiv = 3; break;
151+
case AM_HAL_PDM_MCLKDIV_2: MClkDiv = 2; break;
152+
case AM_HAL_PDM_MCLKDIV_1: MClkDiv = 1; break;
153+
154+
default:
155+
MClkDiv = 0;
156+
}
157+
158+
switch (myPDM.getClockSpeed())
159+
{
160+
case AM_HAL_PDM_CLK_12MHZ: PDMClk = 12000000; break;
161+
case AM_HAL_PDM_CLK_6MHZ: PDMClk = 6000000; break;
162+
case AM_HAL_PDM_CLK_3MHZ: PDMClk = 3000000; break;
163+
case AM_HAL_PDM_CLK_1_5MHZ: PDMClk = 1500000; break;
164+
case AM_HAL_PDM_CLK_750KHZ: PDMClk = 750000; break;
165+
case AM_HAL_PDM_CLK_375KHZ: PDMClk = 375000; break;
166+
case AM_HAL_PDM_CLK_187KHZ: PDMClk = 187000; break;
167+
168+
default:
169+
PDMClk = 0;
170+
}
171+
172+
//
173+
// Record the effective sample frequency. We'll need it later to print the
174+
// loudest frequency from the sample.
175+
//
176+
sampleFreq = (PDMClk / (MClkDiv * 2 * myPDM.getDecimationRate()));
177+
178+
frequencyUnits = (float) sampleFreq / (float) pdmDataBufferSize;
179+
180+
Serial.printf("Settings:\n");
181+
Serial.printf("PDM Clock (Hz): %12d\n", PDMClk);
182+
Serial.printf("Decimation Rate: %12d\n", myPDM.getDecimationRate());
183+
Serial.printf("Effective Sample Freq.: %12d\n", sampleFreq);
184+
Serial.printf("FFT Length: %12d\n\n", pdmDataBufferSize);
185+
Serial.printf("FFT Resolution: %15.3f Hz\n", frequencyUnits);
186+
}

0 commit comments

Comments
 (0)