VCNL4020, Fully Integrated Proximity and Ambient Light Sensor with Infrared Emitter, I2C Interface, and Interrupt Function

Dependents:   testVCNL4020 testSensor

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