VCNL4020, Fully Integrated Proximity and Ambient Light Sensor with Infrared Emitter, I2C Interface, and Interrupt Function
Dependents: testVCNL4020 testSensor
Diff: VCNL4020.cpp
- Revision:
- 0:95952f8fe2b4
- Child:
- 1:4f4cdaf51fc2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VCNL4020.cpp Wed Mar 29 04:39:07 2017 +0000 @@ -0,0 +1,487 @@ +#include "mbed.h" +#include "VCNL4020.h" + +/* Register address definitions */ +#define REG_COMMAND 0x80 +#define REG_PRODUCT_ID_REV 0x81 +#define REG_PROXIMITY_RATE 0x82 +#define REG_IR_LED_CURRENT 0x83 +#define REG_AMBIENT_LIGHT_PARAM 0x84 +#define REG_AMBIENT_LIGHT_RESULT 0x85 +#define REG_AMBIENT_LIGHT_MSB 0x85 +#define REG_AMBIENT_LIGHT_LSB 0x86 +#define REG_PROXIMITY_RESULT 0x87 +#define REG_PROXIMITY_MSB 0x87 +#define REG_PROXIMITY_LSB 0x88 +#define REG_INTERRUPT_CONTROL 0x89 +#define REG_LOW_THRESHOLD_MSB 0x8A +#define REG_LOW_THRESHOLD_LSB 0x8B +#define REG_HIGH_THRESHOLD_MSB 0x8C +#define REG_HIGH_THRESHOLD_LSB 0x8D +#define REG_INTERRUPT_STATUS 0x8E +#define REG_PROXIMITY_MOD_TIMING 0x8F + +/* bit definitions */ +/* Command Register (0x80) Register #0 */ +/* bit[7] config_lock Read only bit. Value = 1 */ +#define BIT_CONFIG_LOCK 0x80 + +/* bit[6] als_data_rdy Read only bit. + * Value = 1 when ambient light measurement data is availabe in thre result registers. + * This bit will be reset when one of the corresponding result registers (reg #5, reg #6) is read */ +#define BIT_ALS_DATA_RDY 0x40 + +/* bit[5] prox_data_rdy Read only bit. + * Value = 1 when proximity measurement data is available in the result registers. + * This bit will be reset when one of the corresponding result registers (reg #7, reg #8) is read */ +#define BIT_PROX_DATA_RDY 0x20 + +/* bit[4] als_od R/W bit. + * Starts a single on-demand measurement for ambient light. + * If averaging is enabled, starts a sequence of readings and stores the averaged result. + * Result is available at the end of conversion for reading in the registers #5(HB) and #6(LB). */ +#define BIT_ALS_OD 0x10 + +/* bit[3] prox_od R/W bit. + * Starts a single on-demand measurement for proximity. + * Result is available at the end of conversion for reading in the registers #7(HB) and #8(LB). */ +#define BIT_PROX_OD 0x08 + +/* bit[2] als_en R/W bit. Enables periodic als measurement */ +#define BIT_ALS_EN 0x04 + +/* bit[1] prox_en R/W bit. Enables periodic proximity measurement */ +#define BIT_PROX_EN 0x02 + +/* bit[0] sleftimed_en R/W bit. + * Enables state machine and LP oscillator for self timed measurements; + * no measurement is performed until the correnponding bit is set */ +#define BIT_SELFTIMED_EN 0x01 + +/* Note: With setting bit[3] and bit[4] at the same write command, + * a simultaneously measurement of ambient light and proximity is done. + * Beside als_en and/or prox_en first selftimed_en needs to be set. + * On-demand measurement modes are disabled if setltimed_en bit is set. + * For the selftimed_en mode changes in reading rates (reg #5 and reg #2) + * can be made only when b[0] (seltfimed_en bit) = 0. + * For the als_od mode changes to the reg #4 can be made only when b[4](als_od bit) = 0; + * this is to avoid synchronization problems and undefined states between + * the clock domains. In effect this means that it is only reasonable to change + * rates while no selftimed conversion is ongoing. */ + + uint8_t VCNL4020::getCommandReg(void) + { + uint8_t cmd ; + readRegs(REG_COMMAND, &cmd, 1) ; + return(cmd) ; +} + +void VCNL4020::setCommandReg(uint8_t cmd) +{ + uint8_t data[2] ; + data[0] = REG_COMMAND ; + data[1] = cmd ; + writeRegs(data, 2) ; +} + +uint8_t VCNL4020::getConfigLock(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd = (cmd >> 7) & 0x01 ; + return(cmd) ; +} + +void VCNL4020::setConfigLock(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd |= BIT_CONFIG_LOCK ; + setCommandReg(cmd) ; +} + +void VCNL4020::clearConfigLock(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd ^= BIT_CONFIG_LOCK ; + setCommandReg(cmd) ; +} + +uint8_t VCNL4020::alsDataReady(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd = (cmd >> 6) & 0x01 ; + return(cmd) ; +} + +uint8_t VCNL4020::proxDataReady(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd = (cmd >> 5) & 0x01 ; + return(cmd) ; +} + +void VCNL4020::trigAlsOd(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd |= BIT_ALS_OD ; + setCommandReg(cmd) ; +} + +void VCNL4020::trigProxOd(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd |= BIT_PROX_OD ; + setCommandReg(cmd) ; +} + +void VCNL4020::trigBothOd(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd |= (BIT_ALS_OD | BIT_PROX_OD) ; + setCommandReg(cmd) ; +} + +uint8_t VCNL4020::getAlsPeriodicEnable(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd = (cmd >> 2) & 0x01 ; + return(cmd) ; +} + +void VCNL4020::enableAlsPeriodic(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd |= BIT_ALS_EN ; + setCommandReg(cmd) ; +} + +void VCNL4020::disableAlsPeriodic(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd ^= BIT_ALS_EN ; + setCommandReg(cmd) ; +} + +uint8_t VCNL4020::getProxPeriodicEnable(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd = (cmd >> 1) & 0x01 ; + return(cmd) ; +} + +void VCNL4020::enableProxPeriodic(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd |= BIT_PROX_EN ; + setCommandReg(cmd) ; +} + +void VCNL4020::disableProxPeriodic(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd ^= BIT_PROX_EN ; + setCommandReg(cmd) ; +} + +uint8_t VCNL4020::getSelfTimedEnable(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd = cmd & BIT_SELFTIMED_EN ; + return(cmd) ; +} + +void VCNL4020::enableSelfTimed(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd |= BIT_SELFTIMED_EN ; + setCommandReg(cmd) ; +} + +void VCNL4020::disableSelfTimed(void) +{ + uint8_t cmd ; + cmd = getCommandReg() ; + cmd ^= BIT_SELFTIMED_EN ; + setCommandReg(cmd) ; +} + +/* Product ID Revision (0x81) Register #1 */ +/* bit[7:4] Product ID Read Only bits. Value = 2 */ +/* bit[3:0] Revision ID Read Only bits. Value = 1 */ +uint8_t VCNL4020::getProdID(void) +{ + uint8_t prod_id ; + readRegs(REG_PRODUCT_ID_REV, &prod_id, 1) ; + prod_id = (prod_id >> 4) & 0x0F ; + return(prod_id) ; +} + +/* Proximity Rate (0x82) Register #2 */ +/* bit[7:3] (reserved) */ +/* bit[2:1] Rate of Proximity Measurement (no. of measurements per second) */ +/* R/W bits */ +/* 000 - 1.95 measurements/s (DEFAULT) */ +/* 001 - 3.90626 */ +/* 010 - 7.8125 */ +/* 011 - 16.625 */ +/* 100 - 31.25 */ +/* 101 - 62.5 */ +/* 110 - 125 */ +/* 111 - 250 */ +uint8_t VCNL4020::getProxRate(void) +{ + uint8_t rate ; + readRegs(REG_PROXIMITY_RATE, &rate, 1) ; + rate &= 0x07 ; + return( rate ) ; +} + +void VCNL4020::setProxRate(uint8_t rate) +{ + uint8_t data[2] ; + data[0] = REG_PROXIMITY_RATE ; + data[1] = (rate & 0x07) ; + writeRegs(data, 2) ; +} + +/* IR LED Current (0x83) Register #3 */ +/* bit[7:6] Fuse prog ID Read only bits */ +/* Information about fuse program revision used for initial setup/calibration of the device. */ +/* bit[5:0] IR LED current value R/W bits. */ +/* IR LED current = Value(dec.) x 10mA */ +/* Valid Rage = 0 to 20d. +/* 0 = 0mA, 1 = 10mA, 2 = 20mA (DEFAULT) ... 20 = 200mA */ +/* LED Current is limited to 200mA for values higher than 20d. */ +uint8_t VCNL4020::getFuseProgID(void) +{ + uint8_t data ; + readRegs(REG_IR_LED_CURRENT, &data, 1) ; + data = ((data >> 5) & 0x03) ; + return(data) ; +} + +uint8_t VCNL4020::getIrLedCurrent(void) +{ + uint8_t data ; + readRegs(REG_IR_LED_CURRENT, &data, 1) ; + data = data & 0x3F ; + return(data) ; +} + +void VCNL4020::setIrLedCurrent(uint8_t value) +{ + uint8_t data[2] ; + data[0] = REG_IR_LED_CURRENT ; + data[1] = value & 0x3F ; + writeRegs(data, 2) ; +} + +/* Ambient Light Parameter (0x84) Register #4 */ + +/* bit[7] Cont.Conv.mode R/W bit. Continuous conversion mode. */ +/* Enable = 1; Disable = 0 = DEFAULT */ +/* This funcion can be used for performing faster ambient light measurements. */ +/* This mode should only be used with ambient light on-demand measurements. */ +/* Do not use with self-fimed mode. */ +/* Please refer to the application information chapter 3.3 for details about this function */ +#define BIT_CONT_CONV_MODE 0x80 + +/* bit[6:4] als_rate R/W bits. Ambient light measurement rate */ +/* 000 - 1 samples/s */ +/* 001 - 2 */ +/* 010 - 3 */ +/* 011 - 4 */ +/* 100 - 5 */ +/* 101 - 6 */ +/* 110 - 8 */ +/* 111 - 10 */ + +/* bit[3] Auto offset compensation R/W bit. Automatic offset compensation */ +/* Enable = 1 = DEFAULT; Disable = 0 */ +/* In order to compensate a technology, package or temperature realted drift +/* of the ambient light values there is a built in automatic offset compensation function */ +/* With active auto offset compensation the offset value is measured before each +/* ambient light measurement and subtracted automatically from actual reading. */ + +/* bit[2:0] Averaging function (number of measurements per fun) */ +/* R/W bits. Averating function */ +/* Bit values sets the number of single conversions done during one measurement cycle. */ +/* Result is the average value of all conversions */ +/* Number of conversions = 2^decimal_value */ +/* 0 = 1 conv, 1 = 2 conv, 2 = 4 conv, ... 5 = 32 conv (DEFAULT), ... 7 = 128 conv. */ + +/* Ambient Light Result 0x85, 0x86, Read only bits Register #5, #6 */ +uint16_t VCNL4020::getAls(void) +{ + uint16_t result ; + uint8_t data[2] ; + readRegs(REG_AMBIENT_LIGHT_RESULT, data, 2) ; + result = (data[0] << 8) | data[1] ; + return( result ) ; +} + +/* Proxymity Measurement Result 0x87, 0x88 Register #7, #8 */ +uint16_t VCNL4020::getProx(void) +{ + uint16_t result ; + uint8_t data[2] ; + readRegs(REG_PROXIMITY_RESULT, data, 2) ; + result = (data[0] << 8) | data[1] ; + return( result ) ; +} + +/* Interrupt Control 0x89, Register #9 */ +/* bit[7:5] Int count exceed R/W bits */ +/* These bits contains number of consecutive measurements needed above/below the threshold */ +/* 000 - 1 count = DEFAULT */ +/* 001 - 2 */ +/* 010 - 4 */ +/* 011 - 8 */ +/* 100 - 16 */ +/* 101 - 32 */ +/* 110 - 64 */ +/* 111 - 128 */ +/* bit[4] (reserved) */ +/* bit[3] INT_PROX_ready_EN R/W bit */ +/* Enables interrupt generation at proximity data ready */ + +/* bit[2] INT_ALS_ready_EN R/W bit */ +/* Enables interrupt generation at ambient data ready */ + +/* bit[1] INT_THRES_EN R/W bit */ +/* Enables interrupt generation when high or low threshol is exceeded */ + +/* bit[0] INT_THRES_SEL R/W bit */ +/* if 0: thresholds are applied to proximity measurements */ +/* if 1: thresholds are applied to als measurements */ +uint8_t VCNL4020::getIntControl(void) +{ + uint8_t data ; + readRegs(REG_INTERRUPT_CONTROL, &data, 1) ; + return(data) ; +} + +void VCNL4020::setIntControl(uint8_t ctrl) +{ + uint8_t data[2] ; + data[0] = REG_INTERRUPT_CONTROL ; + data[1] = ctrl ; + writeRegs(data, 2) ; +} + +/* Low Threshold 0x8A, 0x8B Register #10, #11 */ + +uint16_t VCNL4020::getLowThreshold(void) +{ + uint32_t threshold ; + uint8_t data[2] ; + readRegs(REG_LOW_THRESHOLD_MSB, data, 2) ; + threshold = (data[0] << 8) | data[1] ; + return(threshold) ; +} + +void VCNL4020::setLowThreshold(uint16_t threshold) +{ + uint8_t data[5] ; + data[0] = REG_LOW_THRESHOLD_MSB ; + data[1] = (threshold >> 8) & 0xFF ; + data[2] = threshold & 0xFF ; + writeRegs(data, 3) ; +} + +/* High Threshold 0x8C, 0x8D Register #12, #13 */ +uint16_t VCNL4020::getHighThreshold(void) +{ + uint32_t threshold ; + uint8_t data[2] ; + readRegs(REG_HIGH_THRESHOLD_MSB, data, 2) ; + threshold = (data[0] << 8) | data[1] ; + return(threshold) ; +} + +void VCNL4020::setHighThreshold(uint16_t threshold) +{ + uint8_t data[5] ; + data[0] = REG_HIGH_THRESHOLD_MSB ; + data[1] = (threshold >> 8) & 0xFF ; + data[2] = threshold & 0xFF ; + writeRegs(data, 3) ; +} + + +/* Interrupt Status 0x8E Register #14 */ +/* bit[7:4] (reserved) */ +/* bit[3] int_prox_ready */ +/* bit[2] int_als_ready */ +/* bit[1] int_th_low */ +/* bit[0] int_th_hi */ +uint8_t VCNL4020::getIntStatus(void) +{ + uint8_t status ; + readRegs(REG_INTERRUPT_STATUS, &status, 1) ; + status &= 0x0F ; + return(status) ; +} + +/* Proximity Modulator Timing Adjustment 0x8F Register #15 */ +/* bit[7:5] Modulation delay time */ +/* bit[4:3] Proximity frequency */ +/* bit[2:0] Modulation dead time */ +uint8_t VCNL4020::getProxModTiming(void) +{ + uint8_t pmta ; /* Proximity Modulator Timing Adjustment */ + readRegs(REG_PROXIMITY_MOD_TIMING, &pmta, 1) ; + return(pmta) ; +} + +void VCNL4020::setProxModTiming(uint8_t pmta) +{ + uint8_t data[2] ; + data[0] = REG_PROXIMITY_MOD_TIMING ; + data[1] = pmta ; + writeRegs(data, 2) ; +} + +uint8_t VCNL4020::getRevID(void) +{ + uint8_t rev_id ; + readRegs(REG_PRODUCT_ID_REV, &rev_id, 1) ; + rev_id = (rev_id & 0x0F) ; + return(rev_id) ; +} + +VCNL4020::VCNL4020(PinName sda, PinName scl, int addr) : + m_i2c(sda, scl), m_addr(addr<<1) +{ + // activate the peripheral +} + + +VCNL4020::~VCNL4020() +{ +} + +void VCNL4020::readRegs(int addr, uint8_t * data, int len) { + char t[1] = {addr}; + m_i2c.write(m_addr, t, 1, true); + m_i2c.read(m_addr, (char *)data, len); +} + +void VCNL4020::writeRegs(uint8_t * data, int len) { + m_i2c.write(m_addr, (char *)data, len); +} \ No newline at end of file