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 16:42:03 2017 +0100
Revision:
1:410f61a3900b
Parent:
0:667132a19341
Child:
2:1e2dd643afa8
Forgot function implementation

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