From 12c81adeba07ca1915f4fd663e3e69f8db0aa068 Mon Sep 17 00:00:00 2001 From: Norbert Wesp Date: Tue, 14 Feb 2017 12:01:32 +0100 Subject: [PATCH] mma8x5x: Added upm support for some MMA8X5X sensors This commit adds support for following sensors: MMA8652 , MMA8653, MMA8451 , MMA8452 , MMA8453 These sensors are three-axis accelerometer. Signed-off-by: Norbert Wesp Signed-off-by: Mihai Tudor Panu --- doxy/samples.mapping.txt | 1 + examples/c++/CMakeLists.txt | 1 + examples/c++/mma8x5x.cxx | 91 +++++++ examples/python/mma8x5x.py | 62 +++++ src/mma8x5x/CMakeLists.txt | 5 + src/mma8x5x/javaupm_mma8x5x.i | 19 ++ src/mma8x5x/jsupm_mma8x5x.i | 8 + src/mma8x5x/mma8x5x.cpp | 346 +++++++++++++++++++++++++ src/mma8x5x/mma8x5x.hpp | 473 ++++++++++++++++++++++++++++++++++ src/mma8x5x/pyupm_mma8x5x.i | 15 ++ 10 files changed, 1021 insertions(+) create mode 100644 examples/c++/mma8x5x.cxx create mode 100644 examples/python/mma8x5x.py create mode 100644 src/mma8x5x/CMakeLists.txt create mode 100644 src/mma8x5x/javaupm_mma8x5x.i create mode 100644 src/mma8x5x/jsupm_mma8x5x.i create mode 100644 src/mma8x5x/mma8x5x.cpp create mode 100644 src/mma8x5x/mma8x5x.hpp create mode 100644 src/mma8x5x/pyupm_mma8x5x.i diff --git a/doxy/samples.mapping.txt b/doxy/samples.mapping.txt index 4b803a6a..886e58e2 100644 --- a/doxy/samples.mapping.txt +++ b/doxy/samples.mapping.txt @@ -76,3 +76,4 @@ sensortemplate.cxx SensorTemplateSample.java sensortemplate.js sensortemplate.py p9813.cxx P9813Sample.java p9813.js p9813.py tcs37727.cxx tcs37727.py tmp006.cxx tmp006.py +mma8x5x.cxx mma8x5x.py diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index 5c40d70b..ddc4c137 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -336,6 +336,7 @@ add_example (lcdks) add_example (mmc35240) add_example (tcs37727) add_example (tmp006) +add_example (mma8x5x) # These are special cases where you specify example binary, source file and module(s) include_directories (${PROJECT_SOURCE_DIR}/src) diff --git a/examples/c++/mma8x5x.cxx b/examples/c++/mma8x5x.cxx new file mode 100644 index 00000000..c7035f89 --- /dev/null +++ b/examples/c++/mma8x5x.cxx @@ -0,0 +1,91 @@ +/* Author: Norbert Wesp + * Copyright (c) 2017 Phytec Messtechnik GmbH. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +#include "mma8x5x.hpp" + +using namespace upm; + +bool run = true; + +void sig_handler(int sig) +{ + if (sig == SIGINT) + run = false; +} + +int main(int argc, char **argv) +{ + signal(SIGINT, sig_handler); + +//! [Interesting] + upm::mma8x5x_data_t data; + + // U can set your own parameters for an MMA8X5X instance with + /* + upm::mma8x5x_params_t params; + params.type = ; device-id of your sensor + params.rate = ; between 0<<3 and 7<<3 + params.range = ; between 0 and 2 + params.offsetX = ; between 0 and 255 + params.offsetY = ; between 0 and 255 + params.offsetZ = ; between 0 and 255 + */ + + cout << "Initializing test-application..." << endl; + + // Instantiate an MMA8X5X instance on bus 1 with default parameters + // The sensor-type will be detected by reading out the device-id + upm::MMA8X5X *mySensor = new upm::MMA8X5X(1); + + // If u have set own parameters use this one + /* + upm::MMA8X5X *mySensor = new upm::MMA8X5X(1, ¶ms); + */ + + // activate periodic measurements + mySensor->setActive(); + + // update and print available values every second + while (run) + { + mySensor->getData (&data, true); + cout << "x: " << (int)data.x << endl + << "y: " << (int)data.y << endl + << "z: " << (int)data.z << endl; + + cout << endl; + + sleep(1); + } + + cout << "Exiting test-application..." << endl; + + delete mySensor; +//! [Interesting] + + return 0; +} \ No newline at end of file diff --git a/examples/python/mma8x5x.py b/examples/python/mma8x5x.py new file mode 100644 index 00000000..51bb9621 --- /dev/null +++ b/examples/python/mma8x5x.py @@ -0,0 +1,62 @@ +#!/usr/bin/python +# Author: Norbert Wesp +# Copyright (c) 2017 Phytec Messtechnik GmbH. +# +# based on: tcs3414cs.py +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +from __future__ import print_function +import time, sys, signal, atexit +from upm import pyupm_mma8x5x as MMA8X5X + +def main(): + # Instantiate the Three-Axis Accelerometer Sensor on I2C on bus 1 + mySensor = MMA8X5X.MMA8X5X(1) + + ## Exit handlers ## + # This stops python from printing a stacktrace when you hit control-C + def SIGINTHandler(signum, frame): + raise SystemExit + + # This lets you run code on exit, + # including functions from mySensor + def exitHandler(): + print("Exiting") + sys.exit(0) + + # Register exit handlers + atexit.register(exitHandler) + signal.signal(signal.SIGINT, SIGINTHandler) + + data = MMA8X5X.mma8x5x_data_t() + + # activate periodic measurements + mySensor.setActive(); + + # Print out the x, y, z value every 0.5 seconds + while(1): + mySensor.getData(data, True) + print(data.x, data.y, data.z) + + time.sleep(.5) + +if __name__ == '__main__': + main() diff --git a/src/mma8x5x/CMakeLists.txt b/src/mma8x5x/CMakeLists.txt new file mode 100644 index 00000000..8c53050e --- /dev/null +++ b/src/mma8x5x/CMakeLists.txt @@ -0,0 +1,5 @@ +set (libname "mma8x5x") +set (libdescription "Tri-axis Accelerometer Sensor") +set (module_src ${libname}.cpp) +set (module_hpp ${libname}.hpp) +upm_module_init() diff --git a/src/mma8x5x/javaupm_mma8x5x.i b/src/mma8x5x/javaupm_mma8x5x.i new file mode 100644 index 00000000..15597374 --- /dev/null +++ b/src/mma8x5x/javaupm_mma8x5x.i @@ -0,0 +1,19 @@ +%module javaupm_mma8x5x +%include "../upm.i" + +%{ + #include "mma8x5x.hpp" +%} + +%include "mma8x5x.hpp" + +%pragma(java) jniclasscode=%{ + static { + try { + System.loadLibrary("javaupm_mma8x5x"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. \n" + e); + System.exit(1); + } + } +%} \ No newline at end of file diff --git a/src/mma8x5x/jsupm_mma8x5x.i b/src/mma8x5x/jsupm_mma8x5x.i new file mode 100644 index 00000000..cc0fae9d --- /dev/null +++ b/src/mma8x5x/jsupm_mma8x5x.i @@ -0,0 +1,8 @@ +%module jsupm_mma8x5x +%include "../upm.i" + +%{ + #include "mma8x5x.hpp" +%} + +%include "mma8x5x.hpp" diff --git a/src/mma8x5x/mma8x5x.cpp b/src/mma8x5x/mma8x5x.cpp new file mode 100644 index 00000000..a1a5d7b7 --- /dev/null +++ b/src/mma8x5x/mma8x5x.cpp @@ -0,0 +1,346 @@ +/* + * Author: Norbert Wesp + * Copyright (c) 2017 Phytec Messtechnik GmbH. + * + * based on: RIOT-driver mma8x5x by Johann Fischer + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "mma8x5x.hpp" + +using namespace upm; + +MMA8X5X::MMA8X5X (int bus, mma8x5x_params_t *params, + int devAddr) : m_i2ControlCtx(bus) { + uint8_t reg; + + s_data->x = 0; + s_data->y = 0; + s_data->z = 0; + + m_controlAddr = devAddr; + m_bus = bus; + + mraa::Result ret = m_i2ControlCtx.address(m_controlAddr); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_address() failed"); + } + + if (setDeviceParams(params)) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": setDeviceParams() failed"); + } + + /* reset device */ + ret = m_i2ControlCtx.writeReg(MMA8X5X_CTRL_REG2, MMA8X5X_CTRL_REG2_RST); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte_data() failed"); + } + do { + usleep(500000); + reg = m_i2ControlCtx.readReg(MMA8X5X_CTRL_REG2); + } while (reg & MMA8X5X_CTRL_REG2_RST); + + /* configure the user offset */ + ret = m_i2ControlCtx.writeReg(MMA8X5X_OFF_X, s_params->offsetX); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte_data() failed"); + } + ret = m_i2ControlCtx.writeReg(MMA8X5X_OFF_Y, s_params->offsetY); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte_data() failed"); + } + ret = m_i2ControlCtx.writeReg(MMA8X5X_OFF_Z, s_params->offsetZ); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte_data() failed"); + } + + /* configure range */ + reg = (s_params->range & MMA8X5X_XYZ_DATA_CFG_FS_MASK); + ret = m_i2ControlCtx.writeReg(MMA8X5X_XYZ_DATA_CFG, reg); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte_data() failed"); + } + + /* configure rate and activate the device */ + reg = ((s_params->rate & MMA8X5X_CTRL_REG1_DR_MASK) | + MMA8X5X_CTRL_REG1_ACTIVE); + ret = m_i2ControlCtx.writeReg(MMA8X5X_CTRL_REG1, reg); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte_data() failed"); + } +} + +int +MMA8X5X::setDeviceName(uint8_t type) +{ + uint8_t id; + + if (type == 0){ + id = m_i2ControlCtx.readReg(MMA8X5X_DEVICE_ID_REG); + } else { + id = type; + } + + switch (id) { + case (MMA8X5X_DEVICE_ID_MMA8652): + m_name = MMA8X5X_NAME_MMA8652; + s_params->type = MMA8X5X_DEVICE_ID_MMA8652; + break; + case (MMA8X5X_DEVICE_ID_MMA8653): + m_name = MMA8X5X_NAME_MMA8653; + s_params->type = MMA8X5X_DEVICE_ID_MMA8653; + break; + case (MMA8X5X_DEVICE_ID_MMA8451): + m_name = MMA8X5X_NAME_MMA8451; + s_params->type = MMA8X5X_DEVICE_ID_MMA8451; + break; + case (MMA8X5X_DEVICE_ID_MMA8452): + m_name = MMA8X5X_NAME_MMA8452; + s_params->type = MMA8X5X_DEVICE_ID_MMA8452; + break; + case (MMA8X5X_DEVICE_ID_MMA8453): + m_name = MMA8X5X_NAME_MMA8453; + s_params->type = MMA8X5X_DEVICE_ID_MMA8453; + break; + default: + return -1; + } + + return 0; +} + +int +MMA8X5X::setDeviceParams (mma8x5x_params_t* params) +{ + if (params == NULL) { + if (setDeviceName(0)) { + return -1; + } + + s_params->rate = MMA8X5X_RATE_DEFAULT; + s_params->range = MMA8X5X_RANGE_DEFAULT; + s_params->offsetX = 0; + s_params->offsetY = 0; + s_params->offsetZ = 0; + } else { + if (params->type != MMA8X5X_DEVICE_ID_MMA8652 && + params->type != MMA8X5X_DEVICE_ID_MMA8653 && + params->type != MMA8X5X_DEVICE_ID_MMA8451 && + params->type != MMA8X5X_DEVICE_ID_MMA8452 && + params->type != MMA8X5X_DEVICE_ID_MMA8453) { + /* given type is not supported */ + return -1; + } + setDeviceName(params->type); + + if (params->rate != MMA8X5X_RATE_800HZ && + params->rate != MMA8X5X_RATE_400HZ && + params->rate != MMA8X5X_RATE_200HZ && + params->rate != MMA8X5X_RATE_100HZ && + params->rate != MMA8X5X_RATE_50HZ && + params->rate != MMA8X5X_RATE_1HZ25 && + params->rate != MMA8X5X_RATE_6HZ25 && + params->rate != MMA8X5X_RATE_1HZ56) { + /* given rate is not supported */ + return -1; + } + s_params->rate = params->rate; + + if (params->range != MMA8X5X_RANGE_2G && + params->range != MMA8X5X_RANGE_4G && + params->range != MMA8X5X_RANGE_8G) { + /* given range is not supported */ + return -1; + } + s_params->range = params->range; + + s_params->offsetX = params->offsetX; + s_params->offsetY = params->offsetY; + s_params->offsetZ = params->offsetZ; + } + + return 0; +} + +int +MMA8X5X::setUserOffset(int8_t x, int8_t y, int8_t z) +{ + mraa::Result ret = m_i2ControlCtx.writeReg(MMA8X5X_OFF_X, (uint8_t)x); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte_data() failed"); + return -1; + } + ret = m_i2ControlCtx.writeReg(MMA8X5X_OFF_Y, (uint8_t)y); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte_data() failed"); + return -1; + } + ret = m_i2ControlCtx.writeReg(MMA8X5X_OFF_Z, (uint8_t)z); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte_data() failed"); + return -1; + } + + return 0; +} + +int +MMA8X5X::setActive(void) +{ + uint8_t reg; + + reg = m_i2ControlCtx.readReg(MMA8X5X_CTRL_REG1); + reg |= MMA8X5X_CTRL_REG1_ACTIVE; + + mraa::Result ret = m_i2ControlCtx.writeReg(MMA8X5X_CTRL_REG1, reg); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte_data() failed"); + return -1; + } + return 0; +} + +int +MMA8X5X::setStandby(void) +{ + uint8_t reg; + + reg = m_i2ControlCtx.readReg(MMA8X5X_CTRL_REG1); + reg &= ~MMA8X5X_CTRL_REG1_ACTIVE; + + mraa::Result ret = m_i2ControlCtx.writeReg(MMA8X5X_CTRL_REG1, reg); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte_data() failed"); + return -1; + } + return 0; +} + +int +MMA8X5X::isReady(void) +{ + uint8_t reg; + + reg = m_i2ControlCtx.readReg(MMA8X5X_STATUS); + + if (reg & MMA8X5X_STATUS_ZYXDR) { + return MMA8X5X_DATA_READY; + } else { + return MMA8X5X_NODATA; + } +} + +int +MMA8X5X::sampleData(void) +{ + uint8_t buf[7]; + int re = 0; + + re = m_i2ControlCtx.readBytesReg(MMA8X5X_STATUS, buf, 7); + if (re != 7) { + /* did not read enough bytes */ + return -1; + } + + s_data->x = ((int16_t)(buf[1] << 8 | buf[2])) / (16 >> s_params->range); + s_data->y = ((int16_t)(buf[3] << 8 | buf[4])) / (16 >> s_params->range); + s_data->z = ((int16_t)(buf[5] << 8 | buf[6])) / (16 >> s_params->range); + + return 0; +} + +int16_t +MMA8X5X::getX(int bSampleData) +{ + if (bSampleData) { + if (sampleData() != 0) { + /* error in read values from reg */ + return -999; + } + } + + return s_data->x; +} + +int16_t +MMA8X5X::getY(int bSampleData) +{ + if (bSampleData) { + if (sampleData() != 0) { + /* error in read values from reg */ + return -999; + } + } + + return s_data->y; +} + +int16_t +MMA8X5X::getZ(int bSampleData) +{ + if (bSampleData) { + if (sampleData() != 0) { + /* error in read values from reg */ + return -999; + } + } + + return s_data->z; +} + +int +MMA8X5X::getData(mma8x5x_data_t* data, int bSampleData) +{ + if (bSampleData) { + if (sampleData() != 0) { + /* error in read values from reg */ + return -1; + } + } + + data->x = s_data->x; + data->y = s_data->y; + data->z = s_data->z; + + return 0; +} \ No newline at end of file diff --git a/src/mma8x5x/mma8x5x.hpp b/src/mma8x5x/mma8x5x.hpp new file mode 100644 index 00000000..05844f63 --- /dev/null +++ b/src/mma8x5x/mma8x5x.hpp @@ -0,0 +1,473 @@ +/* + * Author: Norbert Wesp + * Copyright (c) 2017 Phytec Messtechnik GmbH. + * + * based on: RIOT-driver mma8x5x by Johann Fischer + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include +#include +#include +#include + +/* Supported devices by this driver */ +#define MMA8X5X_DEVICE_ID_MMA8652 0x4a +#define MMA8X5X_DEVICE_ID_MMA8653 0x5a +#define MMA8X5X_DEVICE_ID_MMA8451 0x1a +#define MMA8X5X_DEVICE_ID_MMA8452 0x2a +#define MMA8X5X_DEVICE_ID_MMA8453 0x3a + +#define MMA8X5X_NAME_MMA8652 "MMA8652" +#define MMA8X5X_NAME_MMA8653 "MMA8653" +#define MMA8X5X_NAME_MMA8451 "MMA8451" +#define MMA8X5X_NAME_MMA8452 "MMA8452" +#define MMA8X5X_NAME_MMA8453 "MMA8453" + +/* MMA8x5x Fix settings of supported sensors */ +#define MMA8X5X_I2C_ADDRESS 0x1D +#define MMA8X5X_DEVICE_ID_REG 0x0D + +/* MMA8x5x Register Map */ +#define MMA8X5X_STATUS 0x00 /* Data or FIFO Status */ +#define MMA8X5X_OUT_X_MSB 0x01 /* [7:0] are 8 MSBs of X data */ +#define MMA8X5X_OUT_X_LSB 0x02 /* [7:4] are 4 LSBs of X data */ +#define MMA8X5X_OUT_Y_MSB 0x03 /* [7:0] are 8 MSBs of Y data */ +#define MMA8X5X_OUT_Y_LSB 0x04 /* [7:4] are 4 LSBs of Y data */ +#define MMA8X5X_OUT_Z_MSB 0x05 /* [7:0] are 8 MSBs of Z data */ +#define MMA8X5X_OUT_Z_LSB 0x06 /* [7:4] are 8 LSBs of Z data */ +#define MMA8X5X_F_SETUP 0x09 /* FIFO setup */ +#define MMA8X5X_TRIG_CFG 0x0A /* Map of FIFO data capture events */ +#define MMA8X5X_SYSMOD 0x0B /* Current System mode */ +#define MMA8X5X_INT_SOURCE 0x0C /* Interrupt status */ +#define MMA8X5X_XYZ_DATA_CFG 0x0E /* Dynamic Range Settings */ +#define MMA8X5X_HP_FILTER_CUTOFF 0x0F /* High-Pass Filter Selection */ +#define MMA8X5X_PL_STATUS 0x10 /* Landscape/Portrait + orientation status */ +#define MMA8X5X_PL_CFG 0x11 /* Landscape/Portrait configuration */ +#define MMA8X5X_PL_COUNT 0x12 /* Landscape/Portrait debounce counter */ +#define MMA8X5X_PL_BF_ZCOMP 0x13 /* Back/Front, Z-Lock Trip threshold */ +#define MMA8X5X_P_L_THS_REG 0x14 /* Portrait/Landscape + Threshold and Hysteresis */ +#define MMA8X5X_FF_MT_CFG 0x15 /* Freefall/Motion + functional block configuration */ +#define MMA8X5X_FF_MT_SRC 0x16 /* Freefall/Motion + event source register */ +#define MMA8X5X_FF_MT_THS 0x17 /* Freefall/Motion threshold register */ +#define MMA8X5X_FF_MT_COUNT 0x18 /* Freefall/Motion debounce counter */ +#define MMA8X5X_TRANSIENT_CFG 0x1D /* Transient + functional block configuration */ +#define MMA8X5X_TRANSIENT_SRC 0x1E /* Transient event status register */ +#define MMA8X5X_TRANSIENT_THS 0x1F /* Transient event threshold */ +#define MMA8X5X_TRANSIENT_COUNT 0x20 /* Transient debounce counter */ +#define MMA8X5X_PULSE_CFG 0x21 /* Pulse enable configuration */ +#define MMA8X5X_PULSE_SRC 0x22 /* Pulse detection source */ +#define MMA8X5X_PULSE_THSX 0x23 /* X pulse threshold */ +#define MMA8X5X_PULSE_THSY 0x24 /* Y pulse threshold */ +#define MMA8X5X_PULSE_THSZ 0x25 /* Z pulse threshold */ +#define MMA8X5X_PULSE_TMLT 0x26 /* Time limit for pulse */ +#define MMA8X5X_PULSE_LTCY 0x27 /* Latency time for 2nd pulse */ +#define MMA8X5X_PULSE_WIND 0x28 /* Window time for 2nd pulse */ +#define MMA8X5X_ASLP_COUNT 0x29 /* Counter setting for Auto-SLEEP */ +#define MMA8X5X_CTRL_REG1 0x2A /* Data rates and modes setting */ +#define MMA8X5X_CTRL_REG2 0x2B /* Sleep Enable, OS modes, RST, ST */ +#define MMA8X5X_CTRL_REG3 0x2C /* Wake from Sleep, IPOL, PP_OD */ +#define MMA8X5X_CTRL_REG4 0x2D /* Interrupt enable register */ +#define MMA8X5X_CTRL_REG5 0x2E /* Interrupt pin (INT1/INT2) map */ +#define MMA8X5X_OFF_X 0x2F /* X-axis offset adjust */ +#define MMA8X5X_OFF_Y 0x30 /* Y-axis offset adjust */ +#define MMA8X5X_OFF_Z 0x31 /* Z-axis offset adjust */ + +/* MMA8x5x Available sampling rates */ +#define MMA8X5X_RATE_800HZ (0 << 3) /* 800 Hz Ouput Data Rate in WAKE mode */ +#define MMA8X5X_RATE_400HZ (1 << 3) /* 400 Hz Ouput Data Rate in WAKE mode */ +#define MMA8X5X_RATE_200HZ (2 << 3) /* 200 Hz Ouput Data Rate in WAKE mode */ +#define MMA8X5X_RATE_100HZ (3 << 3) /* 100 Hz Ouput Data Rate in WAKE mode */ +#define MMA8X5X_RATE_50HZ (4 << 3) /* 50 Hz Ouput Data Rate in WAKE mode */ +#define MMA8X5X_RATE_1HZ25 (5 << 3) /* 12.5 Hz Ouput Data Rate in WAKE mode */ +#define MMA8X5X_RATE_6HZ25 (6 << 3) /* 6.25 Hz Ouput Data Rate in WAKE mode */ +#define MMA8X5X_RATE_1HZ56 (7 << 3) /* 1.56 Hz Ouput Data Rate in WAKE mode */ + +#define MMA8X5X_RATE_DEFAULT MMA8X5X_RATE_200HZ + +/* MMA8x5x Available range options */ +#define MMA8X5X_RANGE_2G 0 +#define MMA8X5X_RANGE_4G 1 +#define MMA8X5X_RANGE_8G 2 + +#define MMA8X5X_RANGE_DEFAULT MMA8X5X_RANGE_2G + +/* Named return values */ +#define MMA8X5X_OK 0 /* everything was fine */ +#define MMA8X5X_DATA_READY 1 /* new data ready to be read */ +#define MMA8X5X_NOI2C -1 /* I2C communication failed */ +#define MMA8X5X_NODEV -2 /* no MMA8X5X device found on the bus */ +#define MMA8X5X_NODATA -3 /* no data available */ + +/* MMA8x5x Register Bitfields */ +#define MMA8X5X_STATUS_XDR (1 << 0) +#define MMA8X5X_STATUS_YDR (1 << 1) +#define MMA8X5X_STATUS_ZDR (1 << 2) +#define MMA8X5X_STATUS_ZYXDR (1 << 3) +#define MMA8X5X_STATUS_XOW (1 << 4) +#define MMA8X5X_STATUS_YOW (1 << 5) +#define MMA8X5X_STATUS_ZOW (1 << 6) +#define MMA8X5X_STATUS_ZYXOW (1 << 7) + +#define MMA8X5X_F_STATUS_F_CNT_MASK 0x3F +#define MMA8X5X_F_STATUS_F_WMRK_FLAG (1 << 6) +#define MMA8X5X_F_STATUS_F_OVF (1 << 7) + +#define MMA8X5X_F_SETUP_MODE_MASK 0xC0 +#define MMA8X5X_F_SETUP_MODE_DISABLED 0 +#define MMA8X5X_F_SETUP_MODE_CIRCULAR 1 +#define MMA8X5X_F_SETUP_MODE_STOP 2 +#define MMA8X5X_F_SETUP_MODE_TRIGGER 3 +#define MMA8X5X_F_SETUP_F_WMRK_MASK 0x3F + +#define MMA8X5X_TRIG_CFG_FF_MT (1 << 2) +#define MMA8X5X_TRIG_CFG_PULSE (1 << 3) +#define MMA8X5X_TRIG_CFG_LNDPRT (1 << 4) +#define MMA8X5X_TRIG_CFG_TRANS (1 << 5) + +#define MMA8X5X_SYSMOD_MASK 0x3 +#define MMA8X5X_SYSMOD_STANDBY 0 +#define MMA8X5X_SYSMOD_WAKE 1 +#define MMA8X5X_SYSMOD_SLEEP 2 +#define MMA8X5X_SYSMOD_FGT_MASK 0x7C +#define MMA8X5X_SYSMOD_FGERR (1 << 7) + +#define MMA8X5X_INT_SOURCE_DRDY (1 << 0) +#define MMA8X5X_INT_SOURCE_FF_MT (1 << 2) +#define MMA8X5X_INT_SOURCE_PULSE (1 << 3) +#define MMA8X5X_INT_SOURCE_LNDPRT (1 << 4) +#define MMA8X5X_INT_SOURCE_TRANS (1 << 5) +#define MMA8X5X_INT_SOURCE_FIFO (1 << 6) +#define MMA8X5X_INT_SOURCE_ASLP (1 << 7) + +#define MMA8X5X_XYZ_DATA_CFG_FS_MASK 0x3 +#define MMA8X5X_XYZ_DATA_CFG_HPF_OUT (1 << 4) + +#define MMA8X5X_HP_FILTER_SEL_MASK 0x03 +#define MMA8X5X_HP_FILTER_LPF_EN (1 << 4) +#define MMA8X5X_HP_FILTER_HPF_BYP (1 << 5) + +#define MMA8X5X_PL_STATUS_BAFRO (1 << 0) +#define MMA8X5X_PL_STATUS_LAPO_MASK 0x6 +#define MMA8X5X_PL_STATUS_LAPO_P_UP 0 +#define MMA8X5X_PL_STATUS_LAPO_P_DOWN 1 +#define MMA8X5X_PL_STATUS_LAPO_L_RIGHT 2 +#define MMA8X5X_PL_STATUS_LAPO_L_LEFT 3 +#define MMA8X5X_PL_STATUS_LO (1 << 6) +#define MMA8X5X_PL_STATUS_NEWLP (1 << 7) + +#define MMA8X5X_PL_CFG_PL_EN (1 << 6) +#define MMA8X5X_PL_CFG_DBCNTM (1 << 7) + +#define MMA8X5X_PL_BF_ZCOMP_ZLOCK_MASK 0x07 +#define MMA8X5X_PL_BF_ZCOMP_BKFR_MASK 0xC0 + +#define MMA8X5X_P_L_HYS_MASK 0x07 +#define MMA8X5X_P_L_THS_MASK 0xF8 + +#define MMA8X5X_FF_MT_CFG_XEFE (1 << 3) +#define MMA8X5X_FF_MT_CFG_YEFE (1 << 4) +#define MMA8X5X_FF_MT_CFG_ZEFE (1 << 5) +#define MMA8X5X_FF_MT_CFG_OAE (1 << 6) +#define MMA8X5X_FF_MT_CFG_ELE (1 << 7) + +#define MMA8X5X_FF_MT_SRC_XHP (1 << 0) +#define MMA8X5X_FF_MT_SRC_XHE (1 << 1) +#define MMA8X5X_FF_MT_SRC_YHP (1 << 2) +#define MMA8X5X_FF_MT_SRC_YHE (1 << 3) +#define MMA8X5X_FF_MT_SRC_ZHP (1 << 4) +#define MMA8X5X_FF_MT_SRC_ZHE (1 << 5) +#define MMA8X5X_FF_MT_SRC_EA (1 << 7) + +#define MMA8X5X_FF_MT_THS_MASK 0x7F +#define MMA8X5X_FF_MT_THS_DBCNTM (1 << 7) + +#define MMA8X5X_TRANSIENT_CFG_HPF_BYP (1 << 0) +#define MMA8X5X_TRANSIENT_CFG_XTEFE (1 << 1) +#define MMA8X5X_TRANSIENT_CFG_YTEFE (1 << 2) +#define MMA8X5X_TRANSIENT_CFG_ZTEFE (1 << 3) +#define MMA8X5X_TRANSIENT_CFG_ELE (1 << 4) + +#define MMA8X5X_TRANSIENT_SRC_XTPOL (1 << 0) +#define MMA8X5X_TRANSIENT_SRC_XTEVENT (1 << 1) +#define MMA8X5X_TRANSIENT_SRC_YTPOL (1 << 2) +#define MMA8X5X_TRANSIENT_SRC_YTEVENT (1 << 3) +#define MMA8X5X_TRANSIENT_SRC_ZTPOL (1 << 4) +#define MMA8X5X_TRANSIENT_SRC_ZTEVENT (1 << 5) +#define MMA8X5X_TRANSIENT_SRC_EA (1 << 6) + +#define MMA8X5X_TRANSIENT_THS_MASK 0x7F +#define MMA8X5X_TRANSIENT_THS_DBCNTM (1<< 7) + +#define MMA8X5X_PULSE_CFG_XSPEFE (1 << 0) +#define MMA8X5X_PULSE_CFG_XDPEFE (1 << 1) +#define MMA8X5X_PULSE_CFG_YSPEFE (1 << 2) +#define MMA8X5X_PULSE_CFG_YDPEFE (1 << 3) +#define MMA8X5X_PULSE_CFG_ZSPEFE (1 << 4) +#define MMA8X5X_PULSE_CFG_ZDPEFE (1 << 5) +#define MMA8X5X_PULSE_CFG_ELE (1 << 6) +#define MMA8X5X_PULSE_CFG_DPA (1 << 7) + +#define MMA8X5X_PULSE_SRC_POLX (1 << 0) +#define MMA8X5X_PULSE_SRC_POLY (1 << 1) +#define MMA8X5X_PULSE_SRC_POLZ (1 << 2) +#define MMA8X5X_PULSE_SRC_DPE (1 << 3) +#define MMA8X5X_PULSE_SRC_AXX (1 << 4) +#define MMA8X5X_PULSE_SRC_AXY (1 << 5) +#define MMA8X5X_PULSE_SRC_AXZ (1 << 6) +#define MMA8X5X_PULSE_SRC_EA (1 << 7) + +#define MMA8X5X_PULSE_THSX_MASK 0x7F +#define MMA8X5X_PULSE_THSY_MASK 0x7F +#define MMA8X5X_PULSE_THSZ_MASK 0x7F + +#define MMA8X5X_CTRL_REG1_ACTIVE (1 << 0) +#define MMA8X5X_CTRL_REG1_F_READ (1 << 1) +#define MMA8X5X_CTRL_REG1_DR_MASK 0x38 +#define MMA8X5X_CTRL_REG1_DR_SHIFT 3 +#define MMA8X5X_CTRL_REG1_DR(x) (((uint8_t)(((uint8_t)(x))<<\ + MMA8X5X_CTRL_REG1_DR_SHIFT))\ + &MMA8X5X_CTRL_REG1_DR_MASK) +#define MMA8X5X_CTRL_REG1_ASR_MASK 0xC0 +#define MMA8X5X_CTRL_REG1_ASR_50HZ 0 +#define MMA8X5X_CTRL_REG1_ASR_12HZ5 1 +#define MMA8X5X_CTRL_REG1_ASR_6HZ25 2 +#define MMA8X5X_CTRL_REG1_ASR_1HZ56 3 + +#define MMA8X5X_CTRL_REG2_MODS_MASK 0x3 +#define MMA8X5X_CTRL_REG2_MODS_NORMAL 0 +#define MMA8X5X_CTRL_REG2_MODS_LNLP 1 +#define MMA8X5X_CTRL_REG2_MODS_HR 2 +#define MMA8X5X_CTRL_REG2_MODS_LP 3 +#define MMA8X5X_CTRL_REG2_SLPE (1 << 2) +#define MMA8X5X_CTRL_REG2_SMODS_MASK 0x18 +#define MMA8X5X_CTRL_REG2_SMODS_NORMAL 0 +#define MMA8X5X_CTRL_REG2_SMODS_LNLP 1 +#define MMA8X5X_CTRL_REG2_SMODS_HR 2 +#define MMA8X5X_CTRL_REG2_SMODS_LP 3 +#define MMA8X5X_CTRL_REG2_RST (1 << 6) +#define MMA8X5X_CTRL_REG2_ST (1 << 7) + +#define MMA8X5X_CTRL_REG3_PP_OD (1 << 0) +#define MMA8X5X_CTRL_REG3_IPOL (1 << 1) +#define MMA8X5X_CTRL_REG3_WAKE_FF_MT (1 << 3) +#define MMA8X5X_CTRL_REG3_WAKE_PULSE (1 << 4) +#define MMA8X5X_CTRL_REG3_WAKE_LNDPRT (1 << 5) +#define MMA8X5X_CTRL_REG3_WAKE_TRANS (1 << 6) +#define MMA8X5X_CTRL_REG3_FIFO_GATE (1 << 7) + +#define MMA8X5X_CTRL_REG4_INT_EN_DRDY (1 << 0) +#define MMA8X5X_CTRL_REG4_INT_EN_FF_MT (1 << 2) +#define MMA8X5X_CTRL_REG4_INT_EN_PULSE (1 << 3) +#define MMA8X5X_CTRL_REG4_INT_EN_LNDPRT (1 << 4) +#define MMA8X5X_CTRL_REG4_INT_EN_TRANS (1 << 5) +#define MMA8X5X_CTRL_REG4_INT_EN_FIFO (1 << 6) +#define MMA8X5X_CTRL_REG4_INT_EN_ASLP (1 << 7) + +#define MMA8X5X_CTRL_REG5_INT_CFG_DRDY (1 << 0) +#define MMA8X5X_CTRL_REG5_INT_CFG_FF_MT (1 << 2) +#define MMA8X5X_CTRL_REG5_INT_CFG_PULSE (1 << 3) +#define MMA8X5X_CTRL_REG5_INT_CFG_LNDPRT (1 << 4) +#define MMA8X5X_CTRL_REG5_INT_CFG_TRANS (1 << 5) +#define MMA8X5X_CTRL_REG5_INT_CFG_FIFO (1 << 6) +#define MMA8X5X_CTRL_REG5_INT_CFG_ASLP (1 << 7) + +namespace upm { + +typedef struct { + uint8_t type; + uint8_t rate; + uint8_t range; + uint8_t offsetX; + uint8_t offsetY; + uint8_t offsetZ; +} mma8x5x_params_t; + +typedef struct { + int16_t x; + int16_t y; + int16_t z; +} mma8x5x_data_t; + +/** + * @brief MMA8X5X Three-Axis Accelerometer + * @defgroup mma8x5x libupm-mma8x5x + * @ingroup freescale i2c accelerometer compass + */ + +/** + * @library mma8x5x + * @sensor mma8x5x + * @comname MMA8X5X Three-Axis Accelerometer + * @altid mma8451 mma8452 mma8453 mma8652 mma8653 + * @type accelerometer compass + * @man freescale + * @web http://www.nxp.com/products/sensors/accelerometers:DRSNSAXLRTN + * @con i2c + * + * @brief API for the MMA8X5X Three-Axis Accelerometer + * + * Description in web-link above: + * The NXP MMA8X5X are low-power, three-axis capacitive micromachined + * accelerometer with 10/12/14 bits of resolution. These accelerometer + * are packed with embedded functions with flexible user-programmable + * options configurable to two interrupt pins. The MMA8X5X have user-selectable + * full scales of ±2g/±4g/±8g. + * + * @snippet mma8x5x.cxx Interesting + */ +class MMA8X5X { + public: + /** + * + * Instantiates an MMA8X5X object + * + * @param bus Number of the used bus + * @params params Params of device + * @param devAddr Address of the used I2C device + */ + MMA8X5X (int bus, mma8x5x_params_t* params=NULL, + int devAddr=MMA8X5X_I2C_ADDRESS); + + /** + * Set device name and type matching given type or + * read out devive_id to set name and type of device + * + * @param type Type of device if set or + * 0 if needed to find out by it + * @return 0 on success + * -1 on error + */ + int setDeviceName(uint8_t type); + + /** + * Set device params to given data or + * set default params and read out devive_id to set type of device + * + * @param params Params of device if set by user + * NULL if it is not set by user + * @return 0 on success + * -1 on error + */ + int setDeviceParams(mma8x5x_params_t* params); + + /** + * Set user offset correction + * Offset correction register will be erased after accelerometer reset + * + * @param x Offset correction value for x-axis + * @param y Offset correction value for y-axis + * @param z Offset correction value for z-axis + * + * @return 0 on success + * -1 on error + */ + int setUserOffset(int8_t x, int8_t y, int8_t z); + + /** + * Set active mode, this enables periodic measurements + * + * @return 0 on success + * -1 on error + */ + int setActive(void); + + /** + * Set standby mode, this disables periodic measurements + * + * @return 0 on success + * -1 on error + */ + int setStandby(void); + + /** + * Check for new set of measurement data. + * + * @return MMA8X5X_DATA_READY if new sample is ready + * MMA8X5X_NODATA if nothing is available + */ + int isReady(void); + + /** + * Read & calculate accelerometer data in mg & saves them to variables + * + * @return 0 on success + * -1 on error + */ + int sampleData(void); + + /** + * Get x-axis acceleration + * + * @param bSampleData Flag to read sensor + * @return The x-axis acceleration on success + * -999 on error + */ + int16_t getX(int bSampleData = 0); + + /** + * Get y-axis acceleration + * + * @param bSampleData Flag to read sensor + * @return The y-axis acceleration on success + * -999 on error + */ + int16_t getY(int bSampleData = 0); + + /** + * Get z-axis acceleration + * + * @param bSampleData Flag to read sensor + * @return The z-axis acceleration on success + * -999 on error + */ + int16_t getZ(int bSampleData = 0); + + /** + * Get sensor values + * + * @param data Sensor values + * @param bSampleData Flag to read sensor + * @return 0 on success + * -1 on error + */ + int getData(mma8x5x_data_t* data, int bSampleData = 0); + + private: + + std::string m_name; + + int m_controlAddr; + int m_bus; + mraa::I2c m_i2ControlCtx; + + mma8x5x_params_t s_params[1]; + mma8x5x_data_t s_data[1]; +}; + +} diff --git a/src/mma8x5x/pyupm_mma8x5x.i b/src/mma8x5x/pyupm_mma8x5x.i new file mode 100644 index 00000000..bfeaa19c --- /dev/null +++ b/src/mma8x5x/pyupm_mma8x5x.i @@ -0,0 +1,15 @@ +// Include doxygen-generated documentation +%include "pyupm_doxy2swig.i" +%module pyupm_mma8x5x +%include "../upm.i" + +%feature("autodoc", "3"); + +#ifdef DOXYGEN +%include "mma8x5x_doc.i" +#endif + +%include "mma8x5x.hpp" +%{ + #include "mma8x5x.hpp" +%}