A library for the Avago ADJD-S311-CR999 Color Light Sensor
Dependents: ADJD-S311_HelloWorld
ADJDs311.cpp
- Committer:
- CheeseW
- Date:
- 2014-03-24
- Revision:
- 0:d5bb69f92ea3
File content as of revision 0:d5bb69f92ea3:
#include "ADJDs311.h" #include "mbed.h" #include <algorithm> ADJDs311::ADJDs311(PinName sda, PinName scl, PinName led): _i2c(sda, scl), _led(led) { // hard coded value for number of capacitors colorCap.red = 12; colorCap.green = 9; colorCap.blue = 2; colorCap.clear = 9; // hard coded value for number of integration time slot colorInt.red = 16; colorInt.green = 16; colorInt.blue = 16; colorInt.clear = 16; colorOffset.red = readRegister(OFFSET_RED); colorOffset.green = readRegister(OFFSET_GREEN); colorOffset.blue = readRegister(OFFSET_BLUE); colorOffset.clear = readRegister(OFFSET_CLEAR); // write number of capacitors to registers writeRegister(colorCap.red & 0xF, CAP_RED); writeRegister(colorCap.green & 0xF, CAP_GREEN); writeRegister(colorCap.blue & 0xF, CAP_BLUE); writeRegister(colorCap.clear & 0xF, CAP_CLEAR); // write number of integration time slot to registers writeInt(colorInt.red & 0xFFF, INT_RED_LO); writeInt(colorInt.green & 0xFFF, INT_GREEN_LO); writeInt(colorInt.blue & 0xFFF, INT_BLUE_LO); writeInt(colorInt.clear & 0xFFF, INT_CLEAR_LO); } // Read data regeisters and return a RGBC var RGBC ADJDs311::read(){ RGBC color = RGBC(); performMeasurement(); color.red = readInt(DATA_RED_LO); color.green = readInt(DATA_GREEN_LO); color.blue = readInt(DATA_BLUE_LO); color.clear = readInt(DATA_CLEAR_LO); return color; } // get number of capacitor RGBC ADJDs311::getColorCap() { return colorCap; } // get number of intetgration time slot RGBC ADJDs311::getColorInt() { return colorInt; } // set number of capacitor void ADJDs311::setColorCap(int red, int green, int blue, int clear) { colorCap.red = red; colorCap.green = green; colorCap.blue = blue; colorCap.clear = clear; // write number of capacitors to registers writeRegister(colorCap.red & 0xF, CAP_RED); writeRegister(colorCap.green & 0xF, CAP_GREEN); writeRegister(colorCap.blue & 0xF, CAP_BLUE); writeRegister(colorCap.clear & 0xF, CAP_CLEAR); } // set number of integration time slot void ADJDs311::setColorInt(int red, int green, int blue, int clear) { colorInt.red = red; colorInt.green = green; colorInt.blue = blue; colorInt.clear = clear; // write number of integration time slot to registers writeInt(colorInt.red & 0xFFF, INT_RED_LO); writeInt(colorInt.green & 0xFFF, INT_GREEN_LO); writeInt(colorInt.blue & 0xFFF, INT_BLUE_LO); writeInt(colorInt.clear & 0xFFF, INT_CLEAR_LO); } // Perform measurement and save the result to registers void ADJDs311::performMeasurement(){ writeRegister(0x01, 0x00); // start sensing while(readRegister(0x00) != 0) ; // waiting for a result } // Write a byte of data to a specific ADJD-S311 address void ADJDs311::writeRegister(char data, char regAddr){ char temp[2]; temp[0] = regAddr; // register addresss temp[1] = data; _i2c.write(WRITE_ADDRESS, temp, 2, false); } // Read a byte of data from ADJD-S311 address char ADJDs311::readRegister(char regAddr){ char data; _i2c.write(WRITE_ADDRESS, ®Addr, 1, true); _i2c.read(READ_ADDRESS, &data, 1, false); return data; } // Read two bytes of data from ADJD-S311 address and addres+1 int ADJDs311::readInt(char loRegAddr) { return (unsigned char)readRegister(loRegAddr) + (((unsigned char)readRegister(loRegAddr+1))<<8); } // Write two bytes of data to ADJD-S311 address and addres+1 void ADJDs311::writeInt(int data, char loRegAddr) { char lobyte = data; char hibyte = data >> 8; writeRegister(lobyte, loRegAddr); writeRegister(hibyte, loRegAddr+1); } /* calibrateClear() - This function calibrates the clear integration registers of the ADJD-S311. */ void ADJDs311::calibrateClearInt(){ bool gainFound = false; int upperBox=4096; int lowerBox = 0; int half; while (!gainFound){ half = ((upperBox-lowerBox)/2)+lowerBox; //no further halfing possbile if (half==lowerBox){ gainFound=true; }else{ colorInt.clear = half; writeInt(colorInt.clear & 0xFFF, INT_CLEAR_LO); performMeasurement(); int halfValue = readInt(DATA_CLEAR_LO); if (halfValue>800){ upperBox=half; }else if (halfValue<800){ lowerBox=half; }else{ gainFound=true; } } } } /* calibrateColor() - This function clalibrates the RG and B integration registers. */ void ADJDs311::calibrateColorInt(){ bool gainFound = false; int upperBox=4096; int lowerBox = 0; int half; int halfValue; while (!gainFound) { half = ((upperBox-lowerBox)/2)+lowerBox; //no further halfing possbile if (half==lowerBox) { gainFound=true; } else { colorInt.red = half; colorInt.green = half; colorInt.blue = half; // write number of integration time slot to registers writeInt(colorInt.red & 0xFFF, INT_RED_LO); writeInt(colorInt.green & 0xFFF, INT_GREEN_LO); writeInt(colorInt.blue & 0xFFF, INT_BLUE_LO); performMeasurement(); halfValue = 0; halfValue=std::max(halfValue, readInt(DATA_RED_LO)); halfValue=std::max(halfValue, readInt(DATA_GREEN_LO)); halfValue=std::max(halfValue, readInt(DATA_BLUE_LO)); if (halfValue>800) { upperBox=half; } else if (halfValue<800) { lowerBox=half; } else { gainFound=true; } } } } /* calibrateCapacitors() - This function calibrates each of the RGB and C capacitor registers. */ void ADJDs311::calibrateCapacitors(){ bool calibrated = false; //need to store detect better calibration int diff; int oldDiff = 1024; while (!calibrated){ // sensor gain setting (Avago app note 5330) // CAPs are 4bit (higher value will result in lower output) writeRegister(colorCap.red & 0xF, CAP_RED); writeRegister(colorCap.green & 0xF, CAP_GREEN); writeRegister(colorCap.blue & 0xF, CAP_BLUE); int maxRead = 0; int minRead = 1024; int red = 0; int green = 0; int blue = 0; for (int i=0; i<4 ;i ++) { performMeasurement(); red += readInt(DATA_RED_LO); green += readInt(DATA_GREEN_LO); blue += readInt(DATA_BLUE_LO); } red /= 4; green /= 4; blue /= 4; maxRead = std::max(maxRead, red); maxRead = std::max(maxRead, green); maxRead = std::max(maxRead, blue); minRead = std::min(minRead, red); minRead = std::min(minRead, green); minRead = std::min(minRead, blue); diff = maxRead - minRead; if (oldDiff != diff) { if ((maxRead==red) && (colorCap.red<15)) colorCap.red++; else if ((maxRead == green) && (colorCap.green<15)) colorCap.green++; else if ((maxRead == blue) && (colorCap.blue<15)) colorCap.blue++; } else calibrated = true; oldDiff=diff; } } void ADJDs311::calibrate(){ setColorCap(0, 0, 0, 8); calibrateColorInt(); // This calibrates R, G, and B int registers calibrateClearInt(); // This calibrates the C int registers calibrateCapacitors(); // This calibrates the RGB, and C cap registers calibrateColorInt(); } void ADJDs311::ledMode(bool ledOn) { _led = ledOn; } void ADJDs311::offsetMode(bool useOffset) { if (useOffset) { writeRegister(0x01, CONFIG); } else { writeRegister(0x00, CONFIG); } } RGBC ADJDs311::getOffset() { return colorOffset; } RGBC ADJDs311::setOffset(bool useOffset) { _led = 0; writeRegister(0x02, CTRL); while(readRegister(CTRL)); colorOffset.red = readRegister(OFFSET_RED); colorOffset.green = readRegister(OFFSET_GREEN); colorOffset.blue = readRegister(OFFSET_BLUE); colorOffset.clear = readRegister(OFFSET_CLEAR); offsetMode(useOffset); return colorOffset; }