Aaron Allar / TCS3472_I2C

Dependents:   colerSenser2

Fork of TCS3472_I2C by Karl Maxwell

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TCS3472_I2C.cpp Source File

TCS3472_I2C.cpp

00001 #include "TCS3472_I2C.h"
00002 
00003 TCS3472_I2C::TCS3472_I2C( PinName sda, PinName scl ) : i2c( sda, scl ){   
00004     i2c.frequency(100000);
00005     enablePowerAndRGBC();
00006 }
00007 
00008 TCS3472_I2C::~TCS3472_I2C(){
00009     
00010 }
00011 
00012 bool TCS3472_I2C::verifyConnection(void) {
00013     uint8_t part_id = readSingleRegister(0x12);//ID
00014     if (part_id == 0x44)
00015         return true;
00016     return false;
00017 }
00018 int TCS3472_I2C::writeSingleRegister( char address, char data ){
00019     char tx[2] = { address | 160, data }; //0d160 = 0b10100000
00020     int ack = i2c.write( SLAVE_ADDRESS << 1, tx, 2 );
00021     return ack;
00022 }
00023 
00024 int TCS3472_I2C::writeMultipleRegisters( char address, char* data, int quantity ){
00025     char tx[ quantity + 1 ];
00026     tx[0] = address | 160;
00027     for ( int i = 1; i <= quantity; i++ ){
00028         tx[ i ] = data[ i - 1 ];
00029     }
00030     int ack = i2c.write( SLAVE_ADDRESS << 1, tx, quantity + 1 );
00031     return ack;
00032 }
00033 
00034 char TCS3472_I2C::readSingleRegister( char address ){
00035     char output = 255;
00036     char command = address | 160; //0d160 = 0b10100000
00037     i2c.write( SLAVE_ADDRESS << 1, &command, 1, true );
00038     i2c.read( SLAVE_ADDRESS << 1, &output, 1 );
00039     return output;
00040 }
00041 
00042 int TCS3472_I2C::readMultipleRegisters( char address, char* output, int quantity ){
00043     char command = address | 160; //0d160 = 0b10100000
00044     i2c.write( SLAVE_ADDRESS << 1, &command, 1, true );
00045     int ack = i2c.read( SLAVE_ADDRESS << 1, output, quantity );
00046     return ack;
00047 }
00048 
00049 void TCS3472_I2C::getAllColors( int* readings ){
00050     char buffer[8] = { 0 };
00051 
00052     if (readMultipleRegisters( CDATA, buffer, 8 ) ==0){
00053         readings[0] = (int)buffer[1] << 8 | (int)buffer[0];//c
00054         readings[1] = (int)buffer[3] << 8 | (int)buffer[2];//r
00055         readings[2] = (int)buffer[5] << 8 | (int)buffer[4];//g
00056         readings[3] = (int)buffer[7] << 8 | (int)buffer[6];//b
00057     }
00058     else{
00059         readings[0] = 0;readings[1] = 0;readings[2] = 0;readings[3] = 0;
00060     }
00061 }
00062 
00063 int TCS3472_I2C::getClearData(){
00064     char buffer[2] = { 0 };
00065     readMultipleRegisters( CDATA, buffer, 2 );
00066     int reading = (int)buffer[1] << 8 | (int)buffer[0];
00067     return reading;
00068 }
00069 
00070 int TCS3472_I2C::getRedData(){
00071     char buffer[2] = { 0 };
00072     readMultipleRegisters( RDATA, buffer, 2 );
00073     int reading = (int)buffer[1] << 8 | (int)buffer[0];
00074     return reading;
00075 }
00076 
00077 int TCS3472_I2C::getGreenData(){
00078     char buffer[2] = { 0 };
00079     readMultipleRegisters( GDATA, buffer, 2 );
00080     int reading = (int)buffer[1] << 8 | (int)buffer[0];
00081     return reading;
00082 }
00083 
00084 int TCS3472_I2C::getBlueData(){
00085     char buffer[2] = { 0 };
00086     readMultipleRegisters( BDATA, buffer, 2 );
00087     int reading = (int)buffer[1] << 8 | (int)buffer[0];
00088     return reading;
00089 }
00090 
00091 int TCS3472_I2C::enablePower(){
00092     char enable_old = readSingleRegister( ENABLE );
00093     char enable_new = enable_old | 1; // sets PON (bit 0) to 1
00094     int ack = writeSingleRegister( ENABLE, enable_new );
00095     return ack;
00096 }
00097 
00098 int TCS3472_I2C::disablePower(){
00099     char enable_old = readSingleRegister( ENABLE );
00100     char enable_new = enable_old & 254; // sets PON (bit 0) to 0
00101     int ack = writeSingleRegister( ENABLE, enable_new );
00102     return ack;
00103 }
00104 
00105 bool TCS3472_I2C::isPowerEnabled(){
00106     char enable = readSingleRegister( ENABLE );
00107     char pon = enable << 7;
00108     pon = pon >> 7; // gets PON (bit 0) from ENABLE register byte
00109     return (bool)pon;
00110 }
00111 
00112 int TCS3472_I2C::enableRGBC(){
00113     char enable_old = readSingleRegister( ENABLE );
00114     char enable_new = enable_old | 2; // sets AEN (bit 1) to 1
00115     int ack = writeSingleRegister( ENABLE, enable_new );
00116     return ack;
00117 }
00118 
00119 int TCS3472_I2C::disableRGBC(){
00120     char enable_old = readSingleRegister( ENABLE );
00121     char enable_new = enable_old & 253; // sets AEN (bit 1) to 0
00122     int ack = writeSingleRegister( ENABLE, enable_new );
00123     return ack;
00124 }
00125 
00126 bool TCS3472_I2C::isRGBCEnabled(){
00127     char enable = readSingleRegister( ENABLE );
00128     char aen = enable << 6;
00129     aen = aen >> 7; // gets AEN (bit 1) from ENABLE register byte
00130     return (bool)aen;
00131 }
00132 
00133 int TCS3472_I2C::enablePowerAndRGBC(){
00134     char enable_old = readSingleRegister( ENABLE );
00135     char enable_new = enable_old | 3; // sets PON (bit 0) and AEN (bit 1) to 1
00136     int ack = writeSingleRegister( ENABLE, enable_new );
00137     return ack;
00138 }
00139 
00140 int TCS3472_I2C::disablePowerAndRGBC(){
00141     char enable_old = readSingleRegister( ENABLE );
00142     char enable_new = enable_old & 252; // sets PON (bit 0) and AEN (bit 1) to 0
00143     int ack = writeSingleRegister( ENABLE, enable_new );
00144     return ack;
00145 }
00146 
00147 int TCS3472_I2C::enableWait(){
00148     char enable_old = readSingleRegister( ENABLE );
00149     char enable_new = enable_old | 8; // sets WEN (bit 3) to 1
00150     int ack = writeSingleRegister( ENABLE, enable_new );
00151     return ack;
00152 }
00153 
00154 int TCS3472_I2C::disableWait(){
00155     char enable_old = readSingleRegister( ENABLE );
00156     char enable_new = enable_old & 247; // sets WEN (bit 3) to 0
00157     int ack = writeSingleRegister( ENABLE, enable_new );
00158     return ack;
00159 }
00160 
00161 bool TCS3472_I2C::isWaitEnabled(){ 
00162     char enable = readSingleRegister( ENABLE );
00163     char wen = enable << 4;
00164     wen = wen >> 7; // gets WEN (bit 3) from ENABLE register byte
00165     return (bool)wen;
00166 }
00167 
00168 int TCS3472_I2C::enableInterrupt(){
00169     char enable_old = readSingleRegister( ENABLE );
00170     char enable_new = enable_old | 16; // sets AIEN (bit 4) to 1
00171     int ack = writeSingleRegister( ENABLE, enable_new );
00172     return ack;
00173 }
00174 
00175 int TCS3472_I2C::disableInterrupt(){
00176     char enable_old = readSingleRegister( ENABLE );
00177     char enable_new = enable_old & 239; // sets AIEN (bit 4) to 0
00178     int ack = writeSingleRegister( ENABLE, enable_new );
00179     return ack;
00180 }
00181 
00182 bool TCS3472_I2C::isInterruptEnabled(){
00183     char enable = readSingleRegister( ENABLE );
00184     char aien = enable << 3;
00185     aien = aien >> 7; // gets AIEN (bit 4) from ENABLE register byte
00186     return (bool)aien;
00187 }
00188 
00189 int TCS3472_I2C::setIntegrationTime( const float itime ){
00190     char atime = 256 - (int)roundTowardsZero( itime / 2.4 ); // rounding ensures nearest value of atime is used
00191     int ack = writeSingleRegister( ATIME, atime );
00192     return ack;
00193 }
00194 
00195 float TCS3472_I2C::readIntegrationTime(){
00196     float itime = 0;
00197     char atime = readSingleRegister( ATIME );
00198     itime = 2.4 * ( 256 - atime );
00199     return itime;
00200 }
00201 
00202 int TCS3472_I2C::setWaitTime( const float time ){
00203     int ack = 1;
00204     char wtime = 0;
00205     if ( time >= 2.39 && time <= 614.4 ){ // 2.39 instead of 2.4 to allow for float accuracy errors
00206         ack = writeSingleRegister( CONFIG, 0 ); // sets WLONG to 0
00207         wtime = 256 - roundTowardsZero( time / 2.4 );
00208     }
00209     else if ( time > 614.4 && time <= 7400.1 ){ // 7400.1 instead of 7400 to allow for float accuracy errors
00210         ack = writeSingleRegister( CONFIG, 2 ); // sets WLONG to 1
00211         wtime = 256 - roundTowardsZero( time / 28.8 );
00212     } 
00213     ack = ack || writeSingleRegister( WTIME, wtime );
00214     return ack;
00215 }
00216 
00217 float TCS3472_I2C::readWaitTime(){
00218     float time = 0;
00219     char wtime = readSingleRegister( WTIME );
00220     char config = readSingleRegister( CONFIG );
00221     int wlong = ( config << 6 ) >> 7; // gets WLONG (bit 1) from CONFIG register byte
00222     if ( wlong == 0 ){
00223         time = 2.4 * ( 256 - wtime );
00224     }
00225     else if ( wlong == 1 ){
00226         time = 28.8 * ( 256 - wtime ); // 28.8 = 2.4 * 12
00227     }
00228     return time;
00229 }
00230 
00231 char TCS3472_I2C::readEnableRegister(){
00232     return readSingleRegister( ENABLE );
00233 }
00234 
00235 int TCS3472_I2C::readLowInterruptThreshold(){
00236     char buffer[2] = { 0 };
00237     readMultipleRegisters( AILTL, buffer, 2 );
00238     int reading = (int)buffer[1] << 8 | (int)buffer[0];
00239     return reading;
00240 }
00241 
00242 int TCS3472_I2C::readHighInterruptThreshold(){
00243     char buffer[2] = { 0 };
00244     readMultipleRegisters( AIHTL, buffer, 2 );
00245     int reading = (int)buffer[1] << 8 | (int)buffer[0];
00246     return reading;
00247 }
00248 
00249 int TCS3472_I2C::setLowInterruptThreshold( const int threshold ){
00250     char threshold_bytes[2];
00251     threshold_bytes[0] = threshold; // take lowest 8 bits of threshold
00252     threshold_bytes[1] = threshold >> 8; // take highest 8 bits of threshold
00253     int ack = writeMultipleRegisters( AILTL, threshold_bytes, 2 );
00254     return ack;
00255 }
00256 
00257 int TCS3472_I2C::setHighInterruptThreshold( const int threshold ){
00258     char threshold_bytes[2];
00259     threshold_bytes[0] = threshold;
00260     threshold_bytes[1] = threshold >> 8;
00261     int ack = writeMultipleRegisters( AIHTL, threshold_bytes, 2 );
00262     return ack;
00263 }
00264 
00265 int TCS3472_I2C::readInterruptPersistence(){
00266     char pers = readSingleRegister( PERS );
00267     char persistence_bits = ( pers << 4 ) >> 4; // discard bits 4 to 7, keep only bits 0 to 3
00268     int persistence = -1;
00269     switch (persistence_bits){
00270         case 0:
00271             persistence = 0;
00272             break;
00273         case 1:
00274             persistence = 1;
00275             break;
00276         case 2:
00277             persistence = 2;
00278             break;
00279         case 3:
00280             persistence = 3;
00281             break;
00282         case 4:
00283             persistence = 5;
00284             break;
00285         case 5:
00286             persistence = 10;
00287             break;
00288         case 6:
00289             persistence = 15;
00290             break;
00291         case 7:
00292             persistence = 20;
00293             break;
00294         case 8:
00295             persistence = 25;
00296             break;
00297         case 9:
00298             persistence = 30;
00299             break;
00300         case 10:
00301             persistence = 35;
00302             break;
00303         case 11:
00304             persistence = 40;
00305             break;
00306         case 12:
00307             persistence = 45;
00308             break;
00309         case 13:
00310             persistence = 50;
00311             break;
00312         case 14:
00313             persistence = 55;
00314             break;
00315         case 15:
00316             persistence = 60;
00317             break;
00318         default:
00319             break;
00320     }
00321     return persistence;
00322 }
00323 
00324 int TCS3472_I2C::setInterruptPersistence( const int persistence ){
00325     char pers_byte;
00326     int ack = 0;
00327     switch (persistence){
00328         case 0:
00329             pers_byte = 0;
00330             break;
00331         case 1:
00332             pers_byte = 1;
00333             break;
00334         case 2:
00335             pers_byte = 2;
00336             break;
00337         case 3:
00338             pers_byte = 3;
00339             break;
00340         case 5:
00341             pers_byte = 4;
00342             break;
00343         case 10:
00344             pers_byte = 5;
00345             break;
00346         case 15:
00347             pers_byte = 6;
00348             break;
00349         case 20:
00350             pers_byte = 7;
00351             break;
00352         case 25:
00353             pers_byte = 8;
00354             break;
00355         case 30:
00356             pers_byte = 9;
00357             break;
00358         case 35:
00359             pers_byte = 10;
00360             break;
00361         case 40:
00362             pers_byte = 11;
00363             break;
00364         case 45:
00365             pers_byte = 12;
00366             break;
00367         case 50:
00368             pers_byte = 13;
00369             break;
00370         case 55:
00371             pers_byte = 14;
00372             break;
00373         case 60:
00374             pers_byte = 15;
00375             break;
00376         default:
00377             ack = 2; // 2 used to indicate invalid entry
00378             break;
00379     }
00380     if ( ack != 2 ){
00381         ack = writeSingleRegister( PERS, pers_byte );
00382     }
00383     return ack;
00384 }
00385 
00386 int TCS3472_I2C::clearInterrupt(){
00387     char tx = 230;
00388     int ack = i2c.write( SLAVE_ADDRESS << 1, &tx, 1 );
00389     return ack;
00390 }
00391 
00392 int TCS3472_I2C::readRGBCGain(){
00393     char control = readSingleRegister( CONTROL );
00394     char gain_bits = ( control << 6 ) >> 6; // discard  bits 2 to 7, keep only bits 0 & 1
00395     int gain;
00396     switch (gain_bits) {
00397         case 0:
00398             gain = 1;
00399             break;
00400         case 1:
00401             gain = 4;
00402             break;
00403         case 2:
00404             gain = 16;
00405             break;
00406         case 3:
00407             gain = 60;
00408             break;
00409         default:
00410             gain = 0;
00411             break;
00412     }
00413     return gain;
00414 }
00415 
00416 int TCS3472_I2C::setRGBCGain( const int gain ){
00417     char control;
00418     int ack = 0;
00419     switch (gain){
00420         case 1:
00421             control = 0;
00422             break;
00423         case 4:
00424             control = 1;
00425             break;
00426         case 16:
00427             control = 2;
00428             break;
00429         case 60:
00430             control = 3;
00431             break;
00432         default:
00433             ack = 2; // 2 used to indicate invalid entry
00434             break;
00435     }
00436     if ( ack != 2 ){
00437         ack = writeSingleRegister( CONTROL, control );
00438     }
00439     return ack;
00440 }
00441 
00442 char TCS3472_I2C::getDeviceID(){
00443     return readSingleRegister( ID );
00444 }
00445 
00446 char TCS3472_I2C::readStatusRegister(){
00447     return readSingleRegister( STATUS );
00448 }
00449 
00450 float TCS3472_I2C::roundTowardsZero( const float value ){
00451     float result = 0;
00452     if ( ( value >= 0 && ( value - (int)value ) < 0.5 ) || ( value < 0 && ( abs(value) - (int)abs(value) ) >= 0.5 ) ){
00453         result = floor(value);
00454     }
00455     else{
00456         result = ceil(value);
00457     }
00458     return result;
00459 }
00460 
00461 int TCS3472_I2C::calculateColorTemperature(int r, int g, int b)
00462 {
00463   float X, Y, Z;      /* RGB to XYZ correlation      */
00464   float xc, yc;       /* Chromaticity co-ordinates   */
00465   float n;            /* McCamy's formula            */
00466   float cct;
00467 
00468   /* 1. Map RGB values to their XYZ counterparts.    */
00469   /* Based on 6500K fluorescent, 3000K fluorescent   */
00470   /* and 60W incandescent values for a wide range.   */
00471   /* Note: Y = Illuminance or lux                    */
00472   X = (-0.14282F * r) + (1.54924F * g) + (-0.95641F * b);
00473   Y = (-0.32466F * r) + (1.57837F * g) + (-0.73191F * b);
00474   Z = (-0.68202F * r) + (0.77073F * g) + ( 0.56332F * b);
00475 
00476   /* 2. Calculate the chromaticity co-ordinates      */
00477   xc = (X) / (X + Y + Z);
00478   yc = (Y) / (X + Y + Z);
00479 
00480   /* 3. Use McCamy's formula to determine the CCT    */
00481   n = (xc - 0.3320F) / (0.1858F - yc);
00482 
00483   /* Calculate the final CCT */
00484   cct = -(449.0F * powf(n, 3)) + (3525.0F * powf(n, 2)) - (6823.3F * n) + 5520.33F;
00485 
00486   /* Return the results in degrees Kelvin */
00487   return (int)cct;
00488 }
00489 
00490 float TCS3472_I2C::calculateChromaticityX(int r, int g, int b)
00491 {
00492   float X, Y, Z;      /* RGB to XYZ correlation      */
00493   float xc, yc;       /* Chromaticity co-ordinates   */
00494 
00495   /* 1. Map RGB values to their XYZ counterparts.    */
00496   /* Based on 6500K fluorescent, 3000K fluorescent   */
00497   /* and 60W incandescent values for a wide range.   */
00498   /* Note: Y = Illuminance or lux                    */
00499   X = (-0.14282F * r) + (1.54924F * g) + (-0.95641F * b);
00500   Y = (-0.32466F * r) + (1.57837F * g) + (-0.73191F * b);
00501   Z = (-0.68202F * r) + (0.77073F * g) + ( 0.56332F * b);
00502 
00503   /* 2. Calculate the chromaticity co-ordinates      */
00504   xc = (X) / (X + Y + Z);
00505   yc = (Y) / (X + Y + Z);
00506 
00507   /* Return the results in degrees Kelvin */
00508   return (float)xc;
00509 }
00510 float TCS3472_I2C::calculateChromaticityY(int r, int g, int b)
00511 {
00512   float X, Y, Z;      /* RGB to XYZ correlation      */
00513   float xc, yc;       /* Chromaticity co-ordinates   */
00514 
00515   /* 1. Map RGB values to their XYZ counterparts.    */
00516   /* Based on 6500K fluorescent, 3000K fluorescent   */
00517   /* and 60W incandescent values for a wide range.   */
00518   /* Note: Y = Illuminance or lux                    */
00519   X = (-0.14282F * r) + (1.54924F * g) + (-0.95641F * b);
00520   Y = (-0.32466F * r) + (1.57837F * g) + (-0.73191F * b);
00521   Z = (-0.68202F * r) + (0.77073F * g) + ( 0.56332F * b);
00522 
00523   /* 2. Calculate the chromaticity co-ordinates      */
00524   xc = (X) / (X + Y + Z);
00525   yc = (Y) / (X + Y + Z);
00526 
00527   /* Return the results in degrees Kelvin */
00528   return (float)yc;
00529 }
00530 
00531 int TCS3472_I2C::calculateLux(int r, int g, int b)
00532 {
00533   float illuminance;
00534 
00535   /* This only uses RGB ... how can we integrate clear or calculate lux */
00536   /* based exclusively on clear since this might be more reliable?      */
00537   illuminance = (-0.32466F * r) + (1.57837F * g) + (-0.73191F * b);
00538 
00539   return (int)illuminance;
00540 }