Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
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"
32 #include "math/pprz_algebra_int.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 */
39 static void invensense3_parse_fifo_data(struct invensense3_t *inv, uint8_t *data, uint16_t samples);
40 static void invensense3_parse_reg_data(struct invensense3_t *inv, uint8_t *data);
41 static void invensense3_fix_config(struct invensense3_t *inv);
42 static bool invensense3_register_write(struct invensense3_t *inv, uint16_t bank_reg, uint8_t value);
43 static bool invensense3_register_read(struct invensense3_t *inv, uint16_t bank_reg, uint16_t size);
44 static bool invensense3_select_bank(struct invensense3_t *inv, uint8_t bank);
45 static bool invensense3_config(struct invensense3_t *inv);
46 static bool invensense3_reset_fifo(struct invensense3_t *inv);
47 static int samples_from_odr(int odr);
48 
49 /* Default gyro scalings */
50 static 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 */
70 static 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) */
84 static 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 
150 static 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 
216 static const uint8_t invensense3_fifo_sample_size[4] = {8,8,16,20};
217 
223 void invensense3_init(struct invensense3_t *inv) {
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 
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 
287  case INVENSENSE3_CONFIG:
288  /* Start configuring */
289  if(invensense3_config(inv)) {
291  }
292  break;
293 
294  case INVENSENSE3_RUNNING:
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];
304  read_bytes = Min(max_bytes, read_bytes);
305  // round to the packet boundaries
306  read_bytes -= read_bytes % invensense3_fifo_sample_size[inv->sample_size];
307  invensense3_register_read(inv, INV3REG_FIFO_COUNTH, read_bytes + 2);
308  inv->timer = 0; // reset leftover bytes
309  break;
310  }
311  default: break;
312  }
313 
314  default: break;
315  }
316  }
317 }
318 
327 void invensense3_event(struct invensense3_t *inv) {
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) {
350  } else if(inv->rx_buffer[1] == INV3_WHOAMI_ICM40609) {
352  } else if(inv->rx_buffer[1] == INV3_WHOAMI_ICM42605) {
354  } else if(inv->rx_buffer[1] == INV3_WHOAMI_IIM42652) {
356  } else if(inv->rx_buffer[1] == INV3_WHOAMI_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 
367  case INVENSENSE3_CONFIG:
368  /* Apply the next configuration register */
369  if(invensense3_config(inv)) {
371  }
372  break;
373 
374  case INVENSENSE3_RUNNING:
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];
402  invensense3_parse_fifo_data(inv, &inv->rx_buffer[3], Min(n_samples, nb_packets_read));
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) {
432  case INVENSENSE3_CONFIG:
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 */
438  if(invensense3_config(inv)) {
440  }
441  break;
442  case INVENSENSE3_IDLE:
443  case INVENSENSE3_RUNNING:
444  /* Ignore while idle/running */
445  default:
446  break;
447  }
448  }
449 }
450 
458 static void invensense3_parse_fifo_data(struct invensense3_t *inv, uint8_t *data, uint16_t samples) {
459  static struct Int32Vect3 accel[INVENSENSE3_FIFO_BUFFER_LEN] = {0};
460  static struct Int32Rates gyro[INVENSENSE3_FIFO_BUFFER_LEN] = {0};
461 
462  samples = Min(samples, INVENSENSE3_FIFO_BUFFER_LEN);
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;
475  uint16_t gyro_samplerate_count;
476  uint16_t accel_samplerate_count;
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);
484  if(gyro_samplerate_count % faster_odr == 0) {
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);
497  if(accel_samplerate_count % faster_odr == 0) {
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 
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
518  uint32_t now_ts = get_sys_time_usec();
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);
521  AbiSendMsgTEMPERATURE(inv->abi_id, temp_f);
522 }
523 
530 static void invensense3_parse_reg_data(struct invensense3_t *inv, uint8_t *data) {
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
547  uint32_t now_ts = get_sys_time_usec();
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);
550  AbiSendMsgTEMPERATURE(inv->abi_id, temp_f);
551 }
552 
558 static void invensense3_fix_config(struct invensense3_t *inv) {
559  /* Fix wrong configuration settings (prevent user error) */
562 
563  if(inv->device == INVENSENSE3_ICM40605 || inv->device == INVENSENSE3_ICM42605) {
566  else if(inv->gyro_odr < INVENSENSE3_GYRO_ODR_8KHZ)
568 
571  else if(inv->accel_odr < INVENSENSE3_ACCEL_ODR_8KHZ)
573  }
574 
579 
580  /* Fix the AAF bandwidth setting */
581  const uint16_t (*aaf_table)[4];
582  uint16_t aaf_len;
583  if(inv->device == INVENSENSE3_ICM40605 || inv->device == INVENSENSE3_ICM42605) {
584  aaf_len = sizeof(invensense3_aaf4x605) / sizeof(invensense3_aaf4x605[0]);
585  aaf_table = invensense3_aaf4x605;
586  }
587  else {
588  aaf_len = sizeof(invensense3_aaf) / sizeof(invensense3_aaf[0]);
589  aaf_table = invensense3_aaf;
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 
727 static bool invensense3_register_write(struct invensense3_t *inv, uint16_t bank_reg, uint8_t value) {
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 */
733  if(invensense3_select_bank(inv, bank)) {
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 
763 static bool invensense3_register_read(struct invensense3_t *inv, uint16_t bank_reg, uint16_t size) {
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 */
769  if(invensense3_select_bank(inv, bank)) {
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 
797 static bool invensense3_select_bank(struct invensense3_t *inv, uint8_t bank) {
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 
824 static bool invensense3_reset_fifo(struct invensense3_t *inv) {
826  return true;
827  return false;
828 }
829 
837 static bool invensense3_config(struct invensense3_t *inv) {
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 
875  if(invensense3_register_write(inv, INV3REG_ACCEL_CONFIG0, accel_config))
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 */
893  inv->config_idx++;
894  break;
895  case 7:
896  /* Configure gyro AAF DELTSQR upper and bitshift */
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 */
908  inv->config_idx++;
909  break;
910  case 10:
911  /* Configure accel AAF DELTSQR upper and bitshift */
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 */
970  if(invensense3_reset_fifo(inv))
971  inv->config_idx++;
972  break;
973 
974  default:
975  inv->timer = 0;
976  return true;
977  }
978  return false;
979 }
980 
981 static int samples_from_odr(int odr) {
982  float freq = 0;
983  if(odr < INVENSENSE3_GYRO_ODR_200HZ) {
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.
Definition: sys_time_arch.c:71
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: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
#define RMAT_COPY(_o, _i)
Definition: pprz_algebra.h:704
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]
Definition: invensense3.c:150
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.
Definition: invensense3.c:275
static void invensense3_parse_fifo_data(struct invensense3_t *inv, uint8_t *data, uint16_t samples)
Parse the FIFO buffer data.
Definition: invensense3.c:458
static int samples_from_odr(int odr)
Definition: invensense3.c:981
static const uint8_t invensense3_fifo_sample_size[4]
Definition: invensense3.c:216
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.
Definition: invensense3.c:530
static bool invensense3_reset_fifo(struct invensense3_t *inv)
Reset FIFO (can be useful in some situations)
Definition: invensense3.c:824
static bool invensense3_select_bank(struct invensense3_t *inv, uint8_t bank)
Select the correct register bank.
Definition: invensense3.c:797
void invensense3_event(struct invensense3_t *inv)
Should be called in the event thread.
Definition: invensense3.c:327
static bool invensense3_config(struct invensense3_t *inv)
Configure the Invensense 3 device register by register.
Definition: invensense3.c:837
static void invensense3_fix_config(struct invensense3_t *inv)
This fixes the configuration errors and sets the correct scalings.
Definition: invensense3.c:558
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.
Definition: invensense3.c:763
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.
Definition: invensense3.c:727
void invensense3_init(struct invensense3_t *inv)
Initialize the invensense v3 sensor instance.
Definition: invensense3.c:223
Driver for the Invensense V3 IMUs ICM40605, ICM40609, ICM42605, IIM42652 and ICM42688.
enum invensense3_gyro_range_t gyro_range
Gyro range configuration.
Definition: invensense3.h:174
@ INVENSENSE3_ACCEL_RANGE_16G
Definition: invensense3.h:147
@ INVENSENSE3_ACCEL_RANGE_4G
Definition: invensense3.h:149
uint8_t register_bank
The current register bank communicating with.
Definition: invensense3.h:169
enum invensense3_status_t status
Status of the invensense v3 device.
Definition: invensense3.h:156
uint16_t * rx_length
Definition: invensense3.h:167
@ INVENSENSE3_GYRO_ODR_4KHZ
Definition: invensense3.h:99
@ INVENSENSE3_GYRO_ODR_25HZ
Definition: invensense3.h:105
@ INVENSENSE3_GYRO_ODR_500HZ
Definition: invensense3.h:110
@ INVENSENSE3_GYRO_ODR_8KHZ
Definition: invensense3.h:98
@ INVENSENSE3_GYRO_ODR_1_5625HZ
Definition: invensense3.h:109
@ INVENSENSE3_GYRO_ODR_100HZ
Definition: invensense3.h:103
@ INVENSENSE3_GYRO_ODR_2KHZ
Definition: invensense3.h:100
@ INVENSENSE3_GYRO_ODR_50HZ
Definition: invensense3.h:104
@ INVENSENSE3_GYRO_ODR_1KHZ
Definition: invensense3.h:101
@ 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
Definition: invensense3.h:108
@ INVENSENSE3_GYRO_ODR_6_25HZ
Definition: invensense3.h:107
@ INVENSENSE3_GYRO_ODR_200HZ
Definition: invensense3.h:102
@ INVENSENSE3_GYRO_ODR_12_5HZ
Definition: invensense3.h:106
@ 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
enum invensense3_parser_t parser
Parser of the device.
Definition: invensense3.h:158
uint16_t accel_aaf
Accelerometer Anti-alias filter 3dB Bandwidth configuration [Hz].
Definition: invensense3.h:179
@ INVENSENSE3_PARSER_FIFO
Definition: invensense3.h:74
@ INVENSENSE3_PARSER_REGISTERS
Definition: invensense3.h:73
uint32_t timer
Used to time operations during configuration (samples left during measuring)
Definition: invensense3.h:171
enum invensense3_accel_odr_t accel_odr
Accelerometer Output Data Rate configuration.
Definition: invensense3.h:177
@ INVENSENSE3_ACCEL_ODR_4KHZ
Definition: invensense3.h:130
@ INVENSENSE3_ACCEL_ODR_16KHZ
Not possible for ICM40605 and ICM42605.
Definition: invensense3.h:128
@ INVENSENSE3_ACCEL_ODR_50HZ
Definition: invensense3.h:135
@ INVENSENSE3_ACCEL_ODR_32KHZ
Not possible for ICM40605 and ICM42605.
Definition: invensense3.h:127
@ INVENSENSE3_ACCEL_ODR_2KHZ
Definition: invensense3.h:131
@ INVENSENSE3_ACCEL_ODR_25HZ
Definition: invensense3.h:136
@ INVENSENSE3_ACCEL_ODR_1_5625HZ
Definition: invensense3.h:140
@ INVENSENSE3_ACCEL_ODR_8KHZ
Definition: invensense3.h:129
@ INVENSENSE3_ACCEL_ODR_6_25HZ
Definition: invensense3.h:138
@ INVENSENSE3_ACCEL_ODR_200HZ
Definition: invensense3.h:133
@ INVENSENSE3_ACCEL_ODR_100HZ
Definition: invensense3.h:134
@ INVENSENSE3_ACCEL_ODR_1KHZ
Definition: invensense3.h:132
@ INVENSENSE3_ACCEL_ODR_500HZ
Definition: invensense3.h:141
@ INVENSENSE3_ACCEL_ODR_12_5HZ
Definition: invensense3.h:137
@ INVENSENSE3_ACCEL_ODR_3_125HZ
Definition: invensense3.h:139
enum invensense3_bus_t bus
The communication bus used to connect the device SPI/I2C.
Definition: invensense3.h:160
uint8_t config_idx
The current configuration index.
Definition: invensense3.h:170
uint8_t * rx_buffer
Definition: invensense3.h:165
int sample_numbers
expected FIFO packet number, assuming reading at PERIODIC_FREQUENCY
Definition: invensense3.h:182
enum invensense3_device_t device
The device type detected.
Definition: invensense3.h:157
float gyro_samplerate
Sample rate in Hz from the gyro_odr.
Definition: invensense3.h:183
@ INVENSENSE3_I2C
Definition: invensense3.h:61
@ INVENSENSE3_SPI
Definition: invensense3.h:60
uint8_t * tx_buffer
Definition: invensense3.h:166
float accel_samplerate
Sample rate in Hz from the accel_odr.
Definition: invensense3.h:184
enum invensense3_accel_range_t accel_range
Accelerometer range configuration.
Definition: invensense3.h:178
enum invensense3_fifo_packet_t sample_size
FIFO packet size.
Definition: invensense3.h:181
@ INVENSENSE3_SAMPLE_SIZE_PK3
Definition: invensense3.h:80
uint16_t gyro_aaf_regs[4]
Gyro Anti-alias filter register values.
Definition: invensense3.h:176
uint8_t abi_id
The ABI id used to broadcast the device measurements.
Definition: invensense3.h:155
uint16_t accel_aaf_regs[4]
Accelerometer Anti-alias filter register values.
Definition: invensense3.h:180
uint16_t gyro_aaf
Gyro Anti-alias filter 3dB Bandwidth configuration [Hz].
Definition: invensense3.h:175
enum invensense3_gyro_odr_t gyro_odr
Gyro Output Data Rate configuration.
Definition: invensense3.h:173
#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
Paparazzi fixed point algebra.
Paparazzi atmospheric pressure conversion utilities.
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
Definition: vl53l1_types.h:88
int int32_t
Typedef defining 32 bit int type.
Definition: vl53l1_types.h:83
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
Definition: vl53l1_types.h:78
short int16_t
Typedef defining 16 bit short type.
Definition: vl53l1_types.h:93
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
Definition: vl53l1_types.h:98
signed char int8_t
Typedef defining 8 bit char type.
Definition: vl53l1_types.h:103