You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by vi...@apache.org on 2017/02/24 19:38:25 UTC

[30/50] incubator-mynewt-core git commit: Modifying tsl2561 driver

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 <vi...@apache.org>
Authored: Wed Feb 1 15:37:39 2017 -0800
Committer: Vipul Rahane <vi...@apache.org>
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