Kevin Braun / bme280

veml60xx.cpp

Committer:
loopsva
Date:
2016-04-21
Revision:
1:d8d62aee6d5b
Parent:
bme280.cpp@ 0:40b4ebf843c6

File content as of revision 1:d8d62aee6d5b:

// Vishay veml6040 RGBW and veml6075 UVA + UVB optical sensors

#include "veml60xx.h"

//--------------------------------------------------------------------------------------------------------------------------------------//
// Constructor, to allow for user to select i2c frequency

veml60xx::veml60xx(PinName sda, PinName scl,  int i2cFrequency) {
    _i2c_ = new I2C(sda, scl);
    _i2c_->frequency(i2cFrequency);
}

//--------------------------------------------------------------------------------------------------------------------------------------//
// deconstructor

veml60xx::~veml60xx() {
}

//--------------------------------------------------------------------------------------------------------------------------------------//
// Set/initialize the veml60xx config register.

void veml60xx::setConfig(veml60xx_struct& Pntr, uint16_t val) {
    vemlBuffer[0] = VEML60xx_CONF_REG;
    vemlBuffer[1] = val;
    //vemlBuffer[1] = VEML60xx_CONF_BITS_IT_400m320m | val;
    //vemlBuffer[1] = VEML60xx_CONF_BITS_IT_400m320m | VEML6075_CONF_BITS_HD;
    //vemlBuffer[1] = VEML60xx_CONF_BITS_IT_400m320m | VEML6075_CONF_BITS_HD | VEML60xx_CONF_BITS_AF;
    vemlBuffer[2] = 0;
    _i2c_->write(VEML60_WADDR, vemlBuffer, 3, false);
    Pntr.conf_reg = (vemlBuffer[2] << 8)  | vemlBuffer[1];
}

//--------------------------------------------------------------------------------------------------------------------------------------//
// Get veml60xx ID register.  Returns register value
// Note: the veml6040 does hvae a device ID, but is not in datasheet

uint16_t veml60xx::getID(veml60xx_struct& Pntr) {
    vemlBuffer[0] = VEML6075_CHIP_ID_REG;
    _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
    _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
    uint16_t rdata = (vemlBuffer[1] << 8)  | vemlBuffer[0];
    if((rdata & VEML6075_DEVICE_ID) == VEML6075_DEVICE_ID) {
        Pntr.is6075 = true;
        Pntr.is6040 = false;
    } else
    if((rdata & VEML6040_DEVICE_ID) == VEML6040_DEVICE_ID) {
        Pntr.is6075 = false;
        Pntr.is6040 = true;
    } else {
        Pntr.is6075 = false;
        Pntr.is6040 = false;
    }
    return(rdata);
}

//--------------------------------------------------------------------------------------------------------------------------------------//
// Get veml60xx config register.  Returns register value

uint16_t veml60xx::getConfig(veml60xx_struct& Pntr) {
    vemlBuffer[0] = VEML60xx_CONF_REG;
    _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
    _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
    uint16_t rdata = (vemlBuffer[1] << 8)  | vemlBuffer[0];
    if(Pntr.is6040) {
        uint16_t c = rdata & VEML60xx_CONF_BITS_IT;
        switch (c) {
            case VEML60xx_CONF_BITS_IT_50m40m: 
                Pntr.lux_step = VEML6040_LUX_STEP_000;
                break;
            case VEML60xx_CONF_BITS_IT_100m80m:
                Pntr.lux_step = VEML6040_LUX_STEP_001;
                break;
            case VEML60xx_CONF_BITS_IT_200m160m:
                Pntr.lux_step = VEML6040_LUX_STEP_010;
                break;
            case VEML60xx_CONF_BITS_IT_400m320m:
                Pntr.lux_step = VEML6040_LUX_STEP_011;
                break;
            case VEML60xx_CONF_BITS_IT_800m640m:
                Pntr.lux_step = VEML6040_LUX_STEP_100;
                break;
            case VEML6040_CONF_BITS_IT_1280m:
                Pntr.lux_step = VEML6040_LUX_STEP_101;
                break;
            default:
                Pntr.lux_step = 0.0;
                break;
        }
    }
    return(rdata);
}    

//--------------------------------------------------------------------------------------------------------------------------------------//
// If AF set to trigger mode, start a conversion process trigger
// Returns: 0=trigger set, 1=already triggered,  2=no AF bit - cannot set trigger

uint16_t veml60xx::startAccess(veml60xx_struct& Pntr) {
    uint16_t val = getConfig(Pntr);
    if((val & VEML60xx_CONF_BITS_AF) == VEML60xx_CONF_BITS_AF) {
        if((val & VEML60xx_CONF_BITS_TRIG) == VEML60xx_CONF_BITS_TRIG) return(1);
        val |= VEML60xx_CONF_BITS_TRIG;
        setConfig(Pntr, val);
        return(0);
    }
    return(2);
}       
    
//--------------------------------------------------------------------------------------------------------------------------------------//
// Get VEML60xx values.  Saves raw data is data structure.  Returns 0 if successful, !0 if status is (something else);
// mode: false = VEML6075, true = VEML6040

uint16_t veml60xx::getRawData(veml60xx_struct& Pntr) {
    Pntr.conf_reg = getConfig(Pntr);
    Pntr.id = getID(Pntr);
        
    if(Pntr.is6075) {
        vemlBuffer[0] = VEML6075_UVA_DATA_REG;
        _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
        _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
        Pntr.uva_d = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
    }
    
    vemlBuffer[0] = VEML6075_DUMMY_REG;
    _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
    _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
    if(Pntr.is6075) {
        Pntr.dummy_d = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
    } else 
    if(Pntr.is6040) {
        Pntr.r_d = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
    }
    
    vemlBuffer[0] = VEML6075_UVB_DATA_REG;
    _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
    _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
    if(Pntr.is6075) {
        Pntr.uvb_d = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
    } else 
    if(Pntr.is6040) {
        Pntr.g_d = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
    }
       
    vemlBuffer[0] = VEML6075_UV_COMP1_REG;
    _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
    _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
    if(Pntr.is6075) {
        Pntr.uv_c1 = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
    } else 
    if(Pntr.is6040) {
        Pntr.b_d = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
    }
        
    vemlBuffer[0] = VEML6075_UV_COMP2_REG;
    _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
    _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
    if(Pntr.is6075) {
        Pntr.uv_c1 = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
    } else
    if(Pntr.is6040) {
        Pntr.w_d = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
    }
    
    return(0);
}

//--------------------------------------------------------------------------------------------------------------------------------------//
// Convert raw data into real UVA, UVB and UVI numbers

void veml60xx::convertRawData(veml60xx_struct& Pntr) {
    getRawData(Pntr);
    
    //Eq (1)
    Pntr.uva_comp = (double)(Pntr.uva_d - Pntr.dummy_d) - 
                    VEML6075_UVA_COEF_A * (double)(Pntr.uv_c1 - Pntr.dummy_d) - 
                    VEML6075_UVA_COEF_B * (double)(Pntr.uv_c2 - Pntr.dummy_d);
    
    //Eq (2)
    Pntr.uvb_comp = (double)(Pntr.uvb_d - Pntr.dummy_d) - 
                    VEML6075_UVB_COEF_C * (double)(Pntr.uv_c1 - Pntr.dummy_d) - 
                    VEML6075_UVB_COEF_D * (double)(Pntr.uv_c2 - Pntr.dummy_d);
    //Eq (3)
    Pntr.uv_index = ((Pntr.uva_comp * VEML6075_UVA_RESP) + (Pntr.uvb_comp * VEML6075_UVB_RESP))/2.0;
}
    

//--------------------------------------------------------------------------------------------------------------------------------------//
// If there is a lux over/underflow, automatically adjust the CONF_BITS_IT by +-1 to compensate accordingly
// if returns true, the Lux level was changed.

bool veml60xx::autoAdjustLux(veml60xx_struct& Pntr) {
    getRawData(Pntr);
    uint16_t rdata = Pntr.conf_reg;
    uint16_t lux = rdata & VEML60xx_CONF_BITS_IT;
    if(Pntr.is6040) {
        if((Pntr.r_d < 255) && (Pntr.g_d < 255) && (Pntr.b_d < 255) && (Pntr.w_d < 255)) {
            if(lux == VEML6040_CONF_BITS_IT_1280m) return false;
            lux += VEML60xx_CONF_BITS_IT_100m80m;
            rdata = (rdata & ~VEML60xx_CONF_BITS_IT) | lux;
            setConfig(Pntr, rdata);
            return true;
        } else 
        if((Pntr.r_d == 65535) || (Pntr.g_d == 65535) || (Pntr.b_d == 65535) || (Pntr.w_d == 65535)) {
            if(lux == VEML60xx_CONF_BITS_IT_50m40m) return false;
            lux -= VEML60xx_CONF_BITS_IT_100m80m;
            rdata = (rdata & ~VEML60xx_CONF_BITS_IT) | lux;
            setConfig(Pntr, rdata);
            return true;
        }
    } else
    if(Pntr.is6075) {
        if((Pntr.uva_d < 255) && (Pntr.uvb_d < 255)) {
            if(lux == VEML60xx_CONF_BITS_IT_800m640m) return false;
            lux += VEML60xx_CONF_BITS_IT_100m80m;
            rdata = (rdata & ~VEML60xx_CONF_BITS_IT) | lux;
            setConfig(Pntr, rdata);
            return true;
        } else 
        if((Pntr.uva_d == 65535) || (Pntr.uvb_d == 65535)) {
            if(lux == VEML60xx_CONF_BITS_IT_50m40m) return false;
            lux -= VEML60xx_CONF_BITS_IT_100m80m;
            rdata = (rdata & ~VEML60xx_CONF_BITS_IT) | lux;
            setConfig(Pntr, rdata);
            return true;
        }
    }
    return false;
}