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 NRFX_GPIOTE_H__ 33 #define NRFX_GPIOTE_H__ 34 35 #include <nrfx.h> 36 #include <hal/nrf_gpiote.h> 37 #include <hal/nrf_gpio.h> 38 39 #ifdef __cplusplus 40 extern "C" { 41 #endif 42 43 /** 44 * @defgroup nrfx_gpiote GPIOTE driver 45 * @{ 46 * @ingroup nrf_gpiote 47 * @brief GPIOTE peripheral driver. 48 */ 49 50 /**@brief Input pin configuration. */ 51 typedef struct 52 { 53 nrf_gpiote_polarity_t sense; /**< Transition that triggers interrupt. */ 54 nrf_gpio_pin_pull_t pull; /**< Pulling mode. */ 55 bool is_watcher : 1; /**< True when the input pin is tracking an output pin. */ 56 bool hi_accuracy : 1; /**< True when high accuracy (IN_EVENT) is used. */ 57 bool skip_gpio_setup : 1; /**< Do not change GPIO configuration */ 58 } nrfx_gpiote_in_config_t; 59 60 /**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect low-to-high transition. 61 * @details Set hi_accu to true to use IN_EVENT. */ 62 #define NRFX_GPIOTE_CONFIG_IN_SENSE_LOTOHI(hi_accu) \ 63 { \ 64 .is_watcher = false, \ 65 .hi_accuracy = hi_accu, \ 66 .pull = NRF_GPIO_PIN_NOPULL, \ 67 .sense = NRF_GPIOTE_POLARITY_LOTOHI, \ 68 } 69 70 /**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect high-to-low transition. 71 * @details Set hi_accu to true to use IN_EVENT. */ 72 #define NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(hi_accu) \ 73 { \ 74 .is_watcher = false, \ 75 .hi_accuracy = hi_accu, \ 76 .pull = NRF_GPIO_PIN_NOPULL, \ 77 .sense = NRF_GPIOTE_POLARITY_HITOLO, \ 78 } 79 80 /**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect any change on the pin. 81 * @details Set hi_accu to true to use IN_EVENT.*/ 82 #define NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE(hi_accu) \ 83 { \ 84 .is_watcher = false, \ 85 .hi_accuracy = hi_accu, \ 86 .pull = NRF_GPIO_PIN_NOPULL, \ 87 .sense = NRF_GPIOTE_POLARITY_TOGGLE, \ 88 } 89 90 /**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect low-to-high transition. 91 * @details Set hi_accu to true to use IN_EVENT. 92 * @note This macro prepares configuration that skips GPIO setup. */ 93 #define NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_LOTOHI(hi_accu) \ 94 { \ 95 .is_watcher = false, \ 96 .hi_accuracy = hi_accu, \ 97 .pull = NRF_GPIO_PIN_NOPULL, \ 98 .sense = NRF_GPIOTE_POLARITY_LOTOHI, \ 99 .skip_gpio_setup = true, \ 100 } 101 102 /**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect high-to-low transition. 103 * @details Set hi_accu to true to use IN_EVENT. 104 * @note This macro prepares configuration that skips GPIO setup. */ 105 #define NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_HITOLO(hi_accu) \ 106 { \ 107 .is_watcher = false, \ 108 .hi_accuracy = hi_accu, \ 109 .pull = NRF_GPIO_PIN_NOPULL, \ 110 .sense = NRF_GPIOTE_POLARITY_HITOLO, \ 111 .skip_gpio_setup = true, \ 112 } 113 114 /**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect any change on the pin. 115 * @details Set hi_accu to true to use IN_EVENT. 116 * @note This macro prepares configuration that skips GPIO setup. */ 117 #define NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_TOGGLE(hi_accu) \ 118 { \ 119 .is_watcher = false, \ 120 .hi_accuracy = hi_accu, \ 121 .pull = NRF_GPIO_PIN_NOPULL, \ 122 .sense = NRF_GPIOTE_POLARITY_TOGGLE, \ 123 .skip_gpio_setup = true, \ 124 } 125 126 127 /**@brief Output pin configuration. */ 128 typedef struct 129 { 130 nrf_gpiote_polarity_t action; /**< Configuration of the pin task. */ 131 nrf_gpiote_outinit_t init_state; /**< Initial state of the output pin. */ 132 bool task_pin; /**< True if the pin is controlled by a GPIOTE task. */ 133 } nrfx_gpiote_out_config_t; 134 135 /**@brief Macro for configuring a pin to use as output. GPIOTE is not used for the pin. */ 136 #define NRFX_GPIOTE_CONFIG_OUT_SIMPLE(init_high) \ 137 { \ 138 .init_state = init_high ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW, \ 139 .task_pin = false, \ 140 } 141 142 /**@brief Macro for configuring a pin to use the GPIO OUT TASK to change the state from high to low. 143 * @details The task will clear the pin. Therefore, the pin is set initially. */ 144 #define NRFX_GPIOTE_CONFIG_OUT_TASK_LOW \ 145 { \ 146 .init_state = NRF_GPIOTE_INITIAL_VALUE_HIGH, \ 147 .task_pin = true, \ 148 .action = NRF_GPIOTE_POLARITY_HITOLO, \ 149 } 150 151 /**@brief Macro for configuring a pin to use the GPIO OUT TASK to change the state from low to high. 152 * @details The task will set the pin. Therefore, the pin is cleared initially. */ 153 #define NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH \ 154 { \ 155 .init_state = NRF_GPIOTE_INITIAL_VALUE_LOW, \ 156 .task_pin = true, \ 157 .action = NRF_GPIOTE_POLARITY_LOTOHI, \ 158 } 159 160 /**@brief Macro for configuring a pin to use the GPIO OUT TASK to toggle the pin state. 161 * @details The initial pin state must be provided. */ 162 #define NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(init_high) \ 163 { \ 164 .init_state = init_high ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW, \ 165 .task_pin = true, \ 166 .action = NRF_GPIOTE_POLARITY_TOGGLE, \ 167 } 168 169 /** @brief Pin. */ 170 typedef uint32_t nrfx_gpiote_pin_t; 171 172 /** 173 * @brief Pin event handler prototype. 174 * 175 * @param pin Pin that triggered this event. 176 * @param action Action that lead to triggering this event. 177 */ 178 typedef void (*nrfx_gpiote_evt_handler_t)(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action); 179 180 /** 181 * @brief Function for initializing the GPIOTE module. 182 * 183 * @details Only static configuration is supported to prevent the shared 184 * resource being customized by the initiator. 185 * 186 * @retval NRFX_SUCCESS If initialization was successful. 187 * @retval NRFX_ERROR_INVALID_STATE If the driver was already initialized. 188 */ 189 nrfx_err_t nrfx_gpiote_init(void); 190 191 /** 192 * @brief Function for checking if the GPIOTE module is initialized. 193 * 194 * @details The GPIOTE module is a shared module. Therefore, you should check if 195 * the module is already initialized and skip initialization if it is. 196 * 197 * @retval true If the module is already initialized. 198 * @retval false If the module is not initialized. 199 */ 200 bool nrfx_gpiote_is_init(void); 201 202 /** 203 * @brief Function for uninitializing the GPIOTE module. 204 */ 205 void nrfx_gpiote_uninit(void); 206 207 /** 208 * @brief Function for initializing a GPIOTE output pin. 209 * @details The output pin can be controlled by the CPU or by PPI. The initial 210 * configuration specifies which mode is used. If PPI mode is used, the driver 211 * attempts to allocate one of the available GPIOTE channels. If no channel is 212 * available, an error is returned. 213 * 214 * @param[in] pin Pin. 215 * @param[in] p_config Initial configuration. 216 * 217 * @retval NRFX_SUCCESS If initialization was successful. 218 * @retval NRFX_ERROR_INVALID_STATE If the driver is not initialized or the pin is already used. 219 * @retval NRFX_ERROR_NO_MEM If no GPIOTE channel is available. 220 */ 221 nrfx_err_t nrfx_gpiote_out_init(nrfx_gpiote_pin_t pin, 222 nrfx_gpiote_out_config_t const * p_config); 223 224 /** 225 * @brief Function for uninitializing a GPIOTE output pin. 226 * @details The driver frees the GPIOTE channel if the output pin was using one. 227 * 228 * @param[in] pin Pin. 229 */ 230 void nrfx_gpiote_out_uninit(nrfx_gpiote_pin_t pin); 231 232 /** 233 * @brief Function for setting a GPIOTE output pin. 234 * 235 * @param[in] pin Pin. 236 */ 237 void nrfx_gpiote_out_set(nrfx_gpiote_pin_t pin); 238 239 /** 240 * @brief Function for clearing a GPIOTE output pin. 241 * 242 * @param[in] pin Pin. 243 */ 244 void nrfx_gpiote_out_clear(nrfx_gpiote_pin_t pin); 245 246 /** 247 * @brief Function for toggling a GPIOTE output pin. 248 * 249 * @param[in] pin Pin. 250 */ 251 void nrfx_gpiote_out_toggle(nrfx_gpiote_pin_t pin); 252 253 /** 254 * @brief Function for enabling a GPIOTE output pin task. 255 * 256 * @param[in] pin Pin. 257 */ 258 void nrfx_gpiote_out_task_enable(nrfx_gpiote_pin_t pin); 259 260 /** 261 * @brief Function for disabling a GPIOTE output pin task. 262 * 263 * @param[in] pin Pin. 264 */ 265 void nrfx_gpiote_out_task_disable(nrfx_gpiote_pin_t pin); 266 267 /** 268 * @brief Function for getting the address of a configurable GPIOTE task. 269 * 270 * @param[in] pin Pin. 271 * 272 * @return Address of OUT task. 273 */ 274 uint32_t nrfx_gpiote_out_task_addr_get(nrfx_gpiote_pin_t pin); 275 276 #if defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__) 277 /** 278 * @brief Function for getting the address of a configurable GPIOTE task. 279 * 280 * @param[in] pin Pin. 281 * 282 * @return Address of SET task. 283 */ 284 uint32_t nrfx_gpiote_set_task_addr_get(nrfx_gpiote_pin_t pin); 285 #endif // defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__) 286 287 #if defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__) 288 /** 289 * @brief Function for getting the address of a configurable GPIOTE task. 290 * 291 * @param[in] pin Pin. 292 * 293 * @return Address of CLR task. 294 */ 295 uint32_t nrfx_gpiote_clr_task_addr_get(nrfx_gpiote_pin_t pin); 296 #endif // defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__) 297 298 /** 299 * @brief Function for initializing a GPIOTE input pin. 300 * @details The input pin can act in two ways: 301 * - lower accuracy but low power (high frequency clock not needed) 302 * - higher accuracy (high frequency clock required) 303 * 304 * The initial configuration specifies which mode is used. 305 * If high-accuracy mode is used, the driver attempts to allocate one 306 * of the available GPIOTE channels. If no channel is 307 * available, an error is returned. 308 * In low accuracy mode SENSE feature is used. In this case only one active pin 309 * can be detected at a time. It can be worked around by setting all of the used 310 * low accuracy pins to toggle mode. 311 * For more information about SENSE functionality, refer to Product Specification. 312 * 313 * @param[in] pin Pin. 314 * @param[in] p_config Initial configuration. 315 * @param[in] evt_handler User function to be called when the configured transition occurs. 316 * 317 * @retval NRFX_SUCCESS If initialization was successful. 318 * @retval NRFX_ERROR_INVALID_STATE If the driver is not initialized or the pin is already used. 319 * @retval NRFX_ERROR_NO_MEM If no GPIOTE channel is available. 320 */ 321 nrfx_err_t nrfx_gpiote_in_init(nrfx_gpiote_pin_t pin, 322 nrfx_gpiote_in_config_t const * p_config, 323 nrfx_gpiote_evt_handler_t evt_handler); 324 325 /** 326 * @brief Function for uninitializing a GPIOTE input pin. 327 * @details The driver frees the GPIOTE channel if the input pin was using one. 328 * 329 * @param[in] pin Pin. 330 */ 331 void nrfx_gpiote_in_uninit(nrfx_gpiote_pin_t pin); 332 333 /** 334 * @brief Function for enabling sensing of a GPIOTE input pin. 335 * 336 * @details If the input pin is configured as high-accuracy pin, the function 337 * enables an IN_EVENT. Otherwise, the function enables the GPIO sense mechanism. 338 * Note that a PORT event is shared between multiple pins, therefore the 339 * interrupt is always enabled. 340 * 341 * @param[in] pin Pin. 342 * @param[in] int_enable True to enable the interrupt. Always valid for a high-accuracy pin. 343 */ 344 void nrfx_gpiote_in_event_enable(nrfx_gpiote_pin_t pin, bool int_enable); 345 346 /** 347 * @brief Function for disabling a GPIOTE input pin. 348 * 349 * @param[in] pin Pin. 350 */ 351 void nrfx_gpiote_in_event_disable(nrfx_gpiote_pin_t pin); 352 353 /** 354 * @brief Function for checking if a GPIOTE input pin is set. 355 * 356 * @param[in] pin Pin. 357 * 358 * @retval true If the input pin is set. 359 * @retval false If the input pin is not set. 360 */ 361 bool nrfx_gpiote_in_is_set(nrfx_gpiote_pin_t pin); 362 363 /** 364 * @brief Function for getting the address of a GPIOTE input pin event. 365 * @details If the pin is configured to use low-accuracy mode, the address of the PORT event is returned. 366 * 367 * @param[in] pin Pin. 368 */ 369 uint32_t nrfx_gpiote_in_event_addr_get(nrfx_gpiote_pin_t pin); 370 371 /** 372 * @brief Function for forcing a specific state on the pin configured as task. 373 * 374 * @param[in] pin Pin. 375 * @param[in] state Pin state. 376 */ 377 void nrfx_gpiote_out_task_force(nrfx_gpiote_pin_t pin, uint8_t state); 378 379 /** 380 * @brief Function for triggering the task OUT manually. 381 * 382 * @param[in] pin Pin. 383 */ 384 void nrfx_gpiote_out_task_trigger(nrfx_gpiote_pin_t pin); 385 386 #if defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__) 387 /** 388 * @brief Function for triggering the task SET manually. 389 * 390 * @param[in] pin Pin. 391 */ 392 void nrfx_gpiote_set_task_trigger(nrfx_gpiote_pin_t pin); 393 #endif // defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__) 394 395 #if defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__) 396 /** 397 * @brief Function for triggering the task CLR manually. 398 * 399 * @param[in] pin Pin. 400 */ 401 void nrfx_gpiote_clr_task_trigger(nrfx_gpiote_pin_t pin); 402 #endif // defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__) 403 404 405 void nrfx_gpiote_irq_handler(void); 406 407 408 /** @} */ 409 410 #ifdef __cplusplus 411 } 412 #endif 413 414 #endif // NRFX_GPIOTE_H__ 415