diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index ca403be1..cd4981c8 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -241,6 +241,7 @@ endif() add_example (hdxxvxta) add_example (rhusb) add_example (apds9930) +add_example (kxcjk1013) # 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++/kxcjk1013.cxx b/examples/c++/kxcjk1013.cxx new file mode 100644 index 00000000..3732dbde --- /dev/null +++ b/examples/c++/kxcjk1013.cxx @@ -0,0 +1,75 @@ +/* + * Author: Lay, Kuan Loon + * 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 "kxcjk1013.h" + +using namespace std; + +int shouldRun = true; +upm::KXCJK1013* accelerometer; + +void +sig_handler(int signo) +{ + if (signo == SIGINT) + shouldRun = false; +} + +void +data_callback(char* data) +{ + float x, y, z; + accelerometer->extract3Axis(data, &x, &y, &z); + printf("%.1f %.1f %.1f\n", x, y, z); + // usleep(100); +} + +int +main() +{ + signal(SIGINT, sig_handler); + //! [Interesting] + // Instantiate a KXCJK1013 Accelerometer Sensor on iio device 0 + accelerometer = new upm::KXCJK1013(0); + accelerometer->setScale(0.019163); + accelerometer->setSamplingFrequency(25.0); + accelerometer->enable3AxisChannel(); + accelerometer->installISR(data_callback, NULL); + accelerometer->enableBuffer(16); + + while (shouldRun) { + sleep(1); + } + accelerometer->disableBuffer(); + + //! [Interesting] + cout << "Exiting" << endl; + + delete accelerometer; + + return 0; +} diff --git a/src/kxcjk1013/CMakeLists.txt b/src/kxcjk1013/CMakeLists.txt new file mode 100755 index 00000000..679dc4ae --- /dev/null +++ b/src/kxcjk1013/CMakeLists.txt @@ -0,0 +1,5 @@ +set (libname "kxcjk1013") +set (libdescription "upm kxcjk1013 sensor module") +set (module_src ${libname}.cxx) +set (module_h ${libname}.h) +upm_module_init() diff --git a/src/kxcjk1013/javaupm_kxcjk1013.i b/src/kxcjk1013/javaupm_kxcjk1013.i new file mode 100755 index 00000000..48dea5af --- /dev/null +++ b/src/kxcjk1013/javaupm_kxcjk1013.i @@ -0,0 +1,14 @@ +%module javaupm_kxcjk1013 +%include "../upm.i" +%include "stdint.i" +%include "typemaps.i" + +%feature("director") IsrCallback; + +%ignore generic_callback_isr; +%include "../IsrCallback.h" + +%{ + #include "kxcjk1013.h" +%} +%include "kxcjk1013.h" diff --git a/src/kxcjk1013/jsupm_kxcjk1013.i b/src/kxcjk1013/jsupm_kxcjk1013.i new file mode 100755 index 00000000..e4575638 --- /dev/null +++ b/src/kxcjk1013/jsupm_kxcjk1013.i @@ -0,0 +1,8 @@ +%module jsupm_kxcjk1013 +%include "../upm.i" + +%{ + #include "kxcjk1013.h" +%} + +%include "kxcjk1013.h" diff --git a/src/kxcjk1013/kxcjk1013.cxx b/src/kxcjk1013/kxcjk1013.cxx new file mode 100644 index 00000000..19ce1366 --- /dev/null +++ b/src/kxcjk1013/kxcjk1013.cxx @@ -0,0 +1,207 @@ +/* + * Author: Lay, Kuan Loon + * 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 "kxcjk1013.h" + +using namespace upm; + +KXCJK1013::KXCJK1013(int device) +{ + float accel_scale; + char trigger[64]; + + if (!(m_iio = mraa_iio_init(device))) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_iio_init() failed, invalid device?"); + return; + } + m_scale = 1; + m_iio_device_num = device; + sprintf(trigger, "hrtimer-kxcjk1013-hr-dev%d", device); + + if (mraa_iio_create_trigger(m_iio, trigger) != MRAA_SUCCESS) + fprintf(stderr, "Create trigger failed\n"); + + if (mraa_iio_get_mounting_matrix(m_iio, m_mount_matrix) == MRAA_SUCCESS) + m_mount_matrix_exist = true; + else + m_mount_matrix_exist = false; + + if (mraa_iio_read_float(m_iio, "in_accel_scale", &accel_scale) == MRAA_SUCCESS) + m_scale = accel_scale; +} + +KXCJK1013::~KXCJK1013() +{ + // mraa_iio_stop(m_iio); +} + +#ifdef JAVACALLBACK +void +KXCJK1013::installISR(IsrCallback* cb) +{ + installISR(generic_callback_isr, cb); +} +#endif + +void +KXCJK1013::installISR(void (*isr)(char*), void* arg) +{ + mraa_iio_trigger_buffer(m_iio, isr, NULL); +} + +int64_t +KXCJK1013::getChannelValue(unsigned char* input, mraa_iio_channel* chan) +{ + uint64_t u64; + int i; + int storagebits = chan->bytes * 8; + int realbits = chan->bits_used; + int zeroed_bits = storagebits - realbits; + uint64_t sign_mask; + uint64_t value_mask; + + u64 = 0; + + if (!chan->lendian) + for (i = 0; i < storagebits / 8; i++) + u64 = (u64 << 8) | input[i]; + else + for (i = storagebits / 8 - 1; i >= 0; i--) + u64 = (u64 << 8) | input[i]; + + u64 = (u64 >> chan->shift) & (~0ULL >> zeroed_bits); + + if (!chan->signedd) + return (int64_t) u64; /* We don't handle unsigned 64 bits int */ + + /* Signed integer */ + + switch (realbits) { + case 0 ... 1: + return 0; + + case 8: + return (int64_t)(int8_t) u64; + + case 16: + return (int64_t)(int16_t) u64; + + case 32: + return (int64_t)(int32_t) u64; + + case 64: + return (int64_t) u64; + + default: + sign_mask = 1 << (realbits - 1); + value_mask = sign_mask - 1; + + if (u64 & sign_mask) + return -((~u64 & value_mask) + 1); /* Negative value: return 2-complement */ + else + return (int64_t) u64; /* Positive value */ + } +} + +bool +KXCJK1013::enableBuffer(int length) +{ + mraa_iio_write_integer(m_iio, "buffer/length", length); + // enable must be last step, else will have error in writing above config + mraa_iio_write_integer(m_iio, "buffer/enable", 1); + + return true; +} + +bool +KXCJK1013::disableBuffer() +{ + mraa_iio_write_integer(m_iio, "buffer/enable", 0); + + return true; +} + +bool +KXCJK1013::setScale(float scale) +{ + mraa_iio_write_float(m_iio, "in_accel_scale", scale); + + return true; +} + +bool +KXCJK1013::setSamplingFrequency(float sampling_frequency) +{ + mraa_iio_write_float(m_iio, "in_accel_sampling_frequency", sampling_frequency); + + return true; +} + +bool +KXCJK1013::enable3AxisChannel() +{ + char trigger[64]; + sprintf(trigger, "kxcjk1013-hr-dev%d", m_iio_device_num); + + mraa_iio_write_string(m_iio, "trigger/current_trigger", trigger); + mraa_iio_write_integer(m_iio, "scan_elements/in_accel_x_en", 1); + mraa_iio_write_integer(m_iio, "scan_elements/in_accel_y_en", 1); + mraa_iio_write_integer(m_iio, "scan_elements/in_accel_z_en", 1); + + // need update channel data size after enable + mraa_iio_update_channels(m_iio); + return true; +} + +void +KXCJK1013::extract3Axis(char* data, float* x, float* y, float* z) +{ + mraa_iio_channel* channels = mraa_iio_get_channels(m_iio); + float tmp[3]; + int i = 0; + int iio_x, iio_y, iio_z; + + iio_x = getChannelValue((unsigned char*) (data + channels[0].location), &channels[0]); + iio_y = getChannelValue((unsigned char*) (data + channels[1].location), &channels[1]); + iio_z = getChannelValue((unsigned char*) (data + channels[2].location), &channels[2]); + + *x = (iio_x * m_scale); + *y = (iio_y * m_scale); + *z = (iio_z * m_scale); + + if (m_mount_matrix_exist) { + tmp[0] = *x * m_mount_matrix[0] + *y * m_mount_matrix[1] + *z * m_mount_matrix[2]; + tmp[1] = *x * m_mount_matrix[3] + *y * m_mount_matrix[4] + *z * m_mount_matrix[5]; + tmp[2] = *x * m_mount_matrix[6] + *y * m_mount_matrix[7] + *z * m_mount_matrix[8]; + + *x = tmp[0]; + *y = tmp[1]; + *z = tmp[2]; + } +} diff --git a/src/kxcjk1013/kxcjk1013.h b/src/kxcjk1013/kxcjk1013.h new file mode 100644 index 00000000..63205870 --- /dev/null +++ b/src/kxcjk1013/kxcjk1013.h @@ -0,0 +1,135 @@ +/* + * Author: Lay, Kuan Loon + * 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. + */ +#pragma once + +#include +#include + +#if defined(SWIGJAVA) || defined(JAVACALLBACK) +#include "../IsrCallback.h" +#endif + +namespace upm +{ +/** + * @brief KXCJK1013 Tri-axis Digital Accelerometer + * @defgroup kxcjk1013 libupm-kxcjk1013 + * @ingroup Kionix iio i2c tri-axis digital accelerometer + */ + +/** + * @library kxcjk1013 + * @sensor kxcjk1013 + * @comname KXCJK1013 Tri-axis Digital Accelerometer + * @type accelerometer + * @man Kionix + * @con iio i2c + * + * @brief KXCJK1013 Tri-axis Digital Accelerometer API + * + * The KXCJK is a tri-axis +/-2g, +/-4g or +/-8g silicon micromachined + * accelerometer. + * + * @snippet kxcjk1013.cxx Interesting + */ + +class KXCJK1013 +{ + public: + /** + * KXCJK1013 Tri-axis Digital Accelerometer + * + * @param iio device number + */ + KXCJK1013(int device); + /** + * KXCJK1013 destructor + */ + ~KXCJK1013(); +/** + * Installs an interrupt service routine (ISR) to be called when + * an interrupt occurs + * + * @param interrupt channel + * @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(IsrCallback* cb); +#else + void installISR(void (*isr)(char*), void* arg); +#endif + /** + * Extract the channel value based on channel type + * @param input Channel data + * @param chan MRAA iio-layer channel info + */ + int64_t getChannelValue(unsigned char* input, mraa_iio_channel* chan); + + /** + * Enable trigger buffer + * @param trigger buffer length in string + */ + bool enableBuffer(int length); + + /** + * Disable trigger buffer + */ + bool disableBuffer(); + + /** + * Set scale + * @param scale in string + */ + bool setScale(const float scale); + + /** + * Set sampling frequency + * @param sampling frequency in string + */ + bool setSamplingFrequency(const float sampling_frequency); + + /** + * Enable 3 axis scan element + */ + bool enable3AxisChannel(); + + /** + * Process enabled channel buffer and return x, y, z axis + * @param data Enabled channel data, 6 bytes, each axis 2 bytes + * @param x X-Axis + * @param y Y-Axis + * @param z Z-Axis + */ + void extract3Axis(char* data, float* x, float* y, float* z); + + private: + mraa_iio_context m_iio; + int m_iio_device_num; + bool m_mount_matrix_exist; // is mount matrix exist + float m_mount_matrix[9]; // mount matrix + float m_scale; // accelerometer data scale +}; +} diff --git a/src/kxcjk1013/pyupm_kxcjk1013.i b/src/kxcjk1013/pyupm_kxcjk1013.i new file mode 100755 index 00000000..87b8d77b --- /dev/null +++ b/src/kxcjk1013/pyupm_kxcjk1013.i @@ -0,0 +1,9 @@ +%module pyupm_kxcjk1013 +%include "../upm.i" + +%feature("autodoc", "3"); + +%include "kxcjk1013.h" +%{ + #include "kxcjk1013.h" +%}