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