123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889 |
- /*
- * 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 <finsh.h>
- 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
- /***************************************************************************//**
- * @}
- ******************************************************************************/
|