/* * Copyright (c) 2015, Nordic Semiconductor * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``as-is'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /*---------------------------------------------------------------------------*/ /** * \addtogroup nrf52dk-devices Device drivers * @{ * * \addtogroup nrf52dk-devices-button Buttons driver * @{ * * \file * Driver for nRF52 DK buttons. * \author * Wojciech Bober */ /*---------------------------------------------------------------------------*/ #include #include "nordic_common.h" #include "nrf_drv_gpiote.h" #include "nrf_assert.h" #include "boards.h" #include "contiki.h" #include "lib/sensors.h" #include "button-sensor.h" /*---------------------------------------------------------------------------*/ #define DEBOUNCE_DURATION (CLOCK_SECOND >> 5) /**< Delay before button state is assumed to be stable */ /*---------------------------------------------------------------------------*/ struct btn_timer { struct timer debounce; clock_time_t start; clock_time_t duration; }; static struct btn_timer btn_timer[BUTTONS_NUMBER]; static int btn_state = 0; /*---------------------------------------------------------------------------*/ /** * \brief Button toggle handler * \param pin GPIO pin which has been triggered * \param action toggle direction * */ static void gpiote_event_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { int id = pin - BUTTON_START; if(!timer_expired(&(btn_timer[id].debounce))) { return; } /* Set timer to ignore consecutive changes for * DEBOUNCE_DURATION. */ timer_set(&(btn_timer[id].debounce), DEBOUNCE_DURATION); /* * Start measuring duration on falling edge, stop on rising edge. */ if(nrf_drv_gpiote_in_is_set(pin) == 0) { btn_timer[id].start = clock_time(); btn_timer[id].duration = 0; } else { btn_timer[id].duration = clock_time() - btn_timer[id].start; } sensors_changed(&buttons[id]); } /*---------------------------------------------------------------------------*/ /** * \brief Configuration function for the button sensor for all buttons. * * \param type if \a SENSORS_HW_INIT is passed the function will initialize * given button * if \a SENSORS_ACTIVE is passed then \p c parameter defines * whether button should be set active or inactive * \param c 0 to disable the button, non-zero: enable * \param pin GPIOE pin number */ static int config(int type, int c, nrf_drv_gpiote_pin_t pin) { int id = pin - BUTTON_START; switch(type) { case SENSORS_HW_INIT: { nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false); config.pull = NRF_GPIO_PIN_PULLUP; nrf_drv_gpiote_in_init(pin, &config, gpiote_event_handler); timer_set(&(btn_timer[id].debounce), DEBOUNCE_DURATION); return 1; } case SENSORS_ACTIVE: { if(c) { nrf_drv_gpiote_in_event_enable(pin, true); btn_state |= (1 << id); } else { nrf_drv_gpiote_in_event_disable(pin); btn_state &= ~(1 << id); } return 1; } default: return 0; } } /*---------------------------------------------------------------------------*/ /** * \brief Configuration function for button 1 * * \param type passed to config() as-is * \param value passed to config() as-is * \return same as config() return value */ static int config_button_1(int type, int value) { return config(type, value, BSP_BUTTON_0); } /*---------------------------------------------------------------------------*/ /** * \brief Configuration function for button 2 * * \param type passed to config() as-is * \param value passed to config() as-is * \return same as config() return value */ static int config_button_2(int type, int value) { return config(type, value, BSP_BUTTON_1); } /*---------------------------------------------------------------------------*/ /** * \brief Configuration function for button 3 * * \param type passed to config() as-is * \param value passed to config() as-is * \return same as config() return value */ static int config_button_3(int type, int value) { return config(type, value, BSP_BUTTON_2); } /*---------------------------------------------------------------------------*/ /** * \brief Configuration function for button 4 * * \param type passed to config() as-is * \param value passed to config() as-is * \return same as config() return value */ static int config_button_4(int type, int value) { return config(type, value, BSP_BUTTON_3); } /*---------------------------------------------------------------------------*/ /** * \brief Return current state of a button * \param type pass \ref BUTTON_SENSOR_VALUE_STATE to get current button state * or \ref BUTTON_SENSOR_VALUE_DURATION to get active state duration * \param pin GPIOE pin number * * \retval BUTTON_SENSOR_VALUE_PRESSED * \retval BUTTON_SENSOR_VALUE_RELEASED when \a type is \ref BUTTON_SENSOR_VALUE_STATE * \retval duration Active state duration in clock ticks */ static int value(int type, nrf_drv_gpiote_pin_t pin) { if(type == BUTTON_SENSOR_VALUE_STATE) { return nrf_drv_gpiote_in_is_set(pin) == 0 ? BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; } else if(type == BUTTON_SENSOR_VALUE_DURATION) { return btn_timer[pin - BUTTON_START].duration; } return 0; } /*---------------------------------------------------------------------------*/ /** * \brief Return current state of a button 1 * \param type passed to value() as-is * \return same as value returned by value() */ static int value_button_1(int type) { return value(type, BSP_BUTTON_0); } /*---------------------------------------------------------------------------*/ /** * \brief Return current state of a button 2 * \param type passed to value() as-is * \return same as value returned by value() */ static int value_button_2(int type) { return value(type, BSP_BUTTON_1); } /*---------------------------------------------------------------------------*/ /** * \brief Return current state of a button 3 * \param type passed to value() as-is * \return same as value returned by value() */ static int value_button_3(int type) { return value(type, BSP_BUTTON_2); } /*---------------------------------------------------------------------------*/ /** * \brief Return current state of a button 4 * \param type passed to value() as-is * \return same as value returned by value() */ static int value_button_4(int type) { return value(type, BSP_BUTTON_3); } /*---------------------------------------------------------------------------*/ /** * \brief Get status of a given button * \param type \a SENSORS_ACTIVE or \a SENSORS_READY * \param pin GPIOE pin number * \return 1 if the button's port interrupt is enabled */ static int status(int type, nrf_drv_gpiote_pin_t pin) { switch(type) { case SENSORS_ACTIVE: case SENSORS_READY: return (btn_state & (1 << (pin - BUTTON_START))); default: break; } return 0; } /*---------------------------------------------------------------------------*/ /** * \brief Status function for button 1 * \param type passed to state() as-is * \return value returned by state() */ static int status_button_1(int type) { return status(type, BSP_BUTTON_0); } /*---------------------------------------------------------------------------*/ /** * \brief Status function for button 2 * \param type passed to state() as-is * \return value returned by state() */ static int status_button_2(int type) { return status(type, BSP_BUTTON_1); } /*---------------------------------------------------------------------------*/ /** * \brief Status function for button 3 * \param type passed to state() as-is * \return value returned by state() */ static int status_button_3(int type) { return status(type, BSP_BUTTON_2); } /*---------------------------------------------------------------------------*/ /** * \brief Status function for button 3 * \param type passed to state() as-is * \return value returned by state() */ static int status_button_4(int type) { return status(type, BSP_BUTTON_3); } /*---------------------------------------------------------------------------*/ const struct sensors_sensor buttons[BUTTONS_NUMBER] = { {BUTTON_SENSOR, value_button_1, config_button_1, status_button_1}, {BUTTON_SENSOR, value_button_2, config_button_2, status_button_2}, {BUTTON_SENSOR, value_button_3, config_button_3, status_button_3}, {BUTTON_SENSOR, value_button_4, config_button_4, status_button_4}, }; /*---------------------------------------------------------------------------*/ /** * @} * @} */