/** * @brief Read BMA250 acceleration data. * * This function obtains accelerometer data for all three axes of the Bosch * device. The data is read from three device registers using a multi-byte * bus transfer. * * Along with the actual sensor data, the LSB byte contains a "new" flag * indicating if the data for this axis has been updated since the last * time the axis data was read. Reading either LSB or MSB data will * clear this flag. * * @param sensor Address of an initialized sensor device descriptor. * @param data The address of a vector storing sensor axis data. * @return bool true if the call succeeds, else false is returned. */ static bool bma250_get_accel(sensor_hal_t *hal, sensor_data_t *data) { size_t const count = sensor_bus_read(hal, hal->burst_addr, event_regs.acc, sizeof(event_regs.acc)); format_axis_data(hal, event_regs.acc, data); return (count == sizeof(event_regs.acc)); }
/** * @brief Read accelerometer data. * * This function obtains accelerometer data for all three axes of the Bosch * device. The data is read from six device registers using a multi-byte * bus transfer. The 10-bit raw results are then assembled from the two * register values for each axis, including extending the sign bit, to * form a signed 32-bit value. * * Along with the actual sensor data, the LSB byte contains a "new" flag * indicating if the data for this axis has been updated since the last * time the axis data was read. Reading either LSB or MSB data will * clear this flag. * * @param hal Address of an initialized sensor hardware descriptor. * @param data The address of a vector storing sensor axis data. * @return bool true if the call succeeds, else false is returned. */ static bool bma180_get_accel(sensor_hal_t *hal, sensor_data_t *data) { bma_axis_t axis[3]; size_t const count = sensor_bus_read(hal, hal->burst_addr, axis, sizeof(axis)); format_axis_data(hal, axis, data); return (count == sizeof(axis)); }
/** * @brief Bosch BMA250 accelerometer driver initialization. * * This is the main initialization function for the BMA250 device. * * @param sensor Address of a sensor device descriptor. * @param resvd Reserved value. * @return bool true if the call succeeds, else false is returned. */ bool bma250_init(sensor_t *sensor, int resvd) { bool status = false; sensor_hal_t *const hal = sensor->hal; if (BMA250_ID_VAL == sensor_bus_get(hal, BMA250_CHIP_ID)) { /* Set the driver function table and capabilities pointer. */ static const sensor_device_t bma250_device = { /* Bosch BMA250 Driver Entry Points & Capabilities */ .func.read = bma250_read, .func.ioctl = bma250_ioctl, .func.selftest = bma250_selftest, .func.event = bma250_event, .caps.feature = SENSOR_CAPS_3_AXIS | SENSOR_CAPS_SELFTEST | SENSOR_CAPS_HI_G_EVENT | SENSOR_CAPS_LO_G_EVENT | SENSOR_CAPS_TAP_EVENT | SENSOR_CAPS_TILT_EVENT | SENSOR_CAPS_AUX_TEMP, .caps.vendor = SENSOR_VENDOR_BOSCH, .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_g0, .caps.scale = SENSOR_SCALE_milli, .caps.name = "BMA250 Digital, triaxial acceleration sensor" }; sensor->drv = &bma250_device; /* Set the driver (device) default range, bandwidth, & * resolution. * * \internal * Per the BMA250 Datasheet the default range and bandwidth * after device reset are +/- 2g and 1kHz respectively. */ bma250_set_state(sensor, SENSOR_STATE_RESET); hal->range = 2000; hal->bandwidth = 1000; hal->resolution = BMA250_DATA_RESOLUTION; hal->burst_addr = BMA250_NEW_DATA_X; /* Install an interrupt handler. */ if ((STATUS_OK == hal->bus.status) && sensor_irq_connect(hal->mcu_sigint, bma250_isr, hal)) { status = true; } } return status; } /** * @brief Bosch BMA250 driver interrupt service routine. * * This is the common interrupt service routine for all enabled BMA250 interrupt * events. Five different types of interrupts can be programmed. All interrupt * criteria are combined and drive the interrupt pad with a Boolean \c OR * condition. * * Interrupt criteria are tested against values from the BMA250 digital filter * output. All thresholds are scaled using the current device range. Timings * for high and low acceleration are absolute values (1 LSB of HG_dur and LG_dur * registers corresponds to 1 millisecond, +/- 10%). Timing for the any-motion * interrupt and alert detection are proportional to the bandwidth setting. * * This routine handles interrupts generated when low-g, high-g, any-motion, * alert, and new data criteria are satisfied and the corresponding event * notification is enabled in the device. * * The BMA250 device does not provide any way to definitively identify an * any-motion interrupt once it has occurred. So, if a handler has been * installed for that event, it will always be called by this routine, * and the SENSOR_EVENT_MOTION indicator will be set in the event type field. * * @param arg The address of the driver sensor_hal_t descriptor. * @return Nothing. */ static void bma250_isr(volatile void *arg) { sensor_hal_t *const hal = (sensor_hal_t *)arg; hal->bus.no_wait = true; sensor_bus_read(hal, hal->burst_addr, &event_regs, sizeof(event_regs)); hal->bus.no_wait = false; if (STATUS_OK == hal->bus.status) { sensor_event_data_t event_data = {.data.scaled = true}; event_data.data.timestamp = sensor_timestamp(); event_data.event = SENSOR_EVENT_UNKNOWN; format_axis_data(hal, event_regs.acc, &(event_data.data)); if (event_regs.status_field.data_int) { event_data.event |= SENSOR_EVENT_NEW_DATA; (event_cb[0].handler)(&event_data, event_cb[0].arg); } if (event_regs.status_field.slope_int) { event_data.event |= SENSOR_EVENT_MOTION; (event_cb[1].handler)(&event_data, event_cb[1].arg); } if (event_regs.status_field.low_int) { event_data.event |= SENSOR_EVENT_LOW_G; (event_cb[2].handler)(&event_data, event_cb[2].arg); } if (event_regs.status_field.high_int) { event_data.event |= SENSOR_EVENT_HIGH_G; (event_cb[3].handler)(&event_data, event_cb[3].arg); } if (event_regs.status_field.s_tap_int) { event_data.event |= SENSOR_EVENT_S_TAP; (event_cb[4].handler)(&event_data, event_cb[4].arg); } if (event_regs.status_field.d_tap_int) { event_data.event |= SENSOR_EVENT_D_TAP; (event_cb[4].handler)(&event_data, event_cb[4].arg); } } }
/** * @brief Bosch BMA150 accelerometer driver initialization. * * This is the main initialization function for the BMA150 device. * * @param sensor Address of a sensor device descriptor. * @param resvd Reserved value. * @return bool true if the call succeeds, else false is returned. */ bool bma150_init(sensor_t *sensor, int resvd) { bool status = false; sensor_hal_t *const hal = sensor->hal; if (BMA150_ID_VAL == sensor_bus_get(hal, BMA150_CHIP_ID)) { /* Set the driver function table and capabilities pointer. */ static const sensor_device_t bma150_device = { .func.read = bma150_read, .func.ioctl = bma150_ioctl, .func.selftest = bma150_selftest, .func.event = bma150_event, .caps.feature = SENSOR_CAPS_3_AXIS | SENSOR_CAPS_SELFTEST | SENSOR_CAPS_HI_G_EVENT | SENSOR_CAPS_LO_G_EVENT | SENSOR_CAPS_AUX_TEMP, .caps.vendor = SENSOR_VENDOR_BOSCH, .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_g0, .caps.scale = SENSOR_SCALE_milli, .caps.name = "BMA150 Digital, triaxial acceleration sensor" }; sensor->drv = &bma150_device; /* Set the driver (device) default range, bandwidth, & * resolution. * * Per the BMA150 Datasheet the default range and bandwidth * after device reset are +/- 4g and 1500 Hz. respectively. So, * if that's the desired initialization state for this device, *then * don't use software to set these values in the driver _init() * routine. */ hal->range = 4000; hal->bandwidth = 1500; hal->resolution = BMA150_DATA_RESOLUTION; /* Set the device burst read base address. */ hal->burst_addr = BMA150_ACC_X_LSB; /* Initialize the control registers. */ sensor_bus_put(hal, BMA150_CTRL1, 0); sensor_bus_put(hal, BMA150_CTRL2, 0); sensor_bus_put(hal, BMA150_CTRL5, 0); /* Set the interrupt handler. */ if ((STATUS_OK == hal->bus.status) && sensor_irq_connect(hal->mcu_sigint, bma150_isr, hal)) { status = true; } } return status; } /** * @brief Bosch BMA150 driver interrupt service routine. * * This is the common interrupt service routine for all enabled BMA150 interrupt * events. Five different types of interrupts can be programmed. All interrupt * criteria are combined and drive the interrupt pad with a Boolean \c OR * condition. * * Interrupt events may be set to an inconsistent state by device EEPROM * changes. BMA150 interrupts should be disabled at the host microcontroller * when device EEPROM writes are performed. * * Interrupt criteria are tested against values from the BMA150 digital filter * output. All thresholds are scaled using the current device range. Timings * for high and low acceleration are absolute values (1 LSB of HG_dur and LG_dur * registers corresponds to 1 millisecond, +/- 10%). Timing for the any-motion * interrupt and alert detection are proportional to the bandwidth setting. * * This routine handles interrupts generated when low-g, high-g, any-motion, * alert, and new data criteria are satisfied and the corresponding event * notification is enabled in the device. * * The BMA150 device does not provide any way to definitively identify an * any-motion interrupt once it has occurred. So, if a handler has been * installed for that event, it will always be called by this routine, * and the SENSOR_EVENT_MOTION indicator will be set in the event type field. * * @param arg The address of the driver sensor_hal_t descriptor. * @return Nothing. */ static void bma150_isr(volatile void *arg) { sensor_hal_t *const hal = (sensor_hal_t *)arg; hal->bus.no_wait = true; sensor_bus_read(hal, hal->burst_addr, &event_regs, sizeof(event_regs)); hal->bus.no_wait = false; if (STATUS_OK == hal->bus.status) { static sensor_event_data_t event_data = {.data.scaled = true}; event_data.data.timestamp = sensor_timestamp(); event_data.event = SENSOR_EVENT_MOTION; /* * Test the "new data" bit in the sample outputs prior to * converting axis data to sign extended 10-bit values and * buffering the result. */ bool const new_data = event_regs.acc[2].field.new_data; format_axis_data(hal, event_regs.acc, &(event_data.data)); if (event_regs.status_field.LG_issued) { event_data.event = SENSOR_EVENT_LOW_G; (event_cb[2].handler)(&event_data, event_cb[2].arg); } else if (event_regs.status_field.HG_issued) { event_data.event = SENSOR_EVENT_HIGH_G; (event_cb[3].handler)(&event_data, event_cb[3].arg); } else if (new_data) { event_data.event = SENSOR_EVENT_NEW_DATA; (event_cb[0].handler)(&event_data, event_cb[0].arg); } else { /* Assume the any-motion event triggered the interrupt. */ (event_cb[1].handler)(&event_data, event_cb[1].arg); } } } /** * @brief Read BMA150 device ID and revision numbers. * * This function reads the accelerometer hardware identification registers * and returns these values in the specified data structure. * * @param hal Address of an initialized sensor hardware descriptor. * @param data Address of sensor_data_t structure to return values. * @return bool true if the call succeeds, else false is returned. */ static bool bma150_device_id(sensor_hal_t *hal, sensor_data_t *data) { data->device.id = sensor_bus_get(hal, BMA150_CHIP_ID); data->device.version = sensor_bus_get(hal, BMA150_CHIP_VERSION); return true; }