0,0 → 1,233 |
#include "sensor_lux_TSL2561.h" |
#include "defines.h" |
#include "base_I2C.h" |
#include <delays.h> |
|
static TSL2561_DATA *tsl2561_data_p; |
|
void LUX_Init(TSL2561_DATA *data, char address) { |
tsl2561_data_p = data; |
tsl2561_data_p->address = address; |
tsl2561_data_p->integration = TSL2561_INTEGRATIONTIME_13MS; |
tsl2561_data_p->gain = TSL2561_GAIN_16X; |
} |
|
void LUX_Begin(void) { |
char result, buffer[2]; |
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); |
char length = I2C_Read_Buffer(buffer); |
DBG_PRINT_LUX("Received %d bytes: ", length); |
for (char 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)) { |
if ((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)); |
// TODO: Change this back once they fix compiler |
temp = (channel0 * b); |
temp -= (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(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(char reg, char value) { |
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(char reg) { |
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(buffer); |
ret = buffer[1] << 8; |
ret |= buffer[0]; |
|
return ret; |
} |