Driver for the Silicon Labs Si1133 Visible Light/UV sensor

Dependents:   TBSense2_Sensor_Demo mbed-BLE-coragem-teste Pulga_BLE_GPS pulga-mbed-lorawan-gps ... more

Sample library for use with the Silicon Labs Si1133 sensor for visible light intensity (lux) and UV index measurements.

Information

All examples in this repo are considered EXPERIMENTAL QUALITY, meaning this code has been created as one-off proof-of-concept and is suitable as a demonstration for experimental purposes only. This code will not be regularly maintained by Silicon Labs and there is no guarantee that these projects will work across all environments, SDK versions and hardware.

Datasheet

https://www.silabs.com/documents/public/data-sheets/Si1133.pdf

Usage

#include "mbed.h"
#include "Si1133.h"
//Create an Si1133 object
Si1133 sensor(PC4, PC5);
int main()
{
    //Try to open the Si1133
    if (sensor.open()) {
        printf("Device detected!\n");
        while (1) {
            //Print the current light level
            printf("Lux = %.3f\n", (float)sensor.get_light_level());
            //Print the current UV index
            printf("UV index = %.3f\n", (float)sensor.get_uv_index());
            //Sleep for 0.5 seconds
            wait(0.5);
        }
    } else {
        error("Device not detected!\n");
    }
}
Committer:
stevew817
Date:
Sun Nov 12 15:58:26 2017 +0100
Revision:
0:667132a19341
Child:
1:410f61a3900b
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
stevew817 0:667132a19341 1 /***************************************************************************//**
stevew817 0:667132a19341 2 * @file Si1133.cpp
stevew817 0:667132a19341 3 *******************************************************************************
stevew817 0:667132a19341 4 * @section License
stevew817 0:667132a19341 5 * <b>(C) Copyright 2017 Silicon Labs, http://www.silabs.com</b>
stevew817 0:667132a19341 6 *******************************************************************************
stevew817 0:667132a19341 7 *
stevew817 0:667132a19341 8 * SPDX-License-Identifier: Apache-2.0
stevew817 0:667132a19341 9 *
stevew817 0:667132a19341 10 * Licensed under the Apache License, Version 2.0 (the "License"); you may
stevew817 0:667132a19341 11 * not use this file except in compliance with the License.
stevew817 0:667132a19341 12 * You may obtain a copy of the License at
stevew817 0:667132a19341 13 *
stevew817 0:667132a19341 14 * http://www.apache.org/licenses/LICENSE-2.0
stevew817 0:667132a19341 15 *
stevew817 0:667132a19341 16 * Unless required by applicable law or agreed to in writing, software
stevew817 0:667132a19341 17 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
stevew817 0:667132a19341 18 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
stevew817 0:667132a19341 19 * See the License for the specific language governing permissions and
stevew817 0:667132a19341 20 * limitations under the License.
stevew817 0:667132a19341 21 *
stevew817 0:667132a19341 22 ******************************************************************************/
stevew817 0:667132a19341 23
stevew817 0:667132a19341 24 #include "Si1133.h"
stevew817 0:667132a19341 25
stevew817 0:667132a19341 26 #define SI1133_I2C_ADDRESS (0xAA) /** Hardcoded address for Si1133 sensor */
stevew817 0:667132a19341 27
stevew817 0:667132a19341 28 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
stevew817 0:667132a19341 29
stevew817 0:667132a19341 30 #define X_ORDER_MASK 0x0070
stevew817 0:667132a19341 31 #define Y_ORDER_MASK 0x0007
stevew817 0:667132a19341 32 #define SIGN_MASK 0x0080
stevew817 0:667132a19341 33 #define GET_X_ORDER(m) ( ((m) & X_ORDER_MASK) >> 4)
stevew817 0:667132a19341 34 #define GET_Y_ORDER(m) ( ((m) & Y_ORDER_MASK) )
stevew817 0:667132a19341 35 #define GET_SIGN(m) ( ((m) & SIGN_MASK) >> 7)
stevew817 0:667132a19341 36
stevew817 0:667132a19341 37 #define UV_INPUT_FRACTION 15
stevew817 0:667132a19341 38 #define UV_OUTPUT_FRACTION 12
stevew817 0:667132a19341 39 #define UV_NUMCOEFF 2
stevew817 0:667132a19341 40
stevew817 0:667132a19341 41 #define ADC_THRESHOLD 16000
stevew817 0:667132a19341 42 #define INPUT_FRACTION_HIGH 7
stevew817 0:667132a19341 43 #define INPUT_FRACTION_LOW 15
stevew817 0:667132a19341 44 #define LUX_OUTPUT_FRACTION 12
stevew817 0:667132a19341 45 #define NUMCOEFF_LOW 9
stevew817 0:667132a19341 46 #define NUMCOEFF_HIGH 4
stevew817 0:667132a19341 47
stevew817 0:667132a19341 48 /** @endcond */
stevew817 0:667132a19341 49
stevew817 0:667132a19341 50 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
stevew817 0:667132a19341 51 /***************************************************************************//**
stevew817 0:667132a19341 52 * @brief
stevew817 0:667132a19341 53 * Coefficients for lux calculation
stevew817 0:667132a19341 54 ******************************************************************************/
stevew817 0:667132a19341 55 const Si1133::LuxCoeff_t Si1133::lk = {
stevew817 0:667132a19341 56 { { 0, 209 }, /**< coeff_high[0] */
stevew817 0:667132a19341 57 { 1665, 93 }, /**< coeff_high[1] */
stevew817 0:667132a19341 58 { 2064, 65 }, /**< coeff_high[2] */
stevew817 0:667132a19341 59 { -2671, 234 } }, /**< coeff_high[3] */
stevew817 0:667132a19341 60 { { 0, 0 }, /**< coeff_low[0] */
stevew817 0:667132a19341 61 { 1921, 29053 }, /**< coeff_low[1] */
stevew817 0:667132a19341 62 { -1022, 36363 }, /**< coeff_low[2] */
stevew817 0:667132a19341 63 { 2320, 20789 }, /**< coeff_low[3] */
stevew817 0:667132a19341 64 { -367, 57909 }, /**< coeff_low[4] */
stevew817 0:667132a19341 65 { -1774, 38240 }, /**< coeff_low[5] */
stevew817 0:667132a19341 66 { -608, 46775 }, /**< coeff_low[6] */
stevew817 0:667132a19341 67 { -1503, 51831 }, /**< coeff_low[7] */
stevew817 0:667132a19341 68 { -1886, 58928 } } /**< coeff_low[8] */
stevew817 0:667132a19341 69 };
stevew817 0:667132a19341 70
stevew817 0:667132a19341 71 /***************************************************************************//**
stevew817 0:667132a19341 72 * @brief
stevew817 0:667132a19341 73 * Coefficients for UV index calculation
stevew817 0:667132a19341 74 ******************************************************************************/
stevew817 0:667132a19341 75 const Si1133::Coeff_t Si1133::uk[2] = {
stevew817 0:667132a19341 76 { 1281, 30902 }, /**< coeff[0] */
stevew817 0:667132a19341 77 { -638, 46301 } /**< coeff[1] */
stevew817 0:667132a19341 78 };
stevew817 0:667132a19341 79
stevew817 0:667132a19341 80 /**************************************************************************//**
stevew817 0:667132a19341 81 * @name Error Codes
stevew817 0:667132a19341 82 * @{
stevew817 0:667132a19341 83 ******************************************************************************/
stevew817 0:667132a19341 84 #define SI1133_OK 0x0000 /**< No errors */
stevew817 0:667132a19341 85 #define SI1133_ERROR_I2C_TRANSACTION_FAILED 0x0001 /**< I2C transaction failed */
stevew817 0:667132a19341 86 #define SI1133_ERROR_SLEEP_FAILED 0x0002 /**< Entering sleep mode failed */
stevew817 0:667132a19341 87 /**@}*/
stevew817 0:667132a19341 88
stevew817 0:667132a19341 89 /** @endcond */
stevew817 0:667132a19341 90
stevew817 0:667132a19341 91 Si1133::Si1133(PinName sda, PinName scl, int hz) : m_I2C(sda, scl)
stevew817 0:667132a19341 92 {
stevew817 0:667132a19341 93 //Set the I2C bus frequency
stevew817 0:667132a19341 94 m_I2C.frequency(hz);
stevew817 0:667132a19341 95 }
stevew817 0:667132a19341 96
stevew817 0:667132a19341 97 Si1133::~Si1133(void)
stevew817 0:667132a19341 98 {
stevew817 0:667132a19341 99 deinit();
stevew817 0:667132a19341 100 }
stevew817 0:667132a19341 101
stevew817 0:667132a19341 102 bool Si1133::open()
stevew817 0:667132a19341 103 {
stevew817 0:667132a19341 104 //Probe for the Si1133 using a Zero Length Transfer
stevew817 0:667132a19341 105 if (m_I2C.write(SI1133_I2C_ADDRESS, NULL, 0)) {
stevew817 0:667132a19341 106 //Return success
stevew817 0:667132a19341 107 return false;
stevew817 0:667132a19341 108 }
stevew817 0:667132a19341 109
stevew817 0:667132a19341 110 // initialize sensor
stevew817 0:667132a19341 111 if (SI1133_OK == init()) {
stevew817 0:667132a19341 112 return true;
stevew817 0:667132a19341 113 }
stevew817 0:667132a19341 114 return false;
stevew817 0:667132a19341 115 }
stevew817 0:667132a19341 116
stevew817 0:667132a19341 117 /** Measure the current light level (in lux) on the Si1133
stevew817 0:667132a19341 118 *
stevew817 0:667132a19341 119 * @returns The current temperature measurement in Lux.
stevew817 0:667132a19341 120 */
stevew817 0:667132a19341 121 float Si1133::get_light_level()
stevew817 0:667132a19341 122 {
stevew817 0:667132a19341 123 float lux, uvi;
stevew817 0:667132a19341 124 measureLuxUvi(&lux, &uvi);
stevew817 0:667132a19341 125 return lux;
stevew817 0:667132a19341 126 }
stevew817 0:667132a19341 127
stevew817 0:667132a19341 128 /** Measure the current UV Index on the Si1133
stevew817 0:667132a19341 129 *
stevew817 0:667132a19341 130 * @returns The current UV index.
stevew817 0:667132a19341 131 */
stevew817 0:667132a19341 132 float Si1133::get_uv_index()
stevew817 0:667132a19341 133 {
stevew817 0:667132a19341 134 float lux, uvi;
stevew817 0:667132a19341 135 measureLuxUvi(&lux, &uvi);
stevew817 0:667132a19341 136 return uvi;
stevew817 0:667132a19341 137 }
stevew817 0:667132a19341 138
stevew817 0:667132a19341 139 /***************************************************************************//**
stevew817 0:667132a19341 140 * @brief
stevew817 0:667132a19341 141 * Reads register from the Si1133 sensor
stevew817 0:667132a19341 142 *
stevew817 0:667132a19341 143 * @param[in] reg
stevew817 0:667132a19341 144 * The register address to read from in the sensor.
stevew817 0:667132a19341 145 *
stevew817 0:667132a19341 146 * @param[out] data
stevew817 0:667132a19341 147 * The data read from the sensor
stevew817 0:667132a19341 148 *
stevew817 0:667132a19341 149 * @return
stevew817 0:667132a19341 150 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 151 ******************************************************************************/
stevew817 0:667132a19341 152 uint32_t Si1133::read_register(enum Si1133::Register reg, uint8_t *data)
stevew817 0:667132a19341 153 {
stevew817 0:667132a19341 154 char buf[1];
stevew817 0:667132a19341 155 buf[0] = (char) reg;
stevew817 0:667132a19341 156
stevew817 0:667132a19341 157 if (m_I2C.write(SI1133_I2C_ADDRESS, buf, 1, true)) {
stevew817 0:667132a19341 158 //Return failure
stevew817 0:667132a19341 159 return SI1133_ERROR_I2C_TRANSACTION_FAILED;
stevew817 0:667132a19341 160 }
stevew817 0:667132a19341 161
stevew817 0:667132a19341 162 if (m_I2C.read(SI1133_I2C_ADDRESS, buf, 1)) {
stevew817 0:667132a19341 163 //Return failure
stevew817 0:667132a19341 164 return SI1133_ERROR_I2C_TRANSACTION_FAILED;
stevew817 0:667132a19341 165 }
stevew817 0:667132a19341 166
stevew817 0:667132a19341 167 *data = buf[0];
stevew817 0:667132a19341 168
stevew817 0:667132a19341 169 return SI1133_OK;
stevew817 0:667132a19341 170 }
stevew817 0:667132a19341 171
stevew817 0:667132a19341 172 /***************************************************************************//**
stevew817 0:667132a19341 173 * @brief
stevew817 0:667132a19341 174 * Writes register in the Si1133 sensor
stevew817 0:667132a19341 175 *
stevew817 0:667132a19341 176 * @param[in] reg
stevew817 0:667132a19341 177 * The register address to write to in the sensor
stevew817 0:667132a19341 178 *
stevew817 0:667132a19341 179 * @param[in] data
stevew817 0:667132a19341 180 * The data to write to the sensor
stevew817 0:667132a19341 181 *
stevew817 0:667132a19341 182 * @return
stevew817 0:667132a19341 183 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 184 ******************************************************************************/
stevew817 0:667132a19341 185 uint32_t Si1133::write_register(enum Si1133::Register reg, uint8_t data)
stevew817 0:667132a19341 186 {
stevew817 0:667132a19341 187 char buf[2];
stevew817 0:667132a19341 188 buf[0] = (char) reg;
stevew817 0:667132a19341 189 buf[1] = (char) data;
stevew817 0:667132a19341 190
stevew817 0:667132a19341 191 if (m_I2C.write(SI1133_I2C_ADDRESS, buf, 2)) {
stevew817 0:667132a19341 192 //Return failure
stevew817 0:667132a19341 193 return SI1133_ERROR_I2C_TRANSACTION_FAILED;
stevew817 0:667132a19341 194 }
stevew817 0:667132a19341 195
stevew817 0:667132a19341 196 return SI1133_OK;
stevew817 0:667132a19341 197 }
stevew817 0:667132a19341 198
stevew817 0:667132a19341 199 /***************************************************************************//**
stevew817 0:667132a19341 200 * @brief
stevew817 0:667132a19341 201 * Writes a block of data to the Si1133 sensor.
stevew817 0:667132a19341 202 *
stevew817 0:667132a19341 203 * @param[in] reg
stevew817 0:667132a19341 204 * The first register to begin writing to
stevew817 0:667132a19341 205 *
stevew817 0:667132a19341 206 * @param[in] length
stevew817 0:667132a19341 207 * The number of bytes to write to the sensor
stevew817 0:667132a19341 208 *
stevew817 0:667132a19341 209 * @param[in] data
stevew817 0:667132a19341 210 * The data to write to the sensor
stevew817 0:667132a19341 211 *
stevew817 0:667132a19341 212 * @return
stevew817 0:667132a19341 213 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 214 ******************************************************************************/
stevew817 0:667132a19341 215 uint32_t Si1133::write_register_block(enum Si1133::Register reg, uint8_t length, uint8_t *data)
stevew817 0:667132a19341 216 {
stevew817 0:667132a19341 217 char buf[length+1];
stevew817 0:667132a19341 218 buf[0] = (char)reg;
stevew817 0:667132a19341 219 memcpy(&buf[1], data, length);
stevew817 0:667132a19341 220
stevew817 0:667132a19341 221 if (m_I2C.write(SI1133_I2C_ADDRESS, buf, length + 1)) {
stevew817 0:667132a19341 222 //Return failure
stevew817 0:667132a19341 223 return SI1133_ERROR_I2C_TRANSACTION_FAILED;
stevew817 0:667132a19341 224 }
stevew817 0:667132a19341 225
stevew817 0:667132a19341 226 return SI1133_OK;
stevew817 0:667132a19341 227 }
stevew817 0:667132a19341 228
stevew817 0:667132a19341 229 /***************************************************************************//**
stevew817 0:667132a19341 230 * @brief
stevew817 0:667132a19341 231 * Reads a block of data from the Si1133 sensor.
stevew817 0:667132a19341 232 *
stevew817 0:667132a19341 233 * @param[in] reg
stevew817 0:667132a19341 234 * The first register to begin reading from
stevew817 0:667132a19341 235 *
stevew817 0:667132a19341 236 * @param[in] length
stevew817 0:667132a19341 237 * The number of bytes to write to the sensor
stevew817 0:667132a19341 238 *
stevew817 0:667132a19341 239 * @param[out] data
stevew817 0:667132a19341 240 * The data read from the sensor
stevew817 0:667132a19341 241 *
stevew817 0:667132a19341 242 * @return
stevew817 0:667132a19341 243 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 244 ******************************************************************************/
stevew817 0:667132a19341 245 uint32_t Si1133::read_register_block(enum Si1133::Register reg, uint8_t length, uint8_t *data)
stevew817 0:667132a19341 246 {
stevew817 0:667132a19341 247 char reg_c = (char)reg;
stevew817 0:667132a19341 248 if (m_I2C.write(SI1133_I2C_ADDRESS, &reg_c, 1, true)) {
stevew817 0:667132a19341 249 //Return failure
stevew817 0:667132a19341 250 return SI1133_ERROR_I2C_TRANSACTION_FAILED;
stevew817 0:667132a19341 251 }
stevew817 0:667132a19341 252
stevew817 0:667132a19341 253 if (m_I2C.read(SI1133_I2C_ADDRESS, (char*) data, length)) {
stevew817 0:667132a19341 254 //Return failure
stevew817 0:667132a19341 255 return SI1133_ERROR_I2C_TRANSACTION_FAILED;
stevew817 0:667132a19341 256 }
stevew817 0:667132a19341 257
stevew817 0:667132a19341 258 return SI1133_OK;
stevew817 0:667132a19341 259 }
stevew817 0:667132a19341 260
stevew817 0:667132a19341 261 /***************************************************************************//**
stevew817 0:667132a19341 262 * @brief
stevew817 0:667132a19341 263 * Reads the interrupt status register of the device
stevew817 0:667132a19341 264 *
stevew817 0:667132a19341 265 * @param[out] irqStatus
stevew817 0:667132a19341 266 * The contentof the IRQ status register
stevew817 0:667132a19341 267 *
stevew817 0:667132a19341 268 * @return
stevew817 0:667132a19341 269 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 270 ******************************************************************************/
stevew817 0:667132a19341 271 uint32_t Si1133::get_irq_status(uint8_t *irq_status)
stevew817 0:667132a19341 272 {
stevew817 0:667132a19341 273 return read_register(REG_IRQ_STATUS, irq_status);
stevew817 0:667132a19341 274 }
stevew817 0:667132a19341 275
stevew817 0:667132a19341 276 /***************************************************************************//**
stevew817 0:667132a19341 277 * @brief
stevew817 0:667132a19341 278 * Waits until the Si1133 is sleeping before proceeding
stevew817 0:667132a19341 279 *
stevew817 0:667132a19341 280 * @return
stevew817 0:667132a19341 281 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 282 ******************************************************************************/
stevew817 0:667132a19341 283 uint32_t Si1133::wait_until_sleep(void)
stevew817 0:667132a19341 284 {
stevew817 0:667132a19341 285 uint32_t ret;
stevew817 0:667132a19341 286 uint8_t response;
stevew817 0:667132a19341 287 size_t count = 0;
stevew817 0:667132a19341 288
stevew817 0:667132a19341 289 /* This loops until the Si1133 is known to be in its sleep state */
stevew817 0:667132a19341 290 /* or if an i2c error occurs */
stevew817 0:667132a19341 291 while ( count < 5 ) {
stevew817 0:667132a19341 292 ret = read_register(REG_RESPONSE0, &response);
stevew817 0:667132a19341 293 if ( (response & (uint8_t)RSP0_CHIPSTAT_MASK) == (uint8_t)RSP0_SLEEP ) {
stevew817 0:667132a19341 294 return SI1133_OK;
stevew817 0:667132a19341 295 }
stevew817 0:667132a19341 296
stevew817 0:667132a19341 297 if ( ret != SI1133_OK ) {
stevew817 0:667132a19341 298 return SI1133_ERROR_SLEEP_FAILED;
stevew817 0:667132a19341 299 }
stevew817 0:667132a19341 300
stevew817 0:667132a19341 301 count++;
stevew817 0:667132a19341 302 }
stevew817 0:667132a19341 303
stevew817 0:667132a19341 304 return SI1133_ERROR_SLEEP_FAILED;
stevew817 0:667132a19341 305 }
stevew817 0:667132a19341 306
stevew817 0:667132a19341 307 /***************************************************************************//**
stevew817 0:667132a19341 308 * @brief
stevew817 0:667132a19341 309 * Resets the Si1133
stevew817 0:667132a19341 310 *
stevew817 0:667132a19341 311 * @return
stevew817 0:667132a19341 312 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 313 ******************************************************************************/
stevew817 0:667132a19341 314 uint32_t Si1133::reset(void)
stevew817 0:667132a19341 315 {
stevew817 0:667132a19341 316 uint32_t retval;
stevew817 0:667132a19341 317
stevew817 0:667132a19341 318 /* Do not access the Si1133 earlier than 25 ms from power-up */
stevew817 0:667132a19341 319 wait_ms(30);
stevew817 0:667132a19341 320
stevew817 0:667132a19341 321 /* Perform the Reset Command */
stevew817 0:667132a19341 322 retval = write_register(REG_COMMAND, (uint8_t)CMD_RESET);
stevew817 0:667132a19341 323
stevew817 0:667132a19341 324 /* Delay for 10 ms. This delay is needed to allow the Si1133 */
stevew817 0:667132a19341 325 /* to perform internal reset sequence. */
stevew817 0:667132a19341 326 wait_ms(10);
stevew817 0:667132a19341 327
stevew817 0:667132a19341 328 return retval;
stevew817 0:667132a19341 329 }
stevew817 0:667132a19341 330
stevew817 0:667132a19341 331 /***************************************************************************//**
stevew817 0:667132a19341 332 * @brief
stevew817 0:667132a19341 333 * Helper function to send a command to the Si1133
stevew817 0:667132a19341 334 *
stevew817 0:667132a19341 335 * @param[in] command
stevew817 0:667132a19341 336 * The command to send to the sensor
stevew817 0:667132a19341 337 *
stevew817 0:667132a19341 338 * @return
stevew817 0:667132a19341 339 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 340 ******************************************************************************/
stevew817 0:667132a19341 341 uint32_t Si1133::send_cmd(enum Si1133::Command command)
stevew817 0:667132a19341 342 {
stevew817 0:667132a19341 343 uint8_t response;
stevew817 0:667132a19341 344 uint8_t response_stored;
stevew817 0:667132a19341 345 uint8_t count = 0;
stevew817 0:667132a19341 346 uint32_t ret;
stevew817 0:667132a19341 347
stevew817 0:667132a19341 348 /* Get the response register contents */
stevew817 0:667132a19341 349 ret = read_register(REG_RESPONSE0, &response_stored);
stevew817 0:667132a19341 350 if ( ret != SI1133_OK ) {
stevew817 0:667132a19341 351 return ret;
stevew817 0:667132a19341 352 }
stevew817 0:667132a19341 353
stevew817 0:667132a19341 354 response_stored = response_stored & (uint8_t)RSP0_COUNTER_MASK;
stevew817 0:667132a19341 355
stevew817 0:667132a19341 356 /* Double-check the response register is consistent */
stevew817 0:667132a19341 357 while ( count < 5 ) {
stevew817 0:667132a19341 358 ret = wait_until_sleep();
stevew817 0:667132a19341 359 if ( ret != SI1133_OK ) {
stevew817 0:667132a19341 360 return ret;
stevew817 0:667132a19341 361 }
stevew817 0:667132a19341 362 /* Skip if the command is RESET COMMAND COUNTER */
stevew817 0:667132a19341 363 if ( command == (uint8_t)CMD_RESET_CMD_CTR ) {
stevew817 0:667132a19341 364 break;
stevew817 0:667132a19341 365 }
stevew817 0:667132a19341 366
stevew817 0:667132a19341 367 ret = read_register(REG_RESPONSE0, &response);
stevew817 0:667132a19341 368
stevew817 0:667132a19341 369 if ( (response & (uint8_t)RSP0_COUNTER_MASK) == response_stored ) {
stevew817 0:667132a19341 370 break;
stevew817 0:667132a19341 371 } else {
stevew817 0:667132a19341 372 if ( ret != SI1133_OK ) {
stevew817 0:667132a19341 373 return ret;
stevew817 0:667132a19341 374 } else {
stevew817 0:667132a19341 375 response_stored = response & (uint8_t)RSP0_COUNTER_MASK;
stevew817 0:667132a19341 376 }
stevew817 0:667132a19341 377 }
stevew817 0:667132a19341 378
stevew817 0:667132a19341 379 count++;
stevew817 0:667132a19341 380 }
stevew817 0:667132a19341 381
stevew817 0:667132a19341 382 /* Send the command */
stevew817 0:667132a19341 383 ret = write_register(REG_COMMAND, command);
stevew817 0:667132a19341 384 if ( ret != SI1133_OK ) {
stevew817 0:667132a19341 385 return ret;
stevew817 0:667132a19341 386 }
stevew817 0:667132a19341 387
stevew817 0:667132a19341 388 count = 0;
stevew817 0:667132a19341 389 /* Expect a change in the response register */
stevew817 0:667132a19341 390 while ( count < 5 ) {
stevew817 0:667132a19341 391 /* Skip if the command is RESET COMMAND COUNTER */
stevew817 0:667132a19341 392 if ( command == (uint8_t)CMD_RESET_CMD_CTR ) {
stevew817 0:667132a19341 393 break;
stevew817 0:667132a19341 394 }
stevew817 0:667132a19341 395
stevew817 0:667132a19341 396 ret = read_register(REG_RESPONSE0, &response);
stevew817 0:667132a19341 397 if ( (response & (uint8_t)RSP0_COUNTER_MASK) != response_stored ) {
stevew817 0:667132a19341 398 break;
stevew817 0:667132a19341 399 } else {
stevew817 0:667132a19341 400 if ( ret != SI1133_OK ) {
stevew817 0:667132a19341 401 return ret;
stevew817 0:667132a19341 402 }
stevew817 0:667132a19341 403 }
stevew817 0:667132a19341 404
stevew817 0:667132a19341 405 count++;
stevew817 0:667132a19341 406 }
stevew817 0:667132a19341 407
stevew817 0:667132a19341 408 return SI1133_OK;
stevew817 0:667132a19341 409 }
stevew817 0:667132a19341 410
stevew817 0:667132a19341 411 /***************************************************************************//**
stevew817 0:667132a19341 412 * @brief
stevew817 0:667132a19341 413 * Sends a RESET COMMAND COUNTER command to the Si1133
stevew817 0:667132a19341 414 *
stevew817 0:667132a19341 415 * @return
stevew817 0:667132a19341 416 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 417 ******************************************************************************/
stevew817 0:667132a19341 418 uint32_t Si1133::reset_cmd_counter(void)
stevew817 0:667132a19341 419 {
stevew817 0:667132a19341 420 return send_cmd(CMD_RESET_CMD_CTR);
stevew817 0:667132a19341 421 }
stevew817 0:667132a19341 422
stevew817 0:667132a19341 423 /***************************************************************************//**
stevew817 0:667132a19341 424 * @brief
stevew817 0:667132a19341 425 * Sends a FORCE command to the Si1133
stevew817 0:667132a19341 426 *
stevew817 0:667132a19341 427 * @return
stevew817 0:667132a19341 428 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 429 ******************************************************************************/
stevew817 0:667132a19341 430 uint32_t Si1133::force_measurement(void)
stevew817 0:667132a19341 431 {
stevew817 0:667132a19341 432 return send_cmd(CMD_FORCE_CH);
stevew817 0:667132a19341 433 }
stevew817 0:667132a19341 434
stevew817 0:667132a19341 435 /***************************************************************************//**
stevew817 0:667132a19341 436 * @brief
stevew817 0:667132a19341 437 * Sends a START command to the Si1133
stevew817 0:667132a19341 438 *
stevew817 0:667132a19341 439 * @return
stevew817 0:667132a19341 440 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 441 ******************************************************************************/
stevew817 0:667132a19341 442 uint32_t Si1133::start_measurement(void)
stevew817 0:667132a19341 443 {
stevew817 0:667132a19341 444 return send_cmd(CMD_START);
stevew817 0:667132a19341 445 }
stevew817 0:667132a19341 446
stevew817 0:667132a19341 447 /***************************************************************************//**
stevew817 0:667132a19341 448 * @brief
stevew817 0:667132a19341 449 * Sends a PAUSE command to the Si1133
stevew817 0:667132a19341 450 *
stevew817 0:667132a19341 451 * @return
stevew817 0:667132a19341 452 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 453 ******************************************************************************/
stevew817 0:667132a19341 454 uint32_t Si1133::pause_measurement(void)
stevew817 0:667132a19341 455 {
stevew817 0:667132a19341 456 return send_cmd(CMD_PAUSE_CH);
stevew817 0:667132a19341 457 }
stevew817 0:667132a19341 458
stevew817 0:667132a19341 459 /***************************************************************************//**
stevew817 0:667132a19341 460 * @brief
stevew817 0:667132a19341 461 * Writes a byte to an Si1133 Parameter
stevew817 0:667132a19341 462 *
stevew817 0:667132a19341 463 * @param[in] address
stevew817 0:667132a19341 464 * The parameter address
stevew817 0:667132a19341 465 *
stevew817 0:667132a19341 466 * @param[in] value
stevew817 0:667132a19341 467 * The byte value to be written to the Si1133 parameter
stevew817 0:667132a19341 468 *
stevew817 0:667132a19341 469 * @return
stevew817 0:667132a19341 470 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 471 *
stevew817 0:667132a19341 472 * @note
stevew817 0:667132a19341 473 * This function ensures that the Si1133 is idle and ready to
stevew817 0:667132a19341 474 * receive a command before writing the parameter. Furthermore,
stevew817 0:667132a19341 475 * command completion is checked. If setting parameter is not done
stevew817 0:667132a19341 476 * properly, no measurements will occur. This is the most common
stevew817 0:667132a19341 477 * error. It is highly recommended that host code make use of this
stevew817 0:667132a19341 478 * function.
stevew817 0:667132a19341 479 ******************************************************************************/
stevew817 0:667132a19341 480 uint32_t Si1133::set_parameter (enum Si1133::Parameter address, uint8_t value)
stevew817 0:667132a19341 481 {
stevew817 0:667132a19341 482 uint32_t retval;
stevew817 0:667132a19341 483 uint8_t buffer[2];
stevew817 0:667132a19341 484 uint8_t response_stored;
stevew817 0:667132a19341 485 uint8_t response;
stevew817 0:667132a19341 486 size_t count;
stevew817 0:667132a19341 487
stevew817 0:667132a19341 488 retval = wait_until_sleep();
stevew817 0:667132a19341 489 if ( retval != SI1133_OK ) {
stevew817 0:667132a19341 490 return retval;
stevew817 0:667132a19341 491 }
stevew817 0:667132a19341 492
stevew817 0:667132a19341 493 read_register(REG_RESPONSE0, &response_stored);
stevew817 0:667132a19341 494 response_stored &= (uint8_t)RSP0_COUNTER_MASK;
stevew817 0:667132a19341 495
stevew817 0:667132a19341 496 buffer[0] = value;
stevew817 0:667132a19341 497 buffer[1] = 0x80 + ((uint8_t)address & 0x3F);
stevew817 0:667132a19341 498
stevew817 0:667132a19341 499 retval = write_register_block(REG_HOSTIN0, 2, (uint8_t*) buffer);
stevew817 0:667132a19341 500 if ( retval != SI1133_OK ) {
stevew817 0:667132a19341 501 return retval;
stevew817 0:667132a19341 502 }
stevew817 0:667132a19341 503
stevew817 0:667132a19341 504 /* Wait for command to finish */
stevew817 0:667132a19341 505 count = 0;
stevew817 0:667132a19341 506 /* Expect a change in the response register */
stevew817 0:667132a19341 507 while ( count < 5 ) {
stevew817 0:667132a19341 508 retval = read_register(REG_RESPONSE0, &response);
stevew817 0:667132a19341 509 if ( (response & (uint8_t)RSP0_COUNTER_MASK) != response_stored ) {
stevew817 0:667132a19341 510 break;
stevew817 0:667132a19341 511 } else {
stevew817 0:667132a19341 512 if ( retval != SI1133_OK ) {
stevew817 0:667132a19341 513 return retval;
stevew817 0:667132a19341 514 }
stevew817 0:667132a19341 515 }
stevew817 0:667132a19341 516
stevew817 0:667132a19341 517 count++;
stevew817 0:667132a19341 518 }
stevew817 0:667132a19341 519
stevew817 0:667132a19341 520 if (count >= 5) {
stevew817 0:667132a19341 521 return SI1133_ERROR_I2C_TRANSACTION_FAILED;
stevew817 0:667132a19341 522 }
stevew817 0:667132a19341 523
stevew817 0:667132a19341 524 return SI1133_OK;
stevew817 0:667132a19341 525 }
stevew817 0:667132a19341 526
stevew817 0:667132a19341 527 /***************************************************************************//**
stevew817 0:667132a19341 528 * @brief
stevew817 0:667132a19341 529 * Reads a parameter from the Si1133
stevew817 0:667132a19341 530 *
stevew817 0:667132a19341 531 * @param[in] address
stevew817 0:667132a19341 532 * The address of the parameter.
stevew817 0:667132a19341 533 *
stevew817 0:667132a19341 534 * @return
stevew817 0:667132a19341 535 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 536 ******************************************************************************/
stevew817 0:667132a19341 537 uint32_t Si1133::read_parameter (enum Si1133::Parameter address)
stevew817 0:667132a19341 538 {
stevew817 0:667132a19341 539 uint8_t retval;
stevew817 0:667132a19341 540 uint8_t cmd;
stevew817 0:667132a19341 541
stevew817 0:667132a19341 542 cmd = 0x40 + ((uint8_t)address & 0x3F);
stevew817 0:667132a19341 543
stevew817 0:667132a19341 544 retval = send_cmd((enum Si1133::Command)cmd);
stevew817 0:667132a19341 545 if ( retval != SI1133_OK ) {
stevew817 0:667132a19341 546 return retval;
stevew817 0:667132a19341 547 }
stevew817 0:667132a19341 548
stevew817 0:667132a19341 549 read_register(REG_RESPONSE1, &retval);
stevew817 0:667132a19341 550
stevew817 0:667132a19341 551 return retval;
stevew817 0:667132a19341 552 }
stevew817 0:667132a19341 553
stevew817 0:667132a19341 554 /**************************************************************************//**
stevew817 0:667132a19341 555 * @brief
stevew817 0:667132a19341 556 * Initializes the Si1133 chip
stevew817 0:667132a19341 557 *
stevew817 0:667132a19341 558 * @return
stevew817 0:667132a19341 559 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 560 *****************************************************************************/
stevew817 0:667132a19341 561 uint32_t Si1133::init (void)
stevew817 0:667132a19341 562 {
stevew817 0:667132a19341 563 uint32_t retval;
stevew817 0:667132a19341 564
stevew817 0:667132a19341 565 /* Allow some time for the part to power up */
stevew817 0:667132a19341 566 wait_ms(5);
stevew817 0:667132a19341 567
stevew817 0:667132a19341 568 retval = reset();
stevew817 0:667132a19341 569
stevew817 0:667132a19341 570 wait_ms(10);
stevew817 0:667132a19341 571
stevew817 0:667132a19341 572 retval += set_parameter(PARAM_CH_LIST, 0x0f);
stevew817 0:667132a19341 573 retval += set_parameter(PARAM_ADCCONFIG0, 0x78);
stevew817 0:667132a19341 574 retval += set_parameter(PARAM_ADCSENS0, 0x71);
stevew817 0:667132a19341 575 retval += set_parameter(PARAM_ADCPOST0, 0x40);
stevew817 0:667132a19341 576 retval += set_parameter(PARAM_ADCCONFIG1, 0x4d);
stevew817 0:667132a19341 577 retval += set_parameter(PARAM_ADCSENS1, 0xe1);
stevew817 0:667132a19341 578 retval += set_parameter(PARAM_ADCPOST1, 0x40);
stevew817 0:667132a19341 579 retval += set_parameter(PARAM_ADCCONFIG2, 0x41);
stevew817 0:667132a19341 580 retval += set_parameter(PARAM_ADCSENS2, 0xe1);
stevew817 0:667132a19341 581 retval += set_parameter(PARAM_ADCPOST2, 0x50);
stevew817 0:667132a19341 582 retval += set_parameter(PARAM_ADCCONFIG3, 0x4d);
stevew817 0:667132a19341 583 retval += set_parameter(PARAM_ADCSENS3, 0x87);
stevew817 0:667132a19341 584 retval += set_parameter(PARAM_ADCPOST3, 0x40);
stevew817 0:667132a19341 585
stevew817 0:667132a19341 586 retval += write_register(REG_IRQ_ENABLE, 0x0f);
stevew817 0:667132a19341 587
stevew817 0:667132a19341 588 return retval;
stevew817 0:667132a19341 589 }
stevew817 0:667132a19341 590
stevew817 0:667132a19341 591 /***************************************************************************//**
stevew817 0:667132a19341 592 * @brief
stevew817 0:667132a19341 593 * Stops the measurements on all channel and waits until the chip
stevew817 0:667132a19341 594 * goes to sleep state.
stevew817 0:667132a19341 595 *
stevew817 0:667132a19341 596 * @return
stevew817 0:667132a19341 597 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 598 ******************************************************************************/
stevew817 0:667132a19341 599 uint32_t Si1133::deinit (void)
stevew817 0:667132a19341 600 {
stevew817 0:667132a19341 601 uint32_t retval;
stevew817 0:667132a19341 602
stevew817 0:667132a19341 603 retval = set_parameter(PARAM_CH_LIST, 0x3f);
stevew817 0:667132a19341 604 retval += pause_measurement();
stevew817 0:667132a19341 605 retval += wait_until_sleep();
stevew817 0:667132a19341 606
stevew817 0:667132a19341 607 return retval;
stevew817 0:667132a19341 608 }
stevew817 0:667132a19341 609
stevew817 0:667132a19341 610 /***************************************************************************//**
stevew817 0:667132a19341 611 * @brief
stevew817 0:667132a19341 612 * Read samples from the Si1133 chip
stevew817 0:667132a19341 613 *
stevew817 0:667132a19341 614 * @param[out] samples
stevew817 0:667132a19341 615 * Retrieves interrupt status and measurement data for channel 0..3 and
stevew817 0:667132a19341 616 * converts the data to int32_t format
stevew817 0:667132a19341 617 *
stevew817 0:667132a19341 618 * @return
stevew817 0:667132a19341 619 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 620 ******************************************************************************/
stevew817 0:667132a19341 621 uint32_t Si1133::measurementGet (Si1133::Samples_t *samples)
stevew817 0:667132a19341 622 {
stevew817 0:667132a19341 623 uint8_t buffer[13];
stevew817 0:667132a19341 624 uint32_t retval;
stevew817 0:667132a19341 625
stevew817 0:667132a19341 626 retval = read_register_block(REG_IRQ_STATUS, 13, buffer);
stevew817 0:667132a19341 627
stevew817 0:667132a19341 628 samples->irq_status = buffer[0];
stevew817 0:667132a19341 629
stevew817 0:667132a19341 630 samples->ch0 = buffer[1] << 16;
stevew817 0:667132a19341 631 samples->ch0 |= buffer[2] << 8;
stevew817 0:667132a19341 632 samples->ch0 |= buffer[3];
stevew817 0:667132a19341 633 if ( samples->ch0 & 0x800000 ) {
stevew817 0:667132a19341 634 samples->ch0 |= 0xFF000000;
stevew817 0:667132a19341 635 }
stevew817 0:667132a19341 636
stevew817 0:667132a19341 637 samples->ch1 = buffer[4] << 16;
stevew817 0:667132a19341 638 samples->ch1 |= buffer[5] << 8;
stevew817 0:667132a19341 639 samples->ch1 |= buffer[6];
stevew817 0:667132a19341 640 if ( samples->ch1 & 0x800000 ) {
stevew817 0:667132a19341 641 samples->ch1 |= 0xFF000000;
stevew817 0:667132a19341 642 }
stevew817 0:667132a19341 643
stevew817 0:667132a19341 644 samples->ch2 = buffer[7] << 16;
stevew817 0:667132a19341 645 samples->ch2 |= buffer[8] << 8;
stevew817 0:667132a19341 646 samples->ch2 |= buffer[9];
stevew817 0:667132a19341 647 if ( samples->ch2 & 0x800000 ) {
stevew817 0:667132a19341 648 samples->ch2 |= 0xFF000000;
stevew817 0:667132a19341 649 }
stevew817 0:667132a19341 650
stevew817 0:667132a19341 651 samples->ch3 = buffer[10] << 16;
stevew817 0:667132a19341 652 samples->ch3 |= buffer[11] << 8;
stevew817 0:667132a19341 653 samples->ch3 |= buffer[12];
stevew817 0:667132a19341 654 if ( samples->ch3 & 0x800000 ) {
stevew817 0:667132a19341 655 samples->ch3 |= 0xFF000000;
stevew817 0:667132a19341 656 }
stevew817 0:667132a19341 657
stevew817 0:667132a19341 658 return retval;
stevew817 0:667132a19341 659 }
stevew817 0:667132a19341 660
stevew817 0:667132a19341 661 int32_t Si1133::calculate_polynomial_helper (int32_t input, int8_t fraction, uint16_t mag, int8_t shift)
stevew817 0:667132a19341 662 {
stevew817 0:667132a19341 663 int32_t value;
stevew817 0:667132a19341 664
stevew817 0:667132a19341 665 if ( shift < 0 ) {
stevew817 0:667132a19341 666 value = ( (input << fraction) / mag) >> -shift;
stevew817 0:667132a19341 667 } else {
stevew817 0:667132a19341 668 value = ( (input << fraction) / mag) << shift;
stevew817 0:667132a19341 669 }
stevew817 0:667132a19341 670
stevew817 0:667132a19341 671 return value;
stevew817 0:667132a19341 672 }
stevew817 0:667132a19341 673
stevew817 0:667132a19341 674 int32_t Si1133::calculate_polynomial (int32_t x, int32_t y, uint8_t input_fraction, uint8_t output_fraction, uint8_t num_coeff, const Si1133::Coeff_t *kp)
stevew817 0:667132a19341 675 {
stevew817 0:667132a19341 676 uint8_t info, x_order, y_order, counter;
stevew817 0:667132a19341 677 int8_t sign, shift;
stevew817 0:667132a19341 678 uint16_t mag;
stevew817 0:667132a19341 679 int32_t output = 0, x1, x2, y1, y2;
stevew817 0:667132a19341 680
stevew817 0:667132a19341 681 for ( counter = 0; counter < num_coeff; counter++ ) {
stevew817 0:667132a19341 682 info = kp->info;
stevew817 0:667132a19341 683 x_order = GET_X_ORDER(info);
stevew817 0:667132a19341 684 y_order = GET_Y_ORDER(info);
stevew817 0:667132a19341 685
stevew817 0:667132a19341 686 shift = ( (uint16_t) kp->info & 0xff00) >> 8;
stevew817 0:667132a19341 687 shift ^= 0x00ff;
stevew817 0:667132a19341 688 shift += 1;
stevew817 0:667132a19341 689 shift = -shift;
stevew817 0:667132a19341 690
stevew817 0:667132a19341 691 mag = kp->mag;
stevew817 0:667132a19341 692
stevew817 0:667132a19341 693 if ( GET_SIGN(info) ) {
stevew817 0:667132a19341 694 sign = -1;
stevew817 0:667132a19341 695 } else {
stevew817 0:667132a19341 696 sign = 1;
stevew817 0:667132a19341 697 }
stevew817 0:667132a19341 698
stevew817 0:667132a19341 699 if ( (x_order == 0) && (y_order == 0) ) {
stevew817 0:667132a19341 700 output += sign * mag << output_fraction;
stevew817 0:667132a19341 701 } else {
stevew817 0:667132a19341 702 if ( x_order > 0 ) {
stevew817 0:667132a19341 703 x1 = calculate_polynomial_helper(x, input_fraction, mag, shift);
stevew817 0:667132a19341 704 if ( x_order > 1 ) {
stevew817 0:667132a19341 705 x2 = calculate_polynomial_helper(x, input_fraction, mag, shift);
stevew817 0:667132a19341 706 } else {
stevew817 0:667132a19341 707 x2 = 1;
stevew817 0:667132a19341 708 }
stevew817 0:667132a19341 709 } else {
stevew817 0:667132a19341 710 x1 = 1;
stevew817 0:667132a19341 711 x2 = 1;
stevew817 0:667132a19341 712 }
stevew817 0:667132a19341 713
stevew817 0:667132a19341 714 if ( y_order > 0 ) {
stevew817 0:667132a19341 715 y1 = calculate_polynomial_helper(y, input_fraction, mag, shift);
stevew817 0:667132a19341 716 if ( y_order > 1 ) {
stevew817 0:667132a19341 717 y2 = calculate_polynomial_helper(y, input_fraction, mag, shift);
stevew817 0:667132a19341 718 } else {
stevew817 0:667132a19341 719 y2 = 1;
stevew817 0:667132a19341 720 }
stevew817 0:667132a19341 721 } else {
stevew817 0:667132a19341 722 y1 = 1;
stevew817 0:667132a19341 723 y2 = 1;
stevew817 0:667132a19341 724 }
stevew817 0:667132a19341 725
stevew817 0:667132a19341 726 output += sign * x1 * x2 * y1 * y2;
stevew817 0:667132a19341 727 }
stevew817 0:667132a19341 728
stevew817 0:667132a19341 729 kp++;
stevew817 0:667132a19341 730 }
stevew817 0:667132a19341 731
stevew817 0:667132a19341 732 if ( output < 0 ) {
stevew817 0:667132a19341 733 output = -output;
stevew817 0:667132a19341 734 }
stevew817 0:667132a19341 735
stevew817 0:667132a19341 736 return output;
stevew817 0:667132a19341 737 }
stevew817 0:667132a19341 738
stevew817 0:667132a19341 739 /***************************************************************************//**
stevew817 0:667132a19341 740 * @brief
stevew817 0:667132a19341 741 * Compute UV index
stevew817 0:667132a19341 742 *
stevew817 0:667132a19341 743 * @param[in] uv
stevew817 0:667132a19341 744 * UV sensor raw data
stevew817 0:667132a19341 745 *
stevew817 0:667132a19341 746 * @param[in] uk
stevew817 0:667132a19341 747 * UV calculation coefficients
stevew817 0:667132a19341 748 *
stevew817 0:667132a19341 749 * @return
stevew817 0:667132a19341 750 * UV index scaled by UV_OUPTUT_FRACTION
stevew817 0:667132a19341 751 ******************************************************************************/
stevew817 0:667132a19341 752 int32_t Si1133::getUv (int32_t uv)
stevew817 0:667132a19341 753 {
stevew817 0:667132a19341 754 int32_t uvi;
stevew817 0:667132a19341 755
stevew817 0:667132a19341 756 uvi = calculate_polynomial(0, uv, UV_INPUT_FRACTION, UV_OUTPUT_FRACTION, UV_NUMCOEFF, uk);
stevew817 0:667132a19341 757
stevew817 0:667132a19341 758 return uvi;
stevew817 0:667132a19341 759 }
stevew817 0:667132a19341 760
stevew817 0:667132a19341 761 /***************************************************************************//**
stevew817 0:667132a19341 762 * @brief
stevew817 0:667132a19341 763 * Compute lux value
stevew817 0:667132a19341 764 *
stevew817 0:667132a19341 765 * @param[in] vis_high
stevew817 0:667132a19341 766 * Visible light sensor raw data
stevew817 0:667132a19341 767 *
stevew817 0:667132a19341 768 * @param[in] vis_low
stevew817 0:667132a19341 769 * Visible light sensor raw data
stevew817 0:667132a19341 770 *
stevew817 0:667132a19341 771 * @param[in] ir
stevew817 0:667132a19341 772 * Infrared sensor raw data
stevew817 0:667132a19341 773 *
stevew817 0:667132a19341 774 * @param[in] lk
stevew817 0:667132a19341 775 * Lux calculation coefficients
stevew817 0:667132a19341 776 *
stevew817 0:667132a19341 777 * @return
stevew817 0:667132a19341 778 * Lux value scaled by LUX_OUPTUT_FRACTION
stevew817 0:667132a19341 779 ******************************************************************************/
stevew817 0:667132a19341 780 int32_t Si1133::getLux (int32_t vis_high, int32_t vis_low, int32_t ir)
stevew817 0:667132a19341 781 {
stevew817 0:667132a19341 782 int32_t lux;
stevew817 0:667132a19341 783
stevew817 0:667132a19341 784 if ( (vis_high > ADC_THRESHOLD) || (ir > ADC_THRESHOLD) ) {
stevew817 0:667132a19341 785 lux = calculate_polynomial(vis_high,
stevew817 0:667132a19341 786 ir,
stevew817 0:667132a19341 787 INPUT_FRACTION_HIGH,
stevew817 0:667132a19341 788 LUX_OUTPUT_FRACTION,
stevew817 0:667132a19341 789 NUMCOEFF_HIGH,
stevew817 0:667132a19341 790 &(lk.coeff_high[0]) );
stevew817 0:667132a19341 791 } else {
stevew817 0:667132a19341 792 lux = calculate_polynomial(vis_low,
stevew817 0:667132a19341 793 ir,
stevew817 0:667132a19341 794 INPUT_FRACTION_LOW,
stevew817 0:667132a19341 795 LUX_OUTPUT_FRACTION,
stevew817 0:667132a19341 796 NUMCOEFF_LOW,
stevew817 0:667132a19341 797 &(lk.coeff_low[0]) );
stevew817 0:667132a19341 798 }
stevew817 0:667132a19341 799
stevew817 0:667132a19341 800 return lux;
stevew817 0:667132a19341 801 }
stevew817 0:667132a19341 802
stevew817 0:667132a19341 803 /***************************************************************************//**
stevew817 0:667132a19341 804 * @brief
stevew817 0:667132a19341 805 * Measure lux and UV index using the Si1133 sensor
stevew817 0:667132a19341 806 *
stevew817 0:667132a19341 807 * @param[out] lux
stevew817 0:667132a19341 808 * The measured ambient light illuminace in lux
stevew817 0:667132a19341 809 *
stevew817 0:667132a19341 810 * @param[out] uvi
stevew817 0:667132a19341 811 * UV index
stevew817 0:667132a19341 812 *
stevew817 0:667132a19341 813 * @return
stevew817 0:667132a19341 814 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 815 ******************************************************************************/
stevew817 0:667132a19341 816 uint32_t Si1133::measureLuxUvi (float *lux, float *uvi)
stevew817 0:667132a19341 817 {
stevew817 0:667132a19341 818 Si1133::Samples_t samples;
stevew817 0:667132a19341 819 uint32_t retval;
stevew817 0:667132a19341 820 uint8_t response;
stevew817 0:667132a19341 821
stevew817 0:667132a19341 822 /* Force measurement */
stevew817 0:667132a19341 823 retval = force_measurement();
stevew817 0:667132a19341 824
stevew817 0:667132a19341 825 /* Go to sleep while the sensor does the conversion */
stevew817 0:667132a19341 826 wait_ms(200);
stevew817 0:667132a19341 827
stevew817 0:667132a19341 828 /* Check if the measurement finished, if not then wait */
stevew817 0:667132a19341 829 retval += read_register(REG_IRQ_STATUS, &response);
stevew817 0:667132a19341 830 while ( response != 0x0F ) {
stevew817 0:667132a19341 831 wait_ms(5);
stevew817 0:667132a19341 832 retval += read_register(REG_IRQ_STATUS, &response);
stevew817 0:667132a19341 833 }
stevew817 0:667132a19341 834
stevew817 0:667132a19341 835 /* Get the results */
stevew817 0:667132a19341 836 measurementGet(&samples);
stevew817 0:667132a19341 837
stevew817 0:667132a19341 838 /* Convert the readings to lux */
stevew817 0:667132a19341 839 *lux = (float) getLux(samples.ch1, samples.ch3, samples.ch2);
stevew817 0:667132a19341 840 *lux = *lux / (1 << LUX_OUTPUT_FRACTION);
stevew817 0:667132a19341 841
stevew817 0:667132a19341 842 /* Convert the readings to UV index */
stevew817 0:667132a19341 843 *uvi = (float) getUv(samples.ch0);
stevew817 0:667132a19341 844 *uvi = *uvi / (1 << UV_OUTPUT_FRACTION);
stevew817 0:667132a19341 845
stevew817 0:667132a19341 846 return retval;
stevew817 0:667132a19341 847 }
stevew817 0:667132a19341 848
stevew817 0:667132a19341 849 /***************************************************************************//**
stevew817 0:667132a19341 850 * @brief
stevew817 0:667132a19341 851 * Reads Hardware ID from the SI1133 sensor
stevew817 0:667132a19341 852 *
stevew817 0:667132a19341 853 * @param[out] hardwareID
stevew817 0:667132a19341 854 * The Hardware ID of the chip (should be 0x33)
stevew817 0:667132a19341 855 *
stevew817 0:667132a19341 856 * @return
stevew817 0:667132a19341 857 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 858 ******************************************************************************/
stevew817 0:667132a19341 859 uint32_t Si1133::getHardwareID (uint8_t *hardwareID)
stevew817 0:667132a19341 860 {
stevew817 0:667132a19341 861 uint32_t retval;
stevew817 0:667132a19341 862
stevew817 0:667132a19341 863 retval = read_register(REG_PART_ID, hardwareID);
stevew817 0:667132a19341 864
stevew817 0:667132a19341 865 return retval;
stevew817 0:667132a19341 866 }
stevew817 0:667132a19341 867
stevew817 0:667132a19341 868 /***************************************************************************//**
stevew817 0:667132a19341 869 * @brief
stevew817 0:667132a19341 870 * Retrieve the sample values from the chip and convert them
stevew817 0:667132a19341 871 * to lux and UV index values
stevew817 0:667132a19341 872 *
stevew817 0:667132a19341 873 * @param[out] lux
stevew817 0:667132a19341 874 * The measured ambient light illuminace in lux
stevew817 0:667132a19341 875 *
stevew817 0:667132a19341 876 * @param[out] uvi
stevew817 0:667132a19341 877 * UV index
stevew817 0:667132a19341 878 *
stevew817 0:667132a19341 879 * @return
stevew817 0:667132a19341 880 * Returns zero on OK, non-zero otherwise
stevew817 0:667132a19341 881 ******************************************************************************/
stevew817 0:667132a19341 882 uint32_t Si1133::getMeasurement (float *lux, float *uvi)
stevew817 0:667132a19341 883 {
stevew817 0:667132a19341 884 Si1133::Samples_t samples;
stevew817 0:667132a19341 885 uint32_t retval;
stevew817 0:667132a19341 886
stevew817 0:667132a19341 887 /* Get the results */
stevew817 0:667132a19341 888 retval = measurementGet(&samples);
stevew817 0:667132a19341 889
stevew817 0:667132a19341 890 /* Convert the readings to lux */
stevew817 0:667132a19341 891 *lux = (float) getLux(samples.ch1, samples.ch3, samples.ch2);
stevew817 0:667132a19341 892 *lux = *lux / (1 << LUX_OUTPUT_FRACTION);
stevew817 0:667132a19341 893
stevew817 0:667132a19341 894 /* Convert the readings to UV index */
stevew817 0:667132a19341 895 *uvi = (float) getUv(samples.ch0);
stevew817 0:667132a19341 896 *uvi = *uvi / (1 << UV_OUTPUT_FRACTION);
stevew817 0:667132a19341 897
stevew817 0:667132a19341 898 return retval;
stevew817 0:667132a19341 899 }