Icm20948AuxTransport.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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 "Icm20948Defs.h"
  14. #include "Icm20948DataBaseDriver.h"
  15. #include "Icm20948AuxTransport.h"
  16. void inv_icm20948_init_secondary(struct inv_icm20948 * s)
  17. {
  18. s->secondary_state.slv_reg[0].addr = REG_I2C_SLV0_ADDR;
  19. s->secondary_state.slv_reg[0].reg = REG_I2C_SLV0_REG;
  20. s->secondary_state.slv_reg[0].ctrl = REG_I2C_SLV0_CTRL;
  21. s->secondary_state.slv_reg[0].d0 = REG_I2C_SLV0_DO;
  22. s->secondary_state.slv_reg[1].addr = REG_I2C_SLV1_ADDR;
  23. s->secondary_state.slv_reg[1].reg = REG_I2C_SLV1_REG;
  24. s->secondary_state.slv_reg[1].ctrl = REG_I2C_SLV1_CTRL;
  25. s->secondary_state.slv_reg[1].d0 = REG_I2C_SLV1_DO;
  26. s->secondary_state.slv_reg[2].addr = REG_I2C_SLV2_ADDR;
  27. s->secondary_state.slv_reg[2].reg = REG_I2C_SLV2_REG;
  28. s->secondary_state.slv_reg[2].ctrl = REG_I2C_SLV2_CTRL;
  29. s->secondary_state.slv_reg[2].d0 = REG_I2C_SLV2_DO;
  30. s->secondary_state.slv_reg[3].addr = REG_I2C_SLV3_ADDR;
  31. s->secondary_state.slv_reg[3].reg = REG_I2C_SLV3_REG;
  32. s->secondary_state.slv_reg[3].ctrl = REG_I2C_SLV3_CTRL;
  33. s->secondary_state.slv_reg[3].d0 = REG_I2C_SLV3_DO;
  34. /* Make sure that by default all channels are disabled
  35. To not inherit from a previous configuration from a previous run*/
  36. inv_icm20948_secondary_stop_channel(s, 0);
  37. inv_icm20948_secondary_stop_channel(s, 1);
  38. inv_icm20948_secondary_stop_channel(s, 2);
  39. inv_icm20948_secondary_stop_channel(s, 3);
  40. }
  41. /* the following functions are used for configuring the secondary devices */
  42. /*
  43. * inv_configure_secondary_read(): set secondary registers for reading.
  44. The chip must be set as bank 3 before calling.
  45. * This is derived from inv_icm20948_read_secondary in linux...
  46. * for now, uses a very simple data struct for the registers
  47. *
  48. * index gives the mapping to the particular SLVx registers
  49. * addr is the physical address of the device to be accessed
  50. * reg is the device register we wish to access
  51. * len is the number of bytes to be read
  52. *
  53. */
  54. int inv_icm20948_read_secondary(struct inv_icm20948 * s, int index, unsigned char addr, unsigned char reg, char len)
  55. {
  56. int result = 0;
  57. unsigned char data;
  58. data = INV_MPU_BIT_I2C_READ | addr;
  59. result |= inv_icm20948_write_mems_reg(s, s->secondary_state.slv_reg[index].addr, 1, &data);
  60. data = reg;
  61. result |= inv_icm20948_write_mems_reg(s, s->secondary_state.slv_reg[index].reg, 1, &data);
  62. data = INV_MPU_BIT_SLV_EN | len;
  63. result |= inv_icm20948_write_mems_reg(s, s->secondary_state.slv_reg[index].ctrl, 1, &data);
  64. return result;
  65. }
  66. int inv_icm20948_execute_read_secondary(struct inv_icm20948 * s, int index, unsigned char addr, int reg, int len, uint8_t *d)
  67. {
  68. int result = 0;
  69. result |= inv_icm20948_read_secondary(s, index, addr, reg, len);
  70. result |= inv_icm20948_secondary_enable_i2c(s);
  71. inv_icm20948_sleep(SECONDARY_INIT_WAIT);
  72. result |= inv_icm20948_secondary_disable_i2c(s);
  73. result |= inv_icm20948_read_mems_reg(s, REG_EXT_SLV_SENS_DATA_00, len, d);
  74. result |= inv_icm20948_secondary_stop_channel(s, index);
  75. return result;
  76. }
  77. /*
  78. * inv_icm20948_write_secondary(): set secondary registers for writing?.
  79. The chip must be set as bank 3 before calling.
  80. * This is derived from inv_icm20948_write_secondary in linux...
  81. * for now, uses a very simple data struct for the registers
  82. *
  83. * index gives the mapping to the particular SLVx registers
  84. * addr is the physical address of the device to be accessed
  85. * reg is the device register we wish to access
  86. * len is the number of bytes to be read
  87. *
  88. */
  89. int inv_icm20948_write_secondary(struct inv_icm20948 * s, int index, unsigned char addr, unsigned char reg, char v)
  90. {
  91. int result = 0;
  92. unsigned char data;
  93. data = (unsigned char)addr;
  94. result |= inv_icm20948_write_mems_reg(s, s->secondary_state.slv_reg[index].addr, 1, &data);
  95. data = reg;
  96. result |= inv_icm20948_write_mems_reg(s, s->secondary_state.slv_reg[index].reg, 1, &data);
  97. data = v;
  98. result |= inv_icm20948_write_mems_reg(s, s->secondary_state.slv_reg[index].d0, 1, &data);
  99. data = INV_MPU_BIT_SLV_EN | 1;
  100. result |= inv_icm20948_write_mems_reg(s, s->secondary_state.slv_reg[index].ctrl, 1, &data);
  101. return result;
  102. }
  103. int inv_icm20948_execute_write_secondary(struct inv_icm20948 * s, int index, unsigned char addr, int reg, uint8_t v)
  104. {
  105. int result = 0;
  106. result |= inv_icm20948_write_secondary(s, index, addr, reg, v);
  107. result |= inv_icm20948_secondary_enable_i2c(s);
  108. inv_icm20948_sleep(SECONDARY_INIT_WAIT);
  109. result |= inv_icm20948_secondary_disable_i2c(s);
  110. result |= inv_icm20948_secondary_stop_channel(s, index);
  111. return result;
  112. }
  113. void inv_icm20948_secondary_saveI2cOdr(struct inv_icm20948 * s)
  114. {
  115. inv_icm20948_read_mems_reg(s, REG_I2C_MST_ODR_CONFIG,1,&s->secondary_state.sSavedI2cOdr);
  116. }
  117. void inv_icm20948_secondary_restoreI2cOdr(struct inv_icm20948 * s)
  118. {
  119. inv_icm20948_write_single_mems_reg(s, REG_I2C_MST_ODR_CONFIG,s->secondary_state.sSavedI2cOdr);
  120. }
  121. int inv_icm20948_secondary_stop_channel(struct inv_icm20948 * s, int index)
  122. {
  123. return inv_icm20948_write_single_mems_reg(s, s->secondary_state.slv_reg[index].ctrl, 0);
  124. }
  125. int inv_icm20948_secondary_enable_i2c(struct inv_icm20948 * s)
  126. {
  127. s->base_state.user_ctrl |= BIT_I2C_MST_EN;
  128. return inv_icm20948_write_single_mems_reg(s, REG_USER_CTRL, s->base_state.user_ctrl);
  129. }
  130. int inv_icm20948_secondary_disable_i2c(struct inv_icm20948 * s)
  131. {
  132. s->base_state.user_ctrl &= ~BIT_I2C_MST_EN;
  133. return inv_icm20948_write_single_mems_reg(s, REG_USER_CTRL, s->base_state.user_ctrl);
  134. }
  135. int inv_icm20948_secondary_set_odr(struct inv_icm20948 * s, int divider, unsigned int* effectiveDivider)
  136. {
  137. int mst_odr_config = 0;
  138. // find 2^x = divider to fit BASE_SAMPLE_RATE/2^REG_I2C_MST_ODR_CONFIG
  139. do
  140. {
  141. divider>>=1;
  142. mst_odr_config++;
  143. } while(divider>>1);
  144. if (mst_odr_config < MIN_MST_ODR_CONFIG)
  145. mst_odr_config = MIN_MST_ODR_CONFIG;
  146. *effectiveDivider = 1<<mst_odr_config;
  147. return inv_icm20948_set_secondary_divider(s, (unsigned char)mst_odr_config);
  148. }