Rev 154 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
#include "lux_TSL2561.h"#include "defines.h"#include "i2c.h"#include <delays.h>static TSL2561_DATA tsl2561_data;static TSL2561_DATA *tsl2561_data_p = &tsl2561_data;void LUX_Init(unsigned char address) {tsl2561_data_p->address = address;tsl2561_data_p->integration = TSL2561_INTEGRATIONTIME_13MS;tsl2561_data_p->gain = TSL2561_GAIN_16X;}void LUX_Begin(void) {unsigned char i, result, length, buffer[10];unsigned char toSend = TSL2561_REGISTER_ID;DBG_PRINT_LUX("Sending %X to address %X\r\n", toSend, tsl2561_data_p->address);I2C_Master_Send(tsl2561_data_p->address, 1, &toSend);do {result = I2C_Get_Status();} while (!result);I2C_Master_Recv(tsl2561_data_p->address, 1);do {result = I2C_Get_Status();} while (!result);length = I2C_Read_Buffer((char *)buffer);DBG_PRINT_LUX("Received %d bytes: ", length);for (i = 0; i < length; i++) {DBG_PRINT_LUX("%c ", buffer[i]);}DBG_PRINT_LUX("\r\n");// Set default integration time and gainLUX_Set_Timing(tsl2561_data_p->integration);LUX_Set_Gain(tsl2561_data_p->gain);// Start the chip in power-down modeLUX_Disable();}void LUX_Enable() {LUX_Write_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWERON);}void LUX_Disable() {LUX_Write_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF);}void LUX_Set_Gain(tsl2561Gain_t gain) {LUX_Enable();tsl2561_data_p->gain = gain;LUX_Write_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING,tsl2561_data_p->integration | tsl2561_data_p->gain);LUX_Disable();}void LUX_Set_Timing(tsl2561IntegrationTime_t integration) {LUX_Enable();tsl2561_data_p->integration = integration;LUX_Write_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING,tsl2561_data_p->integration | tsl2561_data_p->gain);LUX_Disable();}unsigned long LUX_Calculate_Lux(unsigned int ch0, unsigned int ch1) {unsigned long chScale, channel0, channel1, ratio1, ratio, temp, lux;unsigned int b, m;switch (tsl2561_data_p->integration) {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 = 402mschScale = (1 << TSL2561_LUX_CHSCALE);break;}// Scale for gain (1x or 16x)if (!tsl2561_data_p->gain)chScale = chScale << 4;// scale the channel valueschannel0 = (ch0 * chScale) >> TSL2561_LUX_CHSCALE;channel1 = (ch1 * chScale) >> TSL2561_LUX_CHSCALE;// find the ratio of the channel values (Channel1/Channel0)ratio1 = 0;if (channel0 != 0)ratio1 = (channel1 << (TSL2561_LUX_RATIOSCALE+1)) / channel0;// round the ratio valueratio = (ratio1 + 1) >> 1;#ifdef TSL2561_PACKAGE_CSif ((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;}#elseif ((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;}#endiftemp = ((channel0 * b) - (channel1 * m));// do not allow negative lux valueif (temp < 0)temp = 0;// round lsb (2^(LUX_SCALE-1))temp += (1 << (TSL2561_LUX_LUXSCALE-1));// strip off fractional portionlux = temp >> TSL2561_LUX_LUXSCALE;return lux;}unsigned long LUX_Get_Full_Luminosity() {unsigned long x;// Enable the device by setting the control bit to 0x03LUX_Enable();// Wait x ms for ADC to completeswitch (tsl2561_data_p->integration) {case TSL2561_INTEGRATIONTIME_13MS:Delay10KTCYx(67);break;case TSL2561_INTEGRATIONTIME_101MS:Delay10KTCYx(255);Delay10KTCYx(230);break;default:Delay10KTCYx(255);Delay10KTCYx(255);Delay10KTCYx(255);Delay10KTCYx(255);Delay10KTCYx(255);Delay10KTCYx(255);Delay10KTCYx(255);Delay10KTCYx(145);break;}x = LUX_Read_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW);x <<= 16;x |= LUX_Read_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW);LUX_Disable();return x;}unsigned int LUX_Get_Luminosity(unsigned char channel) {unsigned long x = LUX_Get_Full_Luminosity();if (channel == 0) {// Reads two byte value from channel 0 (visible + infrared)return (x & 0xFFFF);} else if (channel == 1) {// Reads two byte value from channel 1 (infrared)return (x >> 16);} else if (channel == 2) {// Reads all and subtracts out just the visible!return ( (x & 0xFFFF) - (x >> 16));}// Unknown channel!return 0;}void LUX_Write_2_Bytes(unsigned char reg, unsigned char value) {unsigned char buffer[2], result;buffer[0] = reg;buffer[1] = value;I2C_Master_Send(tsl2561_data_p->address, 2, buffer);do {result = I2C_Get_Status();} while (!result);}unsigned int LUX_Read_2_Bytes(unsigned char reg) {unsigned char result, length, buffer[2];unsigned int ret;I2C_Master_Restart(tsl2561_data_p->address, reg, 2);do {result = I2C_Get_Status();} while (!result);length = I2C_Read_Buffer((char *)buffer);ret = buffer[1] << 8;ret |= buffer[0];return ret;}