Nucleo Lora / Mbed 2 deprecated STM32_I2C_Sensiron_SCD41

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sensirion_i2c.c Source File

sensirion_i2c.c

00001 /*
00002  * Copyright (c) 2018, Sensirion AG
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * * Redistributions of source code must retain the above copyright notice, this
00009  *   list of conditions and the following disclaimer.
00010  *
00011  * * Redistributions in binary form must reproduce the above copyright notice,
00012  *   this list of conditions and the following disclaimer in the documentation
00013  *   and/or other materials provided with the distribution.
00014  *
00015  * * Neither the name of Sensirion AG nor the names of its
00016  *   contributors may be used to endorse or promote products derived from
00017  *   this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00020  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00023  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00024  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00025  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00026  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00027  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00028  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029  * POSSIBILITY OF SUCH DAMAGE.
00030  */
00031 
00032 #include "sensirion_i2c.h"
00033 #include "sensirion_common.h"
00034 #include "sensirion_config.h"
00035 #include "sensirion_i2c_hal.h"
00036 
00037 uint8_t sensirion_i2c_generate_crc(const uint8_t* data, uint16_t count) {
00038     uint16_t current_byte;
00039     uint8_t crc = CRC8_INIT;
00040     uint8_t crc_bit;
00041 
00042     /* calculates 8-Bit checksum with given polynomial */
00043     for (current_byte = 0; current_byte < count; ++current_byte) {
00044         crc ^= (data[current_byte]);
00045         for (crc_bit = 8; crc_bit > 0; --crc_bit) {
00046             if (crc & 0x80)
00047                 crc = (crc << 1) ^ CRC8_POLYNOMIAL;
00048             else
00049                 crc = (crc << 1);
00050         }
00051     }
00052     return crc;
00053 }
00054 
00055 int8_t sensirion_i2c_check_crc(const uint8_t* data, uint16_t count,
00056                                uint8_t checksum) {
00057     if (sensirion_i2c_generate_crc(data, count) != checksum)
00058         return CRC_ERROR;
00059     return NO_ERROR;
00060 }
00061 
00062 int16_t sensirion_i2c_general_call_reset(void) {
00063     const uint8_t data = 0x06;
00064     return sensirion_i2c_hal_write(0, &data, (uint16_t)sizeof(data));
00065 }
00066 
00067 uint16_t sensirion_i2c_fill_cmd_send_buf(uint8_t* buf, uint16_t cmd,
00068                                          const uint16_t* args,
00069                                          uint8_t num_args) {
00070     uint8_t i;
00071     uint16_t idx = 0;
00072 
00073     buf[idx++] = (uint8_t)((cmd & 0xFF00) >> 8);
00074     buf[idx++] = (uint8_t)((cmd & 0x00FF) >> 0);
00075 
00076     for (i = 0; i < num_args; ++i) {
00077         buf[idx++] = (uint8_t)((args[i] & 0xFF00) >> 8);
00078         buf[idx++] = (uint8_t)((args[i] & 0x00FF) >> 0);
00079 
00080         uint8_t crc = sensirion_i2c_generate_crc((uint8_t*)&buf[idx - 2],
00081                                                  SENSIRION_WORD_SIZE);
00082         buf[idx++] = crc;
00083     }
00084     return idx;
00085 }
00086 
00087 int16_t sensirion_i2c_read_words_as_bytes(uint8_t address, uint8_t* data,
00088                                           uint16_t num_words) {
00089     int16_t ret;
00090     uint16_t i, j;
00091     uint16_t size = num_words * (SENSIRION_WORD_SIZE + CRC8_LEN);
00092     uint16_t word_buf[SENSIRION_MAX_BUFFER_WORDS];
00093     uint8_t* const buf8 = (uint8_t*)word_buf;
00094 
00095     ret = sensirion_i2c_hal_read(address, buf8, size);
00096     if (ret != NO_ERROR)
00097         return ret;
00098 
00099     /* check the CRC for each word */
00100     for (i = 0, j = 0; i < size; i += SENSIRION_WORD_SIZE + CRC8_LEN) {
00101 
00102         ret = sensirion_i2c_check_crc(&buf8[i], SENSIRION_WORD_SIZE,
00103                                       buf8[i + SENSIRION_WORD_SIZE]);
00104         if (ret != NO_ERROR)
00105             return ret;
00106 
00107         data[j++] = buf8[i];
00108         data[j++] = buf8[i + 1];
00109     }
00110 
00111     return NO_ERROR;
00112 }
00113 
00114 int16_t sensirion_i2c_read_words(uint8_t address, uint16_t* data_words,
00115                                  uint16_t num_words) {
00116     int16_t ret;
00117     uint8_t i;
00118 
00119     ret = sensirion_i2c_read_words_as_bytes(address, (uint8_t*)data_words,
00120                                             num_words);
00121     if (ret != NO_ERROR)
00122         return ret;
00123 
00124     for (i = 0; i < num_words; ++i) {
00125         const uint8_t* word_bytes = (uint8_t*)&data_words[i];
00126         data_words[i] = ((uint16_t)word_bytes[0] << 8) | word_bytes[1];
00127     }
00128 
00129     return NO_ERROR;
00130 }
00131 
00132 int16_t sensirion_i2c_write_cmd(uint8_t address, uint16_t command) {
00133     uint8_t buf[SENSIRION_COMMAND_SIZE];
00134 
00135     sensirion_i2c_fill_cmd_send_buf(buf, command, NULL, 0);
00136     return sensirion_i2c_hal_write(address, buf, SENSIRION_COMMAND_SIZE);
00137 }
00138 
00139 int16_t sensirion_i2c_write_cmd_with_args(uint8_t address, uint16_t command,
00140                                           const uint16_t* data_words,
00141                                           uint16_t num_words) {
00142     uint8_t buf[SENSIRION_MAX_BUFFER_WORDS];
00143     uint16_t buf_size;
00144 
00145     buf_size =
00146         sensirion_i2c_fill_cmd_send_buf(buf, command, data_words, num_words);
00147     return sensirion_i2c_hal_write(address, buf, buf_size);
00148 }
00149 
00150 int16_t sensirion_i2c_delayed_read_cmd(uint8_t address, uint16_t cmd,
00151                                        uint32_t delay_us, uint16_t* data_words,
00152                                        uint16_t num_words) {
00153     int16_t ret;
00154     uint8_t buf[SENSIRION_COMMAND_SIZE];
00155 
00156     sensirion_i2c_fill_cmd_send_buf(buf, cmd, NULL, 0);
00157     ret = sensirion_i2c_hal_write(address, buf, SENSIRION_COMMAND_SIZE);
00158     if (ret != NO_ERROR)
00159         return ret;
00160 
00161     if (delay_us)
00162         sensirion_i2c_hal_sleep_usec(delay_us);
00163 
00164     return sensirion_i2c_read_words(address, data_words, num_words);
00165 }
00166 
00167 int16_t sensirion_i2c_read_cmd(uint8_t address, uint16_t cmd,
00168                                uint16_t* data_words, uint16_t num_words) {
00169     return sensirion_i2c_delayed_read_cmd(address, cmd, 0, data_words,
00170                                           num_words);
00171 }
00172 
00173 uint16_t sensirion_i2c_add_command_to_buffer(uint8_t* buffer, uint16_t offset,
00174                                              uint16_t command) {
00175     buffer[offset++] = (uint8_t)((command & 0xFF00) >> 8);
00176     buffer[offset++] = (uint8_t)((command & 0x00FF) >> 0);
00177     return offset;
00178 }
00179 
00180 uint16_t sensirion_i2c_add_uint32_t_to_buffer(uint8_t* buffer, uint16_t offset,
00181                                               uint32_t data) {
00182     buffer[offset++] = (uint8_t)((data & 0xFF000000) >> 24);
00183     buffer[offset++] = (uint8_t)((data & 0x00FF0000) >> 16);
00184     buffer[offset] = sensirion_i2c_generate_crc(
00185         &buffer[offset - SENSIRION_WORD_SIZE], SENSIRION_WORD_SIZE);
00186     offset++;
00187     buffer[offset++] = (uint8_t)((data & 0x0000FF00) >> 8);
00188     buffer[offset++] = (uint8_t)((data & 0x000000FF) >> 0);
00189     buffer[offset] = sensirion_i2c_generate_crc(
00190         &buffer[offset - SENSIRION_WORD_SIZE], SENSIRION_WORD_SIZE);
00191     offset++;
00192 
00193     return offset;
00194 }
00195 
00196 uint16_t sensirion_i2c_add_int32_t_to_buffer(uint8_t* buffer, uint16_t offset,
00197                                              int32_t data) {
00198     return sensirion_i2c_add_uint32_t_to_buffer(buffer, offset, (uint32_t)data);
00199 }
00200 
00201 uint16_t sensirion_i2c_add_uint16_t_to_buffer(uint8_t* buffer, uint16_t offset,
00202                                               uint16_t data) {
00203     buffer[offset++] = (uint8_t)((data & 0xFF00) >> 8);
00204     buffer[offset++] = (uint8_t)((data & 0x00FF) >> 0);
00205     buffer[offset] = sensirion_i2c_generate_crc(
00206         &buffer[offset - SENSIRION_WORD_SIZE], SENSIRION_WORD_SIZE);
00207     offset++;
00208 
00209     return offset;
00210 }
00211 
00212 uint16_t sensirion_i2c_add_int16_t_to_buffer(uint8_t* buffer, uint16_t offset,
00213                                              int16_t data) {
00214     return sensirion_i2c_add_uint16_t_to_buffer(buffer, offset, (uint16_t)data);
00215 }
00216 
00217 uint16_t sensirion_i2c_add_float_to_buffer(uint8_t* buffer, uint16_t offset,
00218                                            float data) {
00219     union {
00220         uint32_t uint32_data;
00221         float float_data;
00222     } convert;
00223 
00224     convert.float_data = data;
00225 
00226     buffer[offset++] = (uint8_t)((convert.uint32_data & 0xFF000000) >> 24);
00227     buffer[offset++] = (uint8_t)((convert.uint32_data & 0x00FF0000) >> 16);
00228     buffer[offset] = sensirion_i2c_generate_crc(
00229         &buffer[offset - SENSIRION_WORD_SIZE], SENSIRION_WORD_SIZE);
00230     offset++;
00231     buffer[offset++] = (uint8_t)((convert.uint32_data & 0x0000FF00) >> 8);
00232     buffer[offset++] = (uint8_t)((convert.uint32_data & 0x000000FF) >> 0);
00233     buffer[offset] = sensirion_i2c_generate_crc(
00234         &buffer[offset - SENSIRION_WORD_SIZE], SENSIRION_WORD_SIZE);
00235     offset++;
00236 
00237     return offset;
00238 }
00239 
00240 uint16_t sensirion_i2c_add_bytes_to_buffer(uint8_t* buffer, uint16_t offset,
00241                                            uint8_t* data,
00242                                            uint16_t data_length) {
00243     uint16_t i;
00244 
00245     if (data_length % SENSIRION_WORD_SIZE != 0) {
00246         return BYTE_NUM_ERROR;
00247     }
00248 
00249     for (i = 0; i < data_length; i += 2) {
00250         buffer[offset++] = data[i];
00251         buffer[offset++] = data[i + 1];
00252 
00253         buffer[offset] = sensirion_i2c_generate_crc(
00254             &buffer[offset - SENSIRION_WORD_SIZE], SENSIRION_WORD_SIZE);
00255         offset++;
00256     }
00257 
00258     return offset;
00259 }
00260 
00261 int16_t sensirion_i2c_write_data(uint8_t address, const uint8_t* data,
00262                                  uint16_t data_length) {
00263     return sensirion_i2c_hal_write(address, data, data_length);
00264 }
00265 
00266 int16_t sensirion_i2c_read_data_inplace(uint8_t address, uint8_t* buffer,
00267                                         uint16_t expected_data_length) {
00268     int16_t error;
00269     uint16_t i, j;
00270     uint16_t size = (expected_data_length / SENSIRION_WORD_SIZE) *
00271                     (SENSIRION_WORD_SIZE + CRC8_LEN);
00272 
00273     if (expected_data_length % SENSIRION_WORD_SIZE != 0) {
00274         return BYTE_NUM_ERROR;
00275     }
00276 
00277     error = sensirion_i2c_hal_read(address, buffer, size);
00278     if (error) {
00279         return error;
00280     }
00281 
00282     for (i = 0, j = 0; i < size; i += SENSIRION_WORD_SIZE + CRC8_LEN) {
00283 
00284         error = sensirion_i2c_check_crc(&buffer[i], SENSIRION_WORD_SIZE,
00285                                         buffer[i + SENSIRION_WORD_SIZE]);
00286         if (error) {
00287             return error;
00288         }
00289         buffer[j++] = buffer[i];
00290         buffer[j++] = buffer[i + 1];
00291     }
00292 
00293     return NO_ERROR;
00294 }