A library for the Avago ADJD-S311-CR999 Color Light Sensor
Dependents: ADJD-S311_HelloWorld
Diff: ADJDs311.cpp
- Revision:
- 0:d5bb69f92ea3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ADJDs311.cpp Mon Mar 24 04:46:51 2014 +0000 @@ -0,0 +1,320 @@ +#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; +}