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