1 /* 2 * Author: Jon Trulson <jtrulson (at) 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 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 58 MMA7660::~MMA7660() 59 { 60 if (m_isrInstalled) 61 uninstallISR(); 62 63 setModeStandby(); 64 mraa_i2c_stop(m_i2c); 65 } 66 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 79 uint8_t MMA7660::readByte(uint8_t reg) 80 { 81 return mraa_i2c_read_byte_data(m_i2c, reg); 82 } 83 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 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 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 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 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 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 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 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 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 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 208 void MMA7660::installISR(int pin, IsrCallback *cb) 209 { 210 installISR(pin, generic_callback_isr, cb); 211 } 212 #endif 213 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 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 244 bool MMA7660::setInterruptBits(uint8_t ibits) 245 { 246 return writeByte(REG_INTSU, ibits); 247 } 248 249 bool MMA7660::setSampleRate(MMA7660_AUTOSLEEP_T sr) 250 { 251 return writeByte(REG_SR, sr); 252 } 253 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 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