Nespresso RGB Sensor / GroveColourSensor

Dependents:   ColorDetector ColorDetectorV2 offline_sync_k64f

Fork of GroveColourSensor by Brian Daniels

GroveColourSensor.cpp

Committer:
bridadan
Date:
2015-04-15
Revision:
2:50cb56828ab9
Child:
3:a401a082d57e

File content as of revision 2:50cb56828ab9:

/*
 * Copyright (c) 2006-2013 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include "GroveColourSensor.h"

/**
*   Constructor, doesn't affect the device at all.
*
* @param i2c A pointer to the initialized I2C instance.
*
*/
GroveColourSensor::GroveColourSensor(I2C *i2c) : i2c(i2c) {
    /* empty*/
}

/**
*   Powers up the color sensor.
*
*/
bool GroveColourSensor::powerUp(void) {
    static const char powerUpCommand[] = {0x80, 0x03};
    /* turn on the color sensor */
    return i2c->write((SEVEN_BIT_ADDRESS << 1), powerUpCommand, sizeof(powerUpCommand)) == 0;
}

/**
*   Powers down the color sensor.
*
*/
void GroveColourSensor::powerDown(void) {
    static const char powerDownCommand[] = {0x80, 0x00};
    /* turn on the color sensor */
    if (i2c->write((SEVEN_BIT_ADDRESS << 1), powerDownCommand, sizeof(powerDownCommand)) != 0) {
        error("failed to power down the sensor");
    }
}

/**
*   Set the gain of the color sensor.
*
*   The following are valid gain values:
*   
*   0 - 1X gain
*   1 - 4X gain
*   2 - 16X gain
*   3 - 64X gain
*   
* @param gain The gain value specified above.
*/
void GroveColourSensor::setGain(uint8_t gain) {
    // Set gain (0 Prescale)
    char gainRegValue = 0x00 | (gain << 4);
    
    char gainCommand[] = {0x87, gainRegValue};
    i2c->write((SEVEN_BIT_ADDRESS << 1), gainCommand, sizeof(gainCommand));
}

/**
*   Read a specific color.
*   
* @param colour The color to red (RED, GREEN, BLUE, or CLEAR).
*/
uint16_t GroveColourSensor::readColour(Colour_t colour) {
    char readColorRegistersCommand = 0xb0 + (2 * static_cast<unsigned>(colour));
    i2c->write((SEVEN_BIT_ADDRESS << 1), &readColorRegistersCommand, 1 /* size */);

    uint16_t colourValue;
    i2c->read((SEVEN_BIT_ADDRESS << 1), reinterpret_cast<char *>(&colourValue), sizeof(uint16_t));
    return colourValue;
}

/**
*   Configures the color sensor to expect block reads.
*
*/
void GroveColourSensor::setBlockRead() {
    char blockReadCommand = 0xD0;
    i2c->write((SEVEN_BIT_ADDRESS << 1), &blockReadCommand, 1);
}

/**
*   Read the red, green, blue, and clear channels in one transaction. You must call setBlockRead() before calling this function.
*   
* @param sample A pointer to the RGBC instance you wish to populate.
*/
void GroveColourSensor::readBlock(RGBC *sample) {
    char tmpColours[8] = {0};
    
    if (!i2c->read((SEVEN_BIT_ADDRESS << 1), tmpColours, sizeof(tmpColours))) {        
        sample->ch.green = bytesTo16bit(tmpColours[0], tmpColours[1] << 8);
        sample->ch.red = bytesTo16bit(tmpColours[2], tmpColours[3] << 8);
        sample->ch.blue = bytesTo16bit(tmpColours[4], tmpColours[5] << 8);
        sample->ch.clear = bytesTo16bit(tmpColours[6], tmpColours[7] << 8);
    } else {
        printf("I2C Read error\r\n");
    }
}

/**
*   Non enum version of readColour()
*   
* @param colour The integer corresponding to the color you wish to read.
*/
uint16_t GroveColourSensor::readColour(unsigned colour) {
    if (colour >= NUM_COLORS) {
        return 0;
    }

    return readColour(static_cast<Colour_t>(colour));
}

/**
*   Helper function to convert two bytes into a uint16_t.
*   
* @param lowByte Least signficant byte.
* @param highByte Most signficant byte.
*/
uint16_t GroveColourSensor::bytesTo16bit(char lowByte, char highByte) {
    uint16_t res = 0;
    res |= lowByte;
    res |= highByte << 8;
    return res;
}