Modifying tsl2561 driver - Changing the driver to match the Sensor API - Adding it to the shell - We might want to keep the individual sensor tsl shell as it is. Hence keeping the file around for now. - Current implementation is polling based. We might want to add interrupt based sampling to the Sensor API.
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/9f59c4f0 Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/9f59c4f0 Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/9f59c4f0 Branch: refs/heads/develop Commit: 9f59c4f06a7ba1000d53745a7fcaca114e74d4f9 Parents: 674aa7d Author: Vipul Rahane <[email protected]> Authored: Wed Feb 1 15:37:39 2017 -0800 Committer: Vipul Rahane <[email protected]> Committed: Wed Feb 1 15:37:39 2017 -0800 ---------------------------------------------------------------------- apps/slinky/pkg.yml | 1 + apps/slinky/src/main.c | 36 +- apps/slinky/syscfg.yml | 8 + .../sensors/tsl2561/include/tsl2561/tsl2561.h | 30 +- hw/drivers/sensors/tsl2561/pkg.yml | 14 - hw/drivers/sensors/tsl2561/src/tsl2561.c | 428 +++++++++++++------ hw/drivers/sensors/tsl2561/src/tsl2561_priv.h | 81 +++- hw/drivers/sensors/tsl2561/syscfg.yml | 3 - hw/sensor/include/sensor/light.h | 49 +++ hw/sensor/src/sensor_shell.c | 16 + sys/shell/src/shell.c | 2 +- sys/shell/syscfg.yml | 2 +- 12 files changed, 496 insertions(+), 174 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9f59c4f0/apps/slinky/pkg.yml ---------------------------------------------------------------------- diff --git a/apps/slinky/pkg.yml b/apps/slinky/pkg.yml index 8515446..2f84f69 100644 --- a/apps/slinky/pkg.yml +++ b/apps/slinky/pkg.yml @@ -33,6 +33,7 @@ pkg.deps: - hw/sensor - hw/drivers/sensors/sim - hw/drivers/sensors/lsm303dlhc + - hw/drivers/sensors/tsl2561 - boot/bootutil - sys/shell - sys/config http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9f59c4f0/apps/slinky/src/main.c ---------------------------------------------------------------------- diff --git a/apps/slinky/src/main.c b/apps/slinky/src/main.c index 4b0e870..e87aa0e 100755 --- a/apps/slinky/src/main.c +++ b/apps/slinky/src/main.c @@ -31,6 +31,7 @@ #include <config/config.h> #include <sensor/sensor.h> #include <lsm303dlhc/lsm303dlhc.h> +#include <tsl2561/tsl2561.h> #include "flash_map/flash_map.h" #include <hal/hal_system.h> #if MYNEWT_VAL(SPLIT_LOADER) @@ -240,33 +241,50 @@ static int config_sensor(void) { struct os_dev *dev; - struct lsm303dlhc_cfg cfg; int rc; - dev = (struct os_dev *) os_dev_open("accel0", OS_TIMEOUT_NEVER, NULL); +#if MYNEWT_VAL(TSL2561_PRESENT) + struct tsl2561_cfg tslcfg; + + dev = (struct os_dev *) os_dev_open("light0", OS_TIMEOUT_NEVER, NULL); assert(dev != NULL); + rc = tsl2561_init(dev, NULL); - rc = lsm303dlhc_init(dev, NULL); - if (rc != 0) { + /* Gain set to 1X and Inetgration time set to 13ms */ + tslcfg.gain = TSL2561_LIGHT_GAIN_1X; + tslcfg.integration_time = TSL2561_LIGHT_ITIME_13MS; + + rc = tsl2561_config((struct tsl2561 *)dev, &tslcfg); + if (rc) { os_dev_close(dev); goto err; } +#endif + +#if MYNEWT_VAL(LSM303DLHC_PRESENT) + struct lsm303dlhc_cfg lsmcfg; + + dev = (struct os_dev *) os_dev_open("accel0", OS_TIMEOUT_NEVER, NULL); + assert(dev != NULL); + + rc = lsm303dlhc_init(dev, NULL); /* read once per sec. API should take this value in ms. */ - cfg.accel_rate = LSM303DLHC_ACCEL_RATE_1; - cfg.accel_range = LSM303DLHC_ACCEL_RANGE_2; + lsmcfg.accel_rate = LSM303DLHC_ACCEL_RATE_1; + lsmcfg.accel_range = LSM303DLHC_ACCEL_RANGE_2; - rc = lsm303dlhc_config((struct lsm303dlhc *) dev, &cfg); - if (rc != 0) { + rc = lsm303dlhc_config((struct lsm303dlhc *) dev, &lsmcfg); + if (rc) { os_dev_close(dev); goto err; } +#endif os_dev_close(dev); return (0); err: - return (rc); + return rc; } #endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9f59c4f0/apps/slinky/syscfg.yml ---------------------------------------------------------------------- diff --git a/apps/slinky/syscfg.yml b/apps/slinky/syscfg.yml index 1beee37..d324731 100644 --- a/apps/slinky/syscfg.yml +++ b/apps/slinky/syscfg.yml @@ -43,3 +43,11 @@ syscfg.vals: OS_MAIN_TASK_PRIO: 10 OS_MAIN_STACKS_SIZE: 512 + +syscfg.defs: + TSL2561_PRESENT: + description: 'TSL2561 is present' + value: 0 + LSM303DLHC_PRESENT: + description: 'LSM303 is present' + value: 0 http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9f59c4f0/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 index 03320e8..2f093be 100644 --- a/hw/drivers/sensors/tsl2561/include/tsl2561/tsl2561.h +++ b/hw/drivers/sensors/tsl2561/include/tsl2561/tsl2561.h @@ -38,35 +38,42 @@ #define __ADAFRUIT_TSL2561_H__ #include <os/os.h> +#include "os/os_dev.h" +#include "sensor/sensor.h" #ifdef __cplusplus extern "C" { #endif -/* -struct tsl2561_i2c { - uint8_t i2c_num; - uint8_t i2c_addr; +enum tsl2561_light_gain { + TSL2561_LIGHT_GAIN_1X = 0x00, /* 1X */ + TSL2561_LIGHT_GAIN_16X = 0x01 << 4 /* 16X */ +}; + +enum tsl2561_light_itime { + TSL2561_LIGHT_ITIME_13MS = 0x00, /* 13ms */ + TSL2561_LIGHT_ITIME_101MS = 0x01, /* 101ms */ + TSL2561_LIGHT_ITIME_402MS = 0x01 << 1 /* 402ms */ }; struct tsl2561_cfg { uint8_t gain; uint8_t integration_time; - uint8_t enabled; }; -struct tsl2561_dev { - struct tsl2561_i2c i2c; +struct tsl2561 { + struct os_dev dev; + struct sensor sensor; struct tsl2561_cfg cfg; + os_time_t last_read_time; }; -*/ /** * Initialize the tsl2561. This function is normally called by sysinit. * * @param dev Pointer to the tsl2561_dev device descriptor */ -void tsl2561_init(void); +int tsl2561_init(struct os_dev *dev, void *arg); /** * Enable or disables the sensor to save power @@ -89,10 +96,11 @@ uint8_t tsl2561_get_enable(void); * * @param broadband The full (visible + ir) sensor output * @param ir The ir sensor output + * @param tsl2561 Config and OS device structure * * @return 0 on success, and non-zero error code on failure */ -int tsl2561_get_data(uint16_t *broadband, uint16_t *ir); +int tsl2561_get_data(uint16_t *broadband, uint16_t *ir, struct tsl2561 *tsl2561); /** * Sets the integration time used when sampling light values. @@ -179,6 +187,8 @@ int tsl2561_enable_interrupt(uint8_t enable); */ int tsl2561_clear_interrupt(void); +int tsl2561_config(struct tsl2561 *, struct tsl2561_cfg *); + #ifdef __cplusplus } #endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9f59c4f0/hw/drivers/sensors/tsl2561/pkg.yml ---------------------------------------------------------------------- diff --git a/hw/drivers/sensors/tsl2561/pkg.yml b/hw/drivers/sensors/tsl2561/pkg.yml index e7d0ffd..cebb755 100644 --- a/hw/drivers/sensors/tsl2561/pkg.yml +++ b/hw/drivers/sensors/tsl2561/pkg.yml @@ -33,17 +33,3 @@ pkg.keywords: 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/9f59c4f0/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 index 037ccf8..8f90718 100644 --- a/hw/drivers/sensors/tsl2561/src/tsl2561.c +++ b/hw/drivers/sensors/tsl2561/src/tsl2561.c @@ -37,8 +37,13 @@ #include <assert.h> #include <stdio.h> #include <errno.h> + +#include "defs/error.h" +#include "os/os.h" #include "sysinit/sysinit.h" #include "hal/hal_i2c.h" +#include "sensor/sensor.h" +#include "sensor/light.h" #include "tsl2561/tsl2561.h" #include "tsl2561_priv.h" @@ -53,10 +58,6 @@ /* 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) @@ -90,6 +91,20 @@ static struct log _log; #define TSL2561_ERR(...) #endif +/* Exports for the sensor interface. + */ +static void *tsl2561_sensor_get_interface(struct sensor *, sensor_type_t); +static int tsl2561_sensor_read(struct sensor *, sensor_type_t, + sensor_data_func_t, void *, uint32_t); +static int tsl2561_sensor_get_config(struct sensor *, sensor_type_t, + struct sensor_cfg *); + +static const struct sensor_driver g_tsl2561_sensor_driver = { + tsl2561_sensor_get_interface, + tsl2561_sensor_read, + tsl2561_sensor_get_config +}; + int tsl2561_write8(uint8_t reg, uint32_t value) { @@ -151,7 +166,7 @@ tsl2561_read8(uint8_t reg, uint8_t *value) OS_TICKS_PER_SEC / 10, 1); if (rc) { TSL2561_ERR("Failed to address sensor\n"); - goto error; + goto err; } /* Read one byte back */ @@ -163,7 +178,7 @@ tsl2561_read8(uint8_t reg, uint8_t *value) TSL2561_ERR("Failed to read @0x%02X\n", reg); } -error: +err: return rc; } @@ -184,7 +199,7 @@ tsl2561_read16(uint8_t reg, uint16_t *value) OS_TICKS_PER_SEC / 10, 1); if (rc) { TSL2561_ERR("Failed to address sensor\n"); - goto error; + goto err; } /* Read two bytes back */ @@ -195,53 +210,28 @@ tsl2561_read16(uint8_t reg, uint16_t *value) *value = (uint16_t)payload[0] | ((uint16_t)payload[1] << 8); if (rc) { TSL2561_ERR("Failed to read @0x%02X\n", reg); - goto error; + goto err; } - /* ToDo: Log raw reads */ - // console_printf("0x%04X\n", (uint16_t)payload[0] | ((uint16_t)payload[1] << 8)); - -error: +err: 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) +tsl2561_get_data(uint16_t *broadband, uint16_t *ir, struct tsl2561 *tsl2561) { int rc; int delay_ticks; /* Wait integration time ms before getting a data sample */ - switch (g_tsl2561_integration_time) { - case TSL2561_INTEGRATIONTIME_13MS: + switch (tsl2561->cfg.integration_time) { + case TSL2561_LIGHT_ITIME_13MS: delay_ticks = 14 * OS_TICKS_PER_SEC / 1000; break; - case TSL2561_INTEGRATIONTIME_101MS: + case TSL2561_LIGHT_ITIME_101MS: delay_ticks = 102 * OS_TICKS_PER_SEC / 1000; break; - case TSL2561_INTEGRATIONTIME_402MS: + case TSL2561_LIGHT_ITIME_402MS: default: delay_ticks = 403 * OS_TICKS_PER_SEC / 1000; break; @@ -252,85 +242,33 @@ tsl2561_get_data(uint16_t *broadband, uint16_t *ir) rc = tsl2561_read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW, broadband); if (rc) { - goto error; + goto err; } rc = tsl2561_read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW, ir); if (rc) { - goto error; + goto err; } #if MYNEWT_VAL(TSL2561_STATS) - switch (g_tsl2561_integration_time) { - case TSL2561_INTEGRATIONTIME_13MS: + switch (tsl2561->cfg.integration_time) { + case TSL2561_LIGHT_ITIME_13MS: STATS_INC(g_tsl2561stats, samples_13ms); break; - case TSL2561_INTEGRATIONTIME_101MS: + case TSL2561_LIGHT_ITIME_101MS: STATS_INC(g_tsl2561stats, samples_101ms); break; - case TSL2561_INTEGRATIONTIME_402MS: + case TSL2561_LIGHT_ITIME_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: +err: 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; @@ -340,30 +278,30 @@ int tsl2561_setup_interrupt (uint8_t rate, uint16_t lower, uint16_t upper) rc = tsl2561_write16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_THRESHHOLDL_LOW, lower); if (rc) { - goto error; + goto err; } /* Set upper threshold */ rc = tsl2561_write16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_THRESHHOLDH_LOW, upper); if (rc) { - goto error; + goto err; } /* Set rate */ rc = tsl2561_read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_INTERRUPT, &intval); if (rc) { - goto error; + goto err; } /* 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; + goto err; } -error: +err: return rc; } @@ -375,24 +313,24 @@ int tsl2561_enable_interrupt (uint8_t enable) if (enable > 1) { TSL2561_ERR("Invalid value 0x%02X in tsl2561_enable_interrupt\n", enable); - rc = EINVAL; - goto error; + rc = SYS_EINVAL; + goto err; } /* Read the current value to maintain PERSIST state */ rc = tsl2561_read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_INTERRUPT, &persist_val); if (rc) { - goto error; + goto err; } /* 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; + goto err; } -error: +err: return rc; } @@ -411,34 +349,31 @@ int tsl2561_clear_interrupt (void) rc = hal_i2c_master_write(MYNEWT_VAL(TSL2561_I2CBUS), &data_struct, OS_TICKS_PER_SEC / 10, 1); if (rc) { - goto error; + goto err; } #if MYNEWT_VAL(TSL2561_STATS) STATS_INC(g_tsl2561stats, ints_cleared); #endif -error: +err: return rc; } -void -tsl2561_init(void) +int +tsl2561_init(struct os_dev *dev, void *arg) { + struct tsl2561 *tsl2561; + struct sensor *sensor; int rc; -#if !MYNEWT_VAL(TSL2561_TASK) - return; -#endif + tsl2561 = (struct tsl2561 *) dev; #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 + sensor = &tsl2561->sensor; #if MYNEWT_VAL(TSL2561_STATS) /* Initialise the stats entry */ @@ -451,14 +386,255 @@ tsl2561_init(void) rc = stats_register("tsl2561", STATS_HDR(g_tsl2561stats)); SYSINIT_PANIC_ASSERT(rc == 0); #endif + rc = sensor_init(sensor, dev); + if (rc != 0) { + goto err; + } - /* Enable the device by default */ - rc = tsl2561_enable(1); - SYSINIT_PANIC_ASSERT(rc == 0); + /* Add the light driver */ + rc = sensor_set_driver(sensor, SENSOR_TYPE_LIGHT, + (struct sensor_driver *) &g_tsl2561_sensor_driver); + if (rc != 0) { + goto err; + } - rc = tsl2561_set_gain(TSL2561_GAIN_1X); - SYSINIT_PANIC_ASSERT(rc == 0); + rc = sensor_mgr_register(sensor); + if (rc != 0) { + goto err; + } - rc = tsl2561_set_integration_time(TSL2561_INTEGRATIONTIME_13MS); - SYSINIT_PANIC_ASSERT(rc == 0); + return (0); +err: + return (rc); + +} + +static void * +tsl2561_sensor_get_interface(struct sensor *sensor, sensor_type_t type) +{ + return (NULL); +} + +static uint32_t +tsl2561_calculate_lux(uint16_t broadband, uint16_t ir, struct tsl2561_cfg *cfg) +{ + uint64_t chscale; + uint64_t channel1; + uint64_t channel0; + uint16_t clipthreshold; + uint64_t ratio1; + uint64_t ratio; + int64_t b, m; + uint64_t temp; + uint32_t lux; + + /* Make sure the sensor isn't saturated! */ + switch (cfg->integration_time) { + case TSL2561_LIGHT_ITIME_13MS: + clipthreshold = TSL2561_CLIPPING_13MS; + break; + case TSL2561_LIGHT_ITIME_101MS: + clipthreshold = TSL2561_CLIPPING_101MS; + break; + default: + clipthreshold = TSL2561_CLIPPING_402MS; + break; + } + + /* Return 65536 lux if the sensor is saturated */ + if ((broadband > clipthreshold) || (ir > clipthreshold)) { + return 65536; + } + + /* Get the correct scale depending on the intergration time */ + switch (cfg->integration_time) { + case TSL2561_LIGHT_ITIME_13MS: + chscale = TSL2561_LUX_CHSCALE_TINT0; + break; + case TSL2561_LIGHT_ITIME_101MS: + chscale = TSL2561_LUX_CHSCALE_TINT1; + break; + default: /* No scaling ... integration time = 402ms */ + chscale = (1 << TSL2561_LUX_CHSCALE); + break; + } + + /* Scale for gain (1x or 16x) */ + if (!cfg->gain) { + chscale = chscale << 4; + } + + /* Scale the channel values */ + channel0 = (broadband * chscale) >> TSL2561_LUX_CHSCALE; + channel1 = (ir * chscale) >> TSL2561_LUX_CHSCALE; + + ratio1 = 0; + /* Find the ratio of the channel values (Channel1/Channel0) */ + if (channel0 != 0) { + ratio1 = (channel1 << (TSL2561_LUX_RATIOSCALE+1)) / channel0; + } + + /* round the ratio value */ + ratio = (ratio1 + 1) >> 1; + +#if MYNEWT_VAL(TSL2561_PACKAGE_CS) + if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1C)) { + b = TSL2561_LUX_B1C; + m = TSL2561_LUX_M1C; + } else if (ratio <= TSL2561_LUX_K2C) { + b = TSL2561_LUX_B2C; + m = TSL2561_LUX_M2C; + } else if (ratio <= TSL2561_LUX_K3C) { + b = TSL2561_LUX_B3C; + m = TSL2561_LUX_M3C; + } else if (ratio <= TSL2561_LUX_K4C) { + b = TSL2561_LUX_B4C; + m = TSL2561_LUX_M4C; + } else if (ratio <= TSL2561_LUX_K5C) { + b = TSL2561_LUX_B5C; + m = TSL2561_LUX_M5C; + } else if (ratio <= TSL2561_LUX_K6C) { + b = TSL2561_LUX_B6C; + m = TSL2561_LUX_M6C; + } else if (ratio <= TSL2561_LUX_K7C) { + b = TSL2561_LUX_B7C; + m = TSL2561_LUX_M7C; + } else if (ratio > TSL2561_LUX_K8C) { + b = TSL2561_LUX_B8C; + m = TSL2561_LUX_M8C; + } +#else + if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1T)) { + b = TSL2561_LUX_B1T; + m = TSL2561_LUX_M1T; + } else if (ratio <= TSL2561_LUX_K2T) { + b = TSL2561_LUX_B2T; + m = TSL2561_LUX_M2T; + } else if (ratio <= TSL2561_LUX_K3T) { + b = TSL2561_LUX_B3T; + m = TSL2561_LUX_M3T; + } else if (ratio <= TSL2561_LUX_K4T) { + b = TSL2561_LUX_B4T; + m = TSL2561_LUX_M4T; + } else if (ratio <= TSL2561_LUX_K5T) { + b = TSL2561_LUX_B5T; + m = TSL2561_LUX_M5T; + } else if (ratio <= TSL2561_LUX_K6T) { + b = TSL2561_LUX_B6T; + m = TSL2561_LUX_M6T; + } else if (ratio <= TSL2561_LUX_K7T) { + b = TSL2561_LUX_B7T; + m = TSL2561_LUX_M7T; + } else if (ratio > TSL2561_LUX_K8T) { + b = TSL2561_LUX_B8T; + m = TSL2561_LUX_M8T; + } +#endif + + temp = ((channel0 * b) - (channel1 * m)); + + /* Do not allow negative lux value */ + if (temp < 0) { + temp = 0; + } + /* Round lsb (2^(LUX_SCALE-1)) */ + temp += (1 << (TSL2561_LUX_LUXSCALE - 1)); + + /* Strip off fractional portion */ + lux = temp >> TSL2561_LUX_LUXSCALE; + + return lux; +} + +static int +tsl2561_sensor_read(struct sensor *sensor, sensor_type_t type, + sensor_data_func_t data_func, void *data_arg, uint32_t timeout) +{ + struct tsl2561 *tsl2561; + struct sensor_light_data sld; + uint16_t full; + uint16_t ir; + uint32_t lux; + int rc; + + /* If the read isn't looking for accel or mag data, don't do anything. */ + if (!(type & SENSOR_TYPE_LIGHT)) { + rc = SYS_EINVAL; + goto err; + } + + tsl2561 = (struct tsl2561 *) SENSOR_GET_DEVICE(sensor); + + /* Get a new accelerometer sample */ + if (type & SENSOR_TYPE_LIGHT) { + full = ir = 0; + + rc = tsl2561_get_data(&full, &ir, tsl2561); + if (rc) { + goto err; + } + + lux = tsl2561_calculate_lux(full, ir, &(tsl2561->cfg)); + sld.sld_full = full; + sld.sld_ir = ir; + sld.sld_lux = lux; + + /* Call data function */ + rc = data_func(sensor, data_arg, &sld); + if (rc != 0) { + goto err; + } + } + + return 0; +err: + return rc; +} + +static int +tsl2561_sensor_get_config(struct sensor *sensor, sensor_type_t type, + struct sensor_cfg *cfg) +{ + int rc; + + if ((type != SENSOR_TYPE_LIGHT)) { + rc = SYS_EINVAL; + goto err; + } + + cfg->sc_valtype = SENSOR_VALUE_TYPE_INT32; + + return (0); +err: + return (rc); +} + +int +tsl2561_config(struct tsl2561 *tsl2561, struct tsl2561_cfg *cfg) +{ + int rc; + + if ((cfg->gain != TSL2561_LIGHT_GAIN_1X) && + (cfg->gain != TSL2561_LIGHT_GAIN_16X)) { + TSL2561_ERR("Invalid gain value\n"); + rc = SYS_EINVAL; + goto err; + } + + /* Overwrite the configuration data. */ + memcpy(&tsl2561->cfg, cfg, sizeof(*cfg)); + + /* Enable the device by setting the control bit to 0x03 */ + rc = tsl2561_write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, + TSL2561_CONTROL_POWERON); + + /* Set integration time and gain */ + rc = tsl2561_write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, + cfg->integration_time | cfg->gain); + if (rc) { + goto err; + } + +err: + return (rc); } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9f59c4f0/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 index 5ead614..7d92d5f 100644 --- a/hw/drivers/sensors/tsl2561/src/tsl2561_priv.h +++ b/hw/drivers/sensors/tsl2561/src/tsl2561_priv.h @@ -49,16 +49,6 @@ #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 */ @@ -67,6 +57,77 @@ #define TSL2561_CONTROL_POWERON (0x03) #define TSL2561_CONTROL_POWEROFF (0x00) +#define TSL2561_LUX_LUXSCALE (14) // Scale by 2^14 +#define TSL2561_LUX_RATIOSCALE (9) // Scale ratio by 2^9 +#define TSL2561_LUX_CHSCALE (10) // Scale channel values by 2^10 +#define TSL2561_LUX_CHSCALE_TINT0 (0x7517) // 322/11 * 2^TSL2561_LUX_CHSCALE +#define TSL2561_LUX_CHSCALE_TINT1 (0x0FE7) // 322/81 * 2^TSL2561_LUX_CHSCALE + +// T, FN and CL package values +#define TSL2561_LUX_K1T (0x0040) // 0.125 * 2^RATIO_SCALE +#define TSL2561_LUX_B1T (0x01f2) // 0.0304 * 2^LUX_SCALE +#define TSL2561_LUX_M1T (0x01be) // 0.0272 * 2^LUX_SCALE +#define TSL2561_LUX_K2T (0x0080) // 0.250 * 2^RATIO_SCALE +#define TSL2561_LUX_B2T (0x0214) // 0.0325 * 2^LUX_SCALE +#define TSL2561_LUX_M2T (0x02d1) // 0.0440 * 2^LUX_SCALE +#define TSL2561_LUX_K3T (0x00c0) // 0.375 * 2^RATIO_SCALE +#define TSL2561_LUX_B3T (0x023f) // 0.0351 * 2^LUX_SCALE +#define TSL2561_LUX_M3T (0x037b) // 0.0544 * 2^LUX_SCALE +#define TSL2561_LUX_K4T (0x0100) // 0.50 * 2^RATIO_SCALE +#define TSL2561_LUX_B4T (0x0270) // 0.0381 * 2^LUX_SCALE +#define TSL2561_LUX_M4T (0x03fe) // 0.0624 * 2^LUX_SCALE +#define TSL2561_LUX_K5T (0x0138) // 0.61 * 2^RATIO_SCALE +#define TSL2561_LUX_B5T (0x016f) // 0.0224 * 2^LUX_SCALE +#define TSL2561_LUX_M5T (0x01fc) // 0.0310 * 2^LUX_SCALE +#define TSL2561_LUX_K6T (0x019a) // 0.80 * 2^RATIO_SCALE +#define TSL2561_LUX_B6T (0x00d2) // 0.0128 * 2^LUX_SCALE +#define TSL2561_LUX_M6T (0x00fb) // 0.0153 * 2^LUX_SCALE +#define TSL2561_LUX_K7T (0x029a) // 1.3 * 2^RATIO_SCALE +#define TSL2561_LUX_B7T (0x0018) // 0.00146 * 2^LUX_SCALE +#define TSL2561_LUX_M7T (0x0012) // 0.00112 * 2^LUX_SCALE +#define TSL2561_LUX_K8T (0x029a) // 1.3 * 2^RATIO_SCALE +#define TSL2561_LUX_B8T (0x0000) // 0.000 * 2^LUX_SCALE +#define TSL2561_LUX_M8T (0x0000) // 0.000 * 2^LUX_SCALE + +// CS package values +#define TSL2561_LUX_K1C (0x0043) // 0.130 * 2^RATIO_SCALE +#define TSL2561_LUX_B1C (0x0204) // 0.0315 * 2^LUX_SCALE +#define TSL2561_LUX_M1C (0x01ad) // 0.0262 * 2^LUX_SCALE +#define TSL2561_LUX_K2C (0x0085) // 0.260 * 2^RATIO_SCALE +#define TSL2561_LUX_B2C (0x0228) // 0.0337 * 2^LUX_SCALE +#define TSL2561_LUX_M2C (0x02c1) // 0.0430 * 2^LUX_SCALE +#define TSL2561_LUX_K3C (0x00c8) // 0.390 * 2^RATIO_SCALE +#define TSL2561_LUX_B3C (0x0253) // 0.0363 * 2^LUX_SCALE +#define TSL2561_LUX_M3C (0x0363) // 0.0529 * 2^LUX_SCALE +#define TSL2561_LUX_K4C (0x010a) // 0.520 * 2^RATIO_SCALE +#define TSL2561_LUX_B4C (0x0282) // 0.0392 * 2^LUX_SCALE +#define TSL2561_LUX_M4C (0x03df) // 0.0605 * 2^LUX_SCALE +#define TSL2561_LUX_K5C (0x014d) // 0.65 * 2^RATIO_SCALE +#define TSL2561_LUX_B5C (0x0177) // 0.0229 * 2^LUX_SCALE +#define TSL2561_LUX_M5C (0x01dd) // 0.0291 * 2^LUX_SCALE +#define TSL2561_LUX_K6C (0x019a) // 0.80 * 2^RATIO_SCALE +#define TSL2561_LUX_B6C (0x0101) // 0.0157 * 2^LUX_SCALE +#define TSL2561_LUX_M6C (0x0127) // 0.0180 * 2^LUX_SCALE +#define TSL2561_LUX_K7C (0x029a) // 1.3 * 2^RATIO_SCALE +#define TSL2561_LUX_B7C (0x0037) // 0.00338 * 2^LUX_SCALE +#define TSL2561_LUX_M7C (0x002b) // 0.00260 * 2^LUX_SCALE +#define TSL2561_LUX_K8C (0x029a) // 1.3 * 2^RATIO_SCALE +#define TSL2561_LUX_B8C (0x0000) // 0.000 * 2^LUX_SCALE +#define TSL2561_LUX_M8C (0x0000) // 0.000 * 2^LUX_SCALE + +// Auto-gain thresholds +#define TSL2561_AGC_THI_13MS (4850) // Max value at Ti 13ms = 5047 +#define TSL2561_AGC_TLO_13MS (100) +#define TSL2561_AGC_THI_101MS (36000) // Max value at Ti 101ms = 37177 +#define TSL2561_AGC_TLO_101MS (200) +#define TSL2561_AGC_THI_402MS (63000) // Max value at Ti 402ms = 65535 +#define TSL2561_AGC_TLO_402MS (500) + +// Clipping thresholds +#define TSL2561_CLIPPING_13MS (4900) +#define TSL2561_CLIPPING_101MS (37000) +#define TSL2561_CLIPPING_402MS (65000) + #ifdef __cplusplus extern "C" { #endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9f59c4f0/hw/drivers/sensors/tsl2561/syscfg.yml ---------------------------------------------------------------------- diff --git a/hw/drivers/sensors/tsl2561/syscfg.yml b/hw/drivers/sensors/tsl2561/syscfg.yml index f6e6801..d507b79 100644 --- a/hw/drivers/sensors/tsl2561/syscfg.yml +++ b/hw/drivers/sensors/tsl2561/syscfg.yml @@ -21,9 +21,6 @@ # 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 http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9f59c4f0/hw/sensor/include/sensor/light.h ---------------------------------------------------------------------- diff --git a/hw/sensor/include/sensor/light.h b/hw/sensor/include/sensor/light.h new file mode 100644 index 0000000..677f5c4 --- /dev/null +++ b/hw/sensor/include/sensor/light.h @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef __SENSOR_LIGHT_H__ +#define __SENSOR_LIGHT_H__ + +#include "os/os.h" +#include "os/os_dev.h" +#include "sensor/sensor.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Data representing a singular read from a luminosity sensor. + * All data is in lux + */ +struct sensor_light_data { + uint16_t sld_full; + uint16_t sld_ir; + uint32_t sld_lux; +} __attribute__((packed)); + +/** + * Luminosity Sensor data is unused for this field. + */ +#define SENSOR_LIGHT_DATA_UNUSED (-1) + +#ifdef __cplusplus +} +#endif + +#endif /* __SENSOR_LIGHT_H__ */ http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9f59c4f0/hw/sensor/src/sensor_shell.c ---------------------------------------------------------------------- diff --git a/hw/sensor/src/sensor_shell.c b/hw/sensor/src/sensor_shell.c index 6312f81..c2c68b1 100644 --- a/hw/sensor/src/sensor_shell.c +++ b/hw/sensor/src/sensor_shell.c @@ -33,6 +33,7 @@ #include "sensor/sensor.h" #include "sensor/accel.h" #include "sensor/mag.h" +#include "sensor/light.h" #include "console/console.h" #include "shell/shell.h" @@ -96,6 +97,7 @@ sensor_shell_read_listener(struct sensor *sensor, void *arg, void *data) struct sensor_shell_read_ctx *ctx; struct sensor_accel_data *sad; struct sensor_mag_data *smd; + struct sensor_light_data *sld; char tmpstr[13]; ctx = (struct sensor_shell_read_ctx *) arg; @@ -130,6 +132,20 @@ sensor_shell_read_listener(struct sensor *sensor, void *arg, void *data) console_printf("\n"); } + if (ctx->type == SENSOR_TYPE_LIGHT) { + sld = (struct sensor_light_data *) data; + if (sld->sld_full != SENSOR_LIGHT_DATA_UNUSED) { + console_printf("Full = %u, ", sld->sld_full); + } + if (sld->sld_ir != SENSOR_LIGHT_DATA_UNUSED) { + console_printf("IR = %u, ", sld->sld_ir); + } + if (sld->sld_lux != SENSOR_LIGHT_DATA_UNUSED) { + console_printf("Lux = %u, ", (unsigned int)sld->sld_lux); + } + console_printf("\n"); + } + return (0); } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9f59c4f0/sys/shell/src/shell.c ---------------------------------------------------------------------- diff --git a/sys/shell/src/shell.c b/sys/shell/src/shell.c index f11086b..bc8554e 100644 --- a/sys/shell/src/shell.c +++ b/sys/shell/src/shell.c @@ -211,7 +211,7 @@ err: static int shell_cmd(char *cmd, char **argv, int argc) { - struct shell_cmd *sc; + struct shell_cmd *sc = NULL; int rc; rc = shell_cmd_find(cmd, &sc); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9f59c4f0/sys/shell/syscfg.yml ---------------------------------------------------------------------- diff --git a/sys/shell/syscfg.yml b/sys/shell/syscfg.yml index c495c58..236a20d 100644 --- a/sys/shell/syscfg.yml +++ b/sys/shell/syscfg.yml @@ -27,4 +27,4 @@ syscfg.defs: value: 256 SHELL_DEBUG: description: Enables additional error checking in the shell package. - value: 1 + value: 0
