From e83b8ef114c852b8900361a4965d754ade9f7244 Mon Sep 17 00:00:00 2001 From: Norbert Wesp Date: Tue, 14 Feb 2017 11:43:04 +0100 Subject: [PATCH] tcs37727: Added upm support for color sensor TCS37727 TCS37727 is a Color Light-To-Digital Converter. I also added the manufacturer 'ams' of TCS37727. Signed-off-by: Norbert Wesp Signed-off-by: Mihai Tudor Panu --- doxy/samples.mapping.txt | 1 + examples/c++/CMakeLists.txt | 1 + examples/c++/tcs37727.cxx | 77 +++++++ examples/python/tcs37727.py | 63 ++++++ src/groups.md | 5 + src/tcs37727/CMakeLists.txt | 5 + src/tcs37727/javaupm_tcs37727.i | 19 ++ src/tcs37727/jsupm_tcs37727.i | 8 + src/tcs37727/pyupm_tcs37727.i | 15 ++ src/tcs37727/tcs37727.cpp | 349 ++++++++++++++++++++++++++++++++ src/tcs37727/tcs37727.hpp | 289 ++++++++++++++++++++++++++ 11 files changed, 832 insertions(+) create mode 100644 examples/c++/tcs37727.cxx create mode 100644 examples/python/tcs37727.py create mode 100644 src/tcs37727/CMakeLists.txt create mode 100644 src/tcs37727/javaupm_tcs37727.i create mode 100644 src/tcs37727/jsupm_tcs37727.i create mode 100644 src/tcs37727/pyupm_tcs37727.i create mode 100644 src/tcs37727/tcs37727.cpp create mode 100644 src/tcs37727/tcs37727.hpp diff --git a/doxy/samples.mapping.txt b/doxy/samples.mapping.txt index 76b8da54..e7263a02 100644 --- a/doxy/samples.mapping.txt +++ b/doxy/samples.mapping.txt @@ -74,3 +74,4 @@ wt5001.cxx WT5001Sample.java wt5001.js wt5001.py yg1006.cxx YG1006Sample.java yg1006.js yg1006.py sensortemplate.cxx SensorTemplateSample.java sensortemplate.js sensortemplate.py p9813.cxx P9813Sample.java p9813.js p9813.py +tcs37727.cxx tcs37727.py diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index 4d22d9a6..7ba59829 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -334,6 +334,7 @@ add_example (p9813) add_example (abpdrrt005pg2a5) add_example (lcdks) add_example (mmc35240) +add_example (tcs37727) # 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++/tcs37727.cxx b/examples/c++/tcs37727.cxx new file mode 100644 index 00000000..a13d8d3a --- /dev/null +++ b/examples/c++/tcs37727.cxx @@ -0,0 +1,77 @@ +/* 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 "tcs37727.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::tcs37727_data_t data; + + cout << "Initializing test-application..." << endl; + + // Instantiate an TCS37727 instance on bus 1 + upm::TCS37727 *mySensor = new upm::TCS37727(1); + + // activate periodic measurements + mySensor->setActive(); + + // update and print available values every second + while (run) + { + mySensor->getData (&data, true); + cout << "Red: " << (int)data.red << endl + << "Green: " << (int)data.green << endl + << "Blue: " << (int)data.blue << endl + << "Clear: " << (int)data.clear << endl + << "Lux: " << (int)data.lux << endl + << "Color temperature: " << (int)data.ct << endl; + + cout << endl; + + sleep(1); + } + + cout << "Exiting test-application..." << endl; + + delete mySensor; +//! [Interesting] + + return 0; +} diff --git a/examples/python/tcs37727.py b/examples/python/tcs37727.py new file mode 100644 index 00000000..f9a881d3 --- /dev/null +++ b/examples/python/tcs37727.py @@ -0,0 +1,63 @@ +#!/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_tcs37727 as TCS37727 + +def main(): + # Instantiate the color sensor on I2C on bus 1 + mySensor = TCS37727.TCS37727(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 = TCS37727.tcs37727_data_t() + + # activate periodic measurements + mySensor.setActive(); + + # Print out the red, green, blue, clear, lux and color-temperature value + # every 0.5 seconds + while(1): + mySensor.getData(data, True) + print(data.red, data.green, data.blue, data.clear, data.lux, data.ct) + + time.sleep(.5) + +if __name__ == '__main__': + main() diff --git a/src/groups.md b/src/groups.md index 349ba889..b1cafe08 100644 --- a/src/groups.md +++ b/src/groups.md @@ -275,6 +275,11 @@ and is not meant to be installed anywhere. @brief Amphenol +@defgroup ams ams AG +@ingroup byman +@brief ams AG + + @defgroup bosch Bosch @ingroup byman @brief Bosch diff --git a/src/tcs37727/CMakeLists.txt b/src/tcs37727/CMakeLists.txt new file mode 100644 index 00000000..7046b95f --- /dev/null +++ b/src/tcs37727/CMakeLists.txt @@ -0,0 +1,5 @@ +set (libname "tcs37727") +set (libdescription "Color Sensor") +set (module_src ${libname}.cpp) +set (module_hpp ${libname}.hpp) +upm_module_init() diff --git a/src/tcs37727/javaupm_tcs37727.i b/src/tcs37727/javaupm_tcs37727.i new file mode 100644 index 00000000..ac6c4bcc --- /dev/null +++ b/src/tcs37727/javaupm_tcs37727.i @@ -0,0 +1,19 @@ +%module javaupm_tcs37727 +%include "../upm.i" + +%{ + #include "tcs37727.hpp" +%} + +%include "tcs37727.hpp" + +%pragma(java) jniclasscode=%{ + static { + try { + System.loadLibrary("javaupm_tcs37727"); + } 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/tcs37727/jsupm_tcs37727.i b/src/tcs37727/jsupm_tcs37727.i new file mode 100644 index 00000000..823d6a39 --- /dev/null +++ b/src/tcs37727/jsupm_tcs37727.i @@ -0,0 +1,8 @@ +%module jsupm_tcs37727 +%include "../upm.i" + +%{ + #include "tcs37727.hpp" +%} + +%include "tcs37727.hpp" diff --git a/src/tcs37727/pyupm_tcs37727.i b/src/tcs37727/pyupm_tcs37727.i new file mode 100644 index 00000000..a9a48c21 --- /dev/null +++ b/src/tcs37727/pyupm_tcs37727.i @@ -0,0 +1,15 @@ +// Include doxygen-generated documentation +%include "pyupm_doxy2swig.i" +%module pyupm_tcs37727 +%include "../upm.i" + +%feature("autodoc", "3"); + +#ifdef DOXYGEN +%include "tcs37727_doc.i" +#endif + +%include "tcs37727.hpp" +%{ + #include "tcs37727.hpp" +%} diff --git a/src/tcs37727/tcs37727.cpp b/src/tcs37727/tcs37727.cpp new file mode 100644 index 00000000..ff3a55ec --- /dev/null +++ b/src/tcs37727/tcs37727.cpp @@ -0,0 +1,349 @@ +/* + * Author: Norbert Wesp + * Copyright (c) 2017 Phytec Messtechnik GmbH. + * + * based on: RIOT-driver tcs37727 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 "tcs37727.hpp" + +using namespace upm; + +TCS37727::TCS37727(int bus, int atime_us, int devAddr) : m_i2ControlCtx(bus) { + s_data->red = 0; + s_data->green = 0; + s_data->blue = 0; + s_data->clear = 0; + s_data->lux = 0; + s_data->ct = 0; + s_again = 4; + + m_name = TCS37727_NAME; + + 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 (checkID() != 0) { + /* sensor_id does not match! maybe wrong sensor chosen? */ + throw std::invalid_argument(std::string(__FUNCTION__) + + ": checkID() failed"); + } + + ret = m_i2ControlCtx.writeReg(TCS37727_CONTROL, TCS37727_CONTROL_AGAIN_4); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte_data() failed"); + } + + ret = m_i2ControlCtx.writeReg(TCS37727_ATIME, + TCS37727_ATIME_TO_REG(atime_us)); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte_data() failed"); + } + + s_atime_us = atime_us; +} + +int +TCS37727::checkID(void) +{ + uint8_t id; + + id = m_i2ControlCtx.readReg(TCS37727_DEVICE_ID_REG); + + if (id != TCS37727_DEVICE_ID) { + return -1; + } + + return 0; +} + +int +TCS37727::setActive(void) +{ + uint8_t reg; + + reg = m_i2ControlCtx.readReg(TCS37727_ENABLE); + + reg |= (TCS37727_ENABLE_AEN | TCS37727_ENABLE_PON); + + mraa::Result ret = m_i2ControlCtx.writeReg(TCS37727_ENABLE, reg); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte_data() failed"); + return -1; + } + return 0; +} + +int +TCS37727::setStandby(void) +{ + uint8_t reg; + + reg = m_i2ControlCtx.readReg(TCS37727_ENABLE); + + reg &= ~TCS37727_ENABLE_AEN; + if (!(reg & TCS37727_ENABLE_PEN)) { + reg &= ~TCS37727_ENABLE_PON; + } + + mraa::Result ret = m_i2ControlCtx.writeReg(TCS37727_ENABLE, reg); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte_data() failed"); + return -1; + } + return 0; +} + +uint8_t +TCS37727::trimGain(int rawc) +{ + uint8_t reg_again = 0; + int val_again = s_again; + uint8_t reg; + + if (rawc < TCS37727_AG_THRESHOLD_LOW) { + switch (val_again) { + case 1: + reg_again = TCS37727_CONTROL_AGAIN_4; + val_again = 4; + break; + + case 4: + reg_again = TCS37727_CONTROL_AGAIN_16; + val_again = 16; + break; + + case 16: + reg_again = TCS37727_CONTROL_AGAIN_60; + val_again = 60; + break; + + case 60: + default: + return -1; + } + } + else if (rawc > TCS37727_AG_THRESHOLD_HIGH) { + switch (val_again) { + case 60: + reg_again = TCS37727_CONTROL_AGAIN_16; + val_again = 16; + break; + + case 16: + reg_again = TCS37727_CONTROL_AGAIN_4; + val_again = 4; + break; + + case 4: + reg_again = TCS37727_CONTROL_AGAIN_1; + val_again = 1; + break; + + case 1: + default: + return -1; + } + } + else { + return 0; + } + + reg = m_i2ControlCtx.readReg(TCS37727_CONTROL); + + reg &= ~TCS37727_CONTROL_AGAIN_MASK; + reg |= reg_again; + + mraa::Result ret = m_i2ControlCtx.writeReg(TCS37727_CONTROL, reg); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte_data() failed"); + return -1; + } + + s_again = val_again; + + return 0; + +} + +int +TCS37727::sampleData(void) +{ + uint8_t buf[8]; + int num = 0; + + num = m_i2ControlCtx.readBytesReg((TCS37727_INC_TRANS | TCS37727_CDATA), + buf, 8); + if (num != 8) { + /* not enough values were read */ + return -1; + } + + int32_t tmpc = ((uint16_t)buf[1] << 8) | buf[0]; + int32_t tmpr = ((uint16_t)buf[3] << 8) | buf[2]; + int32_t tmpg = ((uint16_t)buf[5] << 8) | buf[4]; + int32_t tmpb = ((uint16_t)buf[7] << 8) | buf[6]; + + /* Remove IR component as described in the DN40. */ + int32_t ir = (tmpr + tmpg + tmpb - tmpc) >> 1; + tmpr -= ir; + tmpg -= ir; + tmpb -= ir; + + /* Color temperature calculation as described in the DN40. */ + int32_t ct = (CT_COEF_IF * tmpb) / tmpr + CT_OFFSET_IF; + + /* Lux calculation as described in the DN40. */ + int32_t gi = R_COEF_IF * tmpr + G_COEF_IF * tmpg + B_COEF_IF * tmpb; + /* TODO: add Glass Attenuation Factor GA compensation */ + int32_t cpl = (s_atime_us * s_again) / DGF_IF; + int32_t lux = gi / cpl; + + /* Autogain */ + trimGain(tmpc); + + s_data->red = (tmpr < 0) ? 0 : (tmpr * 1000) / cpl; + s_data->green = (tmpg < 0) ? 0 : (tmpg * 1000) / cpl; + s_data->blue = (tmpb < 0) ? 0 : (tmpb * 1000) / cpl; + s_data->clear = (tmpb < 0) ? 0 : (tmpc * 1000) / cpl; + s_data->lux = (lux < 0) ? 0 : lux; + s_data->ct = (ct < 0) ? 0 : ct; + + return 0; +} + +uint32_t +TCS37727::getChannelRed(int bSampleData) +{ + if (bSampleData) { + if (sampleData() != 0) { + /* error in read values from reg */ + return 999; + } + } + + return s_data->red; +} + +uint32_t +TCS37727::getChannelGreen(int bSampleData) +{ + if (bSampleData) { + if (sampleData() != 0) { + /* error in read values from reg */ + return 999; + } + } + + return s_data->green; +} + +uint32_t +TCS37727::getChannelBlue(int bSampleData) +{ + if (bSampleData) { + if (sampleData() != 0) { + /* error in read values from reg */ + return 999; + } + } + + return s_data->blue; +} + +uint32_t +TCS37727::getChannelClear(int bSampleData) +{ + if (bSampleData) { + if (sampleData() != 0) { + /* error in read values from reg */ + return 999; + } + } + + return s_data->clear; +} + +uint32_t +TCS37727::getLux(int bSampleData) +{ + if (bSampleData) { + if (sampleData() != 0) { + /* error in read values from reg */ + return 999; + } + } + + return s_data->lux; +} + +uint32_t +TCS37727::getColorTemperature(int bSampleData) +{ + if (bSampleData) { + if (sampleData() != 0) { + /* error in read values from reg */ + return 999; + } + } + + return s_data->ct; +} + +int +TCS37727::getData(tcs37727_data_t* data, int bSampleData) +{ + if (bSampleData) { + if (sampleData() != 0) { + /* error in read values from reg */ + return -1; + } + } + + data->red = s_data->red; + data->green = s_data->green; + data->blue = s_data->blue; + data->clear = s_data->clear; + data->lux = s_data->lux; + data->ct = s_data->ct; + + return 0; +} diff --git a/src/tcs37727/tcs37727.hpp b/src/tcs37727/tcs37727.hpp new file mode 100644 index 00000000..9af4f359 --- /dev/null +++ b/src/tcs37727/tcs37727.hpp @@ -0,0 +1,289 @@ +/* + * Author: Norbert Wesp + * Copyright (c) 2017 Phytec Messtechnik GmbH. + * + * based on: RIOT-driver tcs37727 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 + +#define TCS37727_NAME "TCS37727" +#define TCS37727_I2C_ADDRESS 0x29 +#define TCS37727_DEVICE_ID 0x49 +#define TCS37727_DEVICE_ID_REG 0x92 + +#define TCS37727_ATIME_DEFAULT 200000 /* Default RGBC integration time */ +#define TCS37727_AG_THRESHOLD_LOW 200 +#define TCS37727_AG_THRESHOLD_HIGH (65535 - TCS37727_AG_THRESHOLD_LOW) + + +/* TCS37727 Register Map */ +#define TCS37727_ENABLE 0x80 /* Enables states and interrupts */ +#define TCS37727_ATIME 0x81 /* RGBC time */ +#define TCS37727_PTIME 0x82 /* Proximity time */ +#define TCS37727_WTIME 0x83 /* Wait time */ +#define TCS37727_AILTL 0x04 /* Clear interrupt low threshold low byte */ +#define TCS37727_AILTH 0x05 /* Clear interrupt low threshold high byte */ +#define TCS37727_AIHTL 0x06 /* Clear interrupt high threshold low byte */ +#define TCS37727_AIHTH 0x07 /* Clear interrupt high threshold high byte */ +#define TCS37727_PILTL 0x08 /* Proximity inter. low threshold low byte */ +#define TCS37727_PILTH 0x09 /* Proximity inter. low threshold high byte */ +#define TCS37727_PIHTL 0x0A /* Proximity inter. high threshold low byte */ +#define TCS37727_PIHTH 0x0B /* Proximity inter. high threshold high byte */ +#define TCS37727_PERS 0x8C /* Interrupt persistence filters */ +#define TCS37727_CONFIG 0x8D /* Configuration */ +#define TCS37727_PPULSE 0x8E /* Proximity pulse count */ +#define TCS37727_CONTROL 0x8F /* Gain control register */ +#define TCS37727_STATUS 0x93 /* Device status */ +#define TCS37727_CDATA 0x14 /* Clear ADC data low byte */ +#define TCS37727_CDATAH 0x15 /* Clear ADC data high byte */ +#define TCS37727_RDATA 0x16 /* Red ADC data low byte */ +#define TCS37727_RDATAH 0x17 /* Red ADC data high byte */ +#define TCS37727_GDATA 0x18 /* Green ADC data low byte */ +#define TCS37727_GDATAH 0x19 /* Green ADC data high byte */ +#define TCS37727_BDATA 0x1A /* Blue ADC data low byte */ +#define TCS37727_BDATAH 0x1B /* Blue ADC data high byte */ +#define TCS37727_PDATA 0x1C /* Proximity ADC data low byte */ +#define TCS37727_PDATAH 0x1D /* Proximity ADC data high byte */ + +/* TCS37727 Command Register */ +#define TCS37727_BYTE_TRANS 0x80 /* Repeated byte protocol transaction */ +#define TCS37727_INC_TRANS 0xA0 /* Auto-increment protocol transaction */ +#define TCS37727_SF_PICLR 0xE5 /* Proximity interrupt clear */ +#define TCS37727_SF_CICLR 0xE6 /* Clear channel interrupt clear */ +#define TCS37727_SF_PCICLR 0xE7 /* Proximity & Clear channel inter. clear */ + +/* TCS37727 Enable Register */ +#define TCS37727_ENABLE_PIEN (1 << 5) /* Proximity interrupt enable */ +#define TCS37727_ENABLE_AIEN (1 << 4) /* Clear channel interrupt enable */ +#define TCS37727_ENABLE_WEN (1 << 3) /* Wait enable */ +#define TCS37727_ENABLE_PEN (1 << 2) /* Proximity enable */ +#define TCS37727_ENABLE_AEN (1 << 1) /* RGBC enable, actives 2-channel ADC */ +#define TCS37727_ENABLE_PON (1 << 0) /* Power ON */ + +/* TCS37727 Control Register */ +#define TCS37727_CONTROL_PDRIVE_100 0x00 /* 100 mA LED Drive Strength */ +#define TCS37727_CONTROL_PDRIVE_50 0x04 /* 50 mA LED Drive Strength */ +#define TCS37727_CONTROL_PDRIVE_25 0x08 /* 25 mA LED Drive Strength */ +#define TCS37727_CONTROL_PDRIVE_12 0x0C /* 12.5 mA LED Drive Strength */ +#define TCS37727_CONTROL_PDRIVE_MASK 0x0C /* PDRIVE Mask */ +#define TCS37727_CONTROL_AGAIN_1 0x00 /* 1 × gain RGBC Gain Value */ +#define TCS37727_CONTROL_AGAIN_4 0x01 /* 4 × gain RGBC Gain Value */ +#define TCS37727_CONTROL_AGAIN_16 0x02 /* 16 × gain RGBC Gain Value */ +#define TCS37727_CONTROL_AGAIN_60 0x03 /* 60 × gain RGBC Gain Value */ +#define TCS37727_CONTROL_AGAIN_MASK 0x03 /* AGAIN Mask */ + +/* TCS37727 ATIME register values */ +#define TCS37727_ATIME_MIN 2400 /* 2.4ms integr. time, max count 1024 */ +#define TCS37727_ATIME_MAX 614000 /* 614ms integr. time, max count 0xffff */ + +#define TCS37727_ATIME_TO_REG(val) (256 - (uint8_t)((val) / 2400)) +#define TCS37727_ATIME_TO_US(reg) ((256 - (uint8_t)(reg)) * 2400) + +/* Coefficients for Lux and CT Equations (DN40) */ +/* Coefficients in integer format, multiplied by 1000 */ +#define DGF_IF 310 +#define R_COEF_IF 136 +#define G_COEF_IF 1000 +#define B_COEF_IF -444 +#define CT_COEF_IF 3810 +#define CT_OFFSET_IF 1391 + +namespace upm { + +typedef struct { + uint32_t red; /**< IR compensated channels red */ + uint32_t green; /**< IR compensated channels green */ + uint32_t blue; /**< IR compensated channels blue */ + uint32_t clear; /**< channels clear */ + uint32_t lux; /**< Lux */ + uint32_t ct; /**< Color temperature */ +} tcs37727_data_t; + +/** + * @brief TCS37727 Color Light-To-Digital Converter + * @defgroup tcs37727 libupm-tcs37727 + * @ingroup ams i2c color + */ + +/** + * @library tcs37727 + * @sensor tcs37727 + * @comname TCS37727 Color Light-To-Digital Converter + * @type color + * @man ams + * @web http://ams.com/eng/Products/Light-Sensors + * @con i2c + * + * @brief API for the TCS37727 Color Light-To-Digital Converter + * + * Description in web-link above: + * The TCS3772 device family provides red, green, blue, and clear (RGBC) light + * sensing and, when coupled with an external IR LED, proximity detection. + * These devices detect light intensity under a variety of lighting conditions + * and through a variety of attenuation materials, including dark glass. The + * proximity detection feature allows a large dynamic range of operation for + * accurate short distance detection, such as in a cell phone, for detecting + * when the user positions the phone close to their ear. An internal state + * machine provides the ability to put the device into a low power state in + * between proximity and RGBC measurements providing very low average power + * consumption. + * + * @snippet tcs37727.cxx Interesting + */ +class TCS37727 { + public: + /** + * + * Instantiates an TCS37727 object + * Settings: Gain 4x, Proximity Detection off + * + * @param bus Number of the used bus + * @param atime_us RGBC integration time + * @param devAddr Address of the used I2C device + */ + TCS37727 (int bus, int atime_us=TCS37727_ATIME_DEFAULT, + int devAddr=TCS37727_I2C_ADDRESS); + + /** + * Check device_id of sensor + * + * @return 0 on success + * -1 on error + */ + int checkID(void); + + /** + * Set active mode, this enables periodic RGBC measurements + * + * @return 0 on success + * -1 on error + */ + int setActive(void); + + /** + * Set standby mode, this disables periodic RGBC measurements + * Also turns off the sensor when proximity measurement is disabled + * + * @return 0 on success + * -1 on error + */ + int setStandby(void); + + /** + * + */ + uint8_t trimGain(int rawc); + + /** + * Read out data of regs and call further function + * Also saves converted values to variables + * + * @return 0 on success + * -1 on error + */ + int sampleData(void); + + /** + * Get the calculated channel red color + * + * @param bSampleData Flag to read sensor + * @return The channel red color on success + * 999 on error + */ + uint32_t getChannelRed(int bSampleData = 0); + + /** + * Get the calculated channel green color + * + * @param bSampleData Flag to read sensor + * @return The channel green color on success + * 999 on error + */ + uint32_t getChannelGreen(int bSampleData = 0); + + /** + * Get the calculated channel blue color + * + * @param bSampleData Flag to read sensor + * @return The channel blue color on success + * 999 on error + */ + uint32_t getChannelBlue(int bSampleData = 0); + + /** + * Get the calculated channel clear color + * + * @param bSampleData Flag to read sensor + * @return The channel clear color on success + * 999 on error + */ + uint32_t getChannelClear(int bSampleData = 0); + + /** + * Get the calculated lux value + * + * @param bSampleData Flag to read sensor + * @return The lux value on success + * 999 on error + */ + uint32_t getLux(int bSampleData = 0); + + /** + * Get the calculated color temperature + * + * @param bSampleData Flag to read sensor + * @return The color temperature on success + * 999 on error + */ + uint32_t getColorTemperature(int bSampleData = 0); + + /** + * Get calculated sensor values + * + * @param data Calculated sensor values + * @param bSampleData Flag to read sensor + * @return 0 on success + * -1 on error + */ + int getData(tcs37727_data_t* data, int bSampleData = 0); + + private: + + std::string m_name; + + int m_controlAddr; + int m_bus; + mraa::I2c m_i2ControlCtx; + + int s_atime_us; /* atime value conveted to microseconds */ + int s_again; /* amount of gain */ + + tcs37727_data_t s_data[1]; + }; + +}