Steve Martin / libdev_sfh7779
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SFH7779.h Source File

SFH7779.h

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2017 AT&T, IIoT Foundry, Plano, TX, USA
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 /** \addtogroup drivers */
00018 
00019 /** Support for the OSRAM SFH7779 I2C IR-LED, proximity and ambient light sensor
00020  *
00021  * Example:
00022  * @code
00023  *
00024  * #include "mbed.h"
00025  * #include "SFH7779.h"
00026  *
00027  * I2C            i2c(I2C_SDA, I2C_SCL);
00028  * SFH7779<I2C>  sfh7779(&i2c);
00029  *
00030  * int main() {
00031  *     sfh7779_measurements_t   data;
00032  *     bool                     ok;
00033  *
00034  *     ok = sfh7779.enable() &&
00035  *          sfh7779.read(&data) &&
00036  *          sfh7779.disable();
00037  *           
00038  *     if (ok) {
00039  *         printf("shf7779 proximity reading = %d\r\n", data.prox);
00040  *     } else {
00041  *         printf("shf7779 error!\r\n");
00042  *     }
00043  * }
00044  * @endcode
00045  * @ingroup drivers
00046  */
00047 
00048 #pragma once
00049 
00050 #define SFH7779_BASE_ADDR_7BIT  0x39
00051 
00052 #define SYSTEM_CONTROL_REG  0x40
00053 
00054 #define MODE_CONTROL_REG    0x41
00055 #define   PS_MODE_NORMAL        (0x00<<4)   // default
00056 #define   PS_MODE_TWO_PULSE     (0x10<<4)
00057 #define   MRR_ALS0PS0           (0x00<<0)   // default
00058 #define   MRR_ALS0PS10          (0x01<<0)
00059 #define   MRR_ALS0PS40          (0x02<<0)
00060 #define   MRR_ALS0PS100         (0x03<<0)
00061 #define   MRR_ALS0PS400         (0x04<<0)
00062 #define   MRR_ALS100PS0         (0x05<<0)
00063 #define   MRR_ALS100PS100       (0x06<<0)
00064 #define   MRR_ALS100PS400       (0x07<<0)
00065 #define   MRR_ALS401PS0         (0x08<<0)
00066 #define   MRR_ALS401PS100       (0x09<<0)
00067 #define   MRR_ALS400PS0         (0x0A<<0)
00068 #define   MRR_ALS400PS400       (0x0B<<0)
00069 #define   MRR_ALS50PS50         (0x0C<<0)
00070 
00071 #define ALS_PS_CONTROL_REG  0x42
00072 #define   PS_OUT_PROXIMITY      (0x00<<6)   // default
00073 #define   PS_OUT_INFRARED_DC    (0x01<<6)
00074 #define   ALS_GAIN_ALS1IR1      (0x00<<2)   // default
00075 #define   ALS_GAIN_ALS2IR1      (0x04<<2)
00076 #define   ALS_GAIN_ALS2IR2      (0x05<<2)
00077 #define   ALS_GAIN_ALS64IR64    (0x0A<<2)
00078 #define   ALS_GAIN_ALS128IR64   (0x0E<<2)
00079 #define   ALS_GAIN_ALS128IR128  (0x0F<<2)
00080 #define   LED_CURRENT_25MA      (0x00<<0)
00081 #define   LED_CURRENT_50MA      (0x01<<0)
00082 #define   LED_CURRENT_100M      (0x02<<0)
00083 #define   LED_CURRENT_200MA     (0x03<<0)   // default
00084 
00085 #define PERSISTANCE_REG     0x43
00086 #define   INTR_ON_DATA_AVAIL    (0x00<<0)
00087 #define   INTR_AFTER_1_VAL      (0x01<<0)   // default
00088 #define   INTR_AFTER_2_VALS     (0x02<<0)
00089 #define   INTR_AFTER_3_VALS     (0x03<<0)
00090 #define   INTR_AFTER_4_VALS     (0x04<<0)
00091 #define   INTR_AFTER_5_VALS     (0x05<<0)
00092 #define   INTR_AFTER_6_VALS     (0x06<<0)
00093 #define   INTR_AFTER_7_VALS     (0x07<<0)
00094 #define   INTR_AFTER_8_VALS     (0x08<<0)
00095 #define   INTR_AFTER_9_VALS     (0x09<<0)
00096 #define   INTR_AFTER_10_VALS    (0x0A<<0)
00097 #define   INTR_AFTER_11_VALS    (0x0B<<0)
00098 #define   INTR_AFTER_12_VALS    (0x0C<<0)
00099 #define   INTR_AFTER_13_VALS    (0x0D<<0)
00100 #define   INTR_AFTER_14_VALS    (0x0E<<0)
00101 #define   INTR_AFTER_15_VALS    (0x0F<<0)
00102 
00103 #define PS_DATA_LSB_REG         0x44
00104 #define PS_DATA_MSB_REG         0x45
00105 #define ALS_VIS_DATA_LSB_REG    0x46
00106 #define ALS_VIS_DATA_MSB_REG    0x47
00107 #define ALS_IR_DATA_LSB_REG     0x48
00108 #define ALS_IR_DATA_MSB_REG     0x49
00109 
00110 #define INTERRUPT_CONTROL_REG   0x4A
00111 #define   PS_INT_ACTIVE             (0x01<<7)
00112 #define   ALS_INT_ACTIVE            (0x01<<6)
00113 #define   INT_MODE_PS_HIGH          (0x00<<4)   // default
00114 #define   INT_MODE_PS_HIGHLOW_HYS   (0x01<<4)
00115 #define   INT_MODE_PS_HIGHLOW_OD    (0x02<<4)
00116 #define   INT_ASSERT_LOW_ONLY       (0x00<<3)   // default
00117 #define   INT_ASSERT_LOW_THEN_HIGH  (0x01<<3)
00118 #define   INT_LATCHED               (0x00<<2)   // default
00119 #define   INT_UNLATCHED             (0x01<<2)
00120 #define   INT_PIN_INACTIVE          (0x00<<0)   // default
00121 #define   INT_PIN_PS_ONLY           (0x01<<0)   // default
00122 #define   INT_PIN_ALS_ONLY          (0x02<<0)   // default
00123 #define   INT_PIN_PS_AND_ALS        (0x03<<0)   // default
00124 
00125 typedef struct {
00126     short   prox;
00127     short   als_vis;
00128     short   als_ir;
00129 } sfh7779_measurements_t;
00130 
00131 template <class T>
00132 class SFH7779
00133 {
00134 public:
00135     /**
00136     * Constructor
00137     *
00138     * @param i2c I2C class servicing the sensor
00139     */
00140     SFH7779(T * i2c) : _i2c(i2c) {};
00141 
00142 protected:
00143     /**
00144     * Write to a sensor register
00145     *
00146     * @param reg sensor register to write
00147     * @param val value to write
00148     *
00149     * @returns true if successful
00150     */
00151     bool write_reg(char reg, char val) {
00152         char out[2] = {reg, val};
00153         return 0 == _i2c->write(SFH7779_BASE_ADDR_7BIT << 1, out, 2);
00154     }
00155 
00156     /**
00157     * Read multiple sensor registers
00158     *
00159     * @param start_reg first sensor register to be read
00160     * @param count number of registers to be read
00161     * @param buff pointer to buffer where to store the register values
00162     *
00163     * @returns true if successful
00164     */
00165     bool read_regs(char start_reg, uint8_t count, void * buff) {
00166         bool ok;
00167         ok = (0 == _i2c->write(SFH7779_BASE_ADDR_7BIT << 1, &start_reg, 1, true))
00168              && (0 == _i2c->read(SFH7779_BASE_ADDR_7BIT << 1, (char *)buff, count));
00169         return ok;
00170     }
00171 
00172 public:
00173     /**
00174     * Activate the sensor (begin measurement sampling).  Data samples are
00175     * taken 10 times per second.
00176     *
00177     * @param start_reg first sensor register to be read
00178     * @param count number of registers to be read
00179     * @param buff pointer to buffer where to store the register values
00180     *
00181     * @returns true if successful
00182     */
00183     bool enable(void) {
00184         bool ok;
00185         ok = write_reg(MODE_CONTROL_REG,        // Start ALS and PS sampling
00186                     PS_MODE_NORMAL | MRR_ALS100PS100)
00187              && write_reg(ALS_PS_CONTROL_REG,   // set ALS_VIS=ALS_IR GAIN = 64 current 25ma
00188                     PS_OUT_PROXIMITY | ALS_GAIN_ALS64IR64 | LED_CURRENT_25MA)
00189              && write_reg(PERSISTANCE_REG,      // set interrupt flag upon [any] data available
00190                     INTR_ON_DATA_AVAIL);
00191         return ok;
00192     }
00193 
00194     /**
00195     * Deactivate the sensor (stop measurement sampling and put the sensor in
00196     * standby/low-power mode)
00197     *
00198     * @returns true if successful
00199     */
00200     bool disable(void) {
00201         bool ok;
00202         ok = write_reg(MODE_CONTROL_REG,       // Stop ALS and PS sampling
00203                     PS_MODE_NORMAL | MRR_ALS0PS0);
00204         return ok;
00205     }
00206 
00207     /**
00208     * Wait for and return the next new sensor measurement (proximity,
00209     * ambient visual light, and ambient infrared light).
00210     *
00211     * @param buff pointer to buffer where to store the register values
00212     * @param timeout_ms maximum time to wait for a new sample to become
00213     *          available.  Time is in milliseconds.  Example timeouts are:
00214     *            0 - return a sample if one is available, otherwise don't
00215     *                wait.
00216     *            n - wait up to n milliseconds for a sample to become
00217     *                available.
00218     *           -1 - wait forever for a sample to become available
00219     *
00220     * @returns true if successful
00221     */
00222     bool read(sfh7779_measurements_t * buff, int timeout_ms = -1) {
00223         Timer timer;
00224         timer.start();
00225         while (true) {
00226             struct PACKED {
00227                 sfh7779_measurements_t  measurements;
00228                 char                    stat;
00229             } in;
00230             if (false == read_regs(PS_DATA_LSB_REG, sizeof(in), &in)) {
00231                 break;
00232             }
00233             if (in.stat & PS_INT_ACTIVE) {
00234                 *buff = in.measurements;
00235                 return true;
00236             }
00237             if (timeout_ms != -1 && (timer.read_ms() >= timeout_ms)) {
00238                 break;
00239             }
00240 #ifdef RTOS_H
00241             Thread::wait(5);
00242 #else
00243             wait(0.005);
00244 #endif
00245         }
00246         return false;
00247     }
00248 
00249 protected:
00250     T  *_i2c;
00251 };
00252