xref: /nrf52832-nimble/nordic/nrfx/hal/nrf_i2s.h (revision 150812a83cab50279bd772ef6db1bfaf255f2c5b)
1 /*
2  * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this
9  *    list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its
16  *    contributors may be used to endorse or promote products derived from this
17  *    software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifndef NRF_I2S_H__
33 #define NRF_I2S_H__
34 
35 #include <nrfx.h>
36 
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40 
41 /**
42  * @defgroup nrf_i2s_hal I2S HAL
43  * @{
44  * @ingroup nrf_i2s
45  * @brief   Hardware access layer for managing the Inter-IC Sound (I2S) peripheral.
46  */
47 
48 /**
49  * @brief This value can be provided as a parameter for the @ref nrf_i2s_pins_set
50  *        function call to specify that a given I2S signal (SDOUT, SDIN, or MCK)
51  *        shall not be connected to a physical pin.
52  */
53 #define NRF_I2S_PIN_NOT_CONNECTED  0xFFFFFFFF
54 
55 
56 /**
57  * @brief I2S tasks.
58  */
59 typedef enum
60 {
61     /*lint -save -e30*/
62     NRF_I2S_TASK_START = offsetof(NRF_I2S_Type, TASKS_START), ///< Starts continuous I2S transfer. Also starts the MCK generator if this is enabled.
63     NRF_I2S_TASK_STOP  = offsetof(NRF_I2S_Type, TASKS_STOP)   ///< Stops I2S transfer. Also stops the MCK generator.
64     /*lint -restore*/
65 } nrf_i2s_task_t;
66 
67 /**
68  * @brief I2S events.
69  */
70 typedef enum
71 {
72     /*lint -save -e30*/
73     NRF_I2S_EVENT_RXPTRUPD = offsetof(NRF_I2S_Type, EVENTS_RXPTRUPD), ///< The RXD.PTR register has been copied to internal double-buffers.
74     NRF_I2S_EVENT_TXPTRUPD = offsetof(NRF_I2S_Type, EVENTS_TXPTRUPD), ///< The TXD.PTR register has been copied to internal double-buffers.
75     NRF_I2S_EVENT_STOPPED  = offsetof(NRF_I2S_Type, EVENTS_STOPPED)   ///< I2S transfer stopped.
76     /*lint -restore*/
77 } nrf_i2s_event_t;
78 
79 /**
80  * @brief I2S interrupts.
81  */
82 typedef enum
83 {
84     NRF_I2S_INT_RXPTRUPD_MASK = I2S_INTENSET_RXPTRUPD_Msk, ///< Interrupt on RXPTRUPD event.
85     NRF_I2S_INT_TXPTRUPD_MASK = I2S_INTENSET_TXPTRUPD_Msk, ///< Interrupt on TXPTRUPD event.
86     NRF_I2S_INT_STOPPED_MASK  = I2S_INTENSET_STOPPED_Msk   ///< Interrupt on STOPPED event.
87 } nrf_i2s_int_mask_t;
88 
89 /**
90  * @brief I2S modes of operation.
91  */
92 typedef enum
93 {
94     NRF_I2S_MODE_MASTER = I2S_CONFIG_MODE_MODE_Master, ///< Master mode.
95     NRF_I2S_MODE_SLAVE  = I2S_CONFIG_MODE_MODE_Slave   ///< Slave mode.
96 } nrf_i2s_mode_t;
97 
98 /**
99  * @brief I2S master clock generator settings.
100  */
101 typedef enum
102 {
103     NRF_I2S_MCK_DISABLED  = 0,                                       ///< MCK disabled.
104 #if defined(I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV2) || defined(__NRFX_DOXYGEN__)
105     // [conversion to 'int' needed to prevent compilers from complaining
106     //  that the provided value (0x80000000UL) is out of range of "int"]
107     NRF_I2S_MCK_32MDIV2   = (int)I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV2, ///< 32 MHz / 2 = 16.0 MHz.
108 #endif
109 #if defined(I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV3) || defined(__NRFX_DOXYGEN__)
110     NRF_I2S_MCK_32MDIV3   = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV3,      ///< 32 MHz / 3 = 10.6666667 MHz.
111 #endif
112 #if defined(I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV4) || defined(__NRFX_DOXYGEN__)
113     NRF_I2S_MCK_32MDIV4   = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV4,      ///< 32 MHz / 4 = 8.0 MHz.
114 #endif
115 #if defined(I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV5) || defined(__NRFX_DOXYGEN__)
116     NRF_I2S_MCK_32MDIV5   = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV5,      ///< 32 MHz / 5 = 6.4 MHz.
117 #endif
118 #if defined(I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV6) || defined(__NRFX_DOXYGEN__)
119     NRF_I2S_MCK_32MDIV6   = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV6,      ///< 32 MHz / 6 = 5.3333333 MHz.
120 #endif
121     NRF_I2S_MCK_32MDIV8   = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV8,      ///< 32 MHz / 8 = 4.0 MHz.
122     NRF_I2S_MCK_32MDIV10  = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV10,     ///< 32 MHz / 10 = 3.2 MHz.
123     NRF_I2S_MCK_32MDIV11  = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV11,     ///< 32 MHz / 11 = 2.9090909 MHz.
124     NRF_I2S_MCK_32MDIV15  = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV15,     ///< 32 MHz / 15 = 2.1333333 MHz.
125     NRF_I2S_MCK_32MDIV16  = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV16,     ///< 32 MHz / 16 = 2.0 MHz.
126     NRF_I2S_MCK_32MDIV21  = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV21,     ///< 32 MHz / 21 = 1.5238095 MHz.
127     NRF_I2S_MCK_32MDIV23  = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV23,     ///< 32 MHz / 23 = 1.3913043 MHz.
128     NRF_I2S_MCK_32MDIV31  = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV31,     ///< 32 MHz / 31 = 1.0322581 MHz.
129     NRF_I2S_MCK_32MDIV42  = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV42,     ///< 32 MHz / 42 = 0.7619048 MHz.
130     NRF_I2S_MCK_32MDIV63  = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV63,     ///< 32 MHz / 63 = 0.5079365 MHz.
131     NRF_I2S_MCK_32MDIV125 = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV125     ///< 32 MHz / 125 = 0.256 MHz.
132 } nrf_i2s_mck_t;
133 
134 /**
135  * @brief I2S MCK/LRCK ratios.
136  */
137 typedef enum
138 {
139     NRF_I2S_RATIO_32X  = I2S_CONFIG_RATIO_RATIO_32X,  ///< LRCK = MCK / 32.
140     NRF_I2S_RATIO_48X  = I2S_CONFIG_RATIO_RATIO_48X,  ///< LRCK = MCK / 48.
141     NRF_I2S_RATIO_64X  = I2S_CONFIG_RATIO_RATIO_64X,  ///< LRCK = MCK / 64.
142     NRF_I2S_RATIO_96X  = I2S_CONFIG_RATIO_RATIO_96X,  ///< LRCK = MCK / 96.
143     NRF_I2S_RATIO_128X = I2S_CONFIG_RATIO_RATIO_128X, ///< LRCK = MCK / 128.
144     NRF_I2S_RATIO_192X = I2S_CONFIG_RATIO_RATIO_192X, ///< LRCK = MCK / 192.
145     NRF_I2S_RATIO_256X = I2S_CONFIG_RATIO_RATIO_256X, ///< LRCK = MCK / 256.
146     NRF_I2S_RATIO_384X = I2S_CONFIG_RATIO_RATIO_384X, ///< LRCK = MCK / 384.
147     NRF_I2S_RATIO_512X = I2S_CONFIG_RATIO_RATIO_512X  ///< LRCK = MCK / 512.
148 } nrf_i2s_ratio_t;
149 
150 /**
151  * @brief I2S sample widths.
152  */
153 typedef enum
154 {
155     NRF_I2S_SWIDTH_8BIT  = I2S_CONFIG_SWIDTH_SWIDTH_8Bit,  ///< 8 bit.
156     NRF_I2S_SWIDTH_16BIT = I2S_CONFIG_SWIDTH_SWIDTH_16Bit, ///< 16 bit.
157     NRF_I2S_SWIDTH_24BIT = I2S_CONFIG_SWIDTH_SWIDTH_24Bit  ///< 24 bit.
158 } nrf_i2s_swidth_t;
159 
160 /**
161  * @brief I2S alignments of sample within a frame.
162  */
163 typedef enum
164 {
165     NRF_I2S_ALIGN_LEFT  = I2S_CONFIG_ALIGN_ALIGN_Left, ///< Left-aligned.
166     NRF_I2S_ALIGN_RIGHT = I2S_CONFIG_ALIGN_ALIGN_Right ///< Right-aligned.
167 } nrf_i2s_align_t;
168 
169 /**
170  * @brief I2S frame formats.
171  */
172 typedef enum
173 {
174     NRF_I2S_FORMAT_I2S     = I2S_CONFIG_FORMAT_FORMAT_I2S,    ///< Original I2S format.
175     NRF_I2S_FORMAT_ALIGNED = I2S_CONFIG_FORMAT_FORMAT_Aligned ///< Alternate (left- or right-aligned) format.
176 } nrf_i2s_format_t;
177 
178 /**
179  * @brief I2S enabled channels.
180  */
181 typedef enum
182 {
183     NRF_I2S_CHANNELS_STEREO = I2S_CONFIG_CHANNELS_CHANNELS_Stereo, ///< Stereo.
184     NRF_I2S_CHANNELS_LEFT   = I2S_CONFIG_CHANNELS_CHANNELS_Left,   ///< Left only.
185     NRF_I2S_CHANNELS_RIGHT  = I2S_CONFIG_CHANNELS_CHANNELS_Right   ///< Right only.
186 } nrf_i2s_channels_t;
187 
188 
189 /**
190  * @brief Function for activating a specific I2S task.
191  *
192  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
193  * @param[in] task  Task to activate.
194  */
195 __STATIC_INLINE void nrf_i2s_task_trigger(NRF_I2S_Type * p_reg,
196                                           nrf_i2s_task_t task);
197 
198 /**
199  * @brief Function for getting the address of a specific I2S task register.
200  *
201  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
202  * @param[in] task  Requested task.
203  *
204  * @return Address of the specified task register.
205  */
206 __STATIC_INLINE uint32_t nrf_i2s_task_address_get(NRF_I2S_Type const * p_reg,
207                                                   nrf_i2s_task_t       task);
208 
209 /**
210  * @brief Function for clearing a specific I2S event.
211  *
212  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
213  * @param[in] event Event to clear.
214  */
215 __STATIC_INLINE void nrf_i2s_event_clear(NRF_I2S_Type * p_reg,
216                                          nrf_i2s_event_t event);
217 
218 /**
219  * @brief Function for checking the state of a specific I2S event.
220  *
221  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
222  * @param[in] event Event to check.
223  *
224  * @retval true  If the event is set.
225  * @retval false If the event is not set.
226  */
227 __STATIC_INLINE bool nrf_i2s_event_check(NRF_I2S_Type const * p_reg,
228                                          nrf_i2s_event_t      event);
229 
230 /**
231  * @brief Function for getting the address of a specific I2S event register.
232  *
233  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
234  * @param[in] event Requested event.
235  *
236  * @return Address of the specified event register.
237  */
238 __STATIC_INLINE uint32_t nrf_i2s_event_address_get(NRF_I2S_Type const * p_reg,
239                                                    nrf_i2s_event_t      event);
240 
241 /**
242  * @brief Function for enabling specified interrupts.
243  *
244  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
245  * @param[in] mask  Interrupts to enable.
246  */
247 __STATIC_INLINE void nrf_i2s_int_enable(NRF_I2S_Type * p_reg, uint32_t mask);
248 
249 /**
250  * @brief Function for disabling specified interrupts.
251  *
252  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
253  * @param[in] mask  Interrupts to disable.
254  */
255 __STATIC_INLINE void nrf_i2s_int_disable(NRF_I2S_Type * p_reg, uint32_t mask);
256 
257 /**
258  * @brief Function for retrieving the state of a given interrupt.
259  *
260  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
261  * @param[in] i2s_int Interrupt to check.
262  *
263  * @retval true  If the interrupt is enabled.
264  * @retval false If the interrupt is not enabled.
265  */
266 __STATIC_INLINE bool nrf_i2s_int_enable_check(NRF_I2S_Type const * p_reg,
267                                               nrf_i2s_int_mask_t   i2s_int);
268 
269 /**
270  * @brief Function for enabling the I2S peripheral.
271  *
272  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
273  */
274 __STATIC_INLINE void nrf_i2s_enable(NRF_I2S_Type * p_reg);
275 
276 /**
277  * @brief Function for disabling the I2S peripheral.
278  *
279  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
280  */
281 __STATIC_INLINE void nrf_i2s_disable(NRF_I2S_Type * p_reg);
282 
283 #if defined(DPPI_PRESENT) || defined(__NRFX_DOXYGEN__)
284 /**
285  * @brief Function for setting the subscribe configuration for a given
286  *        I2S task.
287  *
288  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
289  * @param[in] task    Task for which to set the configuration.
290  * @param[in] channel Channel through which to subscribe events.
291  */
292 __STATIC_INLINE void nrf_i2s_subscribe_set(NRF_I2S_Type * p_reg,
293                                            nrf_i2s_task_t task,
294                                            uint8_t        channel);
295 
296 /**
297  * @brief Function for clearing the subscribe configuration for a given
298  *        I2S task.
299  *
300  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
301  * @param[in] task  Task for which to clear the configuration.
302  */
303 __STATIC_INLINE void nrf_i2s_subscribe_clear(NRF_I2S_Type * p_reg,
304                                              nrf_i2s_task_t task);
305 
306 /**
307  * @brief Function for setting the publish configuration for a given
308  *        I2S event.
309  *
310  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
311  * @param[in] event   Event for which to set the configuration.
312  * @param[in] channel Channel through which to publish the event.
313  */
314 __STATIC_INLINE void nrf_i2s_publish_set(NRF_I2S_Type *  p_reg,
315                                          nrf_i2s_event_t event,
316                                          uint8_t         channel);
317 
318 /**
319  * @brief Function for clearing the publish configuration for a given
320  *        I2S event.
321  *
322  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
323  * @param[in] event Event for which to clear the configuration.
324  */
325 __STATIC_INLINE void nrf_i2s_publish_clear(NRF_I2S_Type *  p_reg,
326                                            nrf_i2s_event_t event);
327 #endif // defined(DPPI_PRESENT) || defined(__NRFX_DOXYGEN__)
328 
329 /**
330  * @brief Function for configuring I2S pins.
331  *
332  * Usage of the SDOUT, SDIN, and MCK signals is optional.
333  * If a given signal is not needed, pass the @ref NRF_I2S_PIN_NOT_CONNECTED
334  * value instead of its pin number.
335  *
336  * @param[in] p_reg     Pointer to the structure of registers of the peripheral.
337  * @param[in] sck_pin   SCK pin number.
338  * @param[in] lrck_pin  LRCK pin number.
339  * @param[in] mck_pin   MCK pin number.
340  * @param[in] sdout_pin SDOUT pin number.
341  * @param[in] sdin_pin  SDIN pin number.
342  */
343 __STATIC_INLINE void nrf_i2s_pins_set(NRF_I2S_Type * p_reg,
344                                       uint32_t       sck_pin,
345                                       uint32_t       lrck_pin,
346                                       uint32_t       mck_pin,
347                                       uint32_t       sdout_pin,
348                                       uint32_t       sdin_pin);
349 
350 /**
351  * @brief Function for setting the I2S peripheral configuration.
352  *
353  * @param[in] p_reg        Pointer to the structure of registers of the peripheral.
354  * @param[in] mode         Mode of operation (master or slave).
355  * @param[in] format       I2S frame format.
356  * @param[in] alignment    Alignment of sample within a frame.
357  * @param[in] sample_width Sample width.
358  * @param[in] channels     Enabled channels.
359  * @param[in] mck_setup    Master clock generator setup.
360  * @param[in] ratio        MCK/LRCK ratio.
361  *
362  * @retval true  If the configuration has been set successfully.
363  * @retval false If the requested configuration is not allowed.
364  */
365 __STATIC_INLINE bool nrf_i2s_configure(NRF_I2S_Type *     p_reg,
366                                        nrf_i2s_mode_t     mode,
367                                        nrf_i2s_format_t   format,
368                                        nrf_i2s_align_t    alignment,
369                                        nrf_i2s_swidth_t   sample_width,
370                                        nrf_i2s_channels_t channels,
371                                        nrf_i2s_mck_t      mck_setup,
372                                        nrf_i2s_ratio_t    ratio);
373 
374 /**
375  * @brief Function for setting up the I2S transfer.
376  *
377  * This function sets up the RX and TX buffers and enables reception and/or
378  * transmission accordingly. If the transfer in a given direction is not
379  * required, pass NULL instead of the pointer to the corresponding buffer.
380  *
381  * @param[in] p_reg       Pointer to the structure of registers of the peripheral.
382  * @param[in] size        Size of the buffers (in 32-bit words).
383  * @param[in] p_rx_buffer Pointer to the receive buffer.
384  *                        Pass NULL to disable reception.
385  * @param[in] p_tx_buffer Pointer to the transmit buffer.
386  *                        Pass NULL to disable transmission.
387  */
388 __STATIC_INLINE void nrf_i2s_transfer_set(NRF_I2S_Type *   p_reg,
389                                           uint16_t         size,
390                                           uint32_t *       p_rx_buffer,
391                                           uint32_t const * p_tx_buffer);
392 
393 /**
394  * @brief Function for setting the pointer to the receive buffer.
395  *
396  * @note The size of the buffer can be set only by calling
397  *       @ref nrf_i2s_transfer_set.
398  *
399  * @param[in] p_reg    Pointer to the structure of registers of the peripheral.
400  * @param[in] p_buffer Pointer to the receive buffer.
401  */
402 __STATIC_INLINE void nrf_i2s_rx_buffer_set(NRF_I2S_Type * p_reg,
403                                            uint32_t *     p_buffer);
404 
405 /**
406  * @brief Function for getting the pointer to the receive buffer.
407  *
408  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
409  *
410  * @return Pointer to the receive buffer.
411  */
412 __STATIC_INLINE uint32_t * nrf_i2s_rx_buffer_get(NRF_I2S_Type const * p_reg);
413 
414 /**
415  * @brief Function for setting the pointer to the transmit buffer.
416  *
417  * @note The size of the buffer can be set only by calling
418  *       @ref nrf_i2s_transfer_set.
419  *
420  * @param[in] p_reg    Pointer to the structure of registers of the peripheral.
421  * @param[in] p_buffer Pointer to the transmit buffer.
422  */
423 __STATIC_INLINE void nrf_i2s_tx_buffer_set(NRF_I2S_Type *   p_reg,
424                                            uint32_t const * p_buffer);
425 
426 /**
427  * @brief Function for getting the pointer to the transmit buffer.
428  *
429  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
430  *
431  * @return Pointer to the transmit buffer.
432  */
433 __STATIC_INLINE uint32_t * nrf_i2s_tx_buffer_get(NRF_I2S_Type const * p_reg);
434 
435 
436 #ifndef SUPPRESS_INLINE_IMPLEMENTATION
437 
nrf_i2s_task_trigger(NRF_I2S_Type * p_reg,nrf_i2s_task_t task)438 __STATIC_INLINE void nrf_i2s_task_trigger(NRF_I2S_Type * p_reg,
439                                           nrf_i2s_task_t task)
440 {
441     *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)task)) = 0x1UL;
442 }
443 
nrf_i2s_task_address_get(NRF_I2S_Type const * p_reg,nrf_i2s_task_t task)444 __STATIC_INLINE uint32_t nrf_i2s_task_address_get(NRF_I2S_Type const * p_reg,
445                                                   nrf_i2s_task_t       task)
446 {
447     return ((uint32_t)p_reg + (uint32_t)task);
448 }
449 
nrf_i2s_event_clear(NRF_I2S_Type * p_reg,nrf_i2s_event_t event)450 __STATIC_INLINE void nrf_i2s_event_clear(NRF_I2S_Type *  p_reg,
451                                          nrf_i2s_event_t event)
452 {
453     *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL;
454 #if __CORTEX_M == 0x04
455     volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event));
456     (void)dummy;
457 #endif
458 }
459 
nrf_i2s_event_check(NRF_I2S_Type const * p_reg,nrf_i2s_event_t event)460 __STATIC_INLINE bool nrf_i2s_event_check(NRF_I2S_Type const * p_reg,
461                                          nrf_i2s_event_t      event)
462 {
463     return (bool)*(volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event);
464 }
465 
nrf_i2s_event_address_get(NRF_I2S_Type const * p_reg,nrf_i2s_event_t event)466 __STATIC_INLINE uint32_t nrf_i2s_event_address_get(NRF_I2S_Type const * p_reg,
467                                                    nrf_i2s_event_t      event)
468 {
469     return ((uint32_t)p_reg + (uint32_t)event);
470 }
471 
nrf_i2s_int_enable(NRF_I2S_Type * p_reg,uint32_t mask)472 __STATIC_INLINE void nrf_i2s_int_enable(NRF_I2S_Type * p_reg, uint32_t mask)
473 {
474     p_reg->INTENSET = mask;
475 }
476 
nrf_i2s_int_disable(NRF_I2S_Type * p_reg,uint32_t mask)477 __STATIC_INLINE void nrf_i2s_int_disable(NRF_I2S_Type * p_reg, uint32_t mask)
478 {
479     p_reg->INTENCLR = mask;
480 }
481 
nrf_i2s_int_enable_check(NRF_I2S_Type const * p_reg,nrf_i2s_int_mask_t i2s_int)482 __STATIC_INLINE bool nrf_i2s_int_enable_check(NRF_I2S_Type const * p_reg,
483                                               nrf_i2s_int_mask_t   i2s_int)
484 {
485     return (bool)(p_reg->INTENSET & i2s_int);
486 }
487 
nrf_i2s_enable(NRF_I2S_Type * p_reg)488 __STATIC_INLINE void nrf_i2s_enable(NRF_I2S_Type * p_reg)
489 {
490     p_reg->ENABLE = (I2S_ENABLE_ENABLE_Enabled << I2S_ENABLE_ENABLE_Pos);
491 }
492 
nrf_i2s_disable(NRF_I2S_Type * p_reg)493 __STATIC_INLINE void nrf_i2s_disable(NRF_I2S_Type * p_reg)
494 {
495     p_reg->ENABLE = (I2S_ENABLE_ENABLE_Disabled << I2S_ENABLE_ENABLE_Pos);
496 }
497 
498 #if defined(DPPI_PRESENT)
nrf_i2s_subscribe_set(NRF_I2S_Type * p_reg,nrf_i2s_task_t task,uint8_t channel)499 __STATIC_INLINE void nrf_i2s_subscribe_set(NRF_I2S_Type * p_reg,
500                                            nrf_i2s_task_t task,
501                                            uint8_t        channel)
502 {
503     *((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) task + 0x80uL)) =
504             ((uint32_t)channel | I2S_SUBSCRIBE_START_EN_Msk);
505 }
506 
nrf_i2s_subscribe_clear(NRF_I2S_Type * p_reg,nrf_i2s_task_t task)507 __STATIC_INLINE void nrf_i2s_subscribe_clear(NRF_I2S_Type * p_reg,
508                                              nrf_i2s_task_t task)
509 {
510     *((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) task + 0x80uL)) = 0;
511 }
512 
nrf_i2s_publish_set(NRF_I2S_Type * p_reg,nrf_i2s_event_t event,uint8_t channel)513 __STATIC_INLINE void nrf_i2s_publish_set(NRF_I2S_Type *  p_reg,
514                                          nrf_i2s_event_t event,
515                                          uint8_t         channel)
516 {
517     *((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) event + 0x80uL)) =
518             ((uint32_t)channel | I2S_PUBLISH_STOPPED_EN_Msk);
519 }
520 
nrf_i2s_publish_clear(NRF_I2S_Type * p_reg,nrf_i2s_event_t event)521 __STATIC_INLINE void nrf_i2s_publish_clear(NRF_I2S_Type *  p_reg,
522                                            nrf_i2s_event_t event)
523 {
524     *((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) event + 0x80uL)) = 0;
525 }
526 #endif // defined(DPPI_PRESENT)
527 
nrf_i2s_pins_set(NRF_I2S_Type * p_reg,uint32_t sck_pin,uint32_t lrck_pin,uint32_t mck_pin,uint32_t sdout_pin,uint32_t sdin_pin)528 __STATIC_INLINE void nrf_i2s_pins_set(NRF_I2S_Type * p_reg,
529                                       uint32_t       sck_pin,
530                                       uint32_t       lrck_pin,
531                                       uint32_t       mck_pin,
532                                       uint32_t       sdout_pin,
533                                       uint32_t       sdin_pin)
534 {
535     p_reg->PSEL.SCK   = sck_pin;
536     p_reg->PSEL.LRCK  = lrck_pin;
537     p_reg->PSEL.MCK   = mck_pin;
538     p_reg->PSEL.SDOUT = sdout_pin;
539     p_reg->PSEL.SDIN  = sdin_pin;
540 }
541 
nrf_i2s_configure(NRF_I2S_Type * p_reg,nrf_i2s_mode_t mode,nrf_i2s_format_t format,nrf_i2s_align_t alignment,nrf_i2s_swidth_t sample_width,nrf_i2s_channels_t channels,nrf_i2s_mck_t mck_setup,nrf_i2s_ratio_t ratio)542 __STATIC_INLINE bool nrf_i2s_configure(NRF_I2S_Type *     p_reg,
543                                        nrf_i2s_mode_t     mode,
544                                        nrf_i2s_format_t   format,
545                                        nrf_i2s_align_t    alignment,
546                                        nrf_i2s_swidth_t   sample_width,
547                                        nrf_i2s_channels_t channels,
548                                        nrf_i2s_mck_t      mck_setup,
549                                        nrf_i2s_ratio_t    ratio)
550 {
551     if (mode == NRF_I2S_MODE_MASTER)
552     {
553         // The MCK/LRCK ratio shall be a multiple of 2 * sample width.
554         if (((sample_width == NRF_I2S_SWIDTH_16BIT) &&
555                  (ratio == NRF_I2S_RATIO_48X))
556             ||
557             ((sample_width == NRF_I2S_SWIDTH_24BIT) &&
558                 ((ratio == NRF_I2S_RATIO_32X)  ||
559                  (ratio == NRF_I2S_RATIO_64X)  ||
560                  (ratio == NRF_I2S_RATIO_128X) ||
561                  (ratio == NRF_I2S_RATIO_256X) ||
562                  (ratio == NRF_I2S_RATIO_512X))))
563         {
564             return false;
565         }
566     }
567 
568     p_reg->CONFIG.MODE     = mode;
569     p_reg->CONFIG.FORMAT   = format;
570     p_reg->CONFIG.ALIGN    = alignment;
571     p_reg->CONFIG.SWIDTH   = sample_width;
572     p_reg->CONFIG.CHANNELS = channels;
573     p_reg->CONFIG.RATIO    = ratio;
574 
575     if (mck_setup == NRF_I2S_MCK_DISABLED)
576     {
577         p_reg->CONFIG.MCKEN =
578             (I2S_CONFIG_MCKEN_MCKEN_Disabled << I2S_CONFIG_MCKEN_MCKEN_Pos);
579     }
580     else
581     {
582         p_reg->CONFIG.MCKFREQ = mck_setup;
583         p_reg->CONFIG.MCKEN =
584             (I2S_CONFIG_MCKEN_MCKEN_Enabled << I2S_CONFIG_MCKEN_MCKEN_Pos);
585     }
586 
587     return true;
588 }
589 
nrf_i2s_transfer_set(NRF_I2S_Type * p_reg,uint16_t size,uint32_t * p_buffer_rx,uint32_t const * p_buffer_tx)590 __STATIC_INLINE void nrf_i2s_transfer_set(NRF_I2S_Type *   p_reg,
591                                           uint16_t         size,
592                                           uint32_t *       p_buffer_rx,
593                                           uint32_t const * p_buffer_tx)
594 {
595     p_reg->RXTXD.MAXCNT = size;
596 
597     nrf_i2s_rx_buffer_set(p_reg, p_buffer_rx);
598     p_reg->CONFIG.RXEN = (p_buffer_rx != NULL) ? 1 : 0;
599 
600     nrf_i2s_tx_buffer_set(p_reg, p_buffer_tx);
601     p_reg->CONFIG.TXEN = (p_buffer_tx != NULL) ? 1 : 0;
602 }
603 
nrf_i2s_rx_buffer_set(NRF_I2S_Type * p_reg,uint32_t * p_buffer)604 __STATIC_INLINE void nrf_i2s_rx_buffer_set(NRF_I2S_Type * p_reg,
605                                            uint32_t * p_buffer)
606 {
607     p_reg->RXD.PTR = (uint32_t)p_buffer;
608 }
609 
nrf_i2s_rx_buffer_get(NRF_I2S_Type const * p_reg)610 __STATIC_INLINE uint32_t * nrf_i2s_rx_buffer_get(NRF_I2S_Type const * p_reg)
611 {
612     return (uint32_t *)(p_reg->RXD.PTR);
613 }
614 
nrf_i2s_tx_buffer_set(NRF_I2S_Type * p_reg,uint32_t const * p_buffer)615 __STATIC_INLINE void nrf_i2s_tx_buffer_set(NRF_I2S_Type * p_reg,
616                                            uint32_t const * p_buffer)
617 {
618     p_reg->TXD.PTR = (uint32_t)p_buffer;
619 }
620 
nrf_i2s_tx_buffer_get(NRF_I2S_Type const * p_reg)621 __STATIC_INLINE uint32_t * nrf_i2s_tx_buffer_get(NRF_I2S_Type const * p_reg)
622 {
623     return (uint32_t *)(p_reg->TXD.PTR);
624 }
625 
626 #endif // SUPPRESS_INLINE_IMPLEMENTATION
627 
628 /** @} */
629 
630 #ifdef __cplusplus
631 }
632 #endif
633 
634 #endif // NRF_I2S_H__
635