Example #1
0
/**
 * @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));
}
Example #2
0
/**
 * @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));
}
Example #3
0
/**
 * @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);
		}
	}
}
Example #4
0
/**
 * @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;
}