Home | History | Annotate | Download | only in h3lis331dl
      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 <unistd.h>
     26 #include <math.h>
     27 #include <iostream>
     28 #include <stdexcept>
     29 #include <string>
     30 
     31 #include "h3lis331dl.h"
     32 
     33 using namespace upm;
     34 using namespace std;
     35 
     36 
     37 H3LIS331DL::H3LIS331DL(int bus, uint8_t address):
     38   m_i2c(bus)
     39 {
     40   m_addr = address;
     41 
     42   mraa::Result rv;
     43   if ( (rv = m_i2c.address(m_addr)) != mraa::SUCCESS)
     44     {
     45       throw std::runtime_error(std::string(__FUNCTION__) +
     46                                ": I2c.address() failed");
     47       return;
     48     }
     49 
     50   m_rawX = m_rawY = m_rawZ = 0;
     51   setAdjustmentOffsets(0, 0, 0);
     52 }
     53 
     54 H3LIS331DL::~H3LIS331DL()
     55 {
     56 }
     57 
     58 bool H3LIS331DL::init(DR_BITS_T odr, PM_BITS_T pm, FS_BITS_T fs)
     59 {
     60   if (!setDataRate(odr))
     61     return false;
     62   if (!setPowerMode(pm))
     63     return false;
     64   if (!setFullScale(fs))
     65     return false;
     66 
     67   // now enable X, Y, and Z axes
     68   if (enableAxis(REG1_XEN | REG1_YEN | REG1_ZEN))
     69     return false;
     70 
     71   return true;
     72 }
     73 
     74 uint8_t H3LIS331DL::getChipID()
     75 {
     76   return m_i2c.readReg(REG_WHOAMI);
     77 }
     78 
     79 bool H3LIS331DL::setDataRate(DR_BITS_T odr)
     80 {
     81   uint8_t reg1 = m_i2c.readReg(REG_REG1);
     82 
     83   reg1 &= ~(REG1_DR0 | REG1_DR1);
     84   reg1 |= (odr << REG1_DR_SHIFT);
     85 
     86   if (m_i2c.writeReg(REG_REG1, reg1))
     87     {
     88       throw std::runtime_error(std::string(__FUNCTION__) +
     89                                ": I2c.writeReg() failed");
     90       return false;
     91     }
     92 
     93   return true;
     94 }
     95 
     96 bool H3LIS331DL::setPowerMode(PM_BITS_T pm)
     97 {
     98   uint8_t reg1 = m_i2c.readReg(REG_REG1);
     99 
    100   reg1 &= ~(REG1_PM0 | REG1_PM1 | REG1_PM2);
    101   reg1 |= (pm << REG1_PM_SHIFT);
    102 
    103   if (m_i2c.writeReg(REG_REG1, reg1))
    104     {
    105       throw std::runtime_error(std::string(__FUNCTION__) +
    106                                ": I2c.writeReg() failed");
    107       return false;
    108     }
    109 
    110   return true;
    111 }
    112 
    113 bool H3LIS331DL::enableAxis(uint8_t axisEnable)
    114 {
    115   uint8_t reg1 = m_i2c.readReg(REG_REG1);
    116 
    117   reg1 &= ~(REG1_XEN | REG1_YEN | REG1_ZEN);
    118   reg1 |= (axisEnable & (REG1_XEN | REG1_YEN | REG1_ZEN));
    119 
    120   if (m_i2c.writeReg(REG_REG1, reg1))
    121     {
    122       throw std::runtime_error(std::string(__FUNCTION__) +
    123                                ": I2c.writeReg() failed");
    124       return false;
    125     }
    126 
    127   return true;
    128 }
    129 
    130 bool H3LIS331DL::setFullScale(FS_BITS_T fs)
    131 {
    132   uint8_t reg4 = m_i2c.readReg(REG_REG4);
    133 
    134   reg4 &= ~(REG4_FS0 | REG4_FS1);
    135   reg4 |= (fs << REG4_FS_SHIFT);
    136 
    137   if (m_i2c.writeReg(REG_REG4, reg4))
    138     {
    139       throw std::runtime_error(std::string(__FUNCTION__) +
    140                                ": I2c.writeReg() failed");
    141       return false;
    142     }
    143 
    144   return true;
    145 }
    146 
    147 bool H3LIS331DL::setHPCF(HPCF_BITS_T val)
    148 {
    149   uint8_t reg = m_i2c.readReg(REG_REG2);
    150 
    151   reg &= ~(REG2_HPCF0 | REG2_HPCF1);
    152   reg |= (val << REG2_HPCF_SHIFT);
    153 
    154   if (m_i2c.writeReg(REG_REG2, reg))
    155     {
    156       throw std::runtime_error(std::string(__FUNCTION__) +
    157                                ": I2c.writeReg() failed");
    158       return false;
    159     }
    160 
    161   return true;
    162 }
    163 
    164 bool H3LIS331DL::setHPM(HPM_BITS_T val)
    165 {
    166   uint8_t reg = m_i2c.readReg(REG_REG2);
    167 
    168   reg &= ~(REG2_HPM0 | REG2_HPM1);
    169   reg |= (val << REG2_HPM_SHIFT);
    170 
    171   if (m_i2c.writeReg(REG_REG2, reg))
    172     {
    173       throw std::runtime_error(std::string(__FUNCTION__) +
    174                                ": I2c.writeReg() failed");
    175       return false;
    176     }
    177 
    178   return true;
    179 }
    180 
    181 bool H3LIS331DL::boot()
    182 {
    183   uint8_t reg = m_i2c.readReg(REG_REG2);
    184 
    185   reg |= REG2_BOOT;
    186 
    187   if (m_i2c.writeReg(REG_REG2, reg))
    188     {
    189       throw std::runtime_error(std::string(__FUNCTION__) +
    190                                ": I2c.writeReg() failed");
    191       return false;
    192     }
    193 
    194   // wait for the boot bit to clear
    195   do {
    196     reg = m_i2c.readReg(REG_REG2);
    197     usleep(200000);
    198   } while (reg & REG2_BOOT);
    199 
    200   return true;
    201 }
    202 
    203 bool H3LIS331DL::enableHPF1(bool enable)
    204 {
    205   uint8_t reg = m_i2c.readReg(REG_REG2);
    206 
    207   if (enable)
    208     reg |= REG2_HPEN1;
    209   else
    210     reg &= ~REG2_HPEN1;
    211 
    212   if (m_i2c.writeReg(REG_REG2, reg))
    213     {
    214       throw std::runtime_error(std::string(__FUNCTION__) +
    215                                ": I2c.writeReg() failed");
    216       return false;
    217     }
    218 
    219   return true;
    220 }
    221 
    222 bool H3LIS331DL::enableHPF2(bool enable)
    223 {
    224   uint8_t reg = m_i2c.readReg(REG_REG2);
    225 
    226   if (enable)
    227     reg |= REG2_HPEN2;
    228   else
    229     reg &= ~REG2_HPEN2;
    230 
    231   if (m_i2c.writeReg(REG_REG2, reg))
    232     {
    233       throw std::runtime_error(std::string(__FUNCTION__) +
    234                                ": I2c.writeReg() failed");
    235       return false;
    236     }
    237 
    238   return true;
    239 }
    240 
    241 bool H3LIS331DL::enableFDS(bool enable)
    242 {
    243   uint8_t reg = m_i2c.readReg(REG_REG2);
    244 
    245   if (enable)
    246     reg |= REG2_FDS;
    247   else
    248     reg &= ~REG2_FDS;
    249 
    250   if (m_i2c.writeReg(REG_REG2, reg))
    251     {
    252       throw std::runtime_error(std::string(__FUNCTION__) +
    253                                ": I2c.writeReg() failed");
    254       return false;
    255     }
    256 
    257   return true;
    258 }
    259 
    260 bool H3LIS331DL::setInterruptActiveLow(bool enable)
    261 {
    262   uint8_t reg = m_i2c.readReg(REG_REG3);
    263 
    264   if (enable)
    265     reg |= REG3_IHL;
    266   else
    267     reg &= ~REG3_IHL;
    268 
    269   if (m_i2c.writeReg(REG_REG3, reg))
    270     {
    271       throw std::runtime_error(std::string(__FUNCTION__) +
    272                                ": I2c.writeReg() failed");
    273       return false;
    274     }
    275 
    276   return true;
    277 }
    278 
    279 bool H3LIS331DL::setInterruptOpenDrain(bool enable)
    280 {
    281   uint8_t reg = m_i2c.readReg(REG_REG3);
    282 
    283   if (enable)
    284     reg |= REG3_PP_OD;
    285   else
    286     reg &= ~REG3_PP_OD;
    287 
    288   if (m_i2c.writeReg(REG_REG3, reg))
    289     {
    290       throw std::runtime_error(std::string(__FUNCTION__) +
    291                                ": I2c.writeReg() failed");
    292       return false;
    293     }
    294 
    295   return true;
    296 }
    297 
    298 bool H3LIS331DL::setInterrupt1Latch(bool enable)
    299 {
    300   uint8_t reg = m_i2c.readReg(REG_REG3);
    301 
    302   if (enable)
    303     reg |= REG3_LIR1;
    304   else
    305     reg &= ~REG3_LIR1;
    306 
    307   if (m_i2c.writeReg(REG_REG3, reg))
    308     {
    309       throw std::runtime_error(std::string(__FUNCTION__) +
    310                                ": I2c.writeReg() failed");
    311       return false;
    312     }
    313 
    314   return true;
    315 }
    316 
    317 bool H3LIS331DL::setInterrupt2Latch(bool enable)
    318 {
    319   uint8_t reg = m_i2c.readReg(REG_REG3);
    320 
    321   if (enable)
    322     reg |= REG3_LIR2;
    323   else
    324     reg &= ~REG3_LIR2;
    325 
    326   if (m_i2c.writeReg(REG_REG3, reg))
    327     {
    328       throw std::runtime_error(std::string(__FUNCTION__) +
    329                                ": I2c.writeReg() failed");
    330       return false;
    331     }
    332 
    333   return true;
    334 }
    335 
    336 bool H3LIS331DL::setInterrupt1PadConfig(I_CFG_BITS_T val)
    337 {
    338   uint8_t reg = m_i2c.readReg(REG_REG3);
    339 
    340   reg &= ~(REG3_I1_CFG0 | REG3_I1_CFG1);
    341   reg |= (val << REG3_I1_CFG_SHIFT);
    342 
    343   if (m_i2c.writeReg(REG_REG3, reg))
    344     {
    345       throw std::runtime_error(std::string(__FUNCTION__) +
    346                                ": I2c.writeReg() failed");
    347       return false;
    348     }
    349 
    350   return true;
    351 }
    352 
    353 bool H3LIS331DL::setInterrupt2PadConfig(I_CFG_BITS_T val)
    354 {
    355   uint8_t reg = m_i2c.readReg(REG_REG3);
    356 
    357   reg &= ~(REG3_I2_CFG0 | REG3_I2_CFG1);
    358   reg |= (val << REG3_I2_CFG_SHIFT);
    359 
    360   if (m_i2c.writeReg(REG_REG3, reg))
    361     {
    362       throw std::runtime_error(std::string(__FUNCTION__) +
    363                                ": I2c.writeReg() failed");
    364       return false;
    365     }
    366 
    367   return true;
    368 }
    369 
    370 
    371 bool H3LIS331DL::enableBDU(bool enable)
    372 {
    373   uint8_t reg = m_i2c.readReg(REG_REG4);
    374 
    375   if (enable)
    376     reg |= REG4_BDU;
    377   else
    378     reg &= ~REG4_BDU;
    379 
    380   if (m_i2c.writeReg(REG_REG4, reg))
    381     {
    382       throw std::runtime_error(std::string(__FUNCTION__) +
    383                                ": I2c.writeReg() failed");
    384       return false;
    385     }
    386 
    387   return true;
    388 }
    389 
    390 bool H3LIS331DL::enableBLE(bool enable)
    391 {
    392   uint8_t reg = m_i2c.readReg(REG_REG4);
    393 
    394   if (enable)
    395     reg |= REG4_BLE;
    396   else
    397     reg &= ~REG4_BLE;
    398 
    399   if (m_i2c.writeReg(REG_REG4, reg))
    400     {
    401       throw std::runtime_error(std::string(__FUNCTION__) +
    402                                ": I2c.writeReg() failed");
    403       return false;
    404     }
    405 
    406   return true;
    407 }
    408 
    409 bool H3LIS331DL::enableSleepToWake(bool enable)
    410 {
    411   uint8_t reg = m_i2c.readReg(REG_REG5);
    412 
    413   if (enable)
    414     reg |= (REG5_TURNON0 | REG5_TURNON1);
    415   else
    416     reg &= ~(REG5_TURNON0 | REG5_TURNON1);
    417 
    418   if (m_i2c.writeReg(REG_REG5, reg))
    419     {
    420       throw std::runtime_error(std::string(__FUNCTION__) +
    421                                ": I2c.writeReg() failed");
    422       return false;
    423     }
    424 
    425   return true;
    426 }
    427 
    428 uint8_t H3LIS331DL::getStatus()
    429 {
    430   return m_i2c.readReg(REG_STATUS);
    431 }
    432 
    433 bool H3LIS331DL::setInterrupt1Config(uint8_t val)
    434 {
    435   uint8_t reg = m_i2c.readReg(REG_INT1_CFG);
    436 
    437   // mask off reserved bit
    438   reg = (val & ~0x40);
    439 
    440   if (m_i2c.writeReg(REG_INT1_CFG, reg))
    441     {
    442       throw std::runtime_error(std::string(__FUNCTION__) +
    443                                ": I2c.writeReg() failed");
    444       return false;
    445     }
    446 
    447   return true;
    448 }
    449 
    450 bool H3LIS331DL::setInterrupt1Source(uint8_t val)
    451 {
    452   uint8_t reg = m_i2c.readReg(REG_INT1_SRC);
    453 
    454   // mask off reserved bit
    455   reg = (val & ~0x80);
    456 
    457   if (m_i2c.writeReg(REG_INT1_SRC, reg))
    458     {
    459       throw std::runtime_error(std::string(__FUNCTION__) +
    460                                ": I2c.writeReg() failed");
    461       return false;
    462     }
    463 
    464   return true;
    465 }
    466 
    467 bool H3LIS331DL::setInterrupt1Threshold(uint8_t val)
    468 {
    469   if (m_i2c.writeReg(REG_INT1_THS, val))
    470     {
    471       throw std::runtime_error(std::string(__FUNCTION__) +
    472                                ": I2c.writeReg() failed");
    473       return false;
    474     }
    475 
    476   return true;
    477 }
    478 
    479 bool H3LIS331DL::setInterrupt1Duration(uint8_t val)
    480 {
    481   if (m_i2c.writeReg(REG_INT1_DUR, val))
    482     {
    483       throw std::runtime_error(std::string(__FUNCTION__) +
    484                                ": I2c.writeReg() failed");
    485       return false;
    486     }
    487 
    488   return true;
    489 }
    490 
    491 bool H3LIS331DL::setInterrupt2Config(uint8_t val)
    492 {
    493   uint8_t reg = m_i2c.readReg(REG_INT2_CFG);
    494 
    495   // mask off reserved bit
    496   reg = (val & ~0x40);
    497 
    498   if (m_i2c.writeReg(REG_INT2_CFG, reg))
    499     {
    500       throw std::runtime_error(std::string(__FUNCTION__) +
    501                                ": I2c.writeReg() failed");
    502       return false;
    503     }
    504 
    505   return true;
    506 }
    507 
    508 bool H3LIS331DL::setInterrupt2Source(uint8_t val)
    509 {
    510   uint8_t reg = m_i2c.readReg(REG_INT2_SRC);
    511 
    512   // mask off reserved bit
    513   reg = (val & ~0x80);
    514 
    515   if (m_i2c.writeReg(REG_INT2_SRC, reg))
    516     {
    517       throw std::runtime_error(std::string(__FUNCTION__) +
    518                                ": I2c.writeReg() failed");
    519       return false;
    520     }
    521 
    522   return true;
    523 }
    524 
    525 bool H3LIS331DL::setInterrupt2Threshold(uint8_t val)
    526 {
    527   if (m_i2c.writeReg(REG_INT2_THS, val))
    528     {
    529       throw std::runtime_error(std::string(__FUNCTION__) +
    530                                ": I2c.writeReg() failed");
    531       return false;
    532     }
    533 
    534   return true;
    535 }
    536 
    537 bool H3LIS331DL::setInterrupt2Duration(uint8_t val)
    538 {
    539   if (m_i2c.writeReg(REG_INT2_DUR, val))
    540     {
    541       throw std::runtime_error(std::string(__FUNCTION__) +
    542                                ": I2c.writeReg() failed");
    543       return false;
    544     }
    545 
    546   return true;
    547 }
    548 
    549 void H3LIS331DL::update()
    550 {
    551   uint8_t low, high;
    552 
    553   // X
    554   low = m_i2c.readReg(REG_OUT_X_L);
    555   high = m_i2c.readReg(REG_OUT_X_H);
    556   m_rawX = ((high << 8) | low);
    557 
    558   // Y
    559   low = m_i2c.readReg(REG_OUT_Y_L);
    560   high = m_i2c.readReg(REG_OUT_Y_H);
    561   m_rawY = ((high << 8) | low);
    562 
    563   // Z
    564   low = m_i2c.readReg(REG_OUT_Z_L);
    565   high = m_i2c.readReg(REG_OUT_Z_H);
    566   m_rawZ = ((high << 8) | low);
    567 }
    568 
    569 void H3LIS331DL::setAdjustmentOffsets(int adjX, int adjY, int adjZ)
    570 {
    571   m_adjX = adjX;
    572   m_adjY = adjY;
    573   m_adjZ = adjZ;
    574 }
    575 
    576 void H3LIS331DL::getAcceleration(float *aX, float *aY, float *aZ)
    577 {
    578   const float gains = 0.003;    // Seeed magic number?
    579 
    580   *aX = float(m_rawX - m_adjX) * gains;
    581   *aY = float(m_rawY - m_adjY) * gains;
    582   *aZ = float(m_rawZ - m_adjZ) * gains;
    583 }
    584 
    585 void H3LIS331DL::getRawXYZ(int *x, int *y, int*z)
    586 {
    587   *x = m_rawX;
    588   *y = m_rawY;
    589   *z = m_rawZ;
    590 }
    591 
    592 void H3LIS331DL::getXYZ(int *x, int *y, int*z)
    593 {
    594   *x = (m_rawX - m_adjX);
    595   *y = (m_rawY - m_adjY);
    596   *z = (m_rawZ - m_adjZ);
    597 }
    598 
    599 #ifdef SWIGJAVA
    600 float *H3LIS331DL::getAcceleration()
    601 {
    602   float *v = new float[3];
    603   getAcceleration(&v[0], &v[1], &v[2]);
    604   return v;
    605 }
    606 
    607 int *H3LIS331DL::getRawXYZ()
    608 {
    609   int *v = new int[3];
    610   getRawXYZ(&v[0], &v[1], &v[2]);
    611   return v;
    612 }
    613 
    614 int *H3LIS331DL::getXYZ()
    615 {
    616   int *v = new int[3];
    617   getXYZ(&v[0], &v[1], &v[2]);
    618   return v;
    619 }
    620 #endif
    621