Contiki 3.x
button-sensor.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/
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
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 /*---------------------------------------------------------------------------*/
31 /**
32  * \addtogroup sensortag-cc26xx-button-sensor
33  * @{
34  *
35  * \file
36  * Driver for the Sensortag-CC26xx buttons
37  */
38 /*---------------------------------------------------------------------------*/
39 #include "contiki.h"
40 #include "lib/sensors.h"
42 #include "gpio-interrupt.h"
43 #include "sys/timer.h"
44 #include "lpm.h"
45 
46 #include "ti-lib.h"
47 
48 #include <stdint.h>
49 /*---------------------------------------------------------------------------*/
50 #ifdef BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN
51 #define BUTTON_SENSOR_ENABLE_SHUTDOWN BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN
52 #else
53 #define BUTTON_SENSOR_ENABLE_SHUTDOWN 1
54 #endif
55 /*---------------------------------------------------------------------------*/
56 #define BUTTON_GPIO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \
57  IOC_IOPULL_UP | IOC_SLEW_DISABLE | \
58  IOC_HYST_DISABLE | IOC_BOTH_EDGES | \
59  IOC_INT_ENABLE | IOC_IOMODE_NORMAL | \
60  IOC_NO_WAKE_UP | IOC_INPUT_ENABLE)
61 /*---------------------------------------------------------------------------*/
62 #define DEBOUNCE_DURATION (CLOCK_SECOND >> 5)
63 
64 struct btn_timer {
65  struct timer debounce;
66  clock_time_t start;
67  clock_time_t duration;
68 };
69 
70 static struct btn_timer left_timer, right_timer;
71 /*---------------------------------------------------------------------------*/
72 /**
73  * \brief Handler for Sensortag-CC26XX button presses
74  */
75 static void
76 button_press_handler(uint8_t ioid)
77 {
78  if(ioid == BOARD_IOID_KEY_LEFT) {
79  if(!timer_expired(&left_timer.debounce)) {
80  return;
81  }
82 
83  timer_set(&left_timer.debounce, DEBOUNCE_DURATION);
84 
85  /*
86  * Start press duration counter on press (falling), notify on release
87  * (rising)
88  */
89  if(ti_lib_gpio_pin_read(BOARD_KEY_LEFT) == 0) {
90  left_timer.start = clock_time();
91  left_timer.duration = 0;
92  } else {
93  left_timer.duration = clock_time() - left_timer.start;
94  sensors_changed(&button_left_sensor);
95  }
96  }
97 
98  if(ioid == BOARD_IOID_KEY_RIGHT) {
99  if(BUTTON_SENSOR_ENABLE_SHUTDOWN == 0) {
100  if(!timer_expired(&right_timer.debounce)) {
101  return;
102  }
103 
104  timer_set(&right_timer.debounce, DEBOUNCE_DURATION);
105 
106  /*
107  * Start press duration counter on press (falling), notify on release
108  * (rising)
109  */
110  if(ti_lib_gpio_pin_read(BOARD_KEY_RIGHT) == 0) {
111  right_timer.start = clock_time();
112  right_timer.duration = 0;
113  } else {
114  right_timer.duration = clock_time() - right_timer.start;
115  sensors_changed(&button_right_sensor);
116  }
117  } else {
118  lpm_shutdown(BOARD_IOID_KEY_RIGHT, IOC_IOPULL_UP, IOC_WAKE_ON_LOW);
119  }
120  }
121 }
122 /*---------------------------------------------------------------------------*/
123 /**
124  * \brief Configuration function for the button sensor for all buttons.
125  *
126  * \param type This function does nothing unless type == SENSORS_ACTIVE
127  * \param c 0: disable the button, non-zero: enable
128  * \param key: One of BOARD_KEY_LEFT, BOARD_KEY_RIGHT etc
129  */
130 static void
131 config_buttons(int type, int c, uint32_t key)
132 {
133  switch(type) {
134  case SENSORS_HW_INIT:
135  ti_lib_gpio_event_clear(1 << key);
136  ti_lib_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG);
137  ti_lib_gpio_dir_mode_set((1 << key), GPIO_DIR_MODE_IN);
139  break;
140  case SENSORS_ACTIVE:
141  if(c) {
142  ti_lib_gpio_event_clear(1 << key);
143  ti_lib_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG);
144  ti_lib_gpio_dir_mode_set((1 << key), GPIO_DIR_MODE_IN);
145  ti_lib_ioc_int_enable(key);
146  } else {
147  ti_lib_ioc_int_disable(key);
148  }
149  break;
150  default:
151  break;
152  }
153 }
154 /*---------------------------------------------------------------------------*/
155 /**
156  * \brief Configuration function for the left button.
157  *
158  * Parameters are passed onto config_buttons, which does the actual
159  * configuration
160  * Parameters are ignored. They have been included because the prototype is
161  * dictated by the core sensor API. The return value is also required by
162  * the API but otherwise ignored.
163  *
164  * \param type passed to config_buttons as-is
165  * \param value passed to config_buttons as-is
166  *
167  * \return ignored
168  */
169 static int
170 config_left(int type, int value)
171 {
172  config_buttons(type, value, BOARD_IOID_KEY_LEFT);
173 
174  return 1;
175 }
176 /*---------------------------------------------------------------------------*/
177 /**
178  * \brief Configuration function for the right button.
179  *
180  * Parameters are passed onto config_buttons, which does the actual
181  * configuration
182  * Parameters are ignored. They have been included because the prototype is
183  * dictated by the core sensor api. The return value is also required by
184  * the API but otherwise ignored.
185  *
186  * \param type passed to config_buttons as-is
187  * \param value passed to config_buttons as-is
188  *
189  * \return ignored
190  */
191 static int
192 config_right(int type, int value)
193 {
194  config_buttons(type, value, BOARD_IOID_KEY_RIGHT);
195 
196  return 1;
197 }
198 /*---------------------------------------------------------------------------*/
199 /**
200  * \brief Status function for all buttons
201  * \param type SENSORS_ACTIVE or SENSORS_READY
202  * \param key_io_id BOARD_IOID_KEY_LEFT, BOARD_IOID_KEY_RIGHT etc
203  * \return 1 if the button's port interrupt is enabled (edge detect)
204  *
205  * This function will only be called by status_left, status_right and the
206  * called will pass the correct key_io_id
207  */
208 static int
209 status(int type, uint32_t key_io_id)
210 {
211  switch(type) {
212  case SENSORS_ACTIVE:
213  case SENSORS_READY:
214  if(ti_lib_ioc_port_configure_get(key_io_id) & IOC_INT_ENABLE) {
215  return 1;
216  }
217  break;
218  default:
219  break;
220  }
221  return 0;
222 }
223 /*---------------------------------------------------------------------------*/
224 static int
225 value_left(int type)
226 {
227  if(type == BUTTON_SENSOR_VALUE_STATE) {
228  return ti_lib_gpio_pin_read(BOARD_KEY_LEFT) == 0 ?
229  BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED;
230  } else if(type == BUTTON_SENSOR_VALUE_DURATION) {
231  return (int)left_timer.duration;
232  }
233  return 0;
234 }
235 /*---------------------------------------------------------------------------*/
236 static int
237 value_right(int type)
238 {
239  if(type == BUTTON_SENSOR_VALUE_STATE) {
240  return ti_lib_gpio_pin_read(BOARD_KEY_RIGHT) == 0 ?
241  BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED;
242  } else if(type == BUTTON_SENSOR_VALUE_DURATION) {
243  return (int)right_timer.duration;
244  }
245  return 0;
246 }
247 /*---------------------------------------------------------------------------*/
248 /**
249  * \brief Status function for the left button.
250  * \param type SENSORS_ACTIVE or SENSORS_READY
251  * \return 1 if the button's port interrupt is enabled (edge detect)
252  *
253  * This function will call status. It will pass type verbatim and it will also
254  * pass the correct key_io_id
255  */
256 static int
257 status_left(int type)
258 {
259  return status(type, BOARD_IOID_KEY_LEFT);
260 }
261 /*---------------------------------------------------------------------------*/
262 /**
263  * \brief Status function for the right button.
264  * \param type SENSORS_ACTIVE or SENSORS_READY
265  * \return 1 if the button's port interrupt is enabled (edge detect)
266  *
267  * This function will call status. It will pass type verbatim and it will also
268  * pass the correct key_io_id
269  */
270 static int
271 status_right(int type)
272 {
273  return status(type, BOARD_IOID_KEY_RIGHT);
274 }
275 /*---------------------------------------------------------------------------*/
276 SENSORS_SENSOR(button_left_sensor, BUTTON_SENSOR, value_left, config_left,
277  status_left);
278 SENSORS_SENSOR(button_right_sensor, BUTTON_SENSOR, value_right, config_right,
279  status_right);
280 /*---------------------------------------------------------------------------*/
281 /** @} */
#define DEBOUNCE_DURATION
Delay before button state is assumed to be stable.
Definition: button-sensor.c:54
static void start(void)
Start measurement.
const struct sensors_sensor button_left_sensor
Exports a global symbol to be used by the sensor API.
Header file with macros which rename TI CC26xxware functions.
void lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on)
Put the chip in shutdown power mode.
Definition: lpm.c:91
Timer library header file.
CCIF clock_time_t clock_time(void)
Get the current clock time.
Definition: clock.c:41
#define BUTTON_SENSOR_VALUE_DURATION
Can be passed to value() function to get low state duration.
Definition: button-sensor.h:55
static void button_press_handler(uint8_t ioid)
Handler for Sensortag-CC26XX button presses.
Definition: button-sensor.c:76
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Definition: timer.c:64
A timer.
Definition: timer.h:86
static int config_right(int type, int value)
Configuration function for the right button.
static int config_left(int type, int value)
Configuration function for the left button.
static int status(int type, uint32_t key_io_id)
Status function for all buttons.
Header file for the CC13xx/CC26xx GPIO interrupt management.
Header file for the Sensortag-CC26xx Button Driver.
#define BUTTON_SENSOR_VALUE_STATE
Can be passed to value() function to get current button state.
Definition: button-sensor.h:52
static int status_left(int type)
Status function for the left button.
void gpio_interrupt_register_handler(uint8_t ioid, gpio_interrupt_handler_t f)
Register a GPIO interrupt handler.
static void config_buttons(int type, int c, uint32_t key)
Configuration function for the button sensor for all buttons.
static int value(int type, nrf_drv_gpiote_pin_t pin)
Return current state of a button.
static int status_right(int type)
Status function for the right button.
int timer_expired(struct timer *t)
Check if a timer has expired.
Definition: timer.c:122