Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
invensense2.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2022 Freek van Tienen <freek.v.tienen@gmail.com>
3 *
4 * This file is part of paparazzi.
5 *
6 * paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, write to
18 * the Free Software Foundation, 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
31#include "math/pprz_isa.h"
33#include "modules/imu/imu.h"
34#include "modules/core/abi.h"
35#include "mcu_periph/gpio_arch.h"
36
37
38/* Local functions */
39static void invensense2_parse_data(struct invensense2_t *inv, volatile uint8_t *data, uint16_t len);
40static void invensense2_fix_config(struct invensense2_t *inv);
44static bool invensense2_config(struct invensense2_t *inv);
45
46/* Default gyro scalings */
47static const struct Int32Rates invensense2_gyro_scale[5][2] = {
48 { {30267, 30267, 30267},
49 {55463, 55463, 55463} }, // 250DPS
50 { {60534, 60534, 60534},
51 {55463, 55463, 55463} }, // 500DPS
52 { {40147, 40147, 40147},
53 {18420, 18420, 18420} }, // 1000DPS
54 { {40147, 40147, 40147},
55 {9210, 9210, 9210} }, // 2000DPS
56 { {40147, 40147, 40147},
57 {4605, 4605, 4605} } // 4000DPS
58};
59
60/* Default accel scalings */
61static const struct Int32Vect3 invensense2_accel_scale[5][2] = {
62 { {3189, 3189, 3189},
63 {5203, 5203, 5203} }, // 2G
64 { {6378, 6378, 6378},
65 {5203, 5203, 5203} }, // 4G
66 { {12756, 12756, 12756},
67 {5203, 5203, 5203} }, // 8G
68 { {25512, 25512, 25512},
69 {5203, 5203, 5203} }, // 16G
70 { {51024, 51024, 51024},
71 {5203, 5203, 5203} } // 30G
72};
73
80 /* General setup */
81 inv->status = INVENSENSE2_IDLE;
82 inv->device = INVENSENSE2_UNKOWN;
83 inv->register_bank = 0xFF;
84 inv->config_idx = 0;
85
86 /* SPI setup */
87 if(inv->bus == INVENSENSE2_SPI) {
88 inv->spi.trans.cpol = SPICpolIdleHigh;
89 inv->spi.trans.cpha = SPICphaEdge2;
90 inv->spi.trans.dss = SPIDss8bit;
91 inv->spi.trans.bitorder = SPIMSBFirst;
92 inv->spi.trans.cdiv = SPIDiv16;
93
94 inv->spi.trans.select = SPISelectUnselect;
95 inv->spi.trans.slave_idx = inv->spi.slave_idx;
96 inv->spi.trans.output_length = 0;
97 inv->spi.trans.input_length = 0;
98 inv->spi.trans.before_cb = NULL;
99 inv->spi.trans.after_cb = NULL;
100 inv->spi.trans.input_buf = inv->spi.rx_buf;
101 inv->spi.trans.output_buf = inv->spi.tx_buf;
102 inv->spi.trans.status = SPITransDone;
103 }
104 /* I2C setup */
105 else {
106 inv->i2c.trans.slave_addr = inv->i2c.slave_addr;
107 inv->i2c.trans.status = I2CTransDone;
108 }
109}
110
120 /* Idle */
121 if((inv->bus == INVENSENSE2_SPI && inv->spi.trans.status == SPITransDone) ||
122 (inv->bus == INVENSENSE2_I2C && inv->i2c.trans.status == I2CTransDone)) {
123
124 /* Depending on the status choose what to do */
125 switch(inv->status) {
126 case INVENSENSE2_IDLE:
127 /* Request WHO_AM_I */
129 break;
131 /* Start configuring */
133 inv->status = INVENSENSE2_RUNNING;
134 }
135 break;
137 /* Request a sensor reading */
139 break;
140 }
141 }
142}
143
153 volatile uint8_t *rx_buffer, *tx_buffer;
154 uint16_t rx_length = 0;
155
156 /* Set the buffers depending on the interface */
157 if(inv->bus == INVENSENSE2_SPI) {
158 rx_buffer = inv->spi.rx_buf;
159 tx_buffer = inv->spi.tx_buf;
160 rx_length = inv->spi.trans.input_length;
161 }
162 else {
163 rx_buffer = inv->i2c.trans.buf;
164 tx_buffer = inv->i2c.trans.buf;
165 rx_length = inv->i2c.trans.len_r;
166 }
167
168 /* Successful transfer */
169 if((inv->bus == INVENSENSE2_SPI && inv->spi.trans.status == SPITransSuccess) ||
170 (inv->bus == INVENSENSE2_I2C && inv->i2c.trans.status == I2CTransSuccess)) {
171
172 /* Update the register bank */
173 if(tx_buffer[0] == INV2REG_BANK_SEL)
174 inv->register_bank = inv->spi.tx_buf[1] >> 4;
175
176 /* Set the transaction as done and update register bank if needed */
177 if(inv->bus == INVENSENSE2_SPI)
178 inv->spi.trans.status = SPITransDone;
179 else
180 inv->i2c.trans.status = I2CTransDone;
181
182 /* Look at the results */
183 switch(inv->status) {
184 case INVENSENSE2_IDLE:
185 /* Check the response of the WHO_AM_I */
186 if(rx_buffer[1] == INV2_WHOAMI_ICM20648) {
187 inv->device = INVENSENSE2_ICM20648;
188 inv->status = INVENSENSE2_CONFIG;
189 } else if(rx_buffer[1] == INV2_WHOAMI_ICM20649) {
190 inv->device = INVENSENSE2_ICM20649;
191 inv->status = INVENSENSE2_CONFIG;
192 } else if(rx_buffer[1] == INV2_WHOAMI_ICM20948) {
193 inv->device = INVENSENSE2_ICM20948;
194 inv->status = INVENSENSE2_CONFIG;
195 }
196
197 /* Fix the configuration and set the scaling */
198 if(inv->status == INVENSENSE2_CONFIG)
200 break;
202 /* Apply the next configuration register */
204 inv->status = INVENSENSE2_RUNNING;
205 }
206 break;
207 case INVENSENSE2_RUNNING: {
208 /* Parse the results */
209 static const uint16_t max_bytes = sizeof(inv->spi.rx_buf) - 3;
210 uint16_t fifo_bytes = (uint16_t)rx_buffer[1] << 8 | rx_buffer[2];
211
212 // We read an incorrect length (try again)
213 if(fifo_bytes > 4096) {
215 return;
216 }
217
218 // Parse the data
219 if((rx_length - 3) > 0) {
220 uint16_t valid_bytes = ((rx_length - 3) < fifo_bytes)? (rx_length - 3) : fifo_bytes;
221 invensense2_parse_data(inv, &rx_buffer[3], valid_bytes);
222 inv->timer -= valid_bytes;
223 } else {
225 inv->timer = fifo_bytes;
226 }
227
228 // If we have more data request more
229 if(inv->timer > 0) {
230 uint16_t read_bytes = (inv->timer > max_bytes)? max_bytes : inv->timer;
232 }
233 break;
234 }
235 }
236 }
237 /* Failed transaction */
238 if((inv->bus == INVENSENSE2_SPI && inv->spi.trans.status == SPITransFailed) ||
239 (inv->bus == INVENSENSE2_I2C && inv->i2c.trans.status == I2CTransFailed)) {
240
241 /* Set the transaction as done and update register bank if needed */
242 if(inv->bus == INVENSENSE2_SPI) {
243 inv->spi.trans.status = SPITransDone;
244 }
245 else {
246 inv->i2c.trans.status = I2CTransDone;
247 }
248
249 /* Retry or ignore */
250 switch(inv->status) {
252 /* If was not a bus switch decrease the index */
253 if(inv->config_idx > 0 && ((inv->bus == INVENSENSE2_SPI && inv->spi.tx_buf[0] != INV2REG_BANK_SEL) ||
254 (inv->bus == INVENSENSE2_I2C && inv->i2c.trans.buf[0] != INV2REG_BANK_SEL))) {
255 inv->config_idx--;
256 }
257 /* Try again */
259 inv->status = INVENSENSE2_RUNNING;
260 }
261 break;
262 case INVENSENSE2_IDLE:
264 /* Ignore while idle/running */
265 break;
266 }
267 }
268}
269
277static void invensense2_parse_data(struct invensense2_t *inv, volatile uint8_t *data, uint16_t len) {
279 static struct Int32Vect3 accel[INVENSENSE2_SAMPLE_CNT] = {0};
280 static struct Int32Rates gyro[INVENSENSE2_SAMPLE_CNT] = {0};
281
284
285 uint16_t gyro_samplerate = 9000;
286 if(inv->gyro_dlpf != INVENSENSE2_GYRO_DLPF_OFF)
287 gyro_samplerate = 1125;
288
289 uint16_t accel_samplerate = 4500;
290 if(inv->accel_dlpf != INVENSENSE2_ACCEL_DLPF_OFF)
291 accel_samplerate = 1125;
292
293 // Go through the different samples
294 uint8_t j = 0;
295 uint8_t downsample = gyro_samplerate / accel_samplerate;
296 int32_t temp = 0;
297 for(uint8_t i = 0; i < samples; i++) {
298 if(i % downsample == 0) {
299 accel[j].x = (int16_t)((uint16_t)data[2] << 8 | data[3]);
300 accel[j].y = (int16_t)((uint16_t)data[0] << 8 | data[1]);
301 accel[j].z = -(int16_t)((uint16_t)data[4] << 8 | data[5]);
302 j++;
303 }
304
305 gyro[i].p = (int16_t)((uint16_t)data[8] << 8 | data[9]);
306 gyro[i].q = (int16_t)((uint16_t)data[6] << 8 | data[7]);
307 gyro[i].r = -(int16_t)((uint16_t)data[10] << 8 | data[11]);
308
309 temp += (int16_t)((uint16_t)data[12] << 8 | data[13]);
311 }
312
313 float temp_f = ((float)temp / samples) / 333.87f + 21.f;
314
315 // Send the scaled values over ABI
317 AbiSendMsgIMU_GYRO_RAW(inv->abi_id, now_ts, gyro, samples, gyro_samplerate*(1+inv->timebase_correction_pll/100.f), temp_f);
318 AbiSendMsgIMU_ACCEL_RAW(inv->abi_id, now_ts, accel, j, accel_samplerate*(1+inv->timebase_correction_pll/100.f), temp_f);
319}
320
327 /* Fix wrong configuration settings (prevent user error) */
328 if(inv->device == INVENSENSE2_ICM20649) {
329 if(inv->gyro_range == INVENSENSE2_GYRO_RANGE_250DPS)
331 if(inv->accel_range == INVENSENSE2_ACCEL_RANGE_2G)
332 inv->accel_range = INVENSENSE2_ACCEL_RANGE_4G;
333 }
334 else {
335 if(inv->gyro_range == INVENSENSE2_GYRO_RANGE_4000DPS)
337 if(inv->accel_range == INVENSENSE2_ACCEL_RANGE_30G)
338 inv->accel_range = INVENSENSE2_ACCEL_RANGE_16G;
339 }
340
341 /* Set the default values */
344}
345
356 /* Split the register and bank */
357 uint8_t bank = bank_reg >> 8;
358 uint8_t reg = bank_reg & 0xFF;
359
360 /* Switch the register bank if needed */
362 return false;
363 }
364
365 /* SPI transaction */
366 if(inv->bus == INVENSENSE2_SPI) {
367 inv->spi.trans.output_length = 2;
368 inv->spi.trans.input_length = 0;
369 inv->spi.tx_buf[0] = reg;
370 inv->spi.tx_buf[1] = value;
371 spi_submit(inv->spi.p, &(inv->spi.trans));
372 }
373 /* I2C transaction */
374 else {
375 inv->i2c.trans.buf[0] = reg;
376 inv->i2c.trans.buf[1] = value;
377 i2c_transmit(inv->i2c.p, &(inv->i2c.trans), inv->i2c.slave_addr, 2);
378 }
379
380 return true;
381}
382
393 /* Split the register and bank */
394 uint8_t bank = bank_reg >> 8;
395 uint8_t reg = bank_reg & 0xFF;
396
397 /* Switch the register bank if needed */
399 return false;
400 }
401
402 /* SPI transaction */
403 if(inv->bus == INVENSENSE2_SPI) {
404 inv->spi.trans.output_length = 2;
405 inv->spi.trans.input_length = 1 + size;
406 inv->spi.tx_buf[0] = reg | INV2_READ_FLAG;
407 inv->spi.tx_buf[1] = 0;
408 spi_submit(inv->spi.p, &(inv->spi.trans));
409 }
410 /* I2C transaction */
411 else {
412 inv->i2c.trans.buf[0] = reg | INV2_READ_FLAG;
413 i2c_transceive(inv->i2c.p, &(inv->i2c.trans), inv->i2c.slave_addr, 1, (1 + size));
414 }
415
416 return true;
417}
418
428 /* If we already selected the correct bank continue */
429 if(inv->register_bank == bank)
430 return false;
431
432 /* SPI transaction */
433 if(inv->bus == INVENSENSE2_SPI) {
434 inv->spi.trans.output_length = 2;
435 inv->spi.trans.input_length = 0;
436 inv->spi.tx_buf[0] = INV2REG_BANK_SEL;
437 inv->spi.tx_buf[1] = bank << 4;
438 spi_submit(inv->spi.p, &(inv->spi.trans));
439 }
440 /* I2C transaction */
441 else {
442 inv->i2c.trans.buf[0] = INV2REG_BANK_SEL;
443 inv->i2c.trans.buf[1] = bank << 4;
444 i2c_transmit(inv->i2c.p, &(inv->i2c.trans), inv->i2c.slave_addr, 2);
445 }
446
447 return true;
448}
449
458 switch(inv->config_idx) {
459 case 0:
460 /* Reset the device */
462 inv->config_idx++;
463 inv->timer = get_sys_time_usec();
464 break;
465 case 1: {
466 /* Reset I2C and FIFO SRAM, disable I2C if using SPI */
468 if(inv->bus == INVENSENSE2_SPI)
470
471 /* Because reset takes time wait ~100ms */
472 if((get_sys_time_usec() - inv->timer) < 100000)
473 break;
474
476 inv->config_idx++;
477 break;
478 }
479 case 2:
480 /* Wakeup the device in auto clock mode */
482 inv->config_idx++;
483 inv->timer = get_sys_time_usec();
484 break;
485 case 3: {
486 /* Configure gyro */
488 if(inv->gyro_dlpf != INVENSENSE2_GYRO_DLPF_OFF)
489 gyro_config |= BIT_GYRO_DLPF_ENABLE | ((inv->gyro_dlpf - 1) << GYRO_DLPF_CFG_SHIFT);
490 if((inv->device == INVENSENSE2_ICM20649 && inv->gyro_range > 0) || inv->gyro_range > 3)
491 gyro_config |= (inv->gyro_range - 1) << GYRO_FS_SEL_SHIFT;
492 else
493 gyro_config |= inv->gyro_range << GYRO_FS_SEL_SHIFT;
494
495 /* Because reset takes time wait ~100ms */
496 if((get_sys_time_usec() - inv->timer) < 100000)
497 break;
498
500 inv->config_idx++;
501 break;
502 }
503 case 4: {
504 /* Configure accelerometer */
506 if(inv->accel_dlpf != INVENSENSE2_ACCEL_DLPF_OFF)
508 if((inv->device == INVENSENSE2_ICM20649 && inv->accel_range > 0) || inv->accel_range > 3)
509 accel_config |= (inv->accel_range - 1) << ACCEL_FS_SEL_SHIFT;
510 else
511 accel_config |= inv->accel_range << ACCEL_FS_SEL_SHIFT;
513 inv->config_idx++;
514 break;
515 }
516 case 5:
517 /* Request TIMEBASE_CORRECTION_PLL */
519 inv->config_idx++;
520 break;
521 case 6:
522 /* Read the TIMEBASE_CORRECTION_PLL */
523 if(inv->bus == INVENSENSE2_SPI) {
524 inv->timebase_correction_pll = ((int8_t)inv->spi.rx_buf[1]) * 0.079f;
525 }
526 else {
527 inv->timebase_correction_pll = ((int8_t)inv->i2c.trans.buf[1]) * 0.079f;
528 }
529
530 /* Set the FIFO mode */
532 inv->config_idx++;
533 break;
534 case 7:
535 /* Set the GYRO sample rate divider */
537 inv->config_idx++;
538 break;
539 case 8:
540 /* FIFO reset 1 */
542 inv->config_idx++;
543 break;
544 case 9:
545 /* FIFO reset 2 */
547 inv->config_idx++;
548 break;
549 case 10: {
550 /* Enable FIFO */
552 if(inv->bus == INVENSENSE2_SPI)
555 inv->config_idx++;
556 break;
557 }
558 case 11:
559 /* Cofigure FIFO enable */
562 inv->config_idx++;
563 break;
564 case 12:
565 /* Enable interrupt pin/status */
567 inv->config_idx++;
568 break;
569 default:
570 inv->timer = 0;
571 return true;
572 }
573 return false;
574}
Main include for ABI (AirBorneInterface).
uint32_t get_sys_time_usec(void)
Get the time in microseconds since startup.
bool i2c_transmit(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint8_t len)
Submit a write only transaction.
Definition i2c.c:324
bool i2c_transceive(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint8_t len_w, uint16_t len_r)
Submit a write/read transaction.
Definition i2c.c:344
@ I2CTransSuccess
transaction successfully finished by I2C driver
Definition i2c.h:57
@ I2CTransFailed
transaction failed
Definition i2c.h:58
@ I2CTransDone
transaction set to done by user level
Definition i2c.h:59
int32_t p
in rad/s with INT32_RATE_FRAC
int32_t r
in rad/s with INT32_RATE_FRAC
int32_t q
in rad/s with INT32_RATE_FRAC
angular rates
bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit SPI transaction.
Definition spi_arch.c:533
@ SPICphaEdge2
CPHA = 1.
Definition spi.h:75
@ SPITransFailed
Definition spi.h:100
@ SPITransSuccess
Definition spi.h:99
@ SPITransDone
Definition spi.h:101
@ SPICpolIdleHigh
CPOL = 1.
Definition spi.h:84
@ SPISelectUnselect
slave is selected before transaction and unselected after
Definition spi.h:63
@ SPIMSBFirst
Definition spi.h:112
@ SPIDiv16
Definition spi.h:123
@ SPIDss8bit
Definition spi.h:90
void imu_set_defaults_accel(uint8_t abi_id, const struct Int32RMat *imu_to_sensor, const struct Int32Vect3 *neutral, const struct Int32Vect3 *scale)
Set the defaults for a accel sensor WARNING: Should be called before sensor is publishing messages to...
Definition imu.c:610
void imu_set_defaults_gyro(uint8_t abi_id, const struct Int32RMat *imu_to_sensor, const struct Int32Rates *neutral, const struct Int32Rates *scale)
Set the defaults for a gyro sensor WARNING: Should be called before sensor is publishing messages to ...
Definition imu.c:580
Inertial Measurement Unit interface.
static const struct Int32Rates invensense2_gyro_scale[5][2]
Definition invensense2.c:47
static bool invensense2_select_bank(struct invensense2_t *inv, uint8_t bank)
Select the correct register bank.
static bool invensense2_register_write(struct invensense2_t *inv, uint16_t bank_reg, uint8_t value)
Write a register based on a combined bank/regsiter value.
void invensense2_event(struct invensense2_t *inv)
Should be called in the event thread.
static void invensense2_parse_data(struct invensense2_t *inv, volatile uint8_t *data, uint16_t len)
Parse the FIFO buffer data.
void invensense2_periodic(struct invensense2_t *inv)
Should be called periodically to request sensor readings.
static bool invensense2_config(struct invensense2_t *inv)
Configure the Invensense 2 device register by register.
static void invensense2_fix_config(struct invensense2_t *inv)
This fixes the configuration errors and sets the correct scalings.
static bool invensense2_register_read(struct invensense2_t *inv, uint16_t bank_reg, uint16_t size)
Read a register based on a combined bank/regsiter value.
void invensense2_init(struct invensense2_t *inv)
Initialize the invensense v2 sensor instance.
Definition invensense2.c:79
static const struct Int32Vect3 invensense2_accel_scale[5][2]
Definition invensense2.c:61
Driver for the Invensense V2 IMUs ICM20948, ICM20648 and ICM20649.
@ INVENSENSE2_GYRO_DLPF_OFF
Definition invensense2.h:81
@ INVENSENSE2_RUNNING
Definition invensense2.h:68
@ INVENSENSE2_IDLE
Definition invensense2.h:66
@ INVENSENSE2_CONFIG
Definition invensense2.h:67
@ INVENSENSE2_GYRO_RANGE_4000DPS
Only possible for ICM20649.
Definition invensense2.h:98
@ INVENSENSE2_GYRO_RANGE_500DPS
Definition invensense2.h:95
@ INVENSENSE2_GYRO_RANGE_2000DPS
Definition invensense2.h:97
@ INVENSENSE2_GYRO_RANGE_250DPS
Not possible for ICM20649.
Definition invensense2.h:94
@ INVENSENSE2_ACCEL_RANGE_2G
Not possible for ICM20649.
@ INVENSENSE2_ACCEL_RANGE_16G
@ INVENSENSE2_ACCEL_RANGE_4G
@ INVENSENSE2_ACCEL_RANGE_30G
Only possible for ICM20649.
@ INVENSENSE2_ACCEL_DLPF_OFF
@ INVENSENSE2_ICM20648
Definition invensense2.h:74
@ INVENSENSE2_ICM20649
Definition invensense2.h:75
@ INVENSENSE2_UNKOWN
Definition invensense2.h:73
@ INVENSENSE2_ICM20948
Definition invensense2.h:76
#define INVENSENSE2_SAMPLE_CNT
Definition invensense2.h:37
#define INVENSENSE2_SAMPLE_SIZE
Definition invensense2.h:38
@ INVENSENSE2_I2C
Definition invensense2.h:61
@ INVENSENSE2_SPI
Definition invensense2.h:60
Register and address definitions for the Invensense V2 from ardupilot.
#define GYRO_FS_SEL_SHIFT
#define BIT_USER_CTRL_FIFO_EN
#define INV2REG_INT_ENABLE_1
#define BIT_ZG_FIFO_EN
#define INV2REG_FIFO_COUNTH
#define BIT_PWR_MGMT_1_CLK_AUTO
#define BIT_YG_FIFO_EN
#define INV2_WHOAMI_ICM20948
#define BIT_ACCEL_DLPF_ENABLE
#define INV2_WHOAMI_ICM20648
#define ACCEL_DLPF_CFG_SHIFT
#define INV2REG_ACCEL_CONFIG
#define BIT_USER_CTRL_I2C_IF_DIS
#define INV2REG_PWR_MGMT_1
#define BIT_USER_CTRL_I2C_MST_RESET
#define INV2REG_GYRO_CONFIG_1
#define INV2REG_TIMEBASE_CORRECTIO
#define INV2REG_WHO_AM_I
#define INV2REG_FIFO_MODE
#define INV2REG_FIFO_EN_2
#define BIT_XG_FIFO_EN
#define INV2REG_USER_CTRL
#define ACCEL_FS_SEL_SHIFT
#define GYRO_DLPF_CFG_SHIFT
#define BIT_USER_CTRL_SRAM_RESET
#define BIT_ACCEL_FIFO_EN
#define INV2REG_BANK_SEL
#define INV2REG_GYRO_SMPLRT_DIV
#define BIT_TEMP_FIFO_EN
#define INV2REG_FIFO_RST
#define BIT_GYRO_DLPF_ENABLE
#define INV2_READ_FLAG
#define BIT_PWR_MGMT_1_DEVICE_RESET
#define INV2_WHOAMI_ICM20649
uint16_t foo
Definition main_demo5.c:58
Paparazzi fixed point algebra.
Paparazzi atmospheric pressure conversion utilities.
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
int int32_t
Typedef defining 32 bit int type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
short int16_t
Typedef defining 16 bit short type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
signed char int8_t
Typedef defining 8 bit char type.