1 /*
2 * Author: Jon Trulson <jtrulson@ics.com>
3 * Copyright (c) 2015 Intel Corporation.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #include <iostream>
26 #include <stdexcept>
27 #include <string>
28
29 #include "mma7660.h"
30
31 using namespace upm;
32 using namespace std;
33
34
MMA7660(int bus,uint8_t address)35 MMA7660::MMA7660(int bus, uint8_t address)
36 {
37 m_addr = address;
38 m_isrInstalled = false;
39
40 // setup our i2c link
41 if ( !(m_i2c = mraa_i2c_init(bus)) )
42 {
43 throw std::invalid_argument(std::string(__FUNCTION__) +
44 ": mraa_i2c_init() failed");
45 return;
46 }
47
48 mraa_result_t rv;
49
50 if ( (rv = mraa_i2c_address(m_i2c, m_addr)) != MRAA_SUCCESS)
51 {
52 throw std::invalid_argument(std::string(__FUNCTION__) +
53 ": mraa_i2c_address() failed");
54 return;
55 }
56 }
57
~MMA7660()58 MMA7660::~MMA7660()
59 {
60 if (m_isrInstalled)
61 uninstallISR();
62
63 setModeStandby();
64 mraa_i2c_stop(m_i2c);
65 }
66
writeByte(uint8_t reg,uint8_t byte)67 bool MMA7660::writeByte(uint8_t reg, uint8_t byte)
68 {
69 mraa_result_t rv = mraa_i2c_write_byte_data(m_i2c, byte, reg);
70
71 if (rv != MRAA_SUCCESS)
72 {
73 return false;
74 }
75
76 return true;
77 }
78
readByte(uint8_t reg)79 uint8_t MMA7660::readByte(uint8_t reg)
80 {
81 return mraa_i2c_read_byte_data(m_i2c, reg);
82 }
83
getRawValues(int * x,int * y,int * z)84 void MMA7660::getRawValues(int *x, int *y, int *z)
85 {
86 *x = getVerifiedAxis(REG_XOUT);
87 *y = getVerifiedAxis(REG_YOUT);
88 *z = getVerifiedAxis(REG_ZOUT);
89 }
90
91 #ifdef JAVACALLBACK
getRawValues()92 int *MMA7660::getRawValues()
93 {
94 int *values = new int[3];
95 getRawValues(&values[0], &values[1], &values[2]);
96 return values;
97 }
98 #endif
99
setModeActive()100 void MMA7660::setModeActive()
101 {
102 uint8_t modeReg = readByte(REG_MODE);
103
104 // The D2 (TON bit) should be cleared, and the MODE bit set
105
106 modeReg &= ~MODE_TON;
107 modeReg |= MODE_MODE;
108
109 writeByte(REG_MODE, modeReg);
110 }
111
setModeStandby()112 void MMA7660::setModeStandby()
113 {
114 uint8_t modeReg = readByte(REG_MODE);
115
116 // the D0 (mode bit) and D2 (TON bit) should be cleared.
117
118 modeReg &= ~MODE_TON;
119 modeReg &= ~MODE_MODE;
120
121 writeByte(REG_MODE, modeReg);
122 }
123
124 // read an axis value, verifying it's validity
getVerifiedAxis(MMA7660_REG_T axis)125 int MMA7660::getVerifiedAxis(MMA7660_REG_T axis)
126 {
127 // We only want one of the 3 axes
128
129 if (axis > 2)
130 {
131 throw std::out_of_range(std::string(__FUNCTION__) +
132 ": axis must be 0, 1, or 2.");
133 return 0;
134 }
135
136 // we need to check the alert bit and sign bits if the alert bit is
137 // set, this means that the register was being updated when the
138 // register was read, so re-read until it's clear.
139
140 uint8_t val;
141 do {
142 val = readByte(axis);
143
144 // check alert bit
145 } while (val & 0x40);
146
147 // shift the sign bit over, and compensate
148 return (char(val << 2) / 4);
149 }
150
151 // read the tilt register, verifying it's validity
getVerifiedTilt()152 uint8_t MMA7660::getVerifiedTilt()
153 {
154 // we need to check the alert bit and sign bits if the alert bit is
155 // set, this means that the register was being updated when the
156 // register was read, so re-read until it's clear.
157
158 uint8_t val;
159 do {
160 val = readByte(REG_TILT);
161
162 // check alert bit
163 } while (val & 0x40);
164
165 return val;
166 }
167
tiltBackFront()168 uint8_t MMA7660::tiltBackFront()
169 {
170 uint8_t val = getVerifiedTilt();
171
172 // mask off the bits we don't care about
173 val &= 0x03;
174 return val;
175 }
176
tiltLandscapePortrait()177 uint8_t MMA7660::tiltLandscapePortrait()
178 {
179 uint8_t val = getVerifiedTilt();
180
181 // mask off the bits we don't care about
182 val >>= 2;
183 val &= 0x07;
184 return val;
185 }
186
tiltTap()187 bool MMA7660::tiltTap()
188 {
189 uint8_t val = getVerifiedTilt();
190
191 if (val & 0x20)
192 return true;
193 else
194 return false;
195 }
196
tiltShake()197 bool MMA7660::tiltShake()
198 {
199 uint8_t val = getVerifiedTilt();
200
201 if (val & 0x80)
202 return true;
203 else
204 return false;
205 }
206
207 #ifdef JAVACALLBACK
installISR(int pin,IsrCallback * cb)208 void MMA7660::installISR(int pin, IsrCallback *cb)
209 {
210 installISR(pin, generic_callback_isr, cb);
211 }
212 #endif
213
installISR(int pin,void (* isr)(void *),void * arg)214 void MMA7660::installISR(int pin, void (*isr)(void *), void *arg)
215 {
216 if (m_isrInstalled)
217 uninstallISR();
218
219 if ( !(m_gpio = mraa_gpio_init(pin)) )
220 {
221 throw std::invalid_argument(std::string(__FUNCTION__) +
222 ": mraa_gpio_init() failed, invalid pin?");
223 return;
224 }
225
226 mraa_gpio_dir(m_gpio, MRAA_GPIO_IN);
227
228 // install our interrupt handler
229 mraa_gpio_isr(m_gpio, MRAA_GPIO_EDGE_RISING,
230 isr, arg);
231 m_isrInstalled = true;
232 }
233
uninstallISR()234 void MMA7660::uninstallISR()
235 {
236 if (!m_isrInstalled)
237 return;
238
239 mraa_gpio_isr_exit(m_gpio);
240 m_isrInstalled = false;
241 mraa_gpio_close(m_gpio);
242 }
243
setInterruptBits(uint8_t ibits)244 bool MMA7660::setInterruptBits(uint8_t ibits)
245 {
246 return writeByte(REG_INTSU, ibits);
247 }
248
setSampleRate(MMA7660_AUTOSLEEP_T sr)249 bool MMA7660::setSampleRate(MMA7660_AUTOSLEEP_T sr)
250 {
251 return writeByte(REG_SR, sr);
252 }
253
getAcceleration(float * ax,float * ay,float * az)254 void MMA7660::getAcceleration(float *ax, float *ay, float *az)
255 {
256 int x, y, z;
257
258 getRawValues(&x, &y, &z);
259
260 // 21.33, typical counts/g
261
262 *ax = x/21.33;
263 *ay = y/21.33;
264 *az = z/21.33;
265 }
266
267 #ifdef JAVACALLBACK
getAcceleration()268 float *MMA7660::getAcceleration()
269 {
270 float *values = new float[3];
271 getAcceleration(&values[0], &values[1], &values[2]);
272 return values;
273 }
274 #endif
275
276