Skip to content

Commit f5d5b46

Browse files
committed
Unify nRF52 and STM PDM libraries
1 parent 3a4d480 commit f5d5b46

File tree

10 files changed

+3576
-7
lines changed

10 files changed

+3576
-7
lines changed

libraries/PDM/src/PDM.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@
2121

2222
#include <Arduino.h>
2323

24-
#if !defined(ARDUINO_ARCH_NRF52840) && !defined(ARDUINO_AS_MBED_LIBRARY)
25-
#error "This library targets only NRF52840 boards, not every mbed target"
26-
#endif
27-
2824
#include "utility/PDMDoubleBuffer.h"
2925

3026
class PDMClass
@@ -45,7 +41,7 @@ class PDMClass
4541
void setBufferSize(int bufferSize);
4642

4743
// private:
48-
void IrqHandler();
44+
void IrqHandler(bool halftranfer);
4945

5046
private:
5147
int _dinPin;

libraries/PDM/src/PDM.cpp renamed to libraries/PDM/src/nrf52/PDM.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
*/
2222

2323
#include "PDM.h"
24+
25+
#if defined(ARDUINO_ARCH_NRF52840)
26+
2427
#include <hal/nrf_pdm.h>
2528

2629
#define DEFAULT_PDM_GAIN 20
@@ -180,7 +183,7 @@ void PDMClass::setBufferSize(int bufferSize)
180183
_doubleBuffer.setSize(bufferSize);
181184
}
182185

183-
void PDMClass::IrqHandler()
186+
void PDMClass::IrqHandler(bool halftranfer)
184187
{
185188
if (nrf_pdm_event_check(NRF_PDM_EVENT_STARTED)) {
186189
nrf_pdm_event_clear(NRF_PDM_EVENT_STARTED);
@@ -210,8 +213,10 @@ void PDMClass::IrqHandler()
210213
extern "C" {
211214
__attribute__((__used__)) void PDM_IRQHandler_v(void)
212215
{
213-
PDM.IrqHandler();
216+
PDM.IrqHandler(true);
214217
}
215218
}
216219

217220
PDMClass PDM(PIN_PDM_DIN, PIN_PDM_CLK, PIN_PDM_PWR);
221+
222+
#endif

libraries/PDM/src/stm32/PDM.cpp

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*
2+
PDM.cpp - library to interface with STM32 PDM microphones
3+
Part of Arduino - http://www.arduino.cc/
4+
5+
Copyright (c) 2020 Arduino SA
6+
7+
This library is free software; you can redistribute it and/or
8+
modify it under the terms of the GNU Lesser General Public
9+
License as published by the Free Software Foundation; either
10+
version 2.1 of the License, or (at your option) any later version.
11+
12+
This library is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
Lesser General Public License for more details.
16+
17+
You should have received a copy of the GNU Lesser General
18+
Public License along with this library; if not, write to the
19+
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20+
Boston, MA 02111-1307 USA
21+
*/
22+
23+
#ifdef TARGET_STM
24+
25+
#include "PDM.h"
26+
#include "audio.h"
27+
#include "mbed.h"
28+
29+
#define AUDIO_FREQUENCY BSP_AUDIO_FREQUENCY_16K
30+
#define AUDIO_IN_PDM_BUFFER_SIZE (uint32_t)(128)
31+
32+
//ALIGN_32BYTES (uint16_t recordPDMBuf[AUDIO_IN_PDM_BUFFER_SIZE]) __attribute__((section(".OPEN_AMP_SHMEM")));
33+
// FIXME: need to add an entry for RAM_D3 to linker script
34+
uint16_t* recordPDMBuf = (uint16_t*)0x38000000;
35+
36+
PDMClass::PDMClass(int dinPin, int clkPin, int pwrPin) :
37+
_dinPin(dinPin),
38+
_clkPin(clkPin),
39+
_pwrPin(pwrPin),
40+
_onReceive(NULL)
41+
{
42+
}
43+
44+
PDMClass::~PDMClass()
45+
{
46+
}
47+
48+
int PDMClass::begin(int channels, long sampleRate) {
49+
50+
_channels = channels;
51+
52+
// fixme: only works in stereo mode
53+
channels = 2;
54+
55+
setBufferSize(AUDIO_IN_PDM_BUFFER_SIZE / 4 * channels);
56+
57+
if (isBoardRev2()) {
58+
mbed::I2C i2c(PB_7, PB_6);
59+
char data[2];
60+
61+
// SW2 to 3.3V (SW2_VOLT)
62+
data[0] = 0x3B;
63+
data[1] = 0xF;
64+
i2c.write(8 << 1, data, sizeof(data));
65+
66+
// SW1 to 3.0V (SW1_VOLT)
67+
data[0] = 0x35;
68+
data[1] = 0xF;
69+
i2c.write(8 << 1, data, sizeof(data));
70+
}
71+
72+
BSP_AUDIO_IN_SelectInterface(AUDIO_IN_INTERFACE_PDM);
73+
74+
/* Initialize audio IN at REC_FREQ*/
75+
if (BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MIC, AUDIO_FREQUENCY, DEFAULT_AUDIO_IN_BIT_RESOLUTION, channels) != AUDIO_OK)
76+
{
77+
return 0;
78+
}
79+
80+
/* Start the record */
81+
BSP_AUDIO_IN_Record((uint16_t*)recordPDMBuf, AUDIO_IN_PDM_BUFFER_SIZE * channels);
82+
return 1;
83+
}
84+
85+
void PDMClass::end()
86+
{
87+
}
88+
89+
int PDMClass::available()
90+
{
91+
size_t avail = _doubleBuffer.available();
92+
if (_channels == 1) {
93+
return avail/2;
94+
} else {
95+
return avail;
96+
}
97+
}
98+
99+
int PDMClass::read(void* buffer, size_t size)
100+
{
101+
if (_channels == 1) {
102+
uint16_t temp[size*2];
103+
int read = _doubleBuffer.read(temp, size*2);
104+
for (int i = 0; i < size; i++) {
105+
((uint16_t*)buffer)[i] = temp[i*2];
106+
}
107+
return read;
108+
}
109+
int read = _doubleBuffer.read(buffer, size);
110+
return read;
111+
}
112+
113+
void PDMClass::onReceive(void(*function)(void))
114+
{
115+
_onReceive = function;
116+
}
117+
118+
void PDMClass::setGain(int gain)
119+
{
120+
121+
}
122+
123+
void PDMClass::setBufferSize(int bufferSize)
124+
{
125+
_doubleBuffer.setSize(bufferSize);
126+
}
127+
128+
void PDMClass::IrqHandler(bool halftranfer)
129+
{
130+
131+
int start = halftranfer ? 0 : AUDIO_IN_PDM_BUFFER_SIZE;
132+
133+
if (BSP_AUDIO_IN_GetInterface() == AUDIO_IN_INTERFACE_PDM && _doubleBuffer.available() == 0) {
134+
135+
/* Invalidate Data Cache to get the updated content of the SRAM*/
136+
SCB_InvalidateDCache_by_Addr((uint32_t *)&recordPDMBuf[start], AUDIO_IN_PDM_BUFFER_SIZE * 2);
137+
138+
//memcpy((uint16_t*)_doubleBuffer.data(), (uint16_t*)&recordPDMBuf[start], AUDIO_IN_PDM_BUFFER_SIZE/2);
139+
BSP_AUDIO_IN_PDMToPCM((uint16_t*)&recordPDMBuf[start], (uint16_t*)_doubleBuffer.data());
140+
141+
/* Clean Data Cache to update the content of the SRAM */
142+
SCB_CleanDCache_by_Addr((uint32_t*)_doubleBuffer.data(), AUDIO_IN_PDM_BUFFER_SIZE * 2);
143+
144+
_doubleBuffer.swap(_doubleBuffer.availableForWrite());
145+
}
146+
if (_onReceive) {
147+
_onReceive();
148+
}
149+
}
150+
151+
extern "C" {
152+
/**
153+
@brief Calculates the remaining file size and new position of the pointer.
154+
@param None
155+
@retval None
156+
*/
157+
__attribute__((__used__)) void BSP_AUDIO_IN_TransferComplete_CallBack(void)
158+
{
159+
PDM.IrqHandler(false);
160+
}
161+
162+
/**
163+
@brief Manages the DMA Half Transfer complete interrupt.
164+
@param None
165+
@retval None
166+
*/
167+
__attribute__((__used__)) void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
168+
{
169+
PDM.IrqHandler(true);
170+
}
171+
}
172+
173+
PDMClass PDM(0, 0, 0);
174+
175+
#endif

0 commit comments

Comments
 (0)