diff --git a/app/include/user_modules.h b/app/include/user_modules.h index 18fc5cfa..cc23f794 100644 --- a/app/include/user_modules.h +++ b/app/include/user_modules.h @@ -40,6 +40,7 @@ #define LUA_USE_MODULES_RTCFIFO #define LUA_USE_MODULES_SNTP //#define LUA_USE_MODULES_BMP085 +#define LUA_USE_MODULES_TSL2561 #endif /* LUA_USE_MODULES */ diff --git a/app/include/user_version.h b/app/include/user_version.h index 40ce7eb4..b4018097 100644 --- a/app/include/user_version.h +++ b/app/include/user_version.h @@ -7,6 +7,6 @@ #define NODE_VERSION_INTERNAL 0U #define NODE_VERSION "NodeMCU 0.9.6" -#define BUILD_DATE "build 20150627" +#define BUILD_DATE "build 20150822" #endif /* __USER_VERSION_H__ */ diff --git a/app/modules/modules.h b/app/modules/modules.h index 176f4591..db5a8b8b 100644 --- a/app/modules/modules.h +++ b/app/modules/modules.h @@ -221,6 +221,13 @@ #define ROM_MODULES_BMP085 #endif +#if defined(LUA_USE_MODULES_TSL2561) +#define MODULES_TSL2561 "TSL2561" +#define ROM_MODULES_TSL2561 \ + _ROM(MODULES_TSL2561, luaopen_tsl2561, tsl2561_map) +#else +#define ROM_MODULES_TSL2561 +#endif #define LUA_MODULES_ROM \ ROM_MODULES_GPIO \ @@ -250,5 +257,5 @@ ROM_MODULES_RTCFIFO \ ROM_MODULES_SNTP \ ROM_MODULES_BMP085 \ - + ROM_MODULES_TSL2561 \ #endif diff --git a/app/modules/tsl2561.c b/app/modules/tsl2561.c new file mode 100644 index 00000000..3546f144 --- /dev/null +++ b/app/modules/tsl2561.c @@ -0,0 +1,88 @@ +/* + * tsl2561.c + * + * Created on: Aug 21, 2015 + * Author: Michael Lucas (Aeprox @github) + */ +#include "lualib.h" +#include "lauxlib.h" +#include "platform.h" +#include "auxmods.h" +#include "lrotable.h" +#include "../tsl2561/tsl2561.h" + +static uint16_t ch0; +static uint16_t ch1; + +static int ICACHE_FLASH_ATTR tsl2561_init(lua_State* L) { + uint32_t sda; + uint32_t scl; + + if (!lua_isnumber(L, 1) || !lua_isnumber(L, 2)) { + return luaL_error(L, "wrong arg range"); + } + + sda = luaL_checkinteger(L, 1); + scl = luaL_checkinteger(L, 2); + + if (scl == 0 || sda == 0) { + return luaL_error(L, "no i2c for D0"); + } + + uint8_t error = tsl2561Init(sda,scl); + lua_pushnumber( L, error ); + return 1; +} + +static int ICACHE_FLASH_ATTR tsl2561_lua_settiming(lua_State* L) { + // check variables + if (!lua_isnumber(L, 1) || !lua_isnumber(L, 2)) { + return luaL_error(L, "wrong arg range"); + } + uint8_t integration = luaL_checkinteger(L, 1); + uint8_t gain = luaL_checkinteger(L, 2); + + lua_pushnumber( L, tsl2561SetTiming(integration, gain) ); + return 1; +} +static int ICACHE_FLASH_ATTR tsl2561_lua_calclux(lua_State* L) { + lua_pushnumber( L, tsl2561CalculateLux(ch0,ch1) ); + return 1; +} + +static int ICACHE_FLASH_ATTR tsl2561_lua_getchannels(lua_State* L) { + uint8_t error = tsl2561GetLuminosity(&ch0,&ch1); + lua_pushnumber( L, ch0 ); + lua_pushnumber( L, ch1 ); + lua_pushnumber( L, error ); + + return 1; +} + +#define MIN_OPT_LEVEL 2 +#include "lrodefs.h" +const LUA_REG_TYPE tsl2561_map[] = +{ + { LSTRKEY( "settiming" ), LFUNCVAL( tsl2561_lua_settiming)}, + { LSTRKEY( "calclux" ), LFUNCVAL( tsl2561_lua_calclux )}, + { LSTRKEY( "channels_raw" ), LFUNCVAL( tsl2561_lua_getchannels )}, + { LSTRKEY( "init" ), LFUNCVAL( tsl2561_init )}, + + { LSTRKEY( "TSL2561_OK" ), LNUMVAL( TSL2561_ERROR_OK ) }, + { LSTRKEY( "TSL2561_ERROR_I2CINIT" ), LNUMVAL( TSL2561_ERROR_I2CINIT ) }, + { LSTRKEY( "TSL2561_ERROR_I2CBUSY" ), LNUMVAL( TSL2561_ERROR_I2CBUSY ) }, + { LSTRKEY( "TSL2561_ERROR_LAST" ), LNUMVAL( TSL2561_ERROR_LAST ) }, + + { LSTRKEY( "TSL2561_INTEGRATIONTIME_13MS" ), LNUMVAL( TSL2561_INTEGRATIONTIME_13MS ) }, + { LSTRKEY( "TSL2561_INTEGRATIONTIME_101MS" ), LNUMVAL( TSL2561_INTEGRATIONTIME_101MS ) }, + { LSTRKEY( "TSL2561_INTEGRATIONTIME_402MS" ), LNUMVAL( TSL2561_INTEGRATIONTIME_402MS ) }, + { LSTRKEY( "TSL2561_GAIN_0X" ), LNUMVAL( TSL2561_GAIN_0X ) }, + { LSTRKEY( "TSL2561_GAIN_16X" ), LNUMVAL( TSL2561_GAIN_16X ) }, + + { LNILKEY, LNILVAL} +}; + +LUALIB_API int luaopen_tsl2561(lua_State *L) { + LREGISTER(L, "tsl2561", tsl2561_map); + return 1; +} diff --git a/app/tsl2561/tsl2561.c b/app/tsl2561/tsl2561.c new file mode 100644 index 00000000..21b76ccb --- /dev/null +++ b/app/tsl2561/tsl2561.c @@ -0,0 +1,331 @@ +/**************************************************************************/ +/*! + @file tsl2561.c + @author K. Townsend (microBuilder.eu) + + @brief Drivers for the TAOS TSL2561 I2C digital luminosity sensor + + @section DESCRIPTION + + The TSL2561 is a 16-bit digital luminosity sensor the approximates + the human eye's response to light. It contains one broadband + photodiode that measures visible plus infrared light (channel 0) + and one infrared photodiode (channel 1). + + @section EXAMPLE + + @code + #include "drivers/sensors/tsl2561/tsl2561.h" + ... + uint16_t broadband, ir; + uint32_t lux; + + // Initialise luminosity sensor + tsl2561Init(); + + // Optional ... default setting is 400ms with no gain + // Set timing to 101ms with no gain + tsl2561SetTiming(TSL2561_INTEGRATIONTIME_101MS, TSL2561_GAIN_0X); + + // Check luminosity level and calculate lux + tsl2561GetLuminosity(&broadband, &ir); + lux = tsl2561CalculateLux(broadband, ir); + printf("Broadband: %u, IR: %u, Lux: %d %s", broadband, ir, lux, CFG_PRINTF_NEWLINE); + + @endcode + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2010, microBuilder SARL + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/**************************************************************************/ +#include "tsl2561.h" +static const uint32_t tsl2561_i2c_id = 0; +static bool _tsl2561Initialised = 0; +static tsl2561IntegrationTime_t _tsl2561IntegrationTime = TSL2561_INTEGRATIONTIME_402MS; +static tsl2561Gain_t _tsl2561Gain = TSL2561_GAIN_0X; + + +/**************************************************************************/ +/*! + @brief Writes an 8 bit values over I2C +*/ +/**************************************************************************/ +tsl2561Error_t tsl2561Write8 (uint8_t reg, uint8_t value) +{ + platform_i2c_send_start(tsl2561_i2c_id); + platform_i2c_send_address(tsl2561_i2c_id, TSL2561_ADDRESS, PLATFORM_I2C_DIRECTION_TRANSMITTER); + platform_i2c_send_byte(tsl2561_i2c_id, reg); + platform_i2c_send_byte(tsl2561_i2c_id, value); + platform_i2c_send_stop(tsl2561_i2c_id); + return TSL2561_ERROR_OK; +} + +/**************************************************************************/ +/*! + @brief Reads a 16 bit values over I2C +*/ +/**************************************************************************/ +tsl2561Error_t tsl2561Read16(uint8_t reg, uint16_t *value) +{ + platform_i2c_send_start(tsl2561_i2c_id); + platform_i2c_send_address(tsl2561_i2c_id, TSL2561_ADDRESS, PLATFORM_I2C_DIRECTION_TRANSMITTER); + platform_i2c_send_byte(tsl2561_i2c_id, reg); + platform_i2c_send_stop(tsl2561_i2c_id); + platform_i2c_send_start(tsl2561_i2c_id); + platform_i2c_send_address(tsl2561_i2c_id, TSL2561_ADDRESS, PLATFORM_I2C_DIRECTION_RECEIVER); + uint8_t ch_high = platform_i2c_recv_byte(tsl2561_i2c_id, 0); + platform_i2c_send_stop(tsl2561_i2c_id); + + platform_i2c_send_start(tsl2561_i2c_id); + platform_i2c_send_address(tsl2561_i2c_id, TSL2561_ADDRESS, PLATFORM_I2C_DIRECTION_TRANSMITTER); + platform_i2c_send_byte(tsl2561_i2c_id, reg); + platform_i2c_send_stop(tsl2561_i2c_id); + platform_i2c_send_start(tsl2561_i2c_id); + platform_i2c_send_address(tsl2561_i2c_id, TSL2561_ADDRESS, PLATFORM_I2C_DIRECTION_RECEIVER); + uint8_t ch_low = platform_i2c_recv_byte(tsl2561_i2c_id, 0); + platform_i2c_send_stop(tsl2561_i2c_id); + + // Shift values to create properly formed integer (low byte first) + *value = (ch_low | (ch_high << 8)); + + return TSL2561_ERROR_OK; +} + +/**************************************************************************/ +/*! + @brief Enables the device +*/ +/**************************************************************************/ +tsl2561Error_t tsl2561Enable(void) +{ + if (!_tsl2561Initialised) tsl2561Init(); + + // Enable the device by setting the control bit to 0x03 + return tsl2561Write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWERON); +} + +/**************************************************************************/ +/*! + @brief Disables the device (putting it in lower power sleep mode) +*/ +/**************************************************************************/ +tsl2561Error_t tsl2561Disable(void) +{ + if (!_tsl2561Initialised) tsl2561Init(); + + // Turn the device off to save power + return tsl2561Write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF); +} + +/**************************************************************************/ +/*! + @brief Initialises the I2C block +*/ +/**************************************************************************/ +tsl2561Error_t tsl2561Init(uint8_t sda, uint8_t scl) +{ + // Initialise I2C + platform_i2c_setup(tsl2561_i2c_id, sda, scl, PLATFORM_I2C_SPEED_SLOW); + + _tsl2561Initialised = 1; + + // Set default integration time and gain + tsl2561SetTiming(_tsl2561IntegrationTime, _tsl2561Gain); + + // Note: by default, the device is in power down mode on bootup + + return TSL2561_ERROR_OK; +} + +/**************************************************************************/ +/*! + @brief Sets the integration time and gain (controls sensitivity) +*/ +/**************************************************************************/ +tsl2561Error_t tsl2561SetTiming(tsl2561IntegrationTime_t integration, tsl2561Gain_t gain) +{ + if (!_tsl2561Initialised) tsl2561Init(); + + tsl2561Error_t error = TSL2561_ERROR_OK; + + // Enable the device by setting the control bit to 0x03 + error = tsl2561Enable(); + if (error) return error; + + // Turn the device off to save power + error = tsl2561Write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, integration | gain); + if (error) return error; + + // Update value placeholders + _tsl2561IntegrationTime = integration; + _tsl2561Gain = gain; + + // Turn the device off to save power + error = tsl2561Disable(); + if (error) return error; + + return error; +} + +/**************************************************************************/ +/*! + @brief Reads the luminosity on both channels from the TSL2561 +*/ +/**************************************************************************/ +tsl2561Error_t tsl2561GetLuminosity (uint16_t *broadband, uint16_t *ir) +{ + if (!_tsl2561Initialised) tsl2561Init(); + + tsl2561Error_t error = TSL2561_ERROR_OK; + + // Enable the device by setting the control bit to 0x03 + error = tsl2561Enable(); + if (error) return error; + + // Wait x ms for ADC to complete + switch (_tsl2561IntegrationTime) + { + case TSL2561_INTEGRATIONTIME_13MS: + systickDelay(14); + break; + case TSL2561_INTEGRATIONTIME_101MS: + systickDelay(102); + break; + default: + systickDelay(400); + break; + } + + // Reads two byte value from channel 0 (visible + infrared) + error = tsl2561Read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW, broadband); + if (error) return error; + + // Reads two byte value from channel 1 (infrared) + error = tsl2561Read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW, ir); + if (error) return error; + + // Turn the device off to save power + error = tsl2561Disable(); + if (error) return error; + + return error; +} + +/**************************************************************************/ +/*! + @brief Calculates LUX from the supplied ch0 (broadband) and ch1 + (IR) readings +*/ +/**************************************************************************/ +uint32_t tsl2561CalculateLux(uint16_t ch0, uint16_t ch1) +{ + unsigned long chScale; + unsigned long channel1; + unsigned long channel0; + + switch (_tsl2561IntegrationTime) + { + case TSL2561_INTEGRATIONTIME_13MS: + chScale = TSL2561_LUX_CHSCALE_TINT0; + break; + case TSL2561_INTEGRATIONTIME_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 (!_tsl2561Gain) chScale = chScale << 4; + + // scale the channel values + channel0 = (ch0 * chScale) >> TSL2561_LUX_CHSCALE; + channel1 = (ch1 * chScale) >> TSL2561_LUX_CHSCALE; + + // find the ratio of the channel values (Channel1/Channel0) + unsigned long ratio1 = 0; + if (channel0 != 0) ratio1 = (channel1 << (TSL2561_LUX_RATIOSCALE+1)) / channel0; + + // round the ratio value + unsigned long ratio = (ratio1 + 1) >> 1; + + unsigned int b, m; + +#ifdef 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 + + unsigned long temp; + 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 + uint32_t lux = temp >> TSL2561_LUX_LUXSCALE; + + // Signal I2C had no errors + return lux; +} diff --git a/app/tsl2561/tsl2561.h b/app/tsl2561/tsl2561.h new file mode 100644 index 00000000..1ec143ec --- /dev/null +++ b/app/tsl2561/tsl2561.h @@ -0,0 +1,160 @@ +/**************************************************************************/ +/*! + @file tsl2561.h + @author K. Townsend (microBuilder.eu) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2010, microBuilder SARL + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/**************************************************************************/ + +#ifndef _TSL2561_H_ +#define _TSL2561_H_ + +#define TSL2561_PACKAGE_CS // Lux calculations differ slightly for CS package +// #define TSL2561_PACKAGE_T_FN_CL + +#define TSL2561_ADDRESS (0x72) // 0111001 shifted left 1 bit = 0x72 (ADDR = GND or floating) +#define TSL2561_READBIT (0x01) + +#define TSL2561_COMMAND_BIT (0x80) // Must be 1 +#define TSL2561_CLEAR_BIT (0x40) // Clears any pending interrupt (write 1 to clear) +#define TSL2561_WORD_BIT (0x20) // 1 = read/write word (rather than byte) +#define TSL2561_BLOCK_BIT (0x10) // 1 = using block read/write + +#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 + +enum +{ + TSL2561_REGISTER_CONTROL = 0x00, + TSL2561_REGISTER_TIMING = 0x01, + TSL2561_REGISTER_THRESHHOLDL_LOW = 0x02, + TSL2561_REGISTER_THRESHHOLDL_HIGH = 0x03, + TSL2561_REGISTER_THRESHHOLDH_LOW = 0x04, + TSL2561_REGISTER_THRESHHOLDH_HIGH = 0x05, + TSL2561_REGISTER_INTERRUPT = 0x06, + TSL2561_REGISTER_CRC = 0x08, + TSL2561_REGISTER_ID = 0x0A, + TSL2561_REGISTER_CHAN0_LOW = 0x0C, + TSL2561_REGISTER_CHAN0_HIGH = 0x0D, + TSL2561_REGISTER_CHAN1_LOW = 0x0E, + TSL2561_REGISTER_CHAN1_HIGH = 0x0F +}; + +typedef enum +{ + TSL2561_INTEGRATIONTIME_13MS = 0x00, // 13.7ms + TSL2561_INTEGRATIONTIME_101MS = 0x01, // 101ms + TSL2561_INTEGRATIONTIME_402MS = 0x02 // 402ms +} +tsl2561IntegrationTime_t; + +typedef enum +{ + TSL2561_GAIN_0X = 0x00, // No gain + TSL2561_GAIN_16X = 0x10, // 16x gain +} +tsl2561Gain_t; + +typedef enum +{ + TSL2561_ERROR_OK = 0, // Everything executed normally + TSL2561_ERROR_I2CINIT, // Unable to initialise I2C + TSL2561_ERROR_I2CBUSY, // I2C already in use + TSL2561_ERROR_LAST +} +tsl2561Error_t; + +tsl2561Error_t tsl2561Init(uint8_t sda, uint8_t scl); +tsl2561Error_t tsl2561SetTiming(tsl2561IntegrationTime_t integration, tsl2561Gain_t gain); +tsl2561Error_t tsl2561GetLuminosity (uint16_t *broadband, uint16_t *ir); +uint32_t tsl2561CalculateLux(uint16_t ch0, uint16_t ch1); + +#endif + +