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 27 #include <unistd.h> 28 #include <math.h> 29 #include <iostream> 30 #include <stdexcept> 31 #include <string> 32 33 #include "si114x.h" 34 35 using namespace upm; 36 using namespace std; 37 38 39 SI114X::SI114X(int bus, uint8_t address) 40 { 41 m_addr = address; 42 m_uvIndex = 0; 43 44 // setup our i2c link 45 if ( !(m_i2c = mraa_i2c_init(bus)) ) 46 { 47 throw std::invalid_argument(std::string(__FUNCTION__) + 48 ": mraa_i2c_init() failed"); 49 return; 50 } 51 52 mraa_result_t rv; 53 54 if ( (rv = mraa_i2c_address(m_i2c, m_addr)) != MRAA_SUCCESS) 55 { 56 throw std::runtime_error(std::string(__FUNCTION__) + 57 ": mraa_i2c_address() failed"); 58 return; 59 } 60 61 // The data sheet recommends setting the UV calibration values to 62 // 0x7b, 0x6b, 0x01, and 0x00, however the adafruit code uses a 63 // different set of values, presumably calibrated to their specific 64 // implementation. We will use those defaults here, as this was 65 // developed on an adafruit device. 66 67 // Use setUVCalibration() to set a different set of values before 68 // calling init() if you need different values. 69 70 setUVCalibration(0x29, 0x89, 0x02, 0x00); 71 } 72 73 SI114X::~SI114X() 74 { 75 mraa_i2c_stop(m_i2c); 76 } 77 78 bool SI114X::writeByte(uint8_t reg, uint8_t byte) 79 { 80 mraa_result_t rv = mraa_i2c_write_byte_data(m_i2c, byte, reg); 81 82 if (rv != MRAA_SUCCESS) 83 { 84 throw std::runtime_error(std::string(__FUNCTION__) + 85 ": mraa_i2c_write_byte() failed"); 86 return false; 87 } 88 89 return true; 90 } 91 92 uint8_t SI114X::readByte(uint8_t reg) 93 { 94 return mraa_i2c_read_byte_data(m_i2c, reg); 95 } 96 97 uint16_t SI114X::readWord(uint8_t reg) 98 { 99 return mraa_i2c_read_word_data(m_i2c, reg); 100 } 101 102 void SI114X::setUVCalibration(uint8_t uvcoeff0, uint8_t uvcoeff1, 103 uint8_t uvcoeff2, uint8_t uvcoeff3) 104 { 105 m_uv_cal[0] = uvcoeff0; 106 m_uv_cal[1] = uvcoeff1; 107 m_uv_cal[2] = uvcoeff2; 108 m_uv_cal[3] = uvcoeff3; 109 }; 110 111 112 void SI114X::writeParam(SI114X_PARAM_T param, uint8_t value) 113 { 114 // write a parameter to the RAM parameter area 115 116 // We write the value to the PARAM_WR register, then execute a 117 // PARAM_WRITE command 118 119 writeByte(REG_PARAM_WR, value); 120 121 // now write it to parameter memory 122 writeByte(REG_COMMAND, CMD_PARAM_SET | param); 123 } 124 125 uint8_t SI114X::readParam(SI114X_PARAM_T param) 126 { 127 // get the parameter into register REG_PARAM_READ, then read and return it. 128 129 writeByte(REG_COMMAND, CMD_PARAM_QUERY | param); 130 return readByte(REG_PARAM_READ); 131 } 132 133 void SI114X::reset() 134 { 135 // reset the device 136 137 // zero out measuring rate 138 writeByte(REG_MEAS_RATE0, 0); 139 writeByte(REG_MEAS_RATE1, 0); 140 141 // disable IRQ MODES 142 // these are undocumented in the datasheet, but mentioned in Adafruit's code 143 writeByte(REG_IRQ_MODE1, 0); 144 writeByte(REG_IRQ_MODE2, 0); 145 146 // turn off interrupts 147 writeByte(REG_INT_CFG, 0); 148 writeByte(REG_IRQ_STATUS, 0xff); 149 150 // send a reset 151 writeByte(REG_COMMAND, CMD_RESET); 152 usleep(100); 153 154 // set the hardware key 155 writeByte(REG_HW_KEY, SI114X_HW_KEY); 156 usleep(100); 157 } 158 159 void SI114X::initialize() 160 { 161 // initialize the device 162 163 // first, reset it 164 reset(); 165 166 // UV coefficients 167 writeByte(REG_UCOEF0, m_uv_cal[0]); 168 writeByte(REG_UCOEF1, m_uv_cal[1]); 169 writeByte(REG_UCOEF2, m_uv_cal[2]); 170 writeByte(REG_UCOEF3, m_uv_cal[3]); 171 172 // enable UV sensor only for now 173 writeParam(PARAM_CHLIST, CHLIST_EN_UV); 174 175 // auto-measure speed - slowest - (rate * 31.25us) 176 writeByte(REG_MEAS_RATE0, 0xff); // 7.9ms 177 178 // set autorun 179 writeByte(REG_COMMAND, CMD_ALS_AUTO); 180 } 181 182 void SI114X::update() 183 { 184 // for now, just update the UV Index member variable 185 uint16_t uvi = readWord(REG_AUX_UVINDEX0); 186 187 m_uvIndex = float(uvi) / 100.0; 188 189 // Add any further data gets() here 190 191 return; 192 } 193