Subversion Repositories Code-Repo

Rev

Rev 282 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "defines.h"
#include "I2C1.h"
#include "TSL2561.h"

extern TSL2561_DATA tsl2561_data;

void TSL2561_Init(uint8_t address) {
    tsl2561_data.address = address;
    tsl2561_data.integration = TSL2561_INTEGRATIONTIME_13MS;
    tsl2561_data.gain = TSL2561_GAIN_16X;

    uint8_t buffer[1];
    I2C1_Master_Restart(tsl2561_data.address, TSL2561_REGISTER_ID, 1);
    while (!I2C1_Get_Status());
    I2C1_Read_Buffer(buffer);

    // Set default integration time and gain
    TSL2561_Set_Timing(tsl2561_data.integration);
    TSL2561_Set_Gain(tsl2561_data.gain);

    // Start the chip in power-down mode
    TSL2561_Disable();
}

void TSL2561_Enable()  {
    TSL2561_Write_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWERON);
}

void TSL2561_Disable() {
    TSL2561_Write_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF);
}

void TSL2561_Set_Gain(tsl2561Gain_t gain) {
    TSL2561_Enable();
    tsl2561_data.gain = gain;
    TSL2561_Write_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING,
            tsl2561_data.integration | tsl2561_data.gain);
    TSL2561_Disable();
}

void TSL2561_Set_Timing(tsl2561IntegrationTime_t integration) {
    TSL2561_Enable();
    tsl2561_data.integration = integration;
    TSL2561_Write_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING,
            tsl2561_data.integration | tsl2561_data.gain);
    TSL2561_Disable();
}

uint32_t TSL2561_Calculate_Lux(uint16_t ch0, uint16_t ch1) {
    uint32_t chScale, channel0, channel1, ratio1, ratio, temp, lux;
    uint16_t b, m;

    switch (tsl2561_data.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.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;
}

uint32_t TSL2561_Get_Full_Luminosity() {
    uint32_t x;

    // Enable the device by setting the control bit to 0x03
    TSL2561_Enable();

    // Wait x ms for ADC to complete
    switch (tsl2561_data.integration) {
        case TSL2561_INTEGRATIONTIME_13MS:
            __delay_ms(15);
            break;
        case TSL2561_INTEGRATIONTIME_101MS:
            __delay_ms(105);
            break;
        default:
            __delay_ms(405);
            break;
    }

    x = TSL2561_Read_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW);
    x <<= 16;
    x |= TSL2561_Read_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW);

    TSL2561_Disable();

    return x;
}

uint16_t TSL2561_Get_Luminosity(uint8_t channel) {
    // Enable the device by setting the control bit to 0x03
    TSL2561_Enable();

    // Wait x ms for ADC to complete
    switch (tsl2561_data.integration) {
        case TSL2561_INTEGRATIONTIME_13MS:
            __delay_ms(15);
            break;
        case TSL2561_INTEGRATIONTIME_101MS:
            __delay_ms(105);
            break;
        default:
            __delay_ms(405);
            break;
    }

    if (channel == 0) {
        // Reads two byte value from channel 0 (visible + infrared)
        return TSL2561_Read_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW);
    } else if (channel == 1) {
        // Reads two byte value from channel 1 (infrared)
        return TSL2561_Read_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW);
    }

    TSL2561_Disable();

    // Unknown channel!
    return 0;
}

void TSL2561_Write_2_Bytes(uint8_t reg, uint8_t value) {
    uint8_t buffer[2];
    buffer[0] = reg;
    buffer[1] = value;
    I2C1_Master_Send(tsl2561_data.address, 2, buffer);
    while (!I2C1_Get_Status());
}

uint16_t TSL2561_Read_2_Bytes(uint8_t reg) {
    uint8_t buffer[2];
    uint16_t ret;

    I2C1_Master_Restart(tsl2561_data.address, reg, 2);
    while (!I2C1_Get_Status());
    I2C1_Read_Buffer(buffer);
    ret = buffer[1] << 8;
    ret |= buffer[0];

    return ret;
}