summaryrefslogtreecommitdiff
path: root/digital/zigbit/bitcloud/stack/Components/BSP/MESHBEAN/src/tsl2550.c
diff options
context:
space:
mode:
authorFlorent Duchon2012-12-26 17:36:00 +0100
committerFlorent Duchon2013-02-13 21:21:12 +0100
commitb24866225a6301d3a663f874725e83c012dc25d3 (patch)
treeca527a2aab9abcdfbaf244c53ca63f0c531892b0 /digital/zigbit/bitcloud/stack/Components/BSP/MESHBEAN/src/tsl2550.c
parent2ba279f4eb2f23fa08a7c13465d16ae6ba5d0f96 (diff)
digital/beacon: add bitcloud stack into common directory digital/zigbit
Diffstat (limited to 'digital/zigbit/bitcloud/stack/Components/BSP/MESHBEAN/src/tsl2550.c')
-rw-r--r--digital/zigbit/bitcloud/stack/Components/BSP/MESHBEAN/src/tsl2550.c457
1 files changed, 457 insertions, 0 deletions
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 <tsl2550.h>
+#include <i2cPacket.h>
+#include <bspTaskManager.h>
+#include <appTimer.h>
+#include <bspDbg.h>
+
+/******************************************************************************
+ 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