Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
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"
33#include "modules/imu/imu.h"
34#include "modules/core/abi.h"
35#include "mcu_periph/gpio_arch.h"
36#include "std.h"
37
38/* Local functions */
40static void invensense3_parse_reg_data(struct invensense3_t *inv, uint8_t *data);
41static void invensense3_fix_config(struct invensense3_t *inv);
45static bool invensense3_config(struct invensense3_t *inv);
46static bool invensense3_reset_fifo(struct invensense3_t *inv);
47static int samples_from_odr(int odr);
48
49/* Default gyro scalings */
50static const struct Int32Rates invensense3_gyro_scale[8][2] = {
51 { {40147, 40147, 40147},
52 {9210, 9210, 9210} }, // 2000DPS
53 { {40147, 40147, 40147},
54 {18420, 18420, 18420} }, // 1000DPS
55 { {60534, 60534, 60534},
56 {55463, 55463, 55463} }, // 500DPS
57 { {30267, 30267, 30267},
58 {55463, 55463, 55463} }, // 250DPS
59 { {30267, 30267, 30267},
60 {110926, 110926, 110926} }, // 125DPS vvv (TODO: the new scales are not tested yet) vvv
61 { {3292054, 3292054, 3292054},
62 {24144015, 24144015, 24144015} }, // 62.5DPS
63 { {1646027, 1646027, 1646027},
64 {24144015, 24144015, 24144015} }, // 31.25DPS
65 { {1646027, 1646027, 1646027},
66 {48288030, 48288030, 48288030} }, // 15.625DPS
67};
68
69/* Default accel scalings */
70static const struct Int32Vect3 invensense3_accel_scale[5][2] = {
71 { {51024, 51024, 51024},
72 {5203, 5203, 5203} }, // 32G
73 { {25512, 25512, 25512},
74 {5203, 5203, 5203} }, // 16G
75 { {12756, 12756, 12756},
76 {5203, 5203, 5203} }, // 8G
77 { {6378, 6378, 6378},
78 {5203, 5203, 5203} }, // 4G
79 { {3189, 3189, 3189},
80 {5203, 5203, 5203} } // 2G
81};
82
83/* AAF settings (3dB Bandwidth [Hz], AAF_DELT, AAF_DELTSQR, AAF_BITSHIFT) */
84static const uint16_t invensense3_aaf[][4] = {
85 {42, 1, 1, 15},
86 {84, 2, 4, 13},
87 {126, 3, 9, 12},
88 {170, 4, 16, 11},
89 {213, 5, 25, 10},
90 {258, 6, 36, 10},
91 {303, 7, 49, 9},
92 {348, 8, 64, 9},
93 {394, 9, 81, 9},
94 {441, 10, 100, 8},
95 {488, 11, 122, 8},
96 {536, 12, 144, 8},
97 {585, 13, 170, 8},
98 {634, 14, 196, 7},
99 {684, 15, 224, 7},
100 {734, 16, 256, 7},
101 {785, 17, 288, 7},
102 {837, 18, 324, 7},
103 {890, 19, 360, 6},
104 {943, 20, 400, 6},
105 {997, 21, 440, 6},
106 {1051, 22, 488, 6},
107 {1107, 23, 528, 6},
108 {1163, 24, 576, 6},
109 {1220, 25, 624, 6},
110 {1277, 26, 680, 6},
111 {1336, 27, 736, 5},
112 {1395, 28, 784, 5},
113 {1454, 29, 848, 5},
114 {1515, 30, 896, 5},
115 {1577, 31, 960, 5},
116 {1639, 32, 1024, 5},
117 {1702, 33, 1088, 5},
118 {1766, 34, 1152, 5},
119 {1830, 35, 1232, 5},
120 {1896, 36, 1296, 5},
121 {1962, 37, 1376, 4},
122 {2029, 38, 1440, 4},
123 {2097, 39, 1536, 4},
124 {2166, 40, 1600, 4},
125 {2235, 41, 1696, 4},
126 {2306, 42, 1760, 4},
127 {2377, 43, 1856, 4},
128 {2449, 44, 1952, 4},
129 {2522, 45, 2016, 4},
130 {2596, 46, 2112, 4},
131 {2671, 47, 2208, 4},
132 {2746, 48, 2304, 4},
133 {2823, 49, 2400, 4},
134 {2900, 50, 2496, 4},
135 {2978, 51, 2592, 4},
136 {3057, 52, 2720, 4},
137 {3137, 53, 2816, 3},
138 {3217, 54, 2944, 3},
139 {3299, 55, 3008, 3},
140 {3381, 56, 3136, 3},
141 {3464, 57, 3264, 3},
142 {3548, 58, 3392, 3},
143 {3633, 59, 3456, 3},
144 {3718, 60, 3584, 3},
145 {3805, 61, 3712, 3},
146 {3892, 62, 3840, 3},
147 {3979, 63, 3968, 3}
148};
149
150static const uint16_t invensense3_aaf4x605[][4] = {
151 {10, 1, 1, 15},
152 {21, 2, 4, 13},
153 {32, 3, 9, 12},
154 {42, 4, 16, 11},
155 {53, 5, 25, 10},
156 {64, 6, 36, 10},
157 {76, 7, 49, 9},
158 {87, 8, 64, 9},
159 {99, 9, 81, 9},
160 {110, 10, 100, 8},
161 {122, 11, 122, 8},
162 {134, 12, 144, 8},
163 {146, 13, 170, 8},
164 {158, 14, 196, 7},
165 {171, 15, 224, 7},
166 {184, 16, 256, 7},
167 {196, 17, 288, 7},
168 {209, 18, 324, 7},
169 {222, 19, 360, 6},
170 {236, 20, 400, 6},
171 {249, 21, 440, 6},
172 {263, 22, 488, 6},
173 {277, 23, 528, 6},
174 {291, 24, 576, 6},
175 {305, 25, 624, 6},
176 {319, 26, 680, 6},
177 {334, 27, 736, 5},
178 {349, 28, 784, 5},
179 {364, 29, 848, 5},
180 {379, 30, 896, 5},
181 {394, 31, 960, 5},
182 {410, 32, 1024, 5},
183 {425, 33, 1088, 5},
184 {441, 34, 1152, 5},
185 {458, 35, 1232, 5},
186 {474, 36, 1296, 5},
187 {490, 37, 1376, 4},
188 {507, 38, 1440, 4},
189 {524, 39, 1536, 4},
190 {541, 40, 1600, 4},
191 {559, 41, 1696, 4},
192 {576, 42, 1760, 4},
193 {594, 43, 1856, 4},
194 {612, 44, 1952, 4},
195 {631, 45, 2016, 4},
196 {649, 46, 2112, 4},
197 {668, 47, 2208, 4},
198 {687, 48, 2304, 4},
199 {706, 49, 2400, 4},
200 {725, 50, 2496, 4},
201 {745, 51, 2592, 4},
202 {764, 52, 2720, 4},
203 {784, 53, 2816, 3},
204 {804, 54, 2944, 3},
205 {825, 55, 3008, 3},
206 {845, 56, 3136, 3},
207 {866, 57, 3264, 3},
208 {887, 58, 3392, 3},
209 {908, 59, 3456, 3},
210 {930, 60, 3584, 3},
211 {951, 61, 3712, 3},
212 {973, 62, 3840, 3},
213 {995, 63, 3968, 3}
214};
215
216static const uint8_t invensense3_fifo_sample_size[4] = {8,8,16,20};
217
224 /* General setup */
225 inv->status = INVENSENSE3_IDLE;
226 inv->device = INVENSENSE3_UNKOWN;
227 inv->register_bank = 0xFF;
228 inv->config_idx = 0;
229
230 /* SPI setup */
231 if(inv->bus == INVENSENSE3_SPI) {
232 inv->spi.trans.cpol = SPICpolIdleHigh;
233 inv->spi.trans.cpha = SPICphaEdge2;
234 inv->spi.trans.dss = SPIDss8bit;
235 inv->spi.trans.bitorder = SPIMSBFirst;
236 inv->spi.trans.cdiv = SPIDiv16;
237
238 inv->spi.trans.select = SPISelectUnselect;
239 inv->spi.trans.slave_idx = inv->spi.slave_idx;
240 inv->spi.trans.output_length = 0;
241 inv->spi.trans.input_length = 0;
242 inv->spi.trans.before_cb = NULL;
243 inv->spi.trans.after_cb = NULL;
244 inv->spi.trans.input_buf = inv->spi.rx_buf;
245 inv->spi.trans.output_buf = inv->spi.tx_buf;
246 inv->spi.trans.status = SPITransDone;
247
248 inv->rx_buffer = inv->spi.rx_buf;
249 inv->tx_buffer = inv->spi.tx_buf;
250 inv->rx_length = &inv->spi.trans.input_length;
251 }
252 /* I2C setup */
253 else {
254 inv->i2c.trans.slave_addr = inv->i2c.slave_addr;
255 inv->i2c.trans.status = I2CTransDone;
256
257 inv->rx_buffer = (uint8_t *)inv->i2c.trans.buf;
258 inv->tx_buffer = (uint8_t *)inv->i2c.trans.buf;
259 inv->rx_length = &inv->i2c.trans.len_r;
260 }
261
262 inv->sample_size = INVENSENSE3_SAMPLE_SIZE_PK3;
263
264 inv->sample_numbers = samples_from_odr(Min((int)inv->gyro_odr, (int)inv->accel_odr));
265}
266
276 /* Idle */
277 if((inv->bus == INVENSENSE3_SPI && inv->spi.trans.status == SPITransDone) ||
278 (inv->bus == INVENSENSE3_I2C && inv->i2c.trans.status == I2CTransDone)) {
279
280 /* Depending on the status choose what to do */
281 switch(inv->status) {
282 case INVENSENSE3_IDLE:
283 /* Request WHO_AM_I */
285 break;
286
288 /* Start configuring */
290 inv->status = INVENSENSE3_RUNNING;
291 }
292 break;
293
295 /* Request a sensor reading */
296 switch (inv->parser) {
299 break;
301 {
302 static const uint16_t max_bytes = sizeof(inv->spi.rx_buf) - 3;
303 int read_bytes = (inv->sample_numbers + inv->timer) * invensense3_fifo_sample_size[inv->sample_size];
305 // round to the packet boundaries
308 inv->timer = 0; // reset leftover bytes
309 break;
310 }
311 default: break;
312 }
313
314 default: break;
315 }
316 }
317}
318
328
329 /* Successful transfer */
330 if((inv->bus == INVENSENSE3_SPI && inv->spi.trans.status == SPITransSuccess) ||
331 (inv->bus == INVENSENSE3_I2C && inv->i2c.trans.status == I2CTransSuccess)) {
332
333 /* Update the register bank */
334 if(inv->tx_buffer[0] == INV3REG_BANK_SEL)
335 inv->register_bank = inv->tx_buffer[1];
336
337 /* Set the transaction as done and update register bank if needed */
338 if(inv->bus == INVENSENSE3_SPI)
339 inv->spi.trans.status = SPITransDone;
340 else
341 inv->i2c.trans.status = I2CTransDone;
342
343 /* Look at the results */
344 switch(inv->status) {
345 case INVENSENSE3_IDLE:
346 /* Check the response of the WHO_AM_I */
347 inv->status = INVENSENSE3_CONFIG;
348 if(inv->rx_buffer[1] == INV3_WHOAMI_ICM40605) {
349 inv->device = INVENSENSE3_ICM40605;
350 } else if(inv->rx_buffer[1] == INV3_WHOAMI_ICM40609) {
351 inv->device = INVENSENSE3_ICM40609;
352 } else if(inv->rx_buffer[1] == INV3_WHOAMI_ICM42605) {
353 inv->device = INVENSENSE3_ICM42605;
354 } else if(inv->rx_buffer[1] == INV3_WHOAMI_IIM42652) {
355 inv->device = INVENSENSE3_IIM42652;
356 } else if(inv->rx_buffer[1] == INV3_WHOAMI_ICM42688) {
357 inv->device = INVENSENSE3_ICM42688;
358 } else {
359 inv->status = INVENSENSE3_IDLE;
360 }
361
362 /* Fix the configuration and set the scaling */
363 if(inv->status == INVENSENSE3_CONFIG)
365 break;
366
368 /* Apply the next configuration register */
370 inv->status = INVENSENSE3_RUNNING;
371 }
372 break;
373
375 /* Select the desired parser */
376 switch (inv->parser) {
378 invensense3_parse_reg_data(inv, &inv->rx_buffer[1]);
379 break;
380
382 /* Parse the results */
383 uint16_t n_samples = (uint16_t)inv->rx_buffer[1] | inv->rx_buffer[2] << 8;
385
386 inv->timer = n_samples; // samples left in FIFO
387
388 // Not enough data in FIFO
389 if(n_samples == 0) {
390 return;
391 }
392
393 // We read an incorrect length (try again)
394 if(fifo_bytes > 4096) {
396 return;
397 }
398
399 // Parse the data
400 if(*inv->rx_length > 3) {
401 uint16_t nb_packets_read = (*inv->rx_length - 3) / invensense3_fifo_sample_size[inv->sample_size];
403 inv->timer -= nb_packets_read;
404 }
405
406 break;
407 }
408 default: break;
409 }
410 break;
411
412 default:
413 inv->status = INVENSENSE3_IDLE;
414 break;
415 }
416 }
417
418 /* Failed transaction */
419 if((inv->bus == INVENSENSE3_SPI && inv->spi.trans.status == SPITransFailed) ||
420 (inv->bus == INVENSENSE3_I2C && inv->i2c.trans.status == I2CTransFailed)) {
421
422 /* Set the transaction as done and update register bank if needed */
423 if(inv->bus == INVENSENSE3_SPI) {
424 inv->spi.trans.status = SPITransDone;
425 }
426 else {
427 inv->i2c.trans.status = I2CTransDone;
428 }
429
430 /* Retry or ignore */
431 switch(inv->status) {
433 /* If was not a bus switch decrease the index */
434 if(inv->config_idx > 0 && inv->tx_buffer[0] != INV3REG_BANK_SEL) {
435 inv->config_idx--;
436 }
437 /* Try again */
439 inv->status = INVENSENSE3_RUNNING;
440 }
441 break;
442 case INVENSENSE3_IDLE:
444 /* Ignore while idle/running */
445 default:
446 break;
447 }
448 }
449}
450
459 static struct Int32Vect3 accel[INVENSENSE3_FIFO_BUFFER_LEN] = {0};
460 static struct Int32Rates gyro[INVENSENSE3_FIFO_BUFFER_LEN] = {0};
461
463
464 uint8_t gyro_samplerate = 17 - inv->gyro_odr;
465 uint8_t accel_samplerate = 17 - inv->accel_odr;
466
467 uint8_t faster_odr = gyro_samplerate;
468 if (accel_samplerate > gyro_samplerate)
469 faster_odr = accel_samplerate;
470
471 // Go through the different samples
472 uint8_t i = 0;
473 uint8_t j = 0;
474 int32_t temp = 0;
477 for(uint8_t sample = 0; sample < samples; sample++) {
478
479 if ((data[0] & 0xFC) != 0x68) {
480 // no or bad data
481 } else {
482
483 gyro_samplerate_count = gyro_samplerate * (sample + 1);
485 gyro[i].p = (int16_t)((uint16_t)data[7] | data[8] << 8 );
486 gyro[i].q = (int16_t)((uint16_t)data[9] | data[10] << 8 );
487 gyro[i].r = (int16_t)((uint16_t)data[11] | data[12] << 8 );
488
489 // Temperature sensor register data TEMP_DATA is updated with new data at max(Accelerometer ODR, Gyroscope ODR)
490 if(gyro_samplerate == faster_odr)
491 temp += (int8_t)data[13];
492
493 i++;
494 }
495
496 accel_samplerate_count = accel_samplerate * (sample + 1);
498 accel[j].x = (int16_t)((uint16_t)data[1] | data[2] << 8 );
499 accel[j].y = (int16_t)((uint16_t)data[3] | data[4] << 8 );
500 accel[j].z = (int16_t)((uint16_t)data[5] | data[6] << 8 );
501
502 if(accel_samplerate == faster_odr)
503 temp += (int8_t)data[13];
504
505 j++;
506 }
507 }
508
509 data += invensense3_fifo_sample_size[inv->sample_size];
510 }
511
512 // ADC temp * temp sensitivity + temp zero
513 float temp_f = ((float)temp / i) / 2.07 + 25.f;
514 if (accel_samplerate == faster_odr)
515 temp_f = ((float)temp / j) / 2.07 + 25.f;
516
517 // Send the scaled values over ABI
519 AbiSendMsgIMU_GYRO_RAW(inv->abi_id, now_ts, gyro, i, inv->gyro_samplerate, temp_f);
520 AbiSendMsgIMU_ACCEL_RAW(inv->abi_id, now_ts, accel, j, inv->accel_samplerate, temp_f);
522}
523
531 static struct Int32Vect3 accel[1] = {0};
532 static struct Int32Rates gyro[1] = {0};
533
534 int32_t temp = (int16_t)((uint16_t)data[0] | data[1] << 8);
535 // ADC temp * temp sensitivity + temp zero
536 float temp_f = (float)temp / 132.48 + 25.f;
537
538 accel[0].x = (int16_t)((uint16_t)data[2] | data[3] << 8 );
539 accel[0].y = (int16_t)((uint16_t)data[4] | data[5] << 8 );
540 accel[0].z = (int16_t)((uint16_t)data[6] | data[7] << 8 );
541
542 gyro[0].p = (int16_t)((uint16_t)data[8] | data[9] << 8 );
543 gyro[0].q = (int16_t)((uint16_t)data[10]| data[11] << 8 );
544 gyro[0].r = (int16_t)((uint16_t)data[12]| data[13] << 8 );
545
546 // Send the scaled values over ABI
548 AbiSendMsgIMU_GYRO_RAW(inv->abi_id, now_ts, gyro, 1, inv->gyro_samplerate, temp_f);
549 AbiSendMsgIMU_ACCEL_RAW(inv->abi_id, now_ts, accel, 1, inv->accel_samplerate, temp_f);
551}
552
559 /* Fix wrong configuration settings (prevent user error) */
560 if(inv->gyro_odr > INVENSENSE3_GYRO_ODR_12_5HZ && inv->gyro_odr != INVENSENSE3_GYRO_ODR_500HZ)
562
563 if(inv->device == INVENSENSE3_ICM40605 || inv->device == INVENSENSE3_ICM42605) {
564 if(inv->gyro_odr > INVENSENSE3_GYRO_ODR_25HZ && inv->gyro_odr != INVENSENSE3_GYRO_ODR_500HZ)
565 inv->gyro_odr = INVENSENSE3_GYRO_ODR_25HZ;
566 else if(inv->gyro_odr < INVENSENSE3_GYRO_ODR_8KHZ)
567 inv->gyro_odr = INVENSENSE3_GYRO_ODR_8KHZ;
568
569 if(inv->device == INVENSENSE3_ICM40605 && inv->accel_odr > INVENSENSE3_ACCEL_ODR_25HZ && inv->accel_odr != INVENSENSE3_ACCEL_ODR_500HZ)
570 inv->accel_odr = INVENSENSE3_ACCEL_ODR_25HZ;
571 else if(inv->accel_odr < INVENSENSE3_ACCEL_ODR_8KHZ)
572 inv->accel_odr = INVENSENSE3_ACCEL_ODR_8KHZ;
573 }
574
575 if(inv->device != INVENSENSE3_ICM40609 && inv->accel_range < INVENSENSE3_ACCEL_RANGE_16G)
576 inv->accel_range = INVENSENSE3_ACCEL_RANGE_16G;
577 else if(inv->device == INVENSENSE3_ICM40609 && inv->accel_range > INVENSENSE3_ACCEL_RANGE_4G)
578 inv->accel_range = INVENSENSE3_ACCEL_RANGE_4G;
579
580 /* Fix the AAF bandwidth setting */
581 const uint16_t (*aaf_table)[4];
583 if(inv->device == INVENSENSE3_ICM40605 || inv->device == INVENSENSE3_ICM42605) {
586 }
587 else {
588 aaf_len = sizeof(invensense3_aaf) / sizeof(invensense3_aaf[0]);
590 }
591
592 uint16_t i = 0;
593 for(i = 0; i < aaf_len; i++) {
594 if(inv->gyro_aaf <= aaf_table[i][0]) {
595 inv->gyro_aaf = aaf_table[i][0];
596 RMAT_COPY(inv->gyro_aaf_regs, aaf_table[i]);
597 break;
598 }
599 }
600 if(i >= (aaf_len-1)) {
601 inv->gyro_aaf = aaf_table[aaf_len-1][0];
602 RMAT_COPY(inv->gyro_aaf_regs, aaf_table[aaf_len-1]);
603 }
604
605 for(i = 0; i < aaf_len; i++) {
606 if(inv->accel_aaf <= aaf_table[i][0]) {
607 inv->accel_aaf = aaf_table[i][0];
608 RMAT_COPY(inv->accel_aaf_regs, aaf_table[i]);
609 break;
610 }
611 }
612 if(i >= (aaf_len-1)) {
613 inv->accel_aaf = aaf_table[aaf_len-1][0];
614 RMAT_COPY(inv->accel_aaf_regs, aaf_table[aaf_len-1]);
615 }
616
617 /* Calculate the samplerates in Hz */
618 switch(inv->gyro_odr) {
620 inv->gyro_samplerate = 32000;
621 break;
623 inv->gyro_samplerate = 16000;
624 break;
626 inv->gyro_samplerate = 8000;
627 break;
629 inv->gyro_samplerate = 4000;
630 break;
632 inv->gyro_samplerate = 2000;
633 break;
635 inv->gyro_samplerate = 1000;
636 break;
638 inv->gyro_samplerate = 200;
639 break;
641 inv->gyro_samplerate = 100;
642 break;
644 inv->gyro_samplerate = 50;
645 break;
647 inv->gyro_samplerate = 25;
648 break;
650 inv->gyro_samplerate = 12.5;
651 break;
653 inv->gyro_samplerate = 6.25;
654 break;
656 inv->gyro_samplerate = 3.125;
657 break;
659 inv->gyro_samplerate = 1.5625;
660 break;
662 inv->gyro_samplerate = 500;
663 break;
664 }
665 switch(inv->accel_odr) {
667 inv->accel_samplerate = 32000;
668 break;
670 inv->accel_samplerate = 16000;
671 break;
673 inv->accel_samplerate = 8000;
674 break;
676 inv->accel_samplerate = 4000;
677 break;
679 inv->accel_samplerate = 2000;
680 break;
682 inv->accel_samplerate = 1000;
683 break;
685 inv->accel_samplerate = 200;
686 break;
688 inv->accel_samplerate = 100;
689 break;
691 inv->accel_samplerate = 50;
692 break;
694 inv->accel_samplerate = 25;
695 break;
697 inv->accel_samplerate = 12.5;
698 break;
700 inv->accel_samplerate = 6.25;
701 break;
703 inv->accel_samplerate = 3.125;
704 break;
706 inv->accel_samplerate = 1.5625;
707 break;
709 inv->accel_samplerate = 500;
710 break;
711 }
712
713 /* Set the default values */
716}
717
728 /* Split the register and bank */
729 uint8_t bank = bank_reg >> 8;
730 uint8_t reg = bank_reg & 0xFF;
731
732 /* Switch the register bank if needed */
734 return false;
735 }
736
737 inv->tx_buffer[0] = reg;
738 inv->tx_buffer[1] = value;
739
740 /* SPI transaction */
741 if(inv->bus == INVENSENSE3_SPI) {
742 inv->spi.trans.output_length = 2;
743 inv->spi.trans.input_length = 0;
744 spi_submit(inv->spi.p, &(inv->spi.trans));
745 }
746 /* I2C transaction */
747 else {
748 i2c_transmit(inv->i2c.p, &(inv->i2c.trans), inv->i2c.slave_addr, 2);
749 }
750
751 return true;
752}
753
764 /* Split the register and bank */
765 uint8_t bank = bank_reg >> 8;
766 uint8_t reg = bank_reg & 0xFF;
767
768 /* Switch the register bank if needed */
770 return false;
771 }
772
773 inv->tx_buffer[0] = reg | INV3_READ_FLAG;
774 /* SPI transaction */
775 if(inv->bus == INVENSENSE3_SPI) {
776 inv->spi.trans.output_length = 2;
777 inv->spi.trans.input_length = 1 + size;
778 inv->tx_buffer[1] = 0;
779 spi_submit(inv->spi.p, &(inv->spi.trans));
780 }
781 /* I2C transaction */
782 else {
783 i2c_transceive(inv->i2c.p, &(inv->i2c.trans), inv->i2c.slave_addr, 1, (1 + size));
784 }
785
786 return true;
787}
788
798 /* If we already selected the correct bank continue */
799 if(inv->register_bank == bank)
800 return false;
801
802 inv->tx_buffer[0] = INV3REG_BANK_SEL;
803 inv->tx_buffer[1] = bank;
804 /* SPI transaction */
805 if(inv->bus == INVENSENSE3_SPI) {
806 inv->spi.trans.output_length = 2;
807 inv->spi.trans.input_length = 0;
808 spi_submit(inv->spi.p, &(inv->spi.trans));
809 }
810 /* I2C transaction */
811 else {
812 i2c_transmit(inv->i2c.p, &(inv->i2c.trans), inv->i2c.slave_addr, 2);
813 }
814
815 return true;
816}
817
829
838 switch(inv->config_idx) {
839 case 0:
840 /* Reset the device */
842 inv->config_idx++;
843 inv->timer = get_sys_time_usec();
844 break;
845
846 case 1:
847 /* Because reset takes time wait ~5ms */
848 if((get_sys_time_usec() - inv->timer) < 5e3)
849 break;
850
851 /* Start the accel en gyro in low noise mode */
853 inv->config_idx++;
854 inv->timer = get_sys_time_usec();
855 break;
856
857 case 2:
858 /* Because starting takes time wait ~1ms */
859 if((get_sys_time_usec() - inv->timer) < 1e3)
860 break;
861
862 /* Configure the gyro ODR/FS */
864 inv->config_idx++;
865 break;
866
867 case 3: {
868 /* Configure the accel ODR/FS */
869 uint8_t accel_config = (inv->accel_odr << ACCEL_ODR_SHIFT);
870 if(inv->device == INVENSENSE3_ICM40609)
871 accel_config |= inv->accel_range << ACCEL_FS_SEL_SHIFT;
872 else
873 accel_config |= (inv->accel_range - 1) << ACCEL_FS_SEL_SHIFT;
874
876 inv->config_idx++;
877 break;
878 }
879
880 case 4:
881 /* Configure gyro AAF enable */
883 inv->config_idx++;
884 break;
885 case 5:
886 /* Configure gyro AAF DELT */
888 inv->config_idx++;
889 break;
890 case 6:
891 /* Configure gyro AAF DELTSQR lower */
892 if(invensense3_register_write(inv, INV3REG_GYRO_CONFIG_STATIC4, (inv->gyro_aaf_regs[2]&0xFF)))
893 inv->config_idx++;
894 break;
895 case 7:
896 /* Configure gyro AAF DELTSQR upper and bitshift */
897 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)))
898 inv->config_idx++;
899 break;
900 case 8:
901 /* Configure accel AAF enable and DELT */
903 inv->config_idx++;
904 break;
905 case 9:
906 /* Configure accel AAF DELTSQR lower */
907 if(invensense3_register_write(inv, INV3REG_ACCEL_CONFIG_STATIC3, (inv->accel_aaf_regs[2]&0xFF)))
908 inv->config_idx++;
909 break;
910 case 10:
911 /* Configure accel AAF DELTSQR upper and bitshift */
912 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)))
913 inv->config_idx++;
914 break;
915
916 case 11:
917 /* FIFO count in records (little-endian data) */
919 inv->config_idx++;
920 break;
921 case 12:
922 /* Disable AFSR, which changes noise sensitivity with angular rate, causing stuck gyro's for 2ms resulting in DC gyro bias */
924 inv->config_idx++;
925 break;
926 case 13:
927 /* FIFO Stop-on-Full mode (enable the FIFO) */
929 inv->config_idx++;
930 break;
931 case 14:
932 /* FIFO content: enable accel, gyro, temperature */
935 inv->config_idx++;
936 break;
937 case 15:
938 /* Set FIFO watermark to 1 (so that INT is triggered for each packet) */
940 inv->config_idx++;
941 break;
942 case 16:
943 /* Set FIFO watermark to 1 (so that INT is triggered for each packet) */
945 inv->config_idx++;
946 break;
947 case 17:
948 /* Enable interrupt pin/status */
949 switch(inv->parser) {
952 inv->config_idx++;
953 break;
956 inv->config_idx++;
957 break;
958 default:
959 break;
960 }
961 break;
962 case 18:
963 /* Interrupt pins ASYNC_RESET configuration */
964 // Datasheet: "User should change setting to 0 from default setting of 1, for proper INT1 and INT2 pin operation"
966 inv->config_idx++;
967 break;
968 case 19:
969 /* FIFO flush */
971 inv->config_idx++;
972 break;
973
974 default:
975 inv->timer = 0;
976 return true;
977 }
978 return false;
979}
980
981static int samples_from_odr(int odr) {
982 float freq = 0;
984 freq = 32000 / pow(2, odr-INVENSENSE3_GYRO_ODR_32KHZ);
985 }
986 else if(odr < INVENSENSE3_GYRO_ODR_500HZ) {
987 freq = 200 / pow(2, odr-INVENSENSE3_GYRO_ODR_200HZ);
988 }
989 else if(odr == INVENSENSE3_GYRO_ODR_500HZ) {
990 freq = 500;
991 } else {
992 // error
993 }
994 return ceilf(freq/PERIODIC_FREQUENCY);
995}
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:57
@ I2CTransFailed
transaction failed
Definition i2c.h:58
@ I2CTransDone
transaction set to done by user level
Definition i2c.h:59
#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: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.
#define GYRO_FS_SEL_SHIFT
#define ACCEL_FS_SEL_SHIFT
static const uint16_t invensense3_aaf4x605[][4]
static const struct Int32Vect3 invensense3_accel_scale[5][2]
Definition invensense3.c:70
void invensense3_periodic(struct invensense3_t *inv)
Should be called periodically to request sensor readings.
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:84
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 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 const struct Int32Rates invensense3_gyro_scale[8][2]
Definition invensense3.c:50
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 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.