1 /**************************************************************************/
4 @author K. Townsend (microBuilder.eu)
5 Morten Hjerde (tcs3414CalculateCCT)
7 @brief Drivers for the TAOS TCS3414 I2C RGB sensor
11 The TAOS TCS3414 is a digital color/light sensor that can be used
12 to derive the color chromaticity and illuminance of ambient light
13 with 16-bit resolution. The device has an array of filtered
14 photo-diodes with 4 red, 4 green, 4 blue and 4 unfiltered
15 captors. The sensor has digital gain and prescalar support so that
16 the sensitivty of the device can be dynamically adjusted with a
17 1,000,000:1 dynamic range.
21 Software License Agreement (BSD License)
23 Copyright (c) 2010, microBuilder SARL
26 Redistribution and use in source and binary forms, with or without
27 modification, are permitted provided that the following conditions are met:
28 1. Redistributions of source code must retain the above copyright
29 notice, this list of conditions and the following disclaimer.
30 2. Redistributions in binary form must reproduce the above copyright
31 notice, this list of conditions and the following disclaimer in the
32 documentation and/or other materials provided with the distribution.
33 3. Neither the name of the copyright holders nor the
34 names of its contributors may be used to endorse or promote products
35 derived from this software without specific prior written permission.
37 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
38 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
39 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
41 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48 /**************************************************************************/
50 #include "core/systick/systick.h"
52 extern volatile uint8_t I2CMasterBuffer
[I2C_BUFSIZE
];
53 extern volatile uint8_t I2CSlaveBuffer
[I2C_BUFSIZE
];
54 extern volatile uint32_t I2CReadLength
, I2CWriteLength
;
56 static bool _tcs3414Initialised
= false;
58 /**************************************************************************/
60 @brief Sends a single command byte over I2C
62 /**************************************************************************/
63 tcs3414Error_e
tcs3414WriteCmd (uint8_t cmd
)
65 // Clear write buffers
67 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
69 I2CMasterBuffer
[i
] = 0x00;
74 I2CMasterBuffer
[0] = TCS3414_ADDRESS
; // I2C device address
75 I2CMasterBuffer
[1] = cmd
; // Command register
77 return TCS3414_ERROR_OK
;
80 /**************************************************************************/
82 @brief Writes an 8 bit values over I2C
84 /**************************************************************************/
85 tcs3414Error_e
tcs3414Write8 (uint8_t reg
, uint32_t value
)
87 // Clear write buffers
89 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
91 I2CMasterBuffer
[i
] = 0x00;
96 I2CMasterBuffer
[0] = TCS3414_ADDRESS
; // I2C device address
97 I2CMasterBuffer
[1] = reg
; // Command register
98 I2CMasterBuffer
[2] = (value
& 0xFF); // Value to write
100 return TCS3414_ERROR_OK
;
103 /**************************************************************************/
105 @brief Reads a 16 bit values over I2C
107 /**************************************************************************/
108 tcs3414Error_e
tcs3414Read16(uint8_t reg
, uint16_t *value
)
110 // Clear write buffers
112 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
114 I2CMasterBuffer
[i
] = 0x00;
119 I2CMasterBuffer
[0] = TCS3414_ADDRESS
; // I2C device address
120 I2CMasterBuffer
[1] = reg
; // Command register
121 // Append address w/read bit
122 I2CMasterBuffer
[2] = TCS3414_ADDRESS
| TCS3414_READBIT
;
125 // Shift values to create properly formed integer (low byte first)
126 *value
= (I2CSlaveBuffer
[0] | (I2CSlaveBuffer
[1] << 8));
128 return TCS3414_ERROR_OK
;
131 /**************************************************************************/
133 @brief Initialises the I2C block
135 /**************************************************************************/
136 tcs3414Error_e
tcs3414Init(void)
139 if (i2cInit(I2CMASTER
) == false)
141 return TCS3414_ERROR_I2CINIT
; /* Fatal error */
144 _tcs3414Initialised
= true;
146 // Note: by default, the device is in power down mode on bootup
148 return TCS3414_ERROR_OK
;
151 /**************************************************************************/
153 @brief Sets the gain and prescalar to control sensitivty
155 /**************************************************************************/
156 tcs3414Error_e
tcs3414SetSensitivity(tcs3414Gain_t gain
, tcs3414Prescalar_t prescalar
)
158 if (!_tcs3414Initialised
) tcs3414Init();
160 tcs3414Error_e error
= TCS3414_ERROR_OK
;
162 // Enable the device by setting the control bit to 0x03 (power + ADC on)
163 error
= tcs3414Write8(TCS3414_COMMAND_BIT
| TCS3414_REGISTER_CONTROL
, TCS3414_CONTROL_POWERON
);
164 if (error
) return error
;
166 // Set the gani and prescalar values using the GAIN register
167 error
= tcs3414Write8(TCS3414_COMMAND_BIT
| TCS3414_REGISTER_GAIN
, gain
| prescalar
);
168 if (error
) return error
;
170 // Turn the device off to save power
171 error
= tcs3414Write8(TCS3414_COMMAND_BIT
| TCS3414_REGISTER_CONTROL
, TCS3414_CONTROL_POWEROFF
);
172 if (error
) return error
;
177 /**************************************************************************/
179 @brief Reads the RGB and clear luminosity from the TCS3414
181 /**************************************************************************/
182 tcs3414Error_e
tcs3414GetRGBL(uint16_t *red
, uint16_t *green
, uint16_t *blue
, uint16_t *clear
)
184 if (!_tcs3414Initialised
) tcs3414Init();
186 tcs3414Error_e error
= TCS3414_ERROR_OK
;
188 // Enable the device by setting the control bit to 0x03 (power + ADC on)
189 error
= tcs3414Write8(TCS3414_COMMAND_BIT
| TCS3414_REGISTER_CONTROL
, TCS3414_CONTROL_POWERON
);
190 if (error
) return error
;
192 // Wait >12ms for ADC to complete
195 // Reads two byte red value
196 error
= tcs3414Read16(TCS3414_COMMAND_BIT
| TCS3414_WORD_BIT
| TCS3414_REGISTER_REDLOW
, red
);
197 if (error
) return error
;
199 // Reads two byte green value
200 error
= tcs3414Read16(TCS3414_COMMAND_BIT
| TCS3414_WORD_BIT
| TCS3414_REGISTER_GREENLOW
, green
);
201 if (error
) return error
;
203 // Reads two byte blue value
204 error
= tcs3414Read16(TCS3414_COMMAND_BIT
| TCS3414_WORD_BIT
| TCS3414_REGISTER_BLUELOW
, blue
);
205 if (error
) return error
;
207 // Reads two byte clear value
208 error
= tcs3414Read16(TCS3414_COMMAND_BIT
| TCS3414_WORD_BIT
| TCS3414_REGISTER_CLEARLOW
, clear
);
209 if (error
) return error
;
211 // Turn the device off to save power
212 error
= tcs3414Write8(TCS3414_COMMAND_BIT
| TCS3414_REGISTER_CONTROL
, TCS3414_CONTROL_POWEROFF
);
213 if (error
) return error
;
218 /**************************************************************************/
220 @brief Reads the RGB values from the TCS3414 color sensor and
221 calculates CCT (Correlated Color Temperature)
223 @return The Correlated Color Temperature in Kelvin
225 /**************************************************************************/
226 uint32_t tcs3414CalculateCCT (uint16_t red
, uint16_t green
, uint16_t blue
)
239 // Convert RGB values to a 0-100 scale
240 R
= (((float) red
) / 65536) * 100;
241 G
= (((float) green
) / 65536) * 100;
242 B
= (((float) blue
)/ 65536) * 100;
244 //do matrix transformation
245 X
= (-0.14282 * R
) + (1.54924 * G
) + (-0.95641 * B
);
246 Y
= (-0.32466 * R
) + (1.57837 * G
) + (-0.73191 * B
);
247 Z
= (-0.68202 * R
) + (0.77073 * G
) + (0.56332 * B
);
249 //calc chromaticity coordinates
253 //use McCamy\92s formula to get CCT:
254 n
= (x
- 0.3320) / (0.1858 - y
);
255 CCT
= (449 * n
* n
* n
); // we don't have pow
256 CCT
+= (3525 * n
* n
);
260 return ((uint32_t) CCT
);