Contiki-NG
ipso-button.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, Yanzi Networks AB.
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 HOLDER 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 ipso-objects
33  * @{
34  */
35 
36 /**
37  * \file
38  * Implementation of OMA LWM2M / IPSO button as a digital input
39  * NOTE: only works with a Contiki Button Sensor (not for Standalone)
40  * \author
41  * Joakim Eriksson <joakime@sics.se>
42  * Niclas Finne <nfi@sics.se>
43  */
44 
45 #include "contiki.h"
46 #include "lwm2m-object.h"
47 #include "lwm2m-engine.h"
48 
49 #define DEBUG 0
50 #if DEBUG
51 #include <stdio.h>
52 #define PRINTF(...) printf(__VA_ARGS__)
53 #else
54 #define PRINTF(...)
55 #endif
56 
57 #define IPSO_INPUT_STATE 5500
58 #define IPSO_INPUT_COUNTER 5501
59 #define IPSO_INPUT_DEBOUNCE 5503
60 #define IPSO_INPUT_EDGE_SEL 5504
61 #define IPSO_INPUT_CTR_RESET 5505
62 #define IPSO_INPUT_SENSOR_TYPE 5751
63 
64 #if PLATFORM_HAS_BUTTON
65 #if PLATFORM_SUPPORTS_BUTTON_HAL
66 #include "dev/button-hal.h"
67 #else
68 #include "dev/button-sensor.h"
69 #define IPSO_BUTTON_SENSOR button_sensor
70 static struct etimer timer;
71 #endif
72 
73 PROCESS(ipso_button_process, "ipso-button");
74 #endif /* PLATFORM_HAS_BUTTON */
75 
76 
77 static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object,
78  lwm2m_context_t *ctx);
79 
80 static int input_state = 0;
81 static int32_t counter = 0;
82 static int32_t edge_selection = 3; /* both */
83 static int32_t debounce_time = 10;
84 
85 static const lwm2m_resource_id_t resources[] = {
86  RO(IPSO_INPUT_STATE), RO(IPSO_INPUT_COUNTER),
87  RW(IPSO_INPUT_DEBOUNCE), RW(IPSO_INPUT_EDGE_SEL), EX(IPSO_INPUT_CTR_RESET),
88  RO(IPSO_INPUT_SENSOR_TYPE)
89 };
90 
91 /* Only support for one button for now */
92 static lwm2m_object_instance_t reg_object = {
93  .object_id = 3200,
94  .instance_id = 0,
95  .resource_ids = resources,
96  .resource_count = sizeof(resources) / sizeof(lwm2m_resource_id_t),
97  .callback = lwm2m_callback,
98 };
99 
100 /*---------------------------------------------------------------------------*/
101 static int
102 read_state(void)
103 {
104  PRINTF("Read button state: %d\n", input_state);
105  return input_state;
106 }
107 /*---------------------------------------------------------------------------*/
108 /*---------------------------------------------------------------------------*/
109 static lwm2m_status_t
110 lwm2m_callback(lwm2m_object_instance_t *object,
111  lwm2m_context_t *ctx)
112 {
113  if(ctx->operation == LWM2M_OP_READ) {
114  switch(ctx->resource_id) {
115  case IPSO_INPUT_STATE:
116  lwm2m_object_write_int(ctx, read_state());
117  break;
118  case IPSO_INPUT_COUNTER:
119  lwm2m_object_write_int(ctx, counter);
120  break;
121  case IPSO_INPUT_DEBOUNCE:
122  lwm2m_object_write_int(ctx, debounce_time);
123  break;
124  case IPSO_INPUT_EDGE_SEL:
125  lwm2m_object_write_int(ctx, edge_selection);
126  break;
127  case IPSO_INPUT_SENSOR_TYPE:
128  lwm2m_object_write_string(ctx, "button", strlen("button"));
129  break;
130  default:
131  return LWM2M_STATUS_ERROR;
132  }
133  } else if(ctx->operation == LWM2M_OP_EXECUTE) {
134  if(ctx->resource_id == IPSO_INPUT_CTR_RESET) {
135  counter = 0;
136  } else {
137  return LWM2M_STATUS_ERROR;
138  }
139  }
140  return LWM2M_STATUS_OK;
141 }
142 /*---------------------------------------------------------------------------*/
143 void
144 ipso_button_init(void)
145 {
146  /* register this device and its handlers - the handlers automatically
147  sends in the object to handle */
148  lwm2m_engine_add_object(&reg_object);
149 
150 #if PLATFORM_HAS_BUTTON
151  process_start(&ipso_button_process, NULL);
152 #endif /* PLATFORM_HAS_BUTTON */
153 }
154 /*---------------------------------------------------------------------------*/
155 #if PLATFORM_HAS_BUTTON
156 PROCESS_THREAD(ipso_button_process, ev, data)
157 {
158  PROCESS_BEGIN();
159 
160 #if !PLATFORM_SUPPORTS_BUTTON_HAL
161  SENSORS_ACTIVATE(IPSO_BUTTON_SENSOR);
162 #endif
163 
164  while(1) {
166 
167 #if PLATFORM_SUPPORTS_BUTTON_HAL
168  if(ev == button_hal_press_event) {
169  input_state = 1;
170  counter++;
171  if((edge_selection & 2) != 0) {
172  lwm2m_notify_object_observers(&reg_object, IPSO_INPUT_STATE);
173  }
174  lwm2m_notify_object_observers(&reg_object, IPSO_INPUT_COUNTER);
175  } else if(ev == button_hal_release_event) {
176  input_state = 0;
177  if((edge_selection & 1) != 0) {
178  lwm2m_notify_object_observers(&reg_object, IPSO_INPUT_STATE);
179  }
180  }
181 #else /* PLATFORM_SUPPORTS_BUTTON_HAL */
182  if(ev == sensors_event && data == &IPSO_BUTTON_SENSOR) {
183  if(!input_state) {
184  int32_t time;
185  input_state = 1;
186  counter++;
187  if((edge_selection & 2) != 0) {
188  lwm2m_notify_object_observers(&reg_object, IPSO_INPUT_STATE);
189  }
190  lwm2m_notify_object_observers(&reg_object, IPSO_INPUT_COUNTER);
191 
192  time = (debounce_time * CLOCK_SECOND / 1000);
193  if(time < 1) {
194  time = 1;
195  }
196  etimer_set(&timer, (clock_time_t)time);
197  }
198  } else if(ev == PROCESS_EVENT_TIMER && data == &timer) {
199  if(!input_state) {
200  /* Button is not in pressed state */
201  } else if(IPSO_BUTTON_SENSOR.value(0) != 0) {
202  /* Button is still pressed */
204  } else {
205  input_state = 0;
206  if((edge_selection & 1) != 0) {
207  lwm2m_notify_object_observers(&reg_object, IPSO_INPUT_STATE);
208  }
209  }
210  }
211 #endif /* PLATFORM_SUPPORTS_BUTTON_HAL */
212  }
213 
214  PROCESS_END();
215 }
216 #endif /* PLATFORM_HAS_BUTTON */
217 /*---------------------------------------------------------------------------*/
218 /** @} */
Header file for the LWM2M object API
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
process_event_t button_hal_release_event
A broadcast event generated when a button gets released.
Definition: button-hal.c:54
#define PROCESS_WAIT_EVENT()
Wait for an event to be posted to the process.
Definition: process.h:141
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
A timer.
Definition: timer.h:82
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
process_event_t button_hal_press_event
A broadcast event generated when a button gets pressed.
Definition: button-hal.c:53
A timer.
Definition: etimer.h:76
Header file for the Contiki OMA LWM2M engine
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1110
void etimer_reset(struct etimer *et)
Reset an event timer with the same interval as was previously set.
Definition: etimer.c:192
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
Definition: etimer.c:177
Header file for the button HAL.
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99