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 #ifndef NRF_PDM_H_
34 #define NRF_PDM_H_
35 
36 #include <nrfx.h>
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 #if !defined(NRF_PDM0) && defined(NRF_PDM)
43 #define NRF_PDM0 NRF_PDM
44 #endif
45 
46 /**
47  * @defgroup nrf_pdm_hal PDM HAL
48  * @{
49  * @ingroup nrf_pdm
50  * @brief   Hardware access layer for managing the Pulse Density Modulation (PDM) peripheral.
51  */
52 
53 /**
54  * @brief Macro for getting a pointer to the structure of registers of the PDM peripheral.
55  *
56  * @param[in] idx PDM instance index.
57  *
58  * @return Pointer to the structure of registers of the PDM peripheral.
59  */
60 #define NRF_PDM_INST_GET(idx) NRFX_CONCAT_2(NRF_PDM, idx)
61 
62 #if defined(PDM_MCLKCONFIG_SRC_Msk) || defined(__NRFX_DOXYGEN__)
63 /** @brief Symbol indicating whether master clock source configuration is available. */
64 #define NRF_PDM_HAS_MCLKCONFIG 1
65 #else
66 #define NRF_PDM_HAS_MCLKCONFIG 0
67 #endif
68 
69 #if defined(PDM_RATIO_RATIO_Msk) || defined(__NRFX_DOXYGEN__)
70 /** @brief Symbol indicating whether ratio configuration is available. */
71 #define NRF_PDM_HAS_RATIO_CONFIG 1
72 #else
73 #define NRF_PDM_HAS_RATIO_CONFIG 0
74 #endif
75 
76 #if (defined(PDM_TASKS_DMA_START_START_Msk) && defined(PDM_EVENTS_DMA_END_END_Msk)) || \
77     defined(__NRFX_DOXYGEN__)
78 /** @brief Symbol indicating whether PDM DMA tasks and events are present. */
79 #define NRF_PDM_HAS_DMA_TASKS_EVENTS 1
80 #else
81 #define NRF_PDM_HAS_DMA_TASKS_EVENTS 0
82 #endif
83 
84 #if defined(PDM_PDMCLKCTRL_FREQ_Msk) || defined(__NRFX_DOXYGEN__)
85 /** @brief Symbol indicating whether PDM clock control register is available. */
86 #define NRF_PDM_HAS_PDMCLKCTRL 1
87 #else
88 #define NRF_PDM_HAS_PDMCLKCTRL 0
89 #endif
90 
91 #if defined(PDM_PRESCALER_DIVISOR_Msk) || defined(__NRFX_DOXYGEN__)
92 /** @brief Symbol indicating whether PDM prescaler register is available. */
93 #define NRF_PDM_HAS_PRESCALER 1
94 #else
95 #define NRF_PDM_HAS_PRESCALER 0
96 #endif
97 
98 /** @brief Minimum value of PDM gain. */
99 #define NRF_PDM_GAIN_MINIMUM  0x00
100 /** @brief Default value of PDM gain. */
101 #define NRF_PDM_GAIN_DEFAULT  0x28
102 /** @brief Maximum value of PDM gain. */
103 #define NRF_PDM_GAIN_MAXIMUM  0x50
104 
105 #if NRF_PDM_HAS_PRESCALER
106 /** @brief Minimum value of PDM prescaler. */
107 #define NRF_PDM_PRESCALER_MIN PDM_PRESCALER_DIVISOR_Min
108 /** @brief Maximum value of PDM prescaler. */
109 #define NRF_PDM_PRESCALER_MAX PDM_PRESCALER_DIVISOR_Max
110 #endif
111 
112 /** @brief PDM gain type. */
113 typedef uint8_t nrf_pdm_gain_t;
114 
115 /** @brief PDM tasks. */
116 typedef enum
117 {
118 #if NRF_PDM_HAS_DMA_TASKS_EVENTS
119     NRF_PDM_TASK_START = offsetof(NRF_PDM_Type, TASKS_DMA.START), ///< Starts continuous PDM transfer.
120     NRF_PDM_TASK_STOP  = offsetof(NRF_PDM_Type, TASKS_DMA.STOP),  ///< Stops PDM transfer.
121 #else
122     NRF_PDM_TASK_START = offsetof(NRF_PDM_Type, TASKS_START),     ///< Starts continuous PDM transfer.
123     NRF_PDM_TASK_STOP  = offsetof(NRF_PDM_Type, TASKS_STOP),      ///< Stops PDM transfer.
124 #endif
125 } nrf_pdm_task_t;
126 
127 /** @brief PDM events. */
128 typedef enum
129 {
130     NRF_PDM_EVENT_STARTED = offsetof(NRF_PDM_Type, EVENTS_STARTED), ///< PDM transfer is started.
131     NRF_PDM_EVENT_STOPPED = offsetof(NRF_PDM_Type, EVENTS_STOPPED), ///< PDM transfer is finished.
132 #if NRF_PDM_HAS_DMA_TASKS_EVENTS
133     NRF_PDM_EVENT_END     = offsetof(NRF_PDM_Type, EVENTS_DMA.END), ///< The PDM has written the last sample specified by MAXCNT (or the last sample after a STOP task has been received) to Data RAM.
134 #else
135     NRF_PDM_EVENT_END     = offsetof(NRF_PDM_Type, EVENTS_END),     ///< The PDM has written the last sample specified by MAXCNT (or the last sample after a STOP task has been received) to Data RAM.
136 #endif
137 } nrf_pdm_event_t;
138 
139 /** @brief PDM interrupt masks. */
140 typedef enum
141 {
142     NRF_PDM_INT_STARTED = PDM_INTENSET_STARTED_Msk, ///< Interrupt on EVENTS_STARTED event.
143     NRF_PDM_INT_STOPPED = PDM_INTENSET_STOPPED_Msk, ///< Interrupt on EVENTS_STOPPED event.
144 #if NRF_PDM_HAS_DMA_TASKS_EVENTS
145     NRF_PDM_INT_END     = PDM_INTENSET_DMAEND_Msk   ///< Interrupt on EVENTS_END event.
146 #else
147     NRF_PDM_INT_END     = PDM_INTENSET_END_Msk      ///< Interrupt on EVENTS_END event.
148 #endif
149 } nrf_pdm_int_mask_t;
150 
151 #if NRF_PDM_HAS_PDMCLKCTRL
152 /** @brief PDM clock frequency. */
153 typedef enum
154 {
155     NRF_PDM_FREQ_1000K = PDM_PDMCLKCTRL_FREQ_1000K,   ///< PDM_CLK = 1.000 MHz.
156     NRF_PDM_FREQ_1032K = PDM_PDMCLKCTRL_FREQ_Default, ///< PDM_CLK = 1.032 MHz.
157     NRF_PDM_FREQ_1067K = PDM_PDMCLKCTRL_FREQ_1067K,   ///< PDM_CLK = 1.067 MHz.
158 #if defined(PDM_PDMCLKCTRL_FREQ_1231K) || defined(__NRFX_DOXYGEN__)
159     NRF_PDM_FREQ_1231K = PDM_PDMCLKCTRL_FREQ_1231K,   ///< PDM_CLK = 1.231 MHz.
160 #endif
161 #if defined(PDM_PDMCLKCTRL_FREQ_1280K) || defined(__NRFX_DOXYGEN__)
162     NRF_PDM_FREQ_1280K = PDM_PDMCLKCTRL_FREQ_1280K,   ///< PDM_CLK = 1.280 MHz.
163 #endif
164 #if defined(PDM_PDMCLKCTRL_FREQ_1333K) || defined(__NRFX_DOXYGEN__)
165     NRF_PDM_FREQ_1333K = PDM_PDMCLKCTRL_FREQ_1333K    ///< PDM_CLK = 1.333 MHz.
166 #endif
167 } nrf_pdm_freq_t;
168 #endif
169 
170 #if NRF_PDM_HAS_RATIO_CONFIG
171 /** @brief PDM ratio between PDM_CLK and output sample rate. */
172 typedef enum
173 {
174 #if defined(PDM_RATIO_RATIO_Ratio32)  || defined(__NRFX_DOXYGEN__)
175     NRF_PDM_RATIO_32X  = PDM_RATIO_RATIO_Ratio32,  ///< Ratio of 32.
176 #endif
177 #if defined(PDM_RATIO_RATIO_Ratio48)  || defined(__NRFX_DOXYGEN__)
178     NRF_PDM_RATIO_48X  = PDM_RATIO_RATIO_Ratio48,  ///< Ratio of 48.
179 #endif
180 #if defined(PDM_RATIO_RATIO_Ratio50)  || defined(__NRFX_DOXYGEN__)
181     NRF_PDM_RATIO_50X  = PDM_RATIO_RATIO_Ratio50,  ///< Ratio of 50.
182 #endif
183     NRF_PDM_RATIO_64X  = PDM_RATIO_RATIO_Ratio64,  ///< Ratio of 64.
184     NRF_PDM_RATIO_80X  = PDM_RATIO_RATIO_Ratio80,  ///< Ratio of 80.
185 #if defined(PDM_RATIO_RATIO_Ratio96)  || defined(__NRFX_DOXYGEN__)
186     NRF_PDM_RATIO_96X  = PDM_RATIO_RATIO_Ratio96,  ///< Ratio of 96.
187 #endif
188 #if defined(PDM_RATIO_RATIO_Ratio100) || defined(__NRFX_DOXYGEN__)
189     NRF_PDM_RATIO_100X = PDM_RATIO_RATIO_Ratio100, ///< Ratio of 100.
190 #endif
191 #if defined(PDM_RATIO_RATIO_Ratio128) || defined(__NRFX_DOXYGEN__)
192     NRF_PDM_RATIO_128X = PDM_RATIO_RATIO_Ratio128, ///< Ratio of 128.
193 #endif
194 } nrf_pdm_ratio_t;
195 #endif
196 
197 /** @brief PDM operation mode. */
198 typedef enum
199 {
200     NRF_PDM_MODE_STEREO = PDM_MODE_OPERATION_Stereo,  ///< Sample and store one pair (Left + Right) of 16-bit samples per RAM word.
201     NRF_PDM_MODE_MONO   = PDM_MODE_OPERATION_Mono     ///< Sample and store two successive Left samples (16 bit each) per RAM word.
202 } nrf_pdm_mode_t;
203 
204 /** @brief PDM sampling mode. */
205 typedef enum
206 {
207     NRF_PDM_EDGE_LEFTFALLING = PDM_MODE_EDGE_LeftFalling,  ///< Left (or mono) is sampled on falling edge of PDM_CLK.
208     NRF_PDM_EDGE_LEFTRISING  = PDM_MODE_EDGE_LeftRising    ///< Left (or mono) is sampled on rising edge of PDM_CLK.
209 } nrf_pdm_edge_t;
210 
211 #if NRF_PDM_HAS_MCLKCONFIG
212 /** @brief PDM master clock source selection. */
213 typedef enum
214 {
215     NRF_PDM_MCLKSRC_PCLK32M = PDM_MCLKCONFIG_SRC_PCLK32M, ///< 32MHz peripheral clock.
216     NRF_PDM_MCLKSRC_ACLK    = PDM_MCLKCONFIG_SRC_ACLK     ///< Audio PLL clock.
217 } nrf_pdm_mclksrc_t;
218 #endif
219 
220 /**
221  * @brief Function for triggering a PDM task.
222  *
223  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
224  * @param[in] task  PDM task.
225  */
226 NRF_STATIC_INLINE void nrf_pdm_task_trigger(NRF_PDM_Type * p_reg, nrf_pdm_task_t task);
227 
228 /**
229  * @brief Function for getting the address of a PDM task register.
230  *
231  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
232  * @param[in] task  PDM task.
233  *
234  * @return Address of the specified PDM task.
235  */
236 NRF_STATIC_INLINE uint32_t nrf_pdm_task_address_get(NRF_PDM_Type const * p_reg,
237                                                     nrf_pdm_task_t       task);
238 
239 /**
240  * @brief Function for retrieving the state of the PDM event.
241  *
242  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
243  * @param[in] event Event to be checked.
244  *
245  * @retval true  The event has been generated.
246  * @retval false The event has not been generated.
247  */
248 NRF_STATIC_INLINE bool nrf_pdm_event_check(NRF_PDM_Type const * p_reg, nrf_pdm_event_t event);
249 
250 /**
251  * @brief Function for clearing a PDM event.
252  *
253  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
254  * @param[in] event PDM event.
255  */
256 NRF_STATIC_INLINE void nrf_pdm_event_clear(NRF_PDM_Type * p_reg, nrf_pdm_event_t event);
257 
258 /**
259  * @brief Function for getting the address of a PDM event register.
260  *
261  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
262  * @param[in] event PDM event.
263  *
264  * @return Address of the specified PDM event.
265  */
266 NRF_STATIC_INLINE uint32_t nrf_pdm_event_address_get(NRF_PDM_Type const * p_reg,
267                                                      nrf_pdm_event_t      event);
268 
269 /**
270  * @brief Function for enabling PDM interrupts.
271  *
272  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
273  * @param[in] mask  Mask of interrupts to be enabled.
274  *                  Use @ref nrf_pdm_int_mask_t values for bit masking.
275  */
276 NRF_STATIC_INLINE void nrf_pdm_int_enable(NRF_PDM_Type * p_reg, uint32_t mask);
277 
278 /**
279  * @brief Function for checking if the specified interrupts are enabled.
280  *
281  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
282  * @param[in] mask  Mask of interrupts to be checked.
283  *                  Use @ref nrf_pdm_int_mask_t values for bit masking.
284  *
285  * @return Mask of enabled interrupts.
286  */
287 NRF_STATIC_INLINE uint32_t nrf_pdm_int_enable_check(NRF_PDM_Type const * p_reg, uint32_t mask);
288 
289 /**
290  * @brief Function for disabling interrupts.
291  *
292  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
293  * @param[in] mask  Mask of interrupts to be disabled.
294  *                  Use @ref nrf_pdm_int_mask_t values for bit masking.
295  */
296 NRF_STATIC_INLINE void nrf_pdm_int_disable(NRF_PDM_Type * p_reg, uint32_t mask);
297 
298 #if defined(DPPI_PRESENT) || defined(__NRFX_DOXYGEN__)
299 /**
300  * @brief Function for setting the subscribe configuration for a given
301  *        PDM task.
302  *
303  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
304  * @param[in] task    Task for which to set the configuration.
305  * @param[in] channel Channel through which to subscribe events.
306  */
307 NRF_STATIC_INLINE void nrf_pdm_subscribe_set(NRF_PDM_Type * p_reg,
308                                              nrf_pdm_task_t task,
309                                              uint8_t        channel);
310 
311 /**
312  * @brief Function for clearing the subscribe configuration for a given
313  *        PDM task.
314  *
315  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
316  * @param[in] task  Task for which to clear the configuration.
317  */
318 NRF_STATIC_INLINE void nrf_pdm_subscribe_clear(NRF_PDM_Type * p_reg, nrf_pdm_task_t task);
319 
320 /**
321  * @brief Function for setting the publish configuration for a given
322  *        PDM event.
323  *
324  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
325  * @param[in] event   Event for which to set the configuration.
326  * @param[in] channel Channel through which to publish the event.
327  */
328 NRF_STATIC_INLINE void nrf_pdm_publish_set(NRF_PDM_Type *  p_reg,
329                                            nrf_pdm_event_t event,
330                                            uint8_t         channel);
331 
332 /**
333  * @brief Function for clearing the publish configuration for a given
334  *        PDM event.
335  *
336  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
337  * @param[in] event Event for which to clear the configuration.
338  */
339 NRF_STATIC_INLINE void nrf_pdm_publish_clear(NRF_PDM_Type * p_reg, nrf_pdm_event_t event);
340 #endif // defined(DPPI_PRESENT) || defined(__NRFX_DOXYGEN__)
341 
342 /**
343  * @brief Function for enabling the PDM peripheral.
344  *
345  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
346  *
347  * The PDM peripheral must be enabled before use.
348  */
349 NRF_STATIC_INLINE void nrf_pdm_enable(NRF_PDM_Type * p_reg);
350 
351 /**
352  * @brief Function for disabling the PDM peripheral.
353  *
354  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
355  */
356 NRF_STATIC_INLINE void nrf_pdm_disable(NRF_PDM_Type * p_reg);
357 
358 /**
359  * @brief Function for checking if the PDM peripheral is enabled.
360  *
361  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
362  *
363  * @retval true  The PDM peripheral is enabled.
364  * @retval false The PDM peripheral is not enabled.
365  */
366 NRF_STATIC_INLINE bool nrf_pdm_enable_check(NRF_PDM_Type const * p_reg);
367 
368 /**
369  * @brief Function for setting the PDM operation mode.
370  *
371  * @param[in] p_reg    Pointer to the structure of registers of the peripheral.
372  * @param[in] pdm_mode PDM operation mode.
373  * @param[in] pdm_edge PDM sampling mode.
374  */
375 NRF_STATIC_INLINE void nrf_pdm_mode_set(NRF_PDM_Type * p_reg,
376                                         nrf_pdm_mode_t pdm_mode,
377                                         nrf_pdm_edge_t pdm_edge);
378 
379 /**
380  * @brief Function for getting the PDM operation mode.
381  *
382  * @param[in]  p_reg      Pointer to the structure of registers of the peripheral.
383  * @param[out] p_pdm_mode PDM operation mode.
384  * @param[out] p_pdm_edge PDM sampling mode.
385  */
386 NRF_STATIC_INLINE void nrf_pdm_mode_get(NRF_PDM_Type const * p_reg,
387                                         nrf_pdm_mode_t *     p_pdm_mode,
388                                         nrf_pdm_edge_t *     p_pdm_edge);
389 
390 #if NRF_PDM_HAS_PDMCLKCTRL
391 /**
392  * @brief Function for setting the PDM clock frequency.
393  *
394  * @param[in] p_reg    Pointer to the structure of registers of the peripheral.
395  * @param[in] pdm_freq PDM clock frequency.
396  */
397 NRF_STATIC_INLINE void nrf_pdm_clock_set(NRF_PDM_Type * p_reg, nrf_pdm_freq_t pdm_freq);
398 
399 /**
400  * @brief Function for getting the PDM clock frequency.
401  *
402  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
403  *
404  * @return PDM clock frequency.
405  */
406 NRF_STATIC_INLINE nrf_pdm_freq_t nrf_pdm_clock_get(NRF_PDM_Type const * p_reg);
407 #endif
408 
409 #if NRF_PDM_HAS_PRESCALER
410 /**
411  * @brief Function for setting the PDM prescaler divisor.
412  *
413  * @param[in] p_reg     Pointer to the structure of registers of the peripheral.
414  * @param[in] prescaler PDM prescaler divisor.
415  */
416 NRF_STATIC_INLINE void nrf_pdm_prescaler_set(NRF_PDM_Type * p_reg, uint32_t prescaler);
417 
418 /**
419  * @brief Function for getting the PDM prescaler divisor.
420  *
421  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
422  *
423  * @return PDM prescaler divisor.
424  */
425 NRF_STATIC_INLINE uint32_t nrf_pdm_prescaler_get(NRF_PDM_Type const * p_reg);
426 #endif
427 
428 /**
429  * @brief Function for setting up the PDM pins.
430  *
431  * @param[in] p_reg    Pointer to the structure of registers of the peripheral.
432  * @param[in] psel_clk CLK pin number.
433  * @param[in] psel_din DIN pin number.
434  */
435 NRF_STATIC_INLINE void nrf_pdm_psel_connect(NRF_PDM_Type * p_reg,
436                                             uint32_t       psel_clk,
437                                             uint32_t       psel_din);
438 
439 /**
440  * @brief Function for setting the CLK pin.
441  *
442  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
443  * @param[in] pin   CLK pin number.
444  */
445 NRF_STATIC_INLINE void nrf_pdm_clk_pin_set(NRF_PDM_Type * p_reg, uint32_t pin);
446 
447 /**
448  * @brief Function for setting the DIN pin.
449  *
450  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
451  * @param[in] pin   DIN pin number.
452  */
453 NRF_STATIC_INLINE void nrf_pdm_din_pin_set(NRF_PDM_Type * p_reg, uint32_t pin);
454 
455 /**
456  * @brief Function for getting the CLK pin selection.
457  *
458  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
459  *
460  * @return CLK pin selection;
461  */
462 NRF_STATIC_INLINE uint32_t nrf_pdm_clk_pin_get(NRF_PDM_Type const * p_reg);
463 
464 /**
465  * @brief Function for getting the DIN pin selection.
466  *
467  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
468  *
469  * @return DIN pin selection;
470  */
471 NRF_STATIC_INLINE uint32_t nrf_pdm_din_pin_get(NRF_PDM_Type const * p_reg);
472 
473 /**
474  * @brief Function for disconnecting the PDM pins.
475  *
476  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
477  */
478 NRF_STATIC_INLINE void nrf_pdm_psel_disconnect(NRF_PDM_Type * p_reg);
479 
480 /**
481  * @brief Function for setting the PDM gain.
482  *
483  * @param[in] p_reg  Pointer to the structure of registers of the peripheral.
484  * @param[in] gain_l Left channel gain.
485  * @param[in] gain_r Right channel gain.
486  */
487 NRF_STATIC_INLINE void nrf_pdm_gain_set(NRF_PDM_Type * p_reg,
488                                         nrf_pdm_gain_t gain_l,
489                                         nrf_pdm_gain_t gain_r);
490 
491 /**
492  * @brief Function for getting the PDM gain.
493  *
494  * @param[in]  p_reg    Pointer to the structure of registers of the peripheral.
495  * @param[out] p_gain_l Left channel gain.
496  * @param[out] p_gain_r Right channel gain.
497  */
498 NRF_STATIC_INLINE void nrf_pdm_gain_get(NRF_PDM_Type const * p_reg,
499                                         nrf_pdm_gain_t *     p_gain_l,
500                                         nrf_pdm_gain_t *     p_gain_r);
501 
502 /**
503  * @brief Function for setting the PDM sample buffer.
504  *
505  * The amount of allocated RAM depends on the operation mode.
506  * - For stereo mode: N 32-bit words.
507  * - For mono mode: Ceil(N/2) 32-bit words.
508  *
509  * @param[in] p_reg    Pointer to the structure of registers of the peripheral.
510  * @param[in] p_buffer Pointer to the RAM address where samples are to be written with EasyDMA.
511  * @param[in] num      Number of samples to allocate memory for in EasyDMA mode.
512  */
513 NRF_STATIC_INLINE void nrf_pdm_buffer_set(NRF_PDM_Type * p_reg, uint32_t * p_buffer, uint32_t num);
514 
515 /**
516  * @brief Function for getting the current PDM sample buffer address.
517  *
518  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
519  *
520  * @return Pointer to the current sample buffer.
521  */
522 NRF_STATIC_INLINE uint32_t * nrf_pdm_buffer_get(NRF_PDM_Type const * p_reg);
523 
524 #if NRF_PDM_HAS_RATIO_CONFIG
525 /**
526  * @brief Function for setting ratio between PDM_CLK and output sample rate.
527  *
528  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
529  * @param[in] ratio Ratio between PDM_CLK and output sample rate.
530  */
531 NRF_STATIC_INLINE void nrf_pdm_ratio_set(NRF_PDM_Type * p_reg, nrf_pdm_ratio_t ratio);
532 #endif
533 
534 #if NRF_PDM_HAS_MCLKCONFIG
535 /**
536  * @brief Function for configuring PDM master clock source.
537  *
538  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
539  * @param[in] mclksrc Master Clock source selection.
540  */
541 NRF_STATIC_INLINE void nrf_pdm_mclksrc_configure(NRF_PDM_Type * p_reg, nrf_pdm_mclksrc_t mclksrc);
542 #endif
543 
544 #ifndef NRF_DECLARE_ONLY
nrf_pdm_task_trigger(NRF_PDM_Type * p_reg,nrf_pdm_task_t task)545 NRF_STATIC_INLINE void nrf_pdm_task_trigger(NRF_PDM_Type * p_reg, nrf_pdm_task_t task)
546 {
547     *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)task)) = 0x1UL;
548 }
549 
nrf_pdm_task_address_get(NRF_PDM_Type const * p_reg,nrf_pdm_task_t task)550 NRF_STATIC_INLINE uint32_t nrf_pdm_task_address_get(NRF_PDM_Type const * p_reg, nrf_pdm_task_t task)
551 {
552     return nrf_task_event_address_get(p_reg, task);
553 }
554 
nrf_pdm_event_check(NRF_PDM_Type const * p_reg,nrf_pdm_event_t event)555 NRF_STATIC_INLINE bool nrf_pdm_event_check(NRF_PDM_Type const * p_reg, nrf_pdm_event_t event)
556 {
557     return nrf_event_check(p_reg, event);
558 }
559 
nrf_pdm_event_clear(NRF_PDM_Type * p_reg,nrf_pdm_event_t event)560 NRF_STATIC_INLINE void nrf_pdm_event_clear(NRF_PDM_Type * p_reg, nrf_pdm_event_t event)
561 {
562     *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL;
563     nrf_event_readback((uint8_t *)p_reg + (uint32_t)event);
564 }
565 
nrf_pdm_event_address_get(NRF_PDM_Type const * p_reg,nrf_pdm_event_t event)566 NRF_STATIC_INLINE uint32_t nrf_pdm_event_address_get(NRF_PDM_Type const * p_reg,
567                                                      nrf_pdm_event_t      event)
568 {
569     return nrf_task_event_address_get(p_reg, event);
570 }
571 
nrf_pdm_int_enable(NRF_PDM_Type * p_reg,uint32_t mask)572 NRF_STATIC_INLINE void nrf_pdm_int_enable(NRF_PDM_Type * p_reg, uint32_t mask)
573 {
574     p_reg->INTENSET = mask;
575 }
576 
nrf_pdm_int_enable_check(NRF_PDM_Type const * p_reg,uint32_t mask)577 NRF_STATIC_INLINE uint32_t nrf_pdm_int_enable_check(NRF_PDM_Type const * p_reg, uint32_t mask)
578 {
579     return p_reg->INTENSET & mask;
580 }
581 
nrf_pdm_int_disable(NRF_PDM_Type * p_reg,uint32_t mask)582 NRF_STATIC_INLINE void nrf_pdm_int_disable(NRF_PDM_Type * p_reg, uint32_t mask)
583 {
584     p_reg->INTENCLR = mask;
585 }
586 
587 #if defined(DPPI_PRESENT)
nrf_pdm_subscribe_set(NRF_PDM_Type * p_reg,nrf_pdm_task_t task,uint8_t channel)588 NRF_STATIC_INLINE void nrf_pdm_subscribe_set(NRF_PDM_Type * p_reg,
589                                              nrf_pdm_task_t task,
590                                              uint8_t        channel)
591 {
592     *((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) task + 0x80uL)) =
593             ((uint32_t)channel | NRF_SUBSCRIBE_PUBLISH_ENABLE);
594 }
595 
nrf_pdm_subscribe_clear(NRF_PDM_Type * p_reg,nrf_pdm_task_t task)596 NRF_STATIC_INLINE void nrf_pdm_subscribe_clear(NRF_PDM_Type * p_reg, nrf_pdm_task_t task)
597 {
598     *((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) task + 0x80uL)) = 0;
599 }
600 
nrf_pdm_publish_set(NRF_PDM_Type * p_reg,nrf_pdm_event_t event,uint8_t channel)601 NRF_STATIC_INLINE void nrf_pdm_publish_set(NRF_PDM_Type *  p_reg,
602                                            nrf_pdm_event_t event,
603                                            uint8_t         channel)
604 {
605     *((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) event + 0x80uL)) =
606             ((uint32_t)channel | NRF_SUBSCRIBE_PUBLISH_ENABLE);
607 }
608 
nrf_pdm_publish_clear(NRF_PDM_Type * p_reg,nrf_pdm_event_t event)609 NRF_STATIC_INLINE void nrf_pdm_publish_clear(NRF_PDM_Type * p_reg, nrf_pdm_event_t event)
610 {
611     *((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) event + 0x80uL)) = 0;
612 }
613 #endif // defined(DPPI_PRESENT)
614 
nrf_pdm_enable(NRF_PDM_Type * p_reg)615 NRF_STATIC_INLINE void nrf_pdm_enable(NRF_PDM_Type * p_reg)
616 {
617     p_reg->ENABLE = (PDM_ENABLE_ENABLE_Enabled << PDM_ENABLE_ENABLE_Pos);
618 }
619 
nrf_pdm_disable(NRF_PDM_Type * p_reg)620 NRF_STATIC_INLINE void nrf_pdm_disable(NRF_PDM_Type * p_reg)
621 {
622     p_reg->ENABLE = (PDM_ENABLE_ENABLE_Disabled << PDM_ENABLE_ENABLE_Pos);
623 }
624 
nrf_pdm_enable_check(NRF_PDM_Type const * p_reg)625 NRF_STATIC_INLINE bool nrf_pdm_enable_check(NRF_PDM_Type const * p_reg)
626 {
627     return (p_reg->ENABLE == (PDM_ENABLE_ENABLE_Enabled << PDM_ENABLE_ENABLE_Pos));
628 }
629 
nrf_pdm_mode_set(NRF_PDM_Type * p_reg,nrf_pdm_mode_t pdm_mode,nrf_pdm_edge_t pdm_edge)630 NRF_STATIC_INLINE void nrf_pdm_mode_set(NRF_PDM_Type * p_reg,
631                                         nrf_pdm_mode_t pdm_mode,
632                                         nrf_pdm_edge_t pdm_edge)
633 {
634     p_reg->MODE = ((pdm_mode << PDM_MODE_OPERATION_Pos) & PDM_MODE_OPERATION_Msk)
635                     | ((pdm_edge << PDM_MODE_EDGE_Pos) & PDM_MODE_EDGE_Msk);
636 }
637 
nrf_pdm_mode_get(NRF_PDM_Type const * p_reg,nrf_pdm_mode_t * p_pdm_mode,nrf_pdm_edge_t * p_pdm_edge)638 NRF_STATIC_INLINE void nrf_pdm_mode_get(NRF_PDM_Type const * p_reg,
639                                         nrf_pdm_mode_t *     p_pdm_mode,
640                                         nrf_pdm_edge_t *     p_pdm_edge)
641 {
642     uint32_t mode = p_reg->MODE;
643     *p_pdm_mode = (nrf_pdm_mode_t)((mode & PDM_MODE_OPERATION_Msk ) >> PDM_MODE_OPERATION_Pos);
644     *p_pdm_edge = (nrf_pdm_edge_t)((mode & PDM_MODE_EDGE_Msk ) >> PDM_MODE_EDGE_Pos);
645 }
646 
647 #if NRF_PDM_HAS_PDMCLKCTRL
nrf_pdm_clock_set(NRF_PDM_Type * p_reg,nrf_pdm_freq_t pdm_freq)648 NRF_STATIC_INLINE void nrf_pdm_clock_set(NRF_PDM_Type * p_reg, nrf_pdm_freq_t pdm_freq)
649 {
650     p_reg->PDMCLKCTRL = ((pdm_freq << PDM_PDMCLKCTRL_FREQ_Pos) & PDM_PDMCLKCTRL_FREQ_Msk);
651 }
652 
nrf_pdm_clock_get(NRF_PDM_Type const * p_reg)653 NRF_STATIC_INLINE nrf_pdm_freq_t nrf_pdm_clock_get(NRF_PDM_Type const * p_reg)
654 {
655      return (nrf_pdm_freq_t) ((p_reg->PDMCLKCTRL << PDM_PDMCLKCTRL_FREQ_Pos) &
656                               PDM_PDMCLKCTRL_FREQ_Msk);
657 }
658 #endif
659 
660 #if NRF_PDM_HAS_PRESCALER
nrf_pdm_prescaler_set(NRF_PDM_Type * p_reg,uint32_t prescaler)661 NRF_STATIC_INLINE void nrf_pdm_prescaler_set(NRF_PDM_Type * p_reg, uint32_t prescaler)
662 {
663     NRFX_ASSERT(prescaler >= NRF_PDM_PRESCALER_MIN);
664     NRFX_ASSERT(prescaler <= NRF_PDM_PRESCALER_MAX);
665     p_reg->PRESCALER = prescaler;
666 }
667 
nrf_pdm_prescaler_get(NRF_PDM_Type const * p_reg)668 NRF_STATIC_INLINE uint32_t nrf_pdm_prescaler_get(NRF_PDM_Type const * p_reg)
669 {
670     return p_reg->PRESCALER;
671 }
672 #endif
673 
nrf_pdm_psel_connect(NRF_PDM_Type * p_reg,uint32_t psel_clk,uint32_t psel_din)674 NRF_STATIC_INLINE void nrf_pdm_psel_connect(NRF_PDM_Type * p_reg,
675                                             uint32_t       psel_clk,
676                                             uint32_t       psel_din)
677 {
678     p_reg->PSEL.CLK = psel_clk;
679     p_reg->PSEL.DIN = psel_din;
680 }
681 
nrf_pdm_clk_pin_set(NRF_PDM_Type * p_reg,uint32_t pin)682 NRF_STATIC_INLINE void nrf_pdm_clk_pin_set(NRF_PDM_Type * p_reg, uint32_t pin)
683 {
684     p_reg->PSEL.CLK = pin;
685 }
686 
nrf_pdm_din_pin_set(NRF_PDM_Type * p_reg,uint32_t pin)687 NRF_STATIC_INLINE void nrf_pdm_din_pin_set(NRF_PDM_Type * p_reg, uint32_t pin)
688 {
689     p_reg->PSEL.DIN = pin;
690 }
691 
nrf_pdm_clk_pin_get(NRF_PDM_Type const * p_reg)692 NRF_STATIC_INLINE uint32_t nrf_pdm_clk_pin_get(NRF_PDM_Type const * p_reg)
693 {
694     return p_reg->PSEL.CLK;
695 }
696 
nrf_pdm_din_pin_get(NRF_PDM_Type const * p_reg)697 NRF_STATIC_INLINE uint32_t nrf_pdm_din_pin_get(NRF_PDM_Type const * p_reg)
698 {
699     return p_reg->PSEL.DIN;
700 }
701 
nrf_pdm_psel_disconnect(NRF_PDM_Type * p_reg)702 NRF_STATIC_INLINE void nrf_pdm_psel_disconnect(NRF_PDM_Type * p_reg)
703 {
704     p_reg->PSEL.CLK = ((PDM_PSEL_CLK_CONNECT_Disconnected << PDM_PSEL_CLK_CONNECT_Pos)
705                          & PDM_PSEL_CLK_CONNECT_Msk);
706     p_reg->PSEL.DIN = ((PDM_PSEL_DIN_CONNECT_Disconnected << PDM_PSEL_DIN_CONNECT_Pos)
707                          & PDM_PSEL_DIN_CONNECT_Msk);
708 }
709 
nrf_pdm_gain_set(NRF_PDM_Type * p_reg,nrf_pdm_gain_t gain_l,nrf_pdm_gain_t gain_r)710 NRF_STATIC_INLINE void nrf_pdm_gain_set(NRF_PDM_Type * p_reg,
711                                         nrf_pdm_gain_t gain_l,
712                                         nrf_pdm_gain_t gain_r)
713 {
714     p_reg->GAINL = gain_l;
715     p_reg->GAINR = gain_r;
716 }
717 
nrf_pdm_gain_get(NRF_PDM_Type const * p_reg,nrf_pdm_gain_t * p_gain_l,nrf_pdm_gain_t * p_gain_r)718 NRF_STATIC_INLINE void nrf_pdm_gain_get(NRF_PDM_Type const * p_reg,
719                                         nrf_pdm_gain_t *     p_gain_l,
720                                         nrf_pdm_gain_t *     p_gain_r)
721 {
722     *p_gain_l = (nrf_pdm_gain_t)p_reg->GAINL;
723     *p_gain_r = (nrf_pdm_gain_t)p_reg->GAINR;
724 }
725 
nrf_pdm_buffer_set(NRF_PDM_Type * p_reg,uint32_t * p_buffer,uint32_t num)726 NRF_STATIC_INLINE void nrf_pdm_buffer_set(NRF_PDM_Type * p_reg, uint32_t * p_buffer, uint32_t num)
727 {
728     p_reg->SAMPLE.PTR = (uint32_t)p_buffer;
729 #if defined(DMA_BUFFER_UNIFIED_BYTE_ACCESS)
730     p_reg->SAMPLE.MAXCNT = num * sizeof(int16_t);
731 #else
732     p_reg->SAMPLE.MAXCNT = num;
733 #endif
734 }
735 
nrf_pdm_buffer_get(NRF_PDM_Type const * p_reg)736 NRF_STATIC_INLINE uint32_t * nrf_pdm_buffer_get(NRF_PDM_Type const * p_reg)
737 {
738     return (uint32_t *)p_reg->SAMPLE.PTR;
739 }
740 
741 #if NRF_PDM_HAS_RATIO_CONFIG
nrf_pdm_ratio_set(NRF_PDM_Type * p_reg,nrf_pdm_ratio_t ratio)742 NRF_STATIC_INLINE void nrf_pdm_ratio_set(NRF_PDM_Type * p_reg, nrf_pdm_ratio_t ratio)
743 {
744     p_reg->RATIO = ratio;
745 }
746 #endif
747 
748 #if NRF_PDM_HAS_MCLKCONFIG
nrf_pdm_mclksrc_configure(NRF_PDM_Type * p_reg,nrf_pdm_mclksrc_t mclksrc)749 NRF_STATIC_INLINE void nrf_pdm_mclksrc_configure(NRF_PDM_Type * p_reg, nrf_pdm_mclksrc_t mclksrc)
750 {
751     p_reg->MCLKCONFIG = mclksrc;
752 }
753 #endif
754 
755 #endif // NRF_DECLARE_ONLY
756 /** @} */
757 
758 #ifdef __cplusplus
759 }
760 #endif
761 
762 #endif // NRF_PDM_H_
763