1 /* 2 * Author: Jon Trulson <jtrulson@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 */ getUVIndex()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