Driver for the Silicon Labs Si1133 Visible Light/UV sensor

Dependents:   TBSense2_Sensor_Demo mbed-BLE-coragem-teste ... 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:
Steven Cooreman
Date:
Fri Mar 22 00:51:29 2019 +0100
Revision:
3:f780ca9105bb
Parent:
2:1e2dd643afa8
remove VLA usage

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