/** * @brief Set the ITG-3200 execution mode. * * This routine sets a specified ITG-3200 execution state to one of the * following: * * SENSOR_STATE_SLEEP or SENSOR_STATE_LOWEST_POWER * Setting the sleep mode puts the device into very low power sleep * mode. In this mode, only the serial interface and internal registers * remain active. * * SENSOR_STATE_NORMAL or SENSOR_STATE_HIGHEST_POWER * Sets the device to a normal operational state. * * SENSOR_STATE_RESET * Sets the device and internal registers to the power-up default * settings. * * @param sensor Address of an initialized sensor device descriptor. * @param state A specified sensor operational state. * @return bool true if the call succeeds, else false is returned. */ static bool itg3200_set_state(sensor_hal_t *hal, sensor_state_t state) { switch (state) { default: return false; case SENSOR_STATE_SLEEP: case SENSOR_STATE_LOWEST_POWER: sensor_reg_bitset(hal, ITG3200_PWR_MGM, PWR_MGM_SLEEP); break; case SENSOR_STATE_NORMAL: case SENSOR_STATE_HIGHEST_POWER: sensor_reg_bitclear(hal, ITG3200_PWR_MGM, PWR_MGM_SLEEP); delay_ms(5); break; case SENSOR_STATE_RESET: /* * \todo * * Update sensor device descriptor operational settings. */ return itg3200_default_init(hal); } return true; }
/** * @brief Enable/disable ITG3200 sensor event * * @param sensor Address of an initialized sensor device descriptor * @param callback Application-defined event callback handler descriptor * @param enable Enable flag: true = enable event, false = disable event * @return bool true if the call succeeds, else false is returned */ static bool itg3200_event(sensor_t *sensor, sensor_event_t sensor_event, sensor_event_callback_t *callback, bool enable) { sensor_hal_t *const hal = sensor->hal; bool status = false; if (sensor_event & SENSOR_EVENT_NEW_DATA) { if (callback) { event_cb = *callback; } if (enable) { /* Enable new data int, latch until any reg is read, * active high */ sensor_bus_put(hal, ITG3200_INT_CFG, INT_CFG_RAW_RDY_EN | INT_CFG_ANYRD_2CLEAR); } else { /* Disable new data int */ sensor_reg_bitclear(hal, ITG3200_INT_CFG, INT_CFG_LATCH_INT_EN); } status = true; } return status; }
/** * @brief Enable or disable the BMA220 sleep mode. * * This routine enables or disables the BMA220 sleep mode depending upon * the value of the \sleep parameter; a \true value enables sleep mode and * a \false value disables sleep mode by setting or clearing the 'sleep_en' * bit, respectively. * * @param hal Address of an initialized sensor hardware descriptor. * @param sleep Set flag \true to enable sleep mode. * @return Nothing */ static inline void bma220_sleep_en(sensor_hal_t *hal, bool sleep) { if (sleep) { sensor_reg_bitset(hal, BMA220_SLEEP_CONFIG, SLEEP_ENABLE); } else { sensor_reg_bitclear(hal, BMA220_SLEEP_CONFIG, SLEEP_ENABLE); } }
/** * @brief Set the BMA150 execution mode. * * This routine sets a specified BMA150 execution state to one of the * following: * * SENSOR_STATE_SLEEP or SENSOR_STATE_LOWEST_POWER * Setting the sleep mode puts the BMA150 into a very low power state in * which no communication with the sensor IC is possible. The current * consumption in sleep mode is about 1 microamp. * * In case of a soft-reset, it is recommended to do the reset after * switching from sleep to operational mode. In case a soft-reset is * activated during sleep mode, it can take up to 30ms until normal * operation has resumed. * * SENSOR_STATE_LOW_POWER * This option sets the BMA150 to a low power "wake-up" mode that triggers * a system wake-up (interrupt output to master) when motion is detected. * In this mode, the device periodically evaluates acceleration data with * respect to interrupt criteria defined by the user. * * Typical current consumption in wake-up mode is estimated as follows: * @code * i_DD * t_active + i_DDsm * wake_up_pause * i_self_wake_up = ------------------------------------------ * t_active + wake_up_pause * @endcode * with approximation: * @code * t_active = 1ms + 0.333ms * [(4 * 750/bandwidth) + (1500/bandwidth) * n] * @endcode * with parameters: * @code * i_DD Normal mode current (200 microamp) * i_DDsm Sleep mode current (1 microamp) * wake_up_pause Wake-up pause setting * n Number of data points in any-motion logic (n=0 for * high-g and low-g threshold, n=3 for any-motion) * bandwidth bandwidth @ settings 1500 through 25 Hz. * @endcode * SENSOR_STATE_NORMAL or SENSOR_STATE_HIGHEST_POWER * In normal mode the sensor IC data and status registers can be accessed * without restriction. The device current consumption is 200 microamps * in this state. * * SENSOR_STATE_RESET * This function resets the device and internal registers to the power-up * default settings. * * In the wake-up mode, the BMA150 automatically switches from sleep mode to * normal mode after a delay defined by a programmable \c wake_up_pause value. * After transitioning from sleep to normal mode, acceleration data acquisition * and interrupt verification are performed. The sensor automatically returns * to sleep mode again if no interrupt criteria are satisfied. * * @param hal Address of an initialized sensor hardware descriptor. * @param state A specified sensor operational state. * @return bool true if the call succeeds, else false is returned. */ static bool bma150_set_state(sensor_hal_t *hal, sensor_state_t state) { switch (state) { case SENSOR_STATE_SLEEP: case SENSOR_STATE_LOWEST_POWER: sensor_reg_bitclear(hal, BMA150_CTRL5, CTRL5_WAKE_UP); sensor_reg_bitset(hal, BMA150_CTRL1, CTRL1_SLEEP); break; case SENSOR_STATE_LOW_POWER: sensor_reg_bitclear(hal, BMA150_CTRL1, CTRL1_SLEEP); sensor_reg_bitset(hal, BMA150_CTRL5, CTRL5_WAKE_UP); break; case SENSOR_STATE_NORMAL: case SENSOR_STATE_HIGHEST_POWER: sensor_reg_bitclear(hal, BMA150_CTRL1, CTRL1_SLEEP); sensor_reg_bitclear(hal, BMA150_CTRL5, CTRL5_WAKE_UP); break; case SENSOR_STATE_RESET: /* * \todo * * Update sensor device descriptor operational settings. */ sensor_reg_bitclear(hal, BMA150_CTRL1, CTRL1_SLEEP); sensor_bus_put(hal, BMA150_CTRL1, CTRL1_SOFT_RESET); break; default: return false; } return true; }
/** * @brief Run BMA150 self-tests. * * @param sensor Address of an initialized sensor device descriptor. * @param test_code Address of a device-specific numeric test code. * @param arg Device-specific self-test argument options. * @return bool true if the call succeeds, else false is returned. */ static bool bma150_selftest(sensor_t *sensor, int *test_code, void *arg) { sensor_hal_t *const hal = sensor->hal; bool result = false; if (SENSOR_TEST_DEFLECTION == *test_code) { /* Execute BMA150 self-test 0; electrostatic deflection test. */ sensor_reg_bitset(hal, BMA150_CTRL1, CTRL1_SELF_TEST_0); result = (STATUS1_ST_RESULT & sensor_bus_get(hal, BMA150_STATUS1)) ? true : false; sensor_reg_bitclear(hal, BMA150_CTRL1, CTRL1_SELF_TEST_0); } else if (SENSOR_TEST_INTERRUPT == *test_code) { /* Execute BMA150 self-test 1; interrupt to MCU test. */ sensor_reg_bitset(hal, BMA150_CTRL1, CTRL1_SELF_TEST_1); } return result; }
/** * @brief InvenSense IMU-3000 motion processor driver initialization. * * This is the main initialization function for the IMU-3000 device. * * @param sensor Address of a sensor device descriptor. * @param resvd Reserved value. * @return bool true if the sensor is ready for use, else false. */ bool imu3000_init(sensor_t *sensor, int resvd) { sensor_hal_t *const hal = sensor->hal; sensor_hal_t *const aux = (sensor_hal_t *)sensor->aux; bool status = false; /* Set the driver function table and capabilities pointer. */ static const sensor_device_t imu3000_device = { .func.read = imu3000_read, .func.ioctl = imu3000_ioctl, .func.event = imu3000_event, .caps.feature = SENSOR_CAPS_3_AXIS | SENSOR_CAPS_AUX_TEMP | SENSOR_CAPS_AUX_ACCEL, .caps.vendor = SENSOR_VENDOR_INVENSENSE, .caps.range_table = range_table, .caps.band_table = band_table, .caps.range_count = ARRAYSIZE(range_table), .caps.band_count = ARRAYSIZE(band_table), .caps.units = SENSOR_UNITS_deg_per_sec, .caps.name = "InvenSense IMU-3000 Motion Processing Unit" }; sensor->drv = &imu3000_device; /* Set the driver default, range, bandwidth, resolution, etc. */ hal->range = range_table [sensor_fs_sel].range_units; hal->bandwidth = band_table [sensor_dlpf_cfg].bandwidth_Hz; hal->sample_rate = 100; hal->resolution = IMU3000_RESOLUTION; /* Apply default device settings */ if (imu3000_default_init(hal, aux) != true) { return status; /* return error */ } /* Set start addr for burst read (used during interrupt). */ hal->burst_addr = IMU3000_INT_STATUS; /* Connect interrupt event handler. */ if (sensor_irq_connect(hal->mcu_sigint, imu3000_isr, hal)) { status = true; } return status; } /** * @brief Invensense IMU3000 driver interrupt service routine. * * This is the interrupt service routine for enabled IMU3000 interrupt events. * Only the new data ("raw data ready") interrupt is supported. * * @param arg The address of the driver sensor_hal_t descriptor. * @return Nothing. */ static void imu3000_isr(volatile void *arg) { sensor_hal_t *const hal = (sensor_hal_t *)arg; int16_t input[3]; hal->bus.no_wait = true; imu3000_event_t regs; sensor_bus_read(hal, hal->burst_addr, ®s, sizeof(regs)); hal->bus.no_wait = false; if (STATUS_OK == hal->bus.status) { /* Assume new data to avoid an apparent race condition. The * interupt status register sometimes has the new data flag * cleared before it is read above. If this happens, the sensor will * not generate any further new data interrupts until the device is * independently accessed. */ static sensor_event_data_t event_data = {.data.scaled = true}; event_data.data.timestamp = sensor_timestamp(); event_data.event = SENSOR_EVENT_NEW_DATA; input[0] = (regs.x_hi << 8) | regs.x_lo; input[1] = (regs.y_hi << 8) | regs.y_lo; input[2] = (regs.z_hi << 8) | regs.z_lo; event_data.data.axis.x = hal->orientation.x.sign * input[hal->orientation.x.axis]; event_data.data.axis.y = hal->orientation.y.sign * input[hal->orientation.y.axis]; event_data.data.axis.z = hal->orientation.z.sign * input[hal->orientation.z.axis]; const int32_t scaling = (int32_t)scale_lsb_per_dps[sensor_fs_sel]; event_data.data.axis.x /= scaling; event_data.data.axis.y /= scaling; event_data.data.axis.z /= scaling; /* Call application-supplied handler routine */ (event_cb.handler)(&event_data, event_cb.arg); } } /** * @brief Enable/disable IMU3000 sensor event * * @param sensor Address of an initialized sensor device descriptor * @param callback Application-defined event callback handler descriptor * @param enable Enable flag: true = enable event, false = disable event * @return bool true if the call succeeds, else false is returned */ static bool imu3000_event(sensor_t *sensor, sensor_event_t sensor_event, sensor_event_callback_t *callback, bool enable) { sensor_hal_t *const hal = sensor->hal; bool status = false; if (sensor_event & SENSOR_EVENT_NEW_DATA) { if (callback) { event_cb = *callback; } if (enable) { /* Enable new data int, latch until any reg is read, * active high */ sensor_bus_put(hal, IMU3000_INT_CFG, INT_CFG_RAW_RDY_EN | INT_CFG_ANYRD_2CLEAR); } else { /* Disable new data int */ sensor_reg_bitclear(hal, IMU3000_INT_CFG, INT_CFG_LATCH_INT_EN); } status = true; } return status; }