OSRAM SFH7779 device driver: Ambient Light and proximity Sensor with Integrated 940nm IR Emitter Version 1.2
Revision 1:fe29e6d3a11e, committed 2017-09-14
- Comitter:
- ninensei
- Date:
- Thu Sep 14 00:18:48 2017 +0000
- Parent:
- 0:51496cf2a8fe
- Commit message:
- Converted to template so that I2C driver derivations can be used (I2C, SoftI2C, etc...); Changed filename to match class name.
Changed in this revision
SFH7779.h | Show annotated file Show diff for this revision Revisions of this file |
sfh7779.h | Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SFH7779.h Thu Sep 14 00:18:48 2017 +0000 @@ -0,0 +1,252 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 AT&T, IIoT Foundry, Plano, TX, USA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** \addtogroup drivers */ + +/** Support for the OSRAM SFH7779 I2C IR-LED, proximity and ambient light sensor + * + * Example: + * @code + * + * #include "mbed.h" + * #include "SFH7779.h" + * + * I2C i2c(I2C_SDA, I2C_SCL); + * SFH7779<I2C> sfh7779(&i2c); + * + * int main() { + * sfh7779_measurements_t data; + * bool ok; + * + * ok = sfh7779.enable() && + * sfh7779.read(&data) && + * sfh7779.disable(); + * + * if (ok) { + * printf("shf7779 proximity reading = %d\r\n", data.prox); + * } else { + * printf("shf7779 error!\r\n"); + * } + * } + * @endcode + * @ingroup drivers + */ + +#pragma once + +#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; + +template <class T> +class SFH7779 +{ +public: + /** + * Constructor + * + * @param i2c I2C class servicing the sensor + */ + SFH7779(T * 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: + T *_i2c; +}; +
--- a/sfh7779.h Tue Sep 12 17:16:56 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,203 +0,0 @@ -// 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; -};