Icm20948DataBaseDriver.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. /*
  2. * ________________________________________________________________________________________________________
  3. * Copyright © 2014-2015 InvenSense Inc. Portions Copyright © 2014-2015 Movea. All rights reserved.
  4. * This software, related documentation and any modifications thereto (collectively “Software”) is subject
  5. * to InvenSense and its licensors' intellectual property rights under U.S. and international copyright and
  6. * other intellectual property rights laws.
  7. * InvenSense and its licensors retain all intellectual property and proprietary rights in and to the Software
  8. * and any use, reproduction, disclosure or distribution of the Software without an express license
  9. * agreement from InvenSense is strictly prohibited.
  10. * ________________________________________________________________________________________________________
  11. */
  12. #include "Icm20948.h"
  13. #include "Icm20948DataBaseDriver.h"
  14. #include "Icm20948Defs.h"
  15. #include "Icm20948DataBaseControl.h"
  16. #include "Icm20948AuxCompassAkm.h"
  17. #include "Icm20948AuxTransport.h"
  18. #include "Icm20948Dmp3Driver.h"
  19. static unsigned char inv_is_gyro_enabled(struct inv_icm20948 * s);
  20. void inv_icm20948_prevent_lpen_control(struct inv_icm20948 * s)
  21. {
  22. s->sAllowLpEn = 0;
  23. }
  24. void inv_icm20948_allow_lpen_control(struct inv_icm20948 * s)
  25. {
  26. s->sAllowLpEn = 1;
  27. inv_icm20948_set_chip_power_state(s, CHIP_LP_ENABLE, 1);
  28. }
  29. static uint8_t inv_icm20948_get_lpen_control(struct inv_icm20948 * s)
  30. {
  31. return s->sAllowLpEn;
  32. }
  33. /*!
  34. ******************************************************************************
  35. * @brief This function sets the power state of the Ivory chip
  36. * loop
  37. * @param[in] Function - CHIP_AWAKE, CHIP_LP_ENABLE
  38. * @param[in] On/Off - The functions are enabled if previously disabled and
  39. disabled if previously enabled based on the value of On/Off.
  40. ******************************************************************************
  41. */
  42. int inv_icm20948_set_chip_power_state(struct inv_icm20948 * s, unsigned char func, unsigned char on_off)
  43. {
  44. int status = 0;
  45. switch(func) {
  46. case CHIP_AWAKE:
  47. if(on_off){
  48. if((s->base_state.wake_state & CHIP_AWAKE) == 0) {// undo sleep_en
  49. s->base_state.pwr_mgmt_1 &= ~BIT_SLEEP;
  50. status = inv_icm20948_write_single_mems_reg_core(s, REG_PWR_MGMT_1, s->base_state.pwr_mgmt_1);
  51. s->base_state.wake_state |= CHIP_AWAKE;
  52. inv_icm20948_sleep_100us(1); // after writing the bit wait 100 Micro Seconds
  53. }
  54. } else {
  55. if(s->base_state.wake_state & CHIP_AWAKE) {// set sleep_en
  56. s->base_state.pwr_mgmt_1 |= BIT_SLEEP;
  57. status = inv_icm20948_write_single_mems_reg_core(s, REG_PWR_MGMT_1, s->base_state.pwr_mgmt_1);
  58. s->base_state.wake_state &= ~CHIP_AWAKE;
  59. inv_icm20948_sleep_100us(1); // after writing the bit wait 100 Micro Seconds
  60. }
  61. }
  62. break;
  63. case CHIP_LP_ENABLE:
  64. if(s->base_state.lp_en_support == 1) {
  65. if(on_off) {
  66. if( (inv_icm20948_get_lpen_control(s)) && ((s->base_state.wake_state & CHIP_LP_ENABLE) == 0)){
  67. s->base_state.pwr_mgmt_1 |= BIT_LP_EN; // lp_en ON
  68. status = inv_icm20948_write_single_mems_reg_core(s, REG_PWR_MGMT_1, s->base_state.pwr_mgmt_1);
  69. s->base_state.wake_state |= CHIP_LP_ENABLE;
  70. }
  71. } else {
  72. if(s->base_state.wake_state & CHIP_LP_ENABLE){
  73. s->base_state.pwr_mgmt_1 &= ~BIT_LP_EN; // lp_en off
  74. status = inv_icm20948_write_single_mems_reg_core(s, REG_PWR_MGMT_1, s->base_state.pwr_mgmt_1);
  75. s->base_state.wake_state &= ~CHIP_LP_ENABLE;
  76. inv_icm20948_sleep_100us(1); // after writing the bit wait 100 Micro Seconds
  77. }
  78. }
  79. }
  80. break;
  81. default:
  82. break;
  83. }// end switch
  84. return status;
  85. }
  86. /*!
  87. ******************************************************************************
  88. * @return Current wake status of the Ivory chip.
  89. ******************************************************************************
  90. */
  91. uint8_t inv_icm20948_get_chip_power_state(struct inv_icm20948 * s)
  92. {
  93. return s->base_state.wake_state;
  94. }
  95. /** Wakes up DMP3 (SMARTSENSOR).
  96. */
  97. int inv_icm20948_wakeup_mems(struct inv_icm20948 * s)
  98. {
  99. unsigned char data;
  100. int result = 0;
  101. result = inv_icm20948_set_chip_power_state(s, CHIP_AWAKE, 1);
  102. if(s->base_state.serial_interface == SERIAL_INTERFACE_SPI) {
  103. s->base_state.user_ctrl |= BIT_I2C_IF_DIS;
  104. inv_icm20948_write_single_mems_reg(s, REG_USER_CTRL, s->base_state.user_ctrl);
  105. }
  106. data = 0x47; // FIXME, should set up according to sensor/engines enabled.
  107. result |= inv_icm20948_write_mems_reg(s, REG_PWR_MGMT_2, 1, &data);
  108. if(s->base_state.firmware_loaded == 1) {
  109. s->base_state.user_ctrl |= BIT_DMP_EN | BIT_FIFO_EN;
  110. result |= inv_icm20948_write_single_mems_reg(s, REG_USER_CTRL, s->base_state.user_ctrl);
  111. }
  112. result |= inv_icm20948_set_chip_power_state(s, CHIP_LP_ENABLE, 1);
  113. return result;
  114. }
  115. /** Puts DMP3 (SMARTSENSOR) into the lowest power state. Assumes sensors are all off.
  116. */
  117. int inv_icm20948_sleep_mems(struct inv_icm20948 * s)
  118. {
  119. int result;
  120. unsigned char data;
  121. data = 0x7F;
  122. result = inv_icm20948_write_mems_reg(s, REG_PWR_MGMT_2, 1, &data);
  123. result |= inv_icm20948_set_chip_power_state(s, CHIP_AWAKE, 0);
  124. return result;
  125. }
  126. int inv_icm20948_set_dmp_address(struct inv_icm20948 * s)
  127. {
  128. int result;
  129. unsigned char dmp_cfg[2] = {0};
  130. unsigned short config;
  131. // Write DMP Start address
  132. inv_icm20948_get_dmp_start_address(s, &config);
  133. /* setup DMP start address and firmware */
  134. dmp_cfg[0] = (unsigned char)((config >> 8) & 0xff);
  135. dmp_cfg[1] = (unsigned char)(config & 0xff);
  136. result = inv_icm20948_write_mems_reg(s, REG_PRGM_START_ADDRH, 2, dmp_cfg);
  137. return result;
  138. }
  139. /**
  140. * @brief Set up the secondary I2C bus on 20630.
  141. * @param[in] MPU state varible
  142. * @return 0 if successful.
  143. */
  144. int inv_icm20948_set_secondary(struct inv_icm20948 * s)
  145. {
  146. int r = 0;
  147. static uint8_t lIsInited = 0;
  148. if(lIsInited == 0) {
  149. r = inv_icm20948_write_single_mems_reg(s, REG_I2C_MST_CTRL, BIT_I2C_MST_P_NSR);
  150. r |= inv_icm20948_write_single_mems_reg(s, REG_I2C_MST_ODR_CONFIG, MIN_MST_ODR_CONFIG);
  151. lIsInited = 1;
  152. }
  153. return r;
  154. }
  155. int inv_icm20948_enter_duty_cycle_mode(struct inv_icm20948 * s)
  156. {
  157. /* secondary cycle mode should be set all the time */
  158. unsigned char data = BIT_I2C_MST_CYCLE|BIT_ACCEL_CYCLE|BIT_GYRO_CYCLE;
  159. s->base_state.chip_lp_ln_mode = CHIP_LOW_POWER_ICM20948;
  160. return inv_icm20948_write_mems_reg(s, REG_LP_CONFIG, 1, &data);
  161. }
  162. int inv_icm20948_enter_low_noise_mode(struct inv_icm20948 * s)
  163. {
  164. /* secondary cycle mode should be set all the time */
  165. unsigned char data = BIT_I2C_MST_CYCLE;
  166. s->base_state.chip_lp_ln_mode = CHIP_LOW_NOISE_ICM20948;
  167. return inv_icm20948_write_mems_reg(s, REG_LP_CONFIG, 1, &data);
  168. }
  169. /** Should be called once on power up. Loads DMP3, initializes internal variables needed
  170. * for other lower driver functions.
  171. */
  172. int inv_icm20948_initialize_lower_driver(struct inv_icm20948 * s, enum SMARTSENSOR_SERIAL_INTERFACE type,
  173. const uint8_t *dmp3_image, uint32_t dmp3_image_size)
  174. {
  175. int result = 0;
  176. static unsigned char data;
  177. // set static variable
  178. s->sAllowLpEn = 1;
  179. s->s_compass_available = 0;
  180. // ICM20948 do not support the proximity sensor for the moment.
  181. // s_proximity_available variable is nerver changes
  182. s->s_proximity_available = 0;
  183. // Set varialbes to default values
  184. memset(&s->base_state, 0, sizeof(s->base_state));
  185. s->base_state.pwr_mgmt_1 = BIT_CLK_PLL;
  186. s->base_state.pwr_mgmt_2 = BIT_PWR_ACCEL_STBY | BIT_PWR_GYRO_STBY | BIT_PWR_PRESSURE_STBY;
  187. s->base_state.serial_interface = type;
  188. result |= inv_icm20948_read_mems_reg(s, REG_USER_CTRL, 1, &s->base_state.user_ctrl);
  189. result |= inv_icm20948_wakeup_mems(s);
  190. result |= inv_icm20948_read_mems_reg(s, REG_WHO_AM_I, 1, &data);
  191. /* secondary cycle mode should be set all the time */
  192. data = BIT_I2C_MST_CYCLE|BIT_ACCEL_CYCLE|BIT_GYRO_CYCLE;
  193. // Set default mode to low power mode
  194. result |= inv_icm20948_set_lowpower_or_highperformance(s, 0);
  195. // Disable Ivory DMP.
  196. if(s->base_state.serial_interface == SERIAL_INTERFACE_SPI)
  197. s->base_state.user_ctrl = BIT_I2C_IF_DIS;
  198. else
  199. s->base_state.user_ctrl = 0;
  200. result |= inv_icm20948_write_single_mems_reg(s, REG_USER_CTRL, s->base_state.user_ctrl);
  201. //Setup Ivory DMP.
  202. result |= inv_icm20948_load_firmware(s, dmp3_image, dmp3_image_size);
  203. if(result)
  204. return result;
  205. else
  206. s->base_state.firmware_loaded = 1;
  207. result |= inv_icm20948_set_dmp_address(s);
  208. // Turn off all sensors on DMP by default.
  209. //result |= dmp_set_data_output_control1(0); // FIXME in DMP, these should be off by default.
  210. result |= dmp_icm20948_reset_control_registers(s);
  211. // set FIFO watermark to 80% of actual FIFO size
  212. result |= dmp_icm20948_set_FIFO_watermark(s, 800);
  213. // Enable Interrupts.
  214. data = 0x2;
  215. result |= inv_icm20948_write_mems_reg(s, REG_INT_ENABLE, 1, &data); // Enable DMP Interrupt
  216. data = 0x1;
  217. result |= inv_icm20948_write_mems_reg(s, REG_INT_ENABLE_2, 1, &data); // Enable FIFO Overflow Interrupt
  218. // TRACKING : To have accelerometers datas and the interrupt without gyro enables.
  219. data = 0XE4;
  220. result |= inv_icm20948_write_mems_reg(s, REG_SINGLE_FIFO_PRIORITY_SEL, 1, &data);
  221. // Disable HW temp fix
  222. inv_icm20948_read_mems_reg(s, REG_HW_FIX_DISABLE,1,&data);
  223. data |= 0x08;
  224. inv_icm20948_write_mems_reg(s, REG_HW_FIX_DISABLE,1,&data);
  225. // Setup MEMs properties.
  226. s->base_state.accel_averaging = 1; //Change this value if higher sensor sample avergaing is required.
  227. s->base_state.gyro_averaging = 1; //Change this value if higher sensor sample avergaing is required.
  228. inv_icm20948_set_gyro_divider(s, FIFO_DIVIDER); //Initial sampling rate 1125Hz/19+1 = 56Hz.
  229. inv_icm20948_set_accel_divider(s, FIFO_DIVIDER); //Initial sampling rate 1125Hz/19+1 = 56Hz.
  230. // Init the sample rate to 56 Hz for BAC,STEPC and B2S
  231. dmp_icm20948_set_bac_rate(s, DMP_ALGO_FREQ_56);
  232. dmp_icm20948_set_b2s_rate(s, DMP_ALGO_FREQ_56);
  233. // FIFO Setup.
  234. result |= inv_icm20948_write_single_mems_reg(s, REG_FIFO_CFG, BIT_SINGLE_FIFO_CFG); // FIFO Config. fixme do once? burst write?
  235. result |= inv_icm20948_write_single_mems_reg(s, REG_FIFO_RST, 0x1f); // Reset all FIFOs.
  236. result |= inv_icm20948_write_single_mems_reg(s, REG_FIFO_RST, 0x1e); // Keep all but Gyro FIFO in reset.
  237. result |= inv_icm20948_write_single_mems_reg(s, REG_FIFO_EN, 0x0); // Slave FIFO turned off.
  238. result |= inv_icm20948_write_single_mems_reg(s, REG_FIFO_EN_2, 0x0); // Hardware FIFO turned off.
  239. s->base_state.lp_en_support = 1;
  240. if(s->base_state.lp_en_support == 1)
  241. inv_icm20948_set_chip_power_state(s, CHIP_LP_ENABLE, 1);
  242. result |= inv_icm20948_sleep_mems(s);
  243. return result;
  244. }
  245. static void activate_compass(struct inv_icm20948 * s)
  246. {
  247. s->s_compass_available = 1;
  248. }
  249. static void desactivate_compass(struct inv_icm20948 * s)
  250. {
  251. s->s_compass_available = 0;
  252. }
  253. int inv_icm20948_get_compass_availability(struct inv_icm20948 * s)
  254. {
  255. return s->s_compass_available;
  256. }
  257. // return true 1 if gyro was enabled, otherwise false 0
  258. static unsigned char inv_is_gyro_enabled(struct inv_icm20948 * s)
  259. {
  260. if ((s->inv_androidSensorsOn_mask[0] & INV_NEEDS_GYRO_MASK) || (s->inv_androidSensorsOn_mask[1] & INV_NEEDS_GYRO_MASK1))
  261. return 1;
  262. return 0;
  263. }
  264. int inv_icm20948_get_proximity_availability(struct inv_icm20948 * s)
  265. {
  266. return s->s_proximity_available;
  267. }
  268. int inv_icm20948_set_slave_compass_id(struct inv_icm20948 * s, int id)
  269. {
  270. int result = 0;
  271. (void)id;
  272. //result = inv_icm20948_wakeup_mems(s);
  273. //if (result)
  274. // return result;
  275. inv_icm20948_prevent_lpen_control(s);
  276. activate_compass(s);
  277. inv_icm20948_init_secondary(s);
  278. // Set up the secondary I2C bus on 20630.
  279. inv_icm20948_set_secondary(s);
  280. //Setup Compass
  281. result = inv_icm20948_setup_compass_akm(s);
  282. //Setup Compass mounting matrix into DMP
  283. result |= inv_icm20948_compass_dmp_cal(s, s->mounting_matrix, s->mounting_matrix_secondary_compass);
  284. if (result)
  285. desactivate_compass(s);
  286. //result = inv_icm20948_sleep_mems(s);
  287. inv_icm20948_allow_lpen_control(s);
  288. return result;
  289. }
  290. int inv_icm20948_set_gyro_divider(struct inv_icm20948 * s, unsigned char div)
  291. {
  292. s->base_state.gyro_div = div;
  293. return inv_icm20948_write_mems_reg(s, REG_GYRO_SMPLRT_DIV, 1, &div);
  294. }
  295. unsigned char inv_icm20948_get_gyro_divider(struct inv_icm20948 * s)
  296. {
  297. return s->base_state.gyro_div;
  298. }
  299. int inv_icm20948_set_secondary_divider(struct inv_icm20948 * s, unsigned char div)
  300. {
  301. s->base_state.secondary_div = 1UL<<div;
  302. return inv_icm20948_write_single_mems_reg(s, REG_I2C_MST_ODR_CONFIG, div);
  303. }
  304. unsigned short inv_icm20948_get_secondary_divider(struct inv_icm20948 * s)
  305. {
  306. return s->base_state.secondary_div;
  307. }
  308. int inv_icm20948_set_accel_divider(struct inv_icm20948 * s, short div)
  309. {
  310. unsigned char data[2] = {0};
  311. s->base_state.accel_div = div;
  312. data[0] = (unsigned char)(div >> 8);
  313. data[1] = (unsigned char)(div & 0xff);
  314. return inv_icm20948_write_mems_reg(s, REG_ACCEL_SMPLRT_DIV_1, 2, data);
  315. }
  316. short inv_icm20948_get_accel_divider(struct inv_icm20948 * s)
  317. {
  318. return s->base_state.accel_div;
  319. }
  320. /*
  321. You can obtain the real odr in Milliseconds, Micro Seconds or Ticks.
  322. Use the enum values: ODR_IN_Ms, ODR_IN_Us or ODR_IN_Ticks,
  323. when calling inv_icm20948_get_odr_in_units().
  324. */
  325. uint32_t inv_icm20948_get_odr_in_units(struct inv_icm20948 * s, unsigned short odrInDivider, unsigned char odr_units )
  326. {
  327. unsigned long odr=0;
  328. unsigned long Us=0;
  329. unsigned char PLL=0, gyro_is_on=0;
  330. if(s->base_state.timebase_correction_pll == 0)
  331. inv_icm20948_read_mems_reg(s, REG_TIMEBASE_CORRECTION_PLL, 1, &s->base_state.timebase_correction_pll);
  332. PLL = s->base_state.timebase_correction_pll;
  333. // check if Gyro is currently enabled
  334. gyro_is_on = inv_is_gyro_enabled(s);
  335. if( PLL < 0x80 ) { // correction positive
  336. // In Micro Seconds
  337. Us = (odrInDivider*1000000L/1125L) * (1270L)/(1270L+ (gyro_is_on ? PLL : 0));
  338. }
  339. else {
  340. PLL &= 0x7F;
  341. // In Micro Seconds
  342. Us = (odrInDivider*1000000L/1125L) * (1270L)/(1270L-(gyro_is_on ? PLL : 0));
  343. }
  344. switch( odr_units ) {
  345. // ret in Milliseconds
  346. case ODR_IN_Ms:
  347. odr = Us/1000;
  348. break;
  349. // ret in Micro
  350. case ODR_IN_Us:
  351. odr = Us;
  352. break;
  353. // ret in Ticks
  354. case ODR_IN_Ticks:
  355. odr = (Us/1000) * (32768/1125);// According to Mars
  356. break;
  357. }
  358. return odr;
  359. }
  360. /**
  361. * Sets the DMP for a particular gyro configuration.
  362. * @param[in] gyro_div Value written to GYRO_SMPLRT_DIV register, where
  363. * 0=1125Hz sample rate, 1=562.5Hz sample rate, ... 4=225Hz sample rate, ...
  364. * 10=102.2727Hz sample rate, ... etc.
  365. * @param[in] gyro_level 0=250 dps, 1=500 dps, 2=1000 dps, 3=2000 dps
  366. */
  367. int inv_icm20948_set_gyro_sf(struct inv_icm20948 * s, unsigned char div, int gyro_level)
  368. {
  369. long gyro_sf;
  370. static long lLastGyroSf = 0;
  371. int result = 0;
  372. // gyro_level should be set to 4 regardless of fullscale, due to the addition of API dmp_icm20648_set_gyro_fsr()
  373. gyro_level = 4;
  374. if(s->base_state.timebase_correction_pll == 0)
  375. result |= inv_icm20948_read_mems_reg(s, REG_TIMEBASE_CORRECTION_PLL, 1, &s->base_state.timebase_correction_pll);
  376. {
  377. unsigned long long const MagicConstant = 264446880937391LL;
  378. unsigned long long const MagicConstantScale = 100000LL;
  379. unsigned long long ResultLL;
  380. if (s->base_state.timebase_correction_pll & 0x80) {
  381. ResultLL = (MagicConstant * (long long)(1ULL << gyro_level) * (1 + div) / (1270 - (s->base_state.timebase_correction_pll & 0x7F)) / MagicConstantScale);
  382. }
  383. else {
  384. ResultLL = (MagicConstant * (long long)(1ULL << gyro_level) * (1 + div) / (1270 + s->base_state.timebase_correction_pll) / MagicConstantScale);
  385. }
  386. /*
  387. In above deprecated FP version, worst case arguments can produce a result that overflows a signed long.
  388. Here, for such cases, we emulate the FP behavior of setting the result to the maximum positive value, as
  389. the compiler's conversion of a u64 to an s32 is simple truncation of the u64's high half, sadly....
  390. */
  391. if (ResultLL > 0x7FFFFFFF)
  392. gyro_sf = 0x7FFFFFFF;
  393. else
  394. gyro_sf = (long)ResultLL;
  395. }
  396. if (gyro_sf != lLastGyroSf) {
  397. result |= dmp_icm20948_set_gyro_sf(s, gyro_sf);
  398. lLastGyroSf = gyro_sf;
  399. }
  400. return result;
  401. }
  402. int inv_icm20948_set_gyro_fullscale(struct inv_icm20948 * s, int level)
  403. {
  404. int result;
  405. s->base_state.gyro_fullscale = level;
  406. result = inv_icm20948_set_icm20948_gyro_fullscale(s, level);
  407. result |= inv_icm20948_set_gyro_sf(s, s->base_state.gyro_div, level);
  408. result |= dmp_icm20948_set_gyro_fsr(s, 250<<level);
  409. return result;
  410. }
  411. uint8_t inv_icm20948_get_gyro_fullscale(struct inv_icm20948 * s)
  412. {
  413. return s->base_state.gyro_fullscale;
  414. }
  415. int inv_icm20948_set_icm20948_gyro_fullscale(struct inv_icm20948 * s, int level)
  416. {
  417. int result = 0;
  418. unsigned char gyro_config_1_reg;
  419. unsigned char gyro_config_2_reg;
  420. unsigned char dec3_cfg;
  421. if (level >= NUM_MPU_GFS)
  422. return -1;
  423. result |= inv_icm20948_read_mems_reg(s, REG_GYRO_CONFIG_1, 1, &gyro_config_1_reg);
  424. gyro_config_1_reg &= 0xC0;
  425. gyro_config_1_reg |= (level << 1) | 1; //fchoice = 1, filter = 0.
  426. result |= inv_icm20948_write_mems_reg(s, REG_GYRO_CONFIG_1, 1, &gyro_config_1_reg);
  427. result |= inv_icm20948_read_mems_reg(s, REG_GYRO_CONFIG_2, 1, &gyro_config_2_reg);
  428. gyro_config_2_reg &= 0xF8;
  429. switch(s->base_state.gyro_averaging) {
  430. case 1:
  431. dec3_cfg = 0;
  432. break;
  433. case 2:
  434. dec3_cfg = 1;
  435. break;
  436. case 4:
  437. dec3_cfg = 2;
  438. break;
  439. case 8:
  440. dec3_cfg = 3;
  441. break;
  442. case 16:
  443. dec3_cfg = 4;
  444. break;
  445. case 32:
  446. dec3_cfg = 5;
  447. break;
  448. case 64:
  449. dec3_cfg = 6;
  450. break;
  451. case 128:
  452. dec3_cfg = 7;
  453. break;
  454. default:
  455. dec3_cfg = 0;
  456. break;
  457. }
  458. gyro_config_2_reg |= dec3_cfg;
  459. result |= inv_icm20948_write_single_mems_reg(s, REG_GYRO_CONFIG_2, gyro_config_2_reg);
  460. return result;
  461. }
  462. int inv_icm20948_set_accel_fullscale(struct inv_icm20948 * s, int level)
  463. {
  464. int result;
  465. s->base_state.accel_fullscale = level;
  466. result = inv_icm20948_set_icm20948_accel_fullscale(s, level);
  467. result |= dmp_icm20948_set_accel_fsr(s, 2<<level);
  468. result |= dmp_icm20948_set_accel_scale2(s, 2<<level);
  469. return result;
  470. }
  471. uint8_t inv_icm20948_get_accel_fullscale(struct inv_icm20948 * s)
  472. {
  473. return s->base_state.accel_fullscale;
  474. }
  475. int inv_icm20948_set_icm20948_accel_fullscale(struct inv_icm20948 * s, int level)
  476. {
  477. int result = 0;
  478. unsigned char accel_config_1_reg;
  479. unsigned char accel_config_2_reg;
  480. unsigned char dec3_cfg;
  481. if (level >= NUM_MPU_AFS)
  482. return -1;
  483. result |= inv_icm20948_read_mems_reg(s, REG_ACCEL_CONFIG, 1, &accel_config_1_reg);
  484. accel_config_1_reg &= 0xC0;
  485. if(s->base_state.accel_averaging > 1)
  486. accel_config_1_reg |= (7 << 3) | (level << 1) | 1; //fchoice = 1, filter = 7.
  487. else
  488. accel_config_1_reg |= (level << 1) | 0; //fchoice = 0, filter = 0.
  489. /* /!\ FCHOICE=0 considers we are in low power mode always and allows us to have correct values on raw data since not averaged,
  490. in case low noise mode is to be supported for 20649, please reconsider this value and update base sample rate from 1125 to 4500...
  491. */
  492. result |= inv_icm20948_write_single_mems_reg(s, REG_ACCEL_CONFIG, accel_config_1_reg);
  493. switch(s->base_state.accel_averaging) {
  494. case 1:
  495. dec3_cfg = 0;
  496. break;
  497. case 4:
  498. dec3_cfg = 0;
  499. break;
  500. case 8:
  501. dec3_cfg = 1;
  502. break;
  503. case 16:
  504. dec3_cfg = 2;
  505. break;
  506. case 32:
  507. dec3_cfg = 3;
  508. break;
  509. default:
  510. dec3_cfg = 0;
  511. break;
  512. }
  513. result |= inv_icm20948_read_mems_reg(s, REG_ACCEL_CONFIG_2, 1, &accel_config_2_reg);
  514. accel_config_2_reg &= 0xFC;
  515. accel_config_2_reg |= dec3_cfg;
  516. result |= inv_icm20948_write_single_mems_reg(s, REG_ACCEL_CONFIG_2, accel_config_2_reg);
  517. return result;
  518. }
  519. int inv_icm20948_enable_hw_sensors(struct inv_icm20948 * s, int bit_mask)
  520. {
  521. int rc = 0;
  522. if ((s->base_state.pwr_mgmt_2 == (BIT_PWR_ACCEL_STBY | BIT_PWR_GYRO_STBY | BIT_PWR_PRESSURE_STBY)) | (bit_mask & 0x80)) {
  523. // All sensors off, or override is on
  524. s->base_state.pwr_mgmt_2 = 0; // Zero means all sensors are on
  525. // Gyro and Accel were off
  526. if ((bit_mask & 2) == 0) {
  527. s->base_state.pwr_mgmt_2 = BIT_PWR_ACCEL_STBY; // Turn off accel
  528. }
  529. if ((bit_mask & 1) == 0) {
  530. s->base_state.pwr_mgmt_2 |= BIT_PWR_GYRO_STBY; // Turn off gyro
  531. }
  532. if ((bit_mask & 4) == 0) {
  533. s->base_state.pwr_mgmt_2 |= BIT_PWR_PRESSURE_STBY; // Turn off pressure
  534. }
  535. rc |= inv_icm20948_write_mems_reg(s, REG_PWR_MGMT_2, 1, &s->base_state.pwr_mgmt_2);
  536. }
  537. if (bit_mask & SECONDARY_COMPASS_AVAILABLE) {
  538. rc |= inv_icm20948_resume_akm(s);
  539. }
  540. else {
  541. rc |= inv_icm20948_suspend_akm(s);
  542. }
  543. return rc;
  544. }
  545. int inv_icm20948_set_serial_comm(struct inv_icm20948 * s, enum SMARTSENSOR_SERIAL_INTERFACE type)
  546. {
  547. s->base_state.serial_interface = type;
  548. return 0;
  549. }
  550. int inv_icm20948_set_int1_assertion(struct inv_icm20948 * s, int enable)
  551. {
  552. int result = 0;
  553. // unsigned char reg_pin_cfg;
  554. unsigned char reg_int_enable;
  555. // INT1 held until interrupt status is cleared
  556. /*
  557. result |= inv_icm20948_read_mems_reg(s, REG_INT_PIN_CFG, 1, &reg_pin_cfg);
  558. reg_pin_cfg |= BIT_INT_LATCH_EN ; // Latchen : BIT5 held the IT until register is read
  559. result |= inv_icm20948_write_single_mems_reg(s, REG_INT_PIN_CFG, reg_pin_cfg);
  560. */
  561. // Set int1 enable
  562. result |= inv_icm20948_read_mems_reg(s, REG_INT_ENABLE, 1, &reg_int_enable);
  563. if(enable) { // Enable bit
  564. reg_int_enable |= BIT_DMP_INT_EN;
  565. }
  566. else { // Disable bit
  567. reg_int_enable &= ~BIT_DMP_INT_EN;
  568. }
  569. result |= inv_icm20948_write_single_mems_reg(s, REG_INT_ENABLE, reg_int_enable);
  570. return result;
  571. }
  572. /**
  573. * @brief Read accel data stored in hw reg
  574. * @param[in] level See mpu_accel_fs
  575. * @return 0 if successful
  576. */
  577. int inv_icm20948_accel_read_hw_reg_data(struct inv_icm20948 * s, short accel_hw_reg_data[3])
  578. {
  579. int result = 0;
  580. uint8_t accel_data[6]; // Store 6 bytes for that
  581. // read mem regs
  582. result = inv_icm20948_read_mems_reg(s, REG_ACCEL_XOUT_H_SH, 6, (unsigned char *) &accel_data);
  583. // Assign axys !
  584. accel_hw_reg_data[0] = (accel_data[0] << 8) + accel_data[1];
  585. accel_hw_reg_data[1] = (accel_data[2] << 8) + accel_data[3];
  586. accel_hw_reg_data[2] = (accel_data[4] << 8) + accel_data[5];
  587. return result;
  588. }