Forked so that I can make it take I2C as a parameter; on a bus with other I2C things.
Fork of Si1133 by
Si1133.cpp
00001 /***************************************************************************//** 00002 * @file Si1133.cpp 00003 ******************************************************************************* 00004 * @section License 00005 * <b>(C) Copyright 2017 Silicon Labs, http://www.silabs.com</b> 00006 ******************************************************************************* 00007 * 00008 * SPDX-License-Identifier: Apache-2.0 00009 * 00010 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00011 * not use this file except in compliance with the License. 00012 * You may obtain a copy of the License at 00013 * 00014 * http://www.apache.org/licenses/LICENSE-2.0 00015 * 00016 * Unless required by applicable law or agreed to in writing, software 00017 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00018 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00019 * See the License for the specific language governing permissions and 00020 * limitations under the License. 00021 * 00022 ******************************************************************************/ 00023 00024 #include "Si1133.h " 00025 00026 #define SI1133_I2C_ADDRESS (0xAA) /** Hardcoded address for Si1133 sensor */ 00027 00028 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ 00029 00030 #define X_ORDER_MASK 0x0070 00031 #define Y_ORDER_MASK 0x0007 00032 #define SIGN_MASK 0x0080 00033 #define GET_X_ORDER(m) ( ((m) & X_ORDER_MASK) >> 4) 00034 #define GET_Y_ORDER(m) ( ((m) & Y_ORDER_MASK) ) 00035 #define GET_SIGN(m) ( ((m) & SIGN_MASK) >> 7) 00036 00037 #define UV_INPUT_FRACTION 15 00038 #define UV_OUTPUT_FRACTION 12 00039 #define UV_NUMCOEFF 2 00040 00041 #define ADC_THRESHOLD 16000 00042 #define INPUT_FRACTION_HIGH 7 00043 #define INPUT_FRACTION_LOW 15 00044 #define LUX_OUTPUT_FRACTION 12 00045 #define NUMCOEFF_LOW 9 00046 #define NUMCOEFF_HIGH 4 00047 00048 /** @endcond */ 00049 00050 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ 00051 /***************************************************************************//** 00052 * @brief 00053 * Coefficients for lux calculation 00054 ******************************************************************************/ 00055 const Si1133::LuxCoeff_t Si1133::lk = { 00056 { { 0, 209 }, /**< coeff_high[0] */ 00057 { 1665, 93 }, /**< coeff_high[1] */ 00058 { 2064, 65 }, /**< coeff_high[2] */ 00059 { -2671, 234 } }, /**< coeff_high[3] */ 00060 { { 0, 0 }, /**< coeff_low[0] */ 00061 { 1921, 29053 }, /**< coeff_low[1] */ 00062 { -1022, 36363 }, /**< coeff_low[2] */ 00063 { 2320, 20789 }, /**< coeff_low[3] */ 00064 { -367, 57909 }, /**< coeff_low[4] */ 00065 { -1774, 38240 }, /**< coeff_low[5] */ 00066 { -608, 46775 }, /**< coeff_low[6] */ 00067 { -1503, 51831 }, /**< coeff_low[7] */ 00068 { -1886, 58928 } } /**< coeff_low[8] */ 00069 }; 00070 00071 /***************************************************************************//** 00072 * @brief 00073 * Coefficients for UV index calculation 00074 ******************************************************************************/ 00075 const Si1133::Coeff_t Si1133::uk[2] = { 00076 { 1281, 30902 }, /**< coeff[0] */ 00077 { -638, 46301 } /**< coeff[1] */ 00078 }; 00079 00080 /**************************************************************************//** 00081 * @name Error Codes 00082 * @{ 00083 ******************************************************************************/ 00084 #define SI1133_OK 0x0000 /**< No errors */ 00085 #define SI1133_ERROR_I2C_TRANSACTION_FAILED 0x0001 /**< I2C transaction failed */ 00086 #define SI1133_ERROR_SLEEP_FAILED 0x0002 /**< Entering sleep mode failed */ 00087 /**@}*/ 00088 00089 /** @endcond */ 00090 00091 Si1133::Si1133(PinName sda, PinName scl, int hz) : m_I2C(sda, scl) 00092 { 00093 //Set the I2C bus frequency 00094 m_I2C.frequency(hz); 00095 } 00096 00097 Si1133::~Si1133(void) 00098 { 00099 deinit(); 00100 } 00101 00102 bool Si1133::open() 00103 { 00104 //Probe for the Si1133 using a Zero Length Transfer 00105 if (m_I2C.write(SI1133_I2C_ADDRESS, NULL, 0)) { 00106 //Return success 00107 return false; 00108 } 00109 00110 // initialize sensor 00111 if (SI1133_OK == init()) { 00112 return true; 00113 } 00114 return false; 00115 } 00116 00117 /** Measure the current light level (in lux) on the Si1133 00118 * 00119 * @returns The current temperature measurement in Lux. 00120 */ 00121 float Si1133::get_light_level() 00122 { 00123 float lux, uvi; 00124 measure_lux_uv(&lux, &uvi); 00125 return lux; 00126 } 00127 00128 /** Measure the current UV Index on the Si1133 00129 * 00130 * @returns The current UV index. 00131 */ 00132 float Si1133::get_uv_index() 00133 { 00134 float lux, uvi; 00135 measure_lux_uv(&lux, &uvi); 00136 return uvi; 00137 } 00138 00139 bool Si1133::get_light_and_uv(float *light_level, float *uv_index) 00140 { 00141 if(measure_lux_uv(light_level, uv_index)) { 00142 return false; 00143 } 00144 return true; 00145 } 00146 00147 /***************************************************************************//** 00148 * @brief 00149 * Reads register from the Si1133 sensor 00150 * 00151 * @param[in] reg 00152 * The register address to read from in the sensor. 00153 * 00154 * @param[out] data 00155 * The data read from the sensor 00156 * 00157 * @return 00158 * Returns zero on OK, non-zero otherwise 00159 ******************************************************************************/ 00160 uint32_t Si1133::read_register(enum Si1133::Register reg, uint8_t *data) 00161 { 00162 char buf[1]; 00163 buf[0] = (char) reg; 00164 00165 if (m_I2C.write(SI1133_I2C_ADDRESS, buf, 1, true)) { 00166 //Return failure 00167 return SI1133_ERROR_I2C_TRANSACTION_FAILED; 00168 } 00169 00170 if (m_I2C.read(SI1133_I2C_ADDRESS, buf, 1)) { 00171 //Return failure 00172 return SI1133_ERROR_I2C_TRANSACTION_FAILED; 00173 } 00174 00175 *data = buf[0]; 00176 00177 return SI1133_OK; 00178 } 00179 00180 /***************************************************************************//** 00181 * @brief 00182 * Writes register in the Si1133 sensor 00183 * 00184 * @param[in] reg 00185 * The register address to write to in the sensor 00186 * 00187 * @param[in] data 00188 * The data to write to the sensor 00189 * 00190 * @return 00191 * Returns zero on OK, non-zero otherwise 00192 ******************************************************************************/ 00193 uint32_t Si1133::write_register(enum Si1133::Register reg, uint8_t data) 00194 { 00195 char buf[2]; 00196 buf[0] = (char) reg; 00197 buf[1] = (char) data; 00198 00199 if (m_I2C.write(SI1133_I2C_ADDRESS, buf, 2)) { 00200 //Return failure 00201 return SI1133_ERROR_I2C_TRANSACTION_FAILED; 00202 } 00203 00204 return SI1133_OK; 00205 } 00206 00207 /***************************************************************************//** 00208 * @brief 00209 * Writes a block of data to the Si1133 sensor. 00210 * 00211 * @param[in] reg 00212 * The first register to begin writing to 00213 * 00214 * @param[in] length 00215 * The number of bytes to write to the sensor 00216 * 00217 * @param[in] data 00218 * The data to write to the sensor 00219 * 00220 * @return 00221 * Returns zero on OK, non-zero otherwise 00222 ******************************************************************************/ 00223 uint32_t Si1133::write_register_block(enum Si1133::Register reg, uint8_t length, uint8_t *data) 00224 { 00225 char buf[length+1]; 00226 buf[0] = (char)reg; 00227 memcpy(&buf[1], data, length); 00228 00229 if (m_I2C.write(SI1133_I2C_ADDRESS, buf, length + 1)) { 00230 //Return failure 00231 return SI1133_ERROR_I2C_TRANSACTION_FAILED; 00232 } 00233 00234 return SI1133_OK; 00235 } 00236 00237 /***************************************************************************//** 00238 * @brief 00239 * Reads a block of data from the Si1133 sensor. 00240 * 00241 * @param[in] reg 00242 * The first register to begin reading from 00243 * 00244 * @param[in] length 00245 * The number of bytes to write to the sensor 00246 * 00247 * @param[out] data 00248 * The data read from the sensor 00249 * 00250 * @return 00251 * Returns zero on OK, non-zero otherwise 00252 ******************************************************************************/ 00253 uint32_t Si1133::read_register_block(enum Si1133::Register reg, uint8_t length, uint8_t *data) 00254 { 00255 char reg_c = (char)reg; 00256 if (m_I2C.write(SI1133_I2C_ADDRESS, ®_c, 1, true)) { 00257 //Return failure 00258 return SI1133_ERROR_I2C_TRANSACTION_FAILED; 00259 } 00260 00261 if (m_I2C.read(SI1133_I2C_ADDRESS, (char*) data, length)) { 00262 //Return failure 00263 return SI1133_ERROR_I2C_TRANSACTION_FAILED; 00264 } 00265 00266 return SI1133_OK; 00267 } 00268 00269 /***************************************************************************//** 00270 * @brief 00271 * Reads the interrupt status register of the device 00272 * 00273 * @param[out] irqStatus 00274 * The contentof the IRQ status register 00275 * 00276 * @return 00277 * Returns zero on OK, non-zero otherwise 00278 ******************************************************************************/ 00279 uint32_t Si1133::get_irq_status(uint8_t *irq_status) 00280 { 00281 return read_register(REG_IRQ_STATUS, irq_status); 00282 } 00283 00284 /***************************************************************************//** 00285 * @brief 00286 * Waits until the Si1133 is sleeping before proceeding 00287 * 00288 * @return 00289 * Returns zero on OK, non-zero otherwise 00290 ******************************************************************************/ 00291 uint32_t Si1133::wait_until_sleep(void) 00292 { 00293 uint32_t ret; 00294 uint8_t response; 00295 size_t count = 0; 00296 00297 /* This loops until the Si1133 is known to be in its sleep state */ 00298 /* or if an i2c error occurs */ 00299 while ( count < 5 ) { 00300 ret = read_register(REG_RESPONSE0, &response); 00301 if ( (response & (uint8_t)RSP0_CHIPSTAT_MASK) == (uint8_t)RSP0_SLEEP ) { 00302 return SI1133_OK; 00303 } 00304 00305 if ( ret != SI1133_OK ) { 00306 return SI1133_ERROR_SLEEP_FAILED; 00307 } 00308 00309 count++; 00310 } 00311 00312 return SI1133_ERROR_SLEEP_FAILED; 00313 } 00314 00315 /***************************************************************************//** 00316 * @brief 00317 * Resets the Si1133 00318 * 00319 * @return 00320 * Returns zero on OK, non-zero otherwise 00321 ******************************************************************************/ 00322 uint32_t Si1133::reset(void) 00323 { 00324 uint32_t retval; 00325 00326 /* Do not access the Si1133 earlier than 25 ms from power-up */ 00327 wait_ms(30); 00328 00329 /* Perform the Reset Command */ 00330 retval = write_register(REG_COMMAND, (uint8_t)CMD_RESET); 00331 00332 /* Delay for 10 ms. This delay is needed to allow the Si1133 */ 00333 /* to perform internal reset sequence. */ 00334 wait_ms(10); 00335 00336 return retval; 00337 } 00338 00339 /***************************************************************************//** 00340 * @brief 00341 * Helper function to send a command to the Si1133 00342 * 00343 * @param[in] command 00344 * The command to send to the sensor 00345 * 00346 * @return 00347 * Returns zero on OK, non-zero otherwise 00348 ******************************************************************************/ 00349 uint32_t Si1133::send_cmd(enum Si1133::Command command) 00350 { 00351 uint8_t response; 00352 uint8_t response_stored; 00353 uint8_t count = 0; 00354 uint32_t ret; 00355 00356 /* Get the response register contents */ 00357 ret = read_register(REG_RESPONSE0, &response_stored); 00358 if ( ret != SI1133_OK ) { 00359 return ret; 00360 } 00361 00362 response_stored = response_stored & (uint8_t)RSP0_COUNTER_MASK; 00363 00364 /* Double-check the response register is consistent */ 00365 while ( count < 5 ) { 00366 ret = wait_until_sleep(); 00367 if ( ret != SI1133_OK ) { 00368 return ret; 00369 } 00370 /* Skip if the command is RESET COMMAND COUNTER */ 00371 if ( command == (uint8_t)CMD_RESET_CMD_CTR ) { 00372 break; 00373 } 00374 00375 ret = read_register(REG_RESPONSE0, &response); 00376 00377 if ( (response & (uint8_t)RSP0_COUNTER_MASK) == response_stored ) { 00378 break; 00379 } else { 00380 if ( ret != SI1133_OK ) { 00381 return ret; 00382 } else { 00383 response_stored = response & (uint8_t)RSP0_COUNTER_MASK; 00384 } 00385 } 00386 00387 count++; 00388 } 00389 00390 /* Send the command */ 00391 ret = write_register(REG_COMMAND, command); 00392 if ( ret != SI1133_OK ) { 00393 return ret; 00394 } 00395 00396 count = 0; 00397 /* Expect a change in the response register */ 00398 while ( count < 5 ) { 00399 /* Skip if the command is RESET COMMAND COUNTER */ 00400 if ( command == (uint8_t)CMD_RESET_CMD_CTR ) { 00401 break; 00402 } 00403 00404 ret = read_register(REG_RESPONSE0, &response); 00405 if ( (response & (uint8_t)RSP0_COUNTER_MASK) != response_stored ) { 00406 break; 00407 } else { 00408 if ( ret != SI1133_OK ) { 00409 return ret; 00410 } 00411 } 00412 00413 count++; 00414 } 00415 00416 return SI1133_OK; 00417 } 00418 00419 /***************************************************************************//** 00420 * @brief 00421 * Sends a RESET COMMAND COUNTER command to the Si1133 00422 * 00423 * @return 00424 * Returns zero on OK, non-zero otherwise 00425 ******************************************************************************/ 00426 uint32_t Si1133::reset_cmd_counter(void) 00427 { 00428 return send_cmd(CMD_RESET_CMD_CTR); 00429 } 00430 00431 /***************************************************************************//** 00432 * @brief 00433 * Sends a FORCE command to the Si1133 00434 * 00435 * @return 00436 * Returns zero on OK, non-zero otherwise 00437 ******************************************************************************/ 00438 uint32_t Si1133::force_measurement(void) 00439 { 00440 return send_cmd(CMD_FORCE_CH); 00441 } 00442 00443 /***************************************************************************//** 00444 * @brief 00445 * Sends a START command to the Si1133 00446 * 00447 * @return 00448 * Returns zero on OK, non-zero otherwise 00449 ******************************************************************************/ 00450 uint32_t Si1133::start_measurement(void) 00451 { 00452 return send_cmd(CMD_START); 00453 } 00454 00455 /***************************************************************************//** 00456 * @brief 00457 * Sends a PAUSE command to the Si1133 00458 * 00459 * @return 00460 * Returns zero on OK, non-zero otherwise 00461 ******************************************************************************/ 00462 uint32_t Si1133::pause_measurement(void) 00463 { 00464 return send_cmd(CMD_PAUSE_CH); 00465 } 00466 00467 /***************************************************************************//** 00468 * @brief 00469 * Writes a byte to an Si1133 Parameter 00470 * 00471 * @param[in] address 00472 * The parameter address 00473 * 00474 * @param[in] value 00475 * The byte value to be written to the Si1133 parameter 00476 * 00477 * @return 00478 * Returns zero on OK, non-zero otherwise 00479 * 00480 * @note 00481 * This function ensures that the Si1133 is idle and ready to 00482 * receive a command before writing the parameter. Furthermore, 00483 * command completion is checked. If setting parameter is not done 00484 * properly, no measurements will occur. This is the most common 00485 * error. It is highly recommended that host code make use of this 00486 * function. 00487 ******************************************************************************/ 00488 uint32_t Si1133::set_parameter (enum Si1133::Parameter address, uint8_t value) 00489 { 00490 uint32_t retval; 00491 uint8_t buffer[2]; 00492 uint8_t response_stored; 00493 uint8_t response; 00494 size_t count; 00495 00496 retval = wait_until_sleep(); 00497 if ( retval != SI1133_OK ) { 00498 return retval; 00499 } 00500 00501 read_register(REG_RESPONSE0, &response_stored); 00502 response_stored &= (uint8_t)RSP0_COUNTER_MASK; 00503 00504 buffer[0] = value; 00505 buffer[1] = 0x80 + ((uint8_t)address & 0x3F); 00506 00507 retval = write_register_block(REG_HOSTIN0, 2, (uint8_t*) buffer); 00508 if ( retval != SI1133_OK ) { 00509 return retval; 00510 } 00511 00512 /* Wait for command to finish */ 00513 count = 0; 00514 /* Expect a change in the response register */ 00515 while ( count < 5 ) { 00516 retval = read_register(REG_RESPONSE0, &response); 00517 if ( (response & (uint8_t)RSP0_COUNTER_MASK) != response_stored ) { 00518 break; 00519 } else { 00520 if ( retval != SI1133_OK ) { 00521 return retval; 00522 } 00523 } 00524 00525 count++; 00526 } 00527 00528 if (count >= 5) { 00529 return SI1133_ERROR_I2C_TRANSACTION_FAILED; 00530 } 00531 00532 return SI1133_OK; 00533 } 00534 00535 /***************************************************************************//** 00536 * @brief 00537 * Reads a parameter from the Si1133 00538 * 00539 * @param[in] address 00540 * The address of the parameter. 00541 * 00542 * @return 00543 * Returns zero on OK, non-zero otherwise 00544 ******************************************************************************/ 00545 uint32_t Si1133::read_parameter (enum Si1133::Parameter address) 00546 { 00547 uint8_t retval; 00548 uint8_t cmd; 00549 00550 cmd = 0x40 + ((uint8_t)address & 0x3F); 00551 00552 retval = send_cmd((enum Si1133::Command)cmd); 00553 if ( retval != SI1133_OK ) { 00554 return retval; 00555 } 00556 00557 read_register(REG_RESPONSE1, &retval); 00558 00559 return retval; 00560 } 00561 00562 /**************************************************************************//** 00563 * @brief 00564 * Initializes the Si1133 chip 00565 * 00566 * @return 00567 * Returns zero on OK, non-zero otherwise 00568 *****************************************************************************/ 00569 uint32_t Si1133::init (void) 00570 { 00571 uint32_t retval; 00572 00573 /* Allow some time for the part to power up */ 00574 wait_ms(5); 00575 00576 retval = reset(); 00577 00578 wait_ms(10); 00579 00580 retval += set_parameter(PARAM_CH_LIST, 0x0f); 00581 retval += set_parameter(PARAM_ADCCONFIG0, 0x78); 00582 retval += set_parameter(PARAM_ADCSENS0, 0x71); 00583 retval += set_parameter(PARAM_ADCPOST0, 0x40); 00584 retval += set_parameter(PARAM_ADCCONFIG1, 0x4d); 00585 retval += set_parameter(PARAM_ADCSENS1, 0xe1); 00586 retval += set_parameter(PARAM_ADCPOST1, 0x40); 00587 retval += set_parameter(PARAM_ADCCONFIG2, 0x41); 00588 retval += set_parameter(PARAM_ADCSENS2, 0xe1); 00589 retval += set_parameter(PARAM_ADCPOST2, 0x50); 00590 retval += set_parameter(PARAM_ADCCONFIG3, 0x4d); 00591 retval += set_parameter(PARAM_ADCSENS3, 0x87); 00592 retval += set_parameter(PARAM_ADCPOST3, 0x40); 00593 00594 retval += write_register(REG_IRQ_ENABLE, 0x0f); 00595 00596 return retval; 00597 } 00598 00599 /***************************************************************************//** 00600 * @brief 00601 * Stops the measurements on all channel and waits until the chip 00602 * goes to sleep state. 00603 * 00604 * @return 00605 * Returns zero on OK, non-zero otherwise 00606 ******************************************************************************/ 00607 uint32_t Si1133::deinit (void) 00608 { 00609 uint32_t retval; 00610 00611 retval = set_parameter(PARAM_CH_LIST, 0x3f); 00612 retval += pause_measurement(); 00613 retval += wait_until_sleep(); 00614 00615 return retval; 00616 } 00617 00618 /***************************************************************************//** 00619 * @brief 00620 * Read samples from the Si1133 chip 00621 * 00622 * @param[out] samples 00623 * Retrieves interrupt status and measurement data for channel 0..3 and 00624 * converts the data to int32_t format 00625 * 00626 * @return 00627 * Returns zero on OK, non-zero otherwise 00628 ******************************************************************************/ 00629 uint32_t Si1133::measure (Si1133::Samples_t *samples) 00630 { 00631 uint8_t buffer[13]; 00632 uint32_t retval; 00633 00634 retval = read_register_block(REG_IRQ_STATUS, 13, buffer); 00635 00636 samples->irq_status = buffer[0]; 00637 00638 samples->ch0 = buffer[1] << 16; 00639 samples->ch0 |= buffer[2] << 8; 00640 samples->ch0 |= buffer[3]; 00641 if ( samples->ch0 & 0x800000 ) { 00642 samples->ch0 |= 0xFF000000; 00643 } 00644 00645 samples->ch1 = buffer[4] << 16; 00646 samples->ch1 |= buffer[5] << 8; 00647 samples->ch1 |= buffer[6]; 00648 if ( samples->ch1 & 0x800000 ) { 00649 samples->ch1 |= 0xFF000000; 00650 } 00651 00652 samples->ch2 = buffer[7] << 16; 00653 samples->ch2 |= buffer[8] << 8; 00654 samples->ch2 |= buffer[9]; 00655 if ( samples->ch2 & 0x800000 ) { 00656 samples->ch2 |= 0xFF000000; 00657 } 00658 00659 samples->ch3 = buffer[10] << 16; 00660 samples->ch3 |= buffer[11] << 8; 00661 samples->ch3 |= buffer[12]; 00662 if ( samples->ch3 & 0x800000 ) { 00663 samples->ch3 |= 0xFF000000; 00664 } 00665 00666 return retval; 00667 } 00668 00669 int32_t Si1133::calculate_polynomial_helper (int32_t input, int8_t fraction, uint16_t mag, int8_t shift) 00670 { 00671 int32_t value; 00672 00673 if ( shift < 0 ) { 00674 value = ( (input << fraction) / mag) >> -shift; 00675 } else { 00676 value = ( (input << fraction) / mag) << shift; 00677 } 00678 00679 return value; 00680 } 00681 00682 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) 00683 { 00684 uint8_t info, x_order, y_order, counter; 00685 int8_t sign, shift; 00686 uint16_t mag; 00687 int32_t output = 0, x1, x2, y1, y2; 00688 00689 for ( counter = 0; counter < num_coeff; counter++ ) { 00690 info = kp->info; 00691 x_order = GET_X_ORDER(info); 00692 y_order = GET_Y_ORDER(info); 00693 00694 shift = ( (uint16_t) kp->info & 0xff00) >> 8; 00695 shift ^= 0x00ff; 00696 shift += 1; 00697 shift = -shift; 00698 00699 mag = kp->mag; 00700 00701 if ( GET_SIGN(info) ) { 00702 sign = -1; 00703 } else { 00704 sign = 1; 00705 } 00706 00707 if ( (x_order == 0) && (y_order == 0) ) { 00708 output += sign * mag << output_fraction; 00709 } else { 00710 if ( x_order > 0 ) { 00711 x1 = calculate_polynomial_helper(x, input_fraction, mag, shift); 00712 if ( x_order > 1 ) { 00713 x2 = calculate_polynomial_helper(x, input_fraction, mag, shift); 00714 } else { 00715 x2 = 1; 00716 } 00717 } else { 00718 x1 = 1; 00719 x2 = 1; 00720 } 00721 00722 if ( y_order > 0 ) { 00723 y1 = calculate_polynomial_helper(y, input_fraction, mag, shift); 00724 if ( y_order > 1 ) { 00725 y2 = calculate_polynomial_helper(y, input_fraction, mag, shift); 00726 } else { 00727 y2 = 1; 00728 } 00729 } else { 00730 y1 = 1; 00731 y2 = 1; 00732 } 00733 00734 output += sign * x1 * x2 * y1 * y2; 00735 } 00736 00737 kp++; 00738 } 00739 00740 if ( output < 0 ) { 00741 output = -output; 00742 } 00743 00744 return output; 00745 } 00746 00747 /***************************************************************************//** 00748 * @brief 00749 * Compute UV index 00750 * 00751 * @param[in] uv 00752 * UV sensor raw data 00753 * 00754 * @param[in] uk 00755 * UV calculation coefficients 00756 * 00757 * @return 00758 * UV index scaled by UV_OUPTUT_FRACTION 00759 ******************************************************************************/ 00760 int32_t Si1133::get_uv (int32_t uv) 00761 { 00762 int32_t uvi; 00763 00764 uvi = calculate_polynomial(0, uv, UV_INPUT_FRACTION, UV_OUTPUT_FRACTION, UV_NUMCOEFF, uk); 00765 00766 return uvi; 00767 } 00768 00769 /***************************************************************************//** 00770 * @brief 00771 * Compute lux value 00772 * 00773 * @param[in] vis_high 00774 * Visible light sensor raw data 00775 * 00776 * @param[in] vis_low 00777 * Visible light sensor raw data 00778 * 00779 * @param[in] ir 00780 * Infrared sensor raw data 00781 * 00782 * @param[in] lk 00783 * Lux calculation coefficients 00784 * 00785 * @return 00786 * Lux value scaled by LUX_OUPTUT_FRACTION 00787 ******************************************************************************/ 00788 int32_t Si1133::get_lux (int32_t vis_high, int32_t vis_low, int32_t ir) 00789 { 00790 int32_t lux; 00791 00792 if ( (vis_high > ADC_THRESHOLD) || (ir > ADC_THRESHOLD) ) { 00793 lux = calculate_polynomial(vis_high, 00794 ir, 00795 INPUT_FRACTION_HIGH, 00796 LUX_OUTPUT_FRACTION, 00797 NUMCOEFF_HIGH, 00798 &(lk.coeff_high[0]) ); 00799 } else { 00800 lux = calculate_polynomial(vis_low, 00801 ir, 00802 INPUT_FRACTION_LOW, 00803 LUX_OUTPUT_FRACTION, 00804 NUMCOEFF_LOW, 00805 &(lk.coeff_low[0]) ); 00806 } 00807 00808 return lux; 00809 } 00810 00811 /***************************************************************************//** 00812 * @brief 00813 * Measure lux and UV index using the Si1133 sensor 00814 * 00815 * @param[out] lux 00816 * The measured ambient light illuminace in lux 00817 * 00818 * @param[out] uvi 00819 * UV index 00820 * 00821 * @return 00822 * Returns zero on OK, non-zero otherwise 00823 ******************************************************************************/ 00824 uint32_t Si1133::measure_lux_uv (float *lux, float *uvi) 00825 { 00826 Si1133::Samples_t samples; 00827 uint32_t retval; 00828 uint8_t response; 00829 00830 /* Force measurement */ 00831 retval = force_measurement(); 00832 00833 /* Go to sleep while the sensor does the conversion */ 00834 wait_ms(200); 00835 00836 /* Check if the measurement finished, if not then wait */ 00837 retval += read_register(REG_IRQ_STATUS, &response); 00838 while ( response != 0x0F ) { 00839 wait_ms(5); 00840 retval += read_register(REG_IRQ_STATUS, &response); 00841 } 00842 00843 /* Get the results */ 00844 measure(&samples); 00845 00846 /* Convert the readings to lux */ 00847 *lux = (float) get_lux(samples.ch1, samples.ch3, samples.ch2); 00848 *lux = *lux / (1 << LUX_OUTPUT_FRACTION); 00849 00850 /* Convert the readings to UV index */ 00851 *uvi = (float) get_uv(samples.ch0); 00852 *uvi = *uvi / (1 << UV_OUTPUT_FRACTION); 00853 00854 return retval; 00855 } 00856 00857 /***************************************************************************//** 00858 * @brief 00859 * Reads Hardware ID from the SI1133 sensor 00860 * 00861 * @param[out] hardwareID 00862 * The Hardware ID of the chip (should be 0x33) 00863 * 00864 * @return 00865 * Returns zero on OK, non-zero otherwise 00866 ******************************************************************************/ 00867 uint32_t Si1133::get_hardware_id (uint8_t *hardware_id) 00868 { 00869 uint32_t retval; 00870 00871 retval = read_register(REG_PART_ID, hardware_id); 00872 00873 return retval; 00874 } 00875 00876 /***************************************************************************//** 00877 * @brief 00878 * Retrieve the sample values from the chip and convert them 00879 * to lux and UV index values 00880 * 00881 * @param[out] lux 00882 * The measured ambient light illuminace in lux 00883 * 00884 * @param[out] uvi 00885 * UV index 00886 * 00887 * @return 00888 * Returns zero on OK, non-zero otherwise 00889 ******************************************************************************/ 00890 uint32_t Si1133::get_measurement (float *lux, float *uvi) 00891 { 00892 Si1133::Samples_t samples; 00893 uint32_t retval; 00894 00895 /* Get the results */ 00896 retval = measure(&samples); 00897 00898 /* Convert the readings to lux */ 00899 *lux = (float) get_lux(samples.ch1, samples.ch3, samples.ch2); 00900 *lux = *lux / (1 << LUX_OUTPUT_FRACTION); 00901 00902 /* Convert the readings to UV index */ 00903 *uvi = (float) get_uv(samples.ch0); 00904 *uvi = *uvi / (1 << UV_OUTPUT_FRACTION); 00905 00906 return retval; 00907 }
Generated on Tue Jul 19 2022 10:03:12 by 1.7.2