dev_accel.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. /***************************************************************************//**
  2. * @file dev_accel.c
  3. * @brief Accelerometer driver of RT-Thread RTOS for EFM32
  4. * COPYRIGHT (C) 2012, RT-Thread Development Team
  5. * @author onelife
  6. * @version 1.0
  7. *******************************************************************************
  8. * @section License
  9. * The license and distribution terms for this file may be found in the file
  10. * LICENSE in this distribution or at http://www.rt-thread.org/license/LICENSE
  11. *******************************************************************************
  12. * @section Change Logs
  13. * Date Author Notes
  14. * 2011-07-13 onelife Initial creation for using EFM32 ADC module to
  15. * interface the Freescale MMA7361L
  16. * 2011-08-02 onelife Add digital interface support of using EFM32 IIC
  17. * module for the Freescale MMA7455L
  18. ******************************************************************************/
  19. /***************************************************************************//**
  20. * @addtogroup efm32
  21. * @{
  22. ******************************************************************************/
  23. /* Includes ------------------------------------------------------------------*/
  24. #include "board.h"
  25. #if defined(EFM32_USING_ACCEL)
  26. #if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC)
  27. #include "drv_adc.h"
  28. #elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
  29. #include "drv_iic.h"
  30. #include "hdl_interrupt.h"
  31. #endif
  32. #include "dev_accel.h"
  33. /* Private typedef -----------------------------------------------------------*/
  34. /* Private define ------------------------------------------------------------*/
  35. /* Private macro -------------------------------------------------------------*/
  36. #ifdef EFM32_ACCEL_DEBUG
  37. #define accel_debug(format,args...) rt_kprintf(format, ##args)
  38. #else
  39. #define accel_debug(format,args...)
  40. #endif
  41. /* Private constants ---------------------------------------------------------*/
  42. static rt_device_t accel;
  43. #if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC)
  44. static struct efm32_adc_control_t control = \
  45. {ADC_MODE_SCAN, {3, ACCEL_USING_DMA}, {}};
  46. static struct efm32_accel_result_t accelOffset = {0};
  47. #elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
  48. static const struct efm32_iic_control_t control = \
  49. {IIC_STATE_MASTER, 0x0000};
  50. #endif
  51. static rt_bool_t accelInTime = true;
  52. static rt_uint32_t accelConfig = 0;
  53. /* Private variables ---------------------------------------------------------*/
  54. /* Private function prototypes -----------------------------------------------*/
  55. /* Private functions ---------------------------------------------------------*/
  56. /***************************************************************************//**
  57. * @brief
  58. * Get accelerometer output
  59. *
  60. * @details
  61. *
  62. * @note
  63. *
  64. * @param[out] data
  65. * Pointer to output buffer
  66. *
  67. * @param[in] lowResolution
  68. * Resolution selection
  69. *
  70. * @return
  71. * Error code
  72. ******************************************************************************/
  73. rt_err_t efm_accel_get_data(struct efm32_accel_result_t *data,
  74. rt_bool_t lowResolution)
  75. {
  76. RT_ASSERT(accel != RT_NULL);
  77. rt_err_t ret;
  78. if (data == RT_NULL)
  79. {
  80. return -RT_ERROR;
  81. }
  82. ret = RT_EOK;
  83. do
  84. {
  85. /* --------- ADC interface --------- */
  86. #if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC)
  87. struct efm32_adc_result_t result;
  88. result.mode = control.mode;
  89. result.buffer = (void *)data;
  90. if ((ret = accel->control(accel, RT_DEVICE_CTRL_RESUME,
  91. (void *)&result)) != RT_EOK)
  92. {
  93. break;
  94. }
  95. if ((ret = accel->control(accel, RT_DEVICE_CTRL_ADC_RESULT, \
  96. (void *)&result)) != RT_EOK)
  97. {
  98. break;
  99. }
  100. data->x += accelOffset.x - 0x800;
  101. data->y += accelOffset.y - 0x800;
  102. data->z += accelOffset.z - 0x800;
  103. if (lowResolution)
  104. {
  105. data->x >>= 4;
  106. data->y >>= 4;
  107. data->z >>= 4;
  108. }
  109. /* --------- IIC interface --------- */
  110. #elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
  111. if (lowResolution || \
  112. ((accelConfig & ACCEL_MASK_RANGE) != MCTL_RANGE_8G))
  113. {
  114. rt_int8_t buf[3];
  115. buf[0] = XOUT8;
  116. if (accel->read(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, \
  117. sizeof(buf)) == 0)
  118. {
  119. ret = -RT_ERROR;
  120. break;
  121. }
  122. data->x = buf[0];
  123. data->y = buf[1];
  124. data->z = buf[2];
  125. }
  126. else
  127. {
  128. rt_uint8_t buf[6];
  129. rt_uint16_t *temp = (rt_uint16_t *)&buf;
  130. buf[0] = XOUTL;
  131. if (accel->read(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, \
  132. sizeof(buf)) == 0)
  133. {
  134. ret = -RT_ERROR;
  135. break;
  136. }
  137. data->x = (*temp & 0x200) ? ((rt_uint32_t)*temp | ~0x3FF) : \
  138. ((rt_uint32_t)*temp & 0x3FF);
  139. data->y = (*++temp & 0x200) ? ((rt_uint32_t)*temp | ~0x3FF) : \
  140. ((rt_uint32_t)*temp & 0x3FF);
  141. data->z = (*++temp & 0x200) ? ((rt_uint32_t)*temp | ~0x3FF) : \
  142. ((rt_uint32_t)*temp & 0x3FF);
  143. }
  144. #endif
  145. return RT_EOK;
  146. } while (0);
  147. accel_debug("Accel err: Get data failed!\n");
  148. return ret;
  149. }
  150. /***************************************************************************//**
  151. * @brief
  152. * Accelerometer timeout interrupt handler
  153. *
  154. * @details
  155. *
  156. * @note
  157. *
  158. * @param[in] parameter
  159. * Parameter
  160. ******************************************************************************/
  161. static void efm_accel_timer(void* parameter)
  162. {
  163. accelInTime = false;
  164. }
  165. #if (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
  166. /***************************************************************************//**
  167. * @brief
  168. * Accelerometer level and pulse detection interrupts handler
  169. *
  170. * @details
  171. *
  172. * @note
  173. *
  174. * @param[in] device
  175. * Pointer to device descriptor
  176. ******************************************************************************/
  177. static void efm_accel_isr(rt_device_t device)
  178. {
  179. rt_uint8_t buf[2];
  180. if ((accelConfig & ACCEL_MASK_MODE) != ACCEL_MODE_MEASUREMENT)
  181. {
  182. /* Read detection source */
  183. buf[0] = DETSRC;
  184. if (accel->read(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 1) != 1)
  185. {
  186. accel_debug("Accel: read error\n");
  187. return;
  188. }
  189. accel_debug("Accel: DETSRC %x\n", buf[0]);
  190. /* Reset the interrupt flags: Part 1 */
  191. buf[0] = INTRST;
  192. buf[1] = INTRST_INT_1 | INTRST_INT_2;
  193. accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2);
  194. /* Read status to waste some time */
  195. buf[0] = STATUS;
  196. if (accel->read(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 1) != 1)
  197. {
  198. accel_debug("Accel: read error\n");
  199. return;
  200. }
  201. accel_debug("Accel: STATUS %x\n", buf[0]);
  202. /* Reset the interrupt flags: Part 2 */
  203. buf[0] = INTRST;
  204. buf[1] = 0x00;
  205. accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2);
  206. }
  207. }
  208. /***************************************************************************//**
  209. * @brief
  210. * Accelerometer configuration function
  211. *
  212. * @details
  213. *
  214. * @note
  215. *
  216. * @param[in] config
  217. * Configuration options
  218. *
  219. * @param[in] level_threshold
  220. * Level detection threshold
  221. *
  222. * @param[in] pulse_threshold
  223. * Pulse detection threshold
  224. *
  225. * @param[in] pulse_duration
  226. * Time window for 1st pulse
  227. *
  228. * @param[in] pulse_latency
  229. * Pulse latency Time
  230. *
  231. * @param[in] pulse_duration2
  232. * Time window for 2nd pulse
  233. *
  234. * @return
  235. * Error code
  236. ******************************************************************************/
  237. rt_err_t efm_accel_config(rt_uint32_t config,
  238. rt_uint8_t level_threshold,
  239. rt_uint8_t pulse_threshold,
  240. rt_uint8_t pulse_duration,
  241. rt_uint8_t pulse_latency,
  242. rt_uint8_t pulse_duration2)
  243. {
  244. rt_err_t ret;
  245. rt_uint8_t buf[2];
  246. rt_uint8_t mode, mctl_reg, ctl1_reg, ctl2_reg;
  247. ret = RT_EOK;
  248. mctl_reg = 0;
  249. ctl1_reg = 0;
  250. ctl2_reg = 0;
  251. /* Modify MCTL */
  252. mode = config & ACCEL_MASK_MODE;
  253. switch (mode)
  254. {
  255. case ACCEL_MODE_STANDBY:
  256. mctl_reg |= MCTL_MODE_STANDBY;
  257. break;
  258. case ACCEL_MODE_MEASUREMENT:
  259. mctl_reg |= MCTL_MODE_MEASUREMENT;
  260. break;
  261. case ACCEL_MODE_LEVEL:
  262. mctl_reg |= MCTL_MODE_LEVEL;
  263. break;
  264. case ACCEL_MODE_PULSE:
  265. mctl_reg |= MCTL_MODE_PULSE;
  266. break;
  267. default:
  268. return -RT_ERROR;
  269. }
  270. switch (config & ACCEL_MASK_RANGE)
  271. {
  272. case ACCEL_RANGE_8G:
  273. mctl_reg |= MCTL_RANGE_8G;
  274. break;
  275. case ACCEL_RANGE_4G:
  276. mctl_reg |= MCTL_RANGE_4G;
  277. break;
  278. case ACCEL_RANGE_2G:
  279. mctl_reg |= MCTL_RANGE_2G;
  280. break;
  281. default:
  282. return -RT_ERROR;
  283. }
  284. if ((mode == ACCEL_MODE_LEVEL) || (mode == ACCEL_MODE_PULSE))
  285. {
  286. mctl_reg |= MCTL_PIN_INT1;
  287. }
  288. /* Modify CTL1 */
  289. if (config & ACCEL_INTPIN_INVERSE)
  290. {
  291. ctl1_reg |= CTL1_INTPIN_INVERSE;
  292. }
  293. switch (config & ACCEL_MASK_INT)
  294. {
  295. case ACCEL_INT_LEVEL_PULSE:
  296. ctl1_reg |= CTL1_INT_LEVEL_PULSE;
  297. break;
  298. case ACCEL_INT_PULSE_LEVEL:
  299. ctl1_reg |= CTL1_INT_PULSE_LEVEL;
  300. break;
  301. case ACCEL_INT_SINGLE_DOUBLE:
  302. ctl1_reg |= CTL1_INT_SINGLE_DOUBLE;
  303. break;
  304. default:
  305. break;
  306. }
  307. switch (config & ACCEL_MASK_DISABLE)
  308. {
  309. case ACCEL_DISABLE_X:
  310. ctl1_reg |= CTL1_X_DISABLE;
  311. break;
  312. case ACCEL_DISABLE_Y:
  313. ctl1_reg |= CTL1_Y_DISABLE;
  314. break;
  315. case ACCEL_DISABLE_Z:
  316. ctl1_reg |= CTL1_Z_DISABLE;
  317. break;
  318. default:
  319. break;
  320. }
  321. if (config & ACCEL_THRESHOLD_INTEGER)
  322. {
  323. ctl1_reg |= CTL1_THRESHOLD_INTEGER;
  324. }
  325. if (config & ACCEL_BANDWIDTH_125HZ)
  326. {
  327. ctl1_reg |= CTL1_BANDWIDTH_125HZ;
  328. }
  329. /* Modify CTL2 */
  330. if (config & ACCEL_LEVEL_AND)
  331. {
  332. ctl2_reg |= CTL2_LEVEL_AND;
  333. }
  334. if (config & ACCEL_PULSE_AND)
  335. {
  336. ctl2_reg |= CTL2_PULSE_AND;
  337. }
  338. if (config & ACCEL_DRIVE_STRONG)
  339. {
  340. ctl2_reg |= CTL2_DRIVE_STRONG;
  341. }
  342. do
  343. {
  344. /* Write registers */
  345. buf[0] = MCTL;
  346. buf[1] = mctl_reg;
  347. if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
  348. {
  349. ret = -RT_ERROR;
  350. break;
  351. }
  352. accel_debug("Accel: MCTL %x\n", mctl_reg);
  353. buf[0] = CTL1;
  354. buf[1] = ctl1_reg;
  355. if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
  356. {
  357. ret = -RT_ERROR;
  358. break;
  359. }
  360. accel_debug("Accel: CTL1 %x\n", ctl1_reg);
  361. buf[0] = CTL2;
  362. buf[1] = ctl2_reg;
  363. if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
  364. {
  365. ret = -RT_ERROR;
  366. break;
  367. }
  368. accel_debug("Accel: CTL2 %x\n", ctl2_reg);
  369. accelConfig = config;
  370. if (mode == ACCEL_MODE_PULSE)
  371. {
  372. buf[0] = PDTH;
  373. buf[1] = pulse_threshold;
  374. if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
  375. {
  376. ret = -RT_ERROR;
  377. break;
  378. }
  379. accel_debug("Accel: PDTH %x\n", buf[1]);
  380. buf[0] = PW;
  381. buf[1] = pulse_duration;
  382. if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
  383. {
  384. ret = -RT_ERROR;
  385. break;
  386. }
  387. accel_debug("Accel: PW %x\n", buf[1]);
  388. buf[0] = LT;
  389. buf[1] = pulse_latency;
  390. if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
  391. {
  392. ret = -RT_ERROR;
  393. break;
  394. }
  395. accel_debug("Accel: LT %x\n", buf[1]);
  396. buf[0] = TW;
  397. buf[1] = pulse_duration2;
  398. if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
  399. {
  400. ret = -RT_ERROR;
  401. break;
  402. }
  403. accel_debug("Accel: TW %x\n", buf[1]);
  404. }
  405. if ((mode == ACCEL_MODE_LEVEL) || (mode == ACCEL_MODE_PULSE))
  406. {
  407. efm32_irq_hook_init_t hook;
  408. /* Reset the interrupt flags: Part 1 */
  409. buf[0] = INTRST;
  410. buf[1] = INTRST_INT_1 | INTRST_INT_2;
  411. if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
  412. {
  413. ret = -RT_ERROR;
  414. break;
  415. }
  416. /* Set level detection threshold */
  417. buf[0] = LDTH;
  418. if (config & ACCEL_THRESHOLD_INTEGER)
  419. {
  420. buf[1] = level_threshold;
  421. }
  422. else
  423. {
  424. buf[1] = level_threshold & 0x7f;
  425. }
  426. if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
  427. {
  428. ret = -RT_ERROR;
  429. break;
  430. }
  431. accel_debug("Accel: LDTH %x\n", buf[1]);
  432. /* Config interrupt */
  433. hook.type = efm32_irq_type_gpio;
  434. hook.unit = ACCEL_INT1_PIN;
  435. hook.cbFunc = efm_accel_isr;
  436. hook.userPtr = RT_NULL;
  437. efm32_irq_hook_register(&hook);
  438. hook.unit = ACCEL_INT2_PIN;
  439. efm32_irq_hook_register(&hook);
  440. /* Clear pending interrupt */
  441. BITBAND_Peripheral(&(GPIO->IFC), ACCEL_INT1_PIN, 0x1UL);
  442. BITBAND_Peripheral(&(GPIO->IFC), ACCEL_INT2_PIN, 0x1UL);
  443. /* Set raising edge interrupt and clear/enable it */
  444. GPIO_IntConfig(
  445. ACCEL_INT1_PORT,
  446. ACCEL_INT1_PIN,
  447. true,
  448. false,
  449. true);
  450. GPIO_IntConfig(
  451. ACCEL_INT2_PORT,
  452. ACCEL_INT2_PIN,
  453. true,
  454. false,
  455. true);
  456. if (((rt_uint8_t)ACCEL_INT1_PORT % 2) || \
  457. ((rt_uint8_t)ACCEL_INT2_PORT % 2))
  458. {
  459. NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
  460. NVIC_SetPriority(GPIO_ODD_IRQn, EFM32_IRQ_PRI_DEFAULT);
  461. NVIC_EnableIRQ(GPIO_ODD_IRQn);
  462. }
  463. if (!((rt_uint8_t)ACCEL_INT1_PORT % 2) || \
  464. !((rt_uint8_t)ACCEL_INT2_PORT % 2))
  465. {
  466. NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn);
  467. NVIC_SetPriority(GPIO_EVEN_IRQn, EFM32_IRQ_PRI_DEFAULT);
  468. NVIC_EnableIRQ(GPIO_EVEN_IRQn);
  469. }
  470. /* Reset the interrupt flags: Part 2 */
  471. buf[0] = INTRST;
  472. buf[1] = 0x00;
  473. if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0)
  474. {
  475. ret = -RT_ERROR;
  476. break;
  477. }
  478. }
  479. } while (0);
  480. return ret;
  481. }
  482. #endif
  483. /***************************************************************************//**
  484. * @brief
  485. * Accelerometer auto-zero calibration function
  486. *
  487. * @details
  488. *
  489. * @note
  490. *
  491. * @param[in] mode
  492. * 0, simple mode (assuming the device is placed on flat surface)
  493. * 1, interaction method
  494. *
  495. * @param[in] period
  496. * Time period to perform auto-zero calibration
  497. *
  498. * @return
  499. * Error code
  500. ******************************************************************************/
  501. rt_err_t efm_accel_auto_zero(rt_uint8_t mode, rt_tick_t period)
  502. {
  503. RT_ASSERT(accel != RT_NULL);
  504. rt_timer_t calTimer;
  505. struct efm32_accel_result_t min = {0, 0, 0};
  506. struct efm32_accel_result_t max = {0, 0, 0};
  507. struct efm32_accel_result_t temp, sum;
  508. rt_int32_t simpleOffset[] = ACCEL_CAL_1G_VALUE;
  509. rt_uint8_t cmd[7] = {0};
  510. rt_uint8_t i, j;
  511. /* Reset offset */
  512. #if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC)
  513. accelOffset.x = 0;
  514. accelOffset.y = 0;
  515. accelOffset.z = 0;
  516. #elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
  517. cmd[0] = XOFFL;
  518. if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, cmd, sizeof(cmd)) == 0)
  519. {
  520. return -RT_ERROR;
  521. }
  522. #endif
  523. if (mode == ACCEL_CAL_SIMPLE)
  524. {
  525. /* Simple mode */
  526. for (j = 0; j < ACCEL_CAL_ROUND; j++)
  527. {
  528. sum.x = 0x0;
  529. sum.y = 0x0;
  530. sum.z = 0x0;
  531. for (i = 0; i < ACCEL_CAL_SAMPLES; i++)
  532. {
  533. #if (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
  534. /* Waiting for data ready */
  535. while(!GPIO_PinInGet(ACCEL_INT1_PORT, ACCEL_INT1_PIN));
  536. #endif
  537. if (efm_accel_get_data(&temp, false) != RT_EOK)
  538. {
  539. return -RT_ERROR;
  540. }
  541. sum.x += temp.x;
  542. sum.y += temp.y;
  543. sum.z += temp.z;
  544. }
  545. #if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC)
  546. temp.x = sum.x / ACCEL_CAL_SAMPLES;
  547. temp.y = sum.y / ACCEL_CAL_SAMPLES;
  548. temp.z = sum.z / ACCEL_CAL_SAMPLES - simpleOffset[ACCEL_G_SELECT];
  549. if ((temp.x == 0) && (temp.y == 0) && \
  550. (temp.z == 0))
  551. {
  552. accel_debug("Accel: Offset %+d %+d %+d\n",
  553. accelOffset.x, accelOffset.y, accelOffset.z);
  554. break;
  555. }
  556. accelOffset.x -= temp.x;
  557. accelOffset.y -= temp.y;
  558. accelOffset.z -= temp.z;
  559. #elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
  560. temp.x = sum.x / (ACCEL_CAL_SAMPLES >> 1);
  561. temp.y = sum.y / (ACCEL_CAL_SAMPLES >> 1);
  562. temp.z = sum.z / (ACCEL_CAL_SAMPLES >> 1) \
  563. - (simpleOffset[ACCEL_G_SELECT] << 1);
  564. if ((temp.x == 0) && (temp.y == 0) && \
  565. (temp.z == 0))
  566. {
  567. break;
  568. }
  569. /* Set offset drift registers */
  570. max.x -= temp.x;
  571. max.y -= temp.y;
  572. max.z -= temp.z;
  573. *(rt_int16_t *)&cmd[1] = (rt_int16_t)max.x;
  574. *(rt_int16_t *)&cmd[3] = (rt_int16_t)max.y;
  575. *(rt_int16_t *)&cmd[5] = (rt_int16_t)max.z;
  576. if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, cmd, sizeof(cmd)) == 0)
  577. {
  578. return -RT_ERROR;
  579. }
  580. accel_debug("Accel: Offset %+d %+d %+d\n", *(rt_int16_t *)&cmd[1], \
  581. *(rt_int16_t *)&cmd[3], *(rt_int16_t *)&cmd[5]);
  582. #endif
  583. rt_thread_sleep(1);
  584. }
  585. }
  586. else
  587. {
  588. /* Interact mode */
  589. if ((calTimer = rt_timer_create(
  590. "cal_tmr",
  591. efm_accel_timer,
  592. RT_NULL,
  593. period,
  594. RT_TIMER_FLAG_ONE_SHOT)) == RT_NULL)
  595. {
  596. accel_debug("Accel err: Create timer failed!\n");
  597. return -RT_ERROR;
  598. }
  599. accelInTime = true;
  600. rt_timer_start(calTimer);
  601. do
  602. {
  603. sum.x = 0x0;
  604. sum.y = 0x0;
  605. sum.z = 0x0;
  606. for (i = 0; i < ACCEL_CAL_SAMPLES; i++)
  607. {
  608. #if (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
  609. /* Waiting for data ready */
  610. while(!GPIO_PinInGet(ACCEL_INT1_PORT, ACCEL_INT1_PIN));
  611. #endif
  612. if (efm_accel_get_data(&temp, false) != RT_EOK)
  613. {
  614. return -RT_ERROR;
  615. }
  616. sum.x += temp.x;
  617. sum.y += temp.y;
  618. sum.z += temp.z;
  619. }
  620. sum.x /= ACCEL_CAL_SAMPLES;
  621. sum.y /= ACCEL_CAL_SAMPLES;
  622. sum.z /= ACCEL_CAL_SAMPLES;
  623. if (sum.x < min.x)
  624. {
  625. min.x = sum.x;
  626. }
  627. if (sum.y < min.y)
  628. {
  629. min.y = sum.y;
  630. }
  631. if (sum.z < min.z)
  632. {
  633. min.z = sum.z;
  634. }
  635. if (sum.x > max.x)
  636. {
  637. max.x = sum.x;
  638. }
  639. if (sum.y > max.y)
  640. {
  641. max.y = sum.y;
  642. }
  643. if (sum.z > max.z)
  644. {
  645. max.z = sum.z;
  646. }
  647. rt_thread_sleep(1);
  648. } while (accelInTime);
  649. accel_debug("Accel: Min %+d %+d %+d, max %+d %+d %+d\n",
  650. min.x, min.y, min.z, max.x, max.y, max.z);
  651. #if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC)
  652. accelOffset.x = -((min.x + max.x) >> 1);
  653. accelOffset.y = -((min.y + max.y) >> 1);
  654. accelOffset.z = -((min.z + max.z) >> 1);
  655. accel_debug("Accel: Offset %+d %+d %+d\n",
  656. accelOffset.x, accelOffset.y, accelOffset.z);
  657. #elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
  658. /* Set offset drift registers */
  659. *(rt_int16_t *)&cmd[1] = (rt_int16_t)-(min.x + max.x);
  660. *(rt_int16_t *)&cmd[3] = (rt_int16_t)-(min.y + max.y);
  661. *(rt_int16_t *)&cmd[5] = (rt_int16_t)-(min.z + max.z);
  662. if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, cmd, sizeof(cmd)) == 0)
  663. {
  664. return -RT_ERROR;
  665. }
  666. accel_debug("Accel: Offset %+d %+d %+d\n",
  667. *(rt_int16_t *)&cmd[1], *(rt_int16_t *)&cmd[3], *(rt_int16_t *)&cmd[5]);
  668. #endif
  669. rt_timer_delete(calTimer);
  670. }
  671. return RT_EOK;
  672. }
  673. /***************************************************************************//**
  674. * @brief
  675. * Initialize the accelerometer
  676. *
  677. * @details
  678. *
  679. * @note
  680. *
  681. * @return
  682. * Error code
  683. ******************************************************************************/
  684. rt_err_t efm_accel_init(void)
  685. {
  686. rt_err_t ret;
  687. ret = RT_EOK;
  688. do
  689. {
  690. /* Find ADC device */
  691. accel = rt_device_find(ACCEL_USING_DEVICE_NAME);
  692. if (accel == RT_NULL)
  693. {
  694. accel_debug("Accel err: Can't find device: %s!\n", ACCEL_USING_DEVICE_NAME);
  695. ret = -RT_ERROR;
  696. break;
  697. }
  698. accel_debug("Accel: Find device %s\n", ACCEL_USING_DEVICE_NAME);
  699. /* --------- ADC interface --------- */
  700. #if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC)
  701. ADC_InitScan_TypeDef scanInit = ADC_INITSCAN_DEFAULT;
  702. #if defined(EFM32_GXXX_DK)
  703. /* Enable accelerometer */
  704. DVK_enablePeripheral(DVK_ACCEL);
  705. /* Select g-range */
  706. #if (ACCEL_G_SELECT == 0)
  707. DVK_disablePeripheral(DVK_ACCEL_GSEL);
  708. #elif (ACCEL_G_SELECT == 1)
  709. DVK_enablePeripheral(DVK_ACCEL_GSEL);
  710. #else
  711. #error "Wrong value for ACCEL_G_SELECT"
  712. #endif
  713. #endif
  714. /* Init ADC for scan mode */
  715. scanInit.reference = adcRefVDD;
  716. scanInit.input = ACCEL_X_ADC_CH | ACCEL_Y_ADC_CH | ACCEL_Z_ADC_CH;
  717. control.scan.init = &scanInit;
  718. if ((ret = accel->control(accel, RT_DEVICE_CTRL_ADC_MODE, \
  719. (void *)&control)) != RT_EOK)
  720. {
  721. break;
  722. }
  723. /* --------- IIC interface --------- */
  724. #elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC)
  725. rt_uint8_t cmd[2];
  726. /* Initialize */
  727. if ((ret = accel->control(accel, RT_DEVICE_CTRL_IIC_SETTING, \
  728. (void *)&control)) != RT_EOK)
  729. {
  730. break;
  731. }
  732. if (efm_accel_config(
  733. ACCEL_MODE_MEASUREMENT | ACCEL_RANGE_2G,
  734. EFM32_NO_DATA,
  735. EFM32_NO_DATA,
  736. EFM32_NO_DATA,
  737. EFM32_NO_DATA,
  738. EFM32_NO_DATA) != RT_EOK)
  739. {
  740. break;
  741. }
  742. /* Config interrupt pin1 */
  743. GPIO_PinModeSet(ACCEL_INT1_PORT, ACCEL_INT1_PIN, gpioModeInput, 0);
  744. /* Config interrupt pin2 */
  745. GPIO_PinModeSet(ACCEL_INT2_PORT, ACCEL_INT2_PIN, gpioModeInput, 0);
  746. #endif
  747. accel_debug("Accel: Init OK\n");
  748. return RT_EOK;
  749. } while (0);
  750. accel_debug("Accel err: Init failed!\n");
  751. return -RT_ERROR;
  752. }
  753. /*******************************************************************************
  754. * Export to FINSH
  755. ******************************************************************************/
  756. #ifdef RT_USING_FINSH
  757. #include <finsh.h>
  758. void accel_cal(rt_uint8_t mode, rt_uint32_t second)
  759. {
  760. if (efm_accel_auto_zero(mode, RT_TICK_PER_SECOND * second) != RT_EOK)
  761. {
  762. rt_kprintf("Error occurred.");
  763. return;
  764. }
  765. rt_kprintf("Calibration done.\n");
  766. }
  767. FINSH_FUNCTION_EXPORT(accel_cal, auto-zero calibration.)
  768. void list_accel(void)
  769. {
  770. struct efm32_accel_result_t data;
  771. efm_accel_get_data(&data, false);
  772. rt_kprintf("X: %d, Y: %d, Z: %d\n", data.x, data.y, data.z);
  773. }
  774. FINSH_FUNCTION_EXPORT(list_accel, list accelerometer info.)
  775. void test_accel(rt_uint8_t mode)
  776. {
  777. if (mode == 0)
  778. {
  779. if (efm_accel_config(
  780. ACCEL_MODE_LEVEL | ACCEL_RANGE_8G | ACCEL_INT_LEVEL_PULSE | \
  781. ACCEL_SOURCE_LEVEL_X | ACCEL_SOURCE_LEVEL_Y,
  782. 0x1f,
  783. EFM32_NO_DATA,
  784. EFM32_NO_DATA,
  785. EFM32_NO_DATA,
  786. EFM32_NO_DATA) != RT_EOK)
  787. {
  788. rt_kprintf("efm_accel_config(): error\n");
  789. return;
  790. }
  791. }
  792. else
  793. {
  794. if (efm_accel_config(
  795. ACCEL_MODE_PULSE | ACCEL_RANGE_8G | ACCEL_INT_SINGLE_DOUBLE | \
  796. ACCEL_SOURCE_PULSE_X | ACCEL_SOURCE_PULSE_Y,
  797. 0x1f,
  798. 0x1f,
  799. 200,
  800. 255,
  801. 255) != RT_EOK)
  802. {
  803. rt_kprintf("efm_accel_config(): error\n");
  804. return;
  805. }
  806. }
  807. }
  808. FINSH_FUNCTION_EXPORT(test_accel, list accelerometer info.)
  809. #endif
  810. #endif
  811. /***************************************************************************//**
  812. * @}
  813. ******************************************************************************/