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/03/09 23:17:16 UTC

incubator-mynewt-core git commit: MYNEWT-665 SensorAPI: Add TCS34725 Driver and color sensor support

Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop 605317587 -> 2d4f8a760


MYNEWT-665
SensorAPI: Add TCS34725 Driver and color sensor support


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/2d4f8a76
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/2d4f8a76
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/2d4f8a76

Branch: refs/heads/develop
Commit: 2d4f8a76055e50d42983da0eef2158e99be721d1
Parents: 6053175
Author: Vipul Rahane <vi...@apache.org>
Authored: Thu Mar 9 15:07:58 2017 -0800
Committer: Vipul Rahane <vi...@apache.org>
Committed: Thu Mar 9 15:16:46 2017 -0800

----------------------------------------------------------------------
 apps/sensors_test/pkg.yml                       |   1 +
 apps/sensors_test/src/main.c                    |  32 +-
 apps/sensors_test/syscfg.yml                    |   7 +-
 hw/bsp/nrf52dk/src/hal_bsp.c                    |  68 ++
 .../tcs34725/include/tcs34725/tcs34725.h        |  84 ++
 hw/drivers/sensors/tcs34725/pkg.yml             |  32 +
 hw/drivers/sensors/tcs34725/src/tcs34725.c      | 920 +++++++++++++++++++
 hw/drivers/sensors/tcs34725/src/tcs34725_priv.h | 278 ++++++
 .../sensors/tcs34725/src/tcs34725_shell.c       | 471 ++++++++++
 hw/drivers/sensors/tcs34725/syscfg.yml          |  35 +
 hw/sensor/include/sensor/color.h                |  51 +
 hw/sensor/include/sensor/sensor.h               |   8 +-
 hw/sensor/src/sensor_shell.c                    |  25 +
 13 files changed, 2004 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2d4f8a76/apps/sensors_test/pkg.yml
----------------------------------------------------------------------
diff --git a/apps/sensors_test/pkg.yml b/apps/sensors_test/pkg.yml
index 406ad30..41db418 100644
--- a/apps/sensors_test/pkg.yml
+++ b/apps/sensors_test/pkg.yml
@@ -35,6 +35,7 @@ pkg.deps:
     - hw/drivers/sensors/lsm303dlhc
     - hw/drivers/sensors/tsl2561
     - hw/drivers/sensors/bno055
+    - hw/drivers/sensors/tcs34725
     - boot/bootutil
     - sys/shell
     - sys/config

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2d4f8a76/apps/sensors_test/src/main.c
----------------------------------------------------------------------
diff --git a/apps/sensors_test/src/main.c b/apps/sensors_test/src/main.c
index b79b2b5..45d25a2 100755
--- a/apps/sensors_test/src/main.c
+++ b/apps/sensors_test/src/main.c
@@ -32,6 +32,7 @@
 #include <sensor/sensor.h>
 #include <lsm303dlhc/lsm303dlhc.h>
 #include <tsl2561/tsl2561.h>
+#include <tcs34725/tcs34725.h>
 #include <bno055/bno055.h>
 #include "flash_map/flash_map.h"
 #include <hal/hal_system.h>
@@ -244,6 +245,29 @@ config_sensor(void)
     struct os_dev *dev;
     int rc;
 
+#if MYNEWT_VAL(TCS34725_PRESENT)
+    struct tcs34725_cfg tcscfg;
+
+    dev = (struct os_dev *) os_dev_open("color0", OS_TIMEOUT_NEVER, NULL);
+    assert(dev != NULL);
+    rc = tcs34725_init(dev, NULL);
+    if (rc) {
+        os_dev_close(dev);
+        goto err;
+    }
+
+    /* Gain set to 16X and Inetgration time set to 24ms */
+    tcscfg.gain = TCS34725_GAIN_16X;;
+    tcscfg.integration_time = TCS34725_INTEGRATIONTIME_24MS;
+
+    rc = tcs34725_config((struct tcs34725 *)dev, &tcscfg);
+    if (rc) {
+        os_dev_close(dev);
+        goto err;
+    }
+    os_dev_close(dev);
+#endif
+
 #if MYNEWT_VAL(TSL2561_PRESENT)
     struct tsl2561_cfg tslcfg;
 
@@ -309,9 +333,9 @@ config_sensor(void)
                     BNO055_DO_FORMAT_ANDROID;
 
     bcfg.bc_opr_mode = BNO055_OPR_MODE_ACCONLY;
-
     bcfg.bc_pwr_mode = BNO055_PWR_MODE_NORMAL;
-
+    bcfg.bc_acc_bw = BNO055_ACC_CFG_BW_125HZ;
+    bcfg.bc_acc_range =  BNO055_ACC_CFG_RNG_16G;
     bcfg.bc_use_ext_xtal = 1;
 
     rc = bno055_config((struct bno055 *) dev, &bcfg);
@@ -418,6 +442,10 @@ main(int argc, char **argv)
     }
 #endif
 
+#if MYNEWT_VAL(TCS34725_CLI)
+    tcs34725_shell_init();
+#endif
+
 #if MYNEWT_VAL(TSL2561_CLI)
     tsl2561_shell_init();
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2d4f8a76/apps/sensors_test/syscfg.yml
----------------------------------------------------------------------
diff --git a/apps/sensors_test/syscfg.yml b/apps/sensors_test/syscfg.yml
index 5507f28..bdbe400 100644
--- a/apps/sensors_test/syscfg.yml
+++ b/apps/sensors_test/syscfg.yml
@@ -47,11 +47,14 @@ syscfg.vals:
 syscfg.defs:
     TSL2561_PRESENT:
         description: 'TSL2561 is present'
-        value : 1
+        value : 0
     LSM303DLHC_PRESENT:
         description: 'LSM303 is present'
         value : 1
     BNO055_PRESENT:
         description: 'BNO055 is present'
-        value : 1
+        value : 0
+    TCS34725_PRESENT:
+        description: 'BNO055 is present'
+        value : 0
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2d4f8a76/hw/bsp/nrf52dk/src/hal_bsp.c
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf52dk/src/hal_bsp.c b/hw/bsp/nrf52dk/src/hal_bsp.c
index 1ab37e1..3b7b375 100644
--- a/hw/bsp/nrf52dk/src/hal_bsp.c
+++ b/hw/bsp/nrf52dk/src/hal_bsp.c
@@ -42,6 +42,26 @@
 #endif
 #include "os/os_dev.h"
 #include "bsp.h"
+#include <lsm303dlhc/lsm303dlhc.h>
+#include <tsl2561/tsl2561.h>
+#include <tcs34725/tcs34725.h>
+#include <bno055/bno055.h>
+
+#if MYNEWT_VAL(LSM303DLHC_PRESENT)
+static struct lsm303dlhc lsm303dlhc;
+#endif
+
+#if MYNEWT_VAL(BNO055_PRESENT)
+static struct bno055 bno055;
+#endif
+
+#if MYNEWT_VAL(TSL2561_PRESENT)
+static struct tsl2561 tsl2561;
+#endif
+
+#if MYNEWT_VAL(TCS34725_PRESENT)
+static struct tcs34725 tcs34725;
+#endif
 
 #if MYNEWT_VAL(UART_0)
 static struct uart_dev os_bsp_uart0;
@@ -151,6 +171,30 @@ hal_bsp_get_nvic_priority(int irq_num, uint32_t pri)
     return cfg_pri;
 }
 
+#if MYNEWT_VAL(LSM303DLHC_PRESENT) || MYNEWT_VAL(BNO055_PRESENT)
+static int
+slinky_accel_init(struct os_dev *dev, void *arg)
+{
+   return (0);
+}
+#endif
+
+#if MYNEWT_VAL(TSL2561_PRESENT)
+static int
+slinky_light_init(struct os_dev *dev, void *arg)
+{
+    return (0);
+}
+#endif
+
+#if MYNEWT_VAL(TCS34725_PRESENT)
+static int
+slinky_color_init(struct os_dev *dev, void *arg)
+{
+    return (0);
+}
+#endif
+
 void
 hal_bsp_init(void)
 {
@@ -202,6 +246,30 @@ hal_bsp_init(void)
     assert(rc == 0);
 #endif
 
+#if MYNEWT_VAL(LSM303DLHC_PRESENT)
+    rc = os_dev_create((struct os_dev *) &lsm303dlhc, "accel0",
+      OS_DEV_INIT_PRIMARY, 0, slinky_accel_init, NULL);
+    assert(rc == 0);
+#endif
+
+#if MYNEWT_VAL(BNO055_PRESENT)
+    rc = os_dev_create((struct os_dev *) &bno055, "accel1",
+      OS_DEV_INIT_PRIMARY, 0, slinky_accel_init, NULL);
+    assert(rc == 0);
+#endif
+
+#if MYNEWT_VAL(TSL2561_PRESENT)
+    rc = os_dev_create((struct os_dev *) &tsl2561, "light0",
+      OS_DEV_INIT_PRIMARY, 0, slinky_light_init, NULL);
+    assert(rc == 0);
+#endif
+
+#if MYNEWT_VAL(TCS34725_PRESENT)
+    rc = os_dev_create((struct os_dev *) &tcs34725, "color0",
+      OS_DEV_INIT_PRIMARY, 0, slinky_color_init, NULL);
+    assert(rc == 0);
+#endif
+
 #if MYNEWT_VAL(UART_0)
     rc = os_dev_create((struct os_dev *) &os_bsp_uart0, "uart0",
       OS_DEV_INIT_PRIMARY, 0, uart_hal_init, (void *)&os_bsp_uart0_cfg);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2d4f8a76/hw/drivers/sensors/tcs34725/include/tcs34725/tcs34725.h
----------------------------------------------------------------------
diff --git a/hw/drivers/sensors/tcs34725/include/tcs34725/tcs34725.h b/hw/drivers/sensors/tcs34725/include/tcs34725/tcs34725.h
new file mode 100644
index 0000000..59e4385
--- /dev/null
+++ b/hw/drivers/sensors/tcs34725/include/tcs34725/tcs34725.h
@@ -0,0 +1,84 @@
+/*
+ * 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
+ * resarding 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 __TCS34725_H__
+#define __TCS34725_H__
+
+#define TCS34725_INTEGRATIONTIME_2_4MS  0xFF   /* 2.4ms - 1 cycle    - Max Count: 1024  */
+#define TCS34725_INTEGRATIONTIME_24MS   0xF6   /* 24ms  - 10 cycles  - Max Count: 10240 */
+#define TCS34725_INTEGRATIONTIME_50MS   0xEB   /* 50ms  - 20 cycles  - Max Count: 20480 */
+#define TCS34725_INTEGRATIONTIME_101MS  0xD5   /* 101ms - 42 cycles  - Max Count: 43008 */
+#define TCS34725_INTEGRATIONTIME_154MS  0xC0   /* 154ms - 64 cycles  - Max Count: 65535 */
+#define TCS34725_INTEGRATIONTIME_700MS  0x00   /* 700ms - 256 cycles - Max Count: 65535 */
+
+#define TCS34725_GAIN_1X                0x00   /* No gain  */
+#define TCS34725_GAIN_4X                0x01   /* 4x gain  */
+#define TCS34725_GAIN_16X               0x02   /* 16x gain */
+#define TCS34725_GAIN_60X               0x03   /* 60x gain */
+
+#include <os/os.h>
+#include "os/os_dev.h"
+#include "sensor/sensor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct tcs34725_cfg {
+    uint8_t gain;
+    uint8_t integration_time;
+};
+
+struct tcs34725 {
+    struct os_dev dev;
+    struct sensor sensor;
+    struct tcs34725_cfg cfg;
+    os_time_t last_read_time;
+};
+
+/**
+ * Expects to be called back through os_dev_create().
+ *
+ * @param The device object associated with this accellerometer
+ * @param Argument passed to OS device init, unused
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int
+tcs34725_init(struct os_dev *dev, void *arg);
+
+/**
+ * Configure the sensor
+ *
+ * @param ptr to the sensor
+ * @param ptr to sensor config
+ * @return 0 on success, non-zero on failure
+ */
+int
+tcs34725_config(struct tcs34725 *tcs34725, struct tcs34725_cfg *cfg);
+
+#if MYNEWT_VAL(TCS34725_CLI)
+int tcs34725_shell_init(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2d4f8a76/hw/drivers/sensors/tcs34725/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/drivers/sensors/tcs34725/pkg.yml b/hw/drivers/sensors/tcs34725/pkg.yml
new file mode 100644
index 0000000..18c65c4
--- /dev/null
+++ b/hw/drivers/sensors/tcs34725/pkg.yml
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+
+pkg.name: hw/drivers/sensors/tcs34725
+pkg.description: Driver for the TCS34725 light to digital sensor
+pkg.author: "Adafruit <su...@adafruit.com>"
+pkg.homepage: "http://www.adafruit.com/"
+pkg.keywords:
+    - adafruit
+    - tcs34725
+    - i2c
+    - sensor
+
+pkg.deps:
+    - "@apache-mynewt-core/kernel/os"
+    - "@apache-mynewt-core/hw/hal"

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2d4f8a76/hw/drivers/sensors/tcs34725/src/tcs34725.c
----------------------------------------------------------------------
diff --git a/hw/drivers/sensors/tcs34725/src/tcs34725.c b/hw/drivers/sensors/tcs34725/src/tcs34725.c
new file mode 100644
index 0000000..cd0f2c2
--- /dev/null
+++ b/hw/drivers/sensors/tcs34725/src/tcs34725.c
@@ -0,0 +1,920 @@
+/*
+ * 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
+ * resarding 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.
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "defs/error.h"
+#include "os/os.h"
+#include "sysinit/sysinit.h"
+#include "hal/hal_i2c.h"
+#include "sensor/sensor.h"
+#include "tcs34725/tcs34725.h"
+#include "tcs34725_priv.h"
+#include "sensor/color.h"
+
+#if MYNEWT_VAL(TCS34725_LOG)
+#include "log/log.h"
+#endif
+
+#if MYNEWT_VAL(TCS34725_STATS)
+#include "stats/stats.h"
+#endif
+
+#if MYNEWT_VAL(TCS34725_STATS)
+/* Define the stats section and records */
+STATS_SECT_START(tcs34725_stat_section)
+    STATS_SECT_ENTRY(samples_2_4ms)
+    STATS_SECT_ENTRY(samples_24ms)
+    STATS_SECT_ENTRY(samples_50ms)
+    STATS_SECT_ENTRY(samples_101ms)
+    STATS_SECT_ENTRY(samples_154ms)
+    STATS_SECT_ENTRY(samples_700ms)
+    STATS_SECT_ENTRY(samples_userdef)
+    STATS_SECT_ENTRY(errors)
+STATS_SECT_END
+
+/* Define stat names for querying */
+STATS_NAME_START(tcs34725_stat_section)
+    STATS_NAME(tcs34725_stat_section, samples_2_4ms)
+    STATS_NAME(tcs34725_stat_section, samples_24ms)
+    STATS_NAME(tcs34725_stat_section, samples_50ms)
+    STATS_NAME(tcs34725_stat_section, samples_101ms)
+    STATS_NAME(tcs34725_stat_section, samples_154ms)
+    STATS_NAME(tcs34725_stat_section, samples_700ms)
+    STATS_NAME(tcs34725_stat_section, samples_userdef)
+    STATS_NAME(tcs34725_stat_section, errors)
+STATS_NAME_END(tcs34725_stat_section)
+
+/* Global variable used to hold stats data */
+STATS_SECT_DECL(tcs34725_stat_section) g_tcs34725stats;
+#endif
+
+#if MYNEWT_VAL(TCS34725_LOG)
+#define LOG_MODULE_TCS34725 (307)
+#define TCS34725_INFO(...)  LOG_INFO(&_log, LOG_MODULE_TCS34725, __VA_ARGS__)
+#define TCS34725_ERR(...)   LOG_ERROR(&_log, LOG_MODULE_TCS34725, __VA_ARGS__)
+static struct log _log;
+#else
+#define TCS34725_INFO(...)
+#define TCS34725_ERR(...)
+#endif
+
+/* Exports for the sensor interface.
+ */
+static void *tcs34725_sensor_get_interface(struct sensor *, sensor_type_t);
+static int tcs34725_sensor_read(struct sensor *, sensor_type_t,
+        sensor_data_func_t, void *, uint32_t);
+static int tcs34725_sensor_get_config(struct sensor *, sensor_type_t,
+        struct sensor_cfg *);
+
+static const struct sensor_driver g_tcs34725_sensor_driver = {
+    tcs34725_sensor_get_interface,
+    tcs34725_sensor_read,
+    tcs34725_sensor_get_config
+};
+
+uint8_t g_tcs34725_gain;
+uint8_t g_tcs34725_integration_time;
+uint8_t g_tcs34725_enabled;
+
+/**
+ * Writes a single byte to the specified register
+ *
+ * @param The register address to write to
+ * @param The value to write
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int
+tcs34725_write8(uint8_t reg, uint32_t value)
+{
+    int rc;
+    uint8_t payload[2] = { reg | TCS34725_COMMAND_BIT, value & 0xFF };
+
+    struct hal_i2c_master_data data_struct = {
+        .address = MYNEWT_VAL(TCS34725_I2CADDR),
+        .len = 2,
+        .buffer = payload
+    };
+
+    rc = hal_i2c_master_write(MYNEWT_VAL(TCS34725_I2CBUS), &data_struct,
+                              OS_TICKS_PER_SEC / 10, 1);
+    if (rc) {
+        TCS34725_ERR("Failed to write to 0x%02X:0x%02X with value 0x%02X\n",
+                       addr, reg, value);
+#if MYNEWT_VAL(TCS34725_STATS)
+        STATS_INC(g_tcs34725stats, errors);
+#endif
+    }
+
+    return rc;
+}
+
+/**
+ * Reads a single byte from the specified register
+ *
+ * @param The register address to read from
+ * @param Pointer to where the register value should be written
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int
+tcs34725_read8(uint8_t reg, uint8_t *value)
+{
+    int rc;
+    uint8_t payload;
+
+    struct hal_i2c_master_data data_struct = {
+        .address = MYNEWT_VAL(TCS34725_I2CADDR),
+        .len = 1,
+        .buffer = &payload
+    };
+
+    /* Register write */
+    payload = reg | TCS34725_COMMAND_BIT;
+    rc = hal_i2c_master_write(MYNEWT_VAL(TCS34725_I2CBUS), &data_struct,
+                              OS_TICKS_PER_SEC / 10, 1);
+    if (rc) {
+        TCS34725_ERR("I2C access failed at address 0x%02X\n", addr);
+#if MYNEWT_VAL(TCS34725_STATS)
+        STATS_INC(g_tcs34725stats, errors);
+#endif
+        goto error;
+    }
+
+    /* Read one byte back */
+    payload = 0;
+    rc = hal_i2c_master_read(MYNEWT_VAL(TCS34725_I2CBUS), &data_struct,
+                             OS_TICKS_PER_SEC / 10, 1);
+    *value = payload;
+    if (rc) {
+        TCS34725_ERR("Failed to read from 0x%02X:0x%02X\n", addr, reg);
+#if MYNEWT_VAL(TCS34725_STATS)
+        STATS_INC(g_tcs34725stats, errors);
+#endif
+    }
+
+error:
+    return rc;
+}
+
+/**
+ * Read data from the sensor of variable length (MAX: 8 bytes)
+ *
+ * @param Register to read from
+ * @param Bufer to read into
+ * @param Length of the buffer
+ *
+ * @return 0 on success and non-zero on failure
+ */
+int
+tcs34725_readlen(uint8_t reg, uint8_t *buffer, uint8_t len)
+{
+    int rc;
+    uint8_t payload[9] = { reg | TCS34725_COMMAND_BIT, 0, 0, 0, 0, 0, 0, 0, 0};
+
+    struct hal_i2c_master_data data_struct = {
+        .address = MYNEWT_VAL(TCS34725_I2CADDR),
+        .len = 1,
+        .buffer = payload
+    };
+
+    /* Clear the supplied buffer */
+    memset(buffer, 0, len);
+
+    /* Register write */
+    rc = hal_i2c_master_write(MYNEWT_VAL(TCS34725_I2CBUS), &data_struct,
+                              OS_TICKS_PER_SEC / 10, 1);
+    if (rc) {
+        TCS34725_ERR("I2C access failed at address 0x%02X\n", addr);
+#if MYNEWT_VAL(TCS34725_STATS)
+        STATS_INC(g_tcs34725stats, errors);
+#endif
+        goto err;
+    }
+
+    /* Read len bytes back */
+    memset(payload, 0, sizeof(payload));
+    data_struct.len = len;
+    rc = hal_i2c_master_read(MYNEWT_VAL(TCS34725_I2CBUS), &data_struct,
+                             OS_TICKS_PER_SEC / 10, 1);
+
+    if (rc) {
+        TCS34725_ERR("Failed to read from 0x%02X:0x%02X\n", addr, reg);
+#if MYNEWT_VAL(TCS34725_STATS)
+        STATS_INC(g_tcs34725stats, errors);
+#endif
+        goto err;
+    }
+
+    /* Copy the I2C results into the supplied buffer */
+    memcpy(buffer, payload, len);
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Writes a multiple bytes to the specified register
+ *
+ * @param The register address to write to
+ * @param The data buffer to write from
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int
+tcs34725_writelen(uint8_t reg, uint8_t *buffer, uint8_t len)
+{
+    int rc;
+    uint8_t payload[9] = { reg, 0, 0, 0, 0, 0, 0, 0, 0};
+
+    struct hal_i2c_master_data data_struct = {
+        .address = MYNEWT_VAL(TCS34725_I2CADDR),
+        .len = 1,
+        .buffer = payload
+    };
+
+    memcpy(&payload[1], buffer, len);
+
+    /* Register write */
+    rc = hal_i2c_master_write(MYNEWT_VAL(TCS34725_I2CBUS), &data_struct,
+                              OS_TICKS_PER_SEC / 10, 1);
+    if (rc) {
+        TCS34725_ERR("I2C access failed at address 0x%02X\n", addr);
+#if MYNEWT_VAL(TCS34725_STATS)
+        STATS_INC(g_tcs34725stats, errors);
+#endif
+        goto err;
+    }
+
+    memset(payload, 0, sizeof(payload));
+    data_struct.len = len;
+    rc = hal_i2c_master_write(MYNEWT_VAL(TCS34725_I2CBUS), &data_struct,
+                              OS_TICKS_PER_SEC / 10, len);
+
+    if (rc) {
+        TCS34725_ERR("Failed to read from 0x%02X:0x%02X\n", addr, reg);
+#if MYNEWT_VAL(TCS34725_STATS)
+        STATS_INC(g_tcs34725stats, errors);
+#endif
+        goto err;
+    }
+
+    return 0;
+err:
+    return rc;
+}
+
+
+#if MYNEWT_VAL(USE_MATH)
+/**
+ * Float power function
+ *
+ * @param float base
+ * @param float exponent
+ */
+static float
+powf(float base, float exp)
+{
+    return (float)(pow((double)base, (double)exp));
+}
+
+#endif
+
+/**
+ *
+ * Enables the device
+ *
+ * @param enable/disable
+ * @return 0 on success, non-zero on error
+ */
+int
+tcs34725_enable(uint8_t enable)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = tcs34725_read8(TCS34725_REG_ENABLE, &reg);
+    if (rc) {
+        goto err;
+    }
+
+    os_time_delay((3 * OS_TICKS_PER_SEC)/1000 + 1);
+
+    if (enable) {
+        rc = tcs34725_write8(TCS34725_REG_ENABLE, reg | TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN);
+        if (rc) {
+            goto err;
+        }
+    } else {
+        rc = tcs34725_write8(TCS34725_REG_ENABLE, reg & ~(TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN));
+        if (rc) {
+            goto err;
+        }
+    }
+
+    g_tcs34725_enabled = enable;
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Expects to be called back through os_dev_create().
+ *
+ * @param The device object associated with this accellerometer
+ * @param Argument passed to OS device init, unused
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int
+tcs34725_init(struct os_dev *dev, void *arg)
+{
+    struct tcs34725 *tcs34725;
+    struct sensor *sensor;
+    int rc;
+
+    tcs34725 = (struct tcs34725 *) dev;
+
+#if MYNEWT_VAL(TCS34725_LOG)
+    log_register("tcs34725", &_log, &log_console_handler, NULL, LOG_SYSLEVEL);
+#endif
+
+    sensor = &tcs34725->sensor;
+
+#if MYNEWT_VAL(TCS34725_STATS)
+    /* Initialise the stats entry */
+    rc = stats_init(
+        STATS_HDR(g_tcs34725stats),
+        STATS_SIZE_INIT_PARMS(g_tcs34725stats, STATS_SIZE_32),
+        STATS_NAME_INIT_PARMS(tcs34725_stat_section));
+    SYSINIT_PANIC_ASSERT(rc == 0);
+    /* Register the entry with the stats registry */
+    rc = stats_register("tcs34725", STATS_HDR(g_tcs34725stats));
+    SYSINIT_PANIC_ASSERT(rc == 0);
+#endif
+
+    rc = sensor_init(sensor, dev);
+    if (rc != 0) {
+        goto err;
+    }
+
+    /* Add the color sensor driver */
+    rc = sensor_set_driver(sensor, SENSOR_TYPE_COLOR,
+                           (struct sensor_driver *) &g_tcs34725_sensor_driver);
+    if (rc != 0) {
+        goto err;
+    }
+
+    rc = sensor_mgr_register(sensor);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ * Indicates whether the sensor is enabled or not
+ *
+ * @return 1 if enabled, 0 if disabled
+ */
+uint8_t
+tcs34725_get_enable (void)
+{
+    return g_tcs34725_enabled;
+}
+
+/**
+ * Sets integration time
+ *
+ * @param integration time to be set
+ * @return 0 on success, non-zero on failure
+ */
+int
+tcs34725_set_integration_time(uint8_t int_time)
+{
+    int rc;
+
+    rc = tcs34725_write8(TCS34725_REG_ATIME,
+                         int_time | g_tcs34725_gain);
+    if (rc) {
+        goto err;
+    }
+
+    g_tcs34725_integration_time = int_time;
+
+err:
+    return rc;
+}
+
+/**
+ * Gets integration time set earlier
+ *
+ * @return integration time
+ */
+uint8_t
+tcs34725_get_integration_time(void)
+{
+    return g_tcs34725_integration_time;
+}
+
+/**
+ * Set gain of the sensor
+ *
+ * @param gain
+ * @return 0 on success, non-zero on failure
+ */
+int
+tcs34725_set_gain(uint8_t gain)
+{
+    int rc;
+
+    if (gain > TCS34725_GAIN_60X) {
+        TCS34725_ERR("Invalid gain value\n");
+        rc = SYS_EINVAL;
+        goto err;
+    }
+
+    rc = tcs34725_write8(TCS34725_REG_CONTROL,
+                        g_tcs34725_integration_time | gain);
+    if (rc) {
+        goto err;
+    }
+
+    g_tcs34725_gain = gain;
+
+err:
+    return rc;
+}
+
+/**
+ * Get gain of the sensor
+ *
+ * @return gain
+ */
+uint8_t
+tcs34725_get_gain(void)
+{
+    return g_tcs34725_gain;
+}
+
+/**
+ * Get chip ID from the sensor
+ *
+ * @param Pointer to the variable to fill up chip ID in
+ * @return 0 on success, non-zero on failure
+ */
+int
+tcs34725_get_chip_id(uint8_t *id)
+{
+    int rc;
+    uint8_t idtmp;
+
+    /* Check if we can read the chip address */
+    rc = tcs34725_read8(TCS34725_REG_ID, &idtmp);
+    if (rc) {
+        goto err;
+    }
+
+    *id = idtmp;
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Configure the sensor
+ *
+ * @param ptr to the sensor
+ * @param ptr to sensor config
+ * @return 0 on success, non-zero on failure
+ */
+int
+tcs34725_config(struct tcs34725 *tcs34725, struct tcs34725_cfg *cfg)
+{
+    int rc;
+    uint8_t id;
+
+    rc = tcs34725_get_chip_id(&id);
+    if (id != TCS34725_ID || rc != 0) {
+        rc = SYS_EINVAL;
+        goto err;
+    }
+
+    rc |= tcs34725_enable(1);
+
+    rc |= tcs34725_set_integration_time(cfg->integration_time);
+
+    rc |= tcs34725_set_gain(cfg->gain);
+    if (rc) {
+        goto err;
+    }
+
+    /* Overwrite the configuration data. */
+    memcpy(&tcs34725->cfg, cfg, sizeof(*cfg));
+
+err:
+    return (rc);
+}
+
+/**
+ * Reads the raw red, green, blue and clear channel values
+ *
+ *
+ * @param red value to return
+ * @param green value to return
+ * @param blue value to return
+ * @param clear channel value
+ * @param driver sturcture containing config
+ */
+int
+tcs34725_get_rawdata(uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c,
+                     struct tcs34725 *tcs34725)
+{
+    uint8_t payload[8] = {0};
+    int rc;
+    int delay_ticks;
+
+    /* Set a delay for the integration time */
+    switch (tcs34725->cfg.integration_time)
+    {
+        case TCS34725_INTEGRATIONTIME_2_4MS:
+            delay_ticks = (3 * OS_TICKS_PER_SEC)/1000 + 1;
+            break;
+        case TCS34725_INTEGRATIONTIME_24MS:
+            delay_ticks = (24 * OS_TICKS_PER_SEC)/1000 + 1;
+            break;
+        case TCS34725_INTEGRATIONTIME_50MS:
+            delay_ticks = (50 * OS_TICKS_PER_SEC)/1000 + 1;
+            break;
+        case TCS34725_INTEGRATIONTIME_101MS:
+            delay_ticks = (101 * OS_TICKS_PER_SEC)/1000 + 1;
+            break;
+        case TCS34725_INTEGRATIONTIME_154MS:
+            delay_ticks = (154 * OS_TICKS_PER_SEC)/1000 + 1;
+            break;
+        case TCS34725_INTEGRATIONTIME_700MS:
+            delay_ticks = (700 * OS_TICKS_PER_SEC)/1000 + 1;
+            break;
+        default:
+            /*
+             * If the integration time specified is not from the config,
+             * it will get considered as valid inetgration time in ms
+             */
+            delay_ticks = (tcs34725->cfg.integration_time * OS_TICKS_PER_SEC)/
+                          1000 + 1;
+            break;
+    }
+
+    os_time_delay(delay_ticks);
+
+    *c = *r = *g = *b = 0;
+
+    rc = tcs34725_readlen(TCS34725_REG_CDATAL, payload, 8);
+    if (rc) {
+        goto err;
+    }
+
+    *c = payload[1] << 8 | payload[0];
+    *r = payload[3] << 8 | payload[2];
+    *g = payload[5] << 8 | payload[4];
+    *b = payload[7] << 8 | payload[6];
+
+#if MYNEWT_VAL(TCS34725_STATS)
+    switch (tcs34725->cfg.integration_time) {
+        case TCS34725_INTEGRATIONTIME_2_4MS:
+            STATS_INC(g_tcs34725stats, samples_2_4ms);
+            break;
+        case TCS34725_INTEGRATIONTIME_24MS:
+            STATS_INC(g_tcs34725stats, samples_24ms);
+            break;
+        case TCS34725_INTEGRATIONTIME_50MS:
+            STATS_INC(g_tcs34725stats, samples_50ms);
+            break;
+        case TCS34725_INTEGRATIONTIME_101MS:
+            STATS_INC(g_tcs34725stats, samples_101ms);
+            break;
+        case TCS34725_INTEGRATIONTIME_154MS:
+            STATS_INC(g_tcs34725stats, samples_154ms);
+            break;
+        case TCS34725_INTEGRATIONTIME_700MS:
+            STATS_INC(g_tcs34725stats, samples_700ms);
+        default:
+            STATS_INC(g_tcs34725stats, samples_userdef);
+        break;
+    }
+
+#endif
+
+    return 0;
+err:
+    return rc;
+
+}
+
+/**
+ *
+ * Converts raw RGB values to color temp in deg K
+ *
+ * @param red value
+ * @param green value
+ * @param blue value
+ * @return final CCT value using McCamy's formula
+ */
+static uint16_t
+tcs34725_calculate_color_temp(uint16_t r, uint16_t g, uint16_t b)
+{
+    float n;
+    float cct;
+
+    /**
+     * From the designer's notebook by TAOS:
+     * Mapping sensor response  RGB values to CIE tristimulus values(XYZ)
+     * based on broad enough transformation, the light sources chosen were a
+     * high color temperature fluorescent (6500K), a low color temperature
+     * fluorescent (3000K), and an incandescent (60W)
+     * Note: y = Illuminance or lux
+     *
+     * For applications requiring more precision,
+     * narrower range of light sources should be used and a new correlation
+     * matrix could be formulated and CIE tristimulus values should be
+     * calculated. Please refer the manual for calculating tristumulus values.
+     *
+     * x = (-0.14282F * r) + (1.54924F * g) + (-0.95641F * b);
+     * y = (-0.32466F * r) + (1.57837F * g) + (-0.73191F * b);
+     * z = (-0.68202F * r) + (0.77073F * g) + ( 0.56332F * b);
+     *
+     *
+     * Calculating chromaticity co-ordinates, the light can be plotted on a two
+     * dimensional chromaticity diagram
+     *
+     * xc = x / (x + y + z);
+     * yc = y / (x + y + z);
+     *
+     * Use McCamy's formula to determine the CCT
+     * n = (xc - 0.3320F) / (0.1858F - yc);
+     */
+
+     /*
+      * n can be calculated directly using the following formula for
+      * above considerations
+      */
+    n = ((0.23881)*r + (0.25499)*g + (-0.58291)*b) / ((0.11109)*r + (-0.85406)*g +
+         (0.52289)*b);
+
+    /*
+     * Calculate the final CCT
+     * CCT is only meant to characterize near white lights.
+     */
+
+#if MYNEWT_VAL(USE_MATH)
+    cct = (449.0F * powf(n, 3)) + (3525.0F * powf(n, 2)) + (6823.3F * n) + 5520.33F;
+#else
+    cct = (449.0F * n * n * n) + (3525.0F * n * n) + (6823.3F * n) + 5520.33F;
+#endif
+
+    /* Return the results in degrees Kelvin */
+    return (uint16_t)cct;
+}
+
+/**
+ *
+ * Converts the raw RGB values to lux
+ *
+ * @param red value
+ * @param green value
+ * @param blue value
+ * @return lux value
+ */
+static uint16_t
+tcs34725_calculate_lux(uint16_t r, uint16_t g, uint16_t b)
+{
+    float lux;
+
+    lux = (-0.32466F * r) + (1.57837F * g) + (-0.73191F * b);
+
+    return (uint16_t)lux;
+}
+
+
+
+static int
+tcs34725_sensor_read(struct sensor *sensor, sensor_type_t type,
+        sensor_data_func_t data_func, void *data_arg, uint32_t timeout)
+{
+    struct tcs34725 *tcs34725;
+    struct sensor_color_data scd;
+    uint16_t r;
+    uint16_t g;
+    uint16_t b;
+    uint16_t c;
+    int rc;
+
+    /* If the read isn't looking for accel or mag data, don't do anything. */
+    if (!(type & SENSOR_TYPE_COLOR)) {
+        rc = SYS_EINVAL;
+        goto err;
+    }
+
+    tcs34725 = (struct tcs34725 *) SENSOR_GET_DEVICE(sensor);
+
+    /* Get a new accelerometer sample */
+    if (type & SENSOR_TYPE_COLOR) {
+        r = g = b = c = 0;
+
+        rc = tcs34725_get_rawdata(&r, &g, &b, &c, tcs34725);
+        if (rc) {
+            goto err;
+        }
+
+        scd.scd_r = r;
+        scd.scd_g = g;
+        scd.scd_b = b;
+        scd.scd_c = c;
+        scd.scd_lux = tcs34725_calculate_lux(r, g, b);
+        scd.scd_colortemp = tcs34725_calculate_color_temp(r, g, b);
+
+        /* Call data function */
+        rc = data_func(sensor, data_arg, &scd);
+        if (rc != 0) {
+            goto err;
+        }
+    }
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * enables/disables interrupts
+ *
+ * @param enable/disable
+ * @return 0 on success, non-zero on failure
+ */
+int
+tcs34725_enable_interrupt(uint8_t enable)
+{
+    uint8_t reg;
+    int rc;
+
+    rc = tcs34725_read8(TCS34725_REG_ENABLE, &reg);
+    if (rc) {
+        goto err;
+    }
+
+    if (enable) {
+        reg |= TCS34725_ENABLE_AIEN;
+    } else {
+        reg &= ~TCS34725_ENABLE_AIEN;
+    }
+
+    rc = tcs34725_write8(TCS34725_REG_ENABLE, reg);
+    if (rc) {
+        goto err;
+    }
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Clears the interrupt by writing to the command register
+ * as a special function
+ * ______________________________________________________
+ * |   CMD |     TYPE    |         ADDR/SF              |
+ * |    7  |     6:5     |           4:0                |
+ * |    1  |      11     |          00110               |
+ * |_______|_____________|______________________________|
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+tcs34725_clear_interrupt(void)
+{
+    int rc;
+    uint8_t payload = TCS34725_COMMAND_BIT | TCS34725_CMD_TYPE | TCS34725_CMD_ADDR;
+
+    struct hal_i2c_master_data data_struct = {
+        .address = MYNEWT_VAL(TCS34725_I2CADDR),
+        .len = 0,
+        .buffer = &payload
+    };
+
+    rc = hal_i2c_master_write(MYNEWT_VAL(TCS34725_I2CBUS), &data_struct,
+                              OS_TICKS_PER_SEC / 10, 1);
+    if (rc) {
+        goto err;
+    }
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Sets threshold limits for interrupts, if the low threshold is set above
+ * the high threshold, the high threshold is ignored and only the low
+ * threshold is evaluated
+ *
+ * @param lower threshold
+ * @param higher threshold
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+tcs34725_set_int_limits(uint16_t low, uint16_t high)
+{
+    uint8_t payload[4];
+    int rc;
+
+    payload[0] = low & 0xFF;
+    payload[1] = low >> 8;
+    payload[2] = high & 0xFF;
+    payload[3] = high >> 8;
+
+    rc = tcs34725_writelen(TCS34725_REG_AILTL, payload, sizeof(payload));
+    if (rc) {
+        return rc;
+    }
+    return 0;
+}
+
+static void *
+tcs34725_sensor_get_interface(struct sensor *sensor, sensor_type_t type)
+{
+    return (NULL);
+}
+
+/**
+ *
+ * Gets threshold limits for interrupts, if the low threshold is set above
+ * the high threshold, the high threshold is ignored and only the low
+ * threshold is evaluated
+ *
+ * @param ptr to lower threshold
+ * @param ptr to higher threshold
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+tcs34725_get_int_limits(uint16_t *low, uint16_t *high)
+{
+    uint8_t payload[4];
+    int rc;
+
+    rc = tcs34725_readlen(TCS34725_REG_AILTL, payload, sizeof(payload));
+    if (rc) {
+        return rc;
+    }
+
+    *low   = payload[0];
+    *low  |= payload[1] << 8;
+    *high  = payload[2];
+    *high |= payload[3] << 8;
+
+    return 0;
+}
+
+static int
+tcs34725_sensor_get_config(struct sensor *sensor, sensor_type_t type,
+                           struct sensor_cfg *cfg)
+{
+    int rc;
+
+    if ((type != SENSOR_TYPE_COLOR)) {
+        rc = SYS_EINVAL;
+        goto err;
+    }
+
+    cfg->sc_valtype = SENSOR_VALUE_TYPE_INT32;
+
+    return (0);
+err:
+    return (rc);
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2d4f8a76/hw/drivers/sensors/tcs34725/src/tcs34725_priv.h
----------------------------------------------------------------------
diff --git a/hw/drivers/sensors/tcs34725/src/tcs34725_priv.h b/hw/drivers/sensors/tcs34725/src/tcs34725_priv.h
new file mode 100644
index 0000000..4c47929
--- /dev/null
+++ b/hw/drivers/sensors/tcs34725/src/tcs34725_priv.h
@@ -0,0 +1,278 @@
+/*
+ * 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
+ * resarding 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 __TCS34725_PRIV_H__
+#define __TCS34725_PRIV_H__
+
+#define TCS34725_ID               0x44
+
+/* COMMAND Register - Specific register address */
+#define TCS34725_COMMAND_BIT      (1 << 7)
+#define TCS34725_CMD_TYPE         (3 << 5)
+#define TCS34725_CMD_ADDR         (6 << 1)
+
+/* Enable register */
+#define TCS34725_REG_ENABLE       0x00
+#define TCS34725_ENABLE_AIEN      0x10    /* enable/disable RGBC interrupt */
+#define TCS34725_ENABLE_WEN       0x08    /* enable/disable wait timer */
+#define TCS34725_ENABLE_AEN       0x02    /* enable/disable ADC */
+#define TCS34725_ENABLE_PON       0x01    /* enable/disable int oscillator */
+
+/* Integration time */
+#define TCS34725_REG_ATIME        0x01
+
+/* Wait time register (if TCS34725_ENABLE_WEN is asserted) */
+#define TCS34725_REG_WTIME        0x03
+#define TCS34725_WTIME_2_4MS      0xFF    /* WLONG0 = 2.4ms WLONG1 = 0.029s */
+#define TCS34725_WTIME_204MS      0xAB    /* WLONG0 = 204ms WLONG1 = 2.45s  */
+#define TCS34725_WTIME_614MS      0x00    /* WLONG0 = 614ms WLONG1 = 7.4s   */
+
+/* Clear channel lower interrupt threshold register */
+#define TCS34725_REG_AILTL        0x04
+#define TCS34725_REG_AILTH        0x05
+
+/* Clear channel upper interrupt threshold register */
+#define TCS34725_REG_AIHTL        0x06
+#define TCS34725_REG_AIHTH        0x07
+
+/* Persistence register */
+#define TCS34725_REG_PERS         0x0C
+#define TCS34725_PERS_NONE        0x00    /* interrupt for each RGBC cycle */
+#define TCS34725_PERS_1_CYCLE     0x01    /* interrupt for 1 RGBC cycle    */
+#define TCS34725_PERS_2_CYCLE     0x02    /* interrupt for 2 RGBC cycle    */
+#define TCS34725_PERS_3_CYCLE     0x03    /* interrupt for 3 RGBC cycle    */
+#define TCS34725_PERS_5_CYCLE     0x04    /* interrupt for 5 RGBC cycle    */
+#define TCS34725_PERS_10_CYCLE    0x05    /* interrupt for 10 RGBC cycle   */
+#define TCS34725_PERS_15_CYCLE    0x06    /* interrupt for 15 RGBC cycle   */
+#define TCS34725_PERS_20_CYCLE    0x07    /* interrupt for 20 RGBC cycle   */
+#define TCS34725_PERS_25_CYCLE    0x08    /* interrupt for 25 RGBC cycle   */
+#define TCS34725_PERS_30_CYCLE    0x09    /* interrupt for 30 RGBC cycle   */
+#define TCS34725_PERS_35_CYCLE    0x0A    /* interrupt for 35 RGBC cycle   */
+#define TCS34725_PERS_40_CYCLE    0x0B    /* interrupt for 40 RGBC cycle   */
+#define TCS34725_PERS_45_CYCLE    0x0C    /* interrupt for 45 RGBC cycle   */
+#define TCS34725_PERS_50_CYCLE    0x0D    /* interrupt for 50 RGBC cycle   */
+#define TCS34725_PERS_55_CYCLE    0x0E    /* interrupt for 55 RGBC cycle   */
+#define TCS34725_PERS_60_CYCLE    0x0F    /* interrupt for 60 RGBC cycle   */
+
+/* Configuration register */
+#define TCS34725_REG_CONFIG       0x0D
+#define TCS34725_CONFIG_WLONG     0x02    /* 0x or 12x TCS34725_WTIME */
+
+/* Set the gain level for the sensor */
+#define TCS34725_REG_CONTROL      0x0F
+
+/* Should be 0x44 for TCS34725 */
+#define TCS34725_REG_ID           0x12
+
+/* Device status register */
+#define TCS34725_REG_STATUS       0x13
+#define TCS34725_STATUS_AINT      0x10    /* RGBC Clean channel interrupt  */
+#define TCS34725_STATUS_AVALID    0x01    /* RGBC completed an integ cycle */
+
+/* Clear channel data */
+#define TCS34725_REG_CDATAL       0x14
+#define TCS34725_REG_CDATAH       0x15
+
+/* Red channel data */
+#define TCS34725_REG_RDATAL       0x16
+#define TCS34725_REG_RDATAH       0x17
+
+/* Green channel data */
+#define TCS34725_REG_GDATAL       0x18
+#define TCS34725_REG_GDATAH       0x19
+
+/* Blue channel data */
+#define TCS34725_REG_BDATAL       0x1A
+#define TCS34725_REG_BDATAH       0x1B
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Writes a single byte to the specified register
+ *
+ * @param The register address to write to
+ * @param The value to write
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+
+int tcs34725_write8(uint8_t reg, uint32_t value);
+
+/**
+ * Writes multiple bytes to the specified register
+ *
+ * @param The register address to write to
+ * @param The data buffer to write from
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int
+tcs34725_writelen(uint8_t reg, uint8_t *buffer, uint8_t len);
+
+
+/**
+ * Reads a single byte from the specified register
+ *
+ * @param The register address to read from
+ * @param Pointer to where the register value should be written
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int
+tcs34725_read8(uint8_t reg, uint8_t *value);
+
+/**
+ * Read data from the sensor of variable length (MAX: 8 bytes)
+ *
+ *
+ * @param Register to read from
+ * @param Bufer to read into
+ * @param Length of the buffer
+ *
+ * @return 0 on success and non-zero on failure
+ */
+int
+tcs34725_readlen(uint8_t reg, uint8_t *buffer, uint8_t len);
+
+/**
+ * Get chip ID from the sensor
+ *
+ * @param Pointer to the variable to fill up chip ID in
+ * @return 0 on success, non-zero on failure
+ */
+int
+tcs34725_get_chip_id(uint8_t *id);
+
+/**
+ * Get gain of the sensor
+ *
+ * @return gain
+ */
+uint8_t
+tcs34725_get_gain(void);
+
+/**
+ * Set gain of the sensor
+ *
+ * @param gain
+ * @return 0 on success, non-zero on failure
+ */
+int
+tcs34725_set_gain(uint8_t gain);
+
+/**
+ * enables/disables interrupts
+ *
+ * @param enable/disable
+ * @return 0 on success, non-zero on failure
+ */
+int
+tcs34725_enable_interrupt(uint8_t enable);
+
+/**
+ * Clears the interrupts
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+tcs34725_clear_interrupt(void);
+
+/**
+ * Sets threshold limits for interrupts, if the low threshold is set above
+ * the high threshold, the high threshold is ignored and only the low
+ * threshold is evaluated
+ *
+ * @param lower threshold
+ * @param higher threshold
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+tcs34725_set_int_limits(uint16_t low, uint16_t high);
+
+/**
+ * Sets integration time
+ *
+ * @param integration time to be set
+ * @return 0 on success, non-zero on failure
+ */
+int
+tcs34725_set_integration_time(uint8_t int_time);
+
+/**
+ * Gets integration time set earlier
+ *
+ * @return integration time
+ */
+uint8_t
+tcs34725_get_integration_time(void);
+
+/**
+ *
+ * Enables the device
+ *
+ * @param enable/disable
+ * @return 0 on success, non-zero on error
+ */
+int
+tcs34725_enable(uint8_t enable);
+
+/**
+ * Indicates whether the sensor is enabled or not
+ *
+ * @return 1 if enabled, 0 if disabled
+ */
+uint8_t
+tcs34725_get_enable (void);
+
+/**
+ * Reads the raw red, green, blue and clear channel values
+ *
+ *
+ * @param red value to return
+ * @param green value to return
+ * @param blue value to return
+ * @param clear channel value
+ * @param driver sturcture containing config
+ */
+int
+tcs34725_get_rawdata(uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c,
+                     struct tcs34725 *tcs34725);
+
+/**
+ *
+ * Gets threshold limits for interrupts, if the low threshold is set above
+ * the high threshold, the high threshold is ignored and only the low
+ * threshold is evaluated
+ *
+ * @param ptr to lower threshold
+ * @param ptr to higher threshold
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+tcs34725_get_int_limits(uint16_t *low, uint16_t *high);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TCS34725_PRIV_H_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2d4f8a76/hw/drivers/sensors/tcs34725/src/tcs34725_shell.c
----------------------------------------------------------------------
diff --git a/hw/drivers/sensors/tcs34725/src/tcs34725_shell.c b/hw/drivers/sensors/tcs34725/src/tcs34725_shell.c
new file mode 100644
index 0000000..e15b4fc
--- /dev/null
+++ b/hw/drivers/sensors/tcs34725/src/tcs34725_shell.c
@@ -0,0 +1,471 @@
+/*
+ * 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
+ * resarding 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.
+ */
+
+#include <string.h>
+#include "sysinit/sysinit.h"
+#include "console/console.h"
+#include "shell/shell.h"
+#include "hal/hal_gpio.h"
+#include "tcs34725/tcs34725.h"
+#include "tcs34725_priv.h"
+#include "defs/error.h"
+
+#if MYNEWT_VAL(TCS34725_CLI)
+extern uint8_t g_tcs34725_integration_time;
+extern uint8_t g_tcs34725_gain;
+
+static int tcs34725_shell_cmd(int argc, char **argv);
+
+static struct shell_cmd tcs34725_shell_cmd_struct = {
+    .sc_cmd = "tcs34725",
+    .sc_cmd_func = tcs34725_shell_cmd
+};
+
+static int
+tcs34725_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 SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+static int
+tcs34725_shell_err_too_many_args(char *cmd_name)
+{
+    console_printf("Error: too many arguments for command \"%s\"\n",
+                   cmd_name);
+    return SYS_EINVAL;
+}
+
+static int
+tcs34725_shell_err_unknown_arg(char *cmd_name)
+{
+    console_printf("Error: unknown argument \"%s\"\n",
+                   cmd_name);
+    return SYS_EINVAL;
+}
+
+static int
+tcs34725_shell_err_invalid_arg(char *cmd_name)
+{
+    console_printf("Error: invalid argument \"%s\"\n",
+                   cmd_name);
+    return SYS_EINVAL;
+}
+
+static int
+tcs34725_shell_help(void)
+{
+    console_printf("%s cmd [flags...]\n", tcs34725_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
+tcs34725_shell_cmd_read(int argc, char **argv)
+{
+    uint16_t r;
+    uint16_t g;
+    uint16_t b;
+    uint16_t c;
+    uint16_t samples = 1;
+    long val;
+    int rc;
+    struct tcs34725 tcs34725;
+
+    if (argc > 3) {
+        return tcs34725_shell_err_too_many_args(argv[1]);
+    }
+
+    /* Check if more than one sample requested */
+    if (argc == 3) {
+        if (tcs34725_shell_stol(argv[2], 1, UINT16_MAX, &val)) {
+            return tcs34725_shell_err_invalid_arg(argv[2]);
+        }
+        samples = (uint16_t)val;
+    }
+
+    while(samples--) {
+
+        tcs34725.cfg.gain = g_tcs34725_gain;
+        tcs34725.cfg.integration_time = g_tcs34725_integration_time;
+
+        rc = tcs34725_get_rawdata(&r, &g, &b, &c, &tcs34725);
+        if (rc) {
+            console_printf("Read failed: %d\n", rc);
+            return rc;
+        }
+
+        console_printf("r: %u g: %u b: %u c: %u \n", r, g, b, c);
+    }
+
+    return 0;
+}
+
+
+static int
+tcs34725_shell_cmd_gain(int argc, char **argv)
+{
+    long val;
+    uint8_t gain;
+    int rc;
+
+    if (argc > 3) {
+        return tcs34725_shell_err_too_many_args(argv[1]);
+    }
+
+    /* Display the gain */
+    if (argc == 2) {
+        gain = tcs34725_get_gain();
+        console_printf("\tgain [0: 1|1: 4|2: 16|3: 60]\n");
+        console_printf("%u\n", gain);
+    }
+
+    /* Update the gain */
+    if (argc == 3) {
+        if (tcs34725_shell_stol(argv[2], 0, 3, &val)) {
+            return tcs34725_shell_err_invalid_arg(argv[2]);
+        }
+        /* Make sure gain is valid */
+        if (val > 3) {
+            return tcs34725_shell_err_invalid_arg(argv[2]);
+        }
+        rc = tcs34725_set_gain(val);
+        if (rc) {
+            goto err;
+        }
+    }
+
+    return 0;
+err:
+    return rc;
+}
+
+
+static int
+tcs34725_shell_cmd_time(int argc, char **argv)
+{
+    uint8_t time;
+    long val;
+    int rc;
+
+    if (argc > 3) {
+        return tcs34725_shell_err_too_many_args(argv[1]);
+    }
+
+    /* Display the integration time */
+    if (argc == 2) {
+        time = tcs34725_get_integration_time();
+        switch (time) {
+            case TCS34725_INTEGRATIONTIME_2_4MS:
+                console_printf("2.4\n");
+                break;
+            case TCS34725_INTEGRATIONTIME_24MS:
+                console_printf("24\n");
+                break;
+            case TCS34725_INTEGRATIONTIME_50MS:
+                console_printf("50\n");
+                break;
+            case TCS34725_INTEGRATIONTIME_101MS:
+                console_printf("101\n");
+                break;
+            case TCS34725_INTEGRATIONTIME_154MS:
+                console_printf("154\n");
+                break;
+            case TCS34725_INTEGRATIONTIME_700MS:
+                console_printf("700\n");
+                break;
+            default:
+                assert(0);
+                break;
+        }
+    }
+
+    /* Set the integration time */
+    if (argc == 3) {
+        if (tcs34725_shell_stol(argv[2], 0, 5, &val)) {
+            return tcs34725_shell_err_invalid_arg(argv[2]);
+        }
+
+        switch(val) {
+            case 0:
+                time = TCS34725_INTEGRATIONTIME_2_4MS;
+                break;
+            case 1:
+                time = TCS34725_INTEGRATIONTIME_24MS;
+                break;
+            case 2:
+                time = TCS34725_INTEGRATIONTIME_50MS;
+                break;
+            case 3:
+                time = TCS34725_INTEGRATIONTIME_101MS;
+                break;
+            case 4:
+                time = TCS34725_INTEGRATIONTIME_154MS;
+                break;
+            case 5:
+                time = TCS34725_INTEGRATIONTIME_700MS;
+                break;
+            default:
+                assert(0);
+        }
+
+        rc = tcs34725_set_integration_time(time);
+        if (rc) {
+            goto err;
+        }
+    }
+
+    return 0;
+err:
+    return rc;
+}
+
+
+static int
+tcs34725_shell_cmd_int(int argc, char **argv)
+{
+    int rc;
+    int pin;
+    long val;
+    uint16_t lower;
+    uint16_t upper;
+
+    if (argc > 6) {
+        return tcs34725_shell_err_too_many_args(argv[1]);
+    }
+
+    if (argc == 2) {
+        rc = tcs34725_get_int_limits(&lower, &upper);
+        if (rc) {
+            return rc;
+        }
+        console_printf("Interrupt lower limit: %u upper limit: %u",
+                       lower, upper);
+        return 0;
+    }
+
+    /* Enable the interrupt */
+    if (argc == 3 && strcmp(argv[2], "on") == 0) {
+        return tcs34725_enable_interrupt(1);
+    }
+
+    /* Disable the interrupt */
+    if (argc == 3 && strcmp(argv[2], "off") == 0) {
+        return tcs34725_enable_interrupt(0);
+    }
+
+    /* Clear the interrupt on 'clr' */
+    if (argc == 3 && strcmp(argv[2], "clr") == 0) {
+        return tcs34725_clear_interrupt();
+    }
+
+    /* Configure the interrupt on 'set' */
+    if (argc == 3 && strcmp(argv[2], "set") == 0) {
+        /* Get lower threshold */
+        if (tcs34725_shell_stol(argv[4], 0, UINT16_MAX, &val)) {
+            return tcs34725_shell_err_invalid_arg(argv[4]);
+        }
+        lower = (uint16_t)val;
+        /* Get upper threshold */
+        if (tcs34725_shell_stol(argv[5], 0, UINT16_MAX, &val)) {
+            return tcs34725_shell_err_invalid_arg(argv[5]);
+        }
+        upper = (uint16_t)val;
+        /* Set the values */
+        rc = tcs34725_set_int_limits(lower, upper);
+        console_printf("Configured interrupt as:\n");
+        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 (tcs34725_shell_stol(argv[3], 0, 0xFF, &val)) {
+            return tcs34725_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 tcs34725_shell_err_invalid_arg(argv[2]);
+}
+
+
+static int
+tcs34725_shell_cmd_en(int argc, char **argv)
+{
+    char *endptr;
+    long lval;
+
+    if (argc > 3) {
+        return tcs34725_shell_err_too_many_args(argv[1]);
+    }
+
+    /* Display current enable state */
+    if (argc == 2) {
+        console_printf("%u\n", tcs34725_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) {
+                tcs34725_enable(lval);
+        } else {
+            return tcs34725_shell_err_invalid_arg(argv[2]);
+        }
+    }
+
+    return 0;
+}
+
+static int
+tcs34725_shell_cmd_dump(int argc, char **argv)
+{
+  uint8_t val;
+
+  if (argc > 3) {
+      return tcs34725_shell_err_too_many_args(argv[1]);
+  }
+
+  /* Dump all the register values for debug purposes */
+  val = 0;
+  assert(0 == tcs34725_read8(TCS34725_REG_ENABLE, &val));
+  console_printf("0x%02X (ENABLE): 0x%02X\n", TCS34725_REG_ENABLE, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_ATIME, &val));
+  console_printf("0x%02X (ATIME):  0x%02X\n", TCS34725_REG_ATIME, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_WTIME, &val));
+  console_printf("0x%02X (WTIME):   0x%02X\n", TCS34725_REG_WTIME, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_AILTL, &val));
+  console_printf("0x%02X (AILTL):   0x%02X\n", TCS34725_REG_AILTL, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_AILTH, &val));
+  console_printf("0x%02X (AILTH):   0x%02X\n", TCS34725_REG_AILTH, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_AIHTL, &val));
+  console_printf("0x%02X (AIHTL):   0x%02X\n", TCS34725_REG_AIHTL, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_AIHTH, &val));
+  console_printf("0x%02X (AIHTH):   0x%02X\n", TCS34725_REG_AIHTH, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_PERS, &val));
+  console_printf("0x%02X (PERS):   0x%02X\n", TCS34725_REG_PERS, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_CONFIG, &val));
+  console_printf("0x%02X (CONFIG):   0x%02X\n", TCS34725_REG_CONFIG, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_CONTROL, &val));
+  console_printf("0x%02X (CONTROL):   0x%02X\n", TCS34725_REG_CONTROL, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_ID, &val));
+  console_printf("0x%02X (ID):    0x%02X\n", TCS34725_REG_ID, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_STATUS, &val));
+  console_printf("0x%02X (STATUS):    0x%02X\n", TCS34725_REG_STATUS, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_CDATAL, &val));
+  console_printf("0x%02X (CDATAL):    0x%02X\n", TCS34725_REG_CDATAL, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_CDATAH, &val));
+  console_printf("0x%02X (CDATAH):    0x%02X\n", TCS34725_REG_CDATAH, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_RDATAL, &val));
+  console_printf("0x%02X (RDATAL):    0x%02X\n", TCS34725_REG_RDATAL, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_RDATAH, &val));
+  console_printf("0x%02X (RDATAH):    0x%02X\n", TCS34725_REG_RDATAH, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_GDATAL, &val));
+  console_printf("0x%02X (GDATAL):    0x%02X\n", TCS34725_REG_GDATAL, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_GDATAH, &val));
+  console_printf("0x%02X (GDATAH):    0x%02X\n", TCS34725_REG_GDATAH, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_BDATAL, &val));
+  console_printf("0x%02X (BDATAL):    0x%02X\n", TCS34725_REG_BDATAL, val);
+  assert(0 == tcs34725_read8(TCS34725_REG_BDATAH, &val));
+  console_printf("0x%02X (BDATAH):    0x%02X\n", TCS34725_REG_BDATAH, val);
+
+  return 0;
+}
+
+static int
+tcs34725_shell_cmd(int argc, char **argv)
+{
+    if (argc == 1) {
+        return tcs34725_shell_help();
+    }
+
+    /* Read command (get a new data sample) */
+    if (argc > 1 && strcmp(argv[1], "r") == 0) {
+        return tcs34725_shell_cmd_read(argc, argv);
+    }
+
+    /* Gain command */
+    if (argc > 1 && strcmp(argv[1], "gain") == 0) {
+        return tcs34725_shell_cmd_gain(argc, argv);
+    }
+
+    /* Integration time command */
+    if (argc > 1 && strcmp(argv[1], "time") == 0) {
+        return tcs34725_shell_cmd_time(argc, argv);
+    }
+
+    /* Enable */
+    if (argc > 1 && strcmp(argv[1], "en") == 0) {
+        return tcs34725_shell_cmd_en(argc, argv);
+    }
+
+    /* Interrupt */
+    if (argc > 1 && strcmp(argv[1], "int") == 0) {
+        return tcs34725_shell_cmd_int(argc, argv);
+    }
+
+    /* Debug */
+    if (argc > 1 && strcmp(argv[1], "dumpreg") == 0) {
+        return tcs34725_shell_cmd_dump(argc, argv);
+    }
+
+    return tcs34725_shell_err_unknown_arg(argv[1]);
+}
+
+int
+tcs34725_shell_init(void)
+{
+    int rc;
+
+    rc = shell_cmd_register(&tcs34725_shell_cmd_struct);
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    return rc;
+}
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2d4f8a76/hw/drivers/sensors/tcs34725/syscfg.yml
----------------------------------------------------------------------
diff --git a/hw/drivers/sensors/tcs34725/syscfg.yml b/hw/drivers/sensors/tcs34725/syscfg.yml
new file mode 100644
index 0000000..4df3b64
--- /dev/null
+++ b/hw/drivers/sensors/tcs34725/syscfg.yml
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+syscfg.defs:
+    TCS34725_I2CADDR:
+        description: 'HW I2C address for the TCS34725 (0x29)'
+        value: 0x29
+    TCS34725_I2CBUS:
+        description: 'I2C bus number for the TCS34725'
+        value: -1
+    TCS34725_CLI:
+        description: 'Enable shell support for the TCS34725'
+        value: 0
+    TCS34725_LOG:
+        description: 'Enable TCS34725 logging'
+        value: 0
+    TCS34725_STATS:
+        description: 'Enable TCS34725 statistics'
+        value: 0

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2d4f8a76/hw/sensor/include/sensor/color.h
----------------------------------------------------------------------
diff --git a/hw/sensor/include/sensor/color.h b/hw/sensor/include/sensor/color.h
new file mode 100644
index 0000000..6f219d7
--- /dev/null
+++ b/hw/sensor/include/sensor/color.h
@@ -0,0 +1,51 @@
+/*
+ * 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_COLOR_H__
+#define __SENSOR_COLOR_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 color sensor
+ */
+struct sensor_color_data {
+    uint16_t scd_r;         /* Red data   */
+    uint16_t scd_g;         /* Green data */
+    uint16_t scd_b;         /* Blue data  */
+    uint16_t scd_c;         /* Clear data */
+    uint16_t scd_lux;       /* Lux data   */
+    uint16_t scd_colortemp; /* Color temp */
+} __attribute__((packed));
+
+/**
+ * Color Sensor data is unused for this field.
+ */
+#define SENSOR_COLOR_DATA_UNUSED (-1)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SENSOR_COLOR_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2d4f8a76/hw/sensor/include/sensor/sensor.h
----------------------------------------------------------------------
diff --git a/hw/sensor/include/sensor/sensor.h b/hw/sensor/include/sensor/sensor.h
index 813634b..9dc7cc0 100644
--- a/hw/sensor/include/sensor/sensor.h
+++ b/hw/sensor/include/sensor/sensor.h
@@ -72,12 +72,12 @@ typedef enum {
     SENSOR_TYPE_GRAVITY              = (1 << 27),
     /* Euler Orientation Sensor */
     SENSOR_TYPE_EULER                = (1 << 28),
+    /* Color Sensor */
+    SENSOR_TYPE_COLOR                = (1 << 29),
     /* User defined sensor type 1 */
-    SENSOR_TYPE_USER_DEFINED_1       = (1 << 29),
+    SENSOR_TYPE_USER_DEFINED_1       = (1 << 30),
     /* User defined sensor type 2 */
-    SENSOR_TYPE_USER_DEFINED_2       = (1 << 30),
-    /* User defined sensor type 3 */
-    SENSOR_TYPE_USER_DEFINED_3       = (1 << 31),
+    SENSOR_TYPE_USER_DEFINED_2       = (1 << 31),
     /* A selector, describes all sensors */
     SENSOR_TYPE_ALL                  = 0xFFFFFFFF
 } sensor_type_t;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2d4f8a76/hw/sensor/src/sensor_shell.c
----------------------------------------------------------------------
diff --git a/hw/sensor/src/sensor_shell.c b/hw/sensor/src/sensor_shell.c
index 291ae04..3d86beb 100644
--- a/hw/sensor/src/sensor_shell.c
+++ b/hw/sensor/src/sensor_shell.c
@@ -36,6 +36,7 @@
 #include "sensor/light.h"
 #include "sensor/quat.h"
 #include "sensor/euler.h"
+#include "sensor/color.h"
 #include "console/console.h"
 #include "shell/shell.h"
 #include "hal/hal_i2c.h"
@@ -107,6 +108,7 @@ sensor_shell_read_listener(struct sensor *sensor, void *arg, void *data)
     struct sensor_light_data *sld;
     struct sensor_euler_data *sed;
     struct sensor_quat_data *sqd;
+    struct sensor_color_data *scd;
     int8_t *temperature;
     char tmpstr[13];
 
@@ -196,6 +198,29 @@ sensor_shell_read_listener(struct sensor *sensor, void *arg, void *data)
         console_printf("\n");
     }
 
+    if (ctx->type == SENSOR_TYPE_COLOR) {
+        scd = (struct sensor_color_data *) data;
+        if (scd->scd_r != SENSOR_LIGHT_DATA_UNUSED) {
+            console_printf("red = %u, ", scd->scd_r);
+        }
+        if (scd->scd_g != SENSOR_LIGHT_DATA_UNUSED) {
+            console_printf("green = %u, ", scd->scd_g);
+        }
+        if (scd->scd_b != SENSOR_LIGHT_DATA_UNUSED) {
+            console_printf("blue = %u, ", scd->scd_b);
+        }
+        if (scd->scd_c != SENSOR_LIGHT_DATA_UNUSED) {
+            console_printf("clear = %u, ", scd->scd_c);
+        }
+        if (scd->scd_lux != SENSOR_LIGHT_DATA_UNUSED) {
+            console_printf("lux = %u, ", scd->scd_lux);
+        }
+        if (scd->scd_colortemp != SENSOR_LIGHT_DATA_UNUSED) {
+            console_printf("color temperature = %u, ", scd->scd_colortemp);
+        }
+        console_printf("\n");
+    }
+
     return (0);
 }