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 #pragma once 25 26 #include <string> 27 #include <mraa/common.hpp> 28 #include <mraa/i2c.hpp> 29 30 #define H3LIS331DL_I2C_BUS 0 31 #define H3LIS331DL_DEFAULT_I2C_ADDR 0x18 32 33 namespace upm { 34 35 /** 36 * @brief H3LIS331DL I2C Accelerometer (400g) library 37 * @defgroup h3lis331dl libupm-h3lis331dl 38 * @ingroup seeed i2c accelerometer 39 */ 40 41 /** 42 * @library h3lis331dl 43 * @sensor h3lis331dl 44 * @comname H3LIS331DL 3-Axis Digital Accelerometer 45 * @altname Grove 3-Axis Digital Accelerometer (400g) 46 * @type accelerometer 47 * @man seeed 48 * @web http://www.seeedstudio.com/depot/Grove-3Axis-Digital-Accelerometer400g-p-1897.html 49 * @con i2c 50 * 51 * @brief API for the H3LIS331DL-based Grove 3-Axis Digital Accelerometer (400g) 52 * 53 * This is a high-performance, high-range accelerometer for extreme applications. 54 * 55 * @image html h3lis331dl.jpg 56 * @snippet h3lis331dl.cxx Interesting 57 */ 58 class H3LIS331DL { 59 public: 60 61 /** 62 * H3LIS331DL registers 63 */ 64 typedef enum { 65 // Reserved bytes must not be written into as they contain 66 // factory calibration data. Changing those values may lead to 67 // improper functioning of the device. 68 69 // 0x00-0x0E reserved 70 71 REG_WHOAMI = 0x0f, 72 73 // 0x10-0x1f reserved 74 75 REG_REG1 = 0x20, 76 REG_REG2 = 0x21, 77 REG_REG3 = 0x22, 78 REG_REG4 = 0x23, 79 REG_REG5 = 0x24, 80 81 REG_HP_FILTER_RESET = 0x25, 82 REG_REFERENCE = 0x26, 83 84 REG_STATUS = 0x27, 85 86 REG_OUT_X_L = 0x28, 87 REG_OUT_X_H = 0x29, 88 REG_OUT_Y_L = 0x2a, 89 REG_OUT_Y_H = 0x2b, 90 REG_OUT_Z_L = 0x2c, 91 REG_OUT_Z_H = 0x2d, 92 93 // 0x2e, 0x2f reserved 94 95 REG_INT1_CFG = 0x30, 96 REG_INT1_SRC = 0x31, 97 REG_INT1_THS = 0x32, 98 REG_INT1_DUR = 0x33, 99 100 REG_INT2_CFG = 0x34, 101 REG_INT2_SRC = 0x35, 102 REG_INT2_THS = 0x36, 103 REG_INT2_DUR = 0x37, 104 105 // 0x38-0x3f reserved 106 } H3LIS331DL_REG_T; 107 108 /** 109 * REG1 bits 110 */ 111 typedef enum { 112 REG1_XEN = 0x01, // X-axis enable 113 REG1_YEN = 0x02, 114 REG1_ZEN = 0x04, 115 116 REG1_DR0 = 0x08, // data rate 117 REG1_DR1 = 0x10, 118 REG1_DR_SHIFT = 3, // DR shift 119 120 REG1_PM0 = 0x20, // power mode 121 REG1_PM1 = 0x40, 122 REG1_PM2 = 0x80, 123 REG1_PM_SHIFT = 5 124 } REG1_BITS_T; 125 126 /** 127 * REG1 DR (output rate) bits 128 */ 129 typedef enum { 130 DR_50_37 = 0x0, // 50Hz output with 37Hz LPF cutoff 131 DR_100_74 = 0x1, 132 DR_400_292 = 0x2, 133 DR_1000_780 = 0x3 134 } DR_BITS_T; 135 136 /** 137 * REG1 PM (power mode) bits 138 */ 139 typedef enum { 140 PM_POWERDWN = 0x0, 141 PM_NORMAL = 0x1, 142 PM_LP05 = 0x2, // .5 updates/sec 143 PM_LP1 = 0x3, // 1 update/sec 144 PM_LP2 = 0x4, 145 PM_LP5 = 0x5, 146 PM_LP10 = 0x6 147 } PM_BITS_T; 148 149 /** 150 * REG2 bits 151 */ 152 typedef enum { 153 REG2_HPCF0 = 0x01, 154 REG2_HPCF1 = 0x02, 155 REG2_HPCF_SHIFT = 0, 156 157 REG2_HPEN1 = 0x04, 158 REG2_HPEN2 = 0x08, 159 REG2_FDS = 0x10, 160 161 REG2_HPM0 = 0x20, 162 REG2_HPM1 = 0x40, 163 REG2_HPM_SHIFT = 5, 164 165 REG2_BOOT = 0x80 166 } REG2_BITS_T; 167 168 /** 169 * REG2 HPCF (high-pass cutoff frequency) bits 170 */ 171 typedef enum { 172 HPCF_8 = 0x0, 173 HPCF_16 = 0x1, 174 HPCF_32 = 0x2, 175 HPCF_64 = 0x3, 176 } HPCF_BITS_T; 177 178 /** 179 * REG2 HPM (high-pass filter mode) bits 180 */ 181 typedef enum { 182 HPM_NORMAL0 = 0x0, 183 HPM_REF = 0x1, 184 HPM_NORMAL1 = 0x2 185 } HPM_BITS_T; 186 187 /** 188 * REG3 bits 189 */ 190 typedef enum { 191 REG3_I1_CFG0 = 0x01, 192 REG3_I1_CFG1 = 0x02, 193 REG3_I1_CFG_SHIFT = 0, 194 195 REG3_LIR1 = 0x04, 196 197 REG3_I2_CFG0 = 0x08, 198 REG3_I2_CFG1 = 0x10, 199 REG3_I2_CFG_SHIFT = 3, 200 201 REG3_LIR2 = 0x20, 202 REG3_PP_OD = 0x40, 203 REG3_IHL = 0x80 204 } REG3_BITS_T; 205 206 /** 207 * REG3 I1/I2 PAD control bits 208 */ 209 typedef enum { 210 I_SRC = 0x0, // INT source 211 I_OR = 0x1, // INT1 OR INT2 source 212 I_DR = 0x2, // Data Ready 213 I_BOOTING = 0x3 // Boot is running 214 } I_CFG_BITS_T; 215 216 /** 217 * REG4 bits 218 */ 219 typedef enum { 220 REG4_SIM = 0x01, // SPI 4 or 3 wire 221 222 // bits 01,02,04 reserved 223 224 REG4_FS0 = 0x10, 225 REG4_FS1 = 0x20, 226 REG4_FS_SHIFT = 4, 227 228 REG4_BLE = 0x40, // big/little-endian 229 REG4_BDU = 0x80 // Block data update 230 } REG4_BITS_T; 231 232 /** 233 * REG4 FS (full scale) bits 234 */ 235 typedef enum { 236 FS_100 = 0x0, // 100g scale 237 FS_200 = 0x1, // 200g scale 238 FS_400 = 0x3 // 400g scale 239 } FS_BITS_T; 240 241 /** 242 * REG5 TURNON (sleep to wake) bits 243 */ 244 typedef enum { 245 REG5_TURNON0 = 0x01, // turn-on mode for sleep-to-wake 246 REG5_TURNON1 = 0x02 247 248 // bits 04-80 reserved 249 } REG5_BITS_T; 250 251 /** 252 * STATUS bits 253 */ 254 typedef enum { 255 STATUS_XDA = 0x01, // X data available 256 STATUS_YDA = 0x02, 257 STATUS_ZDA = 0x04, 258 STATUS_ZYXDA = 0x08, // X, Y, and Z data available 259 STATUS_XOR = 0x10, // X overrun 260 STATUS_YOR = 0x20, 261 STATUS_ZOR = 0x40, 262 STATUS_ZYXOR = 0x80 // X, Y, and Z data overrun 263 } STATUS_BITS_T; 264 265 /** 266 * INT1/INT2 CFG bits 267 */ 268 typedef enum { 269 INT_CFG_XLIE = 0x01, // enable intr on low X event 270 INT_CFG_XHIE = 0x02, // enable intr on high X event 271 INT_CFG_YLIE = 0x04, 272 INT_CFG_YHIE = 0x08, 273 INT_CFG_ZLIE = 0x10, 274 INT_CFG_ZHIE = 0x20, 275 // 0x40 reserved 276 INT_CFG_AOI = 0x80 // AND or OR combination or intrs 277 } INT_CFG_BITS_T; 278 279 /** 280 * INT1/INT2 SRC bits 281 */ 282 typedef enum { 283 INT_SRC_XL = 0x01, // X low intr event 284 INT_SRC_XH = 0x02, // X high intr event 285 INT_SRC_YL = 0x04, 286 INT_SRC_YH = 0x08, 287 INT_SRC_ZL = 0x10, 288 INT_SRC_ZH = 0x20, 289 INT_SRC_IA = 0x40 // Interrupt generated (active) 290 // 0x80 reserved 291 } INT_SRC_BITS_T; 292 293 /** 294 * H3LIS331DL constructor 295 * 296 * @param bus I2C bus to use 297 * @param address Address for this device 298 */ 299 H3LIS331DL(int bus, uint8_t address = H3LIS331DL_DEFAULT_I2C_ADDR); 300 301 /** 302 * H3LIS331DL destructor 303 */ 304 ~H3LIS331DL(); 305 306 /** 307 * Sets up initial values and starts operation 308 * 309 * @param odr Data rate: one of the DR_BITS_T values 310 * @param pm Power mode: one of the PM_BITS_T values 311 * @param fs FullScale: one of the FS_BITS_T values 312 * @return True if successful 313 */ 314 bool init(DR_BITS_T odr=DR_50_37, PM_BITS_T pm=PM_NORMAL, 315 FS_BITS_T fs=FS_100); 316 317 /** 318 * Reads and returns the chip ID (WHO_AM_I register) 319 * 320 * @return True if successful 321 */ 322 uint8_t getChipID(); 323 324 /** 325 * Sets the output data rate 326 * 327 * @param One of the DR_BITS_T values 328 * @return True if successful 329 */ 330 bool setDataRate(DR_BITS_T odr); 331 332 /** 333 * Sets the power mode 334 * 335 * @param One of the PM_BITS_T values 336 * @return True if successful 337 */ 338 bool setPowerMode(PM_BITS_T pm); 339 340 /** 341 * Enables one or more of the 3 axes. The argument is a bitmask 342 * composed of REG1_XEN, REG1_YEN, and/or REG1_ZEN corresponding to 343 * the axes you want enabled. 344 * 345 * @param axisEnable Bitmask of axes to enable 346 * (REG1_XEN | REG1_YEN | REG1_ZEN) 347 * @return True if successful 348 */ 349 bool enableAxis(uint8_t axisEnable); 350 351 /** 352 * Sets the scaling factor to 100g, 200g, or 400g 353 * 354 * @param fs One of the FS_BITS_T values 355 * @return True if successful 356 */ 357 bool setFullScale(FS_BITS_T fs); 358 359 /** 360 * Sets a high-pass cutoff filter 361 * 362 * @param val One of the HPCF_BITS_T values 363 * @return True if successful 364 */ 365 bool setHPCF(HPCF_BITS_T val); 366 367 /** 368 * Sets a high-pass filter mode 369 * 370 * @param val One of the HPM_BITS_T values 371 * @return True if successful 372 */ 373 bool setHPM(HPM_BITS_T val); 374 375 /** 376 * Boots the device. Booting the device causes internal flash 377 * calibration values to be reloaded into the visible registers 378 * in case they have been corrupted. This function 379 * returns when the booting is complete. 380 * 381 * @return True if successful 382 */ 383 bool boot(); 384 385 /** 386 * Enables a high-pass filter for interrupt 1 source 387 * 388 * @param enable True to enable the filter, false otherwise 389 * @return True if successful 390 */ 391 bool enableHPF1(bool enable); 392 393 /** 394 * Enables a high-pass filter for interrupt 2 source 395 * 396 * @param enable True to enable the filter, false otherwise 397 * @return True if successful 398 */ 399 bool enableHPF2(bool enable); 400 401 /** 402 * Enables filtered data selection 403 * 404 * @param enable True to enable, false otherwise 405 * @return True if successful 406 */ 407 bool enableFDS(bool enable); 408 409 /** 410 * Sets interrupts to be active low instead of high 411 * 412 * @param enable True to enable, false otherwise 413 * @return True if successful 414 */ 415 bool setInterruptActiveLow(bool enable); 416 417 /** 418 * Sets an interrupt output mode to open drain rather than push/pull 419 * 420 * @param enable True to enable, false otherwise 421 * @return True if successful 422 */ 423 bool setInterruptOpenDrain(bool enable); 424 425 /** 426 * Enables interrupt 1 latch 427 * 428 * @param enable True to enable, false otherwise 429 * @return True if successful 430 */ 431 bool setInterrupt1Latch(bool enable); 432 433 /** 434 * Enables interrupt 2 latch 435 * 436 * @param enable True to enable, false otherwise 437 * @return True if successful 438 */ 439 bool setInterrupt2Latch(bool enable); 440 441 /** 442 * Sets the interrupt 1 pad configuration 443 * 444 * @param val One fo the I_CFG_BITS_T values 445 * @return True if successful 446 */ 447 bool setInterrupt1PadConfig(I_CFG_BITS_T val); 448 449 /** 450 * Sets the interrupt 2 pad configuration 451 * 452 * @param val One fo the I_CFG_BITS_T values 453 * @return True if successful 454 */ 455 bool setInterrupt2PadConfig(I_CFG_BITS_T val); 456 457 /** 458 * Enables block data update. When enabled, low/high output 459 * registers are not updated until both low and high values have 460 * been read. 461 * 462 * @param enable True to enable, false otherwise 463 * @return True if successful 464 */ 465 bool enableBDU(bool enable); 466 467 /** 468 * Enables big-endian output for 16b reads 469 * 470 * @param enable True to enable, false otherwise 471 * @return True if successful 472 */ 473 bool enableBLE(bool enable); 474 475 /** 476 * Enables sleep-to-wake functionality 477 * 478 * @param enable True to enable, false otherwise 479 * @return True if successful 480 */ 481 bool enableSleepToWake(bool enable); 482 483 /** 484 * Returns the contents of the REG_STATUS register 485 * 486 * @return Contents of the REG_STATUS register 487 */ 488 uint8_t getStatus(); 489 490 /** 491 * Sets up the interrupt 1 config register 492 * 493 * @param val Bitmask of desired INT_CFG_BITS_T bits 494 * @return True if successful 495 */ 496 bool setInterrupt1Config(uint8_t val); 497 498 /** 499 * Sets up the interrupt 2 config register 500 * 501 * @param val Bitmask of desired INT_CFG_BITS_T bits 502 * @return True if successful 503 */ 504 bool setInterrupt2Config(uint8_t val); 505 506 /** 507 * Sets up the interrupt 1 source register 508 * 509 * @param val Bitmask of desired INT_SRC_BITS_T bits 510 * @return True if successful 511 */ 512 bool setInterrupt1Source(uint8_t val); 513 514 /** 515 * Sets up the interrupt 2 source register 516 * 517 * @param val Bitmask of desired INT_SRC_BITS_T bits 518 * @return True if successful 519 */ 520 bool setInterrupt2Source(uint8_t val); 521 522 /** 523 * Sets up the interrupt 1 threshold register 524 * 525 * @param val Threshhold to set 526 * @return True if successful 527 */ 528 bool setInterrupt1Threshold(uint8_t val); 529 530 /** 531 * Sets up the interrupt 2 threshold register 532 * 533 * @param val Threshhold to set 534 * @return True if successful 535 */ 536 bool setInterrupt2Threshold(uint8_t val); 537 538 /** 539 * Sets up the interrupt 1 duration register 540 * 541 * @param val Duration to set 542 * @return True if successful 543 */ 544 bool setInterrupt1Duration(uint8_t val); 545 546 /** 547 * Sets up the interrupt 2 duration register 548 * 549 * @param val Duration to set 550 * @return True if successful 551 */ 552 bool setInterrupt2Duration(uint8_t val); 553 554 /** 555 * Reads the sensor and stores current values internally 556 */ 557 void update(); 558 559 /** 560 * Sets adjustment offsets for each of the axes. This can be used 561 * for calibration. The values supplied here are subtracted 562 * from the axis data read from the device. 563 * 564 * @param adjX Amount by which to correct the X-axis measurement 565 * @param adjY Amount by which to correct the Y-axis measurement 566 * @param adjZ Amount by which to correct the Z-axis measurement 567 */ 568 void setAdjustmentOffsets(int adjX, int adjY, int adjZ); 569 570 /** 571 * Gets acceleration values for each of the axes 572 * 573 * @param aX Returned X-axis acceleration 574 * @param aY Returned Y-axis acceleration 575 * @param aZ Returned Z-axis acceleration 576 */ 577 void getAcceleration(float *aX, float *aY, float *aZ); 578 579 /** 580 * Gets raw axis values 581 * 582 * @param x Returned raw X-axis value 583 * @param y Returned raw Y-axis value 584 * @param z Returned raw Z-axis value 585 */ 586 void getRawXYZ(int *x, int *y, int *z); 587 588 /** 589 * Gets adjusted axis values 590 * 591 * @param x Returned X-axis value 592 * @param y Returned Y-axis value 593 * @param z Returned Z-axis value 594 */ 595 void getXYZ(int *x, int *y, int *z); 596 597 #ifdef SWIGJAVA 598 /** 599 * Gets acceleration values for each of the axes 600 * 601 * @return Array containing X, Y, Z acceleration values 602 */ 603 float *getAcceleration(); 604 605 /** 606 * Gets raw axis values 607 * 608 * @return Array containing X, Y, Z raw values 609 */ 610 int *getRawXYZ(); 611 612 /** 613 * Gets adjusted axis values 614 * 615 * @return Array containing X, Y, Z adjusted axis values 616 */ 617 int *getXYZ(); 618 #endif 619 620 621 /** 622 * Provides public access to the MRAA I2C context of the class for 623 * direct user access 624 * 625 * @return Reference to the class I2C context 626 */ 627 mraa::I2c& i2cContext() { return m_i2c; }; 628 629 630 protected: 631 int16_t m_rawX, m_rawY, m_rawZ; 632 int16_t m_adjX, m_adjY, m_adjZ; 633 mraa::I2c m_i2c; 634 635 private: 636 uint8_t m_addr; 637 }; 638 } 639 640 641