@@ -11,11 +11,7 @@ extern "C" {
11
11
}
12
12
#include " hardware/sync.h"
13
13
#include " pdm.pio.h"
14
-
15
- // Hardware peripherals used
16
- uint dmaChannel = 0 ;
17
- PIO pio = pio0;
18
- uint sm = 0 ;
14
+ static PIOProgram _pdmPgm (&pdm_pio_program);
19
15
20
16
// raw buffers contain PDM data
21
17
#define RAW_BUFFER_SIZE 512 // should be a multiple of (decimation / 8)
@@ -49,7 +45,11 @@ PDMClass::PDMClass(int dinPin, int clkPin, int pwrPin) :
49
45
_gain(-1 ),
50
46
_channels(-1 ),
51
47
_samplerate(-1 ),
52
- _init(-1 )
48
+ _init(-1 ),
49
+ _dmaChannel(0 ),
50
+ _pio(nullptr ),
51
+ _smIdx(-1 ),
52
+ _pgmOffset(-1 )
53
53
{
54
54
}
55
55
@@ -89,29 +89,35 @@ int PDMClass::begin(int channels, int sampleRate)
89
89
90
90
// Configure PIO state machine
91
91
float clkDiv = (float )clock_get_hz (clk_sys) / sampleRate / decimation / 2 ;
92
- uint offset = pio_add_program (pio, &pdm_pio_program);
93
- pdm_pio_program_init (pio, sm, offset, _clkPin, _dinPin, clkDiv);
92
+
93
+ if (!_pdmPgm.prepare (&_pio, &_smIdx, &_pgmOffset)) {
94
+ // ERROR, no free slots
95
+ return -1 ;
96
+ }
97
+ pdm_pio_program_init (_pio, _smIdx, _pgmOffset, _clkPin, _dinPin, clkDiv);
94
98
95
99
// Wait for microphone
96
100
delay (100 );
97
101
98
102
// Configure DMA for transferring PIO rx buffer to raw buffers
99
- dma_channel_config c = dma_channel_get_default_config (dmaChannel);
103
+ _dmaChannel = dma_claim_unused_channel (false );
104
+ dma_channel_config c = dma_channel_get_default_config (_dmaChannel);
100
105
channel_config_set_read_increment (&c, false );
101
106
channel_config_set_write_increment (&c, true );
102
- channel_config_set_dreq (&c, pio_get_dreq (pio, sm , false ));
107
+ channel_config_set_dreq (&c, pio_get_dreq (_pio, _smIdx , false ));
103
108
channel_config_set_transfer_data_size (&c, DMA_SIZE_8);
104
109
105
110
// Clear DMA interrupts
106
- dma_hw->ints0 = 1u << dmaChannel ;
111
+ dma_hw->ints0 = 1u << _dmaChannel ;
107
112
// Enable DMA interrupts
108
- dma_channel_set_irq0_enabled (dmaChannel, true );
109
- irq_set_exclusive_handler (DMA_IRQ_0, dmaHandler);
113
+ dma_channel_set_irq0_enabled (_dmaChannel, true );
114
+ // Share but allocate a high priority to the interrupt
115
+ irq_add_shared_handler (DMA_IRQ_0, dmaHandler, 0 );
110
116
irq_set_enabled (DMA_IRQ_0, true );
111
117
112
- dma_channel_configure (dmaChannel , &c,
118
+ dma_channel_configure (_dmaChannel , &c,
113
119
rawBuffer[rawBufferIndex], // Destinatinon pointer
114
- &pio ->rxf [sm ], // Source pointer
120
+ &_pio ->rxf [_smIdx ], // Source pointer
115
121
RAW_BUFFER_SIZE, // Number of transfers
116
122
true // Start immediately
117
123
);
@@ -123,7 +129,7 @@ int PDMClass::begin(int channels, int sampleRate)
123
129
124
130
void PDMClass::end ()
125
131
{
126
- dma_channel_abort (dmaChannel );
132
+ dma_channel_abort (_dmaChannel );
127
133
pinMode (_clkPin, INPUT);
128
134
}
129
135
@@ -171,10 +177,10 @@ void PDMClass::IrqHandler(bool halftranfer)
171
177
static int cutSamples = 100 ;
172
178
173
179
// Clear the interrupt request.
174
- dma_hw->ints0 = 1u << dmaChannel ;
180
+ dma_hw->ints0 = 1u << _dmaChannel ;
175
181
// Restart dma pointing to the other buffer
176
182
int shadowIndex = rawBufferIndex ^ 1 ;
177
- dma_channel_set_write_addr (dmaChannel , rawBuffer[shadowIndex], true );
183
+ dma_channel_set_write_addr (_dmaChannel , rawBuffer[shadowIndex], true );
178
184
179
185
if (_doubleBuffer.available ()) {
180
186
// buffer overflow, stop
0 commit comments