tap.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /**
  2. * Copyright (C) 2018 Bosch Sensortec GmbH
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. *
  6. * @file bmi160_read_sensor_data.c
  7. * @brief Sample file to read BMI160 sensor data using COINES library
  8. *
  9. */
  10. /*********************************************************************/
  11. /* system header files */
  12. /*********************************************************************/
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <stdint.h>
  16. /*********************************************************************/
  17. /* own header files */
  18. /*********************************************************************/
  19. #include "coines.h"
  20. #include "bmi160.h"
  21. /*********************************************************************/
  22. /* local macro definitions */
  23. /*! i2c interface communication, 1 - Enable; 0- Disable */
  24. #define BMI160_INTERFACE_I2C 0
  25. /*! spi interface communication, 1 - Enable; 0- Disable */
  26. #define BMI160_INTERFACE_SPI 1
  27. #if (!((BMI160_INTERFACE_I2C == 1) && (BMI160_INTERFACE_SPI == 0)) && \
  28. (!((BMI160_INTERFACE_I2C == 0) && (BMI160_INTERFACE_SPI == 1))))
  29. #error "Invalid value given for the macros BMI160_INTERFACE_I2C / BMI160_INTERFACE_SPI"
  30. #endif
  31. /*! bmi160 shuttle id */
  32. #define BMI160_SHUTTLE_ID 0x38
  33. /*! bmi160 Device address */
  34. #define BMI160_DEV_ADDR BMI160_I2C_ADDR
  35. /*********************************************************************/
  36. /* global variables */
  37. /*********************************************************************/
  38. /*! @brief This structure containing relevant bmi160 info */
  39. struct bmi160_dev bmi160dev;
  40. /*! @brief variable to hold the bmi160 accel data */
  41. struct bmi160_sensor_data bmi160_accel;
  42. /*! @brief variable to hold the bmi160 gyro data */
  43. struct bmi160_sensor_data bmi160_gyro;
  44. /*********************************************************************/
  45. /* static function declarations */
  46. /*********************************************************************/
  47. /*!
  48. * @brief internal API is used to initialize the sensor interface
  49. */
  50. static void init_sensor_interface(void);
  51. /*!
  52. * @brief This internal API is used to initialize the bmi160 sensor with default
  53. */
  54. static void init_bmi160(void);
  55. /*!
  56. * @brief This internal API is used to initialize the sensor driver interface
  57. */
  58. static void init_bmi160_sensor_driver_interface(void);
  59. /*!
  60. * @brief This internal API is used to set tap configurations
  61. */
  62. static int8_t set_tap_config(uint8_t feature_enable);
  63. /*********************************************************************/
  64. /* functions */
  65. /*********************************************************************/
  66. /*!
  67. * @brief This internal API is used to initialize the sensor interface depending
  68. * on selection either SPI or I2C.
  69. *
  70. * @param[in] void
  71. *
  72. * @return void
  73. *
  74. */
  75. static void init_sensor_interface(void)
  76. {
  77. /* Switch VDD for sensor off */
  78. coines_set_shuttleboard_vdd_vddio_config(0, 0);
  79. /* wait until the sensor goes off */
  80. coines_delay_msec(10);
  81. #if BMI160_INTERFACE_I2C == 1
  82. /* SDO pin is made low for selecting I2C address 0x68 */
  83. coines_set_pin_config(COINES_SHUTTLE_PIN_15, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW);
  84. /* set the sensor interface as I2C */
  85. coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_FAST_MODE);
  86. coines_delay_msec(10);
  87. /* CSB pin is made high for selecting I2C protocol*/
  88. coines_set_pin_config(COINES_SHUTTLE_PIN_7, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH);
  89. #endif
  90. #if BMI160_INTERFACE_SPI == 1
  91. /* CSB pin is made low for selecting SPI protocol*/
  92. coines_set_pin_config(COINES_SHUTTLE_PIN_7, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW);
  93. coines_delay_msec(10);
  94. coines_config_spi_bus(COINES_SPI_BUS_0, COINES_SPI_SPEED_5_MHZ, COINES_SPI_MODE3);
  95. #endif
  96. coines_delay_msec(10);
  97. /* Switch VDD for sensor on */
  98. coines_set_shuttleboard_vdd_vddio_config(3300, 3300);
  99. #if BMI160_INTERFACE_SPI == 1
  100. coines_delay_msec(10);
  101. /* CSB pin is made high for selecting SPI protocol
  102. * Note: CSB has to see rising after power up, to switch to SPI protocol */
  103. coines_set_pin_config(COINES_SHUTTLE_PIN_7, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH);
  104. #endif
  105. }
  106. /*!
  107. * @brief This internal API is used to initializes the bmi160 sensor
  108. * settings like power mode and OSRS settings.
  109. *
  110. * @param[in] void
  111. *
  112. * @return void
  113. *
  114. */
  115. static void init_bmi160(void)
  116. {
  117. int8_t rslt;
  118. rslt = bmi160_init(&bmi160dev);
  119. if (rslt == BMI160_OK)
  120. {
  121. printf("BMI160 initialization success !\n");
  122. printf("Chip ID 0x%X\n", bmi160dev.chip_id);
  123. }
  124. else
  125. {
  126. printf("BMI160 initialization failure !\n");
  127. exit(COINES_E_FAILURE);
  128. }
  129. /* Select the Output data rate, range of accelerometer sensor */
  130. bmi160dev.accel_cfg.odr = BMI160_ACCEL_ODR_100HZ;
  131. bmi160dev.accel_cfg.range = BMI160_ACCEL_RANGE_8G;
  132. bmi160dev.accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4;
  133. /* Select the power mode of accelerometer sensor */
  134. bmi160dev.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;
  135. /* Set the sensor configuration */
  136. rslt = bmi160_set_sens_conf(&bmi160dev);
  137. }
  138. /*!
  139. * @brief This internal API is used to set the sensor driver interface to
  140. * read/write the data.
  141. *
  142. * @param[in] void
  143. *
  144. * @return void
  145. *
  146. */
  147. static void init_bmi160_sensor_driver_interface(void)
  148. {
  149. #if BMI160_INTERFACE_I2C == 1
  150. /* I2C setup */
  151. /* link read/write/delay function of host system to appropriate
  152. * bmi160 function call prototypes */
  153. bmi160dev.write = coines_write_i2c;
  154. bmi160dev.read = coines_read_i2c;
  155. bmi160dev.delay_ms = coines_delay_msec;
  156. /* set correct i2c address */
  157. bmi160dev.id = BMI160_DEV_ADDR;
  158. bmi160dev.intf = BMI160_I2C_INTF;
  159. #endif
  160. #if BMI160_INTERFACE_SPI == 1
  161. /* SPI setup */
  162. /* link read/write/delay function of host system to appropriate
  163. * bmi160 function call prototypes */
  164. bmi160dev.write = coines_write_spi;
  165. bmi160dev.read = coines_read_spi;
  166. bmi160dev.delay_ms = coines_delay_msec;
  167. bmi160dev.id = COINES_SHUTTLE_PIN_7;
  168. bmi160dev.intf = BMI160_SPI_INTF;
  169. #endif
  170. }
  171. /*!
  172. * @brief Main Function where the execution getting started to test the code.
  173. *
  174. * @param[in] argc
  175. * @param[in] argv
  176. *
  177. * @return status
  178. *
  179. */
  180. int main(int argc, char *argv[])
  181. {
  182. struct coines_board_info board_info;
  183. int16_t rslt;
  184. init_bmi160_sensor_driver_interface();
  185. rslt = coines_open_comm_intf(COINES_COMM_INTF_USB);
  186. if (rslt < 0)
  187. {
  188. printf(
  189. "\n Unable to connect with Application Board ! \n" " 1. Check if the board is connected and powered on. \n" " 2. Check if Application Board USB driver is installed. \n"
  190. " 3. Check if board is in use by another application. (Insufficient permissions to access USB) \n");
  191. exit(rslt);
  192. }
  193. rslt = coines_get_board_info(&board_info);
  194. if (rslt == COINES_SUCCESS)
  195. {
  196. if (board_info.shuttle_id != BMI160_SHUTTLE_ID)
  197. {
  198. printf("! Warning invalid sensor shuttle \n ," "This application will not support this sensor \n");
  199. exit(COINES_E_FAILURE);
  200. }
  201. }
  202. init_sensor_interface();
  203. /* after sensor init introduce 200 msec sleep */
  204. coines_delay_msec(200);
  205. init_bmi160();
  206. rslt = set_tap_config(BMI160_ENABLE);
  207. if (rslt == BMI160_OK)
  208. {
  209. union bmi160_int_status int_status;
  210. uint8_t loop = 0;
  211. uint32_t last_time = 0;
  212. uint32_t current_time = 0;
  213. printf("Do Single or Double Tap the board\n");
  214. fflush(stdout);
  215. memset(int_status.data, 0x00, sizeof(int_status.data));
  216. while (loop < 10)
  217. {
  218. /* Read interrupt status */
  219. rslt = bmi160_get_int_status(BMI160_INT_STATUS_ALL, &int_status, &bmi160dev);
  220. current_time = coines_get_millis();
  221. /* Enters only if the obtained interrupt is single-tap */
  222. if (rslt == BMI160_OK)
  223. {
  224. /* Enters only if the obtained interrupt is single-tap */
  225. if (int_status.bit.s_tap)
  226. {
  227. printf("Single tap, iter:%d, time:%d ms, delta:%d ms, int_status:0x%x\n",
  228. loop++,
  229. current_time,
  230. current_time - last_time,
  231. int_status.data[0]);
  232. }
  233. /* Enters only if the obtained interrupt is double-tap */
  234. else if (int_status.bit.d_tap)
  235. {
  236. printf("Double tap, iter:%d, time:%d ms, delta:%d ms, int_status:0x%x\n",
  237. loop++,
  238. current_time,
  239. current_time - last_time,
  240. int_status.data[0]);
  241. }
  242. fflush(stdout);
  243. }
  244. else
  245. {
  246. break;
  247. }
  248. memset(int_status.data, 0x00, sizeof(int_status.data));
  249. last_time = current_time;
  250. }
  251. /* Disable tap feature */
  252. printf("\nDisable tap test...\n");
  253. rslt = set_tap_config(BMI160_DISABLE);
  254. printf("bmi160_set_int_config(tap enable) status:%d\n", rslt);
  255. fflush(stdout);
  256. }
  257. coines_close_comm_intf(COINES_COMM_INTF_USB);
  258. return EXIT_SUCCESS;
  259. }
  260. static int8_t set_tap_config(uint8_t feature_enable)
  261. {
  262. int8_t rslt = BMI160_OK;
  263. struct bmi160_int_settg int_config;
  264. if (feature_enable > 0)
  265. {
  266. /* Select the Interrupt channel/pin */
  267. int_config.int_channel = BMI160_INT_CHANNEL_1; /* Interrupt channel/pin 1 */
  268. /* Select the interrupt channel/pin settings */
  269. int_config.int_pin_settg.output_en = BMI160_ENABLE; /* Enabling interrupt pins to act as output pin */
  270. int_config.int_pin_settg.output_mode = BMI160_DISABLE; /* Choosing push-pull mode for interrupt pin */
  271. int_config.int_pin_settg.output_type = BMI160_ENABLE; /* Choosing active low output */
  272. int_config.int_pin_settg.edge_ctrl = BMI160_DISABLE; /* Choosing edge triggered output */
  273. int_config.int_pin_settg.input_en = BMI160_DISABLE; /* Disabling interrupt pin to act as input */
  274. int_config.int_pin_settg.latch_dur = BMI160_LATCH_DUR_NONE; /* non-latched output */
  275. /* Select the Interrupt type */
  276. int_config.int_type = BMI160_ACC_SINGLE_TAP_INT; /* Choosing tap interrupt */
  277. /* Select the Any-motion interrupt parameters */
  278. int_config.int_type_cfg.acc_tap_int.tap_en = BMI160_ENABLE; /* 1- Enable tap, 0- disable tap */
  279. int_config.int_type_cfg.acc_tap_int.tap_thr = 2; /* Set tap threshold */
  280. int_config.int_type_cfg.acc_tap_int.tap_dur = 2; /* Set tap duration */
  281. int_config.int_type_cfg.acc_tap_int.tap_shock = 0; /* Set tap shock value */
  282. int_config.int_type_cfg.acc_tap_int.tap_quiet = 0; /* Set tap quiet duration */
  283. int_config.int_type_cfg.acc_tap_int.tap_data_src = 1; /* data source 0 : filter or 1 : pre-filter */
  284. /* Set the Any-motion interrupt */
  285. rslt = bmi160_set_int_config(&int_config, &bmi160dev); /* sensor is an instance of the structure bmi160_dev */
  286. printf("bmi160_set_int_config(tap enable) status:%d\n", rslt);
  287. }
  288. else
  289. {
  290. /* Select the Interrupt channel/pin */
  291. int_config.int_channel = BMI160_INT_CHANNEL_1;
  292. int_config.int_pin_settg.output_en = BMI160_DISABLE; /* Disabling interrupt pins to act as output pin */
  293. int_config.int_pin_settg.edge_ctrl = BMI160_DISABLE; /* Choosing edge triggered output */
  294. /* Select the Interrupt type */
  295. int_config.int_type = BMI160_ACC_SINGLE_TAP_INT; /* Choosing Tap interrupt */
  296. int_config.int_type_cfg.acc_tap_int.tap_en = BMI160_DISABLE; /* 1- Enable tap, 0- disable tap */
  297. /* Set the Data ready interrupt */
  298. rslt = bmi160_set_int_config(&int_config, &bmi160dev); /* sensor is an instance of the structure bmi160_dev */
  299. printf("bmi160_set_int_config(tap disable) status:%d\n", rslt);
  300. }
  301. return rslt;
  302. }