ruuvi.drivers.c ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules
ruuvi_nrf5_sdk15_i2c.c
Go to the documentation of this file.
1
41#include "ruuvi_interface_i2c.h"
42#if RUUVI_NRF5_SDK15_I2C_ENABLED
43#include <stdint.h>
44#include <string.h> //memcpy
45
46#include "ruuvi_boards.h"
47#include "nrf_drv_twi.h"
48#include "ruuvi_driver_error.h"
53
54#ifndef NRF_FIX_TWI_ISSUE_219
55#define NRF_FIX_TWI_ISSUE_219
56#endif
57
58#ifdef NRF_FIX_TWI_ISSUE_219
59#define NRF_DRV_TWI_FREQ_390K (0x06200000UL)
60#endif
61
62static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE (I2C_INSTANCE);
63static bool m_i2c_is_init = false;
64static volatile bool m_tx_in_progress = false;
65static volatile ret_code_t xfer_status = NRF_SUCCESS;
66static uint16_t timeout_us_per_byte = 1000;
67
68static nrf_drv_twi_frequency_t ruuvi_to_nrf_frequency (const
70{
71 switch (freq)
72 {
74 return NRF_DRV_TWI_FREQ_100K;
75
77 return NRF_DRV_TWI_FREQ_250K;
78
80 default:
81 return NRF_DRV_TWI_FREQ_400K;
82 }
83}
84
85static void byte_timeout_set (const
87{
88 switch (freq)
89 {
91 timeout_us_per_byte = 1000;
92
94 timeout_us_per_byte = 400;
95
97 default:
98 timeout_us_per_byte = 200;
99 }
100}
101
102#ifdef NRF_FIX_TWI_ISSUE_219
103static void byte_freq_set (nrf_drv_twi_t const * p_instance,
104 const ri_i2c_frequency_t freq)
105{
106 NRF_TWI_Type * p_reg_twi = p_instance->u.twi.p_twi;
107 NRF_TWIM_Type * p_reg_twim = p_instance->u.twim.p_twim;
108
109 if (freq == RI_I2C_FREQUENCY_400k)
110 {
111 if (NRF_DRV_TWI_USE_TWIM) { p_reg_twim->FREQUENCY = NRF_DRV_TWI_FREQ_390K; }
112 else { p_reg_twi->FREQUENCY = NRF_DRV_TWI_FREQ_390K; }
113 }
114}
115#endif
116
117static void on_complete (nrf_drv_twi_evt_t const * p_event, void * p_context)
118{
119 m_tx_in_progress = false;
120
121 if (p_event->type == NRF_DRV_TWI_EVT_ADDRESS_NACK) { xfer_status |= NRF_ERROR_NOT_FOUND; }
122 else if (p_event->type == NRF_DRV_TWI_EVT_DATA_NACK) { xfer_status |= NRF_ERROR_DRV_TWI_ERR_DNACK; }
123 else if (p_event->type != NRF_DRV_TWI_EVT_DONE) { xfer_status |= NRF_ERROR_INTERNAL; }
124}
125
127 config)
128{
129 ret_code_t err_code;
130 nrf_drv_twi_frequency_t frequency = ruuvi_to_nrf_frequency (config->frequency);
131 byte_timeout_set (config->frequency);
132 const nrf_drv_twi_config_t twi_config =
133 {
134 .scl = ruuvi_to_nrf_pin_map (config->scl),
135 .sda = ruuvi_to_nrf_pin_map (config->sda),
136 .frequency = frequency,
137 .interrupt_priority = APP_IRQ_PRIORITY_LOW,
138 .clear_bus_init = true
139 };
140 // Verify that lines can be pulled up
145 ri_gpio_state_t state_scl, state_sda;
146 ri_delay_us (1000);
147 ri_gpio_read (config->sda, &state_sda);
148 ri_gpio_read (config->scl, &state_scl);
149
150 if (RI_GPIO_HIGH != state_sda ||
151 RI_GPIO_HIGH != state_scl)
152 {
153 return RD_ERROR_INTERNAL;
154 }
155
156 err_code = nrf_drv_twi_init (&m_twi, &twi_config, on_complete, NULL);
157#ifdef NRF_FIX_TWI_ISSUE_219
158 byte_freq_set (&m_twi, config->frequency);
159#endif
160 nrf_drv_twi_enable (&m_twi);
161 m_i2c_is_init = true;
162 m_tx_in_progress = false;
163 return ruuvi_nrf5_sdk15_to_ruuvi_error (err_code);
164}
165
166bool ri_i2c_is_init()
167{
168 return m_i2c_is_init;
169}
170
177{
178 nrf_drv_twi_disable (&m_twi);
179 nrf_drv_twi_uninit (&m_twi);
180 return RD_SUCCESS;
181}
182
183
193rd_status_t ri_i2c_write_blocking (const uint8_t address,
194 uint8_t * const p_tx, const size_t tx_len, const bool stop)
195{
196 if (!m_i2c_is_init) { return RD_ERROR_INVALID_STATE; }
197
198 if (NULL == p_tx) { return RD_ERROR_NULL; }
199
200 if (m_tx_in_progress) { return RD_ERROR_BUSY; }
201
202 int32_t err_code = NRF_SUCCESS;
203 m_tx_in_progress = true;
204 err_code |= nrf_drv_twi_tx (&m_twi, address, p_tx, tx_len, !stop);
205 volatile uint32_t timeout = 0;
206
207 while (m_tx_in_progress && timeout < (timeout_us_per_byte * tx_len))
208 {
209 timeout++;
210 ri_delay_us (1);
211 }
212
213 if (timeout >= (timeout_us_per_byte * tx_len)) { err_code |= NRF_ERROR_TIMEOUT; }
214
215 err_code |= xfer_status;
216 xfer_status = NRF_SUCCESS;
217 return ruuvi_nrf5_sdk15_to_ruuvi_error (err_code);
218}
219
231rd_status_t ri_i2c_read_blocking (const uint8_t address,
232 uint8_t * const p_rx, const size_t rx_len)
233{
234 if (!m_i2c_is_init) { return RD_ERROR_INVALID_STATE; }
235
236 if (NULL == p_rx) { return RD_ERROR_NULL; }
237
238 int32_t err_code = NRF_SUCCESS;
239 m_tx_in_progress = true;
240 err_code |= nrf_drv_twi_rx (&m_twi, address, p_rx, rx_len);
241 volatile uint32_t timeout = 0;
242
243 while (m_tx_in_progress && timeout < (timeout_us_per_byte * rx_len))
244 {
245 timeout++;
246 ri_delay_us (1);
247 }
248
249 if (timeout >= (timeout_us_per_byte * rx_len)) { err_code |= NRF_ERROR_TIMEOUT; }
250
251 err_code |= xfer_status;
252 xfer_status = NRF_SUCCESS;
253 return ruuvi_nrf5_sdk15_to_ruuvi_error (err_code);
254}
255
256#endif
#define RD_ERROR_NULL
Null Pointer.
uint32_t rd_status_t
bitfield for representing errors
rd_status_t ruuvi_nrf5_sdk15_to_ruuvi_error(const ret_code_t error)
convert nrf5 sdk15 error code into Ruuvi error code.
#define RD_SUCCESS
Internal Error.
#define RD_ERROR_INVALID_STATE
Invalid state, operation disallowed in this state.
#define RD_ERROR_INTERNAL
Internal Error.
#define RD_ERROR_BUSY
Busy.
rd_status_t ri_gpio_configure(const ri_gpio_id_t pin, const ri_gpio_mode_t mode)
Configure a pin of a port into a mode. If there are several ports the platform driver must implement ...
rd_status_t ri_gpio_read(const ri_gpio_id_t pin, ri_gpio_state_t *const p_state)
Read state of a pin of a port into bool high If there are several ports the platform driver must impl...
rd_status_t ri_gpio_write(const ri_gpio_id_t pin, const ri_gpio_state_t state)
Write a pin of a port into given state If there are several ports the platform driver must implement ...
Header to enable and disable module compilation.
Ruuvi error codes and error check function.
@ RI_GPIO_MODE_INPUT_PULLUP
Input, can be read. Pulled up by internal resistor, value depends on IC.
@ RI_GPIO_MODE_OUTPUT_HIGHDRIVE
Push-pull output, can be written. Higher current drive than standard.
ri_gpio_state_t
States of GPIO pins.
@ RI_GPIO_HIGH
GPIO electrically high.
Interface for I2C operations.
rd_status_t ri_i2c_init(const ri_i2c_init_config_t *const config)
Initialize I2C driver with given settings.
rd_status_t ri_i2c_write_blocking(const uint8_t address, uint8_t *const p_tx, const size_t tx_len, const bool stop)
I2C read function.
bool ri_i2c_is_init()
Check if i2c driver is initialized.
rd_status_t ri_i2c_uninit(void)
Uninitialize I2C.
ri_i2c_frequency_t
@ RI_I2C_FREQUENCY_250k
250 kbps.
@ RI_I2C_FREQUENCY_400k
400 kbps.
@ RI_I2C_FREQUENCY_100k
100 kbps.
rd_status_t ri_i2c_read_blocking(const uint8_t address, uint8_t *const p_rx, const size_t rx_len)
I2C read function.
rd_status_t ri_delay_us(uint32_t time)
Delay a given number of microseconds.
ri_gpio_id_t bus_pwr
Power to pull-ups, UNUSED if fixed.
ri_gpio_id_t sda
pin number of SDA
ri_i2c_frequency_t frequency
Frequency of I2C Bus, see ri_i2c_frequency_t.
ri_gpio_id_t scl
pin number of SCL