Gsma Version

Dependents:   GSMACode stripReader

sfh7779.h

Committer:
elmkom
Date:
2017-04-21
Revision:
1:fc2dbccffe34
Parent:
0:5e15a306a518

File content as of revision 1:fc2dbccffe34:

// OSRAM SFH7779: I2C IR-LED, proximity sensor, and ambient light sensor

#define SFH7779_BASE_ADDR_7BIT  0x39

#define SYSTEM_CONTROL_REG  0x40

#define MODE_CONTROL_REG    0x41
#define   PS_MODE_NORMAL        (0x00<<4)   // default
#define   PS_MODE_TWO_PULSE     (0x10<<4)
#define   MRR_ALS0PS0           (0x00<<0)   // default
#define   MRR_ALS0PS10          (0x01<<0)
#define   MRR_ALS0PS40          (0x02<<0)
#define   MRR_ALS0PS100         (0x03<<0)    
#define   MRR_ALS0PS400         (0x04<<0)
#define   MRR_ALS100PS0         (0x05<<0)
#define   MRR_ALS100PS100       (0x06<<0)
#define   MRR_ALS100PS400       (0x07<<0)
#define   MRR_ALS401PS0         (0x08<<0)
#define   MRR_ALS401PS100       (0x09<<0)
#define   MRR_ALS400PS0         (0x0A<<0)   
#define   MRR_ALS400PS400       (0x0B<<0)
#define   MRR_ALS50PS50         (0x0C<<0)

#define ALS_PS_CONTROL_REG  0x42
#define   PS_OUT_PROXIMITY      (0x00<<6)   // default
#define   PS_OUT_INFRARED_DC    (0x01<<6)
#define   ALS_GAIN_ALS1IR1      (0x00<<2)   // default
#define   ALS_GAIN_ALS2IR1      (0x04<<2)
#define   ALS_GAIN_ALS2IR2      (0x05<<2)
#define   ALS_GAIN_ALS64IR64    (0x0A<<2)
#define   ALS_GAIN_ALS128IR64   (0x0E<<2)
#define   ALS_GAIN_ALS128IR128  (0x0F<<2)
#define   LED_CURRENT_25MA      (0x00<<0)
#define   LED_CURRENT_50MA      (0x01<<0)
#define   LED_CURRENT_100M      (0x02<<0)
#define   LED_CURRENT_200MA     (0x03<<0)   // default

#define PERSISTANCE_REG     0x43
#define   INTR_ON_DATA_AVAIL    (0x00<<0)
#define   INTR_AFTER_1_VAL      (0x01<<0)   // default
#define   INTR_AFTER_2_VALS     (0x02<<0)
#define   INTR_AFTER_3_VALS     (0x03<<0)
#define   INTR_AFTER_4_VALS     (0x04<<0)
#define   INTR_AFTER_5_VALS     (0x05<<0)
#define   INTR_AFTER_6_VALS     (0x06<<0)
#define   INTR_AFTER_7_VALS     (0x07<<0)
#define   INTR_AFTER_8_VALS     (0x08<<0)
#define   INTR_AFTER_9_VALS     (0x09<<0)
#define   INTR_AFTER_10_VALS    (0x0A<<0)
#define   INTR_AFTER_11_VALS    (0x0B<<0)
#define   INTR_AFTER_12_VALS    (0x0C<<0)
#define   INTR_AFTER_13_VALS    (0x0D<<0)
#define   INTR_AFTER_14_VALS    (0x0E<<0)
#define   INTR_AFTER_15_VALS    (0x0F<<0)

#define PS_DATA_LSB_REG         0x44
#define PS_DATA_MSB_REG         0x45
#define ALS_VIS_DATA_LSB_REG    0x46
#define ALS_VIS_DATA_MSB_REG    0x47
#define ALS_IR_DATA_LSB_REG     0x48
#define ALS_IR_DATA_MSB_REG     0x49

#define INTERRUPT_CONTROL_REG   0x4A
#define   PS_INT_ACTIVE             (0x01<<7)
#define   ALS_INT_ACTIVE            (0x01<<6)
#define   INT_MODE_PS_HIGH          (0x00<<4)   // default
#define   INT_MODE_PS_HIGHLOW_HYS   (0x01<<4)
#define   INT_MODE_PS_HIGHLOW_OD    (0x02<<4)
#define   INT_ASSERT_LOW_ONLY       (0x00<<3)   // default
#define   INT_ASSERT_LOW_THEN_HIGH  (0x01<<3)
#define   INT_LATCHED               (0x00<<2)   // default
#define   INT_UNLATCHED             (0x01<<2)
#define   INT_PIN_INACTIVE          (0x00<<0)   // default
#define   INT_PIN_PS_ONLY           (0x01<<0)   // default
#define   INT_PIN_ALS_ONLY          (0x02<<0)   // default
#define   INT_PIN_PS_AND_ALS        (0x03<<0)   // default

typedef struct {
    short   prox;
    short   als_vis;
    short   als_ir;
} sfh7779_measurements_t;

class SFH7779
{
public:
    /**
    * Constructor
    *
    * @param i2c I2C class servicing the sensor
    */
    SFH7779(I2C * i2c) : _i2c(i2c) {};

protected:
    /**
    * Write to a sensor register
    *
    * @param reg sensor register to write
    * @param val value to write
    *
    * @returns true if successful
    */
    bool write_reg(char reg, char val) {
        char out[2] = {reg, val};
        return 0 == _i2c->write(SFH7779_BASE_ADDR_7BIT << 1, out, 2);
    }
    
    /**
    * Read multiple sensor registers
    *
    * @param start_reg first sensor register to be read
    * @param count number of registers to be read
    * @param buff pointer to buffer where to store the register values
    *
    * @returns true if successful
    */
    bool read_regs(char start_reg, uint8_t count, void * buff) {
        bool ok;
        ok = (0 == _i2c->write(SFH7779_BASE_ADDR_7BIT << 1, &start_reg, 1, true))
             && (0 == _i2c->read(SFH7779_BASE_ADDR_7BIT << 1, (char *)buff, count));
        return ok;
    }
    
public:
    /**
    * Activate the sensor (begin measurement sampling).  Data samples are
    * taken 10 times per second.
    *
    * @param start_reg first sensor register to be read
    * @param count number of registers to be read
    * @param buff pointer to buffer where to store the register values
    *
    * @returns true if successful
    */
    bool enable(void) {
        bool ok;
        ok = write_reg(MODE_CONTROL_REG,        // Start ALS and PS sampling
                    PS_MODE_NORMAL | MRR_ALS100PS100)
             && write_reg(ALS_PS_CONTROL_REG,   // set ALS_VIS=ALS_IR GAIN = 64 current 25ma
                    PS_OUT_PROXIMITY | ALS_GAIN_ALS64IR64 | LED_CURRENT_25MA)
             && write_reg(PERSISTANCE_REG,      // set interrupt flag upon [any] data available
                    INTR_ON_DATA_AVAIL);
        return ok;
    }
        
    /**
    * Deactivate the sensor (stop measurement sampling and put the sensor in
    * standby/low-power mode)
    *
    * @returns true if successful
    */
    bool disable(void) {
        bool ok;        
        ok = write_reg(MODE_CONTROL_REG,       // Stop ALS and PS sampling
                    PS_MODE_NORMAL | MRR_ALS0PS0);
        return ok;
    }
        
    /**
    * Wait for and return the next new sensor measurement (proximity,
    * ambient visual light, and ambient infrared light).
    *
    * @param buff pointer to buffer where to store the register values
    * @param timeout_ms maximum time to wait for a new sample to become
    *          available.  Time is in milliseconds.  Example timeouts are:
    *            0 - return a sample if one is available, otherwise don't
    *                wait.
    *            n - wait up to n milliseconds for a sample to become
    *                available.
    *           -1 - wait forever for a sample to become available
    *
    * @returns true if successful 
    */
    bool read(sfh7779_measurements_t * buff, int timeout_ms = -1) {
        Timer timer;
        timer.start();
        while (true) {
            struct PACKED {
                sfh7779_measurements_t  measurements;
                char                    stat;
            } in;
            if (false == read_regs(PS_DATA_LSB_REG, sizeof(in), &in)) {
                break;
            }
            if (in.stat & PS_INT_ACTIVE) {
                *buff = in.measurements;
                return true;
            }
            if (timeout_ms != -1 && (timer.read_ms() >= timeout_ms)) {
                break;
            }
#ifdef RTOS_H
            Thread::wait(5);
#else
            wait(0.005);
#endif
        }
        return false;
    }

protected:
    I2C *_i2c;
};