app_imu_dmp.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. /*
  2. * app_imu_dmp.cpp
  3. *
  4. * Created on: Nov 11, 2025
  5. * Author: matus
  6. */
  7. #include <app_imu_dmp.h>
  8. #include "DMP_ICM20948.h"
  9. #include "string.h"
  10. /* Internal Variables ------------------------------------------------------------*/
  11. DMP_ICM20948 _imuDmpInstance;
  12. DMP_ICM20948Settings _imuDmpSettings = {
  13. .mode = 1, // 0 = low power mode, 1 = high performance mode
  14. .enable_gyroscope = true, // Enables gyroscope output
  15. .enable_accelerometer = true, // Enables accelerometer output
  16. .enable_magnetometer = false, // Enables magnetometer output // Enables quaternion output
  17. .enable_gravity = false, // Enables gravity vector output
  18. .enable_linearAcceleration = false, // Enables linear acceleration output
  19. .enable_quaternion6 = true, // Enables quaternion 6DOF output
  20. .enable_quaternion9 = false, // Enables quaternion 9DOF output
  21. .enable_har = false, // Enables activity recognition
  22. .enable_steps = false, // Enables step counter
  23. .gyroscope_frequency = 225, // Max frequency = 225, min frequency = 1
  24. .accelerometer_frequency = 225, // Max frequency = 225, min frequency = 1
  25. .magnetometer_frequency = 70, // Max frequency = 70, min frequency = 1
  26. .gravity_frequency = 225, // Max frequency = 225, min frequency = 1
  27. .linearAcceleration_frequency = 225, // Max frequency = 225, min frequency = 1
  28. .quaternion6_frequency = 225, // Max frequency = 225, min frequency = 50
  29. .quaternion9_frequency = 225, // Max frequency = 225, min frequency = 50
  30. .har_frequency = 225, // Max frequency = 225, min frequency = 50
  31. .steps_frequency = 225 // Max frequency = 225, min frequency = 50
  32. };
  33. nBusAppInterface_t _imuDmpNbusDriver = {
  34. imuDmp_init,
  35. imuDmp_reset,
  36. imuDmp_getType,
  37. imuDmp_getSensorCount,
  38. imuDmp_getData,
  39. imuDmp_setData,
  40. imuDmp_hasParam,
  41. imuDmp_getParam,
  42. imuDmp_setParam,
  43. imuDmp_start,
  44. imuDmp_stop,
  45. imuDmp_readData,
  46. imuDmp_store,
  47. imuDmp_calibrate,
  48. imuDmp_getSensorFormat,
  49. imuDmp_find,
  50. imuDmp_device_ready
  51. };
  52. /* Internal Helper Functions ------------------------------------------------------------*/
  53. static inv_sensor_type _convert_sensor_id_to_inv_type(imu_sensorID_t sensor_index)
  54. {
  55. switch(sensor_index)
  56. {
  57. case ID_ACCELEROMETER:
  58. return INV_SENSOR_TYPE_ACCELEROMETER;
  59. break;
  60. case ID_GYROSCOPE:
  61. return INV_SENSOR_TYPE_GYROSCOPE;
  62. break;
  63. case ID_EULER_ANGLES_GAUGE:
  64. return INV_SENSOR_TYPE_GAME_ROTATION_VECTOR;
  65. break;
  66. default:
  67. return INV_SENSOR_TYPE_RESERVED;
  68. }
  69. }
  70. static nBus_statusType_t _update_enable_status(DMP_ICM20948 *imuDmpInstance, DMP_ICM20948Settings *imuDmpSettings, imu_sensorID_t sensor_index, uint8_t value)
  71. {
  72. if (value > 1)
  73. return STATUS_FAIL;
  74. switch(sensor_index)
  75. {
  76. case ID_ACCELEROMETER:
  77. imuDmpSettings->enable_accelerometer = value;
  78. break;
  79. case ID_GYROSCOPE:
  80. imuDmpSettings->enable_gyroscope = value;
  81. break;
  82. case ID_EULER_ANGLES_GAUGE:
  83. imuDmpSettings->enable_quaternion6 = value;
  84. break;
  85. default:
  86. return STATUS_FAIL;
  87. }
  88. imuDmpInstance->enableSensor(_convert_sensor_id_to_inv_type(sensor_index), value);
  89. return STATUS_SUCCESS;
  90. }
  91. static nBus_statusType_t _update_samplerate(DMP_ICM20948 *imuDmpInstance, DMP_ICM20948Settings *imuDmpSettings, imu_sensorID_t sensor_index, uint32_t value)
  92. {
  93. if (value < 1 || value > 225)
  94. return STATUS_FAIL;
  95. switch(sensor_index)
  96. {
  97. case ID_ACCELEROMETER:
  98. imuDmpSettings->accelerometer_frequency = value;
  99. break;
  100. case ID_GYROSCOPE:
  101. imuDmpSettings->gyroscope_frequency = value;
  102. break;
  103. case ID_EULER_ANGLES_GAUGE:
  104. imuDmpSettings->quaternion6_frequency = value;
  105. break;
  106. default:
  107. return STATUS_FAIL;
  108. }
  109. imuDmpInstance->setSensorFrequency(_convert_sensor_id_to_inv_type(sensor_index), value);
  110. return STATUS_SUCCESS;
  111. }
  112. static uint8_t _get_enable_status(DMP_ICM20948Settings *imuDmpSettings, imu_sensorID_t sensor_index)
  113. {
  114. switch(sensor_index)
  115. {
  116. case ID_ACCELEROMETER:
  117. return imuDmpSettings->enable_accelerometer;
  118. break;
  119. case ID_GYROSCOPE:
  120. return imuDmpSettings->enable_gyroscope;
  121. break;
  122. case ID_EULER_ANGLES_GAUGE:
  123. return imuDmpSettings->enable_quaternion6;
  124. break;
  125. default:
  126. return STATUS_FAIL;
  127. }
  128. }
  129. static uint32_t _get_samplerate(DMP_ICM20948Settings *imuDmpSettings, imu_sensorID_t sensor_index)
  130. {
  131. switch(sensor_index)
  132. {
  133. case ID_ACCELEROMETER:
  134. return imuDmpSettings->accelerometer_frequency;
  135. break;
  136. case ID_GYROSCOPE:
  137. return imuDmpSettings->gyroscope_frequency;
  138. break;
  139. case ID_EULER_ANGLES_GAUGE:
  140. return imuDmpSettings->quaternion6_frequency;
  141. break;
  142. default:
  143. return STATUS_FAIL;
  144. }
  145. return STATUS_SUCCESS;
  146. }
  147. /* nBUS Interface Implementation ------------------------------------------------------------*/
  148. nBusAppInterface_t *getImuDriver()
  149. {
  150. return &_imuDmpNbusDriver;
  151. }
  152. nBus_sensorType_t imuDmp_getType(uint8_t sensor_index)
  153. {
  154. switch(sensor_index)
  155. {
  156. case ID_ACCELEROMETER:
  157. return TYPE_ACCELEROMETER;
  158. break;
  159. case ID_GYROSCOPE:
  160. return TYPE_GYROSCOPE;
  161. break;
  162. case ID_EULER_ANGLES_GAUGE:
  163. return TYPE_EULER_ANGLES_GAUGE;
  164. break;
  165. default:
  166. return TYPE_UNKNOWN;
  167. }
  168. }
  169. nBus_sensorCount_t imuDmp_getSensorCount()
  170. {
  171. return (nBus_sensorCount_t){3, 0};
  172. }
  173. uint8_t imuDmp_getData(uint8_t sensor_index, uint8_t *data)
  174. {
  175. size_t data_offset = 0;
  176. float values[3];
  177. int32_t int_value;
  178. uint8_t use_accel = 0, use_gyro = 0, use_euler = 0;
  179. switch(sensor_index)
  180. {
  181. case ID_ALL:
  182. use_accel = _imuDmpSettings.enable_accelerometer && _imuDmpInstance.accelDataIsReady();
  183. use_gyro = _imuDmpSettings.enable_gyroscope && _imuDmpInstance.gyroDataIsReady();
  184. use_euler = _imuDmpSettings.enable_quaternion6 && _imuDmpInstance.euler6DataIsReady();
  185. break;
  186. case ID_ACCELEROMETER:
  187. use_accel = _imuDmpSettings.enable_accelerometer && _imuDmpInstance.accelDataIsReady();
  188. break;
  189. case ID_GYROSCOPE:
  190. use_gyro = _imuDmpSettings.enable_gyroscope && _imuDmpInstance.gyroDataIsReady();
  191. break;
  192. case ID_EULER_ANGLES_GAUGE:
  193. use_euler = _imuDmpSettings.enable_quaternion6 && _imuDmpInstance.euler6DataIsReady();
  194. break;
  195. default:
  196. break;
  197. }
  198. if (use_accel)
  199. {
  200. _imuDmpInstance.readAccelData(&values[0], &values[1], &values[2]);
  201. data[data_offset++] = (uint8_t)ID_ACCELEROMETER;
  202. for (uint8_t i = 0; i < 3; i++)
  203. {
  204. int_value = (int32_t)(values[i] * ACC_MULT_NUM);
  205. memcpy(data + data_offset, &int_value, ACC_BYTES);
  206. data_offset += ACC_BYTES;
  207. }
  208. }
  209. if (use_gyro)
  210. {
  211. _imuDmpInstance.readGyroData(&values[0], &values[1], &values[2]);
  212. data[data_offset++] = (uint8_t)ID_GYROSCOPE;
  213. for (uint8_t i = 0; i < 3; i++)
  214. {
  215. int_value = (int32_t)(values[i] * GYR_MULT_NUM);
  216. memcpy(data + data_offset, &int_value, GYR_BYTES);
  217. data_offset += GYR_BYTES;
  218. }
  219. }
  220. if (use_euler)
  221. {
  222. _imuDmpInstance.readEuler6Data(&values[0], &values[1], &values[2]);
  223. data[data_offset++] = (uint8_t)ID_EULER_ANGLES_GAUGE;
  224. for (uint8_t i = 0; i < 3; i++)
  225. {
  226. int_value = (int32_t)(values[i] * EUL_MULT_NUM);
  227. memcpy(data + data_offset, &int_value, EUL_BYTES);
  228. data_offset += EUL_BYTES;
  229. }
  230. }
  231. return data_offset;
  232. }
  233. nBus_statusType_t imuDmp_setData(uint8_t *data, uint8_t count, uint8_t *response)
  234. {
  235. return STATUS_FAIL;
  236. }
  237. uint8_t imuDmp_hasParam(uint8_t sensor_index, nBus_param_t param_name)
  238. {
  239. if (sensor_index == 0)
  240. return param_name == PARAM_MODE;
  241. switch(param_name)
  242. {
  243. case PARAM_ENABLE:
  244. case PARAM_SAMPLERATE:
  245. return 1;
  246. break;
  247. default:
  248. return 0;
  249. }
  250. }
  251. int32_t imuDmp_getParam(uint8_t sensor_index, nBus_param_t param_name)
  252. {
  253. if (imuDmp_hasParam(sensor_index, param_name))
  254. {
  255. switch(param_name)
  256. {
  257. case PARAM_ENABLE:
  258. return _get_enable_status(&_imuDmpSettings, (imu_sensorID_t)sensor_index);
  259. break;
  260. case PARAM_SAMPLERATE:
  261. return _get_samplerate(&_imuDmpSettings, (imu_sensorID_t)sensor_index);
  262. break;
  263. case PARAM_MODE:
  264. return _imuDmpSettings.mode;
  265. break;
  266. default:
  267. return 0;
  268. }
  269. }
  270. return 0;
  271. }
  272. nBus_statusType_t imuDmp_setParam(uint8_t sensor_index, nBus_param_t param_name, int32_t param_value)
  273. {
  274. if (imuDmp_hasParam(sensor_index, param_name))
  275. {
  276. switch(param_name)
  277. {
  278. case PARAM_ENABLE:
  279. return _update_enable_status(&_imuDmpInstance, &_imuDmpSettings, (imu_sensorID_t)sensor_index, param_value);
  280. break;
  281. case PARAM_SAMPLERATE:
  282. return _update_samplerate(&_imuDmpInstance, &_imuDmpSettings, (imu_sensorID_t)sensor_index, param_value);
  283. break;
  284. case PARAM_MODE:
  285. _imuDmpInstance.setOperatingMode(param_value);
  286. return STATUS_SUCCESS;
  287. break;
  288. default:
  289. return STATUS_FAIL;
  290. }
  291. }
  292. return STATUS_NOT_SUPPORTED;
  293. }
  294. void imuDmp_init(void *hw_interface, void *hw_config)
  295. {
  296. _imuDmpInstance.init(_imuDmpSettings);
  297. }
  298. void imuDmp_reset()
  299. {
  300. // not implemented
  301. }
  302. nBus_statusType_t imuDmp_start(void)
  303. {
  304. return STATUS_SUCCESS;
  305. }
  306. nBus_statusType_t imuDmp_stop(void)
  307. {
  308. return STATUS_SUCCESS;
  309. }
  310. void imuDmp_readData(void)
  311. {
  312. _imuDmpInstance.task();
  313. }
  314. uint8_t imuDmp_store(void)
  315. {
  316. return 0; // not implemented
  317. }
  318. nBus_statusType_t imuDmp_calibrate(uint8_t sensor_index)
  319. {
  320. return STATUS_NOT_SUPPORTED;
  321. }
  322. nBus_sensorFormat_t imuDmp_getSensorFormat(uint8_t sensor_index)
  323. {
  324. switch(sensor_index)
  325. {
  326. case ID_ACCELEROMETER:
  327. return (nBus_sensorFormat_t){.sign = 1, .unit_multiplier = 0, .value_multiplier = ACC_MULT_LOG, .byte_length = ACC_BYTES, .samples = 3};
  328. break;
  329. case ID_GYROSCOPE:
  330. return (nBus_sensorFormat_t){.sign = 1, .unit_multiplier = 0, .value_multiplier = GYR_MULT_LOG, .byte_length = GYR_BYTES, .samples = 3};
  331. break;
  332. case ID_EULER_ANGLES_GAUGE:
  333. return (nBus_sensorFormat_t){.sign = 1, .unit_multiplier = 0, .value_multiplier = EUL_MULT_LOG, .byte_length = EUL_BYTES, .samples = 3};
  334. break;
  335. default:
  336. return (nBus_sensorFormat_t){0, 0, 0, 0, 0};
  337. break;
  338. }
  339. }
  340. nBus_statusType_t imuDmp_find(uint8_t enable)
  341. {
  342. return STATUS_NOT_SUPPORTED;
  343. }
  344. uint8_t imuDmp_device_ready()
  345. {
  346. return 1;
  347. }