/* * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2011-07-13 onelife Initial creation for using EFM32 ADC module to * interface the Freescale MMA7361L * 2011-08-02 onelife Add digital interface support of using EFM32 IIC * module for the Freescale MMA7455L */ /***************************************************************************//** * @addtogroup efm32 * @{ ******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include "board.h" #if defined(EFM32_USING_ACCEL) #if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC) #include "drv_adc.h" #elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC) #include "drv_iic.h" #include "hdl_interrupt.h" #endif #include "dev_accel.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ #ifdef EFM32_ACCEL_DEBUG #define accel_debug(format,args...) rt_kprintf(format, ##args) #else #define accel_debug(format,args...) #endif /* Private constants ---------------------------------------------------------*/ static rt_device_t accel; #if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC) static struct efm32_adc_control_t control = \ {ADC_MODE_SCAN, {3, ACCEL_USING_DMA}, {}}; static struct efm32_accel_result_t accelOffset = {0}; #elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC) static const struct efm32_iic_control_t control = \ {IIC_STATE_MASTER, 0x0000}; #endif static rt_bool_t accelInTime = true; static rt_uint32_t accelConfig = 0; /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /***************************************************************************//** * @brief * Get accelerometer output * * @details * * @note * * @param[out] data * Pointer to output buffer * * @param[in] lowResolution * Resolution selection * * @return * Error code ******************************************************************************/ rt_err_t efm_accel_get_data(struct efm32_accel_result_t *data, rt_bool_t lowResolution) { RT_ASSERT(accel != RT_NULL); rt_err_t ret; if (data == RT_NULL) { return -RT_ERROR; } ret = RT_EOK; do { /* --------- ADC interface --------- */ #if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC) struct efm32_adc_result_t result; result.mode = control.mode; result.buffer = (void *)data; if ((ret = accel->control(accel, RT_DEVICE_CTRL_RESUME, (void *)&result)) != RT_EOK) { break; } if ((ret = accel->control(accel, RT_DEVICE_CTRL_ADC_RESULT, \ (void *)&result)) != RT_EOK) { break; } data->x += accelOffset.x - 0x800; data->y += accelOffset.y - 0x800; data->z += accelOffset.z - 0x800; if (lowResolution) { data->x >>= 4; data->y >>= 4; data->z >>= 4; } /* --------- IIC interface --------- */ #elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC) if (lowResolution || \ ((accelConfig & ACCEL_MASK_RANGE) != MCTL_RANGE_8G)) { rt_int8_t buf[3]; buf[0] = XOUT8; if (accel->read(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, \ sizeof(buf)) == 0) { ret = -RT_ERROR; break; } data->x = buf[0]; data->y = buf[1]; data->z = buf[2]; } else { rt_uint8_t buf[6]; rt_uint16_t *temp = (rt_uint16_t *)&buf; buf[0] = XOUTL; if (accel->read(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, \ sizeof(buf)) == 0) { ret = -RT_ERROR; break; } data->x = (*temp & 0x200) ? ((rt_uint32_t)*temp | ~0x3FF) : \ ((rt_uint32_t)*temp & 0x3FF); data->y = (*++temp & 0x200) ? ((rt_uint32_t)*temp | ~0x3FF) : \ ((rt_uint32_t)*temp & 0x3FF); data->z = (*++temp & 0x200) ? ((rt_uint32_t)*temp | ~0x3FF) : \ ((rt_uint32_t)*temp & 0x3FF); } #endif return RT_EOK; } while (0); accel_debug("Accel err: Get data failed!\n"); return ret; } /***************************************************************************//** * @brief * Accelerometer timeout interrupt handler * * @details * * @note * * @param[in] parameter * Parameter ******************************************************************************/ static void efm_accel_timer(void* parameter) { accelInTime = false; } #if (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC) /***************************************************************************//** * @brief * Accelerometer level and pulse detection interrupts handler * * @details * * @note * * @param[in] device * Pointer to device descriptor ******************************************************************************/ static void efm_accel_isr(rt_device_t device) { rt_uint8_t buf[2]; if ((accelConfig & ACCEL_MASK_MODE) != ACCEL_MODE_MEASUREMENT) { /* Read detection source */ buf[0] = DETSRC; if (accel->read(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 1) != 1) { accel_debug("Accel: read error\n"); return; } accel_debug("Accel: DETSRC %x\n", buf[0]); /* Reset the interrupt flags: Part 1 */ buf[0] = INTRST; buf[1] = INTRST_INT_1 | INTRST_INT_2; accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2); /* Read status to waste some time */ buf[0] = STATUS; if (accel->read(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 1) != 1) { accel_debug("Accel: read error\n"); return; } accel_debug("Accel: STATUS %x\n", buf[0]); /* Reset the interrupt flags: Part 2 */ buf[0] = INTRST; buf[1] = 0x00; accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2); } } /***************************************************************************//** * @brief * Accelerometer configuration function * * @details * * @note * * @param[in] config * Configuration options * * @param[in] level_threshold * Level detection threshold * * @param[in] pulse_threshold * Pulse detection threshold * * @param[in] pulse_duration * Time window for 1st pulse * * @param[in] pulse_latency * Pulse latency Time * * @param[in] pulse_duration2 * Time window for 2nd pulse * * @return * Error code ******************************************************************************/ rt_err_t efm_accel_config(rt_uint32_t config, rt_uint8_t level_threshold, rt_uint8_t pulse_threshold, rt_uint8_t pulse_duration, rt_uint8_t pulse_latency, rt_uint8_t pulse_duration2) { rt_err_t ret; rt_uint8_t buf[2]; rt_uint8_t mode, mctl_reg, ctl1_reg, ctl2_reg; ret = RT_EOK; mctl_reg = 0; ctl1_reg = 0; ctl2_reg = 0; /* Modify MCTL */ mode = config & ACCEL_MASK_MODE; switch (mode) { case ACCEL_MODE_STANDBY: mctl_reg |= MCTL_MODE_STANDBY; break; case ACCEL_MODE_MEASUREMENT: mctl_reg |= MCTL_MODE_MEASUREMENT; break; case ACCEL_MODE_LEVEL: mctl_reg |= MCTL_MODE_LEVEL; break; case ACCEL_MODE_PULSE: mctl_reg |= MCTL_MODE_PULSE; break; default: return -RT_ERROR; } switch (config & ACCEL_MASK_RANGE) { case ACCEL_RANGE_8G: mctl_reg |= MCTL_RANGE_8G; break; case ACCEL_RANGE_4G: mctl_reg |= MCTL_RANGE_4G; break; case ACCEL_RANGE_2G: mctl_reg |= MCTL_RANGE_2G; break; default: return -RT_ERROR; } if ((mode == ACCEL_MODE_LEVEL) || (mode == ACCEL_MODE_PULSE)) { mctl_reg |= MCTL_PIN_INT1; } /* Modify CTL1 */ if (config & ACCEL_INTPIN_INVERSE) { ctl1_reg |= CTL1_INTPIN_INVERSE; } switch (config & ACCEL_MASK_INT) { case ACCEL_INT_LEVEL_PULSE: ctl1_reg |= CTL1_INT_LEVEL_PULSE; break; case ACCEL_INT_PULSE_LEVEL: ctl1_reg |= CTL1_INT_PULSE_LEVEL; break; case ACCEL_INT_SINGLE_DOUBLE: ctl1_reg |= CTL1_INT_SINGLE_DOUBLE; break; default: break; } switch (config & ACCEL_MASK_DISABLE) { case ACCEL_DISABLE_X: ctl1_reg |= CTL1_X_DISABLE; break; case ACCEL_DISABLE_Y: ctl1_reg |= CTL1_Y_DISABLE; break; case ACCEL_DISABLE_Z: ctl1_reg |= CTL1_Z_DISABLE; break; default: break; } if (config & ACCEL_THRESHOLD_INTEGER) { ctl1_reg |= CTL1_THRESHOLD_INTEGER; } if (config & ACCEL_BANDWIDTH_125HZ) { ctl1_reg |= CTL1_BANDWIDTH_125HZ; } /* Modify CTL2 */ if (config & ACCEL_LEVEL_AND) { ctl2_reg |= CTL2_LEVEL_AND; } if (config & ACCEL_PULSE_AND) { ctl2_reg |= CTL2_PULSE_AND; } if (config & ACCEL_DRIVE_STRONG) { ctl2_reg |= CTL2_DRIVE_STRONG; } do { /* Write registers */ buf[0] = MCTL; buf[1] = mctl_reg; if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0) { ret = -RT_ERROR; break; } accel_debug("Accel: MCTL %x\n", mctl_reg); buf[0] = CTL1; buf[1] = ctl1_reg; if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0) { ret = -RT_ERROR; break; } accel_debug("Accel: CTL1 %x\n", ctl1_reg); buf[0] = CTL2; buf[1] = ctl2_reg; if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0) { ret = -RT_ERROR; break; } accel_debug("Accel: CTL2 %x\n", ctl2_reg); accelConfig = config; if (mode == ACCEL_MODE_PULSE) { buf[0] = PDTH; buf[1] = pulse_threshold; if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0) { ret = -RT_ERROR; break; } accel_debug("Accel: PDTH %x\n", buf[1]); buf[0] = PW; buf[1] = pulse_duration; if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0) { ret = -RT_ERROR; break; } accel_debug("Accel: PW %x\n", buf[1]); buf[0] = LT; buf[1] = pulse_latency; if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0) { ret = -RT_ERROR; break; } accel_debug("Accel: LT %x\n", buf[1]); buf[0] = TW; buf[1] = pulse_duration2; if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0) { ret = -RT_ERROR; break; } accel_debug("Accel: TW %x\n", buf[1]); } if ((mode == ACCEL_MODE_LEVEL) || (mode == ACCEL_MODE_PULSE)) { efm32_irq_hook_init_t hook; /* Reset the interrupt flags: Part 1 */ buf[0] = INTRST; buf[1] = INTRST_INT_1 | INTRST_INT_2; if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0) { ret = -RT_ERROR; break; } /* Set level detection threshold */ buf[0] = LDTH; if (config & ACCEL_THRESHOLD_INTEGER) { buf[1] = level_threshold; } else { buf[1] = level_threshold & 0x7f; } if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0) { ret = -RT_ERROR; break; } accel_debug("Accel: LDTH %x\n", buf[1]); /* Config interrupt */ hook.type = efm32_irq_type_gpio; hook.unit = ACCEL_INT1_PIN; hook.cbFunc = efm_accel_isr; hook.userPtr = RT_NULL; efm32_irq_hook_register(&hook); hook.unit = ACCEL_INT2_PIN; efm32_irq_hook_register(&hook); /* Clear pending interrupt */ BITBAND_Peripheral(&(GPIO->IFC), ACCEL_INT1_PIN, 0x1UL); BITBAND_Peripheral(&(GPIO->IFC), ACCEL_INT2_PIN, 0x1UL); /* Set raising edge interrupt and clear/enable it */ GPIO_IntConfig( ACCEL_INT1_PORT, ACCEL_INT1_PIN, true, false, true); GPIO_IntConfig( ACCEL_INT2_PORT, ACCEL_INT2_PIN, true, false, true); if (((rt_uint8_t)ACCEL_INT1_PORT % 2) || \ ((rt_uint8_t)ACCEL_INT2_PORT % 2)) { NVIC_ClearPendingIRQ(GPIO_ODD_IRQn); NVIC_SetPriority(GPIO_ODD_IRQn, EFM32_IRQ_PRI_DEFAULT); NVIC_EnableIRQ(GPIO_ODD_IRQn); } if (!((rt_uint8_t)ACCEL_INT1_PORT % 2) || \ !((rt_uint8_t)ACCEL_INT2_PORT % 2)) { NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn); NVIC_SetPriority(GPIO_EVEN_IRQn, EFM32_IRQ_PRI_DEFAULT); NVIC_EnableIRQ(GPIO_EVEN_IRQn); } /* Reset the interrupt flags: Part 2 */ buf[0] = INTRST; buf[1] = 0x00; if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, (void *)buf, 2) == 0) { ret = -RT_ERROR; break; } } } while (0); return ret; } #endif /***************************************************************************//** * @brief * Accelerometer auto-zero calibration function * * @details * * @note * * @param[in] mode * 0, simple mode (assuming the device is placed on flat surface) * 1, interaction method * * @param[in] period * Time period to perform auto-zero calibration * * @return * Error code ******************************************************************************/ rt_err_t efm_accel_auto_zero(rt_uint8_t mode, rt_tick_t period) { RT_ASSERT(accel != RT_NULL); rt_timer_t calTimer; struct efm32_accel_result_t min = {0, 0, 0}; struct efm32_accel_result_t max = {0, 0, 0}; struct efm32_accel_result_t temp, sum; rt_int32_t simpleOffset[] = ACCEL_CAL_1G_VALUE; rt_uint8_t cmd[7] = {0}; rt_uint8_t i, j; /* Reset offset */ #if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC) accelOffset.x = 0; accelOffset.y = 0; accelOffset.z = 0; #elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC) cmd[0] = XOFFL; if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, cmd, sizeof(cmd)) == 0) { return -RT_ERROR; } #endif if (mode == ACCEL_CAL_SIMPLE) { /* Simple mode */ for (j = 0; j < ACCEL_CAL_ROUND; j++) { sum.x = 0x0; sum.y = 0x0; sum.z = 0x0; for (i = 0; i < ACCEL_CAL_SAMPLES; i++) { #if (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC) /* Waiting for data ready */ while(!GPIO_PinInGet(ACCEL_INT1_PORT, ACCEL_INT1_PIN)); #endif if (efm_accel_get_data(&temp, false) != RT_EOK) { return -RT_ERROR; } sum.x += temp.x; sum.y += temp.y; sum.z += temp.z; } #if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC) temp.x = sum.x / ACCEL_CAL_SAMPLES; temp.y = sum.y / ACCEL_CAL_SAMPLES; temp.z = sum.z / ACCEL_CAL_SAMPLES - simpleOffset[ACCEL_G_SELECT]; if ((temp.x == 0) && (temp.y == 0) && \ (temp.z == 0)) { accel_debug("Accel: Offset %+d %+d %+d\n", accelOffset.x, accelOffset.y, accelOffset.z); break; } accelOffset.x -= temp.x; accelOffset.y -= temp.y; accelOffset.z -= temp.z; #elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC) temp.x = sum.x / (ACCEL_CAL_SAMPLES >> 1); temp.y = sum.y / (ACCEL_CAL_SAMPLES >> 1); temp.z = sum.z / (ACCEL_CAL_SAMPLES >> 1) \ - (simpleOffset[ACCEL_G_SELECT] << 1); if ((temp.x == 0) && (temp.y == 0) && \ (temp.z == 0)) { break; } /* Set offset drift registers */ max.x -= temp.x; max.y -= temp.y; max.z -= temp.z; *(rt_int16_t *)&cmd[1] = (rt_int16_t)max.x; *(rt_int16_t *)&cmd[3] = (rt_int16_t)max.y; *(rt_int16_t *)&cmd[5] = (rt_int16_t)max.z; if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, cmd, sizeof(cmd)) == 0) { return -RT_ERROR; } accel_debug("Accel: Offset %+d %+d %+d\n", *(rt_int16_t *)&cmd[1], \ *(rt_int16_t *)&cmd[3], *(rt_int16_t *)&cmd[5]); #endif rt_thread_delay(1); } } else { /* Interact mode */ if ((calTimer = rt_timer_create( "cal_tmr", efm_accel_timer, RT_NULL, period, RT_TIMER_FLAG_ONE_SHOT)) == RT_NULL) { accel_debug("Accel err: Create timer failed!\n"); return -RT_ERROR; } accelInTime = true; rt_timer_start(calTimer); do { sum.x = 0x0; sum.y = 0x0; sum.z = 0x0; for (i = 0; i < ACCEL_CAL_SAMPLES; i++) { #if (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC) /* Waiting for data ready */ while(!GPIO_PinInGet(ACCEL_INT1_PORT, ACCEL_INT1_PIN)); #endif if (efm_accel_get_data(&temp, false) != RT_EOK) { return -RT_ERROR; } sum.x += temp.x; sum.y += temp.y; sum.z += temp.z; } sum.x /= ACCEL_CAL_SAMPLES; sum.y /= ACCEL_CAL_SAMPLES; sum.z /= ACCEL_CAL_SAMPLES; if (sum.x < min.x) { min.x = sum.x; } if (sum.y < min.y) { min.y = sum.y; } if (sum.z < min.z) { min.z = sum.z; } if (sum.x > max.x) { max.x = sum.x; } if (sum.y > max.y) { max.y = sum.y; } if (sum.z > max.z) { max.z = sum.z; } rt_thread_delay(1); } while (accelInTime); accel_debug("Accel: Min %+d %+d %+d, max %+d %+d %+d\n", min.x, min.y, min.z, max.x, max.y, max.z); #if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC) accelOffset.x = -((min.x + max.x) >> 1); accelOffset.y = -((min.y + max.y) >> 1); accelOffset.z = -((min.z + max.z) >> 1); accel_debug("Accel: Offset %+d %+d %+d\n", accelOffset.x, accelOffset.y, accelOffset.z); #elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC) /* Set offset drift registers */ *(rt_int16_t *)&cmd[1] = (rt_int16_t)-(min.x + max.x); *(rt_int16_t *)&cmd[3] = (rt_int16_t)-(min.y + max.y); *(rt_int16_t *)&cmd[5] = (rt_int16_t)-(min.z + max.z); if (accel->write(accel, ACCEL_IIC_SLAVE_ADDRESS, cmd, sizeof(cmd)) == 0) { return -RT_ERROR; } accel_debug("Accel: Offset %+d %+d %+d\n", *(rt_int16_t *)&cmd[1], *(rt_int16_t *)&cmd[3], *(rt_int16_t *)&cmd[5]); #endif rt_timer_delete(calTimer); } return RT_EOK; } /***************************************************************************//** * @brief * Initialize the accelerometer * * @details * * @note * * @return * Error code ******************************************************************************/ rt_err_t efm_accel_init(void) { rt_err_t ret; ret = RT_EOK; do { /* Find ADC device */ accel = rt_device_find(ACCEL_USING_DEVICE_NAME); if (accel == RT_NULL) { accel_debug("Accel err: Can't find device: %s!\n", ACCEL_USING_DEVICE_NAME); ret = -RT_ERROR; break; } accel_debug("Accel: Find device %s\n", ACCEL_USING_DEVICE_NAME); /* --------- ADC interface --------- */ #if (EFM32_USING_ACCEL == EFM32_INTERFACE_ADC) ADC_InitScan_TypeDef scanInit = ADC_INITSCAN_DEFAULT; #if defined(EFM32_GXXX_DK) /* Enable accelerometer */ DVK_enablePeripheral(DVK_ACCEL); /* Select g-range */ #if (ACCEL_G_SELECT == 0) DVK_disablePeripheral(DVK_ACCEL_GSEL); #elif (ACCEL_G_SELECT == 1) DVK_enablePeripheral(DVK_ACCEL_GSEL); #else #error "Wrong value for ACCEL_G_SELECT" #endif #endif /* Init ADC for scan mode */ scanInit.reference = adcRefVDD; scanInit.input = ACCEL_X_ADC_CH | ACCEL_Y_ADC_CH | ACCEL_Z_ADC_CH; control.scan.init = &scanInit; if ((ret = accel->control(accel, RT_DEVICE_CTRL_ADC_MODE, \ (void *)&control)) != RT_EOK) { break; } /* --------- IIC interface --------- */ #elif (EFM32_USING_ACCEL == EFM32_INTERFACE_IIC) rt_uint8_t cmd[2]; /* Initialize */ if ((ret = accel->control(accel, RT_DEVICE_CTRL_IIC_SETTING, \ (void *)&control)) != RT_EOK) { break; } if (efm_accel_config( ACCEL_MODE_MEASUREMENT | ACCEL_RANGE_2G, EFM32_NO_DATA, EFM32_NO_DATA, EFM32_NO_DATA, EFM32_NO_DATA, EFM32_NO_DATA) != RT_EOK) { break; } /* Config interrupt pin1 */ GPIO_PinModeSet(ACCEL_INT1_PORT, ACCEL_INT1_PIN, gpioModeInput, 0); /* Config interrupt pin2 */ GPIO_PinModeSet(ACCEL_INT2_PORT, ACCEL_INT2_PIN, gpioModeInput, 0); #endif accel_debug("Accel: Init OK\n"); return RT_EOK; } while (0); accel_debug("Accel err: Init failed!\n"); return -RT_ERROR; } /******************************************************************************* * Export to FINSH ******************************************************************************/ #ifdef RT_USING_FINSH #include void accel_cal(rt_uint8_t mode, rt_uint32_t second) { if (efm_accel_auto_zero(mode, RT_TICK_PER_SECOND * second) != RT_EOK) { rt_kprintf("Error occurred."); return; } rt_kprintf("Calibration done.\n"); } FINSH_FUNCTION_EXPORT(accel_cal, auto-zero calibration.) void list_accel(void) { struct efm32_accel_result_t data; efm_accel_get_data(&data, false); rt_kprintf("X: %d, Y: %d, Z: %d\n", data.x, data.y, data.z); } FINSH_FUNCTION_EXPORT(list_accel, list accelerometer info.) void test_accel(rt_uint8_t mode) { if (mode == 0) { if (efm_accel_config( ACCEL_MODE_LEVEL | ACCEL_RANGE_8G | ACCEL_INT_LEVEL_PULSE | \ ACCEL_SOURCE_LEVEL_X | ACCEL_SOURCE_LEVEL_Y, 0x1f, EFM32_NO_DATA, EFM32_NO_DATA, EFM32_NO_DATA, EFM32_NO_DATA) != RT_EOK) { rt_kprintf("efm_accel_config(): error\n"); return; } } else { if (efm_accel_config( ACCEL_MODE_PULSE | ACCEL_RANGE_8G | ACCEL_INT_SINGLE_DOUBLE | \ ACCEL_SOURCE_PULSE_X | ACCEL_SOURCE_PULSE_Y, 0x1f, 0x1f, 200, 255, 255) != RT_EOK) { rt_kprintf("efm_accel_config(): error\n"); return; } } } FINSH_FUNCTION_EXPORT(test_accel, list accelerometer info.) #endif #endif /***************************************************************************//** * @} ******************************************************************************/