1/*
2 * Author: Brendan Le Foll <brendan.le.foll@intel.com>
3 * Contributions: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
4 * Contributions: Sarah Knepper <sarah.knepper@intel.com>
5 * Copyright (c) 2014 Intel Corporation.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27#include <iostream>
28#include <string>
29#include <stdexcept>
30
31#include "grove.h"
32#include "math.h"
33
34using namespace upm;
35
36//// GroveLed ////
37
38GroveLed::GroveLed(int pin)
39{
40    if ( !(m_gpio = mraa_gpio_init(pin)) ) {
41        throw std::invalid_argument(std::string(__FUNCTION__) +
42                                    ": mraa_gpio_init() failed, invalid pin?");
43        return;
44    }
45    mraa_gpio_dir(m_gpio, MRAA_GPIO_OUT);
46    m_name = "LED Socket";
47}
48
49GroveLed::~GroveLed()
50{
51    mraa_gpio_close(m_gpio);
52}
53
54mraa_result_t GroveLed::write(int value)
55{
56    if (value >= 1) {
57        return mraa_gpio_write(m_gpio, 1);
58    }
59    return mraa_gpio_write(m_gpio, 0);
60}
61
62mraa_result_t GroveLed::on()
63{
64    return write(1);
65}
66
67mraa_result_t GroveLed::off()
68{
69    return write(0);
70}
71
72//// GroveRelay ////
73
74GroveRelay::GroveRelay(unsigned int pin)
75{
76    if ( !(m_gpio = mraa_gpio_init(pin)) ) {
77        throw std::invalid_argument(std::string(__FUNCTION__) +
78                                    ": mraa_gpio_init() failed, invalid pin?");
79        return;
80    }
81    mraa_gpio_dir(m_gpio, MRAA_GPIO_OUT);
82    m_name = "Relay Switch";
83}
84
85GroveRelay::~GroveRelay()
86{
87    mraa_gpio_close(m_gpio);
88}
89
90mraa_result_t GroveRelay::on()
91{
92    return mraa_gpio_write(m_gpio, 1);
93}
94
95mraa_result_t GroveRelay::off()
96{
97    return mraa_gpio_write(m_gpio, 0);
98}
99
100bool GroveRelay::isOn()
101{
102    return mraa_gpio_read(m_gpio) == 1;
103}
104
105bool GroveRelay::isOff()
106{
107    return mraa_gpio_read(m_gpio) == 0;
108}
109
110//// GroveTemp ////
111
112GroveTemp::GroveTemp(unsigned int pin)
113{
114    if ( !(m_aio = mraa_aio_init(pin)) ) {
115        throw std::invalid_argument(std::string(__FUNCTION__) +
116                                    ": mraa_aio_init() failed, invalid pin?");
117        return;
118    }
119    m_name = "Temperature Sensor";
120}
121
122GroveTemp::~GroveTemp()
123{
124    mraa_aio_close(m_aio);
125}
126
127int GroveTemp::value ()
128{
129    int a = mraa_aio_read(m_aio);
130    float r = (float)(1023.0-a)*10000.0/a;
131    float t = 1.0/(log(r/10000.0)/3975.0 + 1.0/298.15)-273.15;
132    return (int) round(t);
133}
134
135float GroveTemp::raw_value()
136{
137    return (float) mraa_aio_read(m_aio);
138}
139
140//// GroveLight ////
141
142GroveLight::GroveLight(unsigned int pin)
143{
144    if ( !(m_aio = mraa_aio_init(pin)) ) {
145        throw std::invalid_argument(std::string(__FUNCTION__) +
146                                    ": mraa_aio_init() failed, invalid pin?");
147        return;
148    }
149    m_name = "Light Sensor";
150}
151
152GroveLight::~GroveLight()
153{
154    mraa_aio_close(m_aio);
155}
156
157int GroveLight::value()
158{
159    // rough conversion to lux, using formula from Grove Starter Kit booklet
160    float a = (float) mraa_aio_read(m_aio);
161    a = 10000.0/pow(((1023.0-a)*10.0/a)*15.0,4.0/3.0);
162    return (int) round(a);
163}
164
165float GroveLight::raw_value()
166{
167    return (float) mraa_aio_read(m_aio);
168}
169
170//// GroveRotary ////
171
172GroveRotary::GroveRotary(unsigned int pin)
173{
174    if ( !(m_aio = mraa_aio_init(pin)) ) {
175        throw std::invalid_argument(std::string(__FUNCTION__) +
176                                    ": mraa_aio_init() failed, invalid pin?");
177        return;
178    }
179    m_name = "Rotary Angle Sensor";
180}
181
182GroveRotary::~GroveRotary()
183{
184    mraa_aio_close(m_aio);
185}
186
187float GroveRotary::abs_value()
188{
189    return (float) mraa_aio_read(m_aio);
190}
191
192float GroveRotary::abs_deg()
193{
194    return GroveRotary::abs_value() * (float) m_max_angle / 1023.0;
195}
196
197float GroveRotary::abs_rad()
198{
199    return GroveRotary::abs_deg() * M_PI / 180.0;
200}
201
202float GroveRotary::rel_value()
203{
204    return GroveRotary::abs_value() - 512.0;
205}
206
207float GroveRotary::rel_deg()
208{
209    return GroveRotary::rel_value() * (float) m_max_angle / 1023.0;
210}
211
212float GroveRotary::rel_rad()
213{
214    return GroveRotary::rel_deg() * M_PI / 180.0;
215}
216
217//// GroveSlide ////
218
219GroveSlide::GroveSlide(unsigned int pin, float ref_voltage)
220{
221    if ( !(m_aio = mraa_aio_init(pin)) ) {
222        throw std::invalid_argument(std::string(__FUNCTION__) +
223                                    ": mraa_aio_init() failed, invalid pin?");
224        return;
225    }
226    m_ref_voltage = ref_voltage;
227    m_name = "Slide Potentiometer";
228}
229
230GroveSlide::~GroveSlide()
231{
232    mraa_aio_close(m_aio);
233}
234
235float GroveSlide::raw_value()
236{
237    return (float) mraa_aio_read(m_aio);
238}
239
240float GroveSlide::voltage_value()
241{
242    // conversion to Volts
243    float a = GroveSlide::raw_value();
244    a = m_ref_voltage * a / 1023.0 ;
245    return a;
246}
247
248float GroveSlide::ref_voltage()
249{
250    return m_ref_voltage;
251}
252
253//// GroveButton ////
254
255GroveButton::GroveButton(unsigned int pin)
256{
257    if ( !(m_gpio = mraa_gpio_init(pin)) ) {
258        throw std::invalid_argument(std::string(__FUNCTION__) +
259                                    ": mraa_gpio_init() failed, invalid pin?");
260        return;
261    }
262    mraa_gpio_dir(m_gpio, MRAA_GPIO_IN);
263    m_name = "Button Sensor";
264}
265
266GroveButton::~GroveButton()
267{
268    mraa_gpio_close(m_gpio);
269}
270
271std::string GroveButton::name()
272{
273    return m_name;
274}
275
276int GroveButton::value()
277{
278    return mraa_gpio_read(m_gpio);
279}
280
281#ifdef JAVACALLBACK
282void GroveButton::installISR(mraa::Edge level, IsrCallback *cb)
283{
284  installISR(level, generic_callback_isr, cb);
285}
286#endif
287
288void GroveButton::installISR(mraa::Edge level, void (*isr)(void *), void *arg)
289{
290  if (m_isrInstalled)
291    uninstallISR();
292
293  // install our interrupt handler
294  mraa_gpio_isr(m_gpio, (mraa_gpio_edge_t) level, isr, arg);
295  m_isrInstalled = true;
296}
297
298void GroveButton::uninstallISR()
299{
300  mraa_gpio_isr_exit(m_gpio);
301  m_isrInstalled = false;
302}
303