ruuvi.drivers.c ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
Loading...
Searching...
No Matches
ruuvi_nrf5_sdk15_gpio_interrupt.c
Go to the documentation of this file.
1
10#if RUUVI_NRF5_SDK15_GPIO_INTERRUPT_ENABLED
14
15
16#include <stdbool.h>
17#include "nrf.h"
18#include "nrf_drv_gpiote.h"
19
20//Pointer to look-up table for event handlers
21static ri_gpio_interrupt_fp_t * pin_event_handlers;
22static uint8_t max_interrupts = 0;
23
25 ri_gpio_interrupt_fp_t * const interrupt_table,
26 const uint16_t interrupt_table_size)
27{
28 if (NULL == interrupt_table) { return RD_ERROR_NULL; }
29
30 if (!ri_gpio_is_init()) { return RD_ERROR_INVALID_STATE; }
31
32 // Check module initialization status by max interrupts
33 if (0 != max_interrupts) { return RD_ERROR_INVALID_STATE; }
34
35 /* Driver initialization
36 The GPIOTE driver is a shared resource that can be used by multiple modules in an application.
37 Therefore, it can be initialized only once. If a module is using the driver,
38 it must check if it has already been initialized by calling the function nrf_drv_gpiote_is_init.
39 If this function returns false, the module must initialize the driver by calling the function nrf_drv_gpiote_init.
40
41 The following code example shows how to initialize the driver:
42 */
43 ret_code_t err_code = NRF_SUCCESS;
44
45 if (!nrf_drv_gpiote_is_init())
46 {
47 err_code = nrf_drv_gpiote_init();
48 }
49
50 pin_event_handlers = interrupt_table;
51 max_interrupts = interrupt_table_size;
52 return ruuvi_nrf5_sdk15_to_ruuvi_error (err_code);
53}
54
56{
57 if (0 == max_interrupts) { return RD_SUCCESS; }
58
59 pin_event_handlers = NULL;
60 max_interrupts = 0;
61 return RD_SUCCESS;
62}
63
65{
66 return (0 != max_interrupts);
67}
68
69static void in_pin_handler (const nrf_drv_gpiote_pin_t pin,
70 const nrf_gpiote_polarity_t action)
71{
72 if (max_interrupts <= pin) { return; }
73
74 ri_gpio_evt_t event;
75 ri_gpio_state_t state;
76
77 if (NULL != pin_event_handlers[pin])
78 {
79 switch (action)
80 {
81 case NRF_GPIOTE_POLARITY_LOTOHI:
83 break;
84
85 case NRF_GPIOTE_POLARITY_HITOLO:
86 event.slope = RI_GPIO_SLOPE_HITOLO;
87 break;
88
89 default:
90 // Determine slope from current state
91 ri_gpio_read (nrf_to_ruuvi_pin (pin), &state);
92 event.slope = (state == RI_GPIO_LOW) ? RI_GPIO_SLOPE_HITOLO : RI_GPIO_SLOPE_LOTOHI;
93 break;
94 }
95
96 //Call event handler.
97 event.pin = nrf_to_ruuvi_pin (pin);
98 (pin_event_handlers[pin]) (event);
99 }
100}
101
103 ri_gpio_id_t pin,
104 const ri_gpio_slope_t slope,
105 const ri_gpio_mode_t mode,
106 const ri_gpio_interrupt_fp_t handler)
107{
108 rd_status_t err_code = RD_SUCCESS;
109
111 {
112 err_code |= RD_ERROR_INVALID_STATE;
113 }
114 else if (RI_GPIO_ID_UNUSED == pin)
115 {
116 // No action needed
117 }
118 else
119 {
120 // nRF5 devices have 32 pins per port. Pack the port-pin representation into 8 bits for interrupt table.
121 uint8_t nrf_pin = ruuvi_to_nrf_pin_map (pin);
122
123 if (nrf_pin >= max_interrupts) { return RD_ERROR_INVALID_PARAM; }
124
125 ret_code_t nrf_code = NRF_SUCCESS;
126 nrf_gpiote_polarity_t polarity = NRF_GPIOTE_POLARITY_TOGGLE;
127 nrf_gpio_pin_pull_t pull = NRF_GPIO_PIN_NOPULL;
128
129 switch (slope)
130 {
132 polarity = NRF_GPIOTE_POLARITY_TOGGLE;
133 break;
134
136 polarity = NRF_GPIOTE_POLARITY_LOTOHI;
137 break;
138
140 polarity = NRF_GPIOTE_POLARITY_HITOLO;
141 break;
142
143 default:
144 err_code |= RD_ERROR_INVALID_PARAM;
145 }
146
147 switch (mode)
148 {
150 pull = NRF_GPIO_PIN_NOPULL;
151 break;
152
154 pull = NRF_GPIO_PIN_PULLUP;
155 break;
156
158 pull = NRF_GPIO_PIN_PULLDOWN;
159 break;
160
161 default:
162 err_code |= RD_ERROR_INVALID_PARAM;
163 }
164
165 // high-accuracy mode consumes excess power
166 // is_watcher is used if we track an output pin.
167 nrf_drv_gpiote_in_config_t in_config =
168 {
169 .is_watcher = false,
170 .hi_accuracy = false,
171 .pull = pull,
172 .sense = polarity
173 };
174 pin_event_handlers[nrf_pin] = handler;
175 nrf_code |= nrf_drv_gpiote_in_init (nrf_pin, &in_config, in_pin_handler);
176 nrf_drv_gpiote_in_event_enable (nrf_pin, true);
177 err_code |= ruuvi_nrf5_sdk15_to_ruuvi_error (nrf_code);
178 }
179
180 return err_code;
181}
182
184{
185 rd_status_t err_code = RD_SUCCESS;
186
187 if (RI_GPIO_ID_UNUSED != pin)
188 {
189 uint8_t nrf_pin = ruuvi_to_nrf_pin_map (pin);
190
191 if (NULL != pin_event_handlers && NULL != pin_event_handlers[nrf_pin])
192 {
193 nrf_drv_gpiote_in_event_disable (nrf_pin);
194 nrf_drv_gpiote_in_uninit (nrf_pin);
195 pin_event_handlers[nrf_pin] = NULL;
196 }
197 }
198
199 return err_code;
200}
201
202#endif
#define RD_ERROR_INVALID_PARAM
Invalid Parameter.
#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.
ri_gpio_slope_t
Enable implementation selected by application.
rd_status_t ri_gpio_interrupt_enable(const ri_gpio_id_t pin, const ri_gpio_slope_t slope, const ri_gpio_mode_t mode, const ri_gpio_interrupt_fp_t handler)
Enable interrupt on a pin.
bool ri_gpio_is_init(void)
return true if GPIO is init, false otherwise.
rd_status_t ri_gpio_interrupt_init(ri_gpio_interrupt_fp_t *const interrupt_table, const uint16_t max_interrupts)
Initialize interrupt functionality to GPIO. Takes address of interrupt table as a pointer to avoid ty...
void(* ri_gpio_interrupt_fp_t)(const ri_gpio_evt_t)
rd_status_t ri_gpio_interrupt_uninit(void)
Uninitialize interrupt functionality of GPIO.
rd_status_t ri_gpio_interrupt_disable(const ri_gpio_id_t pin)
Disable interrupt on a pin.
bool ri_gpio_interrupt_is_init(void)
Check if interrupt module is initialized.
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...
Header to enable and disable module compilation.
uint16_t ri_gpio_id_t
port<<8 + pin
#define RI_GPIO_ID_UNUSED
Enable implementation selected by application.
@ RI_GPIO_MODE_INPUT_PULLUP
Input, can be read. Pulled up by internal resistor, value depends on IC.
@ RI_GPIO_MODE_INPUT_NOPULL
Input, can be read. No pull resistors.
@ RI_GPIO_MODE_INPUT_PULLDOWN
Input, can be read. Pulled dpwn by internal resistor, value depends on IC.
ri_gpio_state_t
States of GPIO pins.
@ RI_GPIO_LOW
GPIO electrically low.
ri_gpio_slope_t slope
ri_gpio_slope_t slope of event