Beispiel #1
0
/**
 * @brief Get event threshold value
 *
 * @param hal       Address of an initialized sensor hardware descriptor.
 * @param threshold Address of threshold descriptor.
 * @return bool     true if the call succeeds, else false is returned.
 */
static bool bma150_get_threshold
	(sensor_hal_t *hal, sensor_threshold_desc_t *threshold)
{
	uint32_t regval;
	bool result = false;

	switch (threshold->type) {
	case SENSOR_THRESHOLD_MOTION:           /* any-motion threshold */
		regval = (uint32_t)sensor_bus_get(hal, BMA150_ANY_MOTION_THRES);
		threshold->value = (int16_t)((regval * hal->range * 16) / 2000);
		result = true;
		break;

	case SENSOR_THRESHOLD_LOW_G:            /* low-G threshold */
		regval = (uint32_t)sensor_bus_get(hal, BMA150_LG_THRES);
		threshold->value = (int16_t)((regval * hal->range) / 256);
		result = true;
		break;

	case SENSOR_THRESHOLD_HIGH_G:           /* high-G threshold */
		regval = (uint32_t)sensor_bus_get(hal, BMA150_HG_THRES);
		threshold->value = (int16_t)((regval * hal->range) / 256);
		result = true;
		break;

	default:
		/* Invalid/unsupported threshold type - do nothing, return false. */
		break;
	}

	return result;
}
Beispiel #2
0
/**
 * @brief Enable or disable SFH7770 sensor events.
 *
 * @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 sfh7770_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;

	uint8_t int_set = sensor_bus_get(hal, SFH7770_INT_SET);

	if (sensor_event & SENSOR_EVENT_NEAR_PROXIMITY) {
		if (callback) {
			event_cb[0] = *callback;
		}

		if (enable) {
			int_set |= INT_MODE_PS;
		} else {
			int_set &= ~INT_MODE_PS;
		}

		status = true;
	}

	if (sensor_event & SENSOR_EVENT_LOW_LIGHT) {
		if (callback) {
			event_cb[1] = *callback;
		}

		if (enable) {
			int_set |= INT_MODE_ALS;
		} else {
			int_set &= ~INT_MODE_ALS;
		}

		status = true;
	}

	if (sensor_event & SENSOR_EVENT_HIGH_LIGHT) {
		if (callback) {
			event_cb[2] = *callback;
		}

		if (enable) {
			int_set |= INT_MODE_ALS;
		} else {
			int_set &= ~INT_MODE_ALS;
		}

		status = true;
	}

	/* Write the new setting then read to clear. */
	sensor_bus_put(hal, SFH7770_INT_SET, int_set);

	int_set = sensor_bus_get(hal, SFH7770_INT_SET);

	return status;
}
Beispiel #3
0
/**
 * @brief Osram SFH5712 light sensor driver initialization.
 *
 * This is the main initialization function for the SFH5712 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 sfh5712_init(sensor_t *sensor, int resvd)
{
	bool status = false;
	sensor_hal_t *const hal = sensor->hal;

	/* Read and check part ID register */
	uint8_t part_id = sensor_bus_get(hal, SFH5712_PART_ID);

	if (part_id == (SFH5712_PART_ID_VAL | SFH5712_PART_REV_VAL)) {
		/* Set the driver function table and capabilities pointer. */
		static const sensor_device_t sfh5712_device = {
			.func.read            = sfh5712_read,
			.func.ioctl           = sfh5712_ioctl,
#if 0
			.caps.feature         = XXX
#endif
			.caps.vendor          = SENSOR_VENDOR_OSRAM,
			.caps.units           = SENSOR_UNITS_lux,
			.caps.scale           = SENSOR_SCALE_one,
			.caps.name            = "SFH5712 Ambient Light Sensor"
		};

		sensor->drv = &sfh5712_device;

		hal->resolution = SFH5712_DATA_RESOLUTION;

		/* Put sensor in active mode */
		sensor_bus_put(hal, SFH5712_ALS_CONTROL, ALS_MODE_ACTIVE);

		status = true;
	}

	return status;
}

/**
 * @brief Read SFH5712 device ID and revision numbers.
 *
 * This function reads the sensor 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 sfh5712_device_id(sensor_hal_t *hal, sensor_data_t *data)
{
	uint32_t const part_id = sensor_bus_get(hal, SFH5712_PART_ID);

	data->device.id = (part_id & PART_ID_MASK) >> PART_ID_SHIFT;
	data->device.version = (part_id & PART_REV_MASK);

	return true;
}
Beispiel #4
0
/**
 * @brief Calibrate proximity sensor detection thresholds
 *
 * This function measures the proximity sensor output in 3 different steps,
 * one for each channel in the device.  This function should be called when
 * a sample object has been placed at the desired distance from the device
 * to define the threshold for near-proximity detection.  The measured
 * proximity sensor value for each channel is stored in non-volatile memory.
 * These thresholds will later be used to set the threshold during the
 * device initialization sequence.
 *
 * This routine must be called 3 times total, with the "step" parameter
 * indicating what stage of the calibration is being performed (i.e. which
 * channel of the proximity sensor).  This multi-step mechanism allows
 * the application to prompt for physical placement of the object to be
 * detected before this routine is called.
 *
 * @param sensor     Address of an initialized sensor device descriptor.
 * @param calib_type The address of a vector storing sensor axis data.
 * @param step       The calibration stage number [1,3].
 * @param info       Unimplemented (ignored) parameter.
 * @return bool     true if the call succeeds, else false is returned.
 */
static bool sfh7770_calibrate(sensor_t *sensor,
		sensor_calibration_t calib_type, int step, void *info)
{
	sensor_hal_t *const hal = sensor->hal;

	static uint8_t prox_data[3];
	uint8_t read_data[3];

	/* Validate the specified calibration type */
	if (calib_type != MANUAL_CALIBRATE) {
		sensor->err = SENSOR_ERR_PARAMS;
		return false;
	}

	/* Read proximity sensor for individual channel based on step number. */
	switch (step) {
	case 1:
		prox_data[0] = sensor_bus_get(hal, SFH7770_PS_DATA_LED1);
		break;

	case 2:
		prox_data[1] = sensor_bus_get(hal, SFH7770_PS_DATA_LED2);
		break;

	case 3:
		prox_data[2] = sensor_bus_get(hal, SFH7770_PS_DATA_LED3);

		/* Write data */
		nvram_write((SFH7770_NVRAM_OFFSET), prox_data,
				sizeof(prox_data));

		/* Read back data and confirm it was written correctly */
		nvram_read(SFH7770_NVRAM_OFFSET, read_data, sizeof(read_data));

		if (memcmp(prox_data, read_data, sizeof(prox_data))) {
			sensor->err = SENSOR_ERR_IO;
			return false;
		}

		/* Apply stored proximity thresholds from nvram */
		sensor_bus_write(hal, (SFH7770_PS_THR_LED1), read_data,
				sizeof(read_data));

		break;

	/* Any other step number is invalid */
	default:
		sensor->err = SENSOR_ERR_PARAMS;
		return false;
	}

	return true;
}
Beispiel #5
0
/**
 * @brief Read BMA250 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 bma250_device_id(sensor_hal_t *hal, sensor_data_t *data)
{
	data->device.id = sensor_bus_get(hal, BMA250_CHIP_ID);
	data->device.version = 0;

	return (STATUS_OK == hal->bus.status);
}
Beispiel #6
0
/**
 * @brief Read gyroscope device ID
 *
 * This function reads the gyroscope hardware identification registers
 * and returns these values to the addresses specified in the function
 * parameters.
 *
 * @param sensor    Address of an initialized sensor device 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 imu3000_device_id(sensor_hal_t *hal, sensor_data_t *data)
{
	data->device.id = sensor_bus_get(hal, IMU3000_WHO_AM_I);
	data->device.version = 0;

	return true;
}
/**
 * @brief Read gyroscope device ID
 *
 * This function reads the gyroscope hardware identification registers
 * and returns these values to the addresses specified in the function
 * parameters.
 *
 * @param sensor    Address of an initialized sensor device 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 itg3200_device_id(sensor_hal_t *hal, sensor_data_t *data)
{
	data->device.id = sensor_bus_get(hal, ITG3200_WHOAMI);
	data->device.version = 0;

	return true;
}
Beispiel #8
0
/**
 * @brief Set proximity LED current level
 *
 * @param hal         Address of an initialized sensor hardware descriptor.
 * @param channel     Channel (LED) number to set current
 * @param curr_levels Address of an array of current levels (1 per LED)
 * @return bool     true if the call succeeds, else false is returned.
 */
static bool sfh7770_set_current(sensor_hal_t *hal, int16_t channel,
		uint16_t *level_mA)
{
	uint8_t curr_setting;

	bool status = false;

	/* Find current level in table */
	for (int i = 0; i < NUM_CURRENT_LEVELS; ++i) {
		if (current_table[i].level == *level_mA) {
			curr_setting = current_table[i].field_val;
			status = true;
			break;
		}
	}

	if (status == true) {   /* if entry was found in table */
		uint8_t reg_val;

		if (channel == SENSOR_CHANNEL_ALL) {
			reg_val = sensor_bus_get(hal, SFH7770_I_LED_1_2);
			reg_val &= ~(I_LED1_MASK | I_LED2_MASK);
			reg_val
				|= (curr_setting |
					(curr_setting << I_LED2_SHIFT));
			sensor_bus_put(hal, SFH7770_I_LED_1_2, reg_val);
			sensor_bus_put(hal, SFH7770_I_LED_3, curr_setting);
		} else if ((channel == 1) || (channel == 2)) {
			reg_val = sensor_bus_get(hal, SFH7770_I_LED_1_2);
			if (channel == 1) {
				reg_val &= ~I_LED1_MASK;
				reg_val |= curr_setting;
			} else {
				reg_val &= ~I_LED2_MASK;
				reg_val |= (curr_setting << I_LED2_SHIFT);
			}

			sensor_bus_put(hal, SFH7770_I_LED_1_2, reg_val);
		} else if (channel == 3) {
			sensor_bus_put(hal, SFH7770_I_LED_3, curr_setting);
		} else {        /* invalid channel selected */
			status = false;
		}
	}

	return status;
}
Beispiel #9
0
/**
 * @brief Analog Devices ADXL345Z accelerometer driver initialization.
 *
 * This is the main initialization function for the ADXL345Z device.
 *
 * @param sensor    Address of a sensor device descriptor.
 * @param reserved  Reserved value.
 *
 * @return bool     true if the call succeeds, else false is returned.
 */
bool adxl345z_init(sensor_t *sensor, int reserved)
{
    bool status = false;
    sensor_hal_t *const hal = sensor->hal;

    if (0xe5 == sensor_bus_get(hal, ADXL345Z_DEVID)) {
        /* Set the driver function table and capabilities pointer. */
        static const sensor_device_t adxl345z_device = {
            .func.read        = adxl345z_read,
            .func.ioctl       = adxl345z_ioctl,
            .func.selftest    = adxl345_selftest,
            .func.event       = adxl345_event,

            .caps.feature     = SENSOR_CAPS_3_AXIS    |
            SENSOR_CAPS_SELFTEST  |
            SENSOR_CAPS_TAP_EVENT |
            SENSOR_CAPS_DROP_EVENT,

            .caps.vendor      = SENSOR_VENDOR_ADI,
            .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 = "ADXL345Z Digital, triaxial acceleration sensor"
        };

        sensor->drv = &adxl345z_device;

        /* Set the driver (device) default range, bandwidth, &
         * resolution.
         * Per the ADXL345Z Datasheet the default range and bandwidth
         * after device reset are +/- 2g and 100Hz respectively.
         */
        hal->range      = 2000;
        hal->bandwidth  = 100;
        hal->resolution = 10;
        hal->burst_addr = ADXL345Z_DATAX0;

        /* After power is applied the device enters standby mode, where
         * power consumption is minimized and the device waits for the
         * command to enter measurement mode. While in standby mode, any
         * register can be read or written to configure the part.
         * Configure the part in standby mode prior to enabling
         * measurement mode.
         */
        sensor_reg_bitset(hal, ADXL345Z_POWER_CTL, POWER_CTL_MEASURE);

        /* Install an interrupt handler. */
        if ((STATUS_OK == hal->bus.status) &&
                sensor_irq_connect(hal->mcu_sigint,
                                   adxl345z_isr, hal)) {
            status = true;
        }
    }

    return status;
}
Beispiel #10
0
/**
 * @brief Set the BMA180 ADC output data bandwidth
 *
 * @param hal      Address of an initialized sensor hardware descriptor.
 * @param band     The index of a driver-specific bandwidth table entry.
 * @return bool     true if the call succeeds, else false is returned.
 */
static bool bma180_set_bandwidth(sensor_hal_t *hal, int16_t band)
{
	/* Set the device sample frequency. */
	uint8_t const ctrl_bw = ~(BW)&sensor_bus_get(hal, BMA180_BW_TCS);

	sensor_bus_put
		(hal, BMA180_BW_TCS, ctrl_bw | band_table[band].reserved_val);

	return true;
}
/**
 * @brief  Set the sample bandwidth for the magnetometer
 *
 * @param hal      Address of an initialized sensor hardware descriptor.
 * @param band     The index of a driver-specific bandwidth table entry.
 * @return bool     true if the call succeeds, else false is returned.
 */
static bool hmc5883l_set_bandwidth(sensor_hal_t *hal, int16_t bw)
{
	uint8_t reg_val = sensor_bus_get(hal, HMC5883L_CONFIG_REG_A);

	reg_val &= ~(DATA_RATE); /* clear data rate select bits */

	sensor_bus_put(hal, HMC5883L_CONFIG_REG_A,
			reg_val | band_table[bw].reserved_val);

	return true;
}
Beispiel #12
0
/**
 * @brief Set the BMA150 ADC output data bandwidth
 *
 * @param hal      Address of an initialized sensor hardware descriptor.
 * @param band     The index of a driver-specific bandwidth table entry.
 * @return bool    true if the call succeeds, else false is returned.
 */
static bool bma150_set_bandwidth(sensor_hal_t *hal, int16_t band)
{
	/* Set the device sample frequency. */
	uint8_t const ctrl4 = ~(CTRL4_BANDWIDTH)&
			sensor_bus_get(hal, BMA150_CTRL4);

	sensor_bus_put(hal, BMA150_CTRL4, ctrl4 |
			band_table[band].reserved_val);

	return true;
}
Beispiel #13
0
/**
 * @brief InvenSense ITG-3200 gyroscope driver defaults.
 *
 * This is a convenience routine for setting the default device configuration
 * during initialization or after reset.
 *
 * @param hal       Address of an initialized sensor hardware descriptor.
 * @return bool     true if the sensor is ready for use, else false.
 */
static inline bool itg3200_default_init(sensor_hal_t *hal)
{
	bool status = false;

	/* Assuming the device is on an I2C bus, the device address and ID
	 * are one and the same.  Per the vendor data sheet, AD0 in the
	 * WHO_AM_I (device ID) register is software configurable s.t. two
	 * devices can be installed on the sensor bus.  The undefined AD0
	 * bit is set to zero to select the 110 1000 (AD0=0) address.
	 *
	 * Set the bus address here then verify the setting.
	 */
	sensor_bus_put(hal, ITG3200_WHOAMI, ITG3200_ID_VAL);

	if (ITG3200_ID_VAL == sensor_bus_get(hal, ITG3200_WHOAMI)) {
		/* Reset the motion processing unit to a known state then enable
		 * the gyroscope using the X-axis for clock.
		 */
		sensor_bus_put(hal, ITG3200_PWR_MGM, PWR_MGM_H_RESET);
		sensor_bus_put(hal, ITG3200_WHOAMI, ITG3200_ID_VAL);
		sensor_bus_put(hal, ITG3200_PWR_MGM, PWR_MGM_CLK_SEL_Z);

		/* Set the sample rate divider, digital low-pass filter, and
		 * full-scale range (fixed @ +/-2000 deg/sec).
		 *
		 * The digital low-pass filter also determines the internal
		 * sample rate used by the device.  The 256 Hz. and 2.1 kHz
		 * filter bandwidths result in an 8 kHz. internal sample rate, while
		 * all other settings result in a 1 kHz. internal sample rate.
		 *
		 * This internal sample rate is then further scaled by the
		 * sample rate divider (SMPLRT_DIV) value to produce the gyro
		 * sample rate  according to the formula:
		 *
		 *          F_sample = F_internal / (divider + 1)
		 *
		 * On reset the FS_SEL field is 00h and must be set to the
		 * full-scale range setting of 03h (+/-2000 deg/sec) for proper
		 * operation.
		 */
		uint8_t const dlpf_fs = FS_SEL_2000 | DLPF_CFG_42HZ;

		sensor_bus_put(hal, ITG3200_SMPLRT_DIV, 9); /* 100Hz sample rate
		                                             **/
		sensor_bus_put(hal, ITG3200_DLPF_FS, dlpf_fs);

		if (STATUS_OK == hal->bus.status) {
			status = true;
		}
	}

	return status;
}
Beispiel #14
0
/**
 * @brief Read BMA250 temperature data.
 *
 * This function reads temperature data, where center temperature 24 C
 * corresponds to a value 0x00 read from the temperature register with
 * temperature slope 0.5 C/LSB.
 *
 * @param hal       Address of an initialized sensor hardware descriptor.
 * @param data      The address where temperature samples are returned.
 * @return bool     true if the call succeeds, else false is returned.
 */
static bool bma250_get_temperature(sensor_hal_t *hal, sensor_data_t *data)
{
	int8_t const temp_data = (int8_t)sensor_bus_get(hal, BMA250_TEMP);

	if (data->scaled) {
		data->temperature.value = BMA250_TEMP_OFFSET + (temp_data / 2);
	} else {
		data->temperature.value = temp_data;
	}

	return (STATUS_OK == hal->bus.status);
}
Beispiel #15
0
/**
 * @brief Get event threshold value
 *
 * @param hal       Address of an initialized sensor hardware descriptor.
 * @param threshold Address of threshold descriptor.
 * @return bool     true if the call succeeds, else false is returned.
 */
static bool bma250_get_threshold
	(sensor_hal_t *hal, sensor_threshold_desc_t *threshold)
{
	switch (threshold->type) {
	/* Invalid/unsupported threshold type - do nothing, return false */
	default:
		return false;

	/* any-motion threshold */
	case SENSOR_THRESHOLD_MOTION:
	case SENSOR_THRESHOLD_TILT:
		threshold->value = raw_to_scaled(hal,
				sensor_bus_get(hal, BMA250_SLOPE_THRESHOLD));
		break;

	/* tap/double-tap threshold */
	case SENSOR_THRESHOLD_TAP:
	{
		uint8_t const mask = BMA250_TAP_TH_FIELD;
		threshold->value = raw_to_scaled(hal,
				sensor_reg_fieldget(hal, BMA250_TAP_CONFIG,
				mask));
	}
	break;

	/* low-G threshold */
	case SENSOR_THRESHOLD_LOW_G:
		threshold->value = raw_to_scaled(hal,
				sensor_bus_get(hal, BMA250_LOW_G_THRESHOLD));
		break;

	/* high-G threshold */
	case SENSOR_THRESHOLD_HIGH_G:
		threshold->value = raw_to_scaled(hal,
				sensor_bus_get(hal, BMA250_HIGH_G_THRESHOLD));
		break;
	}

	return true;
}
Beispiel #16
0
/**
 * @brief Set the IMU-3000 full scale range.
 *
 * This routine sets the IMU-3000 full scale range using an index to
 * a table of valid ranges:  +/-250, +/-500, +/-1000, and +/-2000 deg/sec.
 *
 * @param hal       Address of an initialized sensor device descriptor.
 * @param range     The index o a driver-specific range table entry.
 * @return bool     true if the call succeeds, else false is returned.
 */
static bool imu3000_set_range(sensor_hal_t *hal, int16_t range)
{
	sensor_fs_sel = range;

	/* Set the device full scale range. */
	uint8_t const dlpf_fs = (~FS_SEL_FIELD) &
			sensor_bus_get(hal, IMU3000_DLPF_FS);

	sensor_bus_put(hal, IMU3000_DLPF_FS,
			dlpf_fs | range_table [sensor_fs_sel].reserved_val);

	return true;
}
Beispiel #17
0
/**
 * @brief Set the IMU-3000 low-pass filter bandwidth.
 *
 * This routine sets the IMU-3000 low-pass filter bandwidth and the
 * internal sample rate used by the device.  This internal sample rate is
 * then further scaled by the sample rate divider (SMPLRT_DIV) value to
 * produce the gyro sample rate according to the formula:
 *
 *          F_sample = F_internal / (divider + 1)
 *
 * Valid filter bandwidths and the associated internal sample rate are
 * as follows:
 *
 * @code
 *          Low Pass Filter Bandwidth       Internal Sample Rate
 *          ____________________________________________________
 *              256Hz                           8kHz
 *              188Hz                           1kHz
 *              98Hz                            1kHz
 *              42Hz                            1kHz
 *              20Hz                            1kHz
 *              10Hz                            1kHz
 *              5Hz                             1kHz
 * @endcode
 *
 * @param hal       Address of an initialized sensor device descriptor.
 * @param band      The index of a driver-specific bandwidth table entry.
 * @return bool     true if the call succeeds, else false is returned.
 */
static bool imu3000_set_bandwidth(sensor_hal_t *hal, int16_t band)
{
	sensor_dlpf_cfg = band;

	/* Set the device low-pass filter frequency. */
	uint8_t const dlpf_fs = (~DLPF_CFG_FIELD) &
			sensor_bus_get(hal, IMU3000_DLPF_FS);

	sensor_bus_put(hal, IMU3000_DLPF_FS,
			dlpf_fs | band_table [sensor_dlpf_cfg].reserved_val);

	return true;
}
Beispiel #18
0
/**
 * @brief Set the BMA150 full scale acceleration range.
 *
 * @param hal       Address of an initialized sensor hardware descriptor.
 * @param range     The index o a driver-specific range table entry.
 * @return bool     true if the call succeeds, else false is returned.
 */
static bool bma150_set_range(sensor_hal_t *hal, int16_t range)
{
	/*
	 * After changing the full scale range it takes (1/(2 * bandwidth))
	 * to overwrite the data registers with filtered data according to
	 * the selected bandwidth.
	 */
	uint8_t const ctrl4 = ~(CTRL4_RANGE)&sensor_bus_get(hal, BMA150_CTRL4);
	sensor_bus_put(hal, BMA150_CTRL4,
			ctrl4 | range_table[range].reserved_val);

	return true;
}
Beispiel #19
0
/**
 * @brief Get a BMA220 event threshold value
 *
 * @param hal       Address of an initialized sensor hardware descriptor.
 * @param threshold Address of threshold descriptor.
 * @return bool     true if the call succeeds, else false is returned.
 */
static bool bma220_get_threshold
	(sensor_hal_t *hal, sensor_threshold_desc_t *threshold)
{
	uint32_t val;

	switch (threshold->type) {
	/* Invalid/unsupported threshold type */
	default:
		return false;

	/* any-motion threshold */
	case SENSOR_THRESHOLD_MOTION:
	case SENSOR_THRESHOLD_TILT:
		val = sensor_bus_get(hal, REG_ADDR(BMA220_SLOPE_CONFIG));
		threshold->value = (int16_t)((val * hal->range * 16) / 2000);
		break;

	/* tap/double-tap threshold */
	case SENSOR_THRESHOLD_TAP:
		val = sensor_bus_get(hal, REG_ADDR(SENSOR_THRESHOLD_TAP));
		threshold->value = (int16_t)((val * hal->range) / 256);
		break;

	/* low-G threshold */
	case SENSOR_THRESHOLD_LOW_G:
		val = sensor_bus_get(hal, REG_ADDR(BMA220_HG_LG_THRESHOLD));
		threshold->value = (int16_t)((val * hal->range) / 256);
		break;

	/* high-G threshold */
	case SENSOR_THRESHOLD_HIGH_G:
		val = sensor_bus_get(hal, REG_ADDR(BMA220_HG_LG_THRESHOLD));
		threshold->value = (int16_t)((val * hal->range) / 256);
		break;
	}

	return true;
}
Beispiel #20
0
/**
 * @brief Read BMA150 integrated temperature sensor data.
 *
 * @param sensor    Address of an initialized sensor device descriptor.
 * @param data      The address where temperature samples are returned.
 * @return bool     true if the call succeeds, else false is returned.
 */
static bool bma150_get_temperature(sensor_hal_t *hal, sensor_data_t *data)
{
	int8_t temp_data = (int8_t)sensor_bus_get(hal, BMA150_TEMP);

	if (data->scaled) {
		/*
		 * Per the Bosch BMA150 datasheet, temperature data resolution
		 * is about 0.5 C/LSB.
		 */
		data->temperature.value = BMA150_TEMP_OFFSET + (temp_data / 2);
	} else {
		data->temperature.value = temp_data;
	}

	return (STATUS_OK == hal->bus.status);
}
Beispiel #21
0
/**
 * @brief Read BMA180 integrated temperature sensor data.
 *
 * @param hal       Address of an initialized sensor hardware descriptor.
 * @param data      The address where temperature samples are returned.
 * @return bool     true if the call succeeds, else false is returned.
 */
static bool bma180_get_temperature(sensor_hal_t *hal, sensor_data_t *data)
{
	int8_t temp_data = (int8_t)sensor_bus_get(hal, BMA180_TEMP);

	if (data->scaled) {
		/* \todo
		 *
		 * Review and verify this temperature compensation w.r.t. the
		 * setting for the OFFSET_T register in particular.
		 *
		 * Also verify the scaled resolution per the Bosch datasheet;
		 * is the temperature data resolution is 0.5 C/LSB or 0.5 K/LSB?
		 */
		data->temperature.value = BMA180_TEMP_OFFSET + (temp_data / 2);
	} else {
		data->temperature.value = temp_data;
	}

	return (STATUS_OK == hal->bus.status);
}
Beispiel #22
0
/**
 * @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;
}
Beispiel #23
0
/**
 * @brief Get event threshold value
 *
 * @param hal       Address of an initialized sensor hardware descriptor.
 * @param channel   Channel (LED) number to set threshold
 * @param threshold Address of threshold descriptor.
 * @return bool     true if the call succeeds, else false is returned.
 */
static bool sfh7770_get_threshold(sensor_hal_t *hal, int16_t channel,
		sensor_threshold_desc_t *threshold)
{
	bool result = false;

	switch (threshold->type) {  /* check threshold type */
	case SENSOR_THRESHOLD_NEAR_PROXIMITY: /* proximity threshold */
		if (channel == SENSOR_CHANNEL_ALL) {
			/* if "all channels", just use chan #1 value */
			channel = 1;
		}

		if ((channel >= 1) && (channel <= 3)) {
			/* Read corresponding register for LED channel */
			threshold->value = (uint16_t)sensor_bus_get(hal,
					(SFH7770_PS_THR_LED1 + channel - 1));
			result = true;
		}

		break;

	case SENSOR_THRESHOLD_LOW_LIGHT:  /* low light level threshold */
		threshold->value = low_light_threshold;
		result = true;
		break;

	case SENSOR_THRESHOLD_HIGH_LIGHT: /* high light level threshold */
		threshold->value = high_light_threshold;
		result = true;
		break;

	default:
		/* Invalid/unsupported threshold type - do nothing, return false */
		break;
	}

	return result;
}
Beispiel #24
0
/**
 * @brief Osram SFH7770 light & proximity sensor driver initialization.
 *
 * This is the main initialization function for the SFH7770 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 sfh7770_init(sensor_t *sensor, int resvd)
{
	bool status = false;
	sensor_hal_t *const hal = sensor->hal;

	/* Proximity threshold values from NVRAM */
	struct {
		uint8_t ps_thr_led1;
		uint8_t ps_thr_led2;
		uint8_t ps_thr_led3;
	} prox_thresholds;

	/* Read and check part ID register */
	uint8_t part_id = sensor_bus_get(hal, SFH7770_PART_ID);

	if (part_id == (SFH7770_PART_ID_VAL | SFH7770_PART_REV_VAL)) {
		/* Set the driver function table and capabilities pointer. */
		static const sensor_device_t sfh7770_device = {
			.func.read           = sfh7770_read,
			.func.ioctl          = sfh7770_ioctl,
			.func.calibrate      = sfh7770_calibrate,
			.func.event          = sfh7770_event,
#if 0
			.caps.feature        = XXX
#endif
			.caps.vendor         = SENSOR_VENDOR_OSRAM,
			.caps.units          = SENSOR_UNITS_lux,
			.caps.scale          = SENSOR_SCALE_one,
			.caps.name = "SFH7770 Ambient Light & Proximity Sensor"
		};

		sensor->drv = &sfh7770_device;

		hal->resolution = SFH7770_DATA_RESOLUTION;

		/* Set the device burst read starting register address. */
		hal->burst_addr = SFH7770_ALS_DATA_LSB;

		/* Reset device during first init call */
		if (!sfh7770_initialized) {
			sensor_bus_put(hal, SFH7770_ALS_CONTROL,
					ALS_CONTROL_SW_RESET);
		}

		/* Init light sensor functions if specified */

		if (sensor->type & SENSOR_TYPE_LIGHT) {
			/* Set light sensor mode & interval */

			sensor_bus_put(hal, SFH7770_ALS_CONTROL,
					ALS_MODE_FREE_RUNNING);
			sensor_bus_put(hal, SFH7770_ALS_INTERVAL,
					ALS_INTERVAL_500MS);
		}

		/* Init proximity sensor functions if specified */
		if (sensor->type & SENSOR_TYPE_PROXIMITY) {
			/* Set proximity sensor mode & interval */
			sensor_bus_put(hal, SFH7770_PS_CONTROL,
					PS_MODE_FREE_RUNNING);
			sensor_bus_put(hal, SFH7770_PS_INTERVAL,
					PS_INTERVAL_100MS);

			/* Specify which LEDs are active */
			uint8_t const active_leds = LED_ACTIVE_ALL;
			/* XXX one of: */
			/* XXX  LED_ACTIVE_1    - LED1 only (default) */
			/* XXX  LED_ACTIVE_1_2  - LED1 & LED2 */
			/* XXX  LED_ACTIVE_1_3  - LED1 & LED3 */
			/* XXX  LED_ACTIVE_ALL  - all LEDs */

			/* Set LED current levels */
			uint8_t const led1_curr = I_LED_50MA; /* LED1 current */
			uint8_t const led2_curr = I_LED_50MA; /* LED2 current */
			uint8_t const led3_curr = I_LED_50MA; /* LED3 current */

			sensor_bus_put(hal, SFH7770_I_LED_1_2,
					(active_leds |
					(led2_curr <<
					I_LED2_SHIFT) | led1_curr));

			sensor_bus_put(hal, SFH7770_I_LED_3, led3_curr);

			/* Apply stored proximity thresholds from nvram */
			nvram_read(SFH7770_NVRAM_OFFSET, &prox_thresholds,
					sizeof(prox_thresholds));

			sensor_bus_write(hal, (SFH7770_PS_THR_LED1),
					&prox_thresholds,
					sizeof(prox_thresholds));
		}

		if (!sfh7770_initialized) {
			/* Set interrupt output polarity & mode(active-low,
			 * latched).
			 */
			sensor_bus_put(hal, SFH7770_INT_SET, 0);

			/* Set up interrupt handler */
			if (STATUS_OK == hal->bus.status) {
				sensor_irq_connect(hal->mcu_sigint, sfh7770_isr, hal);
			}
		}

		sfh7770_initialized = true;
		status = true;
	}

	return status;
}

/**
 * @brief Osram SFH7770 driver interrupt service routine.
 *
 * This is the common interrupt service routine for all enabled SFH7770
 * interrupt events.  Three different types of interrupts can be programmed:
 * high light level, low light level, and near proximity.  All share the
 * same interrupt pin and therefore the same ISR entry.
 *
 * @param arg       The address of the driver sensor_hal_t descriptor.
 * @return Nothing.
 */
static void sfh7770_isr(volatile void *arg)
{
	sensor_hal_t *const hal = (sensor_hal_t *)arg;

	struct {                    /* Interrupt register data */
		uint8_t als_data_lsb;   /* light meas data - least signif byte */
		uint8_t als_data_msb;   /* light meas data - most signif byte */
		uint8_t als_ps_status;  /* light & prox sensor status */
		uint8_t ps_data_led1;   /* proximity meas data - LED 1 */
		uint8_t ps_data_led2;   /* proximity meas data - LED 2 */
		uint8_t ps_data_led3;   /* proximity meas data - LED 3 */
		uint8_t int_set;        /* interrupt status */
	}
	regs;

	/* Do not wait for a busy bus when reading data. */
	hal->bus.no_wait = true;
	sensor_bus_read(hal, hal->burst_addr, (uint8_t *)&regs, sizeof(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_UNKNOWN;

		/*
		 * Determine the interrupt source then combine measurement
		 * register values into a single 16-bit measurement value.
		 */
		uint8_t const int_source = (regs.int_set & INT_SOURCE_MASK);

		uint16_t const light_level
			= ((regs.als_data_msb << 8) | regs.als_data_lsb);

		switch (int_source) {
		case INT_SOURCE_ALS:

			/* Determine if low or high light interrupt */
			if (light_level >= high_light_threshold) {
				event_data.event = SENSOR_EVENT_HIGH_LIGHT;
				event_data.data.light.value = light_level;

				(event_cb[2].handler)(&event_data,
						event_cb[2].arg);
			} else if (light_level <= low_light_threshold) {
				event_data.event = SENSOR_EVENT_LOW_LIGHT;
				event_data.data.light.value = light_level;

				(event_cb[1].handler)(&event_data,
						event_cb[1].arg);
			}

			return;

		case INT_SOURCE_LED1:
		case INT_SOURCE_LED2:
		case INT_SOURCE_LED3:

			event_data.event = SENSOR_EVENT_NEAR_PROXIMITY;

			if (int_source == INT_SOURCE_LED1) {
				event_data.channel = 1;
			} else if (int_source == INT_SOURCE_LED2) {
				event_data.channel = 2;
			} else { /* INT_SOURCE_LED3 */
				event_data.channel = 3;
			}

			/* Use internal device threshold status to
			 * determine scaled values.
			 */
			event_data.data.proximity.value[0]
				= (regs.als_ps_status & PS_LED1_THRESH) ?
					PROXIMITY_NEAR : PROXIMITY_NONE;

			event_data.data.proximity.value[1]
				= (regs.als_ps_status & PS_LED2_THRESH) ?
					PROXIMITY_NEAR : PROXIMITY_NONE;

			event_data.data.proximity.value[2]
				= (regs.als_ps_status & PS_LED3_THRESH) ?
					PROXIMITY_NEAR : PROXIMITY_NONE;

			(event_cb[0].handler)(&event_data, event_cb[0].arg);
		}
	}
}

/**
 * @brief Read SFH7770 device ID and revision numbers.
 *
 * This function reads the sensor 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 sfh7770_device_id(sensor_hal_t *hal, sensor_data_t *data)
{
	uint8_t const part_id = sensor_bus_get(hal, SFH7770_PART_ID);

	data->device.id = (uint32_t)(part_id & PART_ID_MASK) >> PART_ID_SHIFT;
	data->device.version = (uint32_t)(part_id & PART_REV_MASK);

	return true;
}
Beispiel #25
0
/**
 * @brief Enable or disable BMA150 sensor events.
 *
 * @param  sensor       Address of an initialized sensor device descriptor
 * @param  sensor_event Specifies the sensor event type
 * @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 bma150_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;

	uint8_t ctrl2_value = sensor_bus_get(hal, BMA150_CTRL2);
	uint8_t ctrl5_value = sensor_bus_get(hal, BMA150_CTRL5);

	if (sensor_event & SENSOR_EVENT_NEW_DATA) {
		if (callback) {
			event_cb[0] = *callback;
		}

		if (enable) {
			ctrl5_value |= CTRL5_NEW_DATA_INT;
		} else {
			ctrl5_value &= ~CTRL5_NEW_DATA_INT;
		}

		status = true;
	}

	if (sensor_event & SENSOR_EVENT_MOTION) {
		if (callback) {
			event_cb[1] = *callback;
		}

		if (enable) {
			/* Do not enable both alert & motion. */
			ctrl2_value &= ~CTRL2_ALERT;
			ctrl2_value |= CTRL2_ANY_MOTION;
			ctrl5_value |= CTRL5_ENABLE_ADV_INT;
		} else {
			ctrl2_value &= ~CTRL2_ANY_MOTION;
			ctrl5_value &= ~CTRL5_ENABLE_ADV_INT;
		}

		status = true;
	}

	if (sensor_event & SENSOR_EVENT_LOW_G) {
		if (callback) {
			event_cb[2] = *callback;
		}

		if (enable) {
			ctrl2_value |= CTRL2_ENABLE_LG;
		} else {
			ctrl2_value &= ~CTRL2_ENABLE_LG;
		}

		status = true;
	}

	if (sensor_event & SENSOR_EVENT_HIGH_G) {
		if (callback) {
			event_cb[3] = *callback;
		}

		if (enable) {
			ctrl2_value |= CTRL2_ENABLE_HG;
		} else {
			ctrl2_value &= ~CTRL2_ENABLE_HG;
		}

		status = true;
	}

	sensor_bus_put(hal, BMA150_CTRL2, ctrl2_value);
	sensor_bus_put(hal, BMA150_CTRL5, ctrl5_value);

	return status;
}
Beispiel #26
0
/**
 * @brief InvenSense IMU-3000 gyroscope driver defaults.
 *
 * This is a convenience routine for setting the default device configuration
 * during initialization or after reset.
 *
 * @return bool     true if the sensor is ready for use, else false.
 */
static bool imu3000_default_init(sensor_hal_t *hal, sensor_hal_t *aux)
{
	bool status = false;

	/* Assuming the device is on an I2C bus, the device address and ID
	 * are one and the same.  Per the vendor data sheet, AD0 in the
	 * WHO_AM_I (device ID) register is software configurable s.t. two
	 * devices can be installed on the sensor bus.  The undefined AD0
	 * bit is set to zero to select the 110 1000 (AD0=0) address.
	 *
	 * Set the bus address here then verify the setting.
	 */
	sensor_bus_put(hal, IMU3000_WHO_AM_I, IMU3000_ID_VAL);

	if (IMU3000_ID_VAL == sensor_bus_get(hal, IMU3000_WHO_AM_I)) {
		/* Reset the motion processing unit to a known state then enable
		 * the gyroscope using the Z-axis for clock.
		 */
		sensor_bus_put(hal, IMU3000_PWR_MGM, PWR_MGM_H_RESET);
		sensor_bus_put(hal, IMU3000_WHO_AM_I, IMU3000_ID_VAL);
		sensor_bus_put(hal, IMU3000_PWR_MGM, PWR_MGM_CLK_SEL_Z);

		/* \todo Define a method to support I2C master mode.
		 *
		 * Determine whether it is reasonable to use the
		 * "sensor_desc.aux" field to support an external 3-axis accelerometer
		 * configured as an auxiliary device. For example, assume a user
		 * selects this as a build-time configuration option and the "aux"
		 * field points to a sensor_hal_t type describing the accelerometer.
		 */
		if (aux) {
			/* Configure and enable the IMU-3000 auxiliary device
			 * interface, including bus and burst read addresses.
			 */
			sensor_bus_put(hal, IMU3000_AUX_SLV_ADDR,
					AUX_ADDR_CLKOUTEN | aux->bus.addr);

			sensor_bus_put(hal, IMU3000_AUX_BURST_ADDR,
					aux->burst_addr);

			/* Enable the IMU as master to accelerometer (aux)
			 * interface via secondary I2C bus. For an external
			 * processor to communicate directly to an external accelerometer
			 * the AUX_IF_EN bit should be cleared and AUX_IF_RST bit
			 * should be set. The configuration below turns the accelerometer
			 * into a slave device that's not addressed by a separate
			 * sensor_t descriptor and API routines.
			 */
			sensor_bus_put(hal, IMU3000_USER_CTRL,
					USER_CTRL_AUX_IF_RST |
					USER_CTRL_AUX_IF_EN);
		} else {
			/* Reset the auxiliary interface in pass-through mode
			 * s.t. the external processor can communicate directly with
			 * an external accelerometer.
			 */
			sensor_bus_put(hal, IMU3000_USER_CTRL,
					USER_CTRL_AUX_IF_RST);
		}

		/* \todo Define a method to dynamically compute DC bias.
		 *
		 * The gyro signed offset registers remove DC bias from the
		 * sensor outputs by subtracting the offset values from gyro sensor
		 * values prior to moving sensor data to output registers. The
		 * device is initialized s.t. DC bias offsets are not applied to
		 * sensor data.
		 */
		const uint16_t *const gyro_offsets = (uint16_t [3]) {0};

		sensor_bus_write(hal, IMU3000_X_OFFS_USRH,
				gyro_offsets, 3 * sizeof(uint16_t));

		/* Set the sample rate divider, digital low-pass filter, and
		 * full-scale range.
		 *
		 * The digital low-pass filter also determines the internal
		 * sample rate used by the device.  The 256 Hz. and 2.1 kHz
		 * filter bandwidths result in an 8 kHz. internal sample rate, while
		 * all other settings result in a 1 kHz. internal sample rate.
		 *
		 * This internal sample rate is then further scaled by the
		 * sample rate divider (SMPLRT_DIV) value to produce the gyro
		 * sample rate according to the formula:
		 *
		 *          F_sample = F_internal / (divider + 1)
		 */
		uint8_t const dlpf_fs
			= range_table[sensor_fs_sel].reserved_val |
				band_table[sensor_dlpf_cfg].reserved_val;

		sensor_bus_put(hal, IMU3000_SMPLRT_DIV, 9);
		sensor_bus_put(hal, IMU3000_DLPF_FS, dlpf_fs);
	}

	if (STATUS_OK == hal->bus.status) {
		status = true;
	}

	return status;
}
Beispiel #27
0
/**
 * @brief Enable or disable BMA250 sensor events.
 *
 * @param  sensor       Address of an initialized sensor device descriptor
 * @param  sensor_event Specifies the sensor event type
 * @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 bma250_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;

	uint8_t int_enable1 = sensor_bus_get(hal, BMA250_16_INTR_EN);
	uint8_t int_enable2 = sensor_bus_get(hal, BMA250_17_INTR_EN);

	if (sensor_event & SENSOR_EVENT_NEW_DATA) {
		if (callback) {
			event_cb[0] = *callback;
		}

		if (enable) {
			int_enable2 |=  BMA250_DATA_EN;
		} else {
			int_enable2 &= ~BMA250_DATA_EN;
		}

		status = true;
	}

	if (sensor_event & SENSOR_EVENT_MOTION) {
		if (callback) {
			event_cb[1] = *callback;
		}

		if (enable) {
			/* Enable slope detection on x, y, and z axes using the
			 * default settings for the slope threshold & duration.
			 */
			int_enable1 |=  (BMA250_SLOPE_EN_Z | BMA250_SLOPE_EN_Y |
					BMA250_SLOPE_EN_X);
		} else {
			int_enable1 &= ~(BMA250_SLOPE_EN_Z | BMA250_SLOPE_EN_Y |
					BMA250_SLOPE_EN_X);
		}

		status = true;
	}

	if (sensor_event & SENSOR_EVENT_LOW_G) {
		if (callback) {
			event_cb[2] = *callback;
		}

		if (enable) {
			int_enable2 |=  BMA250_LOW_EN;
		} else {
			int_enable2 &= ~BMA250_LOW_EN;
		}

		status = true;
	}

	if (sensor_event & SENSOR_EVENT_HIGH_G) {
		if (callback) {
			event_cb[3] = *callback;
		}

		if (enable) {
			/* Enable high-g detection on x, y, and z axes using the
			 * default settings for the high-g duration & hysteresis.
			 */
			int_enable2 |=  (BMA250_HIGH_EN_Z | BMA250_HIGH_EN_Y |
					BMA250_HIGH_EN_X);
		} else {
			int_enable2 &= ~(BMA250_HIGH_EN_Z | BMA250_HIGH_EN_Y |
					BMA250_HIGH_EN_X);
		}

		status = true;
	}

	if (sensor_event & SENSOR_EVENT_TAP) {
		if (callback) {
			event_cb[4] = *callback;
		}

		if (enable) {
			int_enable1 |=  (BMA250_S_TAP_EN | BMA250_D_TAP_EN);
		} else {
			int_enable1 &= ~(BMA250_S_TAP_EN | BMA250_D_TAP_EN);
		}

		status = true;
	}

	sensor_bus_put(hal, BMA250_16_INTR_EN, int_enable1);
	sensor_bus_put(hal, BMA250_17_INTR_EN, int_enable2);

	return status;
}
Beispiel #28
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;
}
Beispiel #29
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);
		}
	}
}
Beispiel #30
0
/**
 * @brief Bosch BMA180 accelerometer driver initialization.
 *
 * This is the main initialization function for the BMA180 device.
 * The accelerometer range and bandwidth are set based on user-specified
 * values from the system configuration.
 *
 * @param sensor    Address of a sensor device descriptor.
 * @param resvd     Reserved value.
 * @return bool     true if the call succeeds, else false is returned.
 */
bool bma180_init(sensor_t *sensor, int resvd)
{
	bool status = false;

	sensor_hal_t *const hal = sensor->hal;

	if (BMA180_ID_VAL == sensor_bus_get(hal, BMA180_CHIP_ID)) {
		/* Set the driver function table and capabilities pointer. */
		static const sensor_device_t bma180_device = {
			.func.read        = bma180_read,
			.func.ioctl       = bma180_ioctl,

			.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 = "BMA180 Digital, triaxial acceleration sensor"
		};

		sensor->drv = &bma180_device;

		if (STATUS_OK == hal->bus.status) {
			/* Set the driver (device) default range, bandwidth, &
			 * resolution.
			 */
			hal->range      = 1000; /* milli-g */
			hal->bandwidth  = 10;   /* Hertz */
			hal->resolution = BMA180_DATA_RESOLUTION;

			bma180_set_range(hal, 0);
			bma180_set_bandwidth(hal, 0);

			/* Set the device burst read base address. */
			hal->burst_addr = BMA180_ACC_X_LSB;

			status = (STATUS_OK == hal->bus.status);
		}
	}

	return status;
}

/**
 * @brief Read BMA180 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 bma180_device_id(sensor_hal_t *hal, sensor_data_t *data)
{
	data->device.id = sensor_bus_get(hal, BMA180_CHIP_ID);
	data->device.version = sensor_bus_get(hal, BMA180_CHIP_VERSION);

	return true;
}