Home | History | Annotate | Download | only in si114x
      1 /*
      2  * Author: Jon Trulson <jtrulson (at) ics.com>
      3  * Copyright (c) 2015 Intel Corporation.
      4  *
      5  * Thanks to Adafruit for some important clues
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining
      8  * a copy of this software and associated documentation files (the
      9  * "Software"), to deal in the Software without restriction, including
     10  * without limitation the rights to use, copy, modify, merge, publish,
     11  * distribute, sublicense, and/or sell copies of the Software, and to
     12  * permit persons to whom the Software is furnished to do so, subject to
     13  * the following conditions:
     14  *
     15  * The above copyright notice and this permission notice shall be
     16  * included in all copies or substantial portions of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     22  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     23  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     24  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  */
     26 #pragma once
     27 
     28 #include <string>
     29 #include <mraa/i2c.h>
     30 #include <mraa/gpio.h>
     31 
     32 #define SI114X_I2C_BUS 0
     33 #define SI114X_DEFAULT_I2C_ADDR 0x60
     34 #define SI114X_HW_KEY 0x17
     35 
     36 
     37 namespace upm {
     38 
     39   /**
     40    * @brief SI1145 UV Light Sensor library
     41    * @defgroup si114x libupm-si114x
     42    * @ingroup adafruit i2c light
     43    */
     44 
     45   /**
     46    * @library si114x
     47    * @sensor si114x
     48    * @comname SI1145 UV Light Sensor
     49    * @altname SI1146, SI1147
     50    * @type light
     51    * @man adafruit
     52    * @web https://www.adafruit.com/products/1777
     53    * @con i2c
     54    *
     55    * @brief API for the SI1145 UV Light Sensor
     56    *
     57    * This module was tested with the Adafruit* UV Light Sensor
     58    *
     59    * This device is capable of measuring IR and visible ambient
     60    * light as well. It also supports the ability to use externally
     61    * attached LEDs to perform proximity detection on 3 separate
     62    * channels.
     63    *
     64    * Currently, this class only supports the retrieving of the
     65    * calculated UV index measured by the device, but enough
     66    * infrastructure is provided to make it easy to enhance this driver
     67    * in the future to support additional capabilities, including
     68    * interrupt support.
     69    *
     70    * @image html si114x.jpg
     71    * @snippet si114x.cxx Interesting
     72    */
     73   class SI114X {
     74   public:
     75 
     76     /**
     77      * SI114X registers
     78      */
     79     typedef enum { REG_PART_ID       = 0x00,
     80                    REG_REV_ID        = 0x01,
     81                    REG_SEQ_ID        = 0x02,
     82                    REG_INT_CFG       = 0x03,
     83                    REG_IRQ_ENABLE    = 0x04,
     84 
     85                    // these two are not documented in the datasheet,
     86                    // but are mentioned there, as well as in the
     87                    // Adafruit example
     88                    REG_IRQ_MODE1     = 0x05,
     89                    REG_IRQ_MODE2     = 0x06,
     90 
     91                    REG_HW_KEY        = 0x07,
     92                    REG_MEAS_RATE0    = 0x08,
     93                    REG_MEAS_RATE1    = 0x09,
     94 
     95                    REG_PS_LED21      = 0x0f,
     96                    REG_PS_LED3       = 0x10,
     97 
     98                    REG_UCOEF0        = 0x13,
     99                    REG_UCOEF1        = 0x14,
    100                    REG_UCOEF2        = 0x15,
    101                    REG_UCOEF3        = 0x16,
    102                    REG_PARAM_WR      = 0x17,
    103                    REG_COMMAND       = 0x18,
    104 
    105                    REG_RESPONSE      = 0x20,
    106                    REG_IRQ_STATUS    = 0x21,
    107                    REG_ALS_VIS_DATA0 = 0x22,
    108                    REG_ALS_VIS_DATA1 = 0x23,
    109                    REG_ALS_IR_DATA0  = 0x24,
    110                    REG_ALS_IR_DATA1  = 0x25,
    111                    REG_PS1_DATA0     = 0x26,
    112                    REG_PS1_DATA1     = 0x27,
    113                    REG_PS2_DATA0     = 0x28,
    114                    REG_PS2_DATA1     = 0x29,
    115                    REG_PS3_DATA0     = 0x2a,
    116                    REG_PS3_DATA1     = 0x2b,
    117                    REG_AUX_UVINDEX0  = 0x2c,
    118                    REG_AUX_UVINDEX1  = 0x2d,
    119                    REG_PARAM_READ    = 0x2e,
    120 
    121                    REG_CHIP_STAT     = 0x30,
    122 
    123                    REG_ANA_IN_KEY0   = 0x3b,
    124                    REG_ANA_IN_KEY1   = 0x3c,
    125                    REG_ANA_IN_KEY2   = 0x3d,
    126                    REG_ANA_IN_KEY3   = 0x3e
    127     } SI114X_REG_T;
    128 
    129     /**
    130      * Parameter memory (PARAM)
    131      */
    132     typedef enum { PARAM_I2C_ADDDR         = 0x00,
    133                    PARAM_CHLIST            = 0x01,
    134                    PARAM_PSLED12_SEL       = 0x02,
    135                    PARAM_PSLED3_SEL        = 0x03,
    136 
    137                    PARAM_PS_ENCODING       = 0x05,
    138                    PARAM_ALS_ENCODING      = 0x06,
    139                    PARAM_PS1_ADCMUX        = 0x07,
    140                    PARAM_PS2_ADCMUX        = 0x08,
    141                    PARAM_PS3_ADCMUX        = 0x09,
    142                    PARAM_PS_ADC_COUNT      = 0x0a,
    143                    PARAM_PS_ADC_GAIN       = 0x0b,
    144                    PARAM_PS_ADC_MISC       = 0x0c,
    145 
    146                    PARAM_ALS_IR_ADCMUX     = 0x0e,
    147                    PARAM_AUX_ADCMUX        = 0x0f,
    148                    PARAM_ALS_VIS_ADC_COUNT = 0x10,
    149                    PARAM_ALS_VIS_ADC_GAIN  = 0x11,
    150                    PARAM_ALS_VIS_ADC_MISC  = 0x12,
    151 
    152                    PARAM_LED_REC           = 0x1c,
    153                    PARAM_ALS_IR_ADC_COUNT  = 0x1d,
    154                    PARAM_ALS_IR_ADX_GAIN   = 0x1e,
    155                    PARAM_ALS_IR_ADC_MISC   = 0x1f
    156     } SI114X_PARAM_T;
    157 
    158     /**
    159      * Commands (written to the REG_COMMAND register)
    160      */
    161     typedef enum { CMD_NOOP          = 0x00, // clear RESPONSE reg
    162                    CMD_RESET         = 0x01,
    163                    CMD_BUSADDR       = 0x02,
    164 
    165                    CMD_PS_FORCE      = 0x05,
    166                    CMD_GET_CAL       = 0x12,
    167                    CMD_ALS_FORCE     = 0x06,
    168                    CMD_PSALS_FORCE   = 0x07,
    169 
    170                    CMD_PS_PAUSE      = 0x09,
    171                    CMD_ALS_PAUSE     = 0x0a,
    172                    CMD_PSALS_PAUSE   = 0x0b,
    173 
    174                    CMD_PS_AUTO       = 0x0d,
    175                    CMD_ALS_AUTO      = 0x0e,
    176                    CMD_PSALS_AUTO    = 0x0f,
    177 
    178                    CMD_PARAM_QUERY   = 0x80, // OR'd with PARAM_T value
    179                    CMD_PARAM_SET     = 0xa0  // OR'd with PARAM_T value
    180     } SI114X_CMD_T;
    181 
    182 
    183     /**
    184      * Channel list enable bits
    185      */
    186     typedef enum { CHLIST_EN_PS1     = 0x01, // proximity sense 1-3
    187                    CHLIST_EN_PS2     = 0x02,
    188                    CHLIST_EN_PS3     = 0x04,
    189 
    190                    CHLIST_EN_ALS_VIS = 0x10, // ambient light sense
    191                    CHLIST_EN_ALS_IR  = 0x20,
    192                    CHLIST_EN_AUX     = 0x40, // AUX sense
    193                    CHLIST_EN_UV      = 0x80  // UV sense
    194     } SI114X_CHLIST_BITS_T;
    195 
    196     /**
    197      * Error codes from the RESPONSE register
    198      */
    199     typedef enum { ERR_NONE          = 0x00, // no error if high nibble is 0
    200                                              // lower nibble is a counter
    201                    ERR_INVALID_SET   = 0x80, // invalid setting
    202                    ERR_PS1_ADC_OVER  = 0x88, // overflows
    203                    ERR_PS2_ADC_OVER  = 0x89,
    204                    ERR_PS3_ADC_OVER  = 0x8a,
    205                    ERR_ALS_VIS_ADC_OVER  = 0x8c,
    206                    ERR_ALS_IR_ADC_OVER   = 0x8d,
    207                    ERR_AUX_ADC_OVER  = 0x8e
    208     } SI114X_ERR_T;
    209 
    210 
    211     /**
    212      * Interrupt enable bits
    213      */
    214     typedef enum { IRQEN_ALS_IE      = 0x01,
    215                    IRQEN_PS1_IE      = 0x04,
    216                    IRQEN_PS2_IE      = 0x08,
    217                    IRQEN_PS3_IE      = 0x10
    218     } SI114X_IRQEN_BITS_T;
    219 
    220     /**
    221      * SI114X constructor
    222      *
    223      * @param bus I2C bus to use
    224      * @param address Address for this device
    225      */
    226     SI114X(int bus, uint8_t address = SI114X_DEFAULT_I2C_ADDR);
    227 
    228     /**
    229      * SI114X destructor
    230      */
    231     ~SI114X();
    232 
    233     /**
    234      * Writes a byte value into a register
    235      *
    236      * @param reg Register location to write into
    237      * @param byte Byte to write
    238      * @return True if successful
    239      */
    240     bool writeByte(uint8_t reg, uint8_t byte);
    241 
    242     /**
    243      * Reads a byte value from a register
    244      *
    245      * @param reg Register location to read from
    246      * @return Value in a specified register
    247      */
    248     uint8_t readByte(uint8_t reg);
    249 
    250     /**
    251      * Reads a word value from a register
    252      *
    253      * @param reg Register location to read from
    254      * @return Value in a specified register
    255      */
    256     uint16_t readWord(uint8_t reg);
    257 
    258     /**
    259      * Disables interrupts and auto-measuring, issues a device reset,
    260      * and then sets the hardware key.
    261      */
    262     void reset();
    263 
    264     /**
    265      * Sets UV calibration values. The constructor sets default
    266      * values for you, so you only need this function if you need
    267      * different values for your device and situation. If you set new
    268      * values here, be sure to do so before calling initialize().
    269      *
    270      * @param uvcoeff0 Coefficient for REG_UCOEF0
    271      * @param uvcoeff1 Coefficient for REG_UCOEF1
    272      * @param uvcoeff2 Coefficient for REG_UCOEF2
    273      * @param uvcoeff3 Coefficient for REG_UCOEF3
    274      *
    275      */
    276     void setUVCalibration(uint8_t uvcoeff0, uint8_t uvcoeff1, uint8_t uvcoeff2,
    277                           uint8_t uvcoeff3);
    278 
    279     /**
    280      * Writes a value to the parameter memory.
    281      *
    282      * @param param SI114X_PARAM_T register to write
    283      * @param value Value to write
    284      */
    285     void writeParam(SI114X_PARAM_T param, uint8_t value);
    286 
    287     /**
    288      * Reads a value from the parameter memory
    289      *
    290      * @param param SI114X_PARAM_T register to read
    291      * @return Value
    292      */
    293     uint8_t readParam(SI114X_PARAM_T param);
    294 
    295     /**
    296      * Resets and initializes the device and starts auto-sampling
    297      */
    298     void initialize();
    299 
    300     /**
    301      * Updates stored values. You should call this before calling
    302      * getUVIndex()
    303      */
    304     void update();
    305 
    306     /**
    307      * Reads the currently measured UV index value
    308      *
    309      * @return UV index value
    310      */
    311     float getUVIndex() { return m_uvIndex; };
    312 
    313   private:
    314     mraa_i2c_context m_i2c;
    315     uint8_t m_addr;
    316     // UV calibration values
    317     uint8_t m_uv_cal[4];
    318     // updated by update()
    319     float m_uvIndex;
    320   };
    321 }
    322 
    323 
    324