Adding tsl2561 driver
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/674aa7d4 Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/674aa7d4 Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/674aa7d4 Branch: refs/heads/develop Commit: 674aa7d47a4a1ed6d30d0f5d02d0b9ffa52011cf Parents: fbbad56 Author: Vipul Rahane <[email protected]> Authored: Wed Jan 25 17:56:30 2017 -0800 Committer: Vipul Rahane <[email protected]> Committed: Wed Jan 25 17:56:30 2017 -0800 ---------------------------------------------------------------------- .../sensors/tsl2561/include/tsl2561/tsl2561.h | 186 ++++++++ hw/drivers/sensors/tsl2561/pkg.yml | 49 ++ hw/drivers/sensors/tsl2561/src/tsl2561.c | 464 +++++++++++++++++++ hw/drivers/sensors/tsl2561/src/tsl2561_priv.h | 90 ++++ hw/drivers/sensors/tsl2561/src/tsl2561_shell.c | 426 +++++++++++++++++ hw/drivers/sensors/tsl2561/syscfg.yml | 41 ++ 6 files changed, 1256 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/674aa7d4/hw/drivers/sensors/tsl2561/include/tsl2561/tsl2561.h ---------------------------------------------------------------------- diff --git a/hw/drivers/sensors/tsl2561/include/tsl2561/tsl2561.h b/hw/drivers/sensors/tsl2561/include/tsl2561/tsl2561.h new file mode 100644 index 0000000..03320e8 --- /dev/null +++ b/hw/drivers/sensors/tsl2561/include/tsl2561/tsl2561.h @@ -0,0 +1,186 @@ +/**************************************************************************/ +/*! + @file tsl2561.h + @author ktown (Adafruit Industries) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2016, Adafruit Industries (adafruit.com) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/**************************************************************************/ + +#ifndef __ADAFRUIT_TSL2561_H__ +#define __ADAFRUIT_TSL2561_H__ + +#include <os/os.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* +struct tsl2561_i2c { + uint8_t i2c_num; + uint8_t i2c_addr; +}; + +struct tsl2561_cfg { + uint8_t gain; + uint8_t integration_time; + uint8_t enabled; +}; + +struct tsl2561_dev { + struct tsl2561_i2c i2c; + struct tsl2561_cfg cfg; +}; +*/ + +/** + * Initialize the tsl2561. This function is normally called by sysinit. + * + * @param dev Pointer to the tsl2561_dev device descriptor + */ +void tsl2561_init(void); + +/** + * Enable or disables the sensor to save power + * + * @param state 1 to enable the sensor, 0 to disable it + * + * @return 0 on success, and non-zero error code on failure + */ +int tsl2561_enable(uint8_t state); + +/** + * Gets the current 'enabled' state for the IC + * + * @return 1 if the IC is enabled, otherwise 0 + */ +uint8_t tsl2561_get_enable(void); + +/** + * Gets a new data sample from the light sensor. + * + * @param broadband The full (visible + ir) sensor output + * @param ir The ir sensor output + * + * @return 0 on success, and non-zero error code on failure + */ +int tsl2561_get_data(uint16_t *broadband, uint16_t *ir); + +/** + * Sets the integration time used when sampling light values. + * + * @param int_time The integration time which can be one of: + * - 0x00: 13ms + * - 0x01: 101ms + * - 0x02: 402ms + * + * @return 0 on success, and non-zero error code on failure + */ +int tsl2561_set_integration_time(uint8_t int_time); + +/** + * Gets the current integration time used when sampling light values. + * + * @return The integration time which can be one of: + * - 0x00: 13ms + * - 0x01: 101ms + * - 0x02: 402ms + */ +uint8_t tsl2561_get_integration_time(void); + +/** + * Sets the gain increment used when sampling light values. + * + * @param gain The gain increment which can be one of: + * - 0x00: 1x (no gain) + * - 0x10: 16x gain + * + * @return 0 on success, and non-zero error code on failure + */ +int tsl2561_set_gain(uint8_t gain); + +/** + * Gets the current gain increment used when sampling light values. + * + * @return The gain increment which can be one of: + * - 0x00: 1x (no gain) + * - 0x10: 16x gain + */ +uint8_t tsl2561_get_gain(void); + +/** + * Sets the upper and lower interrupt thresholds + * + * @param rate Sets the rate of interrupts to the host processor: + * - 0 Every ADC cycle generates interrupt + * - 1 Any value outside of threshold range + * - 2 2 integration time periods out of range + * - 3 3 integration time periods out of range + * - 4 4 integration time periods out of range + * - 5 5 integration time periods out of range + * - 6 6 integration time periods out of range + * - 7 7 integration time periods out of range + * - 8 8 integration time periods out of range + * - 9 9 integration time periods out of range + * - 10 10 integration time periods out of range + * - 11 11 integration time periods out of range + * - 12 12 integration time periods out of range + * - 13 13 integration time periods out of range + * - 14 14 integration time periods out of range + * - 15 15 integration time periods out of range + * @param lower The lower threshold + * @param upper The upper threshold + * + * @return 0 on success, and non-zero error code on failure + */ +int tsl2561_setup_interrupt(uint8_t rate, uint16_t lower, uint16_t upper); + +/** + * Enables or disables the HW interrupt on the device + * + * @param enable 0 to disable the interrupt, 1 to enablee it + * + * @return 0 on success, and non-zero error code on failure + */ +int tsl2561_enable_interrupt(uint8_t enable); + +/** + * Clear an asserted interrupt on the device + * + * @return 0 on success, and non-zero error code on failure + */ +int tsl2561_clear_interrupt(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __ADAFRUIT_TSL2561_H__ */ http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/674aa7d4/hw/drivers/sensors/tsl2561/pkg.yml ---------------------------------------------------------------------- diff --git a/hw/drivers/sensors/tsl2561/pkg.yml b/hw/drivers/sensors/tsl2561/pkg.yml new file mode 100644 index 0000000..e7d0ffd --- /dev/null +++ b/hw/drivers/sensors/tsl2561/pkg.yml @@ -0,0 +1,49 @@ +# The BSD License (BSD) +# +# Copyright (c) 2016 Adafruit Industries +# +# 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. + +pkg.name: hw/drivers/sensors/tsl2561 +pkg.description: Driver for the TSL2561 light to digital sensor +pkg.author: "Adafruit <[email protected]>" +pkg.homepage: "http://www.adafruit.com/" +pkg.keywords: + - adafruit + - tsl2561 + - i2c + - sensor + +pkg.deps: + - "@apache-mynewt-core/kernel/os" + - "@apache-mynewt-core/hw/hal" + +pkg.deps.TSL2561_CLI: + - "@apache-mynewt-core/sys/console/full" + - "@apache-mynewt-core/sys/shell" + - "@apache-mynewt-core/sys/sysinit" + +pkg.deps.TSL2561_LOG: + - "@apache-mynewt-core/sys/log" + +pkg.deps.TSL2561_STATS: + - "@apache-mynewt-core/sys/stats" + +pkg.init_function: tsl2561_init +pkg.init_stage: 6 http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/674aa7d4/hw/drivers/sensors/tsl2561/src/tsl2561.c ---------------------------------------------------------------------- diff --git a/hw/drivers/sensors/tsl2561/src/tsl2561.c b/hw/drivers/sensors/tsl2561/src/tsl2561.c new file mode 100644 index 0000000..037ccf8 --- /dev/null +++ b/hw/drivers/sensors/tsl2561/src/tsl2561.c @@ -0,0 +1,464 @@ +/*****************************************************************************/ +/*! + @file tsl2561.c + @author ktown (Adafruit Industries) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2016, Adafruit Industries (adafruit.com) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*****************************************************************************/ + +#include <assert.h> +#include <stdio.h> +#include <errno.h> +#include "sysinit/sysinit.h" +#include "hal/hal_i2c.h" +#include "tsl2561/tsl2561.h" +#include "tsl2561_priv.h" + +#if MYNEWT_VAL(TSL2561_LOG) +#include "log/log.h" +#endif + +#if MYNEWT_VAL(TSL2561_STATS) +#include "stats/stats.h" +#endif + +/* ToDo: Add timer based polling in bg and data ready callback (os_event?) */ +/* ToDo: Move values to struct incl. address to allow multiple instances */ + +static uint8_t g_tsl2561_gain; +static uint8_t g_tsl2561_integration_time; +static uint8_t g_tsl2561_enabled; + +#if MYNEWT_VAL(TSL2561_STATS) +/* Define the stats section and records */ +STATS_SECT_START(tsl2561_stat_section) + STATS_SECT_ENTRY(samples_13ms) + STATS_SECT_ENTRY(samples_101ms) + STATS_SECT_ENTRY(samples_402ms) + STATS_SECT_ENTRY(ints_cleared) + STATS_SECT_ENTRY(errors) +STATS_SECT_END + +/* Define stat names for querying */ +STATS_NAME_START(tsl2561_stat_section) + STATS_NAME(tsl2561_stat_section, samples_13ms) + STATS_NAME(tsl2561_stat_section, samples_101ms) + STATS_NAME(tsl2561_stat_section, samples_402ms) + STATS_NAME(tsl2561_stat_section, ints_cleared) + STATS_NAME(tsl2561_stat_section, errors) +STATS_NAME_END(tsl2561_stat_section) + +/* Global variable used to hold stats data */ +STATS_SECT_DECL(tsl2561_stat_section) g_tsl2561stats; +#endif + +#if MYNEWT_VAL(TSL2561_LOG) +#define LOG_MODULE_TSL2561 (2561) +#define TSL2561_INFO(...) LOG_INFO(&_log, LOG_MODULE_TSL2561, __VA_ARGS__) +#define TSL2561_ERR(...) LOG_ERROR(&_log, LOG_MODULE_TSL2561, __VA_ARGS__) +static struct log _log; +#else +#define TSL2561_INFO(...) +#define TSL2561_ERR(...) +#endif + +int +tsl2561_write8(uint8_t reg, uint32_t value) +{ + int rc; + uint8_t payload[2] = { reg, value & 0xFF }; + + struct hal_i2c_master_data data_struct = { + .address = MYNEWT_VAL(TSL2561_I2CADDR), + .len = 2, + .buffer = payload + }; + + rc = hal_i2c_master_write(MYNEWT_VAL(TSL2561_I2CBUS), &data_struct, + OS_TICKS_PER_SEC / 10, 1); + if (rc) { + TSL2561_ERR("Failed to write @0x%02X with value 0x%02X\n", reg, value); + } + + return rc; +} + +int +tsl2561_write16(uint8_t reg, uint16_t value) +{ + int rc; + uint8_t payload[3] = { reg, value & 0xFF, (value >> 8) & 0xFF }; + + struct hal_i2c_master_data data_struct = { + .address = MYNEWT_VAL(TSL2561_I2CADDR), + .len = 3, + .buffer = payload + }; + + rc = hal_i2c_master_write(MYNEWT_VAL(TSL2561_I2CBUS), &data_struct, + OS_TICKS_PER_SEC / 10, 1); + if (rc) { + TSL2561_ERR("Failed to write @0x%02X with value 0x%02X 0x%02X\n", + reg, payload[0], payload[1]); + } + + return rc; +} + +int +tsl2561_read8(uint8_t reg, uint8_t *value) +{ + int rc; + uint8_t payload; + + struct hal_i2c_master_data data_struct = { + .address = MYNEWT_VAL(TSL2561_I2CADDR), + .len = 1, + .buffer = &payload + }; + + /* Register write */ + payload = reg; + rc = hal_i2c_master_write(MYNEWT_VAL(TSL2561_I2CBUS), &data_struct, + OS_TICKS_PER_SEC / 10, 1); + if (rc) { + TSL2561_ERR("Failed to address sensor\n"); + goto error; + } + + /* Read one byte back */ + payload = 0; + rc = hal_i2c_master_read(MYNEWT_VAL(TSL2561_I2CBUS), &data_struct, + OS_TICKS_PER_SEC / 10, 1); + *value = payload; + if (rc) { + TSL2561_ERR("Failed to read @0x%02X\n", reg); + } + +error: + return rc; +} + +int +tsl2561_read16(uint8_t reg, uint16_t *value) +{ + int rc; + uint8_t payload[2] = { reg, 0 }; + + struct hal_i2c_master_data data_struct = { + .address = MYNEWT_VAL(TSL2561_I2CADDR), + .len = 1, + .buffer = payload + }; + + /* Register write */ + rc = hal_i2c_master_write(MYNEWT_VAL(TSL2561_I2CBUS), &data_struct, + OS_TICKS_PER_SEC / 10, 1); + if (rc) { + TSL2561_ERR("Failed to address sensor\n"); + goto error; + } + + /* Read two bytes back */ + memset(payload, 0, 2); + data_struct.len = 2; + rc = hal_i2c_master_read(MYNEWT_VAL(TSL2561_I2CBUS), &data_struct, + OS_TICKS_PER_SEC / 10, 1); + *value = (uint16_t)payload[0] | ((uint16_t)payload[1] << 8); + if (rc) { + TSL2561_ERR("Failed to read @0x%02X\n", reg); + goto error; + } + + /* ToDo: Log raw reads */ + // console_printf("0x%04X\n", (uint16_t)payload[0] | ((uint16_t)payload[1] << 8)); + +error: + return rc; +} + +int +tsl2561_enable(uint8_t state) +{ + int rc; + + /* Enable the device by setting the control bit to 0x03 */ + rc = tsl2561_write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, + state ? TSL2561_CONTROL_POWERON : + TSL2561_CONTROL_POWEROFF); + if (!rc) { + g_tsl2561_enabled = state ? 1 : 0; + } + + return rc; +} + +uint8_t +tsl2561_get_enable (void) +{ + return g_tsl2561_enabled; +} + +int +tsl2561_get_data(uint16_t *broadband, uint16_t *ir) +{ + int rc; + int delay_ticks; + + /* Wait integration time ms before getting a data sample */ + switch (g_tsl2561_integration_time) { + case TSL2561_INTEGRATIONTIME_13MS: + delay_ticks = 14 * OS_TICKS_PER_SEC / 1000; + break; + case TSL2561_INTEGRATIONTIME_101MS: + delay_ticks = 102 * OS_TICKS_PER_SEC / 1000; + break; + case TSL2561_INTEGRATIONTIME_402MS: + default: + delay_ticks = 403 * OS_TICKS_PER_SEC / 1000; + break; + } + os_time_delay(delay_ticks); + + *broadband = *ir = 0; + rc = tsl2561_read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW, + broadband); + if (rc) { + goto error; + } + rc = tsl2561_read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW, + ir); + if (rc) { + goto error; + } + +#if MYNEWT_VAL(TSL2561_STATS) + switch (g_tsl2561_integration_time) { + case TSL2561_INTEGRATIONTIME_13MS: + STATS_INC(g_tsl2561stats, samples_13ms); + break; + case TSL2561_INTEGRATIONTIME_101MS: + STATS_INC(g_tsl2561stats, samples_101ms); + break; + case TSL2561_INTEGRATIONTIME_402MS: + STATS_INC(g_tsl2561stats, samples_402ms); + default: + break; + } +#endif + +error: + return rc; +} + +int +tsl2561_set_integration_time(uint8_t int_time) +{ + int rc; + + rc = tsl2561_write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, + g_tsl2561_integration_time | g_tsl2561_gain); + if (rc) { + goto error; + } + + g_tsl2561_integration_time = int_time; + +error: + return rc; +} + +uint8_t +tsl2561_get_integration_time(void) +{ + return g_tsl2561_integration_time; +} + +int +tsl2561_set_gain(uint8_t gain) +{ + int rc; + + if ((gain != TSL2561_GAIN_1X) && (gain != TSL2561_GAIN_16X)) { + TSL2561_ERR("Invalid gain value\n"); + rc = EINVAL; + goto error; + } + + rc = tsl2561_write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, + g_tsl2561_integration_time | gain); + if (rc) { + goto error; + } + + g_tsl2561_gain = gain; + +error: + return rc; +} + +uint8_t +tsl2561_get_gain(void) +{ + return g_tsl2561_gain; +} + +int tsl2561_setup_interrupt (uint8_t rate, uint16_t lower, uint16_t upper) +{ + int rc; + uint8_t intval; + + /* Set lower threshold */ + rc = tsl2561_write16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_THRESHHOLDL_LOW, + lower); + if (rc) { + goto error; + } + + /* Set upper threshold */ + rc = tsl2561_write16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_THRESHHOLDH_LOW, + upper); + if (rc) { + goto error; + } + + /* Set rate */ + rc = tsl2561_read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_INTERRUPT, &intval); + if (rc) { + goto error; + } + /* Maintain the INTR Control Select bits */ + rate = (intval & 0xF0) | (rate & 0xF); + rc = tsl2561_write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_INTERRUPT, + rate); + if (rc) { + goto error; + } + +error: + return rc; +} + +int tsl2561_enable_interrupt (uint8_t enable) +{ + int rc; + uint8_t persist_val; + + if (enable > 1) { + TSL2561_ERR("Invalid value 0x%02X in tsl2561_enable_interrupt\n", + enable); + rc = EINVAL; + goto error; + } + + /* Read the current value to maintain PERSIST state */ + rc = tsl2561_read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_INTERRUPT, &persist_val); + if (rc) { + goto error; + } + + /* Enable (1) or disable (0) level interrupts */ + rc = tsl2561_write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_INTERRUPT, + ((enable & 0x01) << 4) | (persist_val & 0x0F) ); + if (rc) { + goto error; + } + +error: + return rc; +} + +int tsl2561_clear_interrupt (void) +{ + int rc; + uint8_t payload = { TSL2561_COMMAND_BIT | TSL2561_CLEAR_BIT }; + + struct hal_i2c_master_data data_struct = { + .address = MYNEWT_VAL(TSL2561_I2CADDR), + .len = 1, + .buffer = &payload + }; + + /* To clear the interrupt set the CLEAR bit in the COMMAND register */ + rc = hal_i2c_master_write(MYNEWT_VAL(TSL2561_I2CBUS), &data_struct, + OS_TICKS_PER_SEC / 10, 1); + if (rc) { + goto error; + } + +#if MYNEWT_VAL(TSL2561_STATS) + STATS_INC(g_tsl2561stats, ints_cleared); +#endif + +error: + return rc; +} + +void +tsl2561_init(void) +{ + int rc; + +#if !MYNEWT_VAL(TSL2561_TASK) + return; +#endif + +#if MYNEWT_VAL(TSL2561_LOG) + log_register("tsl2561", &_log, &log_console_handler, NULL, LOG_SYSLEVEL); +#endif + +#if MYNEWT_VAL(TSL2561_CLI) + rc = tsl2561_shell_init(); + SYSINIT_PANIC_ASSERT(rc == 0); +#endif + +#if MYNEWT_VAL(TSL2561_STATS) + /* Initialise the stats entry */ + rc = stats_init( + STATS_HDR(g_tsl2561stats), + STATS_SIZE_INIT_PARMS(g_tsl2561stats, STATS_SIZE_32), + STATS_NAME_INIT_PARMS(tsl2561_stat_section)); + SYSINIT_PANIC_ASSERT(rc == 0); + /* Register the entry with the stats registry */ + rc = stats_register("tsl2561", STATS_HDR(g_tsl2561stats)); + SYSINIT_PANIC_ASSERT(rc == 0); +#endif + + /* Enable the device by default */ + rc = tsl2561_enable(1); + SYSINIT_PANIC_ASSERT(rc == 0); + + rc = tsl2561_set_gain(TSL2561_GAIN_1X); + SYSINIT_PANIC_ASSERT(rc == 0); + + rc = tsl2561_set_integration_time(TSL2561_INTEGRATIONTIME_13MS); + SYSINIT_PANIC_ASSERT(rc == 0); +} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/674aa7d4/hw/drivers/sensors/tsl2561/src/tsl2561_priv.h ---------------------------------------------------------------------- diff --git a/hw/drivers/sensors/tsl2561/src/tsl2561_priv.h b/hw/drivers/sensors/tsl2561/src/tsl2561_priv.h new file mode 100644 index 0000000..5ead614 --- /dev/null +++ b/hw/drivers/sensors/tsl2561/src/tsl2561_priv.h @@ -0,0 +1,90 @@ +/*****************************************************************************/ +/*! + @file tsl2561_priv.h + @author ktown (Adafruit Industries) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2016, Adafruit Industries (adafruit.com) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*****************************************************************************/ +#ifndef __ADAFRUIT_TSL2561_PRIV_H__ +#define __ADAFRUIT_TSL2561_PRIV_H__ + +#define TSL2561_REGISTER_CONTROL (0x00) +#define TSL2561_REGISTER_TIMING (0x01) +#define TSL2561_REGISTER_THRESHHOLDL_LOW (0x02) +#define TSL2561_REGISTER_THRESHHOLDL_HIGH (0x03) +#define TSL2561_REGISTER_THRESHHOLDH_LOW (0x04) +#define TSL2561_REGISTER_THRESHHOLDH_HIGH (0x05) +#define TSL2561_REGISTER_INTERRUPT (0x06) +#define TSL2561_REGISTER_ID (0x0A) +#define TSL2561_REGISTER_CHAN0_LOW (0x0C) +#define TSL2561_REGISTER_CHAN0_HIGH (0x0D) +#define TSL2561_REGISTER_CHAN1_LOW (0x0E) +#define TSL2561_REGISTER_CHAN1_HIGH (0x0F) + +#define TSL2561_CONTROL_POWERON (0x03) +#define TSL2561_CONTROL_POWEROFF (0x00) + +#define TSL2561_INTEGRATIONTIME_13MS (0x00) /* 13.7ms */ +#define TSL2561_INTEGRATIONTIME_101MS (0x01) /* 101ms */ +#define TSL2561_INTEGRATIONTIME_402MS (0x02) /* 402ms */ + +#define TSL2561_GAIN_1X (0x00) /* No gain */ +#define TSL2561_GAIN_16X (0x10) /* 16x gain */ + +#define TSL2561_COMMAND_BIT (0x80) /* Must be 1 */ +#define TSL2561_CLEAR_BIT (0x40) /* 1=Clear any pending int */ +#define TSL2561_WORD_BIT (0x20) /* 1=Read/write word */ +#define TSL2561_BLOCK_BIT (0x10) /* 1=Use block read/write */ + +#define TSL2561_CONTROL_POWERON (0x03) +#define TSL2561_CONTROL_POWEROFF (0x00) + +#ifdef __cplusplus +extern "C" { +#endif + +/* tsl2561.c */ +int tsl2561_write8(uint8_t reg, uint32_t value); +int tsl2561_write16(uint8_t reg, uint16_t value); +int tsl2561_read8(uint8_t reg, uint8_t *value); +int tsl2561_read16(uint8_t reg, uint16_t *value); + +/* tsl2561_shell.c */ +#if MYNEWT_VAL(TSL2561_CLI) +int tsl2561_shell_init(void); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* __ADAFRUIT_TSL2561_PRIV_H_ */ http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/674aa7d4/hw/drivers/sensors/tsl2561/src/tsl2561_shell.c ---------------------------------------------------------------------- diff --git a/hw/drivers/sensors/tsl2561/src/tsl2561_shell.c b/hw/drivers/sensors/tsl2561/src/tsl2561_shell.c new file mode 100644 index 0000000..c485261 --- /dev/null +++ b/hw/drivers/sensors/tsl2561/src/tsl2561_shell.c @@ -0,0 +1,426 @@ +/**************************************************************************/ +/*! + @file tsl2561_shell.c + @author ktown (Adafruit Industries) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2016, Adafruit Industries (adafruit.com) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/**************************************************************************/ + +#include <string.h> +#include <errno.h> +#include "sysinit/sysinit.h" +#include "console/console.h" +#include "shell/shell.h" +#include "hal/hal_gpio.h" +#include "tsl2561/tsl2561.h" +#include "tsl2561_priv.h" + +#if MYNEWT_VAL(TSL2561_CLI) +static int tsl2561_shell_cmd(int argc, char **argv); + +static struct shell_cmd tsl2561_shell_cmd_struct = { + .sc_cmd = "tsl2561", + .sc_cmd_func = tsl2561_shell_cmd +}; + +/* +static int +tsl2561_shell_err_too_few_args(char *cmd_name) +{ + console_printf("Error: too few arguments for command \"%s\"\n", + cmd_name); + return -1; +} +*/ + +static int +tsl2561_shell_stol(char *param_val, long min, long max, long *output) +{ + char *endptr; + long lval; + + lval = strtol(param_val, &endptr, 10); /* Base 10 */ + if (param_val != '\0' && *endptr == '\0' && + lval >= min && lval <= max) { + *output = lval; + } else { + return EINVAL; + } + + return 0; +} + +static int +tsl2561_shell_err_too_many_args(char *cmd_name) +{ + console_printf("Error: too many arguments for command \"%s\"\n", + cmd_name); + return EINVAL; +} + +static int +tsl2561_shell_err_unknown_arg(char *cmd_name) +{ + console_printf("Error: unknown argument \"%s\"\n", + cmd_name); + return EINVAL; +} + +static int +tsl2561_shell_err_invalid_arg(char *cmd_name) +{ + console_printf("Error: invalid argument \"%s\"\n", + cmd_name); + return EINVAL; +} + +static int +tsl2561_shell_help(void) +{ + console_printf("%s cmd [flags...]\n", tsl2561_shell_cmd_struct.sc_cmd); + console_printf("cmd:\n"); + console_printf("\tr [n_samples]\n"); + console_printf("\tgain [1|16]\n"); + console_printf("\ttime [13|101|402]\n"); + console_printf("\ten [0|1]\n"); + console_printf("\tint pin [p_num(0..255)]\n"); + console_printf("\tint on|off|clr\n"); + console_printf("\tint set [rate(0..15)] [lower(0..65535)] [upper(0..65535)]\n"); + console_printf("\tdump\n"); + + return 0; +} + +static int +tsl2561_shell_cmd_read(int argc, char **argv) +{ + uint16_t full; + uint16_t ir; + uint16_t samples = 1; + long val; + int rc; + + if (argc > 3) { + return tsl2561_shell_err_too_many_args(argv[1]); + } + + /* Check if more than one sample requested */ + if (argc == 3) { + if (tsl2561_shell_stol(argv[2], 1, UINT16_MAX, &val)) { + return tsl2561_shell_err_invalid_arg(argv[2]); + } + samples = (uint16_t)val; + } + + while(samples--) { + rc = tsl2561_get_data(&full, &ir); + if (rc != 0) { + console_printf("Read failed: %d\n", rc); + return rc; + } + console_printf("Full: %u\n", full); + console_printf("IR: %u\n", ir); + } + + return 0; +} + +static int +tsl2561_shell_cmd_gain(int argc, char **argv) +{ + long val; + + if (argc > 3) { + return tsl2561_shell_err_too_many_args(argv[1]); + } + + /* Display the gain */ + if (argc == 2) { + uint8_t gain = tsl2561_get_gain(); + console_printf("%u\n", gain ? 16u : 1u); + } + + /* Update the gain */ + if (argc == 3) { + if (tsl2561_shell_stol(argv[2], 1, 16, &val)) { + return tsl2561_shell_err_invalid_arg(argv[2]); + } + /* Make sure gain is 1 ot 16 */ + if ((val != 1) && (val != 16)) { + return tsl2561_shell_err_invalid_arg(argv[2]); + } + tsl2561_set_gain(val ? TSL2561_GAIN_16X : TSL2561_GAIN_1X); + } + + return 0; +} + +static int +tsl2561_shell_cmd_time(int argc, char **argv) +{ + uint8_t time; + long val; + + if (argc > 3) { + return tsl2561_shell_err_too_many_args(argv[1]); + } + + /* Display the integration time */ + if (argc == 2) { + time = tsl2561_get_integration_time(); + switch (time) { + case TSL2561_INTEGRATIONTIME_13MS: + console_printf("13\n"); + break; + case TSL2561_INTEGRATIONTIME_101MS: + console_printf("101\n"); + break; + case TSL2561_INTEGRATIONTIME_402MS: + console_printf("402\n"); + break; + } + } + + /* Set the integration time */ + if (argc == 3) { + if (tsl2561_shell_stol(argv[2], 13, 402, &val)) { + return tsl2561_shell_err_invalid_arg(argv[2]); + } + /* Make sure val is 13, 102 or 402 */ + if ((val != 13) && (val != 101) && (val != 402)) { + return tsl2561_shell_err_invalid_arg(argv[2]); + } + switch(val) { + case 13: + tsl2561_set_integration_time(TSL2561_INTEGRATIONTIME_13MS); + break; + case 101: + tsl2561_set_integration_time(TSL2561_INTEGRATIONTIME_101MS); + break; + case 402: + tsl2561_set_integration_time(TSL2561_INTEGRATIONTIME_402MS); + break; + } + } + + return 0; +} + +static int +tsl2561_shell_cmd_int(int argc, char **argv) +{ + int rc; + int pin; + long val; + uint8_t rate; + uint16_t lower; + uint16_t upper; + + if (argc > 6) { + return tsl2561_shell_err_too_many_args(argv[1]); + } + + if (argc == 2) { + console_printf("ToDo: Display int details\n"); + return 0; + } + + /* Enable the interrupt */ + if (argc == 3 && strcmp(argv[2], "on") == 0) { + return tsl2561_enable_interrupt(1); + } + + /* Disable the interrupt */ + if (argc == 3 && strcmp(argv[2], "off") == 0) { + return tsl2561_enable_interrupt(0); + } + + /* Clear the interrupt on 'clr' */ + if (argc == 3 && strcmp(argv[2], "clr") == 0) { + return tsl2561_clear_interrupt(); + } + + /* Configure the interrupt on 'set' */ + if (argc == 6 && strcmp(argv[2], "set") == 0) { + /* Get rate */ + if (tsl2561_shell_stol(argv[3], 0, 15, &val)) { + return tsl2561_shell_err_invalid_arg(argv[3]); + } + rate = (uint8_t)val; + /* Get lower threshold */ + if (tsl2561_shell_stol(argv[4], 0, UINT16_MAX, &val)) { + return tsl2561_shell_err_invalid_arg(argv[4]); + } + lower = (uint16_t)val; + /* Get upper threshold */ + if (tsl2561_shell_stol(argv[5], 0, UINT16_MAX, &val)) { + return tsl2561_shell_err_invalid_arg(argv[5]); + } + upper = (uint16_t)val; + /* Set the values */ + rc = tsl2561_setup_interrupt(rate, lower, upper); + console_printf("Configured interrupt as:\n"); + console_printf("\trate: %u\n", rate); + console_printf("\tlower: %u\n", lower); + console_printf("\tupper: %u\n", upper); + return rc; + } + + /* Setup INT pin on 'pin' */ + if (argc == 4 && strcmp(argv[2], "pin") == 0) { + /* Get the pin number */ + if (tsl2561_shell_stol(argv[3], 0, 0xFF, &val)) { + return tsl2561_shell_err_invalid_arg(argv[3]); + } + pin = (int)val; + /* INT is open drain, pullup is required */ + rc = hal_gpio_init_in(pin, HAL_GPIO_PULL_UP); + assert(rc == 0); + console_printf("Set pin \"%d\" to INPUT with pull up enabled\n", pin); + return 0; + } + + /* Unknown command */ + return tsl2561_shell_err_invalid_arg(argv[2]); +} + +static int +tsl2561_shell_cmd_en(int argc, char **argv) +{ + char *endptr; + long lval; + + if (argc > 3) { + return tsl2561_shell_err_too_many_args(argv[1]); + } + + /* Display current enable state */ + if (argc == 2) { + console_printf("%u\n", tsl2561_get_enable()); + } + + /* Update the enable state */ + if (argc == 3) { + lval = strtol(argv[2], &endptr, 10); /* Base 10 */ + if (argv[2] != '\0' && *endptr == '\0' && + lval >= 0 && lval <= 1) { + tsl2561_enable(lval); + } else { + return tsl2561_shell_err_invalid_arg(argv[2]); + } + } + + return 0; +} + +static int +tsl2561_shell_cmd_dump(int argc, char **argv) +{ + uint8_t val; + + if (argc > 3) { + return tsl2561_shell_err_too_many_args(argv[1]); + } + + /* Dump all the register values for debug purposes */ + val = 0; + assert(0 == tsl2561_read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, &val)); + console_printf("0x%02X (CONTROL): 0x%02X\n", TSL2561_REGISTER_CONTROL, val); + assert(0 == tsl2561_read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, &val)); + console_printf("0x%02X (TIMING): 0x%02X\n", TSL2561_REGISTER_TIMING, val); + assert(0 == tsl2561_read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_THRESHHOLDL_LOW, &val)); + console_printf("0x%02X (THRLL): 0x%02X\n", TSL2561_REGISTER_THRESHHOLDL_LOW, val); + assert(0 == tsl2561_read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_THRESHHOLDL_HIGH, &val)); + console_printf("0x%02X (THRLH): 0x%02X\n", TSL2561_REGISTER_THRESHHOLDL_HIGH, val); + assert(0 == tsl2561_read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_THRESHHOLDH_LOW, &val)); + console_printf("0x%02X (THRHL): 0x%02X\n", TSL2561_REGISTER_THRESHHOLDH_LOW, val); + assert(0 == tsl2561_read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_THRESHHOLDH_HIGH, &val)); + console_printf("0x%02X (THRHH): 0x%02X\n", TSL2561_REGISTER_THRESHHOLDH_HIGH, val); + assert(0 == tsl2561_read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_INTERRUPT, &val)); + console_printf("0x%02X (INTER): 0x%02X\n", TSL2561_REGISTER_INTERRUPT, val); + assert(0 == tsl2561_read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_ID, &val)); + console_printf("0x%02X (ID): 0x%02X\n", TSL2561_REGISTER_ID, val); + + return 0; +} + +static int +tsl2561_shell_cmd(int argc, char **argv) +{ + if (argc == 1) { + return tsl2561_shell_help(); + } + + /* Read command (get a new data sample) */ + if (argc > 1 && strcmp(argv[1], "r") == 0) { + return tsl2561_shell_cmd_read(argc, argv); + } + + /* Gain command */ + if (argc > 1 && strcmp(argv[1], "gain") == 0) { + return tsl2561_shell_cmd_gain(argc, argv); + } + + /* Integration time command */ + if (argc > 1 && strcmp(argv[1], "time") == 0) { + return tsl2561_shell_cmd_time(argc, argv); + } + + /* Enable */ + if (argc > 1 && strcmp(argv[1], "en") == 0) { + return tsl2561_shell_cmd_en(argc, argv); + } + + /* Interrupt */ + if (argc > 1 && strcmp(argv[1], "int") == 0) { + return tsl2561_shell_cmd_int(argc, argv); + } + + /* Debug */ + if (argc > 1 && strcmp(argv[1], "dump") == 0) { + return tsl2561_shell_cmd_dump(argc, argv); + } + + return tsl2561_shell_err_unknown_arg(argv[1]); +} + +int +tsl2561_shell_init(void) +{ + int rc; + + rc = shell_cmd_register(&tsl2561_shell_cmd_struct); + SYSINIT_PANIC_ASSERT(rc == 0); + + return rc; +} + +#endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/674aa7d4/hw/drivers/sensors/tsl2561/syscfg.yml ---------------------------------------------------------------------- diff --git a/hw/drivers/sensors/tsl2561/syscfg.yml b/hw/drivers/sensors/tsl2561/syscfg.yml new file mode 100644 index 0000000..f6e6801 --- /dev/null +++ b/hw/drivers/sensors/tsl2561/syscfg.yml @@ -0,0 +1,41 @@ +# The BSD License (BSD) +# +# Copyright (c) 2016 Adafruit Industries +# +# 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. + +syscfg.defs: + TSL2561_TASK: + description: 'Enable the TSL2561 sensor driver' + value: 0 + TSL2561_I2CADDR: + description: 'HW I2C address for the TSL2561 (0x29, 0x39 or 0x49)' + value: 0x39 + TSL2561_I2CBUS: + description: 'I2C bus number for the TSL2561' + value: -1 + TSL2561_CLI: + description: 'Enable shell support for the TSL2561' + value: 0 + TSL2561_LOG: + description: 'Enable TSL2561 logging' + value: 0 + TSL2561_STATS: + description: 'Enable TSL2561 statistics' + value: 0
