app_gpiote.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
  2. *
  3. * The information contained herein is property of Nordic Semiconductor ASA.
  4. * Terms and conditions of usage are described in detail in NORDIC
  5. * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
  6. *
  7. * Licensees are granted free, non-transferable use of the information. NO
  8. * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
  9. * the file.
  10. *
  11. */
  12. #include "app_gpiote.h"
  13. #include "nrf_drv_gpiote.h"
  14. #include "sdk_common.h"
  15. /**@brief GPIOTE user type. */
  16. typedef struct
  17. {
  18. uint32_t pins_mask; /**< Mask defining which pins user wants to monitor. */
  19. uint32_t pins_low_to_high_mask; /**< Mask defining which pins will generate events to this user when toggling low->high. */
  20. uint32_t pins_high_to_low_mask; /**< Mask defining which pins will generate events to this user when toggling high->low. */
  21. uint32_t sense_high_pins; /**< Mask defining which pins are configured to generate GPIOTE interrupt on transition to high level. */
  22. app_gpiote_event_handler_t event_handler; /**< Pointer to function to be executed when an event occurs. */
  23. bool enabled; /**< Flag indicating whether user is enabled. */
  24. } gpiote_user_t;
  25. STATIC_ASSERT(sizeof(gpiote_user_t) <= GPIOTE_USER_NODE_SIZE);
  26. STATIC_ASSERT(sizeof(gpiote_user_t) % 4 == 0);
  27. static uint8_t m_user_array_size; /**< Size of user array. */
  28. static uint8_t m_user_count; /**< Number of registered users. */
  29. static gpiote_user_t * mp_users = NULL; /**< Array of GPIOTE users. */
  30. static uint32_t m_pins; /**< Mask of initialized pins. */
  31. static uint32_t m_last_pins_state; /**< Most recent state of pins. */
  32. #define MODULE_INITIALIZED (mp_users != NULL)
  33. #include "sdk_macros.h"
  34. void gpiote_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
  35. {
  36. int i;
  37. uint32_t pin_mask = 1 << pin;
  38. bool hitolo = (m_last_pins_state & pin_mask) ? true : false;
  39. m_last_pins_state = nrf_gpio_pins_read();
  40. for (i = 0; i < m_user_count; i++)
  41. {
  42. if (mp_users[i].enabled && (pin_mask & mp_users[i].pins_mask))
  43. {
  44. if ((pin_mask & mp_users[i].pins_high_to_low_mask) && hitolo)
  45. {
  46. mp_users[i].event_handler(0,pin_mask);
  47. }
  48. else if ((pin_mask & mp_users[i].pins_low_to_high_mask) && !hitolo)
  49. {
  50. mp_users[i].event_handler(pin_mask,0);
  51. }
  52. }
  53. }
  54. }
  55. uint32_t app_gpiote_init(uint8_t max_users, void * p_buffer)
  56. {
  57. uint32_t ret_code = NRF_SUCCESS;
  58. if (p_buffer == NULL)
  59. {
  60. return NRF_ERROR_INVALID_PARAM;
  61. }
  62. // Check that buffer is correctly aligned.
  63. if (!is_word_aligned(p_buffer))
  64. {
  65. return NRF_ERROR_INVALID_PARAM;
  66. }
  67. // Initialize file globals.
  68. mp_users = (gpiote_user_t *)p_buffer;
  69. m_user_array_size = max_users;
  70. m_user_count = 0;
  71. m_pins = 0;
  72. memset(mp_users, 0, m_user_array_size * sizeof(gpiote_user_t));
  73. if (nrf_drv_gpiote_is_init()==false)
  74. {
  75. ret_code = nrf_drv_gpiote_init();
  76. }
  77. return ret_code;
  78. }
  79. uint32_t app_gpiote_user_register(app_gpiote_user_id_t * p_user_id,
  80. uint32_t pins_low_to_high_mask,
  81. uint32_t pins_high_to_low_mask,
  82. app_gpiote_event_handler_t event_handler)
  83. {
  84. uint32_t user_pin_mask;
  85. uint32_t ret_val = NRF_SUCCESS;
  86. // Check state and parameters.
  87. VERIFY_MODULE_INITIALIZED();
  88. if (event_handler == NULL)
  89. {
  90. return NRF_ERROR_INVALID_PARAM;
  91. }
  92. if (m_user_count >= m_user_array_size)
  93. {
  94. return NRF_ERROR_NO_MEM;
  95. }
  96. user_pin_mask = pins_low_to_high_mask | pins_high_to_low_mask;
  97. // Allocate new user.
  98. mp_users[m_user_count].pins_mask = user_pin_mask;
  99. mp_users[m_user_count].pins_low_to_high_mask = pins_low_to_high_mask;
  100. mp_users[m_user_count].pins_high_to_low_mask = pins_high_to_low_mask;
  101. mp_users[m_user_count].event_handler = event_handler;
  102. mp_users[m_user_count].enabled = false;
  103. *p_user_id = m_user_count++;
  104. uint32_t mask = 1;
  105. uint32_t i;
  106. const nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);
  107. for (i = 0; i < 32; i++)
  108. {
  109. if ((mask & user_pin_mask) & ~m_pins)
  110. {
  111. ret_val = nrf_drv_gpiote_in_init(i, &config, gpiote_handler);
  112. VERIFY_SUCCESS(ret_val);
  113. m_pins |= mask;
  114. }
  115. mask <<= 1;
  116. }
  117. return ret_val;
  118. }
  119. __STATIC_INLINE uint32_t error_check(app_gpiote_user_id_t user_id)
  120. {
  121. // Check state and parameters.
  122. VERIFY_MODULE_INITIALIZED();
  123. if (user_id >= m_user_count)
  124. {
  125. return NRF_ERROR_INVALID_PARAM;
  126. }
  127. return NRF_SUCCESS;
  128. }
  129. /**
  130. * @brief Function for enabling event on pin (if not yet enabled) or disabling the event if no other
  131. * user requires it.
  132. *
  133. * @param pin Pin to enable
  134. * @param enable If true function will attempt to enable the pin else it will attempt to disable it.
  135. */
  136. static void pin_event_enable(uint32_t pin, bool enable)
  137. {
  138. uint32_t i;
  139. uint32_t pin_mask = 1UL << pin;
  140. bool enabled = false;
  141. //search if any user already enabled given pin
  142. for (i = 0; i < m_user_count; i++)
  143. {
  144. if (mp_users[i].enabled && (mp_users[i].pins_mask & pin_mask))
  145. {
  146. enabled = true;
  147. break;
  148. }
  149. }
  150. if (!enabled)
  151. {
  152. if (enable)
  153. {
  154. m_last_pins_state = nrf_gpio_pins_read();
  155. nrf_drv_gpiote_in_event_enable(pin, true);
  156. }
  157. else
  158. {
  159. nrf_drv_gpiote_in_event_disable(pin);
  160. }
  161. }
  162. }
  163. /**
  164. * @brief Function for enabling or disabling events for pins used by the user.
  165. *
  166. * Function will enable pin events only if they are not yet enabled. Function will disable pin
  167. * events only if there is no other enabled user that is using them.
  168. *
  169. * @param user_id User id.
  170. * @param enable If true function will attempt to enable the pin else it will attempt to disable it.
  171. */
  172. static uint32_t user_enable(app_gpiote_user_id_t user_id, bool enable)
  173. {
  174. uint32_t ret_code = error_check(user_id);
  175. if (ret_code == NRF_SUCCESS)
  176. {
  177. uint32_t i;
  178. uint32_t mask = 1UL;
  179. for (i = 0; i < 32; i++)
  180. {
  181. if (mp_users[user_id].pins_mask & mask)
  182. {
  183. pin_event_enable(i, enable);
  184. }
  185. mask <<= 1;
  186. }
  187. }
  188. return ret_code;
  189. }
  190. uint32_t app_gpiote_user_enable(app_gpiote_user_id_t user_id)
  191. {
  192. uint32_t ret_code = NRF_SUCCESS;
  193. if (mp_users[user_id].enabled == false)
  194. {
  195. ret_code = user_enable(user_id, true);
  196. VERIFY_SUCCESS(ret_code);
  197. mp_users[user_id].enabled = true;
  198. return ret_code;
  199. }
  200. else
  201. {
  202. return ret_code;
  203. }
  204. }
  205. uint32_t app_gpiote_user_disable(app_gpiote_user_id_t user_id)
  206. {
  207. uint32_t ret_code = NRF_SUCCESS;
  208. if (mp_users[user_id].enabled)
  209. {
  210. mp_users[user_id].enabled = false;
  211. ret_code = user_enable(user_id, false);
  212. }
  213. return ret_code;
  214. }
  215. uint32_t app_gpiote_pins_state_get(app_gpiote_user_id_t user_id, uint32_t * p_pins)
  216. {
  217. gpiote_user_t * p_user;
  218. uint32_t ret_code = error_check(user_id);
  219. if (ret_code == NRF_SUCCESS)
  220. {
  221. p_user = &mp_users[user_id];
  222. // Get pins.
  223. *p_pins = nrf_gpio_pins_read() & p_user->pins_mask;
  224. }
  225. return ret_code;
  226. }