Vishay VEML6040 Color RGB sensor I2C driver library

Dependents:   test_VEML6040 testSensor

VEML6040.cpp

Committer:
Rhyme
Date:
2017-11-06
Revision:
5:a4dcc19d057e
Parent:
4:f5b142e3fe79

File content as of revision 5:a4dcc19d057e:

/*
 * File description here
 */
#include "VEML6040.h"

/* VEML6075 SLAVE ADDRESS AND FUNCTION DESCRIPTION */
#define REG_COLOR_CONF  0x00
#define REG_Reserved1  0x01
#define REG_Reserved2  0x02
#define REG_Reserved3  0x03
#define REG_Reserved4  0x04
#define REG_Reserved5  0x05
#define REG_Reserved6  0x06
#define REG_Reserved7  0x07
#define REG_R_Data  0x08
#define REG_G_Data  0x09
#define REG_B_Data  0x0A
#define REG_W_Data  0x0B

// Following magic numbers are from 
// VISHAY veml6040 Application Note 84331
// Page 4 
#define LUX_RESOLUTION_0  (0.25168)
#define LUX_RESOLUTION_1  (0.12584)
#define LUX_RESOLUTION_2  (0.06292)
#define LUX_RESOLUTION_3  (0.03146)
#define LUX_RESOLUTION_4  (0.01573)
#define LUX_RESOLUTION_5  (0.007865)

// Following magic numbers are from 
// VISHAY veml6040 Application Note 84331
// Page 9 
#define CORR_COEFF_M0  (0.048403)
#define CORR_COEFF_M1  (0.183633)
#define CORR_COEFF_M2  (-0.253589)
#define CORR_COEFF_M3  (0.022916)
#define CORR_COEFF_M4  (0.176388)
#define CORR_COEFF_M5  (-0.183205)
#define CORR_COEFF_M6  (-0.077436)
#define CORR_COEFF_M7  (0.124541)
#define CORR_COEFF_M8  (0.032081)

// Following magic numbers are from 
// VISHAY veml6040 Application Note 84331
// Page 10
#define CCT_CONST  (4278.6)
#define OFFSET_OPEN_AIR  (0.5)

/* integration time depending on the IT
 * field in the REG_COLOR_CONF[6:4]
 * According to Vishay error could be up to 20%
 */
int IT_TIME[] = {
      50,   /* 000:   40ms */
     100,   /* 001:   80ms */
     200,   /* 010:  160ms */
     400,   /* 011:  320ms */
     800,   /* 100:  640ms */
    1600,   /* 101: 1280ms */
    1600,   /* 110: 1280ms <- place holder */
    1600    /* 111: 1280ms <- place holder */
} ;

VEML6040::VEML6040(PinName sda, PinName scl, int addr) : m_i2c(sda, scl), m_addr(addr<<1) {
    // activate the peripheral
}

VEML6040::~VEML6040() { }

#if 0
//
// numdata is supposed to be 2
//
void VEML6040::cmdWrite(uint8_t cmd, uint8_t *data, uint8_t numdata)
{
   uint8_t buf[3] ;

    buf[0] = cmd ;
    buf[1] = data[0] ;
    buf[2] = data[1] ;
    writeRegs(buf, 3) ;
}

//
// numdata is supposed to be 2
//

void VEML6040::cmdRead(uint8_t cmd, uint8_t *data, uint8_t numdata)
{
    uint8_t buf[1] ;
    buf[0] = cmd ;
    m_i2c.write(m_addr, buf, 1, true) ; // writing command 
    m_i2c.read(m_addr, (char*)data, numdata) ;
}
#endif 

void VEML6040::getCOLORConf(uint8_t *colorconf)
{
    uint8_t data[2] ;
    readRegs(REG_COLOR_CONF, data, 2) ;
    *colorconf = data[0] ;
}

void VEML6040::setCOLORConf(uint8_t colorconf)
{
     uint8_t data[3] ;
     data[0] = REG_COLOR_CONF ;
     data[1] = colorconf ;
     data[2] = 0 ;
     writeRegs(data, 3) ;
}

int VEML6040::getIT(void)
{
    uint8_t colorconf ;
    int IntegrationTime ;
    getCOLORConf(&colorconf) ;
    IntegrationTime = (colorconf >> 4) & 0x07 ;
    return( IntegrationTime ) ;
}

/*
#define IT_40MS   0x00
#define IT_80MS   0x10
#define IT_160MS  0x20
#define IT_320MS  0x30
#define IT_640MS  0x40
#define IT_1280MS 0x50
*/
void VEML6040::setIT(uint8_t it_value)
{
    uint8_t colorconf ;
    getCOLORConf(&colorconf) ;
    colorconf = it_value | (colorconf & 0x0F) ;
    setCOLORConf(colorconf) ;
}

int VEML6040::getRData(uint16_t *rdata)
{
    uint8_t data[2] ;
    int result ;
    result = readRegs(REG_R_Data, data, 2) ;
    *rdata = (data[1]<<8) | data[0] ;
    return( result ) ;
}

int VEML6040::getGData(uint16_t *gdata)
{
    uint8_t data[2] ;
    int result ;
    result = readRegs(REG_G_Data, data, 2) ;
    *gdata = (data[1]<<8) | data[0] ;
    return( result ) ;
}

int VEML6040::getBData(uint16_t *bdata)
{
    uint8_t data[2] ;
    int result ;
    result = readRegs(REG_B_Data, data, 2) ;
    *bdata = (data[1]<<8) | data[0] ;
    return( result ) ;
}

int VEML6040::getWData(uint16_t *wdata)
{
    uint8_t data[2] ;
    int result ;
    result = readRegs(REG_W_Data, data, 2) ;
    *wdata = (data[1]<<8) | data[0] ;
    return( result ) ;
}

// usage
// fvalue = veml->getUVA() ;
// printf("%f", fvalue) ;
float VEML6040::getR(void) 
{
    uint16_t data ;
    float value ;
    getRData(&data) ;
    value = (float)LUX_RESOLUTION_0 * (float)data ;
    return( value ) ;
}

float VEML6040::getG(void) 
{
    uint16_t data ;
    float value ;
    getGData(&data) ;
    value = (float)LUX_RESOLUTION_0 * (float)data ;
    return( value ) ;
}

float VEML6040::getB(void) 
{
    uint16_t data ;
    float value ;
    getBData(&data) ;
    value = (float)LUX_RESOLUTION_0 * (float)data ;
    return( value ) ;
}

float VEML6040::getW(void) 
{
    uint16_t data ;
    float value ;
    getWData(&data) ;
    value = (float)LUX_RESOLUTION_0 * (float)data ;
    return( value ) ;
}

float VEML6040::getX(void) 
{
    uint16_t R ;
    uint16_t G ;
    uint16_t B ;
    float value ;
    getRData(&R) ;
    getGData(&G) ;
    getBData(&B) ;
    value = (float)CORR_COEFF_M0 * (float)R + (float)CORR_COEFF_M1 * (float)G + (float)CORR_COEFF_M2 * (float)B ;
    return( value ) ;
}

float VEML6040::getY(void) 
{
    uint16_t R ;
    uint16_t G ;
    uint16_t B ;
    float value ;
    getRData(&R) ;
    getGData(&G) ;
    getBData(&B) ;
    value = (float)CORR_COEFF_M3 * (float)R + (float)CORR_COEFF_M4 * (float)G + (float)CORR_COEFF_M5 * (float)B ;
    return( value ) ;
}

float VEML6040::getZ(void) 
{
    uint16_t R ;
    uint16_t G ;
    uint16_t B ;
    float value ;
    getRData(&R) ;
    getGData(&G) ;
    getBData(&B) ;
    value = (float)CORR_COEFF_M6 * (float)R + (float)CORR_COEFF_M7 * (float)G + (float)CORR_COEFF_M8 * (float)B ;
    return( value ) ;
}

float VEML6040::getCCTiData(void) 
{
    uint16_t rdata ;
    uint16_t gdata ;
    uint16_t bdata ;
    float value ;
    getRData(&rdata) ;
    getGData(&gdata) ;
    getBData(&bdata) ;
    value = ((float)rdata - (float)bdata) / (float)gdata + (float)OFFSET_OPEN_AIR ;
    return( value ) ;
}

float VEML6040::getCCTData(void) 
{
//    uint16_t cctidata ;
    float cctidata ;
    float value ;
    cctidata = getCCTiData() ;
//    getCCTiData(&cctidata) ;
    value = (float)CCT_CONST * powf( cctidata, -1.2455 ) ;
    return( value ) ;
}

float VEML6040::getCIEX(void) 
{
    float X ;
    float Y ;
    float Z ;
    float value ;
    X = getX() ;
    Y = getY() ;
    Z = getZ() ; 
    value = (float)X / ((float)X + (float)Y + (float)Z) ;
    return( value ) ;
}

float VEML6040::getCIEY(void) 
{
    float X ;
    float Y ;
    float Z ;
    float value ;
    X = getX() ;
    Y = getY() ;
    Z = getZ() ; 
    value = (float)Y / ((float)X + (float)Y + (float)Z) ;
    return( value ) ;
}

int VEML6040::readRegs(int addr, uint8_t * data, int len) {
    char t[1] = {addr};
    int result ;
    result = m_i2c.write(m_addr, t, 1, true);
    if (result == 0) { // wirte success
        result = m_i2c.read(m_addr, (char *)data, len);
    }
    return(result) ;
}

int VEML6040::writeRegs(uint8_t * data, int len) {
    int result ;
    result = m_i2c.write(m_addr, (char *)data, len);
    return(result) ;
}