1 /*
2 * Copyright (c) 2015 - 2025, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <nrfx.h>
35
36 #if NRFX_CHECK(NRFX_PDM_ENABLED)
37
38 #include <nrfx_pdm.h>
39 #include <haly/nrfy_pdm.h>
40 #include <haly/nrfy_gpio.h>
41
42 #define NRFX_LOG_MODULE PDM
43 #include <nrfx_log.h>
44
45 #if !NRFX_FEATURE_PRESENT(NRFX_PDM, _ENABLED)
46 #error "No enabled PDM instances. Check <nrfx_config.h>."
47 #endif
48
49 #define EVT_TO_STR(event) \
50 (event == NRF_PDM_EVENT_STARTED ? "NRF_PDM_EVENT_STARTED" : \
51 (event == NRF_PDM_EVENT_STOPPED ? "NRF_PDM_EVENT_STOPPED" : \
52 (event == NRF_PDM_EVENT_END ? "NRF_PDM_EVENT_END" : \
53 "UNKNOWN EVENT")))
54
55
56 /** @brief PDM driver instance status. */
57 typedef enum
58 {
59 NRFX_PDM_STATE_IDLE,
60 NRFX_PDM_STATE_RUNNING,
61 NRFX_PDM_STATE_STARTING,
62 NRFX_PDM_STATE_STOPPING
63 } nrfx_pdm_state_t;
64
65 /** @brief PDM driver instance control block.*/
66 typedef struct
67 {
68 nrfx_pdm_event_handler_t event_handler; ///< Event handler function pointer.
69 int16_t * buff_address[2]; ///< Sample buffers.
70 uint16_t buff_length[2]; ///< Length of the sample buffers.
71 nrfx_drv_state_t drv_state; ///< Driver state.
72 volatile nrfx_pdm_state_t op_state; ///< PDM peripheral operation state.
73 uint8_t active_buffer; ///< Number of currently active buffer.
74 uint8_t error; ///< Driver error flag.
75 volatile uint8_t irq_buff_request; ///< Request the next buffer in the ISR.
76 bool skip_gpio_cfg; ///< Do not touch GPIO configuration of used pins.
77 } nrfx_pdm_cb_t;
78
79 #define _NRFX_PDM_CB_INITIALIZER(periph_name, prefix, idx, _) \
80 [NRFX_CONCAT(NRFX_, periph_name, idx, _INST_IDX)] = { \
81 .drv_state = NRFX_DRV_STATE_UNINITIALIZED, \
82 },
83
84 static nrfx_pdm_cb_t m_cb[NRFX_PDM_ENABLED_COUNT] = {
85 NRFX_FOREACH_ENABLED(PDM, _NRFX_PDM_CB_INITIALIZER, (), ())
86 };
87
88 /** @brief Function for getting instance control block.
89 *
90 * Function is optimized for case when there is only one PDM instance.
91 *
92 * @param[in] idx Instance index.
93 *
94 * @return Control block.
95 */
get_cb(uint32_t idx)96 static nrfx_pdm_cb_t * get_cb(uint32_t idx)
97 {
98 if (NRFX_PDM_ENABLED_COUNT == 1)
99 {
100 return &m_cb[0];
101 }
102 else
103 {
104 return &m_cb[idx];
105 }
106 }
107
pdm_configure(nrfx_pdm_t const * p_instance,nrfx_pdm_config_t const * p_config)108 static void pdm_configure(nrfx_pdm_t const * p_instance,
109 nrfx_pdm_config_t const * p_config)
110 {
111 if (!p_config->skip_gpio_cfg)
112 {
113 nrfy_gpio_pin_clear(p_config->clk_pin);
114 nrfy_gpio_cfg_output(p_config->clk_pin);
115 nrfy_gpio_cfg_input(p_config->din_pin, NRF_GPIO_PIN_NOPULL);
116 }
117 if (!p_config->skip_psel_cfg)
118 {
119 nrf_pdm_psel_connect(p_instance->p_reg,
120 p_config->clk_pin,
121 p_config->din_pin);
122 }
123
124 nrfy_pdm_config_t nrfy_config =
125 {
126 .mode = p_config->mode,
127 .edge = p_config->edge,
128 .pins =
129 {
130 .clk_pin = p_config->clk_pin,
131 .din_pin = p_config->din_pin,
132 },
133 NRFX_COND_CODE_1(NRF_PDM_HAS_PDMCLKCTRL, (.clock_freq = p_config->clock_freq,), ())
134 NRFX_COND_CODE_1(NRF_PDM_HAS_PRESCALER, (.prescaler = p_config->prescaler,), ())
135 .gain_l = p_config->gain_l,
136 .gain_r = p_config->gain_r,
137 NRFX_COND_CODE_1(NRF_PDM_HAS_RATIO_CONFIG, (.ratio = p_config->ratio,), ())
138 NRFX_COND_CODE_1(NRF_PDM_HAS_MCLKCONFIG, (.mclksrc = p_config->mclksrc,), ())
139 .skip_psel_cfg = p_config->skip_psel_cfg
140 };
141
142 nrfy_pdm_periph_configure(p_instance->p_reg, &nrfy_config);
143
144 nrfy_pdm_int_init(p_instance->p_reg,
145 NRF_PDM_INT_STARTED | NRF_PDM_INT_STOPPED,
146 p_config->interrupt_priority,
147 true);
148 }
149
pdm_init(nrfx_pdm_t const * p_instance,nrfx_pdm_config_t const * p_config,nrfx_pdm_event_handler_t event_handler)150 static nrfx_err_t pdm_init(nrfx_pdm_t const * p_instance,
151 nrfx_pdm_config_t const * p_config,
152 nrfx_pdm_event_handler_t event_handler)
153 {
154 NRFX_ASSERT(p_config);
155 NRFX_ASSERT(event_handler);
156 nrfx_err_t err_code;
157
158 nrfx_pdm_cb_t * p_cb = get_cb(p_instance->drv_inst_idx);
159
160 if (p_cb->drv_state != NRFX_DRV_STATE_UNINITIALIZED)
161 {
162 #if NRFX_API_VER_AT_LEAST(3, 2, 0)
163 err_code = NRFX_ERROR_ALREADY;
164 #else
165 err_code = NRFX_ERROR_INVALID_STATE;
166 #endif
167 NRFX_LOG_WARNING("Function: %s, error code: %s.",
168 __func__,
169 NRFX_LOG_ERROR_STRING_GET(err_code));
170 return err_code;
171 }
172
173 p_cb->buff_address[0] = 0;
174 p_cb->buff_address[1] = 0;
175 p_cb->active_buffer = 0;
176 p_cb->error = 0;
177 p_cb->event_handler = event_handler;
178 p_cb->op_state = NRFX_PDM_STATE_IDLE;
179
180 if (p_config)
181 {
182 p_cb->skip_gpio_cfg = p_config->skip_gpio_cfg;
183
184 if (p_config->gain_l > NRF_PDM_GAIN_MAXIMUM ||
185 p_config->gain_r > NRF_PDM_GAIN_MAXIMUM)
186 {
187 err_code = NRFX_ERROR_INVALID_PARAM;
188 NRFX_LOG_WARNING("Function: %s, error code: %s.",
189 __func__,
190 NRFX_LOG_ERROR_STRING_GET(err_code));
191 return err_code;
192 }
193 #if NRF_PDM_HAS_PRESCALER
194 if (p_config->prescaler < NRF_PDM_PRESCALER_MIN ||
195 p_config->prescaler > NRF_PDM_PRESCALER_MAX)
196 {
197 err_code = NRFX_ERROR_INVALID_PARAM;
198 NRFX_LOG_WARNING("Function: %s, error code: %s.",
199 __func__,
200 NRFX_LOG_ERROR_STRING_GET(err_code));
201 return err_code;
202 }
203 #endif
204 pdm_configure(p_instance, p_config);
205 }
206
207 p_cb->drv_state = NRFX_DRV_STATE_INITIALIZED;
208
209 err_code = NRFX_SUCCESS;
210 NRFX_LOG_INFO("Function: %s, error code: %s.",
211 __func__,
212 NRFX_LOG_ERROR_STRING_GET(err_code));
213 return err_code;
214 }
215
pdm_reconfigure(nrfx_pdm_t const * p_instance,nrfx_pdm_config_t const * p_config)216 static nrfx_err_t pdm_reconfigure(nrfx_pdm_t const * p_instance,
217 nrfx_pdm_config_t const * p_config)
218 {
219 nrfx_pdm_cb_t * p_cb = get_cb(p_instance->drv_inst_idx);
220
221 NRFX_ASSERT(p_config);
222 if (p_cb->drv_state == NRFX_DRV_STATE_UNINITIALIZED)
223 {
224 return NRFX_ERROR_INVALID_STATE;
225 }
226
227 if (p_config->gain_l > NRF_PDM_GAIN_MAXIMUM ||
228 p_config->gain_r > NRF_PDM_GAIN_MAXIMUM)
229 {
230 return NRFX_ERROR_INVALID_PARAM;
231 }
232
233 #if NRF_PDM_HAS_PRESCALER
234 if (p_config->prescaler < NRF_PDM_PRESCALER_MIN ||
235 p_config->prescaler > NRF_PDM_PRESCALER_MAX)
236 {
237 return NRFX_ERROR_INVALID_PARAM;
238 }
239 #endif
240
241 if (p_cb->op_state != NRFX_PDM_STATE_IDLE)
242 {
243 return NRFX_ERROR_BUSY;
244 }
245 nrfy_pdm_disable(p_instance->p_reg);
246 pdm_configure(p_instance, p_config);
247 nrfy_pdm_enable(p_instance->p_reg);
248 return NRFX_SUCCESS;
249 }
250
pdm_uninit(nrfx_pdm_t const * p_instance)251 static void pdm_uninit(nrfx_pdm_t const * p_instance)
252 {
253 nrfy_pdm_int_uninit(p_instance->p_reg);
254 nrfy_pdm_disable(p_instance->p_reg);
255
256 nrfx_pdm_cb_t * p_cb = get_cb(p_instance->drv_inst_idx);
257
258 if (!p_cb->skip_gpio_cfg)
259 {
260 nrfy_pdm_pins_t pins;
261 nrfy_pdm_pins_get(p_instance->p_reg, &pins);
262 nrfy_gpio_cfg_default(pins.clk_pin);
263 nrfy_gpio_cfg_default(pins.din_pin);
264 }
265
266 p_cb->drv_state = NRFX_DRV_STATE_UNINITIALIZED;
267 NRFX_LOG_INFO("Uninitialized.");
268 }
269
pdm_init_check(nrfx_pdm_t const * p_instance)270 static bool pdm_init_check(nrfx_pdm_t const * p_instance)
271 {
272 return (get_cb(p_instance->drv_inst_idx)->drv_state != NRFX_DRV_STATE_UNINITIALIZED);
273 }
274
pdm_buf_request(nrfx_pdm_t const * p_instance)275 static void pdm_buf_request(nrfx_pdm_t const * p_instance)
276 {
277 get_cb(p_instance->drv_inst_idx)->irq_buff_request = 1;
278 NRFY_IRQ_PENDING_SET(nrfx_get_irq_number(p_instance->p_reg));
279 }
280
pdm_start(nrfx_pdm_t const * p_instance)281 static nrfx_err_t pdm_start(nrfx_pdm_t const * p_instance)
282 {
283 nrfx_pdm_cb_t * p_cb = get_cb(p_instance->drv_inst_idx);
284
285 NRFX_ASSERT(p_cb->drv_state != NRFX_DRV_STATE_UNINITIALIZED);
286 nrfx_err_t err_code;
287
288 if (p_cb->op_state != NRFX_PDM_STATE_IDLE)
289 {
290 if (p_cb->op_state == NRFX_PDM_STATE_RUNNING)
291 {
292 err_code = NRFX_SUCCESS;
293 NRFX_LOG_INFO("Function: %s, error code: %s.",
294 __func__,
295 NRFX_LOG_ERROR_STRING_GET(err_code));
296 return err_code;
297 }
298 err_code = NRFX_ERROR_BUSY;
299 NRFX_LOG_WARNING("Function: %s, error code: %s.",
300 __func__,
301 NRFX_LOG_ERROR_STRING_GET(err_code));
302 return err_code;
303 }
304
305 p_cb->op_state = NRFX_PDM_STATE_STARTING;
306 pdm_buf_request(p_instance);
307
308 err_code = NRFX_SUCCESS;
309 NRFX_LOG_INFO("Function: %s, error code: %s.",
310 __func__,
311 NRFX_LOG_ERROR_STRING_GET(err_code));
312 return err_code;
313 }
314
pdm_buffer_set(nrfx_pdm_t const * p_instance,int16_t * buffer,uint16_t buffer_length)315 static nrfx_err_t pdm_buffer_set(nrfx_pdm_t const * p_instance,
316 int16_t * buffer,
317 uint16_t buffer_length)
318 {
319 nrfx_pdm_cb_t * p_cb = get_cb(p_instance->drv_inst_idx);
320
321 if (p_cb->drv_state == NRFX_DRV_STATE_UNINITIALIZED)
322 {
323 return NRFX_ERROR_INVALID_STATE;
324 }
325 if (p_cb->op_state == NRFX_PDM_STATE_STOPPING)
326 {
327 return NRFX_ERROR_BUSY;
328 }
329 if ((buffer == NULL) || (buffer_length > NRFX_PDM_MAX_BUFFER_SIZE))
330 {
331 return NRFX_ERROR_INVALID_PARAM;
332 }
333
334 nrfx_err_t err_code = NRFX_SUCCESS;
335
336 // Enter the PDM critical section.
337 NRFY_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_reg));
338
339 uint8_t next_buffer = (~p_cb->active_buffer) & 0x01;
340 if (p_cb->op_state == NRFX_PDM_STATE_STARTING)
341 {
342 next_buffer = 0;
343 }
344
345 if (p_cb->buff_address[next_buffer])
346 {
347 // Buffer already set.
348 err_code = NRFX_ERROR_BUSY;
349 }
350 else
351 {
352 p_cb->buff_address[next_buffer] = buffer;
353 p_cb->buff_length[next_buffer] = buffer_length;
354
355 nrfy_pdm_buffer_t nrfy_buffer =
356 {
357 .p_buff = buffer,
358 .length = buffer_length,
359 };
360 nrfy_pdm_buffer_set(p_instance->p_reg, &nrfy_buffer);
361
362 if (p_cb->drv_state != NRFX_DRV_STATE_POWERED_ON)
363 {
364 p_cb->drv_state = NRFX_DRV_STATE_POWERED_ON;
365 nrfy_pdm_enable(p_instance->p_reg);
366 nrfy_pdm_start(p_instance->p_reg, NULL);
367 }
368 }
369
370 NRFY_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_reg));
371 return err_code;
372 }
373
pdm_stop(nrfx_pdm_t const * p_instance)374 static nrfx_err_t pdm_stop(nrfx_pdm_t const * p_instance)
375 {
376 nrfx_pdm_cb_t * p_cb = get_cb(p_instance->drv_inst_idx);
377
378 NRFX_ASSERT(p_cb->drv_state != NRFX_DRV_STATE_UNINITIALIZED);
379 nrfx_err_t err_code;
380
381 if (p_cb->op_state != NRFX_PDM_STATE_RUNNING)
382 {
383 if (p_cb->op_state == NRFX_PDM_STATE_IDLE ||
384 p_cb->op_state == NRFX_PDM_STATE_STARTING)
385 {
386 nrfy_pdm_disable(p_instance->p_reg);
387 p_cb->op_state = NRFX_PDM_STATE_IDLE;
388 err_code = NRFX_SUCCESS;
389 NRFX_LOG_INFO("Function: %s, error code: %s.",
390 __func__,
391 NRFX_LOG_ERROR_STRING_GET(err_code));
392 return err_code;
393 }
394 err_code = NRFX_ERROR_BUSY;
395 NRFX_LOG_WARNING("Function: %s, error code: %s.",
396 __func__,
397 NRFX_LOG_ERROR_STRING_GET(err_code));
398 return err_code;
399 }
400 p_cb->drv_state = NRFX_DRV_STATE_INITIALIZED;
401 p_cb->op_state = NRFX_PDM_STATE_STOPPING;
402
403 nrfy_pdm_abort(p_instance->p_reg, NULL);
404 err_code = NRFX_SUCCESS;
405 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
406 return err_code;
407 }
408
409 #if NRFX_API_VER_AT_LEAST(3, 7, 0)
410
nrfx_pdm_init(nrfx_pdm_t const * p_instance,nrfx_pdm_config_t const * p_config,nrfx_pdm_event_handler_t event_handler)411 nrfx_err_t nrfx_pdm_init(nrfx_pdm_t const * p_instance,
412 nrfx_pdm_config_t const * p_config,
413 nrfx_pdm_event_handler_t event_handler)
414 {
415 return pdm_init(p_instance, p_config, event_handler);
416 }
417
nrfx_pdm_reconfigure(nrfx_pdm_t const * p_instance,nrfx_pdm_config_t const * p_config)418 nrfx_err_t nrfx_pdm_reconfigure(nrfx_pdm_t const * p_instance,
419 nrfx_pdm_config_t const * p_config)
420 {
421 return pdm_reconfigure(p_instance, p_config);
422 }
423
nrfx_pdm_uninit(nrfx_pdm_t const * p_instance)424 void nrfx_pdm_uninit(nrfx_pdm_t const * p_instance)
425 {
426 pdm_uninit(p_instance);
427 }
428
nrfx_pdm_init_check(nrfx_pdm_t const * p_instance)429 bool nrfx_pdm_init_check(nrfx_pdm_t const * p_instance)
430 {
431 return pdm_init_check(p_instance);
432 }
433
nrfx_pdm_start(nrfx_pdm_t const * p_instance)434 nrfx_err_t nrfx_pdm_start(nrfx_pdm_t const * p_instance)
435 {
436 return pdm_start(p_instance);
437 }
438
nrfx_pdm_buffer_set(nrfx_pdm_t const * p_instance,int16_t * buffer,uint16_t buffer_length)439 nrfx_err_t nrfx_pdm_buffer_set(nrfx_pdm_t const * p_instance,
440 int16_t * buffer,
441 uint16_t buffer_length)
442 {
443 return pdm_buffer_set(p_instance, buffer, buffer_length);
444 }
445
nrfx_pdm_stop(nrfx_pdm_t const * p_instance)446 nrfx_err_t nrfx_pdm_stop(nrfx_pdm_t const * p_instance)
447 {
448 return pdm_stop(p_instance);
449 }
450
451 #else
452
453 nrfx_pdm_t const pdm_instance = NRFX_PDM_INSTANCE(NRF_PDM_INDEX);
454
nrfx_pdm_init(nrfx_pdm_config_t const * p_config,nrfx_pdm_event_handler_t event_handler)455 nrfx_err_t nrfx_pdm_init(nrfx_pdm_config_t const * p_config,
456 nrfx_pdm_event_handler_t event_handler)
457 {
458 return pdm_init(&pdm_instance, p_config, event_handler);
459 }
460
nrfx_pdm_reconfigure(nrfx_pdm_config_t const * p_config)461 nrfx_err_t nrfx_pdm_reconfigure(nrfx_pdm_config_t const * p_config)
462 {
463 return pdm_reconfigure(&pdm_instance, p_config);
464 }
465
nrfx_pdm_uninit(void)466 void nrfx_pdm_uninit(void)
467 {
468 pdm_uninit(&pdm_instance);
469 }
470
nrfx_pdm_init_check(void)471 bool nrfx_pdm_init_check(void)
472 {
473 return pdm_init_check(&pdm_instance);
474 }
475
nrfx_pdm_start(void)476 nrfx_err_t nrfx_pdm_start(void)
477 {
478 return pdm_start(&pdm_instance);
479 }
480
nrfx_pdm_buffer_set(int16_t * buffer,uint16_t buffer_length)481 nrfx_err_t nrfx_pdm_buffer_set(int16_t * buffer, uint16_t buffer_length)
482 {
483 return pdm_buffer_set(&pdm_instance, buffer, buffer_length);
484 }
485
nrfx_pdm_stop(void)486 nrfx_err_t nrfx_pdm_stop(void)
487 {
488 return pdm_stop(&pdm_instance);
489 }
490
nrfx_pdm_irq_handler(void)491 void nrfx_pdm_irq_handler(void)
492 {
493 nrfx_pdm_cb_t * p_cb = get_cb(0);
494
495 nrfy_pdm_buffer_t buffer =
496 {
497 .p_buff = p_cb->buff_address[p_cb->active_buffer],
498 .length = p_cb->buff_length[p_cb->active_buffer],
499 };
500
501 uint32_t evt_mask = nrfy_pdm_events_process(NRF_PDM0,
502 NRFY_EVENT_TO_INT_BITMASK(NRF_PDM_EVENT_STARTED) |
503 NRFY_EVENT_TO_INT_BITMASK(NRF_PDM_EVENT_STOPPED),
504 &buffer);
505
506 if (evt_mask & NRFY_EVENT_TO_INT_BITMASK(NRF_PDM_EVENT_STARTED))
507 {
508 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_PDM_EVENT_STARTED));
509
510 uint8_t finished_buffer = p_cb->active_buffer;
511
512 // Check if the next buffer was set before.
513 uint8_t next_buffer = (~p_cb->active_buffer) & 0x01;
514 if (p_cb->buff_address[next_buffer] ||
515 p_cb->op_state == NRFX_PDM_STATE_STARTING)
516 {
517 nrfx_pdm_evt_t evt;
518 evt.error = NRFX_PDM_NO_ERROR;
519 p_cb->error = 0;
520
521 // Release the full buffer if ready and request the next one.
522 if (p_cb->op_state == NRFX_PDM_STATE_STARTING)
523 {
524 evt.buffer_released = 0;
525 p_cb->op_state = NRFX_PDM_STATE_RUNNING;
526 }
527 else
528 {
529 evt.buffer_released = p_cb->buff_address[finished_buffer];
530 p_cb->buff_address[finished_buffer] = 0;
531 p_cb->active_buffer = next_buffer;
532 }
533 evt.buffer_requested = true;
534 p_cb->event_handler(&evt);
535 }
536 else
537 {
538 // No next buffer available. Report an error.
539 // Do not request the new buffer as it was already done.
540 if (p_cb->error == 0)
541 {
542 nrfx_pdm_evt_t const evt = {
543 .buffer_requested = false,
544 .buffer_released = NULL,
545 .error = NRFX_PDM_ERROR_OVERFLOW
546 };
547 p_cb->error = 1;
548 p_cb->event_handler(&evt);
549 }
550 }
551
552 if (p_cb->op_state == NRFX_PDM_STATE_STARTING)
553 {
554 p_cb->op_state = NRFX_PDM_STATE_RUNNING;
555 }
556 }
557 else if (evt_mask & NRFY_EVENT_TO_INT_BITMASK(NRF_PDM_EVENT_STOPPED))
558 {
559 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_PDM_EVENT_STOPPED));
560 nrfy_pdm_disable(NRF_PDM0);
561 p_cb->op_state = NRFX_PDM_STATE_IDLE;
562
563 // Release the buffers.
564 nrfx_pdm_evt_t evt;
565 evt.error = NRFX_PDM_NO_ERROR;
566 evt.buffer_requested = false;
567 if (p_cb->buff_address[p_cb->active_buffer])
568 {
569 evt.buffer_released = p_cb->buff_address[p_cb->active_buffer];
570 p_cb->buff_address[p_cb->active_buffer] = 0;
571 p_cb->event_handler(&evt);
572 }
573
574 uint8_t second_buffer = (~p_cb->active_buffer) & 0x01;
575 if (p_cb->buff_address[second_buffer])
576 {
577 evt.buffer_released = p_cb->buff_address[second_buffer];
578 p_cb->buff_address[second_buffer] = 0;
579 p_cb->event_handler(&evt);
580 }
581 p_cb->active_buffer = 0;
582 }
583
584 if (p_cb->irq_buff_request)
585 {
586 nrfx_pdm_evt_t const evt =
587 {
588 .buffer_requested = true,
589 .buffer_released = NULL,
590 .error = NRFX_PDM_NO_ERROR,
591 };
592 p_cb->irq_buff_request = 0;
593 p_cb->event_handler(&evt);
594 }
595 }
596
597 #endif // NRFX_API_VER_AT_LEAST(3, 7, 0)
598
irq_handler(NRF_PDM_Type * p_pdm,nrfx_pdm_cb_t * p_cb)599 static void irq_handler(NRF_PDM_Type * p_pdm, nrfx_pdm_cb_t * p_cb)
600 {
601 nrfy_pdm_buffer_t buffer =
602 {
603 .p_buff = p_cb->buff_address[p_cb->active_buffer],
604 .length = p_cb->buff_length[p_cb->active_buffer],
605 };
606
607 uint32_t evt_mask = nrfy_pdm_events_process(p_pdm,
608 NRFY_EVENT_TO_INT_BITMASK(NRF_PDM_EVENT_STARTED) |
609 NRFY_EVENT_TO_INT_BITMASK(NRF_PDM_EVENT_STOPPED),
610 &buffer);
611
612 if (evt_mask & NRFY_EVENT_TO_INT_BITMASK(NRF_PDM_EVENT_STARTED))
613 {
614 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_PDM_EVENT_STARTED));
615
616 uint8_t finished_buffer = p_cb->active_buffer;
617
618 // Check if the next buffer was set before.
619 uint8_t next_buffer = (~p_cb->active_buffer) & 0x01;
620 if (p_cb->buff_address[next_buffer] ||
621 p_cb->op_state == NRFX_PDM_STATE_STARTING)
622 {
623 nrfx_pdm_evt_t evt;
624 evt.error = NRFX_PDM_NO_ERROR;
625 p_cb->error = 0;
626
627 // Release the full buffer if ready and request the next one.
628 if (p_cb->op_state == NRFX_PDM_STATE_STARTING)
629 {
630 evt.buffer_released = 0;
631 p_cb->op_state = NRFX_PDM_STATE_RUNNING;
632 }
633 else
634 {
635 evt.buffer_released = p_cb->buff_address[finished_buffer];
636 p_cb->buff_address[finished_buffer] = 0;
637 p_cb->active_buffer = next_buffer;
638 }
639 evt.buffer_requested = true;
640 p_cb->event_handler(&evt);
641 }
642 else
643 {
644 // No next buffer available. Report an error.
645 // Do not request the new buffer as it was already done.
646 if (p_cb->error == 0)
647 {
648 nrfx_pdm_evt_t const evt = {
649 .buffer_requested = false,
650 .buffer_released = NULL,
651 .error = NRFX_PDM_ERROR_OVERFLOW
652 };
653 p_cb->error = 1;
654 p_cb->event_handler(&evt);
655 }
656 }
657
658 if (p_cb->op_state == NRFX_PDM_STATE_STARTING)
659 {
660 p_cb->op_state = NRFX_PDM_STATE_RUNNING;
661 }
662 }
663 else if (evt_mask & NRFY_EVENT_TO_INT_BITMASK(NRF_PDM_EVENT_STOPPED))
664 {
665 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_PDM_EVENT_STOPPED));
666 nrfy_pdm_disable(p_pdm);
667 p_cb->op_state = NRFX_PDM_STATE_IDLE;
668
669 // Release the buffers.
670 nrfx_pdm_evt_t evt;
671 evt.error = NRFX_PDM_NO_ERROR;
672 evt.buffer_requested = false;
673 if (p_cb->buff_address[p_cb->active_buffer])
674 {
675 evt.buffer_released = p_cb->buff_address[p_cb->active_buffer];
676 p_cb->buff_address[p_cb->active_buffer] = 0;
677 p_cb->event_handler(&evt);
678 }
679
680 uint8_t second_buffer = (~p_cb->active_buffer) & 0x01;
681 if (p_cb->buff_address[second_buffer])
682 {
683 evt.buffer_released = p_cb->buff_address[second_buffer];
684 p_cb->buff_address[second_buffer] = 0;
685 p_cb->event_handler(&evt);
686 }
687 p_cb->active_buffer = 0;
688 }
689
690 if (p_cb->irq_buff_request)
691 {
692 nrfx_pdm_evt_t const evt =
693 {
694 .buffer_requested = true,
695 .buffer_released = NULL,
696 .error = NRFX_PDM_NO_ERROR,
697 };
698 p_cb->irq_buff_request = 0;
699 p_cb->event_handler(&evt);
700 }
701 }
702
703 NRFX_INSTANCE_IRQ_HANDLERS(PDM, pdm)
704
705 #endif // NRFX_CHECK(NRFX_PDM_ENABLED)
706