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 srf06-common-peripherals
33  * @{
34  *
35  * \file
36  * Driver for the SmartRF06EB buttons when a CC13xx/CC26xxEM is mounted on it
37  */
38 /*---------------------------------------------------------------------------*/
39 #include "contiki.h"
40 #include "lib/sensors.h"
41 #include "srf06/button-sensor.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 sel_timer, left_timer, right_timer, up_timer,
71  down_timer;
72 /*---------------------------------------------------------------------------*/
73 /**
74  * \brief Handler for SmartRF button presses
75  */
76 static void
77 button_press_handler(uint8_t ioid)
78 {
79  if(ioid == BOARD_IOID_KEY_SELECT) {
80  if(!timer_expired(&sel_timer.debounce)) {
81  return;
82  }
83 
84  timer_set(&sel_timer.debounce, DEBOUNCE_DURATION);
85 
86  /*
87  * Start press duration counter on press (falling), notify on release
88  * (rising)
89  */
90  if(ti_lib_gpio_pin_read(BOARD_KEY_SELECT) == 0) {
91  sel_timer.start = clock_time();
92  sel_timer.duration = 0;
93  } else {
94  sel_timer.duration = clock_time() - sel_timer.start;
95  sensors_changed(&button_select_sensor);
96  }
97  }
98 
99  if(ioid == BOARD_IOID_KEY_LEFT) {
100  if(!timer_expired(&left_timer.debounce)) {
101  return;
102  }
103 
104  timer_set(&left_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_LEFT) == 0) {
111  left_timer.start = clock_time();
112  left_timer.duration = 0;
113  } else {
114  left_timer.duration = clock_time() - left_timer.start;
115  sensors_changed(&button_left_sensor);
116  }
117  }
118 
119  if(ioid == BOARD_IOID_KEY_RIGHT) {
120  if(BUTTON_SENSOR_ENABLE_SHUTDOWN == 0) {
121  if(!timer_expired(&right_timer.debounce)) {
122  return;
123  }
124 
125  timer_set(&right_timer.debounce, DEBOUNCE_DURATION);
126 
127  /*
128  * Start press duration counter on press (falling), notify on release
129  * (rising)
130  */
131  if(ti_lib_gpio_pin_read(BOARD_KEY_RIGHT) == 0) {
132  right_timer.start = clock_time();
133  right_timer.duration = 0;
134  } else {
135  right_timer.duration = clock_time() - right_timer.start;
136  sensors_changed(&button_right_sensor);
137  }
138  } else {
139  lpm_shutdown(BOARD_IOID_KEY_RIGHT, IOC_IOPULL_UP, IOC_WAKE_ON_LOW);
140  }
141  }
142 
143  if(ioid == BOARD_IOID_KEY_UP) {
144  if(!timer_expired(&up_timer.debounce)) {
145  return;
146  }
147 
148  timer_set(&up_timer.debounce, DEBOUNCE_DURATION);
149 
150  /*
151  * Start press duration counter on press (falling), notify on release
152  * (rising)
153  */
154  if(ti_lib_gpio_pin_read(BOARD_KEY_UP) == 0) {
155  up_timer.start = clock_time();
156  up_timer.duration = 0;
157  } else {
158  up_timer.duration = clock_time() - up_timer.start;
159  sensors_changed(&button_up_sensor);
160  }
161  }
162 
163  if(ioid == BOARD_IOID_KEY_DOWN) {
164  if(!timer_expired(&down_timer.debounce)) {
165  return;
166  }
167 
168  timer_set(&down_timer.debounce, DEBOUNCE_DURATION);
169 
170  /*
171  * Start press duration counter on press (falling), notify on release
172  * (rising)
173  */
174  if(ti_lib_gpio_pin_read(BOARD_KEY_DOWN) == 0) {
175  down_timer.start = clock_time();
176  down_timer.duration = 0;
177  } else {
178  down_timer.duration = clock_time() - down_timer.start;
179  sensors_changed(&button_down_sensor);
180  }
181  }
182 }
183 /*---------------------------------------------------------------------------*/
184 /**
185  * \brief Configuration function for the button sensor for all buttons.
186  *
187  * \param type This function does nothing unless type == SENSORS_ACTIVE
188  * \param c 0: disable the button, non-zero: enable
189  * \param key: One of BOARD_KEY_LEFT, BOARD_KEY_RIGHT etc
190  */
191 static void
192 config_buttons(int type, int c, uint32_t key)
193 {
194  switch(type) {
195  case SENSORS_HW_INIT:
196  ti_lib_gpio_event_clear(1 << key);
197  ti_lib_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG);
198  ti_lib_gpio_dir_mode_set((1 << key), GPIO_DIR_MODE_IN);
200  break;
201  case SENSORS_ACTIVE:
202  if(c) {
203  ti_lib_gpio_event_clear(1 << key);
204  ti_lib_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG);
205  ti_lib_gpio_dir_mode_set((1 << key), GPIO_DIR_MODE_IN);
206  ti_lib_ioc_int_enable(key);
207  } else {
208  ti_lib_ioc_int_disable(key);
209  }
210  break;
211  default:
212  break;
213  }
214 }
215 /*---------------------------------------------------------------------------*/
216 /**
217  * \brief Configuration function for the select button.
218  *
219  * Parameters are passed onto config_buttons, which does the actual
220  * configuration
221  * Parameters are ignored. They have been included because the prototype is
222  * dictated by the core sensor api. The return value is also required by
223  * the API but otherwise ignored.
224  *
225  * \param type passed to config_buttons as-is
226  * \param value passed to config_buttons as-is
227  *
228  * \return ignored
229  */
230 static int
231 config_select(int type, int value)
232 {
233  config_buttons(type, value, BOARD_IOID_KEY_SELECT);
234 
235  return 1;
236 }
237 /*---------------------------------------------------------------------------*/
238 /**
239  * \brief Configuration function for the left button.
240  *
241  * Parameters are passed onto config_buttons, which does the actual
242  * configuration
243  * Parameters are ignored. They have been included because the prototype is
244  * dictated by the core sensor api. The return value is also required by
245  * the API but otherwise ignored.
246  *
247  * \param type passed to config_buttons as-is
248  * \param value passed to config_buttons as-is
249  *
250  * \return ignored
251  */
252 static int
253 config_left(int type, int value)
254 {
255  config_buttons(type, value, BOARD_IOID_KEY_LEFT);
256 
257  return 1;
258 }
259 /*---------------------------------------------------------------------------*/
260 /**
261  * \brief Configuration function for the right button.
262  *
263  * Parameters are passed onto config_buttons, which does the actual
264  * configuration
265  * Parameters are ignored. They have been included because the prototype is
266  * dictated by the core sensor api. The return value is also required by
267  * the API but otherwise ignored.
268  *
269  * \param type passed to config_buttons as-is
270  * \param value passed to config_buttons as-is
271  *
272  * \return ignored
273  */
274 static int
275 config_right(int type, int value)
276 {
277  config_buttons(type, value, BOARD_IOID_KEY_RIGHT);
278 
279  return 1;
280 }
281 /*---------------------------------------------------------------------------*/
282 /**
283  * \brief Configuration function for the up button.
284  *
285  * Parameters are passed onto config_buttons, which does the actual
286  * configuration
287  * Parameters are ignored. They have been included because the prototype is
288  * dictated by the core sensor api. The return value is also required by
289  * the API but otherwise ignored.
290  *
291  * \param type passed to config_buttons as-is
292  * \param value passed to config_buttons as-is
293  *
294  * \return ignored
295  */
296 static int
297 config_up(int type, int value)
298 {
299  config_buttons(type, value, BOARD_IOID_KEY_UP);
300 
301  return 1;
302 }
303 /*---------------------------------------------------------------------------*/
304 /**
305  * \brief Configuration function for the down button.
306  *
307  * Parameters are passed onto config_buttons, which does the actual
308  * configuration
309  * Parameters are ignored. They have been included because the prototype is
310  * dictated by the core sensor api. The return value is also required by
311  * the API but otherwise ignored.
312  *
313  * \param type passed to config_buttons as-is
314  * \param value passed to config_buttons as-is
315  *
316  * \return ignored
317  */
318 static int
319 config_down(int type, int value)
320 {
321  config_buttons(type, value, BOARD_IOID_KEY_DOWN);
322 
323  return 1;
324 }
325 /*---------------------------------------------------------------------------*/
326 static int
327 value_select(int type)
328 {
329  if(type == BUTTON_SENSOR_VALUE_STATE) {
330  return ti_lib_gpio_pin_read(BOARD_KEY_SELECT) == 0 ?
331  BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED;
332  } else if(type == BUTTON_SENSOR_VALUE_DURATION) {
333  return (int)sel_timer.duration;
334  }
335  return 0;
336 }
337 /*---------------------------------------------------------------------------*/
338 static int
339 value_left(int type)
340 {
341  if(type == BUTTON_SENSOR_VALUE_STATE) {
342  return ti_lib_gpio_pin_read(BOARD_KEY_LEFT) == 0 ?
343  BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED;
344  } else if(type == BUTTON_SENSOR_VALUE_DURATION) {
345  return (int)left_timer.duration;
346  }
347  return 0;
348 }
349 /*---------------------------------------------------------------------------*/
350 static int
351 value_right(int type)
352 {
353  if(type == BUTTON_SENSOR_VALUE_STATE) {
354  return ti_lib_gpio_pin_read(BOARD_KEY_RIGHT) == 0 ?
355  BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED;
356  } else if(type == BUTTON_SENSOR_VALUE_DURATION) {
357  return (int)right_timer.duration;
358  }
359  return 0;
360 }
361 /*---------------------------------------------------------------------------*/
362 static int
363 value_up(int type)
364 {
365  if(type == BUTTON_SENSOR_VALUE_STATE) {
366  return ti_lib_gpio_pin_read(BOARD_KEY_UP) == 0 ?
367  BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED;
368  } else if(type == BUTTON_SENSOR_VALUE_DURATION) {
369  return (int)up_timer.duration;
370  }
371  return 0;
372 }
373 /*---------------------------------------------------------------------------*/
374 static int
375 value_down(int type)
376 {
377  if(type == BUTTON_SENSOR_VALUE_STATE) {
378  return ti_lib_gpio_pin_read(BOARD_KEY_DOWN) == 0 ?
379  BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED;
380  } else if(type == BUTTON_SENSOR_VALUE_DURATION) {
381  return (int)down_timer.duration;
382  }
383  return 0;
384 }
385 /*---------------------------------------------------------------------------*/
386 /**
387  * \brief Status function for all buttons
388  * \param type SENSORS_ACTIVE or SENSORS_READY
389  * \param key_io_id BOARD_IOID_KEY_LEFT, BOARD_IOID_KEY_RIGHT etc
390  * \return 1 if the button's port interrupt is enabled (edge detect)
391  *
392  * This function will only be called by status_left, status_right and the
393  * called will pass the correct key_io_id
394  */
395 static int
396 status(int type, uint32_t key_io_id)
397 {
398  switch(type) {
399  case SENSORS_ACTIVE:
400  case SENSORS_READY:
401  if(ti_lib_ioc_port_configure_get(key_io_id) & IOC_INT_ENABLE) {
402  return 1;
403  }
404  break;
405  default:
406  break;
407  }
408  return 0;
409 }
410 /*---------------------------------------------------------------------------*/
411 /**
412  * \brief Status function for the select button.
413  * \param type SENSORS_ACTIVE or SENSORS_READY
414  * \return 1 if the button's port interrupt is enabled (edge detect)
415  *
416  * This function will call status. It will pass type verbatim and it will also
417  * pass the correct key_io_id
418  */
419 static int
420 status_select(int type)
421 {
422  return status(type, BOARD_IOID_KEY_SELECT);
423 }
424 /*---------------------------------------------------------------------------*/
425 /**
426  * \brief Status function for the left button.
427  * \param type SENSORS_ACTIVE or SENSORS_READY
428  * \return 1 if the button's port interrupt is enabled (edge detect)
429  *
430  * This function will call status. It will pass type verbatim and it will also
431  * pass the correct key_io_id
432  */
433 static int
434 status_left(int type)
435 {
436  return status(type, BOARD_IOID_KEY_LEFT);
437 }
438 /*---------------------------------------------------------------------------*/
439 /**
440  * \brief Status function for the right button.
441  * \param type SENSORS_ACTIVE or SENSORS_READY
442  * \return 1 if the button's port interrupt is enabled (edge detect)
443  *
444  * This function will call status. It will pass type verbatim and it will also
445  * pass the correct key_io_id
446  */
447 static int
448 status_right(int type)
449 {
450  return status(type, BOARD_IOID_KEY_RIGHT);
451 }
452 /*---------------------------------------------------------------------------*/
453 /**
454  * \brief Status function for the up button.
455  * \param type SENSORS_ACTIVE or SENSORS_READY
456  * \return 1 if the button's port interrupt is enabled (edge detect)
457  *
458  * This function will call status. It will pass type verbatim and it will also
459  * pass the correct key_io_id
460  */
461 static int
462 status_up(int type)
463 {
464  return status(type, BOARD_IOID_KEY_UP);
465 }
466 /*---------------------------------------------------------------------------*/
467 /**
468  * \brief Status function for the down button.
469  * \param type SENSORS_ACTIVE or SENSORS_READY
470  * \return 1 if the button's port interrupt is enabled (edge detect)
471  *
472  * This function will call status. It will pass type verbatim and it will also
473  * pass the correct key_io_id
474  */
475 static int
476 status_down(int type)
477 {
478  return status(type, BOARD_IOID_KEY_DOWN);
479 }
480 /*---------------------------------------------------------------------------*/
481 SENSORS_SENSOR(button_select_sensor, BUTTON_SENSOR, value_select,
483 SENSORS_SENSOR(button_left_sensor, BUTTON_SENSOR, value_left, config_left,
484  status_left);
485 SENSORS_SENSOR(button_right_sensor, BUTTON_SENSOR, value_right, config_right,
486  status_right);
487 SENSORS_SENSOR(button_up_sensor, BUTTON_SENSOR, value_up, config_up, status_up);
488 SENSORS_SENSOR(button_down_sensor, BUTTON_SENSOR, value_down, config_down,
489  status_down);
490 /*---------------------------------------------------------------------------*/
491 /** @} */
#define DEBOUNCE_DURATION
Delay before button state is assumed to be stable.
Definition: button-sensor.c:54
static int status_right(int type)
Status function for the right button.
static void button_press_handler(uint8_t ioid)
Handler for SmartRF button presses.
Definition: button-sensor.c:77
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
Header file for the SmartRF06EB + CC13xx/CC26xxEM Button Driver.
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
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Definition: timer.c:64
static void config_buttons(int type, int c, uint32_t key)
Configuration function for the button sensor for all buttons.
A timer.
Definition: timer.h:86
static int status_down(int type)
Status function for the down button.
static int status_up(int type)
Status function for the up button.
static int status_left(int type)
Status function for the left button.
Header file for the CC13xx/CC26xx GPIO interrupt management.
static int config_down(int type, int value)
Configuration function for the down button.
static int status_select(int type)
Status function for the select button.
#define BUTTON_SENSOR_VALUE_STATE
Can be passed to value() function to get current button state.
Definition: button-sensor.h:52
void gpio_interrupt_register_handler(uint8_t ioid, gpio_interrupt_handler_t f)
Register a GPIO interrupt handler.
const struct sensors_sensor button_select_sensor
Exports a global symbol to be used by the sensor API.
static int config_up(int type, int value)
Configuration function for the up button.
static int config_left(int type, int value)
Configuration function for the left button.
static int config_right(int type, int value)
Configuration function for the right button.
static int status(int type, uint32_t key_io_id)
Status function for all buttons.
static int value(int type, nrf_drv_gpiote_pin_t pin)
Return current state of a button.
int timer_expired(struct timer *t)
Check if a timer has expired.
Definition: timer.c:122
static int config_select(int type, int value)
Configuration function for the select button.