From b24866225a6301d3a663f874725e83c012dc25d3 Mon Sep 17 00:00:00 2001 From: Florent Duchon Date: Wed, 26 Dec 2012 17:36:00 +0100 Subject: digital/beacon: add bitcloud stack into common directory digital/zigbit --- .../stack/Components/BSP/MESHBEAN/src/tsl2550.c | 457 +++++++++++++++++++++ 1 file changed, 457 insertions(+) create mode 100644 digital/zigbit/bitcloud/stack/Components/BSP/MESHBEAN/src/tsl2550.c (limited to 'digital/zigbit/bitcloud/stack/Components/BSP/MESHBEAN/src/tsl2550.c') diff --git a/digital/zigbit/bitcloud/stack/Components/BSP/MESHBEAN/src/tsl2550.c b/digital/zigbit/bitcloud/stack/Components/BSP/MESHBEAN/src/tsl2550.c new file mode 100644 index 00000000..9011c6fd --- /dev/null +++ b/digital/zigbit/bitcloud/stack/Components/BSP/MESHBEAN/src/tsl2550.c @@ -0,0 +1,457 @@ +/**************************************************************************//** +\file tsl2550.c + +\brief Implementation of access to tsl2550 the sensor, light sensor. + +\author + Atmel Corporation: http://www.atmel.com \n + Support email: avr@atmel.com + + Copyright (c) 2008-2011, Atmel Corporation. All rights reserved. + Licensed under Atmel's Limited License Agreement (BitCloudTM). + +\internal + History: + 29/06/07 E. Ivanov - Created +******************************************************************************/ +/****************************************************************************** + Includes section +******************************************************************************/ +#include +#include +#include +#include +#include + +/****************************************************************************** + Definitions section +******************************************************************************/ +// device address on i2c bus +#define TSL_DEVICE_ADDRESS 0x39 + +// device registers internal address +#define TSL_READ_CHANNEL0_COMMAND 0x43 +#define TSL_READ_CHANNEL1_COMMAND 0x83 +#define TSL_POWERDOWN_COMMAND 0x00 +#define TSL_POWERUP_COMMAND 0x03 +#define TSL_EXTENDED_RANGE_COMMAND 0x1D +#define TSL_STANDARD_RANGE_COMMAND 0x18 + +// standard mode max +#define TSL_MAX_LUX_VALUE 1846 + +// Conversion time (400ms typ by datasheet). Choose a little more to be on a safe side. +#define TSL_CONVERSION_TIME 500 + +/****************************************************************************** + Types section +******************************************************************************/ +// states +typedef enum +{ + OFF, + IDLE, + POWERUP, + POWERUP_ERR, + DATA, + DATA_ERR, +} Tsl2550States_t; + +typedef struct +{ + Tsl2550States_t state; + uint8_t ch0; + uint8_t ch1; + void(* callback)(bool result, int16_t data); // data callback pointer +} Tsl2550Control_t; + +/****************************************************************************** + Constants section +******************************************************************************/ +PROGMEM_DECLARE(const uint8_t tsl2550Ratio[129]) = +{ +100,100,100,100,100,100,100,100, +100,100,100,100,100,100, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 98, 98, 98, 98, 98, + 98, 98, 97, 97, 97, 97, 97, 96, + 96, 96, 96, 95, 95, 95, 94, 94, + 93, 93, 93, 92, 92, 91, 91, 90, + 89, 89, 88, 87, 87, 86, 85, 84, + 83, 82, 81, 80, 79, 78, 77, 75, + 74, 73, 71, 69, 68, 66, 64, 62, + 60, 58, 56, 54, 52, 49, 47, 44, + 42, 41, 40, 40, 39, 39, 38, 38, + 37, 37, 37, 36, 36, 36, 35, 35, + 35, 35, 34, 34, 34, 34, 33, 33, + 33, 33, 32, 32, 32, 32, 32, 31, + 31, 31, 31, 31, 30, 30, 30, 30, + 30 +}; + +PROGMEM_DECLARE(const uint16_t tsl2550Count[128]) = +{ + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, + 49, 53, 57, 61, 65, 69, 73, 77, + 81, 85, 89, 93, 97, 101, 105, 109, + 115, 123, 131, 139, 147, 155, 163, 171, + 179, 187, 195, 203, 211, 219, 227, 235, + 247, 263, 279, 295, 311, 327, 343, 359, + 375, 391, 407, 423, 439, 455, 471, 487, + 511, 543, 575, 607, 639, 671, 703, 735, + 767, 799, 831, 863, 895, 927, 959, 991, +1039,1103,1167,1231,1295,1359,1423,1487, +1551,1615,1679,1743,1807,1871,1935,1999, +2095,2223,2351,2479,2607,2735,2863,2991, +3119,3247,3375,3503,3631,3759,3887,4015 +}; + +/****************************************************************************** + Static function prototypes section +******************************************************************************/ +static bool tsl2550StartReading(void); +static void tsl2550StartFirstReading(void); +static void tsl2550I2cPacketReadDoneCh1(bool result); +static void tsl2550I2cPacketWriteDoneCh1(bool result); +static void tsl2550I2cPacketReadDoneCh0(bool result); +static void tsl2550I2cPacketWriteDoneCh0(bool result); +static void tsl2550I2cPowerupDone(bool result); +static bool tsl2550StartPowerup(void); + +/****************************************************************************** + Implementations section +******************************************************************************/ + +static Tsl2550Control_t tsl2550Control = {.state = OFF}; + +/**************************************************************************//** +\brief Opens the component to use. + +\return + BC_SUCCESS - the component is ready to be used. \n + BC_FAIL - otherwise. +******************************************************************************/ +result_t openTsl2550(void) +{ + if (IDLE == tsl2550Control.state || OFF == tsl2550Control.state) + return BC_SUCCESS; + + return BC_FAIL; +} + +/**************************************************************************//** +\brief Performs the test if the component have completed request. + +\return + BC_FAIL - the previous request is not completed. \n + BC_SUCCES - otherwise. +******************************************************************************/ +result_t closeTsl2550(void) +{ + if (IDLE == tsl2550Control.state || OFF == tsl2550Control.state) + return BC_SUCCESS; + + return BC_FAIL; +} + +/**************************************************************************//** +\brief Reads data from tsl2550 sensor. + +\param[in] + f - callback method +\param[in] + result - the result of the requested operation. + true - operation finished successfully, false - some error has + occured. +\param[in] + data - sensor data. + +\return + BC_FAIL - the previous request was not completed, + the address of callback is 0, i2c interface is busy, + there is error on i2c interface. \n + BC_SUCCESS - in other case. +******************************************************************************/ +result_t readTsl2550Data(void (*f)(bool result, int16_t data)) +{ + HAL_i2cMode_t i2cMode = {.clockrate = I2C_CLOCK_RATE_62}; + + if (NULL == f) + return BC_FAIL; + + if (OFF == tsl2550Control.state) // Sensor is in powerdown mode, powerup it before reading + { + if (-1 == HAL_OpenI2cPacket(&i2cMode)) + return BC_FAIL; + + if (false == tsl2550StartPowerup()) + { + HAL_CloseI2cPacket(); + return BC_FAIL; + } + tsl2550Control.state = POWERUP; + } + else if (IDLE == tsl2550Control.state) + { + if (-1 == HAL_OpenI2cPacket(&i2cMode)) + return BC_FAIL; + + if (false == tsl2550StartReading()) + { + HAL_CloseI2cPacket(); + return BC_FAIL; + } + tsl2550Control.state = DATA; + } + else + { + return BC_FAIL; + } + + tsl2550Control.callback = f; + + return BC_SUCCESS; +} + +/**************************************************************************//** +\brief BSP tsl2550 handler. +******************************************************************************/ +void bspTsl2550Handler(void) +{ + uint8_t result = false; + uint16_t lux = 0; + + HAL_CloseI2cPacket(); // free + + switch (tsl2550Control.state) + { + case POWERUP_ERR: + tsl2550Control.state = OFF; + break; + + case DATA_ERR: + tsl2550Control.state = IDLE; + break; + + case DATA: + { + uint32_t count0 = 0, count1 = 0; + uint8_t ratio = 128; // default scaling factor + uint8_t R; + + tsl2550Control.state = IDLE; + + if (tsl2550Control.ch0 & tsl2550Control.ch1 & 0x80) + { + memcpy_P(&count0, &tsl2550Count[tsl2550Control.ch0 & 0x7F], sizeof(uint16_t)); + memcpy_P(&count1, &tsl2550Count[tsl2550Control.ch1 & 0x7F], sizeof(uint16_t)); + + if (!count0 || (count0 <= count1)) // count1 cannot be greater than count0 + break; + + ratio = ((uint32_t)(count1 * 128ul) / count0); + // calculate lux + // the "256" is a scaling factor + memcpy_P(&R, &tsl2550Ratio[ratio], sizeof(uint8_t)); + lux = ((count0 - count1) * R) / 256; + // range check lux + if (lux > TSL_MAX_LUX_VALUE) + lux = TSL_MAX_LUX_VALUE; + + result = true; + } + } + break; + + default: + ASSERT(false, TSL2550_UNEXPECTED_STATE); + tsl2550Control.state = IDLE; + break; + } + + tsl2550Control.callback(result, lux); +} + +/**************************************************************************//** +\brief Callback that reading from tsl2550 was completed. + +\param[in] + result - contains result of operation. + if result is false there was problem on i2c interface. +******************************************************************************/ +static void tsl2550I2cPacketReadDoneCh1(bool result) +{ + if (false == result) + tsl2550Control.state = DATA_ERR; + + bspPostTask(BSP_LIGHT); +} + +/**************************************************************************//** +\brief Callback that writing command to tsl2550 was completed. + +\param[in] + result - contains result of operation. + if result is false there was problem on i2c interface. +******************************************************************************/ +static void tsl2550I2cPacketWriteDoneCh1(bool result) +{ + HAL_I2cParams_t i2cParam = + { + .data = &tsl2550Control.ch1, + .f = tsl2550I2cPacketReadDoneCh1, + .id = TSL_DEVICE_ADDRESS, + .length = 1, + .lengthAddr = HAL_NO_INTERNAL_ADDRESS, + }; + + if ((false == result) || (-1 == HAL_ReadI2cPacket(&i2cParam))) + { + tsl2550Control.state = DATA_ERR; + bspPostTask(BSP_LIGHT); + } +} + +/**************************************************************************//** +\brief Callback that reading from tsl2550 was completed. + +\param[in] + result - contains result of operation. + if result is false there was problem on i2c interface. +******************************************************************************/ +static void tsl2550I2cPacketReadDoneCh0(bool result) +{ + HAL_I2cParams_t i2cParam = + { + .data = &tsl2550Control.ch1, + .f = tsl2550I2cPacketWriteDoneCh1, + .id = TSL_DEVICE_ADDRESS, + .length = 1, + .lengthAddr = HAL_NO_INTERNAL_ADDRESS, + }; + + tsl2550Control.ch1 = TSL_READ_CHANNEL1_COMMAND; + + if ((false == result) || (-1 == HAL_WriteI2cPacket(&i2cParam))) + { + tsl2550Control.state = DATA_ERR; + bspPostTask(BSP_LIGHT); + } +} + +/**************************************************************************//** +\brief Callback that writing command to tsl2550 was completed. + +\param[in] + result - contains result of operation. + if result is false there was problem on i2c interface. +******************************************************************************/ +static void tsl2550I2cPacketWriteDoneCh0(bool result) +{ + HAL_I2cParams_t i2cParam = + { + .data = &tsl2550Control.ch0, + .f = tsl2550I2cPacketReadDoneCh0, + .id = TSL_DEVICE_ADDRESS, + .length = 1, + .lengthAddr = HAL_NO_INTERNAL_ADDRESS, + }; + + if ((false == result) || (-1 == HAL_ReadI2cPacket(&i2cParam))) + { + tsl2550Control.state = DATA_ERR; + bspPostTask(BSP_LIGHT); + } +} + +/**************************************************************************//** +\brief Start tsl2550 read sequence. + +\return + false - i2c packet wasn't sent + true - in other case. +******************************************************************************/ +static bool tsl2550StartReading(void) +{ + HAL_I2cParams_t i2cParam = + { + .data = &tsl2550Control.ch0, + .f = tsl2550I2cPacketWriteDoneCh0, + .id = TSL_DEVICE_ADDRESS, + .length = 1, + .lengthAddr = HAL_NO_INTERNAL_ADDRESS, + }; + + tsl2550Control.ch0 = TSL_READ_CHANNEL0_COMMAND; + + return (-1 != HAL_WriteI2cPacket(&i2cParam)) ? true : false; +} + +/**************************************************************************//** +\brief Callback on completion of tsl2550's delay after powerup. +******************************************************************************/ +static void tsl2550StartFirstReading(void) +{ + if (false == tsl2550StartReading()) + { + tsl2550Control.state = DATA_ERR; + bspPostTask(BSP_LIGHT); + return; + } + + tsl2550Control.state = DATA; +} + +/**************************************************************************//** +\brief Callback on completion of tsl2550 powerup. + +\param[in] + result - contains result of operation. + if result is false there was problem on i2c interface. +******************************************************************************/ +static void tsl2550I2cPowerupDone(bool result) +{ + static HAL_AppTimer_t tsl2550PowerupTimer = + { + .interval = TSL_CONVERSION_TIME * 2, // Wait for conversions on two channels one-after-one + .mode = TIMER_ONE_SHOT_MODE, + .callback = tsl2550StartFirstReading, + }; + + if (false == result) + { + tsl2550Control.state = POWERUP_ERR; + bspPostTask(BSP_LIGHT); + return; + } + + HAL_StartAppTimer(&tsl2550PowerupTimer); +} + +/**************************************************************************//** +\brief Start tsl2550 powerup sequence. + +\return + false - i2c packet wasn't sent + true - in other case. +******************************************************************************/ +static bool tsl2550StartPowerup(void) +{ + HAL_I2cParams_t i2cParam = + { + .data = &tsl2550Control.ch0, + .f = tsl2550I2cPowerupDone, + .id = TSL_DEVICE_ADDRESS, + .length = 1, + .lengthAddr = HAL_NO_INTERNAL_ADDRESS, + }; + + tsl2550Control.ch0 = TSL_POWERUP_COMMAND; + + return (-1 != HAL_WriteI2cPacket(&i2cParam)) ? true : false; +} + +// eof tsl2550.c -- cgit v1.2.3