A library for the Avago ADJD-S311-CR999 Color Light Sensor

Dependents:   ADJD-S311_HelloWorld

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, &regAddr, 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;
+}