Skip to content

Commit 134aa6b

Browse files
author
Nathan Seidle
committed
Add example
1 parent e3ed491 commit 134aa6b

File tree

3 files changed

+215
-7
lines changed

3 files changed

+215
-7
lines changed
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
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 PDM microphone on Artemis boards.
6+
*/
7+
8+
#define ARM_MATH_CM4
9+
#include <arm_math.h>
10+
11+
//*****************************************************************************
12+
//
13+
// Example parameters.
14+
//
15+
//*****************************************************************************
16+
#define PDM_FFT_SIZE 4096
17+
//uint32_t pdmDataBufferSize = 4096;
18+
#define pdmDataBufferSize 4096
19+
20+
//#define PDM_FFT_BYTES (PDM_FFT_SIZE * 2)
21+
#define PRINT_PDM_DATA 0
22+
#define PRINT_FFT_DATA 0
23+
24+
//*****************************************************************************
25+
//
26+
// Global variables.
27+
//
28+
//*****************************************************************************
29+
//uint32_t g_ui32PDMDataBuffer[pdmDataBufferSize];
30+
uint32_t pdmDataBuffer[pdmDataBufferSize];
31+
float g_fPDMTimeDomain[pdmDataBufferSize * 2];
32+
float g_fPDMFrequencyDomain[pdmDataBufferSize * 2];
33+
float g_fPDMMagnitudes[pdmDataBufferSize * 2];
34+
35+
uint32_t sampleFreq;
36+
37+
#include <PDM.h> //Include PDM library included with the Aruino_Apollo3 core
38+
39+
AP3_PDM myPDM;
40+
41+
void setup()
42+
{
43+
Serial.begin(9600);
44+
Serial.println("SparkFun PDM Example");
45+
46+
// Turn on the PDM, set it up for our chosen recording settings, and start
47+
// the first DMA transaction.
48+
if (myPDM.begin(22, 23) == false) //Data, clock - These are the pin names from variant file, not pad names
49+
{
50+
Serial.println("PDM Init failed. Are you sure these pins are PDM capable?");
51+
while (1);
52+
}
53+
Serial.println("PDM Initialized");
54+
55+
//myPDM.setClockSpeed(AM_HAL_PDM_CLK_3MHZ);
56+
//myPDM.setClockDivider(AM_HAL_PDM_MCLKDIV_1);
57+
//myPDM.setGain(AM_HAL_PDM_GAIN_P210DB);
58+
//myPDM.setChannel(AM_HAL_PDM_CHANNEL_STEREO);
59+
60+
pdm_config_print();
61+
am_hal_pdm_fifo_flush(myPDM._PDMhandle);
62+
myPDM.getData(pdmDataBuffer, pdmDataBufferSize);
63+
}
64+
65+
void loop()
66+
{
67+
am_hal_interrupt_master_disable();
68+
69+
if (myPDM.available())
70+
{
71+
pcm_fft_print();
72+
73+
while (PRINT_PDM_DATA || PRINT_FFT_DATA);
74+
75+
// Start converting the next set of PCM samples.
76+
myPDM.getData(pdmDataBuffer, pdmDataBufferSize);
77+
}
78+
79+
// Go to Deep Sleep.
80+
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
81+
82+
am_hal_interrupt_master_enable();
83+
}
84+
85+
//*****************************************************************************
86+
//
87+
// Analyze and print frequency data.
88+
//
89+
//*****************************************************************************
90+
void
91+
pcm_fft_print(void)
92+
{
93+
float fMaxValue;
94+
uint32_t ui32MaxIndex;
95+
int16_t *pi16PDMData = (int16_t *) pdmDataBuffer;
96+
uint32_t ui32LoudestFrequency;
97+
98+
//
99+
// Convert the PDM samples to floats, and arrange them in the format
100+
// required by the FFT function.
101+
//
102+
for (uint32_t i = 0; i < PDM_FFT_SIZE; i++)
103+
{
104+
if (PRINT_PDM_DATA)
105+
{
106+
Serial.printf("%d\n", pi16PDMData[i]);
107+
}
108+
109+
g_fPDMTimeDomain[2 * i] = pi16PDMData[i] / 1.0;
110+
g_fPDMTimeDomain[2 * i + 1] = 0.0;
111+
}
112+
113+
if (PRINT_PDM_DATA)
114+
{
115+
Serial.printf("END\n");
116+
}
117+
118+
//
119+
// Perform the FFT.
120+
//
121+
arm_cfft_radix4_instance_f32 S;
122+
arm_cfft_radix4_init_f32(&S, PDM_FFT_SIZE, 0, 1);
123+
arm_cfft_radix4_f32(&S, g_fPDMTimeDomain);
124+
arm_cmplx_mag_f32(g_fPDMTimeDomain, g_fPDMMagnitudes, PDM_FFT_SIZE);
125+
126+
if (PRINT_FFT_DATA)
127+
{
128+
for (uint32_t i = 0; i < PDM_FFT_SIZE / 2; i++)
129+
{
130+
Serial.printf("%f\n", g_fPDMMagnitudes[i]);
131+
}
132+
133+
Serial.printf("END\n");
134+
}
135+
136+
//
137+
// Find the frequency bin with the largest magnitude.
138+
//
139+
arm_max_f32(g_fPDMMagnitudes, PDM_FFT_SIZE / 2, &fMaxValue, &ui32MaxIndex);
140+
141+
ui32LoudestFrequency = (sampleFreq * ui32MaxIndex) / PDM_FFT_SIZE;
142+
143+
if (PRINT_FFT_DATA)
144+
{
145+
Serial.printf("Loudest frequency bin: %d\n", ui32MaxIndex);
146+
}
147+
148+
Serial.printf("Loudest frequency: %d \n", ui32LoudestFrequency);
149+
}
150+
151+
//*****************************************************************************
152+
//
153+
// Print PDM configuration data.
154+
//
155+
//*****************************************************************************
156+
void
157+
pdm_config_print(void)
158+
{
159+
uint32_t PDMClk;
160+
uint32_t MClkDiv;
161+
float frequencyUnits;
162+
163+
//
164+
// Read the config structure to figure out what our internal clock is set
165+
// to.
166+
//
167+
switch (myPDM.getClockDivider())
168+
{
169+
case AM_HAL_PDM_MCLKDIV_4: MClkDiv = 4; break;
170+
case AM_HAL_PDM_MCLKDIV_3: MClkDiv = 3; break;
171+
case AM_HAL_PDM_MCLKDIV_2: MClkDiv = 2; break;
172+
case AM_HAL_PDM_MCLKDIV_1: MClkDiv = 1; break;
173+
174+
default:
175+
MClkDiv = 0;
176+
}
177+
178+
switch (myPDM.getClockSpeed())
179+
{
180+
case AM_HAL_PDM_CLK_12MHZ: PDMClk = 12000000; break;
181+
case AM_HAL_PDM_CLK_6MHZ: PDMClk = 6000000; break;
182+
case AM_HAL_PDM_CLK_3MHZ: PDMClk = 3000000; break;
183+
case AM_HAL_PDM_CLK_1_5MHZ: PDMClk = 1500000; break;
184+
case AM_HAL_PDM_CLK_750KHZ: PDMClk = 750000; break;
185+
case AM_HAL_PDM_CLK_375KHZ: PDMClk = 375000; break;
186+
case AM_HAL_PDM_CLK_187KHZ: PDMClk = 187000; break;
187+
188+
default:
189+
PDMClk = 0;
190+
}
191+
192+
//
193+
// Record the effective sample frequency. We'll need it later to print the
194+
// loudest frequency from the sample.
195+
//
196+
sampleFreq = (PDMClk / (MClkDiv * 2 * myPDM.getDecimationRate()));
197+
198+
frequencyUnits = (float) sampleFreq / (float) PDM_FFT_SIZE;
199+
200+
Serial.printf("Settings:\n");
201+
Serial.printf("PDM Clock (Hz): %12d\n", PDMClk);
202+
Serial.printf("Decimation Rate: %12d\n", myPDM.getDecimationRate());
203+
Serial.printf("Effective Sample Freq.: %12d\n", sampleFreq);
204+
Serial.printf("FFT Length: %12d\n\n", PDM_FFT_SIZE);
205+
Serial.printf("FFT Resolution: %15.3f Hz\n", frequencyUnits);
206+
}

libraries/PDM/src/PDM.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,11 @@ ap3_err_t ap3_pdm_pad_funcsel(ap3_pdm_pad_type_e type, ap3_gpio_pad_t pad, uint8
250250
}
251251

252252
//*****************************************************************************
253-
//
254-
// Start a transaction to get some number of bytes from the PDM interface.
255-
//
256-
//*****************************************************************************
257-
void
258-
AP3_PDM::getData(uint32_t *PDMDataBuffer, uint32_t bufferSize)
253+
//
254+
// Start a transaction to get some number of bytes from the PDM interface.
255+
//
256+
//*****************************************************************************
257+
void AP3_PDM::getData(uint32_t *PDMDataBuffer, uint32_t bufferSize)
259258
{
260259
//
261260
// Configure DMA and target address.
@@ -272,7 +271,7 @@ ap3_err_t ap3_pdm_pad_funcsel(ap3_pdm_pad_type_e type, ap3_gpio_pad_t pad, uint8
272271
am_hal_pdm_fifo_flush(_PDMhandle);
273272
am_hal_pdm_dma_start(_PDMhandle, &sTransfer);
274273

275-
myPDM._PDMdataReady = false;
274+
_PDMdataReady = false;
276275
}
277276

278277
inline void AP3_PDM::pdm_isr(void)

libraries/PDM/src/PDM.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ class AP3_PDM
104104
uint32_t getDecimationRate();
105105

106106
bool updateConfig(am_hal_pdm_config_t newConfiguration);
107+
108+
void getData(uint32_t *PDMDataBuffer, uint32_t bufferSize);
109+
107110
//void begin(void);
108111
// void begin(unsigned long baudrate, uint16_t config);
109112
// void begin(unsigned long baudrate, am_hal_uart_config_t config);

0 commit comments

Comments
 (0)