Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
invensense3.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"
34#include "modules/imu/imu.h"
35#include "modules/core/abi.h"
36#include "mcu_periph/gpio_arch.h"
37#include "std.h"
38
39/* Local functions */
41static void invensense3_parse_reg_data(struct invensense3_t *inv, uint8_t *data);
42static void invensense3_fix_config(struct invensense3_t *inv);
46static bool invensense3_config(struct invensense3_t *inv);
47static bool invensense3_reset_fifo(struct invensense3_t *inv);
48static int samples_from_odr(int odr);
49
50/* Default gyro scalings */
51static const struct FloatRates invensense3_gyro_scale_f[8] = {
52 {4.36332, 4.36332, 4.36332}, // 2000DPS
53 {2.18166, 2.18166, 2.18166}, // 1000DPS
54 {1.09083, 1.09083, 1.09083}, // 500DPS
55 {0.545415, 0.545415, 0.545415}, // 250DPS: RATE_BFP_OF_REAL(radians(250)/(2**15))
56 {0.272707, 0.272707, 0.272707}, // 125DPS
57 {0.136353, 0.136353, 0.136353}, // 62.5DPS
58 {0.0681769, 0.0681769, 0.0681769}, // 31.25DPS
59 {0.0340884, 0.0340884, 0.0340884}, // 15.625DPS
60};
61
62/* Default accel scalings */
63static const struct FloatVect3 invensense3_accel_scale_f[5] = {
64 {9.81, 9.81, 9.81}, // 32G
65 {4.905, 4.905, 4.905}, // 16G
66 {2.4525, 2.4525, 2.4525}, // 8G
67 {1.22583, 1.22583, 1.22583}, // 4G
68 {0.61312, 0.61312, 0.61312}, // 2G: ACCEL_BFP_OF_REAL(2G*9.81/(2**15))
69};
70
71/* AAF settings (3dB Bandwidth [Hz], AAF_DELT, AAF_DELTSQR, AAF_BITSHIFT) */
72static const uint16_t invensense3_aaf[][4] = {
73 {42, 1, 1, 15},
74 {84, 2, 4, 13},
75 {126, 3, 9, 12},
76 {170, 4, 16, 11},
77 {213, 5, 25, 10},
78 {258, 6, 36, 10},
79 {303, 7, 49, 9},
80 {348, 8, 64, 9},
81 {394, 9, 81, 9},
82 {441, 10, 100, 8},
83 {488, 11, 122, 8},
84 {536, 12, 144, 8},
85 {585, 13, 170, 8},
86 {634, 14, 196, 7},
87 {684, 15, 224, 7},
88 {734, 16, 256, 7},
89 {785, 17, 288, 7},
90 {837, 18, 324, 7},
91 {890, 19, 360, 6},
92 {943, 20, 400, 6},
93 {997, 21, 440, 6},
94 {1051, 22, 488, 6},
95 {1107, 23, 528, 6},
96 {1163, 24, 576, 6},
97 {1220, 25, 624, 6},
98 {1277, 26, 680, 6},
99 {1336, 27, 736, 5},
100 {1395, 28, 784, 5},
101 {1454, 29, 848, 5},
102 {1515, 30, 896, 5},
103 {1577, 31, 960, 5},
104 {1639, 32, 1024, 5},
105 {1702, 33, 1088, 5},
106 {1766, 34, 1152, 5},
107 {1830, 35, 1232, 5},
108 {1896, 36, 1296, 5},
109 {1962, 37, 1376, 4},
110 {2029, 38, 1440, 4},
111 {2097, 39, 1536, 4},
112 {2166, 40, 1600, 4},
113 {2235, 41, 1696, 4},
114 {2306, 42, 1760, 4},
115 {2377, 43, 1856, 4},
116 {2449, 44, 1952, 4},
117 {2522, 45, 2016, 4},
118 {2596, 46, 2112, 4},
119 {2671, 47, 2208, 4},
120 {2746, 48, 2304, 4},
121 {2823, 49, 2400, 4},
122 {2900, 50, 2496, 4},
123 {2978, 51, 2592, 4},
124 {3057, 52, 2720, 4},
125 {3137, 53, 2816, 3},
126 {3217, 54, 2944, 3},
127 {3299, 55, 3008, 3},
128 {3381, 56, 3136, 3},
129 {3464, 57, 3264, 3},
130 {3548, 58, 3392, 3},
131 {3633, 59, 3456, 3},
132 {3718, 60, 3584, 3},
133 {3805, 61, 3712, 3},
134 {3892, 62, 3840, 3},
135 {3979, 63, 3968, 3}
136};
137
138static const uint16_t invensense3_aaf4x605[][4] = {
139 {10, 1, 1, 15},
140 {21, 2, 4, 13},
141 {32, 3, 9, 12},
142 {42, 4, 16, 11},
143 {53, 5, 25, 10},
144 {64, 6, 36, 10},
145 {76, 7, 49, 9},
146 {87, 8, 64, 9},
147 {99, 9, 81, 9},
148 {110, 10, 100, 8},
149 {122, 11, 122, 8},
150 {134, 12, 144, 8},
151 {146, 13, 170, 8},
152 {158, 14, 196, 7},
153 {171, 15, 224, 7},
154 {184, 16, 256, 7},
155 {196, 17, 288, 7},
156 {209, 18, 324, 7},
157 {222, 19, 360, 6},
158 {236, 20, 400, 6},
159 {249, 21, 440, 6},
160 {263, 22, 488, 6},
161 {277, 23, 528, 6},
162 {291, 24, 576, 6},
163 {305, 25, 624, 6},
164 {319, 26, 680, 6},
165 {334, 27, 736, 5},
166 {349, 28, 784, 5},
167 {364, 29, 848, 5},
168 {379, 30, 896, 5},
169 {394, 31, 960, 5},
170 {410, 32, 1024, 5},
171 {425, 33, 1088, 5},
172 {441, 34, 1152, 5},
173 {458, 35, 1232, 5},
174 {474, 36, 1296, 5},
175 {490, 37, 1376, 4},
176 {507, 38, 1440, 4},
177 {524, 39, 1536, 4},
178 {541, 40, 1600, 4},
179 {559, 41, 1696, 4},
180 {576, 42, 1760, 4},
181 {594, 43, 1856, 4},
182 {612, 44, 1952, 4},
183 {631, 45, 2016, 4},
184 {649, 46, 2112, 4},
185 {668, 47, 2208, 4},
186 {687, 48, 2304, 4},
187 {706, 49, 2400, 4},
188 {725, 50, 2496, 4},
189 {745, 51, 2592, 4},
190 {764, 52, 2720, 4},
191 {784, 53, 2816, 3},
192 {804, 54, 2944, 3},
193 {825, 55, 3008, 3},
194 {845, 56, 3136, 3},
195 {866, 57, 3264, 3},
196 {887, 58, 3392, 3},
197 {908, 59, 3456, 3},
198 {930, 60, 3584, 3},
199 {951, 61, 3712, 3},
200 {973, 62, 3840, 3},
201 {995, 63, 3968, 3}
202};
203
204static const uint8_t invensense3_fifo_sample_size[4] = {8,8,16,20};
205
212 /* General setup */
213 inv->status = INVENSENSE3_IDLE;
214 inv->device = INVENSENSE3_UNKOWN;
215 inv->register_bank = 0xFF;
216 inv->config_idx = 0;
217
218 /* SPI setup */
219 if(inv->bus == INVENSENSE3_SPI) {
220 inv->spi.trans.cpol = SPICpolIdleHigh;
221 inv->spi.trans.cpha = SPICphaEdge2;
222 inv->spi.trans.dss = SPIDss8bit;
223 inv->spi.trans.bitorder = SPIMSBFirst;
224 inv->spi.trans.cdiv = SPIDiv16;
225
226 inv->spi.trans.select = SPISelectUnselect;
227 inv->spi.trans.slave_idx = inv->spi.slave_idx;
228 inv->spi.trans.output_length = 0;
229 inv->spi.trans.input_length = 0;
230 inv->spi.trans.before_cb = NULL;
231 inv->spi.trans.after_cb = NULL;
232 inv->spi.trans.input_buf = inv->spi.rx_buf;
233 inv->spi.trans.output_buf = inv->spi.tx_buf;
234 inv->spi.trans.status = SPITransDone;
235
236 inv->rx_buffer = inv->spi.rx_buf;
237 inv->tx_buffer = inv->spi.tx_buf;
238 inv->rx_length = &inv->spi.trans.input_length;
239 }
240 /* I2C setup */
241 else {
242 inv->i2c.trans.slave_addr = inv->i2c.slave_addr;
243 inv->i2c.trans.status = I2CTransDone;
244
245 inv->rx_buffer = (uint8_t *)inv->i2c.trans.buf;
246 inv->tx_buffer = (uint8_t *)inv->i2c.trans.buf;
247 inv->rx_length = &inv->i2c.trans.len_r;
248 }
249
250 inv->sample_size = INVENSENSE3_SAMPLE_SIZE_PK3;
251
252 inv->sample_numbers = samples_from_odr(Min((int)inv->gyro_odr, (int)inv->accel_odr));
253}
254
264 /* Idle */
265 if((inv->bus == INVENSENSE3_SPI && inv->spi.trans.status == SPITransDone) ||
266 (inv->bus == INVENSENSE3_I2C && inv->i2c.trans.status == I2CTransDone)) {
267
268 /* Depending on the status choose what to do */
269 switch(inv->status) {
270 case INVENSENSE3_IDLE:
271 /* Request WHO_AM_I */
273 break;
274
276 /* Start configuring */
278 inv->status = INVENSENSE3_RUNNING;
279 }
280 break;
281
283 /* Request a sensor reading */
284 switch (inv->parser) {
287 break;
289 {
290 static const uint16_t max_bytes = sizeof(inv->spi.rx_buf) - 3;
291 int read_bytes = (inv->sample_numbers + inv->timer) * invensense3_fifo_sample_size[inv->sample_size];
293 // round to the packet boundaries
296 inv->timer = 0; // reset leftover bytes
297 break;
298 }
299 default: break;
300 }
301
302 default: break;
303 }
304 }
305}
306
316
317 /* Successful transfer */
318 if((inv->bus == INVENSENSE3_SPI && inv->spi.trans.status == SPITransSuccess) ||
319 (inv->bus == INVENSENSE3_I2C && inv->i2c.trans.status == I2CTransSuccess)) {
320
321 /* Update the register bank */
322 if(inv->tx_buffer[0] == INV3REG_BANK_SEL)
323 inv->register_bank = inv->tx_buffer[1];
324
325 /* Set the transaction as done and update register bank if needed */
326 if(inv->bus == INVENSENSE3_SPI)
327 inv->spi.trans.status = SPITransDone;
328 else
329 inv->i2c.trans.status = I2CTransDone;
330
331 /* Look at the results */
332 switch(inv->status) {
333 case INVENSENSE3_IDLE:
334 /* Check the response of the WHO_AM_I */
335 inv->status = INVENSENSE3_CONFIG;
336 if(inv->rx_buffer[1] == INV3_WHOAMI_ICM40605) {
337 inv->device = INVENSENSE3_ICM40605;
338 } else if(inv->rx_buffer[1] == INV3_WHOAMI_ICM40609) {
339 inv->device = INVENSENSE3_ICM40609;
340 } else if(inv->rx_buffer[1] == INV3_WHOAMI_ICM42605) {
341 inv->device = INVENSENSE3_ICM42605;
342 } else if(inv->rx_buffer[1] == INV3_WHOAMI_IIM42652) {
343 inv->device = INVENSENSE3_IIM42652;
344 } else if(inv->rx_buffer[1] == INV3_WHOAMI_ICM42688) {
345 inv->device = INVENSENSE3_ICM42688;
346 } else {
347 inv->status = INVENSENSE3_IDLE;
348 }
349
350 /* Fix the configuration and set the scaling */
351 if(inv->status == INVENSENSE3_CONFIG)
353 break;
354
356 /* Apply the next configuration register */
358 inv->status = INVENSENSE3_RUNNING;
359 }
360 break;
361
363 /* Select the desired parser */
364 switch (inv->parser) {
366 invensense3_parse_reg_data(inv, &inv->rx_buffer[1]);
367 break;
368
370 /* Parse the results */
371 uint16_t n_samples = (uint16_t)inv->rx_buffer[1] | inv->rx_buffer[2] << 8;
373
374 inv->timer = n_samples; // samples left in FIFO
375
376 // Not enough data in FIFO
377 if(n_samples == 0) {
378 return;
379 }
380
381 // We read an incorrect length (try again)
382 if(fifo_bytes > 4096) {
384 return;
385 }
386
387 // Parse the data
388 if(*inv->rx_length > 3) {
389 uint16_t nb_packets_read = (*inv->rx_length - 3) / invensense3_fifo_sample_size[inv->sample_size];
391 inv->timer -= nb_packets_read;
392 }
393
394 break;
395 }
396 default: break;
397 }
398 break;
399
400 default:
401 inv->status = INVENSENSE3_IDLE;
402 break;
403 }
404 }
405
406 /* Failed transaction */
407 if((inv->bus == INVENSENSE3_SPI && inv->spi.trans.status == SPITransFailed) ||
408 (inv->bus == INVENSENSE3_I2C && inv->i2c.trans.status == I2CTransFailed)) {
409
410 /* Set the transaction as done and update register bank if needed */
411 if(inv->bus == INVENSENSE3_SPI) {
412 inv->spi.trans.status = SPITransDone;
413 }
414 else {
415 inv->i2c.trans.status = I2CTransDone;
416 }
417
418 /* Retry or ignore */
419 switch(inv->status) {
421 /* If was not a bus switch decrease the index */
422 if(inv->config_idx > 0 && inv->tx_buffer[0] != INV3REG_BANK_SEL) {
423 inv->config_idx--;
424 }
425 /* Try again */
427 inv->status = INVENSENSE3_RUNNING;
428 }
429 break;
430 case INVENSENSE3_IDLE:
432 /* Ignore while idle/running */
433 default:
434 break;
435 }
436 }
437}
438
447 static struct Int32Vect3 accel[INVENSENSE3_FIFO_BUFFER_LEN] = {0};
448 static struct Int32Rates gyro[INVENSENSE3_FIFO_BUFFER_LEN] = {0};
449
451
452 uint8_t gyro_samplerate = 17 - inv->gyro_odr;
453 uint8_t accel_samplerate = 17 - inv->accel_odr;
454
455 uint8_t faster_odr = gyro_samplerate;
456 if (accel_samplerate > gyro_samplerate)
457 faster_odr = accel_samplerate;
458
459 // Go through the different samples
460 uint8_t i = 0;
461 uint8_t j = 0;
462 int32_t temp = 0;
465 for(uint8_t sample = 0; sample < samples; sample++) {
466
467 if ((data[0] & 0xFC) != 0x68) {
468 // no or bad data
469 } else {
470
471 gyro_samplerate_count = gyro_samplerate * (sample + 1);
473 gyro[i].p = (int16_t)((uint16_t)data[7] | data[8] << 8 );
474 gyro[i].q = (int16_t)((uint16_t)data[9] | data[10] << 8 );
475 gyro[i].r = (int16_t)((uint16_t)data[11] | data[12] << 8 );
476
477 // Temperature sensor register data TEMP_DATA is updated with new data at max(Accelerometer ODR, Gyroscope ODR)
478 if(gyro_samplerate == faster_odr)
479 temp += (int8_t)data[13];
480
481 i++;
482 }
483
484 accel_samplerate_count = accel_samplerate * (sample + 1);
486 accel[j].x = (int16_t)((uint16_t)data[1] | data[2] << 8 );
487 accel[j].y = (int16_t)((uint16_t)data[3] | data[4] << 8 );
488 accel[j].z = (int16_t)((uint16_t)data[5] | data[6] << 8 );
489
490 if(accel_samplerate == faster_odr)
491 temp += (int8_t)data[13];
492
493 j++;
494 }
495 }
496
497 data += invensense3_fifo_sample_size[inv->sample_size];
498 }
499
500 // ADC temp * temp sensitivity + temp zero
501 float temp_f = ((float)temp / i) / 2.07 + 25.f;
502 if (accel_samplerate == faster_odr)
503 temp_f = ((float)temp / j) / 2.07 + 25.f;
504
505 // Send the scaled values over ABI
507 AbiSendMsgIMU_GYRO_RAW(inv->abi_id, now_ts, gyro, i, inv->gyro_samplerate, temp_f);
508 AbiSendMsgIMU_ACCEL_RAW(inv->abi_id, now_ts, accel, j, inv->accel_samplerate, temp_f);
510}
511
519 static struct Int32Vect3 accel[1] = {0};
520 static struct Int32Rates gyro[1] = {0};
521
522 int32_t temp = (int16_t)((uint16_t)data[0] | data[1] << 8);
523 // ADC temp * temp sensitivity + temp zero
524 float temp_f = (float)temp / 132.48 + 25.f;
525
526 accel[0].x = (int16_t)((uint16_t)data[2] | data[3] << 8 );
527 accel[0].y = (int16_t)((uint16_t)data[4] | data[5] << 8 );
528 accel[0].z = (int16_t)((uint16_t)data[6] | data[7] << 8 );
529
530 gyro[0].p = (int16_t)((uint16_t)data[8] | data[9] << 8 );
531 gyro[0].q = (int16_t)((uint16_t)data[10]| data[11] << 8 );
532 gyro[0].r = (int16_t)((uint16_t)data[12]| data[13] << 8 );
533
534 // Send the scaled values over ABI
536 AbiSendMsgIMU_GYRO_RAW(inv->abi_id, now_ts, gyro, 1, inv->gyro_samplerate, temp_f);
537 AbiSendMsgIMU_ACCEL_RAW(inv->abi_id, now_ts, accel, 1, inv->accel_samplerate, temp_f);
539}
540
547 /* Fix wrong configuration settings (prevent user error) */
548 if(inv->gyro_odr > INVENSENSE3_GYRO_ODR_12_5HZ && inv->gyro_odr != INVENSENSE3_GYRO_ODR_500HZ)
550
551 if(inv->device == INVENSENSE3_ICM40605 || inv->device == INVENSENSE3_ICM42605) {
552 if(inv->gyro_odr > INVENSENSE3_GYRO_ODR_25HZ && inv->gyro_odr != INVENSENSE3_GYRO_ODR_500HZ)
553 inv->gyro_odr = INVENSENSE3_GYRO_ODR_25HZ;
554 else if(inv->gyro_odr < INVENSENSE3_GYRO_ODR_8KHZ)
555 inv->gyro_odr = INVENSENSE3_GYRO_ODR_8KHZ;
556
557 if(inv->device == INVENSENSE3_ICM40605 && inv->accel_odr > INVENSENSE3_ACCEL_ODR_25HZ && inv->accel_odr != INVENSENSE3_ACCEL_ODR_500HZ)
558 inv->accel_odr = INVENSENSE3_ACCEL_ODR_25HZ;
559 else if(inv->accel_odr < INVENSENSE3_ACCEL_ODR_8KHZ)
560 inv->accel_odr = INVENSENSE3_ACCEL_ODR_8KHZ;
561 }
562
563 if(inv->device != INVENSENSE3_ICM40609 && inv->accel_range < INVENSENSE3_ACCEL_RANGE_16G)
564 inv->accel_range = INVENSENSE3_ACCEL_RANGE_16G;
565 else if(inv->device == INVENSENSE3_ICM40609 && inv->accel_range > INVENSENSE3_ACCEL_RANGE_4G)
566 inv->accel_range = INVENSENSE3_ACCEL_RANGE_4G;
567
568 /* Fix the AAF bandwidth setting */
569 const uint16_t (*aaf_table)[4];
571 if(inv->device == INVENSENSE3_ICM40605 || inv->device == INVENSENSE3_ICM42605) {
574 }
575 else {
576 aaf_len = sizeof(invensense3_aaf) / sizeof(invensense3_aaf[0]);
578 }
579
580 uint16_t i = 0;
581 for(i = 0; i < aaf_len; i++) {
582 if(inv->gyro_aaf <= aaf_table[i][0]) {
583 inv->gyro_aaf = aaf_table[i][0];
584 RMAT_COPY(inv->gyro_aaf_regs, aaf_table[i]);
585 break;
586 }
587 }
588 if(i >= (aaf_len-1)) {
589 inv->gyro_aaf = aaf_table[aaf_len-1][0];
590 RMAT_COPY(inv->gyro_aaf_regs, aaf_table[aaf_len-1]);
591 }
592
593 for(i = 0; i < aaf_len; i++) {
594 if(inv->accel_aaf <= aaf_table[i][0]) {
595 inv->accel_aaf = aaf_table[i][0];
596 RMAT_COPY(inv->accel_aaf_regs, aaf_table[i]);
597 break;
598 }
599 }
600 if(i >= (aaf_len-1)) {
601 inv->accel_aaf = aaf_table[aaf_len-1][0];
602 RMAT_COPY(inv->accel_aaf_regs, aaf_table[aaf_len-1]);
603 }
604
605 /* Calculate the samplerates in Hz */
606 switch(inv->gyro_odr) {
608 inv->gyro_samplerate = 32000;
609 break;
611 inv->gyro_samplerate = 16000;
612 break;
614 inv->gyro_samplerate = 8000;
615 break;
617 inv->gyro_samplerate = 4000;
618 break;
620 inv->gyro_samplerate = 2000;
621 break;
623 inv->gyro_samplerate = 1000;
624 break;
626 inv->gyro_samplerate = 200;
627 break;
629 inv->gyro_samplerate = 100;
630 break;
632 inv->gyro_samplerate = 50;
633 break;
635 inv->gyro_samplerate = 25;
636 break;
638 inv->gyro_samplerate = 12.5;
639 break;
641 inv->gyro_samplerate = 6.25;
642 break;
644 inv->gyro_samplerate = 3.125;
645 break;
647 inv->gyro_samplerate = 1.5625;
648 break;
650 inv->gyro_samplerate = 500;
651 break;
652 }
653 switch(inv->accel_odr) {
655 inv->accel_samplerate = 32000;
656 break;
658 inv->accel_samplerate = 16000;
659 break;
661 inv->accel_samplerate = 8000;
662 break;
664 inv->accel_samplerate = 4000;
665 break;
667 inv->accel_samplerate = 2000;
668 break;
670 inv->accel_samplerate = 1000;
671 break;
673 inv->accel_samplerate = 200;
674 break;
676 inv->accel_samplerate = 100;
677 break;
679 inv->accel_samplerate = 50;
680 break;
682 inv->accel_samplerate = 25;
683 break;
685 inv->accel_samplerate = 12.5;
686 break;
688 inv->accel_samplerate = 6.25;
689 break;
691 inv->accel_samplerate = 3.125;
692 break;
694 inv->accel_samplerate = 1.5625;
695 break;
697 inv->accel_samplerate = 500;
698 break;
699 }
700
701 /* Set the default values */
704}
705
716 /* Split the register and bank */
717 uint8_t bank = bank_reg >> 8;
718 uint8_t reg = bank_reg & 0xFF;
719
720 /* Switch the register bank if needed */
722 return false;
723 }
724
725 inv->tx_buffer[0] = reg;
726 inv->tx_buffer[1] = value;
727
728 /* SPI transaction */
729 if(inv->bus == INVENSENSE3_SPI) {
730 inv->spi.trans.output_length = 2;
731 inv->spi.trans.input_length = 0;
732 spi_submit(inv->spi.p, &(inv->spi.trans));
733 }
734 /* I2C transaction */
735 else {
736 i2c_transmit(inv->i2c.p, &(inv->i2c.trans), inv->i2c.slave_addr, 2);
737 }
738
739 return true;
740}
741
752 /* Split the register and bank */
753 uint8_t bank = bank_reg >> 8;
754 uint8_t reg = bank_reg & 0xFF;
755
756 /* Switch the register bank if needed */
758 return false;
759 }
760
761 inv->tx_buffer[0] = reg | INV3_READ_FLAG;
762 /* SPI transaction */
763 if(inv->bus == INVENSENSE3_SPI) {
764 inv->spi.trans.output_length = 2;
765 inv->spi.trans.input_length = 1 + size;
766 inv->tx_buffer[1] = 0;
767 spi_submit(inv->spi.p, &(inv->spi.trans));
768 }
769 /* I2C transaction */
770 else {
771 i2c_transceive(inv->i2c.p, &(inv->i2c.trans), inv->i2c.slave_addr, 1, (1 + size));
772 }
773
774 return true;
775}
776
786 /* If we already selected the correct bank continue */
787 if(inv->register_bank == bank)
788 return false;
789
790 inv->tx_buffer[0] = INV3REG_BANK_SEL;
791 inv->tx_buffer[1] = bank;
792 /* SPI transaction */
793 if(inv->bus == INVENSENSE3_SPI) {
794 inv->spi.trans.output_length = 2;
795 inv->spi.trans.input_length = 0;
796 spi_submit(inv->spi.p, &(inv->spi.trans));
797 }
798 /* I2C transaction */
799 else {
800 i2c_transmit(inv->i2c.p, &(inv->i2c.trans), inv->i2c.slave_addr, 2);
801 }
802
803 return true;
804}
805
817
826 switch(inv->config_idx) {
827 case 0:
828 /* Reset the device */
830 inv->config_idx++;
831 inv->timer = get_sys_time_usec();
832 break;
833
834 case 1:
835 /* Because reset takes time wait ~5ms */
836 if((get_sys_time_usec() - inv->timer) < 5e3)
837 break;
838
839 /* Start the accel en gyro in low noise mode */
841 inv->config_idx++;
842 inv->timer = get_sys_time_usec();
843 break;
844
845 case 2:
846 /* Because starting takes time wait ~1ms */
847 if((get_sys_time_usec() - inv->timer) < 1e3)
848 break;
849
850 /* Configure the gyro ODR/FS */
852 inv->config_idx++;
853 break;
854
855 case 3: {
856 /* Configure the accel ODR/FS */
857 uint8_t accel_config = (inv->accel_odr << ACCEL_ODR_SHIFT);
858 if(inv->device == INVENSENSE3_ICM40609)
859 accel_config |= inv->accel_range << ACCEL_FS_SEL_SHIFT;
860 else
861 accel_config |= (inv->accel_range - 1) << ACCEL_FS_SEL_SHIFT;
862
864 inv->config_idx++;
865 break;
866 }
867
868 case 4:
869 /* Configure gyro AAF enable */
871 inv->config_idx++;
872 break;
873 case 5:
874 /* Configure gyro AAF DELT */
876 inv->config_idx++;
877 break;
878 case 6:
879 /* Configure gyro AAF DELTSQR lower */
880 if(invensense3_register_write(inv, INV3REG_GYRO_CONFIG_STATIC4, (inv->gyro_aaf_regs[2]&0xFF)))
881 inv->config_idx++;
882 break;
883 case 7:
884 /* Configure gyro AAF DELTSQR upper and bitshift */
885 if(invensense3_register_write(inv, INV3REG_GYRO_CONFIG_STATIC5, (inv->gyro_aaf_regs[3] << GYRO_AAF_BITSHIFT_SHIFT) | ((inv->gyro_aaf_regs[2]>>8) & 0x0F)))
886 inv->config_idx++;
887 break;
888 case 8:
889 /* Configure accel AAF enable and DELT */
891 inv->config_idx++;
892 break;
893 case 9:
894 /* Configure accel AAF DELTSQR lower */
895 if(invensense3_register_write(inv, INV3REG_ACCEL_CONFIG_STATIC3, (inv->accel_aaf_regs[2]&0xFF)))
896 inv->config_idx++;
897 break;
898 case 10:
899 /* Configure accel AAF DELTSQR upper and bitshift */
900 if(invensense3_register_write(inv, INV3REG_ACCEL_CONFIG_STATIC4, (inv->accel_aaf_regs[3] << ACCEL_AAF_BITSHIFT_SHIFT) | ((inv->accel_aaf_regs[2]>>8) & 0x0F)))
901 inv->config_idx++;
902 break;
903
904 case 11:
905 /* FIFO count in records (little-endian data) */
907 inv->config_idx++;
908 break;
909 case 12:
910 /* Disable AFSR, which changes noise sensitivity with angular rate, causing stuck gyro's for 2ms resulting in DC gyro bias */
912 inv->config_idx++;
913 break;
914 case 13:
915 /* FIFO Stop-on-Full mode (enable the FIFO) */
917 inv->config_idx++;
918 break;
919 case 14:
920 /* FIFO content: enable accel, gyro, temperature */
923 inv->config_idx++;
924 break;
925 case 15:
926 /* Set FIFO watermark to 1 (so that INT is triggered for each packet) */
928 inv->config_idx++;
929 break;
930 case 16:
931 /* Set FIFO watermark to 1 (so that INT is triggered for each packet) */
933 inv->config_idx++;
934 break;
935 case 17:
936 /* Enable interrupt pin/status */
937 switch(inv->parser) {
940 inv->config_idx++;
941 break;
944 inv->config_idx++;
945 break;
946 default:
947 break;
948 }
949 break;
950 case 18:
951 /* Interrupt pins ASYNC_RESET configuration */
952 // Datasheet: "User should change setting to 0 from default setting of 1, for proper INT1 and INT2 pin operation"
954 inv->config_idx++;
955 break;
956 case 19:
957 /* FIFO flush */
959 inv->config_idx++;
960 break;
961
962 default:
963 inv->timer = 0;
964 return true;
965 }
966 return false;
967}
968
969static int samples_from_odr(int odr) {
970 float freq = 0;
972 freq = 32000 / pow(2, odr-INVENSENSE3_GYRO_ODR_32KHZ);
973 }
974 else if(odr < INVENSENSE3_GYRO_ODR_500HZ) {
975 freq = 200 / pow(2, odr-INVENSENSE3_GYRO_ODR_200HZ);
976 }
977 else if(odr == INVENSENSE3_GYRO_ODR_500HZ) {
978 freq = 500;
979 } else {
980 // error
981 }
982 return ceilf(freq/PERIODIC_FREQUENCY);
983}
Main include for ABI (AirBorneInterface).
uint32_t get_sys_time_usec(void)
Get the time in microseconds since startup.
int n_samples
Definition detect_gate.c:85
#define Min(x, y)
Definition esc_dshot.c:109
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:202
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:222
@ I2CTransSuccess
transaction successfully finished by I2C driver
Definition i2c.h:58
@ I2CTransFailed
transaction failed
Definition i2c.h:59
@ I2CTransDone
transaction set to done by user level
Definition i2c.h:60
angular rates
#define RMAT_COPY(_o, _i)
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:534
@ SPICphaEdge2
CPHA = 1.
Definition spi.h:71
@ SPITransFailed
Definition spi.h:96
@ SPITransSuccess
Definition spi.h:95
@ SPITransDone
Definition spi.h:97
@ SPICpolIdleHigh
CPOL = 1.
Definition spi.h:80
@ SPISelectUnselect
slave is selected before transaction and unselected after
Definition spi.h:59
@ SPIMSBFirst
Definition spi.h:108
@ SPIDiv16
Definition spi.h:119
@ SPIDss8bit
Definition spi.h:86
void imu_set_defaults_gyro(uint8_t abi_id, const struct Int32RMat *imu_to_sensor, const struct Int32Rates *neutral, const struct FloatRates *scale_f)
Set the defaults for a gyro sensor WARNING: Should be called before sensor is publishing messages to ...
Definition imu.c:612
void imu_set_defaults_accel(uint8_t abi_id, const struct Int32RMat *imu_to_sensor, const struct Int32Vect3 *neutral, const struct FloatVect3 *scale_f)
Set the defaults for a accel sensor WARNING: Should be called before sensor is publishing messages to...
Definition imu.c:641
Inertial Measurement Unit interface.
#define GYRO_FS_SEL_SHIFT
#define ACCEL_FS_SEL_SHIFT
static const uint16_t invensense3_aaf4x605[][4]
void invensense3_periodic(struct invensense3_t *inv)
Should be called periodically to request sensor readings.
static const struct FloatRates invensense3_gyro_scale_f[8]
Definition invensense3.c:51
static void invensense3_parse_fifo_data(struct invensense3_t *inv, uint8_t *data, uint16_t samples)
Parse the FIFO buffer data.
static int samples_from_odr(int odr)
static const uint8_t invensense3_fifo_sample_size[4]
static const uint16_t invensense3_aaf[][4]
Definition invensense3.c:72
static void invensense3_parse_reg_data(struct invensense3_t *inv, uint8_t *data)
Parse data from registers.
static bool invensense3_reset_fifo(struct invensense3_t *inv)
Reset FIFO (can be useful in some situations)
static bool invensense3_select_bank(struct invensense3_t *inv, uint8_t bank)
Select the correct register bank.
void invensense3_event(struct invensense3_t *inv)
Should be called in the event thread.
static bool invensense3_config(struct invensense3_t *inv)
Configure the Invensense 3 device register by register.
static void invensense3_fix_config(struct invensense3_t *inv)
This fixes the configuration errors and sets the correct scalings.
static const struct FloatVect3 invensense3_accel_scale_f[5]
Definition invensense3.c:63
static bool invensense3_register_read(struct invensense3_t *inv, uint16_t bank_reg, uint16_t size)
Read a register based on a combined bank/regsiter value.
static bool invensense3_register_write(struct invensense3_t *inv, uint16_t bank_reg, uint8_t value)
Write a register based on a combined bank/regsiter value.
void invensense3_init(struct invensense3_t *inv)
Initialize the invensense v3 sensor instance.
Driver for the Invensense V3 IMUs ICM40605, ICM40609, ICM42605, IIM42652 and ICM42688.
@ INVENSENSE3_ACCEL_RANGE_16G
@ INVENSENSE3_ACCEL_RANGE_4G
@ INVENSENSE3_GYRO_ODR_4KHZ
Definition invensense3.h:99
@ INVENSENSE3_GYRO_ODR_25HZ
@ INVENSENSE3_GYRO_ODR_500HZ
@ INVENSENSE3_GYRO_ODR_8KHZ
Definition invensense3.h:98
@ INVENSENSE3_GYRO_ODR_1_5625HZ
@ INVENSENSE3_GYRO_ODR_100HZ
@ INVENSENSE3_GYRO_ODR_2KHZ
@ INVENSENSE3_GYRO_ODR_50HZ
@ INVENSENSE3_GYRO_ODR_1KHZ
@ INVENSENSE3_GYRO_ODR_16KHZ
Not possible for ICM40605 and ICM42605.
Definition invensense3.h:97
@ INVENSENSE3_GYRO_ODR_32KHZ
Not possible for ICM40605 and ICM42605.
Definition invensense3.h:96
@ INVENSENSE3_GYRO_ODR_3_125HZ
@ INVENSENSE3_GYRO_ODR_6_25HZ
@ INVENSENSE3_GYRO_ODR_200HZ
@ INVENSENSE3_GYRO_ODR_12_5HZ
@ INVENSENSE3_UNKOWN
Definition invensense3.h:86
@ INVENSENSE3_ICM42688
Definition invensense3.h:91
@ INVENSENSE3_ICM40605
Definition invensense3.h:87
@ INVENSENSE3_IIM42652
Definition invensense3.h:90
@ INVENSENSE3_ICM40609
Definition invensense3.h:88
@ INVENSENSE3_ICM42605
Definition invensense3.h:89
@ INVENSENSE3_PARSER_FIFO
Definition invensense3.h:74
@ INVENSENSE3_PARSER_REGISTERS
Definition invensense3.h:73
@ INVENSENSE3_ACCEL_ODR_4KHZ
@ INVENSENSE3_ACCEL_ODR_16KHZ
Not possible for ICM40605 and ICM42605.
@ INVENSENSE3_ACCEL_ODR_50HZ
@ INVENSENSE3_ACCEL_ODR_32KHZ
Not possible for ICM40605 and ICM42605.
@ INVENSENSE3_ACCEL_ODR_2KHZ
@ INVENSENSE3_ACCEL_ODR_25HZ
@ INVENSENSE3_ACCEL_ODR_1_5625HZ
@ INVENSENSE3_ACCEL_ODR_8KHZ
@ INVENSENSE3_ACCEL_ODR_6_25HZ
@ INVENSENSE3_ACCEL_ODR_200HZ
@ INVENSENSE3_ACCEL_ODR_100HZ
@ INVENSENSE3_ACCEL_ODR_1KHZ
@ INVENSENSE3_ACCEL_ODR_500HZ
@ INVENSENSE3_ACCEL_ODR_12_5HZ
@ INVENSENSE3_ACCEL_ODR_3_125HZ
@ INVENSENSE3_I2C
Definition invensense3.h:61
@ INVENSENSE3_SPI
Definition invensense3.h:60
@ INVENSENSE3_SAMPLE_SIZE_PK3
Definition invensense3.h:80
#define INVENSENSE3_FIFO_BUFFER_LEN
Definition invensense3.h:38
@ INVENSENSE3_CONFIG
Definition invensense3.h:67
@ INVENSENSE3_IDLE
Definition invensense3.h:66
@ INVENSENSE3_RUNNING
Definition invensense3.h:68
Register and address definitions for the Invensense V3 from ardupilot.
#define INV3REG_INTF_CONFIG1
#define FIFO_CONFIG_MODE_SHIFT
#define INV3REG_FIFO_CONFIG
#define FIFO_CONFIG_MODE_STOP_ON_FULL
#define GYRO_ODR_SHIFT
#define ACCEL_MODE_SHIFT
#define INV3REG_GYRO_CONFIG_STATIC2
#define INV3REG_ACCEL_CONFIG_STATIC2
#define BIT_FIFO_CONFIG1_ACCEL_EN
#define INV3_WHOAMI_ICM42605
#define INV3REG_WHO_AM_I
#define ACCEL_ODR_SHIFT
#define INV3REG_BANK_SEL
#define BIT_FIFO_CONFIG1_GYRO_EN
#define INV3REG_FIFO_CONFIG3
#define ACCEL_AAF_BITSHIFT_SHIFT
#define INV3_READ_FLAG
#define INV3REG_PWR_MGMT0
#define ACCEL_MODE_LN
#define INV3REG_INT_CONFIG1
#define BIT_SIGNAL_PATH_RESET_FIFO_FLUSH
#define INV3REG_FIFO_CONFIG1
#define BIT_FIFO_FULL_INT_EN
#define FIFO_COUNT_REC
#define ACCEL_AAF_DELT_SHIFT
#define BIT_FIFO_CONFIG1_TEMP_EN
#define INV3REG_INTF_CONFIG0
#define INV3REG_INT_SOURCE0
#define INV3_WHOAMI_ICM42688
#define GYRO_AAF_BITSHIFT_SHIFT
#define INV3REG_TEMP_DATA1
#define INV3_WHOAMI_ICM40605
#define BIT_INT_ASYNC_RESET
#define GYRO_MODE_SHIFT
#define INV3REG_DEVICE_CONFIG
#define INV3REG_GYRO_CONFIG_STATIC3
#define BIT_FIFO_THS_INT_EN
#define INV3REG_ACCEL_CONFIG_STATIC4
#define INV3REG_GYRO_CONFIG_STATIC5
#define INV3REG_GYRO_CONFIG_STATIC4
#define BIT_UI_DRDY_INT_EN
#define INV3_WHOAMI_IIM42652
#define INV3REG_ACCEL_CONFIG_STATIC3
#define GYRO_MODE_LN
#define INV3REG_ACCEL_CONFIG0
#define BIT_DEVICE_CONFIG_SOFT_RESET_CONFIG
#define INV3REG_FIFO_CONFIG2
#define INV3REG_FIFO_COUNTH
#define INV3_WHOAMI_ICM40609
#define INV3REG_SIGNAL_PATH_RESET
#define INV3REG_GYRO_CONFIG0
uint16_t foo
Definition main_demo5.c:58
Paparazzi floating point algebra.
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.