Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
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 }
Generated on Sat Aug 6 2022 14:17:29 by
