Contiki 3.x
button-sensor.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, 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  *
14  * 3. Neither the name of the copyright holder nor the names of its
15  * contributors may be used to endorse or promote products derived
16  * from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29  * OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 /**
32  * \addtogroup cc2538dk-button-sensor
33  * @{
34  *
35  * \file
36  * Driver for the SmartRF06EB buttons
37  */
38 #include "contiki.h"
39 #include "dev/nvic.h"
40 #include "dev/ioc.h"
41 #include "dev/gpio.h"
42 #include "dev/button-sensor.h"
43 #include "sys/timer.h"
44 
45 #include <stdint.h>
46 #include <string.h>
47 
48 #define BUTTON_SELECT_PORT_BASE GPIO_PORT_TO_BASE(BUTTON_SELECT_PORT)
49 #define BUTTON_SELECT_PIN_MASK GPIO_PIN_MASK(BUTTON_SELECT_PIN)
50 
51 #define BUTTON_LEFT_PORT_BASE GPIO_PORT_TO_BASE(BUTTON_LEFT_PORT)
52 #define BUTTON_LEFT_PIN_MASK GPIO_PIN_MASK(BUTTON_LEFT_PIN)
53 
54 #define BUTTON_RIGHT_PORT_BASE GPIO_PORT_TO_BASE(BUTTON_RIGHT_PORT)
55 #define BUTTON_RIGHT_PIN_MASK GPIO_PIN_MASK(BUTTON_RIGHT_PIN)
56 
57 #define BUTTON_UP_PORT_BASE GPIO_PORT_TO_BASE(BUTTON_UP_PORT)
58 #define BUTTON_UP_PIN_MASK GPIO_PIN_MASK(BUTTON_UP_PIN)
59 
60 #define BUTTON_DOWN_PORT_BASE GPIO_PORT_TO_BASE(BUTTON_DOWN_PORT)
61 #define BUTTON_DOWN_PIN_MASK GPIO_PIN_MASK(BUTTON_DOWN_PIN)
62 /*---------------------------------------------------------------------------*/
63 static struct timer debouncetimer;
64 /*---------------------------------------------------------------------------*/
65 /**
66  * \brief Common initialiser for all buttons
67  * \param port_base GPIO port's register offset
68  * \param pin_mask Pin mask corresponding to the button's pin
69  */
70 static void
71 config(uint32_t port_base, uint32_t pin_mask)
72 {
73  /* Software controlled */
74  GPIO_SOFTWARE_CONTROL(port_base, pin_mask);
75 
76  /* Set pin to input */
77  GPIO_SET_INPUT(port_base, pin_mask);
78 
79  /* Enable edge detection */
80  GPIO_DETECT_EDGE(port_base, pin_mask);
81 
82  /* Single edge */
83  GPIO_TRIGGER_SINGLE_EDGE(port_base, pin_mask);
84 
85  /* Trigger interrupt on Falling edge */
86  GPIO_DETECT_RISING(port_base, pin_mask);
87 
88  GPIO_ENABLE_INTERRUPT(port_base, pin_mask);
89 }
90 /*---------------------------------------------------------------------------*/
91 /**
92  * \brief Callback registered with the GPIO module. Gets fired with a button
93  * port/pin generates an interrupt
94  * \param port The port number that generated the interrupt
95  * \param pin The pin number that generated the interrupt. This is the pin
96  * absolute number (i.e. 0, 1, ..., 7), not a mask
97  */
98 static void
99 btn_callback(uint8_t port, uint8_t pin)
100 {
101  if(!timer_expired(&debouncetimer)) {
102  return;
103  }
104 
105  timer_set(&debouncetimer, CLOCK_SECOND / 8);
106  if(port == GPIO_A_NUM) {
107  sensors_changed(&button_select_sensor);
108  } else if(port == GPIO_C_NUM) {
109  switch(pin) {
110  case BUTTON_LEFT_PIN:
111  sensors_changed(&button_left_sensor);
112  break;
113  case BUTTON_RIGHT_PIN:
114  sensors_changed(&button_right_sensor);
115  break;
116  case BUTTON_UP_PIN:
117  sensors_changed(&button_up_sensor);
118  break;
119  case BUTTON_DOWN_PIN:
120  sensors_changed(&button_down_sensor);
121  break;
122  default:
123  return;
124  }
125  }
126 }
127 /*---------------------------------------------------------------------------*/
128 /**
129  * \brief Init function for the select button.
130  *
131  * Parameters are ignored. They have been included because the prototype is
132  * dictated by the core sensor api. The return value is also not required by
133  * the API but otherwise ignored.
134  *
135  * \param type ignored
136  * \param value ignored
137  * \return ignored
138  */
139 static int
140 config_select(int type, int value)
141 {
142  config(BUTTON_SELECT_PORT_BASE, BUTTON_SELECT_PIN_MASK);
143 
144  ioc_set_over(BUTTON_SELECT_PORT, BUTTON_SELECT_PIN, IOC_OVERRIDE_PUE);
145 
146  nvic_interrupt_enable(BUTTON_SELECT_VECTOR);
147 
148  gpio_register_callback(btn_callback, BUTTON_SELECT_PORT, BUTTON_SELECT_PIN);
149  return 1;
150 }
151 /*---------------------------------------------------------------------------*/
152 /**
153  * \brief Init function for the left button.
154  *
155  * Parameters are ignored. They have been included because the prototype is
156  * dictated by the core sensor api. The return value is also not required by
157  * the API but otherwise ignored.
158  *
159  * \param type ignored
160  * \param value ignored
161  * \return ignored
162  */
163 static int
164 config_left(int type, int value)
165 {
166  config(BUTTON_LEFT_PORT_BASE, BUTTON_LEFT_PIN_MASK);
167 
169 
170  nvic_interrupt_enable(BUTTON_LEFT_VECTOR);
171 
172  gpio_register_callback(btn_callback, BUTTON_LEFT_PORT, BUTTON_LEFT_PIN);
173  return 1;
174 }
175 /*---------------------------------------------------------------------------*/
176 /**
177  * \brief Init function for the right button.
178  *
179  * Parameters are ignored. They have been included because the prototype is
180  * dictated by the core sensor api. The return value is also not required by
181  * the API but otherwise ignored.
182  *
183  * \param type ignored
184  * \param value ignored
185  * \return ignored
186  */
187 static int
188 config_right(int type, int value)
189 {
190  config(BUTTON_RIGHT_PORT_BASE, BUTTON_RIGHT_PIN_MASK);
191 
192  ioc_set_over(BUTTON_RIGHT_PORT, BUTTON_RIGHT_PIN, IOC_OVERRIDE_PUE);
193 
194  nvic_interrupt_enable(BUTTON_RIGHT_VECTOR);
195 
196  gpio_register_callback(btn_callback, BUTTON_RIGHT_PORT, BUTTON_RIGHT_PIN);
197  return 1;
198 }
199 /*---------------------------------------------------------------------------*/
200 /**
201  * \brief Init function for the up button.
202  *
203  * Parameters are ignored. They have been included because the prototype is
204  * dictated by the core sensor api. The return value is also not required by
205  * the API but otherwise ignored.
206  *
207  * \param type ignored
208  * \param value ignored
209  * \return ignored
210  */
211 static int
212 config_up(int type, int value)
213 {
214  config(BUTTON_UP_PORT_BASE, BUTTON_UP_PIN_MASK);
215 
217 
218  nvic_interrupt_enable(BUTTON_UP_VECTOR);
219 
220  gpio_register_callback(btn_callback, BUTTON_UP_PORT, BUTTON_UP_PIN);
221  return 1;
222 }
223 /*---------------------------------------------------------------------------*/
224 /**
225  * \brief Init function for the down button.
226  *
227  * Parameters are ignored. They have been included because the prototype is
228  * dictated by the core sensor api. The return value is also not required by
229  * the API but otherwise ignored.
230  *
231  * \param type ignored
232  * \param value ignored
233  * \return ignored
234  */
235 static int
236 config_down(int type, int value)
237 {
238  config(BUTTON_DOWN_PORT_BASE, BUTTON_DOWN_PIN_MASK);
239 
241 
242  nvic_interrupt_enable(BUTTON_DOWN_VECTOR);
243 
244  gpio_register_callback(btn_callback, BUTTON_DOWN_PORT, BUTTON_DOWN_PIN);
245  return 1;
246 }
247 /*---------------------------------------------------------------------------*/
248 void
250 {
251  timer_set(&debouncetimer, 0);
252 }
253 /*---------------------------------------------------------------------------*/
254 SENSORS_SENSOR(button_select_sensor, BUTTON_SENSOR, NULL, config_select, NULL);
255 SENSORS_SENSOR(button_left_sensor, BUTTON_SENSOR, NULL, config_left, NULL);
256 SENSORS_SENSOR(button_right_sensor, BUTTON_SENSOR, NULL, config_right, NULL);
257 SENSORS_SENSOR(button_up_sensor, BUTTON_SENSOR, NULL, config_up, NULL);
258 SENSORS_SENSOR(button_down_sensor, BUTTON_SENSOR, NULL, config_down, NULL);
259 
260 /** @} */
#define GPIO_A_NUM
GPIO_A: 0.
Definition: gpio.h:79
A timer.
Definition: timer.h:86
#define BUTTON_DOWN_PORT
BUTTON_DOWN -&gt; PC7.
Definition: board.h:161
#define BUTTON_LEFT_PORT
BUTTON_LEFT -&gt; PC4.
Definition: board.h:146
Header file for the ARM Nested Vectored Interrupt Controller.
#define BUTTON_UP_PORT
BUTTON_UP -&gt; PC6.
Definition: board.h:156
#define GPIO_DETECT_RISING(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to trigger an interrupt on rising edge.
Definition: gpio.h:166
Header file with register and macro declarations for the cc2538 GPIO module.
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Definition: timer.c:64
void ioc_set_over(uint8_t port, uint8_t pin, uint8_t over)
Set Port:Pin override function.
Definition: ioc.c:54
#define NULL
The null pointer.
#define GPIO_SET_INPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to input.
Definition: gpio.h:93
#define GPIO_DETECT_EDGE(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to detect edge.
Definition: gpio.h:135
Header file with declarations for the I/O Control module.
void nvic_interrupt_enable(uint32_t intr)
Enables interrupt intr.
Definition: nvic.c:64
#define BUTTON_RIGHT_PORT
BUTTON_RIGHT -&gt; PC5.
Definition: board.h:151
void button_sensor_init()
Common initialiser for all SmartRF Buttons.
#define GPIO_SOFTWARE_CONTROL(PORT_BASE, PIN_MASK)
Configure the pin to be software controlled with PIN_MASK of port with PORT_BASE. ...
Definition: gpio.h:214
#define IOC_OVERRIDE_PUE
Pull Up Enable.
Definition: ioc.h:223
struct sensors_sensor button_select_sensor
Exports a global symbol to be used by the sensor API.
void gpio_register_callback(gpio_callback_t f, uint8_t port, uint8_t pin)
Register GPIO callback.
Definition: gpio.c:56
#define GPIO_TRIGGER_SINGLE_EDGE(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to trigger an interrupt on single edge (controlled by G...
Definition: gpio.h:158
#define GPIO_ENABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Enable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:182
Timer library header file.
#define GPIO_C_NUM
GPIO_C: 2.
Definition: gpio.h:81
#define BUTTON_SELECT_PORT
BUTTON_SELECT -&gt; PA3.
Definition: board.h:141
int timer_expired(struct timer *t)
Check if a timer has expired.
Definition: timer.c:121
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82