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

Dependents:   ADJD-S311_HelloWorld

Files at this revision

API Documentation at this revision

Comitter:
CheeseW
Date:
Mon Mar 24 04:46:51 2014 +0000
Child:
1:fc17a6ccc6f0
Commit message:
Come out for publication

Changed in this revision

ADJDs311.cpp Show annotated file Show diff for this revision Revisions of this file
ADJDs311.h Show annotated file Show diff for this revision Revisions of this file
--- /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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ADJDs311.h	Mon Mar 24 04:46:51 2014 +0000
@@ -0,0 +1,218 @@
+#ifndef ADJDs311_h
+#define ADJDs311_h
+
+/**
+ * Includes
+ */
+#include "mbed.h"
+
+// ADJD-S311's I2C address, don't change
+#define WRITE_ADDRESS   0xE8    // Address for write
+#define READ_ADDRESS    0xE9    // Address for read
+
+
+//#define RED     0
+//#define GREEN   1
+//#define BLUE    2
+//#define CLEAR   3
+
+// ADJD-S311's register list
+#define CTRL            0x00
+#define CONFIG          0x01
+#define CAP_RED         0x06
+#define CAP_GREEN       0x07
+#define CAP_BLUE        0x08
+#define CAP_CLEAR       0x09
+#define INT_RED_LO      0xA
+#define INT_RED_HI      0xB
+#define INT_GREEN_LO    0xC
+#define INT_GREEN_HI    0xD
+#define INT_BLUE_LO     0xE
+#define INT_BLUE_HI     0xF
+#define INT_CLEAR_LO    0x10
+#define INT_CLEAR_HI    0x11
+#define DATA_RED_LO     0x40
+#define DATA_RED_HI     0x41
+#define DATA_GREEN_LO   0x42
+#define DATA_GREEN_HI   0x43
+#define DATA_BLUE_LO    0x44
+#define DATA_BLUE_HI    0x45
+#define DATA_CLEAR_LO   0x46
+#define DATA_CLEAR_HI   0x47
+#define OFFSET_RED      0x48
+#define OFFSET_GREEN    0x49
+#define OFFSET_BLUE     0x4A
+#define OFFSET_CLEAR    0x4B
+
+struct RGBC{
+    int red;
+    int blue;
+    int green;
+    int clear;
+};
+
+
+class ADJDs311{
+ public:
+
+/**
+ * Create a color sensor interface
+ *
+ * @param sda       pin connected to sda of color sensor
+ * @param scl       pin connected to scl of color sensor
+ * @param led       pin connected to on board led of the sensor
+ */
+  ADJDs311(PinName sda, PinName scl, PinName led);
+  
+  
+/**
+ * Calibrate the capacitance and integration time slot so that the current
+ * readings are as close to 1000 as possible and the difference between RGB
+ * readings are as small as possible
+ */
+  void calibrate();
+  
+/**
+ * Turn the on board LED on/off.
+ *
+ * @param ledOn     Whether to turn the LED on.
+ */
+  void ledMode(bool ledOn);
+
+/**
+ * Get the current offset stored in offset registers
+ *
+ * @return          Current offset stored in offset registers
+ */
+ RGBC getOffset();
+ 
+/**
+ * Use the current light condition to set the offset
+ *
+ * @param useOffset Wether to use the offset
+ * @return          The offset set
+ */
+ RGBC setOffset(bool useOffset = true);
+ 
+ 
+/**
+ * Use the offset registers to automatically subtract offset from the readings
+ *
+ * @param useOffset Wether to use the offset
+ */
+  void offsetMode(bool useOffset);
+
+/**
+ * Read in the color value from the sensor
+ *
+ * @return          Structure containing the value of red, green, blue and clear
+ */
+  RGBC read();
+  
+/**
+ * Get the gain of number of capacitor for each channel, in the range of 0 to
+ * 15. Less capacitor will give higher sensitivity.
+ *
+ * @return          Structure containing the gain of number of capacitor for each 
+ *                  channel.
+ */
+  RGBC getColorCap();
+  
+/**
+ * Get the gain of number of integration time slot, in the range of 0 to 4095.
+ * More integration time slot will give higher sensitivity.
+ *
+ * @return          Structure containing the gain of number of integration time 
+ *                  slot for each channel.
+ */
+  RGBC getColorInt();
+  
+/**
+ * Set the gain of number of capacitor for each channel, in the range of 0 to
+ * 15. Less capacitor will give higher sensitivity.
+ *
+ * @param red       gain value for red
+ * @param green     gain value for green
+ * @param blue      gain value for blue
+ * @param clear     gain value for clear
+ */
+  void setColorCap(int red, int green, int blue, int clear); 
+  
+/**
+ * Set the gain of number of integration time slot, in the range of 0 to 4095.
+ * More integration time slot will give higher sensitivity.
+ *
+ * @param red       gain value for red
+ * @param green     gain value for green
+ * @param blue      gain value for blue
+ * @param clear     gain value for clear
+ */
+  void setColorInt(int red, int green, int blue, int clear);   
+  
+private:
+
+    // fields
+    I2C _i2c;
+    DigitalOut _led;
+    
+    RGBC colorCap;
+    RGBC colorInt;
+    RGBC colorOffset;
+    
+// private memeber functions
+    
+/** Write a byte of data to ADJD-S311 register
+ *
+ * @param data      byte data to write to the register
+ * @param regAddr   address of the register to write
+ */
+    void writeRegister(char data, char regAddr);
+   
+/** Read a byte of data from ADJD-S311 register
+ *
+ * @param regAddr   address of the register to write
+ * @retrun          byte data read from the register
+ */
+    char readRegister(char regAddr);
+
+/** Read 2 bytes of data from ADJD-S311 registers and return as an integer
+ *
+ * @param loRegAddr low register address
+ * @return          value from registers as an int
+ */
+  int readInt(char loRegAddr);
+  
+/** Write an integer data of 2 bytes to ADJD-S311 registers
+ * 
+ * @param loRegAddr low register address
+ * @param data      integer value to write
+ */
+   void writeInt(int data, char loRegAddr);  
+   
+/**
+ * Tell the color sensor to perform measurement and store data to the color and
+ * clear registers. Must be called before reading
+ * color values
+ */
+  void performMeasurement();
+    
+/**
+ * Calibrate the clear integration time slot so that current reading of the 
+ * clear channel will be as close to 1000 as possible     
+ */  
+  void calibrateClearInt();
+  
+/**
+ * Calibrate the color integration time slots so that the max current reading 
+ * of the RGB channels will be as close to 1000 as possible
+ */  
+  void calibrateColorInt();
+  
+/**
+ * Calibrate the color capacitors so the difference of reading of different
+ * channels are as small as possible 
+ */  
+  void calibrateCapacitors();
+};
+
+#endif
\ No newline at end of file