Forked so that I can make it take I2C as a parameter; on a bus with other I2C things.

Fork of Si1133 by Silicon Labs

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Si1133.cpp Source File

Si1133.cpp

Go to the documentation of this file.
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, &reg_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 }