Subversion Repositories Code-Repo

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
147 Kevin 1
#include "lux_TSL2561.h"
148 Kevin 2
#include "defines.h"
147 Kevin 3
#include "i2c.h"
148 Kevin 4
#include <delays.h>
147 Kevin 5
 
6
static TSL2561_DATA tsl2561_data;
7
static TSL2561_DATA *tsl2561_data_p = &tsl2561_data;
8
 
9
void LUX_Init(unsigned char address) {
10
    tsl2561_data_p->address = address;
11
    tsl2561_data_p->integration = TSL2561_INTEGRATIONTIME_13MS;
12
    tsl2561_data_p->gain = TSL2561_GAIN_16X;
13
}
14
 
15
void LUX_Begin(void) {
148 Kevin 16
    unsigned char i, result, length, buffer[10];
17
    unsigned char toSend = TSL2561_REGISTER_ID;
18
    DBG_PRINT_LUX("Sending %X to address %X\r\n", toSend, tsl2561_data_p->address);
19
    I2C_Master_Send(tsl2561_data_p->address, 1, &toSend);
20
    do {
21
        result = I2C_Get_Status();
22
    } while (!result);
23
 
24
    I2C_Master_Recv(tsl2561_data_p->address, 1);
25
    do {
26
        result = I2C_Get_Status();
27
    } while (!result);
28
    length = I2C_Read_Buffer((char *)buffer);
29
    DBG_PRINT_LUX("Received %d bytes: ", length);
30
    for (i = 0; i < length; i++) {
31
        DBG_PRINT_LUX("%c ", buffer[i]);
32
    }
33
    DBG_PRINT_LUX("\r\n");
34
 
35
    // Set default integration time and gain
154 Kevin 36
    LUX_Set_Timing(tsl2561_data_p->integration);
37
    LUX_Set_Gain(tsl2561_data_p->gain);
148 Kevin 38
 
39
    // Start the chip in power-down mode
40
    LUX_Disable();
41
}
42
 
43
void LUX_Enable()  {
154 Kevin 44
    LUX_Write_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWERON);
148 Kevin 45
}
46
 
47
void LUX_Disable() {
154 Kevin 48
    LUX_Write_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF);
148 Kevin 49
}
50
 
154 Kevin 51
void LUX_Set_Gain(tsl2561Gain_t gain) {
148 Kevin 52
    LUX_Enable();
53
    tsl2561_data_p->gain = gain;
154 Kevin 54
    LUX_Write_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING,
148 Kevin 55
            tsl2561_data_p->integration | tsl2561_data_p->gain);
56
    LUX_Disable();
57
}
58
 
154 Kevin 59
void LUX_Set_Timing(tsl2561IntegrationTime_t integration) {
148 Kevin 60
    LUX_Enable();
61
    tsl2561_data_p->integration = integration;
154 Kevin 62
    LUX_Write_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING,
148 Kevin 63
            tsl2561_data_p->integration | tsl2561_data_p->gain);
64
    LUX_Disable();
65
}
66
 
154 Kevin 67
unsigned long LUX_Calculate_Lux(unsigned int ch0, unsigned int ch1) {
148 Kevin 68
    unsigned long chScale, channel0, channel1, ratio1, ratio, temp, lux;
69
    unsigned int b, m;
70
 
71
    switch (tsl2561_data_p->integration) {
72
        case TSL2561_INTEGRATIONTIME_13MS:
73
            chScale = TSL2561_LUX_CHSCALE_TINT0;
74
            break;
75
        case TSL2561_INTEGRATIONTIME_101MS:
76
            chScale = TSL2561_LUX_CHSCALE_TINT1;
77
            break;
78
        default: // No scaling ... integration time = 402ms
79
            chScale = (1 << TSL2561_LUX_CHSCALE);
80
            break;
81
    }
82
 
83
    // Scale for gain (1x or 16x)
84
    if (!tsl2561_data_p->gain)
85
        chScale = chScale << 4;
86
 
87
    // scale the channel values
88
    channel0 = (ch0 * chScale) >> TSL2561_LUX_CHSCALE;
89
    channel1 = (ch1 * chScale) >> TSL2561_LUX_CHSCALE;
90
 
91
    // find the ratio of the channel values (Channel1/Channel0)
92
    ratio1 = 0;
93
    if (channel0 != 0)
94
        ratio1 = (channel1 << (TSL2561_LUX_RATIOSCALE+1)) / channel0;
95
 
96
    // round the ratio value
97
    ratio = (ratio1 + 1) >> 1;
98
 
99
#ifdef TSL2561_PACKAGE_CS
100
    if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1C)) {
101
        b = TSL2561_LUX_B1C; m = TSL2561_LUX_M1C;
102
    } else if (ratio <= TSL2561_LUX_K2C) {
103
        b = TSL2561_LUX_B2C; m = TSL2561_LUX_M2C;
104
    } else if (ratio <= TSL2561_LUX_K3C) {
105
        b = TSL2561_LUX_B3C; m = TSL2561_LUX_M3C;
106
    } else if (ratio <= TSL2561_LUX_K4C) {
107
        b = TSL2561_LUX_B4C; m = TSL2561_LUX_M4C;
108
    } else if (ratio <= TSL2561_LUX_K5C) {
109
        b = TSL2561_LUX_B5C; m = TSL2561_LUX_M5C;
110
    } else if (ratio <= TSL2561_LUX_K6C) {
111
        b = TSL2561_LUX_B6C; m = TSL2561_LUX_M6C;
112
    } else if (ratio <= TSL2561_LUX_K7C) {
113
        b = TSL2561_LUX_B7C; m = TSL2561_LUX_M7C;
114
    } else if (ratio > TSL2561_LUX_K8C) {
115
        b = TSL2561_LUX_B8C; m = TSL2561_LUX_M8C;
116
    }
117
#else
118
    if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1T)) {
119
        b = TSL2561_LUX_B1T; m = TSL2561_LUX_M1T;
120
    } else if (ratio <= TSL2561_LUX_K2T) {
121
        b = TSL2561_LUX_B2T; m = TSL2561_LUX_M2T;
122
    } else if (ratio <= TSL2561_LUX_K3T) {
123
        b = TSL2561_LUX_B3T; m = TSL2561_LUX_M3T;
124
    } else if (ratio <= TSL2561_LUX_K4T) {
125
        b = TSL2561_LUX_B4T; m = TSL2561_LUX_M4T;
126
    } else if (ratio <= TSL2561_LUX_K5T) {
127
        b = TSL2561_LUX_B5T; m = TSL2561_LUX_M5T;
128
    } else if (ratio <= TSL2561_LUX_K6T) {
129
        b = TSL2561_LUX_B6T; m = TSL2561_LUX_M6T;
130
    } else if (ratio <= TSL2561_LUX_K7T) {
131
        b = TSL2561_LUX_B7T; m = TSL2561_LUX_M7T;
132
    } else if (ratio > TSL2561_LUX_K8T) {
133
        b = TSL2561_LUX_B8T; m = TSL2561_LUX_M8T;
134
    }
135
#endif
147 Kevin 136
 
148 Kevin 137
    temp = ((channel0 * b) - (channel1 * m));
138
 
139
    // do not allow negative lux value
140
    if (temp < 0)
141
        temp = 0;
142
 
143
    // round lsb (2^(LUX_SCALE-1))
144
    temp += (1 << (TSL2561_LUX_LUXSCALE-1));
145
 
146
    // strip off fractional portion
147
    lux = temp >> TSL2561_LUX_LUXSCALE;
148
 
149
    return lux;
150
}
151
 
154 Kevin 152
unsigned long LUX_Get_Full_Luminosity() {
148 Kevin 153
    unsigned long x;
154
 
155
    // Enable the device by setting the control bit to 0x03
156
    LUX_Enable();
157
 
158
    // Wait x ms for ADC to complete
159
    switch (tsl2561_data_p->integration) {
160
        case TSL2561_INTEGRATIONTIME_13MS:
161
            Delay10KTCYx(67);
162
            break;
163
        case TSL2561_INTEGRATIONTIME_101MS:
164
            Delay10KTCYx(255);
165
            Delay10KTCYx(230);
166
            break;
167
        default:
168
            Delay10KTCYx(255);
169
            Delay10KTCYx(255);
170
            Delay10KTCYx(255);
171
            Delay10KTCYx(255);
172
            Delay10KTCYx(255);
173
            Delay10KTCYx(255);
174
            Delay10KTCYx(255);
175
            Delay10KTCYx(145);
176
            break;
177
    }
178
 
154 Kevin 179
    x = LUX_Read_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW);
148 Kevin 180
    x <<= 16;
154 Kevin 181
    x |= LUX_Read_2_Bytes(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW);
148 Kevin 182
 
183
    LUX_Disable();
184
 
185
    return x;
186
}
187
 
154 Kevin 188
unsigned int LUX_Get_Luminosity(unsigned char channel) {
189
    unsigned long x = LUX_Get_Full_Luminosity();
148 Kevin 190
 
191
    if (channel == 0) {
192
        // Reads two byte value from channel 0 (visible + infrared)
193
        return (x & 0xFFFF);
194
    } else if (channel == 1) {
195
        // Reads two byte value from channel 1 (infrared)
196
        return (x >> 16);
197
    } else if (channel == 2) {
198
        // Reads all and subtracts out just the visible!
199
        return ( (x & 0xFFFF) - (x >> 16));
200
    }
201
 
202
    // Unknown channel!
203
    return 0;
204
}
205
 
154 Kevin 206
void LUX_Write_2_Bytes(unsigned char reg, unsigned char value) {
148 Kevin 207
    unsigned char buffer[2], result;
208
    buffer[0] = reg;
209
    buffer[1] = value;
210
    I2C_Master_Send(tsl2561_data_p->address, 2, buffer);
211
    do {
212
        result = I2C_Get_Status();
213
    } while (!result);
214
}
215
 
154 Kevin 216
unsigned int LUX_Read_2_Bytes(unsigned char reg) {
148 Kevin 217
    unsigned char result, length, buffer[2];
218
    unsigned int ret;
219
 
220
    I2C_Master_Restart(tsl2561_data_p->address, reg, 2);
221
    do {
222
        result = I2C_Get_Status();
223
    } while (!result);
224
    length = I2C_Read_Buffer((char *)buffer);
225
    ret = buffer[1] << 8;
226
    ret |= buffer[0];
227
 
228
    return ret;
147 Kevin 229
}