OSRAM SFH7779 device driver: Ambient Light and proximity Sensor with Integrated 940nm IR Emitter Version 1.2

Committer:
ninensei
Date:
Thu Sep 14 00:18:48 2017 +0000
Revision:
1:fe29e6d3a11e
Converted to template so that I2C driver derivations can be used (I2C, SoftI2C, etc...); Changed filename to match class name.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ninensei 1:fe29e6d3a11e 1 /* mbed Microcontroller Library
ninensei 1:fe29e6d3a11e 2 * Copyright (c) 2017 AT&T, IIoT Foundry, Plano, TX, USA
ninensei 1:fe29e6d3a11e 3 *
ninensei 1:fe29e6d3a11e 4 * Licensed under the Apache License, Version 2.0 (the "License");
ninensei 1:fe29e6d3a11e 5 * you may not use this file except in compliance with the License.
ninensei 1:fe29e6d3a11e 6 * You may obtain a copy of the License at
ninensei 1:fe29e6d3a11e 7 *
ninensei 1:fe29e6d3a11e 8 * http://www.apache.org/licenses/LICENSE-2.0
ninensei 1:fe29e6d3a11e 9 *
ninensei 1:fe29e6d3a11e 10 * Unless required by applicable law or agreed to in writing, software
ninensei 1:fe29e6d3a11e 11 * distributed under the License is distributed on an "AS IS" BASIS,
ninensei 1:fe29e6d3a11e 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ninensei 1:fe29e6d3a11e 13 * See the License for the specific language governing permissions and
ninensei 1:fe29e6d3a11e 14 * limitations under the License.
ninensei 1:fe29e6d3a11e 15 */
ninensei 1:fe29e6d3a11e 16
ninensei 1:fe29e6d3a11e 17 /** \addtogroup drivers */
ninensei 1:fe29e6d3a11e 18
ninensei 1:fe29e6d3a11e 19 /** Support for the OSRAM SFH7779 I2C IR-LED, proximity and ambient light sensor
ninensei 1:fe29e6d3a11e 20 *
ninensei 1:fe29e6d3a11e 21 * Example:
ninensei 1:fe29e6d3a11e 22 * @code
ninensei 1:fe29e6d3a11e 23 *
ninensei 1:fe29e6d3a11e 24 * #include "mbed.h"
ninensei 1:fe29e6d3a11e 25 * #include "SFH7779.h"
ninensei 1:fe29e6d3a11e 26 *
ninensei 1:fe29e6d3a11e 27 * I2C i2c(I2C_SDA, I2C_SCL);
ninensei 1:fe29e6d3a11e 28 * SFH7779<I2C> sfh7779(&i2c);
ninensei 1:fe29e6d3a11e 29 *
ninensei 1:fe29e6d3a11e 30 * int main() {
ninensei 1:fe29e6d3a11e 31 * sfh7779_measurements_t data;
ninensei 1:fe29e6d3a11e 32 * bool ok;
ninensei 1:fe29e6d3a11e 33 *
ninensei 1:fe29e6d3a11e 34 * ok = sfh7779.enable() &&
ninensei 1:fe29e6d3a11e 35 * sfh7779.read(&data) &&
ninensei 1:fe29e6d3a11e 36 * sfh7779.disable();
ninensei 1:fe29e6d3a11e 37 *
ninensei 1:fe29e6d3a11e 38 * if (ok) {
ninensei 1:fe29e6d3a11e 39 * printf("shf7779 proximity reading = %d\r\n", data.prox);
ninensei 1:fe29e6d3a11e 40 * } else {
ninensei 1:fe29e6d3a11e 41 * printf("shf7779 error!\r\n");
ninensei 1:fe29e6d3a11e 42 * }
ninensei 1:fe29e6d3a11e 43 * }
ninensei 1:fe29e6d3a11e 44 * @endcode
ninensei 1:fe29e6d3a11e 45 * @ingroup drivers
ninensei 1:fe29e6d3a11e 46 */
ninensei 1:fe29e6d3a11e 47
ninensei 1:fe29e6d3a11e 48 #pragma once
ninensei 1:fe29e6d3a11e 49
ninensei 1:fe29e6d3a11e 50 #define SFH7779_BASE_ADDR_7BIT 0x39
ninensei 1:fe29e6d3a11e 51
ninensei 1:fe29e6d3a11e 52 #define SYSTEM_CONTROL_REG 0x40
ninensei 1:fe29e6d3a11e 53
ninensei 1:fe29e6d3a11e 54 #define MODE_CONTROL_REG 0x41
ninensei 1:fe29e6d3a11e 55 #define PS_MODE_NORMAL (0x00<<4) // default
ninensei 1:fe29e6d3a11e 56 #define PS_MODE_TWO_PULSE (0x10<<4)
ninensei 1:fe29e6d3a11e 57 #define MRR_ALS0PS0 (0x00<<0) // default
ninensei 1:fe29e6d3a11e 58 #define MRR_ALS0PS10 (0x01<<0)
ninensei 1:fe29e6d3a11e 59 #define MRR_ALS0PS40 (0x02<<0)
ninensei 1:fe29e6d3a11e 60 #define MRR_ALS0PS100 (0x03<<0)
ninensei 1:fe29e6d3a11e 61 #define MRR_ALS0PS400 (0x04<<0)
ninensei 1:fe29e6d3a11e 62 #define MRR_ALS100PS0 (0x05<<0)
ninensei 1:fe29e6d3a11e 63 #define MRR_ALS100PS100 (0x06<<0)
ninensei 1:fe29e6d3a11e 64 #define MRR_ALS100PS400 (0x07<<0)
ninensei 1:fe29e6d3a11e 65 #define MRR_ALS401PS0 (0x08<<0)
ninensei 1:fe29e6d3a11e 66 #define MRR_ALS401PS100 (0x09<<0)
ninensei 1:fe29e6d3a11e 67 #define MRR_ALS400PS0 (0x0A<<0)
ninensei 1:fe29e6d3a11e 68 #define MRR_ALS400PS400 (0x0B<<0)
ninensei 1:fe29e6d3a11e 69 #define MRR_ALS50PS50 (0x0C<<0)
ninensei 1:fe29e6d3a11e 70
ninensei 1:fe29e6d3a11e 71 #define ALS_PS_CONTROL_REG 0x42
ninensei 1:fe29e6d3a11e 72 #define PS_OUT_PROXIMITY (0x00<<6) // default
ninensei 1:fe29e6d3a11e 73 #define PS_OUT_INFRARED_DC (0x01<<6)
ninensei 1:fe29e6d3a11e 74 #define ALS_GAIN_ALS1IR1 (0x00<<2) // default
ninensei 1:fe29e6d3a11e 75 #define ALS_GAIN_ALS2IR1 (0x04<<2)
ninensei 1:fe29e6d3a11e 76 #define ALS_GAIN_ALS2IR2 (0x05<<2)
ninensei 1:fe29e6d3a11e 77 #define ALS_GAIN_ALS64IR64 (0x0A<<2)
ninensei 1:fe29e6d3a11e 78 #define ALS_GAIN_ALS128IR64 (0x0E<<2)
ninensei 1:fe29e6d3a11e 79 #define ALS_GAIN_ALS128IR128 (0x0F<<2)
ninensei 1:fe29e6d3a11e 80 #define LED_CURRENT_25MA (0x00<<0)
ninensei 1:fe29e6d3a11e 81 #define LED_CURRENT_50MA (0x01<<0)
ninensei 1:fe29e6d3a11e 82 #define LED_CURRENT_100M (0x02<<0)
ninensei 1:fe29e6d3a11e 83 #define LED_CURRENT_200MA (0x03<<0) // default
ninensei 1:fe29e6d3a11e 84
ninensei 1:fe29e6d3a11e 85 #define PERSISTANCE_REG 0x43
ninensei 1:fe29e6d3a11e 86 #define INTR_ON_DATA_AVAIL (0x00<<0)
ninensei 1:fe29e6d3a11e 87 #define INTR_AFTER_1_VAL (0x01<<0) // default
ninensei 1:fe29e6d3a11e 88 #define INTR_AFTER_2_VALS (0x02<<0)
ninensei 1:fe29e6d3a11e 89 #define INTR_AFTER_3_VALS (0x03<<0)
ninensei 1:fe29e6d3a11e 90 #define INTR_AFTER_4_VALS (0x04<<0)
ninensei 1:fe29e6d3a11e 91 #define INTR_AFTER_5_VALS (0x05<<0)
ninensei 1:fe29e6d3a11e 92 #define INTR_AFTER_6_VALS (0x06<<0)
ninensei 1:fe29e6d3a11e 93 #define INTR_AFTER_7_VALS (0x07<<0)
ninensei 1:fe29e6d3a11e 94 #define INTR_AFTER_8_VALS (0x08<<0)
ninensei 1:fe29e6d3a11e 95 #define INTR_AFTER_9_VALS (0x09<<0)
ninensei 1:fe29e6d3a11e 96 #define INTR_AFTER_10_VALS (0x0A<<0)
ninensei 1:fe29e6d3a11e 97 #define INTR_AFTER_11_VALS (0x0B<<0)
ninensei 1:fe29e6d3a11e 98 #define INTR_AFTER_12_VALS (0x0C<<0)
ninensei 1:fe29e6d3a11e 99 #define INTR_AFTER_13_VALS (0x0D<<0)
ninensei 1:fe29e6d3a11e 100 #define INTR_AFTER_14_VALS (0x0E<<0)
ninensei 1:fe29e6d3a11e 101 #define INTR_AFTER_15_VALS (0x0F<<0)
ninensei 1:fe29e6d3a11e 102
ninensei 1:fe29e6d3a11e 103 #define PS_DATA_LSB_REG 0x44
ninensei 1:fe29e6d3a11e 104 #define PS_DATA_MSB_REG 0x45
ninensei 1:fe29e6d3a11e 105 #define ALS_VIS_DATA_LSB_REG 0x46
ninensei 1:fe29e6d3a11e 106 #define ALS_VIS_DATA_MSB_REG 0x47
ninensei 1:fe29e6d3a11e 107 #define ALS_IR_DATA_LSB_REG 0x48
ninensei 1:fe29e6d3a11e 108 #define ALS_IR_DATA_MSB_REG 0x49
ninensei 1:fe29e6d3a11e 109
ninensei 1:fe29e6d3a11e 110 #define INTERRUPT_CONTROL_REG 0x4A
ninensei 1:fe29e6d3a11e 111 #define PS_INT_ACTIVE (0x01<<7)
ninensei 1:fe29e6d3a11e 112 #define ALS_INT_ACTIVE (0x01<<6)
ninensei 1:fe29e6d3a11e 113 #define INT_MODE_PS_HIGH (0x00<<4) // default
ninensei 1:fe29e6d3a11e 114 #define INT_MODE_PS_HIGHLOW_HYS (0x01<<4)
ninensei 1:fe29e6d3a11e 115 #define INT_MODE_PS_HIGHLOW_OD (0x02<<4)
ninensei 1:fe29e6d3a11e 116 #define INT_ASSERT_LOW_ONLY (0x00<<3) // default
ninensei 1:fe29e6d3a11e 117 #define INT_ASSERT_LOW_THEN_HIGH (0x01<<3)
ninensei 1:fe29e6d3a11e 118 #define INT_LATCHED (0x00<<2) // default
ninensei 1:fe29e6d3a11e 119 #define INT_UNLATCHED (0x01<<2)
ninensei 1:fe29e6d3a11e 120 #define INT_PIN_INACTIVE (0x00<<0) // default
ninensei 1:fe29e6d3a11e 121 #define INT_PIN_PS_ONLY (0x01<<0) // default
ninensei 1:fe29e6d3a11e 122 #define INT_PIN_ALS_ONLY (0x02<<0) // default
ninensei 1:fe29e6d3a11e 123 #define INT_PIN_PS_AND_ALS (0x03<<0) // default
ninensei 1:fe29e6d3a11e 124
ninensei 1:fe29e6d3a11e 125 typedef struct {
ninensei 1:fe29e6d3a11e 126 short prox;
ninensei 1:fe29e6d3a11e 127 short als_vis;
ninensei 1:fe29e6d3a11e 128 short als_ir;
ninensei 1:fe29e6d3a11e 129 } sfh7779_measurements_t;
ninensei 1:fe29e6d3a11e 130
ninensei 1:fe29e6d3a11e 131 template <class T>
ninensei 1:fe29e6d3a11e 132 class SFH7779
ninensei 1:fe29e6d3a11e 133 {
ninensei 1:fe29e6d3a11e 134 public:
ninensei 1:fe29e6d3a11e 135 /**
ninensei 1:fe29e6d3a11e 136 * Constructor
ninensei 1:fe29e6d3a11e 137 *
ninensei 1:fe29e6d3a11e 138 * @param i2c I2C class servicing the sensor
ninensei 1:fe29e6d3a11e 139 */
ninensei 1:fe29e6d3a11e 140 SFH7779(T * i2c) : _i2c(i2c) {};
ninensei 1:fe29e6d3a11e 141
ninensei 1:fe29e6d3a11e 142 protected:
ninensei 1:fe29e6d3a11e 143 /**
ninensei 1:fe29e6d3a11e 144 * Write to a sensor register
ninensei 1:fe29e6d3a11e 145 *
ninensei 1:fe29e6d3a11e 146 * @param reg sensor register to write
ninensei 1:fe29e6d3a11e 147 * @param val value to write
ninensei 1:fe29e6d3a11e 148 *
ninensei 1:fe29e6d3a11e 149 * @returns true if successful
ninensei 1:fe29e6d3a11e 150 */
ninensei 1:fe29e6d3a11e 151 bool write_reg(char reg, char val) {
ninensei 1:fe29e6d3a11e 152 char out[2] = {reg, val};
ninensei 1:fe29e6d3a11e 153 return 0 == _i2c->write(SFH7779_BASE_ADDR_7BIT << 1, out, 2);
ninensei 1:fe29e6d3a11e 154 }
ninensei 1:fe29e6d3a11e 155
ninensei 1:fe29e6d3a11e 156 /**
ninensei 1:fe29e6d3a11e 157 * Read multiple sensor registers
ninensei 1:fe29e6d3a11e 158 *
ninensei 1:fe29e6d3a11e 159 * @param start_reg first sensor register to be read
ninensei 1:fe29e6d3a11e 160 * @param count number of registers to be read
ninensei 1:fe29e6d3a11e 161 * @param buff pointer to buffer where to store the register values
ninensei 1:fe29e6d3a11e 162 *
ninensei 1:fe29e6d3a11e 163 * @returns true if successful
ninensei 1:fe29e6d3a11e 164 */
ninensei 1:fe29e6d3a11e 165 bool read_regs(char start_reg, uint8_t count, void * buff) {
ninensei 1:fe29e6d3a11e 166 bool ok;
ninensei 1:fe29e6d3a11e 167 ok = (0 == _i2c->write(SFH7779_BASE_ADDR_7BIT << 1, &start_reg, 1, true))
ninensei 1:fe29e6d3a11e 168 && (0 == _i2c->read(SFH7779_BASE_ADDR_7BIT << 1, (char *)buff, count));
ninensei 1:fe29e6d3a11e 169 return ok;
ninensei 1:fe29e6d3a11e 170 }
ninensei 1:fe29e6d3a11e 171
ninensei 1:fe29e6d3a11e 172 public:
ninensei 1:fe29e6d3a11e 173 /**
ninensei 1:fe29e6d3a11e 174 * Activate the sensor (begin measurement sampling). Data samples are
ninensei 1:fe29e6d3a11e 175 * taken 10 times per second.
ninensei 1:fe29e6d3a11e 176 *
ninensei 1:fe29e6d3a11e 177 * @param start_reg first sensor register to be read
ninensei 1:fe29e6d3a11e 178 * @param count number of registers to be read
ninensei 1:fe29e6d3a11e 179 * @param buff pointer to buffer where to store the register values
ninensei 1:fe29e6d3a11e 180 *
ninensei 1:fe29e6d3a11e 181 * @returns true if successful
ninensei 1:fe29e6d3a11e 182 */
ninensei 1:fe29e6d3a11e 183 bool enable(void) {
ninensei 1:fe29e6d3a11e 184 bool ok;
ninensei 1:fe29e6d3a11e 185 ok = write_reg(MODE_CONTROL_REG, // Start ALS and PS sampling
ninensei 1:fe29e6d3a11e 186 PS_MODE_NORMAL | MRR_ALS100PS100)
ninensei 1:fe29e6d3a11e 187 && write_reg(ALS_PS_CONTROL_REG, // set ALS_VIS=ALS_IR GAIN = 64 current 25ma
ninensei 1:fe29e6d3a11e 188 PS_OUT_PROXIMITY | ALS_GAIN_ALS64IR64 | LED_CURRENT_25MA)
ninensei 1:fe29e6d3a11e 189 && write_reg(PERSISTANCE_REG, // set interrupt flag upon [any] data available
ninensei 1:fe29e6d3a11e 190 INTR_ON_DATA_AVAIL);
ninensei 1:fe29e6d3a11e 191 return ok;
ninensei 1:fe29e6d3a11e 192 }
ninensei 1:fe29e6d3a11e 193
ninensei 1:fe29e6d3a11e 194 /**
ninensei 1:fe29e6d3a11e 195 * Deactivate the sensor (stop measurement sampling and put the sensor in
ninensei 1:fe29e6d3a11e 196 * standby/low-power mode)
ninensei 1:fe29e6d3a11e 197 *
ninensei 1:fe29e6d3a11e 198 * @returns true if successful
ninensei 1:fe29e6d3a11e 199 */
ninensei 1:fe29e6d3a11e 200 bool disable(void) {
ninensei 1:fe29e6d3a11e 201 bool ok;
ninensei 1:fe29e6d3a11e 202 ok = write_reg(MODE_CONTROL_REG, // Stop ALS and PS sampling
ninensei 1:fe29e6d3a11e 203 PS_MODE_NORMAL | MRR_ALS0PS0);
ninensei 1:fe29e6d3a11e 204 return ok;
ninensei 1:fe29e6d3a11e 205 }
ninensei 1:fe29e6d3a11e 206
ninensei 1:fe29e6d3a11e 207 /**
ninensei 1:fe29e6d3a11e 208 * Wait for and return the next new sensor measurement (proximity,
ninensei 1:fe29e6d3a11e 209 * ambient visual light, and ambient infrared light).
ninensei 1:fe29e6d3a11e 210 *
ninensei 1:fe29e6d3a11e 211 * @param buff pointer to buffer where to store the register values
ninensei 1:fe29e6d3a11e 212 * @param timeout_ms maximum time to wait for a new sample to become
ninensei 1:fe29e6d3a11e 213 * available. Time is in milliseconds. Example timeouts are:
ninensei 1:fe29e6d3a11e 214 * 0 - return a sample if one is available, otherwise don't
ninensei 1:fe29e6d3a11e 215 * wait.
ninensei 1:fe29e6d3a11e 216 * n - wait up to n milliseconds for a sample to become
ninensei 1:fe29e6d3a11e 217 * available.
ninensei 1:fe29e6d3a11e 218 * -1 - wait forever for a sample to become available
ninensei 1:fe29e6d3a11e 219 *
ninensei 1:fe29e6d3a11e 220 * @returns true if successful
ninensei 1:fe29e6d3a11e 221 */
ninensei 1:fe29e6d3a11e 222 bool read(sfh7779_measurements_t * buff, int timeout_ms = -1) {
ninensei 1:fe29e6d3a11e 223 Timer timer;
ninensei 1:fe29e6d3a11e 224 timer.start();
ninensei 1:fe29e6d3a11e 225 while (true) {
ninensei 1:fe29e6d3a11e 226 struct PACKED {
ninensei 1:fe29e6d3a11e 227 sfh7779_measurements_t measurements;
ninensei 1:fe29e6d3a11e 228 char stat;
ninensei 1:fe29e6d3a11e 229 } in;
ninensei 1:fe29e6d3a11e 230 if (false == read_regs(PS_DATA_LSB_REG, sizeof(in), &in)) {
ninensei 1:fe29e6d3a11e 231 break;
ninensei 1:fe29e6d3a11e 232 }
ninensei 1:fe29e6d3a11e 233 if (in.stat & PS_INT_ACTIVE) {
ninensei 1:fe29e6d3a11e 234 *buff = in.measurements;
ninensei 1:fe29e6d3a11e 235 return true;
ninensei 1:fe29e6d3a11e 236 }
ninensei 1:fe29e6d3a11e 237 if (timeout_ms != -1 && (timer.read_ms() >= timeout_ms)) {
ninensei 1:fe29e6d3a11e 238 break;
ninensei 1:fe29e6d3a11e 239 }
ninensei 1:fe29e6d3a11e 240 #ifdef RTOS_H
ninensei 1:fe29e6d3a11e 241 Thread::wait(5);
ninensei 1:fe29e6d3a11e 242 #else
ninensei 1:fe29e6d3a11e 243 wait(0.005);
ninensei 1:fe29e6d3a11e 244 #endif
ninensei 1:fe29e6d3a11e 245 }
ninensei 1:fe29e6d3a11e 246 return false;
ninensei 1:fe29e6d3a11e 247 }
ninensei 1:fe29e6d3a11e 248
ninensei 1:fe29e6d3a11e 249 protected:
ninensei 1:fe29e6d3a11e 250 T *_i2c;
ninensei 1:fe29e6d3a11e 251 };
ninensei 1:fe29e6d3a11e 252