diff --git a/examples/c++/mma7660.cxx b/examples/c++/mma7660.cxx index 19e3e02d..e4694d2d 100644 --- a/examples/c++/mma7660.cxx +++ b/examples/c++/mma7660.cxx @@ -44,36 +44,29 @@ int main(int argc, char **argv) //! [Interesting] // Instantiate an MMA7660 on I2C bus 0 - upm::MMA7660 *accel = new upm::MMA7660(MMA7660_I2C_BUS, + upm::MMA7660 *accel = new upm::MMA7660(MMA7660_DEFAULT_I2C_BUS, MMA7660_DEFAULT_I2C_ADDR); // place device in standby mode so we can write registers accel->setModeStandby(); // enable 64 samples per second - accel->setSampleRate(upm::MMA7660::AUTOSLEEP_64); - + accel->setSampleRate(MMA7660_AUTOSLEEP_64); + // place device into active mode accel->setModeActive(); while (shouldRun) { - int x, y, z; - - accel->getRawValues(&x, &y, &z); - cout << "Raw values: x = " << x - << " y = " << y - << " z = " << z - << endl; - float ax, ay, az; - + accel->getAcceleration(&ax, &ay, &az); - cout << "Acceleration: x = " << ax + cout << "Acceleration: x = " << ax << "g y = " << ay << "g z = " << az << "g" << endl; - + + cout << endl; usleep(500000); } diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt index 1de0ca03..0a660ff7 100644 --- a/examples/c/CMakeLists.txt +++ b/examples/c/CMakeLists.txt @@ -130,6 +130,7 @@ add_example (rpr220) add_example (md) add_example (linefinder) add_example (uln200xa) +add_example (mma7660) # Custom examples add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps) diff --git a/examples/c/mma7660.c b/examples/c/mma7660.c new file mode 100644 index 00000000..c74484d9 --- /dev/null +++ b/examples/c/mma7660.c @@ -0,0 +1,83 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * 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 "upm_utilities.h" +#include "mma7660.h" + +int shouldRun = true; + +void sig_handler(int signo) +{ + if (signo == SIGINT) + shouldRun = false; +} + +int main(int argc, char **argv) +{ + signal(SIGINT, sig_handler); + +//! [Interesting] + // Instantiate an MMA7660 on I2C bus 0 + + mma7660_context accel = mma7660_init(MMA7660_DEFAULT_I2C_BUS, + MMA7660_DEFAULT_I2C_ADDR); + + if (!accel) + { + printf("mma7660_init() failed\n"); + return 1; + } + + // place device in standby mode so we can write registers + mma7660_set_mode_standby(accel); + + // enable 64 samples per second + mma7660_set_sample_rate(accel, MMA7660_AUTOSLEEP_64); + + // place device into active mode + mma7660_set_mode_active(accel); + + while (shouldRun) + { + float ax, ay, az; + + mma7660_get_acceleration(accel, &ax, &ay, &az); + printf("Acceleration: x = %f y = %f z = %f\n\n", + ax, ay, az); + + upm_delay_ms(500); + } + + printf("Exiting...\n"); + + mma7660_close(accel); + +//! [Interesting] + return 0; +} diff --git a/examples/java/MMA7660Sample.java b/examples/java/MMA7660Sample.java index 77736e26..23e31031 100644 --- a/examples/java/MMA7660Sample.java +++ b/examples/java/MMA7660Sample.java @@ -1,5 +1,6 @@ /* * Author: Stefan Andritoiu + * Jon Trulson * Copyright (c) 2015 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining @@ -22,34 +23,39 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -//NOT TESTED!!! -public class MMA7660Sample { +import upm_mma7660.MMA7660; - public static void main(String[] args) throws InterruptedException { - // ! [Interesting] - // Instantiate an MMA7660 on I2C bus 0 - upm_mma7660.MMA7660 accel = new upm_mma7660.MMA7660(0); +public class MMA7660Sample +{ + public static void main(String[] args) throws InterruptedException + { + // ! [Interesting] + // Instantiate an MMA7660 on I2C bus 0 + MMA7660 accel = new MMA7660(0); - // place device in standby mode so we can write registers - accel.setModeStandby(); + // place device in standby mode so we can write registers + accel.setModeStandby(); - // enable 64 samples per second - accel.setSampleRate(upm_mma7660.MMA7660.MMA7660_AUTOSLEEP_T.AUTOSLEEP_64); + // enable 64 samples per second + accel.setSampleRate(upm_mma7660.MMA7660_AUTOSLEEP_T.MMA7660_AUTOSLEEP_64); - // place device into active mode - accel.setModeActive(); + // place device into active mode + accel.setModeActive(); - while (true) { - int[] rawValues = accel.getRawValues(); - System.out.println("Raw Values: x = " + rawValues[0] + " y = " + rawValues[1] + " x = " - + rawValues[2]); + while (true) + { + float acceleration[] = accel.getAcceleration(); + System.out.println("Acceleration: x = " + + acceleration[0] + + " y = " + + acceleration[1] + + " x = " + + acceleration[2]); - float[] acceleration = accel.getAcceleration(); - System.out.println("Raw Values: x = " + acceleration[0] + " y = " + acceleration[1] - + " x = " + acceleration[2]); + System.out.println(); - Thread.sleep(1000); - } - // ! [Interesting] + Thread.sleep(500); + } + // ! [Interesting] } -} \ No newline at end of file +} diff --git a/examples/javascript/mma7660.js b/examples/javascript/mma7660.js index a688ec88..5310b92d 100644 --- a/examples/javascript/mma7660.js +++ b/examples/javascript/mma7660.js @@ -26,23 +26,18 @@ var digitalAccelerometer = require('jsupm_mma7660'); // Instantiate an MMA7660 on I2C bus 0 var myDigitalAccelerometer = new digitalAccelerometer.MMA7660( - digitalAccelerometer.MMA7660_I2C_BUS, + digitalAccelerometer.MMA7660_DEFAULT_I2C_BUS, digitalAccelerometer.MMA7660_DEFAULT_I2C_ADDR); // place device in standby mode so we can write registers myDigitalAccelerometer.setModeStandby(); // enable 64 samples per second -myDigitalAccelerometer.setSampleRate(digitalAccelerometer.MMA7660.AUTOSLEEP_64); +myDigitalAccelerometer.setSampleRate(digitalAccelerometer.MMA7660_AUTOSLEEP_64); // place device into active mode myDigitalAccelerometer.setModeActive(); -var x, y, z; -x = digitalAccelerometer.new_intp(); -y = digitalAccelerometer.new_intp(); -z = digitalAccelerometer.new_intp(); - var ax, ay, az; ax = digitalAccelerometer.new_floatp(); ay = digitalAccelerometer.new_floatp(); @@ -52,18 +47,13 @@ var outputStr; var myInterval = setInterval(function() { - myDigitalAccelerometer.getRawValues(x, y, z); - outputStr = "Raw values: x = " + digitalAccelerometer.intp_value(x) + - " y = " + digitalAccelerometer.intp_value(y) + - " z = " + digitalAccelerometer.intp_value(z); - console.log(outputStr); - myDigitalAccelerometer.getAcceleration(ax, ay, az); outputStr = "Acceleration: x = " + roundNum(digitalAccelerometer.floatp_value(ax), 6) + "g y = " + roundNum(digitalAccelerometer.floatp_value(ay), 6) + "g z = " + roundNum(digitalAccelerometer.floatp_value(az), 6) + "g"; console.log(outputStr); + console.log(); }, 500); // round off output to match C example, which has 6 decimal places diff --git a/examples/python/mma7660.py b/examples/python/mma7660.py index bb4efaeb..cf326510 100755 --- a/examples/python/mma7660.py +++ b/examples/python/mma7660.py @@ -28,7 +28,7 @@ from upm import pyupm_mma7660 as upmMMA7660 def main(): # Instantiate an MMA7660 on I2C bus 0 myDigitalAccelerometer = upmMMA7660.MMA7660( - upmMMA7660.MMA7660_I2C_BUS, + upmMMA7660.MMA7660_DEFAULT_I2C_BUS, upmMMA7660.MMA7660_DEFAULT_I2C_ADDR); ## Exit handlers ## @@ -49,35 +49,24 @@ def main(): myDigitalAccelerometer.setModeStandby() # enable 64 samples per second - myDigitalAccelerometer.setSampleRate(upmMMA7660.MMA7660.AUTOSLEEP_64) + myDigitalAccelerometer.setSampleRate(upmMMA7660.MMA7660_AUTOSLEEP_64) # place device into active mode myDigitalAccelerometer.setModeActive() - x = upmMMA7660.new_intp() - y = upmMMA7660.new_intp() - z = upmMMA7660.new_intp() - ax = upmMMA7660.new_floatp() ay = upmMMA7660.new_floatp() az = upmMMA7660.new_floatp() while (1): - myDigitalAccelerometer.getRawValues(x, y, z) - outputStr = ("Raw values: x = {0}" - " y = {1}" - " z = {2}").format(upmMMA7660.intp_value(x), - upmMMA7660.intp_value(y), - upmMMA7660.intp_value(z)) - print(outputStr) - myDigitalAccelerometer.getAcceleration(ax, ay, az) outputStr = ("Acceleration: x = {0}" - "g y = {1}" - "g z = {2}g").format(upmMMA7660.floatp_value(ax), + "g y = {1}" + "g z = {2}g").format(upmMMA7660.floatp_value(ax), upmMMA7660.floatp_value(ay), upmMMA7660.floatp_value(az)) print(outputStr) + print() time.sleep(.5) if __name__ == '__main__': diff --git a/src/mma7660/CMakeLists.txt b/src/mma7660/CMakeLists.txt index b29af70b..0285d80d 100644 --- a/src/mma7660/CMakeLists.txt +++ b/src/mma7660/CMakeLists.txt @@ -1,5 +1,9 @@ -set (libname "mma7660") -set (libdescription "I2C 3-axis digital accelermeter (1.5g)") -set (module_src ${libname}.cxx) -set (module_hpp ${libname}.hpp) -upm_module_init() +upm_mixed_module_init (NAME mma7660 + DESCRIPTION "I2C 3-axis Digital Accelerometer (1.5g)" + C_HDR mma7660.h mma7660_regs.h + C_SRC mma7660.c + CPP_HDR mma7660.hpp + CPP_SRC mma7660.cxx + FTI_SRC mma7660_fti.c + CPP_WRAPS_C + REQUIRES mraa) diff --git a/src/mma7660/javaupm_mma7660.i b/src/mma7660/javaupm_mma7660.i index abe2aced..4c43256d 100644 --- a/src/mma7660/javaupm_mma7660.i +++ b/src/mma7660/javaupm_mma7660.i @@ -2,14 +2,12 @@ %include "../upm.i" %include "cpointer.i" %include "typemaps.i" +%include "arrays_java.i"; +%include "../java_buffer.i" %apply int *OUTPUT { int *x, int *y, int *z }; %apply float *OUTPUT { float *ax, float *ay, float *az }; -%{ - #include "mma7660.hpp" -%} - %typemap(jni) float* "jfloatArray" %typemap(jstype) float* "float[]" %typemap(jtype) float* "float[]" @@ -21,7 +19,6 @@ %typemap(out) float *getAcceleration { $result = JCALL1(NewFloatArray, jenv, 3); JCALL4(SetFloatArrayRegion, jenv, $result, 0, 3, $1); - delete [] $1; } @@ -36,13 +33,16 @@ %typemap(out) int *getRawValues { $result = JCALL1(NewIntArray, jenv, 3); JCALL4(SetIntArrayRegion, jenv, $result, 0, 3, (const signed int*)$1); - delete [] $1; } %ignore getRawValues(int *, int *, int *); %ignore getAcceleration(float *, float *, float *); +%include "mma7660_regs.h" %include "mma7660.hpp" +%{ + #include "mma7660.hpp" +%} %pragma(java) jniclasscode=%{ static { diff --git a/src/mma7660/jsupm_mma7660.i b/src/mma7660/jsupm_mma7660.i index 64a3cfa7..33f1afe5 100644 --- a/src/mma7660/jsupm_mma7660.i +++ b/src/mma7660/jsupm_mma7660.i @@ -6,8 +6,9 @@ %pointer_functions(int, intp); %pointer_functions(float, floatp); +%include "mma7660_regs.h" +%include "mma7660.hpp" %{ #include "mma7660.hpp" %} -%include "mma7660.hpp" diff --git a/src/mma7660/mma7660.c b/src/mma7660/mma7660.c new file mode 100644 index 00000000..7ffe47a2 --- /dev/null +++ b/src/mma7660/mma7660.c @@ -0,0 +1,367 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 Intel Corporation. + * + * 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 "mma7660.h" + +mma7660_context mma7660_init(int bus, uint8_t address) +{ + mma7660_context dev = + (mma7660_context)malloc(sizeof(struct _mma7660_context)); + + if (!dev) + return NULL; + + memset((void *)dev, 0, sizeof(struct _mma7660_context)); + + dev->i2c = NULL; + dev->gpio = NULL; + dev->isrInstalled = false; + + // make sure MRAA is initialized + int mraa_rv; + if ((mraa_rv = mraa_init()) != MRAA_SUCCESS) + { + printf("%s: mraa_init() failed (%d).\n", __FUNCTION__, mraa_rv); + mma7660_close(dev); + return NULL; + } + + // setup our i2c + if ( !(dev->i2c = mraa_i2c_init(bus)) ) + { + printf("%s: mraa_i2c_init() failed\n", __FUNCTION__); + mma7660_close(dev); + return NULL; + } + + if (mraa_i2c_address(dev->i2c, address)) + { + printf("%s: mraa_i2c_address() failed\n", __FUNCTION__); + mma7660_close(dev); + return NULL; + } + + return dev; +} + +void mma7660_close(mma7660_context dev) +{ + assert(dev != NULL); + + mma7660_uninstall_isr(dev); + + if (dev->i2c) + { + mma7660_set_mode_standby(dev); + mraa_i2c_stop(dev->i2c); + } + + free(dev); +} + +upm_result_t mma7660_write_byte(const mma7660_context dev, + uint8_t reg, uint8_t byte) +{ + assert(dev != NULL); + + if (mraa_i2c_write_byte_data(dev->i2c, byte, reg)) + { + printf("%s: mraa_i2c_write_byte_data() failed.\n", __FUNCTION__); + return UPM_ERROR_OPERATION_FAILED; + } + + return UPM_SUCCESS; +} + +upm_result_t mma7660_read_byte(const mma7660_context dev, uint8_t reg, + uint8_t *byte) +{ + assert(dev != NULL); + + int x = mraa_i2c_read_byte_data(dev->i2c, reg); + + if (x < 0) + { + printf("%s: mraa_i2c_read_byte_data() failed.\n", __FUNCTION__); + if (byte) + *byte = 0; + + return UPM_ERROR_OPERATION_FAILED; + } + + if (byte) + *byte = (uint8_t)(x & 0xff); + + return UPM_SUCCESS; +} + +upm_result_t mma7660_get_raw_values(const mma7660_context dev, + int *x, int *y, int *z) +{ + assert(dev != NULL); + + int rv; + if (x) + { + if ( (rv = mma7660_get_verified_axis(dev, MMA7660_REG_XOUT, x)) ) + return rv; + } + if (y) + { + if ( (rv = mma7660_get_verified_axis(dev, MMA7660_REG_YOUT, y)) ) + return rv; + } + if (z) + { + if ( (rv = mma7660_get_verified_axis(dev, MMA7660_REG_ZOUT, z)) ) + return rv; + } + + return UPM_SUCCESS; +} + +upm_result_t mma7660_set_mode_active(const mma7660_context dev) +{ + assert(dev != NULL); + + uint8_t modeReg; + if (mma7660_read_byte(dev, MMA7660_REG_MODE, &modeReg)) + return UPM_ERROR_OPERATION_FAILED; + + // The D2 (TON bit) should be cleared, and the MODE bit set + + modeReg &= ~MMA7660_MODE_TON; + modeReg |= MMA7660_MODE_MODE; + + return mma7660_write_byte(dev, MMA7660_REG_MODE, modeReg); +} + +upm_result_t mma7660_set_mode_standby(const mma7660_context dev) +{ + assert(dev != NULL); + + uint8_t modeReg; + if (mma7660_read_byte(dev, MMA7660_REG_MODE, &modeReg)) + return UPM_ERROR_OPERATION_FAILED; + + // the D0 (mode bit) and D2 (TON bit) should be cleared. + + modeReg &= ~MMA7660_MODE_TON; + modeReg &= ~MMA7660_MODE_MODE; + + return mma7660_write_byte(dev, MMA7660_REG_MODE, modeReg); +} + +// read an axis value, verifying it's validity +upm_result_t mma7660_get_verified_axis(const mma7660_context dev, + MMA7660_REG_T axis, int *val) +{ + assert(dev != NULL); + + *val = 0; + // We only want one of the 3 axes + + if (axis > 2) + { + printf("%s: axis must be 0, 1, or 2.\n", __FUNCTION__); + return UPM_ERROR_OUT_OF_RANGE; + } + + // we need to check the alert bit and sign bits if the alert bit is + // set, this means that the register was being updated when the + // register was read, so re-read until it's clear. + + uint8_t value = 0; + do { + if (mma7660_read_byte(dev, axis, &value)) + return UPM_ERROR_OPERATION_FAILED; + + // check alert bit + } while (value & 0x40); + + // shift the sign bit over, and compensate + *val = ((int8_t)(value << 2) / 4); + + return UPM_SUCCESS; +} + +// read the tilt register, verifying it's validity +upm_result_t mma7660_get_verified_tilt(const mma7660_context dev, + uint8_t *val) +{ + assert(dev != NULL); + + // we need to check the alert bit and sign bits if the alert bit is + // set, this means that the register was being updated when the + // register was read, so re-read until it's clear. + + do { + if (mma7660_read_byte(dev, MMA7660_REG_TILT, val)) + return UPM_ERROR_OPERATION_FAILED; + + // check alert bit + } while (*val & 0x40); + + return UPM_SUCCESS; +} + +upm_result_t mma7660_tilt_back_front(const mma7660_context dev, + uint8_t *bits) +{ + assert(dev != NULL); + + if (mma7660_get_verified_tilt(dev, bits)) + return UPM_ERROR_OPERATION_FAILED; + + // mask off the bits we don't care about + *bits &= 0x03; + + return UPM_SUCCESS; +} + +upm_result_t mma7660_tilt_landscape_portrait(const mma7660_context dev, + uint8_t *bits) +{ + assert(dev != NULL); + + if (mma7660_get_verified_tilt(dev, bits)) + return UPM_ERROR_OPERATION_FAILED; + + // mask off the bits we don't care about + *bits >>= 2; + *bits &= 0x07; + + return UPM_SUCCESS; +} + +upm_result_t mma7660_tilt_tap(const mma7660_context dev, bool *tap) +{ + assert(dev != NULL); + + uint8_t val = 0; + if (mma7660_get_verified_tilt(dev, &val)) + return UPM_ERROR_OPERATION_FAILED; + + if (val & 0x20) + *tap = true; + else + *tap = false; + + return UPM_SUCCESS; +} + +upm_result_t mma7660_tilt_shake(const mma7660_context dev, bool *shake) +{ + assert(dev != NULL); + + uint8_t val = 0; + if (mma7660_get_verified_tilt(dev, &val)) + return UPM_ERROR_OPERATION_FAILED; + + if (val & 0x80) + *shake = true; + else + *shake = false; + + return UPM_SUCCESS; +} + +upm_result_t mma7660_install_isr(const mma7660_context dev, int pin, + void (*isr)(void *), void *arg) +{ + assert(dev != NULL); + + mma7660_uninstall_isr(dev); + + if ( !(dev->gpio = mraa_gpio_init(pin)) ) + { + printf("%s: mraa_gpio_init failed.\n", __FUNCTION__); + return UPM_ERROR_OPERATION_FAILED; + } + + mraa_gpio_dir(dev->gpio, MRAA_GPIO_IN); + + // install our interrupt handler + mraa_gpio_isr(dev->gpio, MRAA_GPIO_EDGE_RISING, + isr, arg); + dev->isrInstalled = true; + + return UPM_SUCCESS; +} + +void mma7660_uninstall_isr(const mma7660_context dev) +{ + assert(dev != NULL); + + if (!dev->isrInstalled) + return; + + mraa_gpio_isr_exit(dev->gpio); + dev->isrInstalled = false; + mraa_gpio_close(dev->gpio); + dev->gpio = NULL; +} + +upm_result_t mma7660_set_interrupt_bits(const mma7660_context dev, + uint8_t ibits) +{ + assert(dev != NULL); + + return mma7660_write_byte(dev, MMA7660_REG_INTSU, ibits); +} + +upm_result_t mma7660_set_sample_rate(const mma7660_context dev, + MMA7660_AUTOSLEEP_T sr) +{ + assert(dev != NULL); + + return mma7660_write_byte(dev, MMA7660_REG_SR, sr); +} + +upm_result_t mma7660_get_acceleration(const mma7660_context dev, + float *ax, float *ay, float *az) +{ + assert(dev != NULL); + + int x, y, z; + + if (mma7660_get_raw_values(dev, &x, &y, &z)) + { + printf("%s: mma7660_get_raw_values() failed.\n", __FUNCTION__); + return UPM_ERROR_OPERATION_FAILED; + } + + // 21.33, typical counts/g + + if (ax) + *ax = x/21.33; + if (ay) + *ay = y/21.33; + if (az) + *az = z/21.33; + + return UPM_SUCCESS; +} diff --git a/src/mma7660/mma7660.cxx b/src/mma7660/mma7660.cxx index 012fa2d1..38df355e 100644 --- a/src/mma7660/mma7660.cxx +++ b/src/mma7660/mma7660.cxx @@ -1,6 +1,6 @@ /* * Author: Jon Trulson - * Copyright (c) 2015 Intel Corporation. + * Copyright (c) 2015-2016 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -32,250 +32,161 @@ using namespace upm; using namespace std; -MMA7660::MMA7660(int bus, uint8_t address) +MMA7660::MMA7660(int bus, uint8_t address) : + m_mma7660(mma7660_init(bus, address)) { - m_addr = address; - m_isrInstalled = false; - - // setup our i2c link - if ( !(m_i2c = mraa_i2c_init(bus)) ) - { - throw std::invalid_argument(std::string(__FUNCTION__) + - ": mraa_i2c_init() failed"); - return; - } - - mraa_result_t rv; - - if ( (rv = mraa_i2c_address(m_i2c, m_addr)) != MRAA_SUCCESS) - { - throw std::invalid_argument(std::string(__FUNCTION__) + - ": mraa_i2c_address() failed"); - return; - } + if (!m_mma7660) + throw std::runtime_error(std::string(__FUNCTION__) + + ": mma7660_init() failed"); } MMA7660::~MMA7660() { - if (m_isrInstalled) - uninstallISR(); - - setModeStandby(); - mraa_i2c_stop(m_i2c); + mma7660_close(m_mma7660); } bool MMA7660::writeByte(uint8_t reg, uint8_t byte) { - mraa_result_t rv = mraa_i2c_write_byte_data(m_i2c, byte, reg); - - if (rv != MRAA_SUCCESS) - { - cerr << __FUNCTION__ << ": mraa_i2c_write_byte() failed." << endl; - mraa_result_print(rv); - return false; - } - - return true; + if (mma7660_write_byte(m_mma7660, reg, byte)) + throw std::runtime_error(std::string(__FUNCTION__) + + ": mma7660_write_byte() failed"); + return true; } uint8_t MMA7660::readByte(uint8_t reg) { - int x = mraa_i2c_read_byte_data(m_i2c, reg); - if (x != -1) { - return (uint8_t) x; - } - return 0; + uint8_t val = 0; + if (mma7660_read_byte(m_mma7660, reg, &val)) + throw std::runtime_error(std::string(__FUNCTION__) + + ": mma7660_read_byte() failed"); + + return val; } void MMA7660::getRawValues(int *x, int *y, int *z) { - *x = getVerifiedAxis(REG_XOUT); - *y = getVerifiedAxis(REG_YOUT); - *z = getVerifiedAxis(REG_ZOUT); + if (mma7660_get_raw_values(m_mma7660, x, y, z)) + throw std::runtime_error(std::string(__FUNCTION__) + + ": mma7660_get_raw_values() failed"); } -#ifdef JAVACALLBACK -int *MMA7660::getRawValues() -{ - int *values = new int[3]; - getRawValues(&values[0], &values[1], &values[2]); - return values; -} -#endif - void MMA7660::setModeActive() { - uint8_t modeReg = readByte(REG_MODE); - - // The D2 (TON bit) should be cleared, and the MODE bit set - - modeReg &= ~MODE_TON; - modeReg |= MODE_MODE; - - writeByte(REG_MODE, modeReg); + if (mma7660_set_mode_active(m_mma7660)) + throw std::runtime_error(std::string(__FUNCTION__) + + ": mma7660_set_mode_active() failed"); } void MMA7660::setModeStandby() { - uint8_t modeReg = readByte(REG_MODE); - - // the D0 (mode bit) and D2 (TON bit) should be cleared. - - modeReg &= ~MODE_TON; - modeReg &= ~MODE_MODE; - - writeByte(REG_MODE, modeReg); + if (mma7660_set_mode_standby(m_mma7660)) + throw std::runtime_error(std::string(__FUNCTION__) + + ": mma7660_set_mode_standby() failed"); } // read an axis value, verifying it's validity int MMA7660::getVerifiedAxis(MMA7660_REG_T axis) { - // We only want one of the 3 axes + // We only want one of the 3 axes - if (axis > 2) + if (axis > 2) { - throw std::out_of_range(std::string(__FUNCTION__) + - ": axis must be 0, 1, or 2."); - return 0; + throw std::out_of_range(std::string(__FUNCTION__) + + ": axis must be 0, 1, or 2."); + return 0; } - // we need to check the alert bit and sign bits if the alert bit is - // set, this means that the register was being updated when the - // register was read, so re-read until it's clear. - - uint8_t val; - do { - val = readByte(axis); + int val; + if (mma7660_get_verified_axis(m_mma7660, axis, &val)) + throw std::runtime_error(std::string(__FUNCTION__) + + ": mma7660_get_verified_axis() failed"); - // check alert bit - } while (val & 0x40); - - // shift the sign bit over, and compensate - return (char(val << 2) / 4); + return val; } // read the tilt register, verifying it's validity uint8_t MMA7660::getVerifiedTilt() { - // we need to check the alert bit and sign bits if the alert bit is - // set, this means that the register was being updated when the - // register was read, so re-read until it's clear. - - uint8_t val; - do { - val = readByte(REG_TILT); + uint8_t val; + if (mma7660_get_verified_tilt(m_mma7660, &val)) + throw std::runtime_error(std::string(__FUNCTION__) + + ": mma7660_get_verified_axis() failed"); - // check alert bit - } while (val & 0x40); - - return val; + return val; } uint8_t MMA7660::tiltBackFront() { - uint8_t val = getVerifiedTilt(); + uint8_t val; + if (mma7660_tilt_back_front(m_mma7660, &val)) + throw std::runtime_error(std::string(__FUNCTION__) + + ": mma7660_tilt_back_front() failed"); - // mask off the bits we don't care about - val &= 0x03; - return val; + return val; } uint8_t MMA7660::tiltLandscapePortrait() { - uint8_t val = getVerifiedTilt(); + uint8_t val; + if (mma7660_tilt_landscape_portrait(m_mma7660, &val)) + throw std::runtime_error(std::string(__FUNCTION__) + + ": mma7660_tilt_landscape_portrait() failed"); - // mask off the bits we don't care about - val >>= 2; - val &= 0x07; - return val; + return val; } bool MMA7660::tiltTap() { - uint8_t val = getVerifiedTilt(); + bool val; + if (mma7660_tilt_tap(m_mma7660, &val)) + throw std::runtime_error(std::string(__FUNCTION__) + + ": mma7660_tilt_tap_portrait() failed"); - if (val & 0x20) - return true; - else - return false; + return val; } bool MMA7660::tiltShake() { - uint8_t val = getVerifiedTilt(); + bool val; + if (mma7660_tilt_shake(m_mma7660, &val)) + throw std::runtime_error(std::string(__FUNCTION__) + + ": mma7660_tilt_tap_shake() failed"); - if (val & 0x80) - return true; - else - return false; + return val; } -#ifdef JAVACALLBACK -void MMA7660::installISR(int pin, jobject runnable) -{ - installISR(pin, mraa_java_isr_callback, runnable); -} -#endif - void MMA7660::installISR(int pin, void (*isr)(void *), void *arg) { - if (m_isrInstalled) - uninstallISR(); - - if ( !(m_gpio = mraa_gpio_init(pin)) ) - { - throw std::invalid_argument(std::string(__FUNCTION__) + - ": mraa_gpio_init() failed, invalid pin?"); - return; - } - - mraa_gpio_dir(m_gpio, MRAA_GPIO_IN); - - // install our interrupt handler - mraa_gpio_isr(m_gpio, MRAA_GPIO_EDGE_RISING, - isr, arg); - m_isrInstalled = true; + if (mma7660_install_isr(m_mma7660, pin, isr, arg)) + throw std::runtime_error(std::string(__FUNCTION__) + + ": mma7660_install_isr() failed"); } void MMA7660::uninstallISR() { - if (!m_isrInstalled) - return; - - mraa_gpio_isr_exit(m_gpio); - m_isrInstalled = false; - mraa_gpio_close(m_gpio); + mma7660_uninstall_isr(m_mma7660); } bool MMA7660::setInterruptBits(uint8_t ibits) { - return writeByte(REG_INTSU, ibits); + if (mma7660_set_interrupt_bits(m_mma7660, ibits)) + return false; + else + return true; } bool MMA7660::setSampleRate(MMA7660_AUTOSLEEP_T sr) { - return writeByte(REG_SR, sr); + if (mma7660_set_sample_rate(m_mma7660, sr)) + return false; + else + return true; } void MMA7660::getAcceleration(float *ax, float *ay, float *az) { - int x, y, z; - - getRawValues(&x, &y, &z); - - // 21.33, typical counts/g - - *ax = x/21.33; - *ay = y/21.33; - *az = z/21.33; + if (mma7660_get_acceleration(m_mma7660, ax, ay, az)) + throw std::runtime_error(std::string(__FUNCTION__) + + ": mma7660_get_acceleration() failed"); } -#ifdef JAVACALLBACK -float *MMA7660::getAcceleration() -{ - float *values = new float[3]; - getAcceleration(&values[0], &values[1], &values[2]); - return values; -} -#endif - diff --git a/src/mma7660/mma7660.h b/src/mma7660/mma7660.h new file mode 100644 index 00000000..61094553 --- /dev/null +++ b/src/mma7660/mma7660.h @@ -0,0 +1,251 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 Intel Corporation. + * + * 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 +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * @file mma7660.h + * @library mma7660 + * @brief C API for the mma7660 driver + * + * @include mma7660.c + */ + + /** + * Device context + */ + typedef struct _mma7660_context { + mraa_i2c_context i2c; + mraa_gpio_context gpio; + + bool isrInstalled; + } *mma7660_context; + + /** + * MMA7660 initialization. + * + * @param bus I2C bus to use + * @param address Address for this sensor + */ + mma7660_context mma7660_init(int bus, uint8_t address); + + /** + * MMA7660 destructor + * + * @param dev Device context. + */ + void mma7660_close(mma7660_context dev); + + /** + * Writes a byte value into a register + * + * @param dev Device context. + * @param reg Register location to write into + * @param byte Byte to write + * @return UPM result + */ + upm_result_t mma7660_write_byte(const mma7660_context dev, + uint8_t reg, uint8_t byte); + + /** + * Reads a byte value from a register + * + * @param dev Device context. + * @param reg Register location to read from + * @param byte A pointer to hold the value that was read + * @return UPM result + */ + upm_result_t mma7660_read_byte(const mma7660_context dev, uint8_t reg, + uint8_t *byte); + + /** + * Reads the current value of conversion + * + * @param dev Device context. + * @param x Returned x value + * @param y Returned y value + * @param z Returned z value + * @return UPM result + */ + upm_result_t mma7660_get_raw_values(const mma7660_context dev, + int *x, int *y, int *z); + + /** + * Gets the computed acceleration + * + * @param dev Device context. + * @param ax Returned computed acceleration of the X-axis + * @param ay Returned computed acceleration of the Y-axis + * @param az Returned computed acceleration of the Z-axis + * @return UPM result + */ + upm_result_t mma7660_get_acceleration(const mma7660_context dev, + float *ax, float *ay, float *az); + + /** + * Reads an axis, verifying its validity. The value passed must be + * one of MMA7660_REG_XOUT, MMA7660_REG_YOUT, or MMA7660_REG_ZOUT. + * + * @param dev Device context. + * @param axis Axis to read + * @param val pointer containing returned value + * @return UPM result + */ + upm_result_t mma7660_get_verified_axis(const mma7660_context dev, + MMA7660_REG_T axis, int *val); + + /** + * Reads the tilt register, verifying its validity + * + * @param dev Device context. + * @param val Pointer to returned value + * @return UPM result + */ + upm_result_t mma7660_get_verified_tilt(const mma7660_context dev, + uint8_t *val); + + /** + * Puts the device in the active mode. In this mode, register + * writes are not allowed. Place the device in the standby mode before + * attempting to write registers. + * + * @param dev Device context. + * @return UPM result + */ + upm_result_t mma7660_set_mode_active(const mma7660_context dev); + + /** + * Puts the device in the standby (power saving) mode. Note: when in + * the standby mode, there is no valid data in the registers. In + * addition, the only way to write a register is to put the + * device in the standby mode. + * + * @param dev Device context. + * @return UPM result + */ + upm_result_t mma7660_set_mode_standby(const mma7660_context dev); + + /** + * Reads tiltBackFront bits + * + * The value returned is one of the MMA7660_TILT_BF_T values + * + * @param dev Device context. + * @param bits Pointer to returned bits corresponding to the + * BackFront tilt status + * @return UPM result + */ + upm_result_t mma7660_tilt_back_front(const mma7660_context dev, + uint8_t *bits); + + /** + * Reads tiltLandscapePortrait bits + * + * The value returned is one of the MMA7660_TILT_LP_T values + * + * @param dev Device context. + * @param bits Pointer to returned bits corresponding to the + * LandscapePortrait tilt status + * @return UPM result + */ + upm_result_t mma7660_tilt_landscape_portrait(const mma7660_context dev, + uint8_t *bits); + + /** + * Reads the tiltTap status + * + * @param dev Device context. + * @param tap Pointer to a bool indicating tap detection + * @return UPM result + */ + upm_result_t mma7660_tilt_tap(const mma7660_context dev, bool *tap); + + /** + * Reads the tiltShake status + * + * @param dev Device context. + * @param shake Pointer to a bool indicating shake detection + * @return UPM result + */ + upm_result_t mma7660_tilt_shake(const mma7660_context dev, bool *shake); + + /** + * Installs an interrupt service routine (ISR) to be called when + * an interrupt occurs + * + * @param dev Device context. + * @param pin GPIO pin to use as the interrupt pin + * @param fptr Pointer to a function to be called on interrupt + * @param arg Pointer to an object to be supplied as an + * argument to the ISR. + * @return UPM result + */ + upm_result_t mma7660_install_isr(const mma7660_context dev, int pin, + void (*isr)(void *), void *arg); + + /** + * Uninstalls the previously installed ISR + * + * @param dev Device context. + */ + void mma7660_uninstall_isr(const mma7660_context dev); + + /** + * Enables interrupt generation based on passed interrupt bits. + * The bits are a bitmask of the requested MMA7660_INTR_T values. + * Note: the device must be in the standby mode to set this register. + * + * @param dev Device context. + * @param ibits Sets the requested interrupt bits + * @return UPM result + */ + upm_result_t mma7660_set_interrupt_bits(const mma7660_context dev, + uint8_t ibits); + + /** + * Sets the sampling rate of the sensor. The value supplied must + * be one of the MMA7660_AUTOSLEEP_T values. + * + * @param dev Device context. + * @param sr One of the MMA7660_AUTOSLEEP_T values + * @return UPM result + */ + upm_result_t mma7660_set_sample_rate(const mma7660_context dev, + MMA7660_AUTOSLEEP_T sr); + +#ifdef __cplusplus +} +#endif diff --git a/src/mma7660/mma7660.hpp b/src/mma7660/mma7660.hpp index f18a5de9..16b4b8f9 100644 --- a/src/mma7660/mma7660.hpp +++ b/src/mma7660/mma7660.hpp @@ -1,6 +1,6 @@ /* * Author: Jon Trulson - * Copyright (c) 2015 Intel Corporation. + * Copyright (c) 2015-2016 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -23,289 +23,232 @@ */ #pragma once -#include -#include -#include - -#define MMA7660_I2C_BUS 0 -#define MMA7660_DEFAULT_I2C_ADDR 0x4c +#include namespace upm { - /** - * @brief MMA7660 I2C 3-Axis Digital Accelerometer library - * @defgroup mma7660 libupm-mma7660 - * @ingroup seeed i2c gpio accelerometer - */ - /** - * @library mma7660 - * @sensor mma7660 - * @comname MMA7660 3-Axis Digital Accelerometer - * @altname Grove 3-Axis Digital Accelerometer (1.5g) - * @type accelerometer - * @man seeed - * @con i2c gpio - * - * @brief API for the MMA7660 I2C 3-Axis Digital Accelerometer - * - * UPM module for the MMA7660 I2C 3-axis digital accelerometer. - * This device supports a variety of capabilities, including the - * generation of interrupts for various conditions, tilt and basic - * gesture detection, and X/Y/Z-axis measurements of g-forces - * being applied (up to 1.5g) - * - * This module was tested with the Grove 3-Axis Digital - * Accelerometer (1.5g) - * - * @image html mma7660.jpg - * @snippet mma7660.cxx Interesting - */ - class MMA7660 { - public: - - // MMA7660 registers - typedef enum { REG_XOUT = 0x00, - REG_YOUT = 0x01, - REG_ZOUT = 0x02, - REG_TILT = 0x03, - REG_SRST = 0x04, // Sampling Rate Status - REG_SPCNT = 0x05, // sleep count - REG_INTSU = 0x06, // Interrupt setup - REG_MODE = 0x07, // operating mode - REG_SR = 0x08, // auto-wake/sleep, SPS, and debounce - REG_PDET = 0x09, // tap detection - REG_PD = 0x0a // tap debounce count - // 0x0b-0x1f reserved - } MMA7660_REG_T; - - // interrupt enable register bits - typedef enum { INTR_NONE = 0x00, // disabled - INTR_FBINT = 0x01, // front/back - INTR_PLINT = 0x02, // up/down/right/left - INTR_PDINT = 0x04, // tap detection - INTR_ASINT = 0x08, // exit auto-sleep - INTR_GINT = 0x10, // measurement intr - INTR_SHINTZ = 0x20, // shake on Z - INTR_SHINTY = 0x40, // shake on Y - INTR_SHINTX = 0x80 // shake on X - } MMA7660_INTR_T; - - // operating mode register bits - typedef enum { MODE_MODE = 0x01, // determines mode with MODE_TON - // 0x02 reserved - MODE_TON = 0x04, // determines mode with MODE_MODE - MODE_AWE = 0x08, // auto-wake - MODE_ASE = 0x10, // auto-sleep - MODE_SCPS = 0x20, // sleep count prescale - MODE_IPP = 0x40, // intr out push-pull/open drain - MODE_IAH = 0x80 // intr active low/high - } MMA7660_MODE_T; - - // tilt BackFront (BF) bits - typedef enum { BF_UNKNOWN = 0x00, - BF_LYING_FRONT = 0x01, - BF_LYING_BACK = 0x02 - } MMA7660_TILT_BF_T; - - // tilt LandscapePortrait (LP) bits - typedef enum { LP_UNKNOWN = 0x00, - LP_LANDSCAPE_LEFT = 0x01, - LP_LANDSCAPE_RIGHT = 0x02, - LP_VERT_DOWN = 0x05, - LP_VERT_UP = 0x06 - } MMA7660_TILT_LP_T; - - // sample rate (auto-sleep) values - typedef enum { AUTOSLEEP_120 = 0x00, - AUTOSLEEP_64 = 0x01, - AUTOSLEEP_32 = 0x02, - AUTOSLEEP_16 = 0x03, - AUTOSLEEP_8 = 0x04, - AUTOSLEEP_4 = 0x05, - AUTOSLEEP_2 = 0x06, - AUTOSLEEP_1 = 0x07 - } MMA7660_AUTOSLEEP_T; - /** - * MMA7660 constructor + * @brief MMA7660 I2C 3-Axis Digital Accelerometer library + * @defgroup mma7660 libupm-mma7660 + * @ingroup seeed i2c gpio accelerometer + */ + /** + * @library mma7660 + * @sensor mma7660 + * @comname MMA7660 3-Axis Digital Accelerometer + * @altname Grove 3-Axis Digital Accelerometer (1.5g) + * @type accelerometer + * @man seeed + * @con i2c gpio * - * @param bus I2C bus to use - * @param address Address for this sensor; default is 0x55 - */ - MMA7660(int bus, uint8_t address = MMA7660_DEFAULT_I2C_ADDR); - - /** - * MMA7660 destructor - */ - ~MMA7660(); - - /** - * Writes a byte value into a register + * @brief API for the MMA7660 I2C 3-Axis Digital Accelerometer * - * @param reg Register location to write into - * @param byte Byte to write - * @return True if successful - */ - bool writeByte(uint8_t reg, uint8_t byte); - - /** - * Reads a byte value from a register + * UPM module for the MMA7660 I2C 3-axis digital accelerometer. + * This device supports a variety of capabilities, including the + * generation of interrupts for various conditions, tilt and basic + * gesture detection, and X/Y/Z-axis measurements of g-forces + * being applied (up to 1.5g) * - * @param reg Register location to read from - * @return Value in a specified register - */ - uint8_t readByte(uint8_t reg); - - /** - * Reads the current value of conversion + * This module was tested with the Grove 3-Axis Digital + * Accelerometer (1.5g) * - * @param x Returned x value - * @param y Returned y value - * @param z Returned z value + * @image html mma7660.jpg + * @snippet mma7660.cxx Interesting */ - void getRawValues(int *x, int *y, int *z); + class MMA7660 { + public: + + /** + * MMA7660 constructor + * + * @param bus I2C bus to use + * @param address Address for this sensor; default is 0x55 + */ + MMA7660(int bus, uint8_t address=MMA7660_DEFAULT_I2C_ADDR); + + /** + * MMA7660 destructor + */ + virtual ~MMA7660(); + + /** + * Writes a byte value into a register + * + * @param reg Register location to write into + * @param byte Byte to write + * @return True if successful + */ + bool writeByte(uint8_t reg, uint8_t byte); + + /** + * Reads a byte value from a register + * + * @param reg Register location to read from + * @return Value in a specified register + */ + uint8_t readByte(uint8_t reg); + + /** + * Reads the current value of conversion + * + * @param x Returned x value + * @param y Returned y value + * @param z Returned z value + */ + void getRawValues(int *x, int *y, int *z); + + /** + * Gets the computed acceleration + * + * @param ax Returned computed acceleration of the X-axis + * @param ay Returned computed acceleration of the Y-axis + * @param az Returned computed acceleration of the Z-axis + */ + void getAcceleration(float *ax, float *ay, float *az); + + /** + * Reads an axis, verifying its validity. The value passed must + * be one of REG_XOUT, REG_YOUT, or REG_ZOUT. + * + * @param axis Axis to read + * @return Axis value + */ + int getVerifiedAxis(MMA7660_REG_T axis); + + /** + * Reads the tilt register, verifying its validity + * + * @return Tilt value + */ + uint8_t getVerifiedTilt(); + + /** + * Puts the device in the active mode. In this mode, register + * writes are not allowed. Place the device in the standby mode before + * attempting to write registers. + * + */ + void setModeActive(); + + /** + * Puts the device in the standby (power saving) mode. Note: when in + * the standby mode, there is no valid data in the registers. In + * addition, the only way to write a register is to put the + * device in the standby mode. + * + */ + void setModeStandby(); + + /** + * Reads tiltBackFront bits + * + * The value returned is one of the MMA7660_TILT_BF_T values + * + * @return Bits corresponding to the BackFront tilt status + */ + uint8_t tiltBackFront(); + + /** + * Reads tiltLandscapePortrait bits + * + * The value returned is one of the MMA7660_TILT_LP_T values + * + * @return Bits corresponding to the LandscapePortrait tilt status + */ + uint8_t tiltLandscapePortrait(); + + /** + * Reads the tiltTap status + * + * @return True if a tap is detected + */ + bool tiltTap(); + + /** + * Reads the tiltShake status + * + * @return True if a shake is detected + */ + bool tiltShake(); + + /** + * Uninstalls the previously installed ISR + * + */ + void uninstallISR(); + + /** + * Enables interrupt generation based on passed interrupt bits. + * The bits are a bitmask of the requested MMA7660_INTR_T values. + * Note: the device must be in the standby mode to set this register. + * + * @param ibits Sets the requested interrupt bits + * @return True if successful + */ + bool setInterruptBits(uint8_t ibits); + + /** + * Sets the sampling rate of the sensor. The value supplied must + * be one of the MMA7660_AUTOSLEEP_T values. + * + * @param sr One of the MMA7660_AUTOSLEEP_T values + * @return True if successful + */ + bool setSampleRate(MMA7660_AUTOSLEEP_T sr); #if defined(SWIGJAVA) || defined(JAVACALLBACK) - /** - * Reads the current value of conversion - * - * @return Array containing x, y, z. Free using delete. - */ - int *getRawValues(); -#endif + /** + * Reads the current acceleration values. The returned memory + * is statically allocated and will be overwritten on each + * call. + * + * @return Array containing x, y, z. + */ + float *getAcceleration() + { + static float values[3]; + getAcceleration(&values[0], &values[1], &values[2]); + return values; + } - /** - * Gets the computed acceleration - * - * @param ax Returned computed acceleration of the X-axis - * @param ay Returned computed acceleration of the Y-axis - * @param az Returned computed acceleration of the Z-axis - */ - void getAcceleration(float *ax, float *ay, float *az); + /** + * Reads the current value of conversion. The returned memory + * is statically allocated and will be overwritten on each + * call. + * + * @return Array containing x, y, z. + */ + int *getRawValues() + { + static int values[3]; + getRawValues(&values[0], &values[1], &values[2]); + return values; + } -#if defined(SWIGJAVA) || defined(JAVACALLBACK) - /** - * Gets the computed acceleration - * - * @return Array containing x, y, z. Free using delete. - */ - float *getAcceleration(); -#endif - - /** - * Reads an axis, verifying its validity. The value passed must - * be one of REG_XOUT, REG_YOUT, or REG_ZOUT. - * - * @param axis Axis to read - * @return Axis value - */ - int getVerifiedAxis(MMA7660_REG_T axis); - - /** - * Reads the tilt register, verifying its validity - * - * @return Tilt value - */ - uint8_t getVerifiedTilt(); - - /** - * Puts the device in the active mode. In this mode, register - * writes are not allowed. Place the device in the standby mode before - * attempting to write registers. - * - */ - void setModeActive(); - - /** - * Puts the device in the standby (power saving) mode. Note: when in - * the standby mode, there is no valid data in the registers. In - * addition, the only way to write a register is to put the - * device in the standby mode. - * - */ - void setModeStandby(); - - /** - * Reads tiltBackFront bits - * - * The value returned is one of the MMA7660_TILT_BF_T values - * - * @return Bits corresponding to the BackFront tilt status - */ - uint8_t tiltBackFront(); - - /** - * Reads tiltLandscapePortrait bits - * - * The value returned is one of the MMA7660_TILT_LP_T values - * - * @return Bits corresponding to the LandscapePortrait tilt status - */ - uint8_t tiltLandscapePortrait(); - - /** - * Reads the tiltTap status - * - * @return True if a tap is detected - */ - bool tiltTap(); - - /** - * Reads the tiltShake status - * - * @return True if a shake is detected - */ - bool tiltShake(); - - /** - * Installs an interrupt service routine (ISR) to be called when - * an interrupt occurs - * - * @param pin GPIO pin to use as the interrupt pin - * @param fptr Pointer to a function to be called on interrupt - * @param arg Pointer to an object to be supplied as an - * argument to the ISR. - */ -#if defined(SWIGJAVA) || defined(JAVACALLBACK) - void installISR(int pin, jobject runnable); + void installISR(int pin, jobject runnable) + { + installISR(pin, mraa_java_isr_callback, runnable); + } #else - void installISR(int pin, void (*isr)(void *), void *arg); -#endif - /** - * Uninstalls the previously installed ISR - * - */ - void uninstallISR(); + /** + * Installs an interrupt service routine (ISR) to be called when + * an interrupt occurs + * + * @param pin GPIO pin to use as the interrupt pin + * @param fptr Pointer to a function to be called on interrupt + * @param arg Pointer to an object to be supplied as an + * argument to the ISR. + */ + void installISR(int pin, void (*isr)(void *), void *arg); +#endif // defined(SWIGJAVA) || defined(JAVACALLBACK) - /** - * Enables interrupt generation based on passed interrupt bits. - * The bits are a bitmask of the requested MMA7660_INTR_T values. - * Note: the device must be in the standby mode to set this register. - * - * @param ibits Sets the requested interrupt bits - * @return True if successful - */ - bool setInterruptBits(uint8_t ibits); + protected: + mma7660_context m_mma7660; - /** - * Sets the sampling rate of the sensor. The value supplied must - * be one of the MMA7660_AUTOSLEEP_T values. - * - * @param sr One of the MMA7660_AUTOSLEEP_T values - * @return True if successful - */ - bool setSampleRate(MMA7660_AUTOSLEEP_T sr); - - private: + private: #if defined(SWIGJAVA) || defined(JAVACALLBACK) - void installISR(int pin, void (*isr)(void *), void *arg); + void installISR(int pin, void (*isr)(void *), void *arg); #endif - bool m_isrInstalled; - mraa_i2c_context m_i2c; - mraa_gpio_context m_gpio; - uint8_t m_addr; - }; + }; } - - diff --git a/src/mma7660/mma7660_fti.c b/src/mma7660/mma7660_fti.c new file mode 100644 index 00000000..b1140c31 --- /dev/null +++ b/src/mma7660/mma7660_fti.c @@ -0,0 +1,98 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 Intel Corporation. + * + * 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 "mma7660.h" +#include "upm_fti.h" + +/** + * This file implements the Function Table Interface (FTI) for this sensor + */ + +const char upm_mma7660_name[] = "MMA7660"; +const char upm_mma7660_description[] = "Digital 3-axis Accelerometer"; +const upm_protocol_t upm_mma7660_protocol[] = {UPM_I2C, UPM_GPIO}; +const upm_sensor_t upm_mma7660_category[] = {UPM_ACCELEROMETER}; + +// forward declarations +const void* upm_mma7660_get_ft(upm_sensor_t sensor_type); +void* upm_mma7660_init_name(); +void upm_mma7660_close(void *dev); +upm_result_t upm_mma7660_get_acceleration(void *dev, float *value, + upm_acceleration_u unit); + +const upm_sensor_descriptor_t upm_mma7660_get_descriptor() +{ + upm_sensor_descriptor_t usd; + usd.name = upm_mma7660_name; + usd.description = upm_mma7660_description; + usd.protocol_size = 2; + usd.protocol = upm_mma7660_protocol; + usd.category_size = 1; + usd.category = upm_mma7660_category; + return usd; +} + +static const upm_sensor_ft ft = +{ + .upm_sensor_init_name = &upm_mma7660_init_name, + .upm_sensor_close = &upm_mma7660_close, +}; + +static const upm_acceleration_ft aft = +{ + .upm_acceleration_get_value = &upm_mma7660_get_acceleration +}; + +const void* upm_mma7660_get_ft(upm_sensor_t sensor_type) +{ + switch(sensor_type) + { + case UPM_SENSOR: + return &ft; + + case UPM_ACCELEROMETER: + return &aft; + + default: + return NULL; + } +} + +void* upm_mma7660_init_name() +{ + return NULL; +} + + +void upm_mma7660_close(void *dev) +{ + mma7660_close((mma7660_context)dev); +} + +upm_result_t upm_mma7660_get_acceleration(void *dev, float *value, + upm_acceleration_u unit) +{ + return mma7660_get_acceleration((mma7660_context)dev, &value[0], &value[1], + &value[2]); +} diff --git a/src/mma7660/mma7660_regs.h b/src/mma7660/mma7660_regs.h new file mode 100644 index 00000000..d1086d8d --- /dev/null +++ b/src/mma7660/mma7660_regs.h @@ -0,0 +1,104 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 Intel Corporation. + * + * 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 + +#define MMA7660_DEFAULT_I2C_BUS 0 +#define MMA7660_DEFAULT_I2C_ADDR 0x4c + +#ifdef __cplusplus +extern "C" { +#endif + + // MMA7660 registers + typedef enum { + MMA7660_REG_XOUT = 0x00, + MMA7660_REG_YOUT = 0x01, + MMA7660_REG_ZOUT = 0x02, + MMA7660_REG_TILT = 0x03, + MMA7660_REG_SRST = 0x04, // Sampling Rate Status + MMA7660_REG_SPCNT = 0x05, // sleep count + MMA7660_REG_INTSU = 0x06, // Interrupt setup + MMA7660_REG_MODE = 0x07, // operating mode + MMA7660_REG_SR = 0x08, // auto-wake/sleep, SPS, and debounce + MMA7660_REG_PDET = 0x09, // tap detection + MMA7660_REG_PD = 0x0a // tap debounce count + // 0x0b-0x1f reserved + } MMA7660_REG_T; + + // interrupt enable register bits + typedef enum { + MMA7660_INTR_NONE = 0x00, // disabled + MMA7660_INTR_FBINT = 0x01, // front/back + MMA7660_INTR_PLINT = 0x02, // up/down/right/left + MMA7660_INTR_PDINT = 0x04, // tap detection + MMA7660_INTR_ASINT = 0x08, // exit auto-sleep + MMA7660_INTR_GINT = 0x10, // measurement intr + MMA7660_INTR_SHINTZ = 0x20, // shake on Z + MMA7660_INTR_SHINTY = 0x40, // shake on Y + MMA7660_INTR_SHINTX = 0x80 // shake on X + } MMA7660_INTR_T; + + // operating mode register bits + typedef enum { + MMA7660_MODE_MODE = 0x01, // determines mode with MODE_TON + // 0x02 reserved + MMA7660_MODE_TON = 0x04, // determines mode with MODE_MODE + MMA7660_MODE_AWE = 0x08, // auto-wake + MMA7660_MODE_ASE = 0x10, // auto-sleep + MMA7660_MODE_SCPS = 0x20, // sleep count prescale + MMA7660_MODE_IPP = 0x40, // intr out push-pull/open drain + MMA7660_MODE_IAH = 0x80 // intr active low/high + } MMA7660_MODE_T; + + // tilt BackFront (BF) bits + typedef enum { + MMA7660_BF_UNKNOWN = 0x00, + MMA7660_BF_LYING_FRONT = 0x01, + MMA7660_BF_LYING_BACK = 0x02 + } MMA7660_TILT_BF_T; + + // tilt LandscapePortrait (LP) bits + typedef enum { + MMA7660_LP_UNKNOWN = 0x00, + MMA7660_LP_LANDSCAPE_LEFT = 0x01, + MMA7660_LP_LANDSCAPE_RIGHT = 0x02, + MMA7660_LP_VERT_DOWN = 0x05, + MMA7660_LP_VERT_UP = 0x06 + } MMA7660_TILT_LP_T; + + // sample rate (auto-sleep) values + typedef enum { + MMA7660_AUTOSLEEP_120 = 0x00, + MMA7660_AUTOSLEEP_64 = 0x01, + MMA7660_AUTOSLEEP_32 = 0x02, + MMA7660_AUTOSLEEP_16 = 0x03, + MMA7660_AUTOSLEEP_8 = 0x04, + MMA7660_AUTOSLEEP_4 = 0x05, + MMA7660_AUTOSLEEP_2 = 0x06, + MMA7660_AUTOSLEEP_1 = 0x07 + } MMA7660_AUTOSLEEP_T; + +#ifdef __cplusplus +} +#endif diff --git a/src/mma7660/pyupm_mma7660.i b/src/mma7660/pyupm_mma7660.i index c653badf..41ec07d3 100644 --- a/src/mma7660/pyupm_mma7660.i +++ b/src/mma7660/pyupm_mma7660.i @@ -14,6 +14,7 @@ %include "mma7660_doc.i" #endif +%include "mma7660_regs.h" %include "mma7660.hpp" %{ #include "mma7660.hpp"