Icm20948DataConverter.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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. /** @defgroup icm20948_data_converter data_converter
  13. @ingroup SmartSensor_driver
  14. @{
  15. */
  16. #ifndef INV_ICM20948_DATA_CONVERTER_H__
  17. #define INV_ICM20948_DATA_CONVERTER_H__
  18. #ifdef __cplusplus
  19. extern "C"
  20. {
  21. #endif
  22. /* forward declaration */
  23. struct inv_icm20948;
  24. #ifndef M_PI
  25. #define M_PI 3.14159265358979323846f
  26. #endif
  27. #define INV_TWO_POWER_NEG_30 9.313225746154785e-010f
  28. #define ABS(x) (((x)>=0)?(x):-(x)) /*!< Computes the absolute value of its argument \a x. \ingroup invn_macro */
  29. #define MAX(x,y) (((x)>(y))?(x):(y)) /*!< Computes the maximum of \a x and \a y. \ingroup invn_macro*/
  30. #define MIN(x,y) (((x)<(y))?(x):(y)) /*!< Computes the minimum of \a x and \a y. \ingroup invn_macro */
  31. //! \def INVN_FLT_TO_FXP
  32. //! Convert the \a value from float to QN value. \ingroup invn_macro
  33. #define INVN_FLT_TO_FXP(value, shift) ( (int32_t) ((float)(value)*(1ULL << (shift)) + ( (value>=0)-0.5f )) )
  34. //! Macro to convert float values from an address into QN values, and copy them to another address. \ingroup invn_macro
  35. #define INVN_CONVERT_FLT_TO_FXP(fltptr, fixptr, length, shift) { int i; for(i=0; i<(length); ++i) (fixptr)[i] = INVN_FLT_TO_FXP((fltptr)[i], shift); }
  36. /** Performs a fixed point quaternion multiply with inverse on second element q1*q2'.
  37. * @param[in] q1 First Quaternion Multicand, length 4. 1.0 scaled
  38. * to 2^30
  39. * @param[in] q2 Second Quaternion Multicand, length 4. 1.0 scaled
  40. * to 2^30. Inverse will be take before multiply
  41. * @param[out] qProd Product after quaternion multiply q1*q2'. Length 4.
  42. * 1.0 scaled to 2^30.
  43. */
  44. void INV_EXPORT inv_icm20948_q_mult_q_qi(const long *q1, const long *q2, long *qProd);
  45. /** @brief Sets the transformation used for chip to body frame
  46. * @param[in] quat the quaternion used for the transformation
  47. */
  48. void INV_EXPORT inv_icm20948_set_chip_to_body(struct inv_icm20948 * s, long *quat);
  49. /** @brief Converts fixed point DMP rotation vector to floating point android notation
  50. * @param[in] quat 3 element rotation vector from DMP, missing the scalar part. Converts from Chip frame to World frame
  51. * @param[out] values 4 element quaternion in Android format
  52. */
  53. void INV_EXPORT inv_icm20948_convert_rotation_vector(struct inv_icm20948 * s, const long *quat, float *values);
  54. /** @brief Converts 3 element fixed point DMP rotation vector to 4 element rotation vector in world frame
  55. * @param[in] quat 3 element rotation vector from DMP, missing the scalar part. Converts from Chip frame to World frame
  56. * @param[out] quat4_world 4 element quaternion
  57. */
  58. void INV_EXPORT inv_icm20948_convert_rotation_vector_2(struct inv_icm20948 * s, const long *quat, long *quat4_world);
  59. /** @brief Converts 4 element rotation vector in world frame to floating point android notation
  60. * @param[in] quat4_world 4 element rotation vector in World frame
  61. * @param[out] values in Android format
  62. */
  63. void INV_EXPORT inv_icm20948_convert_rotation_vector_3(const long *quat4_world, float *values);
  64. /** @brief Converts the data in android values
  65. * @param[in] vec3 vector of the DMP
  66. * @param[in] scale scale calculated
  67. * @param[out] values in Android format
  68. */
  69. void INV_EXPORT inv_icm20948_convert_dmp3_to_body(struct inv_icm20948 * s, const long *vec3, float scale, float *values);
  70. /** @brief Converts the data in android quaternion values
  71. * @param[in] accel_gyro_matrix vector of the DMP
  72. * @param[out] angle angle calculated
  73. */
  74. void INV_EXPORT inv_icm20948_set_chip_to_body_axis_quaternion(struct inv_icm20948 * s,signed char *accel_gyro_matrix, float angle);
  75. /** @brief Converts a 32-bit long to a little endian byte stream
  76. * @param[in] x the long to be converted
  77. * @param[in] little8 little endian byte converted
  78. * @return 0 on success, negative value on error.
  79. */
  80. unsigned char INV_EXPORT *inv_icm20948_int32_to_little8(long x, unsigned char *little8);
  81. /** @brief Converts degree angle to radian
  82. * @param[in] deg_val the angle in degree
  83. * @return the angle in radian
  84. */
  85. float INV_EXPORT inv_icm20948_convert_deg_to_rad(float deg_val);
  86. /** Performs a multiply and shift by 30.
  87. * \details These are good functions to write in assembly on
  88. * with devices with small memory where you want to get rid of the long long which some
  89. * assemblers don't handle well
  90. * @param[in] a
  91. * @param[in] b
  92. * @return ((long long)a*b)>>30
  93. \ingroup ScalarFxp
  94. */
  95. long INV_EXPORT inv_icm20948_convert_mult_q30_fxp(long a_q30, long b_q30);
  96. /**
  97. * \brief Compute real part of quaternion, element[0]
  98. * @param[in] inQuat_q30 3 elements gyro quaternion. Dimension is 3.
  99. * @param[out] outQuat_q30 Quaternion. Dimension is 4. 4 elements gyro quaternion
  100. * \return 0
  101. * \ingroup QuaternionFxp
  102. */
  103. // FIXME Define input format and output format. Supposed Q30.
  104. int INV_EXPORT inv_icm20948_convert_compute_scalar_part_fxp(const long * inQuat_q30, long* outQuat_q30);
  105. /**
  106. * \brief Calculates square-root of a fixed-point number (30 bit mantissa, positive)
  107. * \details Input must be a positive scaled ( \f$ 2^{30} \f$ ) integer
  108. * The number is scaled to lie between a range in which a Newton-Raphson
  109. * iteration works best.
  110. * @param[in] x0_q30 length 1. Fixed point format is Q30
  111. * @return scaled square root if succeed else 0.
  112. \ingroup ScalarFxp
  113. **/
  114. long INV_EXPORT inv_icm20948_convert_fast_sqrt_fxp(long x0_q30);
  115. /** \brief Auxiliary function used by inv_OneOverX(), inv_fastSquareRoot(), inv_inverseSqrt().
  116. * \details Finds the range of the argument, determines the optimal number of Newton-Raphson
  117. * iterations and .
  118. * Restrictions: Number is represented as Q1.30.
  119. * Number is betweeen the range 2<x<=0
  120. * @param[in] x0_q30 Input length 1. Number is represented as Q30. Number is betweeen the range 2<x<=0
  121. * @param[out] pow Corresponding square root of the power of two is returned. length 1
  122. * @return number of Newton Raphson iterations, x0 scaled between log(2) and log(4) and \f$ 2^N \f$ scaling (N=pow)
  123. \ingroup ScalarFxp
  124. */
  125. int INV_EXPORT inv_icm20948_convert_test_limits_and_scale_fxp(long *x0_q30, int *pow);
  126. /** Auxiliary function used by testLimitsAndScale()
  127. * Find the highest nonzero bit in an unsigned 32 bit integer:
  128. * @param[in] value operand Dimension is 1.
  129. * @return highest bit position.
  130. * \note This function performs the log2 of an interger as well.
  131. * \ingroup binary
  132. **/
  133. int16_t INV_EXPORT inv_icm20948_convert_get_highest_bit_position(uint32_t *value);
  134. /**
  135. * \brief Converts a rotation matrix to a quaternion.
  136. * \param[in] Rcb_q30 Rotation matrix. Fixed point format is Q30.
  137. * \param[out] Qcb_q30 quaternion related to provided rotation matrix. Vector size is 4. Fixed point format is Q30.
  138. * \ingroup QuaternionFxp
  139. */
  140. void INV_EXPORT inv_icm20948_convert_matrix_to_quat_fxp(long *Rcb_q30, long *Qcb_q30);
  141. /**
  142. * \brief Calculates square-root of a fixed-point number
  143. * \details This code calls 1/sqrt(x) and multiplies result with x, i.e. \f$ \sqrt{x}=x*(1/\sqrt{x}) \f$ .
  144. * @param[in] x_q30 Input. Fixed point format is Q30
  145. * @return square root of x0 in Q30.
  146. \ingroup ScalarFxp
  147. **/
  148. long INV_EXPORT inv_icm20948_convert_sqrt_q30_fxp(long x_q30);
  149. /**
  150. * \brief Calculates 1/square-root of a fixed-point number (30 bit mantissa, positive): Q1.30
  151. * \details The number is scaled to lie between a range in which a Newton-Raphson iteration works best.
  152. * Caller must scale final result by 2^rempow (while avoiding overflow).
  153. * @param[in] x_q30 Input. The input must be positive. Fixed point format is Q30.
  154. * @param[out] pow2 Corresponding square root of the power of two is returned. length 1
  155. * @return square root of x in Q30.
  156. \ingroup ScalarFxp
  157. */
  158. long INV_EXPORT inv_icm20948_convert_inv_sqrt_q30_fxp(long x_q30, int *pow2);
  159. /**
  160. * \brief Inverse function based on Newton-Raphson 1/sqrt(x) calculation
  161. \details Note that upshifting c (the result) by pow2 right away will overflow q30 if b<0.5 in q30 (=536870912). \n
  162. So if you are doing some multiplication later on (like a/b), then it might be better
  163. to do <code>q30_mult(a,c)</code> first and then shift it up by pow2: <code>q30_mult(a,c)<<pow2</code> \n
  164. The result might still overflow in some cases (large a, small b: a=1073741824, b=1
  165. but precise limits of the overflow are tbd).
  166. * @param[in] x_q30 the operand. Fixed point format is Q30
  167. * @param[in] pow2 a power of 2 by which 1/b is downshifted to fit in q30.
  168. * @return the 1/x result in Q30 downshifted by pow2.
  169. \ingroup ScalarFxp
  170. **/
  171. long INV_EXPORT inv_icm20948_convert_inverse_q30_fxp(long x_q30, int *pow2);
  172. /**
  173. * Converts a rotation matrix to a quaternion in floating point.
  174. * \param[in] R Rotation matrix in floating point. The
  175. * First 3 elements of the rotation matrix, represent
  176. * the first row of the matrix.
  177. * \param[out] q 4-element quaternion in floating point.
  178. * \warning This functions does not retrieve fixed point quaternion anymore. Use a conversion flt_to_fxp.
  179. * \ingroup QuaternionFlt
  180. */
  181. // FIXME This function can be optimized in term of operation numbers. But a good test must be writtent first.
  182. void INV_EXPORT inv_icm20948_convert_matrix_to_quat_flt(float *R, float *q);
  183. /**
  184. * \brief Performs a multiply and shift by shift.
  185. * \details These are good functions to write in assembly on
  186. * with devices with small memory where you want to get rid of
  187. * the long long which some assemblers don't handle well
  188. * @param[in] a First multicand
  189. * @param[in] b Second multicand
  190. * @param[in] shift Shift amount after multiplying
  191. * @return ((long long)a*b)>>shift
  192. * \warning Same function that invn_math_mult_qfix_fxp.
  193. \ingroup ScalarFxp
  194. */
  195. long INV_EXPORT inv_icm20948_convert_mult_qfix_fxp(long a, long b, unsigned char qfix);
  196. /**
  197. * \brief Converts a quaternion to a rotation matrix in column major convention.
  198. * @param [in] quat_q30 4-element quaternion in fixed point. Fixed point format is Q30.
  199. * @param[ out] rot_q30 Rotation matrix in fixed point. One is 2^30.
  200. * The Rotation matrix multiplied by a 3 element column vector transforms a vector from Body to World.
  201. * \warning output matrix storage is column major.
  202. * \ref colmajor_convention
  203. * \ingroup MatrixFxp
  204. */
  205. void INV_EXPORT inv_icm20948_convert_quat_to_col_major_matrix_fxp(const long *quat_q30, long *rot_q30);
  206. /** \brief Seventh order Chebychev polynomial approximation in Q15.
  207. \details Chebychev 7th order polynomial approximation : <br />
  208. \li in fixed point : \f$ constA7 = \text{int32}(2^{15}*[0.999133448222780 -0.320533292381664 0.144982490144465,-0.038254464970299]); \f$ <br />
  209. \li in float : \f$ A = \begin{bmatrix}[0.999133 & -0.320533 & 0.144982 &-0.0382544 \end{bmatrix}); \f$ <br />
  210. The related formula is : <br />
  211. \f$ \xi = \begin{cases} |y|/|x| && \text{in }(0, \pi/4] \\ |x|/|y| && \text{in } (\pi/4, \pi/2) \end{cases} , \quad
  212. Cheb = A(1)*\xi + A(2)*\xi^3 + A(3)*\xi^5 + A(4)*\xi^7 \f$
  213. 7th Order Accuracy is +/-0.02 degrees (worst case) through entire range (accomplished with scaling). <br />
  214. This code depends on: \ref reciprocal_fun_q15 , \ref inverse_sqrt_q15 , \ref inv_q15_mult
  215. * @param [in] y_q15 first operand of atan2(y, x). Fixed point format is Q15.
  216. * @param [in] x_q15 second operand of atan2(y, x). Fixed point format is Q15.
  217. * @return output angle in radians. Fixed point format is Q15.
  218. * \ingroup GeometryFxp
  219. */
  220. long INV_EXPORT inv_icm20948_math_atan2_q15_fxp(long y_q15, long x_q15);
  221. /**
  222. * \brief Converts a 16-bit short to a big endian byte stream
  223. * \param [in] x operand
  224. * \param [out] big8 big endian byte stream
  225. * \return big8 pointer
  226. * \ingroup binary
  227. */
  228. uint8_t INV_EXPORT *inv_icm20948_convert_int16_to_big8(int16_t x, uint8_t *big8);
  229. /**
  230. * \brief Converts a 32-bit long to a big endian byte stream
  231. * \param [in] x operand
  232. * \param [out] big8 big endian byte stream
  233. * \return big8 pointer
  234. * \ingroup binary
  235. */
  236. uint8_t INV_EXPORT *inv_icm20948_convert_int32_to_big8(int32_t x, uint8_t *big8);
  237. /**
  238. * \brief Converts a big endian byte stream into a 32-bit long
  239. * \param [in] big8 big endian byte stream
  240. * \return corresponding 32-bit integer.
  241. * \ingroup binary
  242. */
  243. int32_t INV_EXPORT inv_icm20948_convert_big8_to_int32(const uint8_t *big8);
  244. /**
  245. * \brief Converts long values according to quat_30 matrix
  246. * \param [in] quat_30 mounting matrix to apply
  247. * \param [in] in long values to be converted
  248. * \param [out] out long values converted
  249. * \return void
  250. */
  251. void INV_EXPORT inv_icm20948_convert_quat_rotate_fxp(const long *quat_q30, const long *in, long *out);
  252. #ifdef __cplusplus
  253. }
  254. #endif
  255. #endif /* INV_ICM20948_DATA_CONVERTER_H__ */
  256. /** @} */