Nordic stack and drivers for the mbed BLE API

Dependents:   idd_hw5_bleFanProto

Fork of nRF51822 by Nordic Semiconductor

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers app_gpiote.c Source File

app_gpiote.c

00001 /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
00002  *
00003  * The information contained herein is property of Nordic Semiconductor ASA.
00004  * Terms and conditions of usage are described in detail in NORDIC
00005  * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
00006  *
00007  * Licensees are granted free, non-transferable use of the information. NO
00008  * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
00009  * the file.
00010  *
00011  */
00012 
00013 #if NEED_APP_GPIOTE /* disabled by default */
00014 
00015 #include "app_gpiote.h "
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include "app_util.h "
00019 #include "app_util_platform.h "
00020 #include "nrf_error.h"
00021 #include "nrf_gpio.h"
00022 
00023 
00024 /**@brief GPIOTE user type. */
00025 typedef struct
00026 {
00027     uint32_t                   pins_mask;             /**< Mask defining which pins user wants to monitor. */
00028     uint32_t                   pins_low_to_high_mask; /**< Mask defining which pins will generate events to this user when toggling low->high. */
00029     uint32_t                   pins_high_to_low_mask; /**< Mask defining which pins will generate events to this user when toggling high->low. */
00030     uint32_t                   sense_high_pins;       /**< Mask defining which pins are configured to generate GPIOTE interrupt on transition to high level. */
00031     app_gpiote_event_handler_t event_handler;         /**< Pointer to function to be executed when an event occurs. */
00032 } gpiote_user_t;
00033 
00034 STATIC_ASSERT(sizeof(gpiote_user_t) <= GPIOTE_USER_NODE_SIZE);
00035 STATIC_ASSERT(sizeof(gpiote_user_t) % 4 == 0);
00036 
00037 static uint32_t        m_enabled_users_mask;          /**< Mask for tracking which users are enabled. */
00038 static uint8_t         m_user_array_size;             /**< Size of user array. */
00039 static uint8_t         m_user_count;                  /**< Number of registered users. */
00040 static gpiote_user_t * mp_users = NULL;               /**< Array of GPIOTE users. */
00041 
00042 
00043 /**@brief Function for toggling sense level for specified pins.
00044  *
00045  * @param[in]   p_user   Pointer to user structure.
00046  * @param[in]   pins     Bitmask specifying for which pins the sense level is to be toggled.
00047  */
00048 static void sense_level_toggle(gpiote_user_t * p_user, uint32_t pins)
00049 {
00050     uint32_t pin_no;
00051 
00052     for (pin_no = 0; pin_no < NO_OF_PINS; pin_no++)
00053     {
00054         uint32_t pin_mask = (1 << pin_no);
00055 
00056         if ((pins & pin_mask) != 0)
00057         {
00058             uint32_t sense;
00059 
00060             // Invert sensing.
00061             if ((p_user->sense_high_pins & pin_mask) == 0)
00062             {
00063                 sense                    = GPIO_PIN_CNF_SENSE_High << GPIO_PIN_CNF_SENSE_Pos;
00064                 p_user->sense_high_pins |= pin_mask;
00065             }
00066             else
00067             {
00068                 sense                    = GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos;
00069                 p_user->sense_high_pins &= ~pin_mask;
00070             }
00071 
00072             NRF_GPIO->PIN_CNF[pin_no] &= ~GPIO_PIN_CNF_SENSE_Msk;
00073             NRF_GPIO->PIN_CNF[pin_no] |= sense;
00074         }
00075     }
00076 }
00077 
00078 
00079 /**@brief Function for handling the GPIOTE interrupt.
00080  */
00081 void GPIOTE_IRQHandler(void)
00082 {
00083     uint8_t  i;
00084     uint32_t pins_changed;
00085     uint32_t pins_state = NRF_GPIO->IN;
00086 
00087     // Clear event.
00088     NRF_GPIOTE->EVENTS_PORT = 0;
00089 
00090     // Check all users.
00091     for (i = 0; i < m_user_count; i++)
00092     {
00093         gpiote_user_t * p_user = &mp_users[i];
00094 
00095         // Check if user is enabled.
00096         if (((1 << i) & m_enabled_users_mask) != 0)
00097         {
00098             uint32_t transition_pins;
00099             uint32_t event_low_to_high;
00100             uint32_t event_high_to_low;
00101 
00102             // Find set of pins on which there has been a transition.
00103             transition_pins = (pins_state ^ ~p_user->sense_high_pins) & p_user->pins_mask;
00104 
00105             // Toggle SENSE level for all pins that have changed state.
00106             sense_level_toggle(p_user, transition_pins);
00107 
00108             // Second read after setting sense.
00109             // Check if any pins have changed while serving this interrupt.
00110             pins_changed = NRF_GPIO->IN ^ pins_state;
00111             if (pins_changed)
00112             {
00113                 // Transition pins detected in late stage.
00114                 uint32_t late_transition_pins;
00115 
00116                 pins_state          |= pins_changed;
00117 
00118                 // Find set of pins on which there has been a transition.
00119                 late_transition_pins = (pins_state ^ ~p_user->sense_high_pins) & p_user->pins_mask;
00120 
00121                 // Toggle SENSE level for all pins that have changed state in last phase.
00122                 sense_level_toggle(p_user, late_transition_pins);
00123 
00124                 // Update pins that has changed state since the interrupt occurred.
00125                 transition_pins |= late_transition_pins;
00126             }
00127 
00128             // Call user event handler if an event has occurred.
00129             event_high_to_low = (~pins_state & p_user->pins_high_to_low_mask) & transition_pins;
00130             event_low_to_high = (pins_state & p_user->pins_low_to_high_mask) & transition_pins;
00131 
00132             if ((event_low_to_high | event_high_to_low) != 0)
00133             {
00134                 p_user->event_handler(event_low_to_high, event_high_to_low);
00135             }
00136         }
00137     }
00138 }
00139 
00140 
00141 /**@brief Function for sense disabling for all pins for specified user.
00142  *
00143  * @param[in]  user_id   User id.
00144  */
00145 static void pins_sense_disable(app_gpiote_user_id_t user_id)
00146 {
00147     uint32_t pin_no;
00148 
00149     for (pin_no = 0; pin_no < 32; pin_no++)
00150     {
00151         if ((mp_users[user_id].pins_mask & (1 << pin_no)) != 0)
00152         {
00153             NRF_GPIO->PIN_CNF[pin_no] &= ~GPIO_PIN_CNF_SENSE_Msk;
00154             NRF_GPIO->PIN_CNF[pin_no] |= GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos;
00155         }
00156     }
00157 }
00158 
00159 
00160 uint32_t app_gpiote_init(uint8_t max_users, void * p_buffer)
00161 {
00162     if (p_buffer == NULL)
00163     {
00164         return NRF_ERROR_INVALID_PARAM;
00165     }
00166 
00167     // Check that buffer is correctly aligned.
00168     if (!is_word_aligned(p_buffer))
00169     {
00170         return NRF_ERROR_INVALID_PARAM;
00171     }
00172 
00173     // Initialize file globals.
00174     mp_users             = (gpiote_user_t *)p_buffer;
00175     m_user_array_size    = max_users;
00176     m_user_count         = 0;
00177     m_enabled_users_mask = 0;
00178 
00179     memset(mp_users, 0, m_user_array_size * sizeof(gpiote_user_t));
00180 
00181     // Initialize GPIOTE interrupt (will not be enabled until app_gpiote_user_enable() is called).
00182     NRF_GPIOTE->INTENCLR = 0xFFFFFFFF;
00183 
00184     NVIC_ClearPendingIRQ(GPIOTE_IRQn);
00185     NVIC_SetPriority(GPIOTE_IRQn, APP_IRQ_PRIORITY_HIGH);
00186     NVIC_EnableIRQ(GPIOTE_IRQn);
00187 
00188     return NRF_SUCCESS;
00189 }
00190 
00191 
00192 uint32_t app_gpiote_user_register(app_gpiote_user_id_t     * p_user_id,
00193                                   uint32_t                   pins_low_to_high_mask,
00194                                   uint32_t                   pins_high_to_low_mask,
00195                                   app_gpiote_event_handler_t event_handler)
00196 {
00197     // Check state and parameters.
00198     if (mp_users == NULL)
00199     {
00200         return NRF_ERROR_INVALID_STATE;
00201     }
00202     if (event_handler == NULL)
00203     {
00204         return NRF_ERROR_INVALID_PARAM;
00205     }
00206     if (m_user_count >= m_user_array_size)
00207     {
00208         return NRF_ERROR_NO_MEM;
00209     }
00210 
00211     // Allocate new user.
00212     mp_users[m_user_count].pins_mask             = pins_low_to_high_mask | pins_high_to_low_mask;
00213     mp_users[m_user_count].pins_low_to_high_mask = pins_low_to_high_mask;
00214     mp_users[m_user_count].pins_high_to_low_mask = pins_high_to_low_mask;
00215     mp_users[m_user_count].event_handler         = event_handler;
00216 
00217     *p_user_id = m_user_count++;
00218 
00219     // Make sure SENSE is disabled for all pins.
00220     pins_sense_disable(*p_user_id);
00221 
00222     return NRF_SUCCESS;
00223 }
00224 
00225 
00226 uint32_t app_gpiote_user_enable(app_gpiote_user_id_t user_id)
00227 {
00228     uint32_t pin_no;
00229     uint32_t pins_state;
00230 
00231     // Check state and parameters.
00232     if (mp_users == NULL)
00233     {
00234         return NRF_ERROR_INVALID_STATE;
00235     }
00236     if (user_id >= m_user_count)
00237     {
00238         return NRF_ERROR_INVALID_PARAM;
00239     }
00240 
00241     // Clear any pending event.
00242     NRF_GPIOTE->EVENTS_PORT = 0;
00243     pins_state              = NRF_GPIO->IN;
00244 
00245     // Enable user.
00246     if (m_enabled_users_mask == 0)
00247     {
00248         NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Msk;
00249     }
00250     m_enabled_users_mask |= (1 << user_id);
00251 
00252     // Enable sensing for all pins for specified user.
00253     mp_users[user_id].sense_high_pins = 0;
00254     for (pin_no = 0; pin_no < 32; pin_no++)
00255     {
00256         uint32_t pin_mask = (1 << pin_no);
00257 
00258         if ((mp_users[user_id].pins_mask & pin_mask) != 0)
00259         {
00260             uint32_t sense;
00261 
00262             if ((pins_state & pin_mask) != 0)
00263             {
00264                 sense = GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos;
00265             }
00266             else
00267             {
00268                 sense = GPIO_PIN_CNF_SENSE_High << GPIO_PIN_CNF_SENSE_Pos;
00269                 mp_users[user_id].sense_high_pins |= pin_mask;
00270             }
00271 
00272             NRF_GPIO->PIN_CNF[pin_no] &= ~GPIO_PIN_CNF_SENSE_Msk;
00273             NRF_GPIO->PIN_CNF[pin_no] |= sense;
00274         }
00275     }
00276 
00277     return NRF_SUCCESS;
00278 }
00279 
00280 
00281 uint32_t app_gpiote_user_disable(app_gpiote_user_id_t user_id)
00282 {
00283     // Check state and parameters.
00284     if (mp_users == NULL)
00285     {
00286         return NRF_ERROR_INVALID_STATE;
00287     }
00288     if (user_id >= m_user_count)
00289     {
00290         return NRF_ERROR_INVALID_PARAM;
00291     }
00292 
00293     // Disable sensing for all pins for specified user.
00294     pins_sense_disable(user_id);
00295 
00296     // Disable user.
00297     m_enabled_users_mask &= ~(1UL << user_id);
00298     if (m_enabled_users_mask == 0)
00299     {
00300         NRF_GPIOTE->INTENCLR = GPIOTE_INTENSET_PORT_Msk;
00301     }
00302 
00303     return NRF_SUCCESS;
00304 }
00305 
00306 
00307 uint32_t app_gpiote_pins_state_get(app_gpiote_user_id_t user_id, uint32_t * p_pins)
00308 {
00309     gpiote_user_t * p_user;
00310 
00311     // Check state and parameters.
00312     if (mp_users == NULL)
00313     {
00314         return NRF_ERROR_INVALID_STATE;
00315     }
00316     if (user_id >= m_user_count)
00317     {
00318         return NRF_ERROR_INVALID_PARAM;
00319     }
00320 
00321     // Get pins.
00322     p_user  = &mp_users[user_id];
00323     *p_pins = NRF_GPIO->IN & p_user->pins_mask;
00324 
00325     return NRF_SUCCESS;
00326 }
00327 
00328 #if defined(SVCALL_AS_NORMAL_FUNCTION) || defined(SER_CONNECTIVITY)
00329 uint32_t app_gpiote_input_event_handler_register(const uint8_t                    channel,
00330                                                  const uint32_t                   pin,
00331                                                  const uint32_t                   polarity,
00332                                                  app_gpiote_input_event_handler_t event_handler)
00333 {
00334     (void)sense_level_toggle(NULL, pin);
00335     return NRF_ERROR_NOT_SUPPORTED;
00336 }
00337 
00338 uint32_t app_gpiote_input_event_handler_unregister(const uint8_t channel)
00339 {
00340     return NRF_ERROR_NOT_SUPPORTED;
00341 }
00342 
00343 uint32_t app_gpiote_end_irq_event_handler_register(app_gpiote_input_event_handler_t event_handler)
00344 {
00345     return NRF_ERROR_NOT_SUPPORTED;
00346 }
00347 
00348 uint32_t app_gpiote_end_irq_event_handler_unregister(void)
00349 {
00350     return NRF_ERROR_NOT_SUPPORTED;
00351 }
00352 
00353 uint32_t app_gpiote_enable_interrupts(void)
00354 {
00355     return NRF_ERROR_NOT_SUPPORTED;
00356 }
00357 
00358 uint32_t app_gpiote_disable_interrupts(void)
00359 {
00360     return NRF_ERROR_NOT_SUPPORTED;
00361 }
00362 #endif // SVCALL_AS_NORMAL_FUNCTION || SER_CONNECTIVITY
00363 
00364 #endif // #if NEED_APP_GPIOTE