1 /*
2  * Copyright (c) 2015 - 2024, 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 #ifndef NRF_TWI_H__
35 #define NRF_TWI_H__
36 
37 #include <nrfx.h>
38 
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 
43 /**
44  * @defgroup nrf_twi_hal TWI HAL
45  * @{
46  * @ingroup nrf_twi
47  * @brief   Hardware access layer for managing the TWI peripheral.
48  */
49 
50 /**
51  * @brief Macro getting pointer to the structure of registers of the TWI peripheral.
52  *
53  * @param[in] idx TWI instance index.
54  *
55  * @return Pointer to the structure of registers of the TWI peripheral.
56  */
57 #define NRF_TWI_INST_GET(idx) NRFX_CONCAT(NRF_, TWI, idx)
58 
59 /** @brief TWI tasks. */
60 typedef enum
61 {
62     NRF_TWI_TASK_STARTRX = offsetof(NRF_TWI_Type, TASKS_STARTRX), ///< Start TWI receive sequence.
63     NRF_TWI_TASK_STARTTX = offsetof(NRF_TWI_Type, TASKS_STARTTX), ///< Start TWI transmit sequence.
64     NRF_TWI_TASK_STOP    = offsetof(NRF_TWI_Type, TASKS_STOP),    ///< Stop TWI transaction.
65     NRF_TWI_TASK_SUSPEND = offsetof(NRF_TWI_Type, TASKS_SUSPEND), ///< Suspend TWI transaction.
66     NRF_TWI_TASK_RESUME  = offsetof(NRF_TWI_Type, TASKS_RESUME)   ///< Resume TWI transaction.
67 } nrf_twi_task_t;
68 
69 /** @brief TWI events. */
70 typedef enum
71 {
72     NRF_TWI_EVENT_STOPPED   = offsetof(NRF_TWI_Type, EVENTS_STOPPED),  ///< TWI stopped.
73     NRF_TWI_EVENT_RXDREADY  = offsetof(NRF_TWI_Type, EVENTS_RXDREADY), ///< TWI RXD byte received.
74     NRF_TWI_EVENT_TXDSENT   = offsetof(NRF_TWI_Type, EVENTS_TXDSENT),  ///< TWI TXD byte sent.
75     NRF_TWI_EVENT_ERROR     = offsetof(NRF_TWI_Type, EVENTS_ERROR),    ///< TWI error.
76     NRF_TWI_EVENT_BB        = offsetof(NRF_TWI_Type, EVENTS_BB),       ///< TWI byte boundary, generated before each byte that is sent or received.
77     NRF_TWI_EVENT_SUSPENDED = offsetof(NRF_TWI_Type, EVENTS_SUSPENDED) ///< TWI entered the suspended state.
78 } nrf_twi_event_t;
79 
80 /** @brief TWI shortcuts. */
81 typedef enum
82 {
83     NRF_TWI_SHORT_BB_SUSPEND_MASK = TWI_SHORTS_BB_SUSPEND_Msk,  ///< Shortcut between BB event and SUSPEND task.
84     NRF_TWI_SHORT_BB_STOP_MASK    = TWI_SHORTS_BB_STOP_Msk,     ///< Shortcut between BB event and STOP task.
85     NRF_TWI_ALL_SHORTS_MASK       = TWI_SHORTS_BB_SUSPEND_Msk |
86                                     TWI_SHORTS_BB_STOP_Msk      ///< All TWI shortcuts.
87 } nrf_twi_short_mask_t;
88 
89 /** @brief TWI interrupts. */
90 typedef enum
91 {
92     NRF_TWI_INT_STOPPED_MASK    = TWI_INTENSET_STOPPED_Msk,    ///< Interrupt on STOPPED event.
93     NRF_TWI_INT_RXDREADY_MASK   = TWI_INTENSET_RXDREADY_Msk,   ///< Interrupt on RXDREADY event.
94     NRF_TWI_INT_TXDSENT_MASK    = TWI_INTENSET_TXDSENT_Msk,    ///< Interrupt on TXDSENT event.
95     NRF_TWI_INT_ERROR_MASK      = TWI_INTENSET_ERROR_Msk,      ///< Interrupt on ERROR event.
96     NRF_TWI_INT_BB_MASK         = TWI_INTENSET_BB_Msk,         ///< Interrupt on BB event.
97     NRF_TWI_INT_SUSPENDED_MASK  = TWI_INTENSET_SUSPENDED_Msk,  ///< Interrupt on SUSPENDED event.
98     NRF_TWI_ALL_INTS_MASK       = TWI_INTENSET_STOPPED_Msk   |
99                                   TWI_INTENSET_RXDREADY_Msk  |
100                                   TWI_INTENSET_TXDSENT_Msk   |
101                                   TWI_INTENSET_ERROR_Msk     |
102                                   TWI_INTENSET_BB_Msk        |
103                                   TWI_INTENSET_SUSPENDED_Msk   ///< All TWI interrupts.
104 } nrf_twi_int_mask_t;
105 
106 /** @brief TWI error source. */
107 typedef enum
108 {
109     NRF_TWI_ERROR_ADDRESS_NACK = TWI_ERRORSRC_ANACK_Msk,  ///< NACK received after sending the address.
110     NRF_TWI_ERROR_DATA_NACK    = TWI_ERRORSRC_DNACK_Msk,  ///< NACK received after sending a data byte.
111     NRF_TWI_ERROR_OVERRUN      = TWI_ERRORSRC_OVERRUN_Msk ///< Overrun error.
112                                                           /**< A new byte was received before the previous byte was read
113                                                            *   from the RXD register (previous data is lost). */
114 } nrf_twi_error_t;
115 
116 /** @brief TWI master clock frequency. */
117 typedef enum
118 {
119     NRF_TWI_FREQ_100K = TWI_FREQUENCY_FREQUENCY_K100, ///< 100 kbps.
120     NRF_TWI_FREQ_250K = TWI_FREQUENCY_FREQUENCY_K250, ///< 250 kbps.
121     NRF_TWI_FREQ_400K = TWI_FREQUENCY_FREQUENCY_K400  ///< 400 kbps.
122 } nrf_twi_frequency_t;
123 
124 
125 /**
126  * @brief Function for activating the specified TWI task.
127  *
128  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
129  * @param[in] task  Task to be activated.
130  */
131 NRF_STATIC_INLINE void nrf_twi_task_trigger(NRF_TWI_Type * p_reg,
132                                             nrf_twi_task_t task);
133 
134 /**
135  * @brief Function for getting the address of the specified TWI task register.
136  *
137  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
138  * @param[in] task  The specified task.
139  *
140  * @return Address of the specified task register.
141  */
142 NRF_STATIC_INLINE uint32_t nrf_twi_task_address_get(NRF_TWI_Type const * p_reg,
143                                                     nrf_twi_task_t       task);
144 
145 /**
146  * @brief Function for clearing the specified TWI event.
147  *
148  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
149  * @param[in] event Event to clear.
150  */
151 NRF_STATIC_INLINE void nrf_twi_event_clear(NRF_TWI_Type *  p_reg,
152                                            nrf_twi_event_t event);
153 
154 /**
155  * @brief Function for retrieving the state of the TWI event.
156  *
157  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
158  * @param[in] event Event to be checked.
159  *
160  * @retval true  The event has been generated.
161  * @retval false The event has not been generated.
162  */
163 NRF_STATIC_INLINE bool nrf_twi_event_check(NRF_TWI_Type const * p_reg,
164                                            nrf_twi_event_t      event);
165 
166 /**
167  * @brief Function for getting the address of the specified TWI event register.
168  *
169  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
170  * @param[in] event The specified event.
171  *
172  * @return Address of the specified event register.
173  */
174 NRF_STATIC_INLINE uint32_t nrf_twi_event_address_get(NRF_TWI_Type const * p_reg,
175                                                      nrf_twi_event_t      event);
176 
177 /**
178  * @brief Function for enabling the specified shortcuts.
179  *
180  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
181  * @param[in] mask  Shortcuts to be enabled.
182  */
183 NRF_STATIC_INLINE void nrf_twi_shorts_enable(NRF_TWI_Type * p_reg,
184                                              uint32_t       mask);
185 
186 /**
187  * @brief Function for disabling the specified shortcuts.
188  *
189  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
190  * @param[in] mask  Shortcuts to be disabled.
191  */
192 NRF_STATIC_INLINE void nrf_twi_shorts_disable(NRF_TWI_Type * p_reg,
193                                               uint32_t       mask);
194 
195 /**
196  * @brief Function for enabling the specified interrupts.
197  *
198  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
199  * @param[in] mask  Mask of interrupts to be enabled.
200  *                  Use @ref nrf_twi_int_mask_t values for bit masking.
201  */
202 NRF_STATIC_INLINE void nrf_twi_int_enable(NRF_TWI_Type * p_reg,
203                                           uint32_t       mask);
204 
205 /**
206  * @brief Function for disabling the specified interrupts.
207  *
208  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
209  * @param[in] mask  Mask of interrupts to be disabled.
210  *                  Use @ref nrf_twi_int_mask_t values for bit masking.
211  */
212 NRF_STATIC_INLINE void nrf_twi_int_disable(NRF_TWI_Type * p_reg,
213                                            uint32_t       mask);
214 
215 /**
216  * @brief Function for checking if the specified interrupts are enabled.
217  *
218  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
219  * @param[in] mask  Mask of interrupts to be checked.
220  *                  Use @ref nrf_twi_int_mask_t values for bit masking.
221  *
222  * @return Mask of enabled interrupts.
223  */
224 NRF_STATIC_INLINE uint32_t nrf_twi_int_enable_check(NRF_TWI_Type const * p_reg, uint32_t mask);
225 
226 /**
227  * @brief Function for enabling the TWI peripheral.
228  *
229  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
230  */
231 NRF_STATIC_INLINE void nrf_twi_enable(NRF_TWI_Type * p_reg);
232 
233 /**
234  * @brief Function for disabling the TWI peripheral.
235  *
236  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
237  */
238 NRF_STATIC_INLINE void nrf_twi_disable(NRF_TWI_Type * p_reg);
239 
240 /**
241  * @brief Function for configuring TWI pins.
242  *
243  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
244  * @param[in] scl_pin SCL pin number.
245  * @param[in] sda_pin SDA pin number.
246  */
247 NRF_STATIC_INLINE void nrf_twi_pins_set(NRF_TWI_Type * p_reg,
248                                         uint32_t       scl_pin,
249                                         uint32_t       sda_pin);
250 
251 /**
252  * @brief Function for retrieving the SCL pin selection.
253  *
254  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
255  *
256  * @return SCL pin selection.
257  */
258 NRF_STATIC_INLINE uint32_t nrf_twi_scl_pin_get(NRF_TWI_Type const * p_reg);
259 
260 /**
261  * @brief Function for retrieving the SDA pin selection.
262  *
263  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
264  *
265  * @return SDA pin selection.
266  */
267 NRF_STATIC_INLINE uint32_t nrf_twi_sda_pin_get(NRF_TWI_Type const * p_reg);
268 
269 /**
270  * @brief Function for setting the TWI master clock frequency.
271  *
272  * @param[in] p_reg     Pointer to the structure of registers of the peripheral.
273  * @param[in] frequency TWI frequency.
274  */
275 NRF_STATIC_INLINE void nrf_twi_frequency_set(NRF_TWI_Type *      p_reg,
276                                              nrf_twi_frequency_t frequency);
277 
278 /**
279  * @brief Function for checking the TWI error source.
280  *
281  * The error flags are cleared after reading.
282  *
283  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
284  *
285  * @return Mask with error source flags.
286  */
287 NRF_STATIC_INLINE uint32_t nrf_twi_errorsrc_get_and_clear(NRF_TWI_Type * p_reg);
288 
289 /**
290  * @brief Function for setting the address to be used in TWI transfers.
291  *
292  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
293  * @param[in] address Address to be used in transfers.
294  */
295 NRF_STATIC_INLINE void nrf_twi_address_set(NRF_TWI_Type * p_reg, uint8_t address);
296 
297 /**
298  * @brief Function for reading data received by TWI.
299  *
300  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
301  *
302  * @return Received data.
303  */
304 NRF_STATIC_INLINE uint8_t nrf_twi_rxd_get(NRF_TWI_Type const * p_reg);
305 
306 /**
307  * @brief Function for writing data to be transmitted by TWI.
308  *
309  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
310  * @param[in] data  Data to be transmitted.
311  */
312 NRF_STATIC_INLINE void nrf_twi_txd_set(NRF_TWI_Type * p_reg, uint8_t data);
313 
314 /**
315  * @brief Function for setting the specified shortcuts.
316  *
317  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
318  * @param[in] mask  Shortcuts to be set.
319  */
320 NRF_STATIC_INLINE void nrf_twi_shorts_set(NRF_TWI_Type * p_reg,
321                                           uint32_t       mask);
322 
323 #ifndef NRF_DECLARE_ONLY
324 
nrf_twi_task_trigger(NRF_TWI_Type * p_reg,nrf_twi_task_t task)325 NRF_STATIC_INLINE void nrf_twi_task_trigger(NRF_TWI_Type * p_reg,
326                                             nrf_twi_task_t task)
327 {
328     *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)task)) = 0x1UL;
329 }
330 
nrf_twi_task_address_get(NRF_TWI_Type const * p_reg,nrf_twi_task_t task)331 NRF_STATIC_INLINE uint32_t nrf_twi_task_address_get(NRF_TWI_Type const * p_reg,
332                                                     nrf_twi_task_t       task)
333 {
334     return nrf_task_event_address_get(p_reg, task);
335 }
336 
nrf_twi_event_clear(NRF_TWI_Type * p_reg,nrf_twi_event_t event)337 NRF_STATIC_INLINE void nrf_twi_event_clear(NRF_TWI_Type  * p_reg,
338                                            nrf_twi_event_t event)
339 {
340     *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL;
341     nrf_event_readback((uint8_t *)p_reg + (uint32_t)event);
342 }
343 
nrf_twi_event_check(NRF_TWI_Type const * p_reg,nrf_twi_event_t event)344 NRF_STATIC_INLINE bool nrf_twi_event_check(NRF_TWI_Type const * p_reg,
345                                            nrf_twi_event_t      event)
346 {
347     return nrf_event_check(p_reg, event);
348 }
349 
nrf_twi_event_address_get(NRF_TWI_Type const * p_reg,nrf_twi_event_t event)350 NRF_STATIC_INLINE uint32_t nrf_twi_event_address_get(NRF_TWI_Type const * p_reg,
351                                                      nrf_twi_event_t      event)
352 {
353     return nrf_task_event_address_get(p_reg, event);
354 }
355 
nrf_twi_shorts_enable(NRF_TWI_Type * p_reg,uint32_t mask)356 NRF_STATIC_INLINE void nrf_twi_shorts_enable(NRF_TWI_Type * p_reg,
357                                              uint32_t       mask)
358 {
359     p_reg->SHORTS |= mask;
360 }
361 
nrf_twi_shorts_disable(NRF_TWI_Type * p_reg,uint32_t mask)362 NRF_STATIC_INLINE void nrf_twi_shorts_disable(NRF_TWI_Type * p_reg,
363                                               uint32_t       mask)
364 {
365     p_reg->SHORTS &= ~(mask);
366 }
367 
nrf_twi_int_enable(NRF_TWI_Type * p_reg,uint32_t mask)368 NRF_STATIC_INLINE void nrf_twi_int_enable(NRF_TWI_Type * p_reg,
369                                           uint32_t       mask)
370 {
371     p_reg->INTENSET = mask;
372 }
373 
nrf_twi_int_disable(NRF_TWI_Type * p_reg,uint32_t mask)374 NRF_STATIC_INLINE void nrf_twi_int_disable(NRF_TWI_Type * p_reg,
375                                            uint32_t       mask)
376 {
377     p_reg->INTENCLR = mask;
378 }
379 
nrf_twi_int_enable_check(NRF_TWI_Type const * p_reg,uint32_t mask)380 NRF_STATIC_INLINE uint32_t nrf_twi_int_enable_check(NRF_TWI_Type const * p_reg, uint32_t mask)
381 {
382     return p_reg->INTENSET & mask;
383 }
384 
nrf_twi_enable(NRF_TWI_Type * p_reg)385 NRF_STATIC_INLINE void nrf_twi_enable(NRF_TWI_Type * p_reg)
386 {
387     p_reg->ENABLE = (TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos);
388 }
389 
nrf_twi_disable(NRF_TWI_Type * p_reg)390 NRF_STATIC_INLINE void nrf_twi_disable(NRF_TWI_Type * p_reg)
391 {
392     p_reg->ENABLE = (TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos);
393 }
394 
nrf_twi_pins_set(NRF_TWI_Type * p_reg,uint32_t scl_pin,uint32_t sda_pin)395 NRF_STATIC_INLINE void nrf_twi_pins_set(NRF_TWI_Type * p_reg,
396                                         uint32_t       scl_pin,
397                                         uint32_t       sda_pin)
398 {
399 #if defined(TWI_PSEL_SCL_CONNECT_Pos)
400     p_reg->PSEL.SCL = scl_pin;
401 #else
402     p_reg->PSELSCL = scl_pin;
403 #endif
404 
405 #if defined(TWI_PSEL_SDA_CONNECT_Pos)
406     p_reg->PSEL.SDA = sda_pin;
407 #else
408     p_reg->PSELSDA = sda_pin;
409 #endif
410 }
411 
nrf_twi_scl_pin_get(NRF_TWI_Type const * p_reg)412 NRF_STATIC_INLINE uint32_t nrf_twi_scl_pin_get(NRF_TWI_Type const * p_reg)
413 {
414 #if defined(TWI_PSEL_SCL_CONNECT_Pos)
415     return p_reg->PSEL.SCL;
416 #else
417     return p_reg->PSELSCL;
418 #endif
419 }
420 
nrf_twi_sda_pin_get(NRF_TWI_Type const * p_reg)421 NRF_STATIC_INLINE uint32_t nrf_twi_sda_pin_get(NRF_TWI_Type const * p_reg)
422 {
423 #if defined(TWI_PSEL_SDA_CONNECT_Pos)
424     return p_reg->PSEL.SDA;
425 #else
426     return p_reg->PSELSDA;
427 #endif
428 }
429 
nrf_twi_frequency_set(NRF_TWI_Type * p_reg,nrf_twi_frequency_t frequency)430 NRF_STATIC_INLINE void nrf_twi_frequency_set(NRF_TWI_Type *      p_reg,
431                                              nrf_twi_frequency_t frequency)
432 {
433     p_reg->FREQUENCY = frequency;
434 }
435 
nrf_twi_errorsrc_get_and_clear(NRF_TWI_Type * p_reg)436 NRF_STATIC_INLINE uint32_t nrf_twi_errorsrc_get_and_clear(NRF_TWI_Type * p_reg)
437 {
438     uint32_t error_source = p_reg->ERRORSRC;
439 
440     // [error flags are cleared by writing '1' on their position]
441     p_reg->ERRORSRC = error_source;
442 
443     return error_source;
444 }
445 
nrf_twi_address_set(NRF_TWI_Type * p_reg,uint8_t address)446 NRF_STATIC_INLINE void nrf_twi_address_set(NRF_TWI_Type * p_reg, uint8_t address)
447 {
448     p_reg->ADDRESS = address;
449 }
450 
nrf_twi_rxd_get(NRF_TWI_Type const * p_reg)451 NRF_STATIC_INLINE uint8_t nrf_twi_rxd_get(NRF_TWI_Type const * p_reg)
452 {
453     return (uint8_t)p_reg->RXD;
454 }
455 
nrf_twi_txd_set(NRF_TWI_Type * p_reg,uint8_t data)456 NRF_STATIC_INLINE void nrf_twi_txd_set(NRF_TWI_Type * p_reg, uint8_t data)
457 {
458     p_reg->TXD = data;
459 }
460 
nrf_twi_shorts_set(NRF_TWI_Type * p_reg,uint32_t mask)461 NRF_STATIC_INLINE void nrf_twi_shorts_set(NRF_TWI_Type * p_reg,
462                                           uint32_t       mask)
463 {
464     p_reg->SHORTS = mask;
465 }
466 
467 #endif // NRF_DECLARE_ONLY
468 
469 /** @} */
470 
471 #ifdef __cplusplus
472 }
473 #endif
474 
475 #endif // NRF_TWI_H__
476