Rev 154 | Blame | Compare with Previous | Last modification | View Log | 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 gain
LUX_Set_Timing(tsl2561_data_p->integration);
LUX_Set_Gain(tsl2561_data_p->gain);
// Start the chip in power-down mode
LUX_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 = 402ms
chScale = (1 << TSL2561_LUX_CHSCALE);
break;
}
// Scale for gain (1x or 16x)
if (!tsl2561_data_p->gain)
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)
ratio1 = 0;
if (channel0 != 0)
ratio1 = (channel1 << (TSL2561_LUX_RATIOSCALE+1)) / channel0;
// round the ratio value
ratio = (ratio1 + 1) >> 1;
#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
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
lux = temp >> TSL2561_LUX_LUXSCALE;
return lux;
}
unsigned long LUX_Get_Full_Luminosity() {
unsigned long x;
// Enable the device by setting the control bit to 0x03
LUX_Enable();
// Wait x ms for ADC to complete
switch (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;
}