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  * Copyright (c) 2015, Zolertia - http://www.zolertia.com
4  * Copyright (c) 2015, University of Bristol - http://www.bristol.ac.uk
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31  * OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 /*---------------------------------------------------------------------------*/
34 /**
35  * \addtogroup zoul-button-sensor
36  * @{
37  *
38  * \file
39  * Driver for the Zoul user button
40  */
41 /*---------------------------------------------------------------------------*/
42 #include "contiki.h"
43 #include "dev/nvic.h"
44 #include "dev/ioc.h"
45 #include "dev/gpio.h"
46 #include "dev/button-sensor.h"
47 #include "sys/timer.h"
48 #include "sys/ctimer.h"
49 #include "sys/process.h"
50 
51 #include <stdint.h>
52 #include <string.h>
53 /*---------------------------------------------------------------------------*/
54 #define BUTTON_USER_PORT_BASE GPIO_PORT_TO_BASE(BUTTON_USER_PORT)
55 #define BUTTON_USER_PIN_MASK GPIO_PIN_MASK(BUTTON_USER_PIN)
56 /*---------------------------------------------------------------------------*/
57 #define DEBOUNCE_DURATION (CLOCK_SECOND >> 4)
58 
59 static struct timer debouncetimer;
60 /*---------------------------------------------------------------------------*/
61 static clock_time_t press_duration = 0;
62 static struct ctimer press_counter;
63 static uint8_t press_event_counter;
64 
65 process_event_t button_press_duration_exceeded;
66 /*---------------------------------------------------------------------------*/
67 static void
68 duration_exceeded_callback(void *data)
69 {
70  press_event_counter++;
71  process_post(PROCESS_BROADCAST, button_press_duration_exceeded,
72  &press_event_counter);
73  ctimer_set(&press_counter, press_duration, duration_exceeded_callback,
74  NULL);
75 }
76 /*---------------------------------------------------------------------------*/
77 /**
78  * \brief Retrieves the value of the button pin
79  * \param type Returns the pin level or the counter of press duration events.
80  * type == BUTTON_SENSOR_VALUE_TYPE_LEVEL or
81  * type == BUTTON_SENSOR_VALUE_TYPE_PRESS_DURATION
82  * respectively
83  */
84 static int
85 value(int type)
86 {
87  switch(type) {
88  case BUTTON_SENSOR_VALUE_TYPE_LEVEL:
89  return GPIO_READ_PIN(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK);
90  case BUTTON_SENSOR_VALUE_TYPE_PRESS_DURATION:
91  return press_event_counter;
92  }
93 
94  return 0;
95 }
96 /*---------------------------------------------------------------------------*/
97 /**
98  * \brief Callback registered with the GPIO module. Gets fired with a button
99  * port/pin generates an interrupt
100  * \param port The port number that generated the interrupt
101  * \param pin The pin number that generated the interrupt. This is the pin
102  * absolute number (i.e. 0, 1, ..., 7), not a mask
103  */
104 static void
105 btn_callback(uint8_t port, uint8_t pin)
106 {
107  if(!timer_expired(&debouncetimer)) {
108  return;
109  }
110 
111  timer_set(&debouncetimer, DEBOUNCE_DURATION);
112 
113  if(press_duration) {
114  press_event_counter = 0;
115  if(value(BUTTON_SENSOR_VALUE_TYPE_LEVEL) == BUTTON_SENSOR_PRESSED_LEVEL) {
116  ctimer_set(&press_counter, press_duration, duration_exceeded_callback,
117  NULL);
118  } else {
119  ctimer_stop(&press_counter);
120  }
121  }
122 
123  sensors_changed(&button_sensor);
124 }
125 /*---------------------------------------------------------------------------*/
126 /**
127  * \brief Init function for the User button.
128  * \param type SENSORS_ACTIVE: Activate / Deactivate the sensor (value == 1
129  * or 0 respectively)
130  *
131  * \param value Depends on the value of the type argument
132  * \return Depends on the value of the type argument
133  */
134 static int
135 config_user(int type, int value)
136 {
137  switch(type) {
138  case SENSORS_HW_INIT:
139  button_press_duration_exceeded = process_alloc_event();
140 
141  /* Software controlled */
142  GPIO_SOFTWARE_CONTROL(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK);
143 
144  /* Set pin to input */
145  GPIO_SET_INPUT(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK);
146 
147  /* Enable edge detection */
148  GPIO_DETECT_EDGE(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK);
149 
150  /* Both Edges */
151  GPIO_TRIGGER_BOTH_EDGES(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK);
152 
154 
156  break;
157  case SENSORS_ACTIVE:
158  if(value) {
159  GPIO_ENABLE_INTERRUPT(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK);
160  nvic_interrupt_enable(BUTTON_USER_VECTOR);
161  } else {
162  GPIO_DISABLE_INTERRUPT(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK);
163  nvic_interrupt_disable(BUTTON_USER_VECTOR);
164  }
165  return value;
166  case BUTTON_SENSOR_CONFIG_TYPE_INTERVAL:
167  press_duration = (clock_time_t)value;
168  break;
169  default:
170  break;
171  }
172 
173  return 1;
174 }
175 /*---------------------------------------------------------------------------*/
176 SENSORS_SENSOR(button_sensor, BUTTON_SENSOR, value, config_user, NULL);
177 /*---------------------------------------------------------------------------*/
178 /** @} */
#define DEBOUNCE_DURATION
Delay before button state is assumed to be stable.
Definition: button-sensor.c:54
#define GPIO_ENABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Enable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:202
#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 IOC_OVERRIDE_PUE
Pull Up Enable.
Definition: ioc.h:223
#define GPIO_DETECT_EDGE(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to detect edge.
Definition: gpio.h:155
Timer library header file.
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Definition: timer.c:64
Header file for the ARM Nested Vectored Interrupt Controller.
A timer.
Definition: timer.h:86
#define GPIO_READ_PIN(PORT_BASE, PIN_MASK)
Read pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:148
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
Definition: process.c:322
process_event_t process_alloc_event(void)
Allocate a global event number.
Definition: process.c:93
static int config_user(int type, int value)
Init function for the User button.
const struct sensors_sensor button_sensor
Copyright (c) 2014, Analog Devices, Inc.
Definition: button-sensor.c:44
Header file for the callback timer
#define NULL
The null pointer.
Header file with declarations for the I/O Control module.
static void btn_callback(uint8_t port, uint8_t pin)
Callback registered with the GPIO module.
#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:259
#define BUTTON_USER_PORT
BUTTON_USER -> PC3.
Definition: board.h:126
#define GPIO_TRIGGER_BOTH_EDGES(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to trigger an interrupt on both edges.
Definition: gpio.h:170
Header file for the Contiki process interface.
void nvic_interrupt_enable(uint32_t intr)
Enables interrupt intr.
Definition: nvic.c:64
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
static int value(int type)
Retrieves the value of the button pin.
Definition: button-sensor.c:85
void nvic_interrupt_disable(uint32_t intr)
Disables interrupt intr.
Definition: nvic.c:71
#define GPIO_DISABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Disable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:210
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:149
void ioc_set_over(uint8_t port, uint8_t pin, uint8_t over)
Set Port:Pin override function.
Definition: ioc.c:54
void gpio_register_callback(gpio_callback_t f, uint8_t port, uint8_t pin)
Register GPIO callback.
Definition: gpio.c:56
int timer_expired(struct timer *t)
Check if a timer has expired.
Definition: timer.c:122