New drivers
[hackover2013-badge-firmware.git] / drivers / sensors / tcs3414 / tcs3414.c
1 /**************************************************************************/
2 /*!
3 @file tcs3414.c
4 @author K. Townsend (microBuilder.eu)
5 Morten Hjerde (tcs3414CalculateCCT)
6
7 @brief Drivers for the TAOS TCS3414 I2C RGB sensor
8
9 @section DESCRIPTION
10
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.
18
19 @section LICENSE
20
21 Software License Agreement (BSD License)
22
23 Copyright (c) 2010, microBuilder SARL
24 All rights reserved.
25
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.
36
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.
47 */
48 /**************************************************************************/
49 #include "tcs3414.h"
50 #include "core/systick/systick.h"
51
52 extern volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE];
53 extern volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE];
54 extern volatile uint32_t I2CReadLength, I2CWriteLength;
55
56 static bool _tcs3414Initialised = false;
57
58 /**************************************************************************/
59 /*!
60 @brief Sends a single command byte over I2C
61 */
62 /**************************************************************************/
63 tcs3414Error_e tcs3414WriteCmd (uint8_t cmd)
64 {
65 // Clear write buffers
66 uint32_t i;
67 for ( i = 0; i < I2C_BUFSIZE; i++ )
68 {
69 I2CMasterBuffer[i] = 0x00;
70 }
71
72 I2CWriteLength = 2;
73 I2CReadLength = 0;
74 I2CMasterBuffer[0] = TCS3414_ADDRESS; // I2C device address
75 I2CMasterBuffer[1] = cmd; // Command register
76 i2cEngine();
77 return TCS3414_ERROR_OK;
78 }
79
80 /**************************************************************************/
81 /*!
82 @brief Writes an 8 bit values over I2C
83 */
84 /**************************************************************************/
85 tcs3414Error_e tcs3414Write8 (uint8_t reg, uint32_t value)
86 {
87 // Clear write buffers
88 uint32_t i;
89 for ( i = 0; i < I2C_BUFSIZE; i++ )
90 {
91 I2CMasterBuffer[i] = 0x00;
92 }
93
94 I2CWriteLength = 3;
95 I2CReadLength = 0;
96 I2CMasterBuffer[0] = TCS3414_ADDRESS; // I2C device address
97 I2CMasterBuffer[1] = reg; // Command register
98 I2CMasterBuffer[2] = (value & 0xFF); // Value to write
99 i2cEngine();
100 return TCS3414_ERROR_OK;
101 }
102
103 /**************************************************************************/
104 /*!
105 @brief Reads a 16 bit values over I2C
106 */
107 /**************************************************************************/
108 tcs3414Error_e tcs3414Read16(uint8_t reg, uint16_t *value)
109 {
110 // Clear write buffers
111 uint32_t i;
112 for ( i = 0; i < I2C_BUFSIZE; i++ )
113 {
114 I2CMasterBuffer[i] = 0x00;
115 }
116
117 I2CWriteLength = 2;
118 I2CReadLength = 2;
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;
123 i2cEngine();
124
125 // Shift values to create properly formed integer (low byte first)
126 *value = (I2CSlaveBuffer[0] | (I2CSlaveBuffer[1] << 8));
127
128 return TCS3414_ERROR_OK;
129 }
130
131 /**************************************************************************/
132 /*!
133 @brief Initialises the I2C block
134 */
135 /**************************************************************************/
136 tcs3414Error_e tcs3414Init(void)
137 {
138 // Initialise I2C
139 if (i2cInit(I2CMASTER) == false)
140 {
141 return TCS3414_ERROR_I2CINIT; /* Fatal error */
142 }
143
144 _tcs3414Initialised = true;
145
146 // Note: by default, the device is in power down mode on bootup
147
148 return TCS3414_ERROR_OK;
149 }
150
151 /**************************************************************************/
152 /*!
153 @brief Sets the gain and prescalar to control sensitivty
154 */
155 /**************************************************************************/
156 tcs3414Error_e tcs3414SetSensitivity(tcs3414Gain_t gain, tcs3414Prescalar_t prescalar)
157 {
158 if (!_tcs3414Initialised) tcs3414Init();
159
160 tcs3414Error_e error = TCS3414_ERROR_OK;
161
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;
165
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;
169
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;
173
174 return error;
175 }
176
177 /**************************************************************************/
178 /*!
179 @brief Reads the RGB and clear luminosity from the TCS3414
180 */
181 /**************************************************************************/
182 tcs3414Error_e tcs3414GetRGBL(uint16_t *red, uint16_t *green, uint16_t *blue, uint16_t *clear)
183 {
184 if (!_tcs3414Initialised) tcs3414Init();
185
186 tcs3414Error_e error = TCS3414_ERROR_OK;
187
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;
191
192 // Wait >12ms for ADC to complete
193 systickDelay(13);
194
195 // Reads two byte red value
196 error = tcs3414Read16(TCS3414_COMMAND_BIT | TCS3414_WORD_BIT | TCS3414_REGISTER_REDLOW, red);
197 if (error) return error;
198
199 // Reads two byte green value
200 error = tcs3414Read16(TCS3414_COMMAND_BIT | TCS3414_WORD_BIT | TCS3414_REGISTER_GREENLOW, green);
201 if (error) return error;
202
203 // Reads two byte blue value
204 error = tcs3414Read16(TCS3414_COMMAND_BIT | TCS3414_WORD_BIT | TCS3414_REGISTER_BLUELOW, blue);
205 if (error) return error;
206
207 // Reads two byte clear value
208 error = tcs3414Read16(TCS3414_COMMAND_BIT | TCS3414_WORD_BIT | TCS3414_REGISTER_CLEARLOW, clear);
209 if (error) return error;
210
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;
214
215 return error;
216 }
217
218 /**************************************************************************/
219 /*!
220 @brief Reads the RGB values from the TCS3414 color sensor and
221 calculates CCT (Correlated Color Temperature)
222
223 @return The Correlated Color Temperature in Kelvin
224 */
225 /**************************************************************************/
226 uint32_t tcs3414CalculateCCT (uint16_t red, uint16_t green, uint16_t blue)
227 {
228 volatile float R;
229 volatile float G;
230 volatile float B;
231 volatile float X;
232 volatile float Y;
233 volatile float Z;
234 volatile float x;
235 volatile float y;
236 volatile float n;
237 volatile float CCT;
238
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;
243
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);
248
249 //calc chromaticity coordinates
250 x = (X)/(X + Y + Z);
251 y = (Y)/(X + Y + Z);
252
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);
257 CCT += (6823.3 * n);
258 CCT += 5520.33;
259
260 return ((uint32_t) CCT);
261 }
This page took 0.066529 seconds and 5 git commands to generate.