1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-17 05:32:45 +01:00

drivers: add driver for FXOS8700 3-axis accelerometer/magnetometer

This commit is contained in:
Hyungsin 2018-04-18 14:44:50 -07:00
parent 689333ff04
commit beaf08bcb2
13 changed files with 922 additions and 0 deletions

View File

@ -123,6 +123,11 @@ ifneq (,$(filter feetech,$(USEMODULE)))
USEMODULE += uart_half_duplex
endif
ifneq (,$(filter fxos8700,$(USEMODULE)))
USEMODULE += xtimer
FEATURES_REQUIRED += periph_i2c
endif
ifneq (,$(filter grove_ledbar,$(USEMODULE)))
USEMODULE += my9221
endif

View File

@ -70,6 +70,10 @@ ifneq (,$(filter feetech,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/feetech/include
endif
ifneq (,$(filter fxos8700,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/fxos8700/include
endif
ifneq (,$(filter grove_ledbar,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/grove_ledbar/include
endif

View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

235
drivers/fxos8700/fxos8700.c Normal file
View File

@ -0,0 +1,235 @@
/*
* Copyright (C) 2018 UC Berkeley
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @file
* @brief Driver for the FXOS8700 3-axis accelerometer/magnetometer
*
* @author Michael Andersen <m.andersen@cs.berkeley.edu>
* @author Hyung-Sin Kim <hs.kim@cs.berkeleyedu>
*/
#include "periph/i2c.h"
#include "xtimer.h"
#include "fxos8700.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#define I2C_SPEED I2C_SPEED_FAST
#define FXOS8700_FULLDATA_LENGTH (12)
static int fxos8700_read_regs(const fxos8700_t* dev, uint8_t reg, uint8_t* data, size_t len)
{
i2c_acquire(dev->p.i2c);
if (i2c_read_regs(dev->p.i2c, dev->p.addr, reg, (char*) data, len) <= 0) {
DEBUG("[fxos8700] Can't read register 0x%x\n", reg);
i2c_release(dev->p.i2c);
return FXOS8700_BUSERR;
}
i2c_release(dev->p.i2c);
return FXOS8700_OK;
}
static int fxos8700_write_regs(const fxos8700_t* dev, uint8_t reg, uint8_t* data, size_t len)
{
i2c_acquire(dev->p.i2c);
if (i2c_write_regs(dev->p.i2c, dev->p.addr, reg, (char*) data, len) <= 0) {
DEBUG("[fxos8700] Can't write to register 0x%x\n", reg);
i2c_release(dev->p.i2c);
return FXOS8700_BUSERR;
}
i2c_release(dev->p.i2c);
return FXOS8700_OK;
}
int fxos8700_init(fxos8700_t* dev, const fxos8700_params_t *params)
{
uint8_t config;
if ((params->addr < 0x1C) || (params->addr > 0x1F)) {
DEBUG("[fxos8700] Invalid address\n");
return FXOS8700_ADDRERR;
}
dev->p.addr = params->addr;
dev->p.i2c = params->i2c;
dev->p.acc_range = params->acc_range;
dev->p.renew_interval = params->renew_interval;
i2c_acquire(dev->p.i2c);
if (i2c_init_master(dev->p.i2c, I2C_SPEED) != 0) {
DEBUG("[fxos8700] Can't initialize I2C master\n");
i2c_release(dev->p.i2c);
return FXOS8700_NOBUS;
}
if (i2c_read_regs(dev->p.i2c, dev->p.addr, FXOS8700_REG_WHO_AM_I, &config, 1) <= 0) {
i2c_release(dev->p.i2c);
DEBUG("[fxos8700] Could not read WHOAMI\n");
return FXOS8700_NOBUS;
}
if (config != FXOS8700_WHO_AM_I_VAL) {
i2c_release(dev->p.i2c);
DEBUG("[fxos8700] WHOAMI is wrong (%2x)\n", config);
return FXOS8700_NODEV;
}
i2c_release(dev->p.i2c);
/* Configure the ODR to maximum (400Hz in hybrid mode) */
config = FXOS8700_REG_CTRL_REG1_ODR__400HZ & FXOS8700_REG_CTRL_REG1_MASK__ODR;
if (fxos8700_write_regs(dev, FXOS8700_REG_CTRL_REG1, &config, 1) != FXOS8700_OK) {
return FXOS8700_BUSERR;
}
dev->config = config;
/* Activate hybrid mode */
config = FXOS8700_REG_M_CTRL_REG1_HMS__HYBRID & FXOS8700_REG_M_CTRL_REG1_MASK__HMS;
if (fxos8700_write_regs(dev, FXOS8700_REG_M_CTRL_REG1, &config, 1) != FXOS8700_OK) {
return FXOS8700_BUSERR;
}
/* Set burst read mode (accel + magnet together) */
config = FXOS8700_REG_M_CTRL_REG2_MASK__HYB_AUTOINC_MODE;
if (fxos8700_write_regs(dev, FXOS8700_REG_M_CTRL_REG2, &config, 1) != FXOS8700_OK) {
return FXOS8700_BUSERR;
}
/* Set accelerator's full-scale range */
if (fxos8700_read_regs(dev, FXOS8700_REG_XYZ_DATA_CFG, &config, 1) != FXOS8700_OK) {
return FXOS8700_BUSERR;
}
config &= ~FXOS8700_REG_XYZ_DATA_CFG_MASK__FS;
config |= dev->p.acc_range & FXOS8700_REG_XYZ_DATA_CFG_MASK__FS;
if (fxos8700_write_regs(dev, FXOS8700_REG_XYZ_DATA_CFG, &config, 1) != FXOS8700_OK) {
return FXOS8700_BUSERR;
}
/* initial read for caching operation */
if (fxos8700_read(dev, &dev->acc_cached, &dev->mag_cached) != FXOS8700_OK) {
return FXOS8700_BUSERR;
}
dev->last_read_time = xtimer_now_usec();
return FXOS8700_OK;
}
int fxos8700_set_active(const fxos8700_t* dev)
{
uint8_t config = dev->config | FXOS8700_REG_CTRL_REG1_MASK__ACTIVE;
if (fxos8700_write_regs(dev, FXOS8700_REG_CTRL_REG1, &config, 1) != FXOS8700_OK) {
return FXOS8700_BUSERR;
}
return FXOS8700_OK;
}
int fxos8700_set_idle(const fxos8700_t* dev)
{
uint8_t config = dev->config & ~FXOS8700_REG_CTRL_REG1_MASK__ACTIVE;
if (fxos8700_write_regs(dev, FXOS8700_REG_CTRL_REG1, &config, 1) != FXOS8700_OK) {
return FXOS8700_BUSERR;
}
return FXOS8700_OK;
}
int fxos8700_read(const fxos8700_t* dev, fxos8700_measurement_t* acc,
fxos8700_measurement_t* mag)
{
uint8_t data[12];
uint8_t ready = 0;
if (fxos8700_set_active(dev)) {
return FXOS8700_BUSERR;
}
while (!(ready & FXOS8700_REG_STATUS_MASK__XYZ_READY)) {
fxos8700_read_regs(dev, FXOS8700_REG_STATUS, &ready, 1);
}
while (!(ready & FXOS8700_REG_M_DR_STATUS_MASK__XYZ_READY)) {
fxos8700_read_regs(dev, FXOS8700_REG_M_DR_STATUS, &ready, 1);
}
/* Read all data at once */
if (fxos8700_read_regs(dev, FXOS8700_REG_OUT_X_MSB, &data[0], FXOS8700_FULLDATA_LENGTH)) {
return FXOS8700_BUSERR;
}
if (fxos8700_set_idle(dev)) {
return FXOS8700_BUSERR;
}
/* Read accelerometer */
if (acc) {
#if FXOS8700_USE_ACC_RAW_VALUES
acc->x = (int16_t) ((data[0] << 8) | data[1]) >> 2;
acc->y = (int16_t) ((data[2] << 8) | data[3]) >> 2;
acc->z = (int16_t) ((data[4] << 8) | data[5]) >> 2;
#else
int32_t acc_raw_x = (int16_t) ((data[0] << 8) | data[1]) >> 2;
int32_t acc_raw_y = (int16_t) ((data[2] << 8) | data[3]) >> 2;
int32_t acc_raw_z = (int16_t) ((data[4] << 8) | data[5]) >> 2;
switch(dev->p.acc_range) {
case FXOS8700_REG_XYZ_DATA_CFG_FS__2G:
acc->x = (int16_t) ((acc_raw_x * 244) / 100);
acc->y = (int16_t) ((acc_raw_y * 244) / 100);
acc->z = (int16_t) ((acc_raw_z * 244) / 100);
break;
case FXOS8700_REG_XYZ_DATA_CFG_FS__4G:
acc->x = (int16_t) ((acc_raw_x * 488) / 1000);
acc->y = (int16_t) ((acc_raw_y * 488) / 1000);
acc->z = (int16_t) ((acc_raw_z * 488) / 1000);
break;
case FXOS8700_REG_XYZ_DATA_CFG_FS__8G:
acc->x = (int16_t) ((acc_raw_x * 976) / 1000);
acc->y = (int16_t) ((acc_raw_y * 976) / 1000);
acc->z = (int16_t) ((acc_raw_z * 976) / 1000);
break;
default:
return FXOS8700_NODEV;
}
#endif
}
/* Read magnetometer */
if (mag) {
mag->x = (int16_t) ((data[6] << 8) | data[7]);
mag->y = (int16_t) ((data[8] << 8) | data[9]);
mag->z = (int16_t) ((data[10] << 8) | data[11]);
}
return FXOS8700_OK;
}
int fxos8700_read_cached(const void *dev, fxos8700_measurement_t* acc,
fxos8700_measurement_t* mag)
{
fxos8700_t* fxos_dev = (fxos8700_t *)dev;
uint32_t now = xtimer_now_usec();
/* check if readings are outdated */
if (now - fxos_dev->last_read_time > fxos_dev->p.renew_interval) {
/* refresh cache and update last_read_time */
if (fxos8700_read(fxos_dev, &fxos_dev->acc_cached, &fxos_dev->mag_cached)
!= FXOS8700_OK) {
return FXOS8700_BUSERR;
}
fxos_dev->last_read_time = now;
}
/* Read cached data */
if (acc) {
acc->x = fxos_dev->acc_cached.x;
acc->y = fxos_dev->acc_cached.y;
acc->z = fxos_dev->acc_cached.z;
}
if (mag) {
mag->x = fxos_dev->mag_cached.x;
mag->y = fxos_dev->mag_cached.y;
mag->z = fxos_dev->mag_cached.z;
}
return FXOS8700_OK;
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (C) 2018 UC Berkeley
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_fxos8700
* @{
*
* @file
* @brief FXOS8700 adaption to the RIOT actuator/sensor interface
*
* @author Hyung-Sin Kim <hs.kim@cs.berkeley.edu>
*
* @}
*/
#include <string.h>
#include "saul.h"
#include "fxos8700.h"
static int read_mag(const void *dev, phydat_t *res)
{
if (fxos8700_read_cached(dev, NULL, (fxos8700_measurement_t *)res)
!= FXOS8700_OK) {
/* Read failure */
return -ECANCELED;
}
res->unit = UNIT_GS;
res->scale = -3;
return 3;
}
static int read_acc(const void *dev, phydat_t *res)
{
if (fxos8700_read_cached(dev, (fxos8700_measurement_t *)res, NULL)
!= FXOS8700_OK) {
/* Read failure */
return -ECANCELED;
}
#if FXOS8700_USE_ACC_RAW_VALUES
res->unit = UNIT_NONE;
res->scale = 0;
#else
res->unit = UNIT_G;
if (((fxos8700_t *)dev)->p.acc_range == FXOS8700_REG_XYZ_DATA_CFG_FS__2G) {
res->scale = -4;
} else {
res->scale = -3;
}
#endif
return 3;
}
const saul_driver_t fxos8700_saul_mag_driver = {
.read = read_mag,
.write = saul_notsup,
.type = SAUL_SENSE_MAG,
};
const saul_driver_t fxos8700_saul_acc_driver = {
.read = read_acc,
.write = saul_notsup,
.type = SAUL_SENSE_ACCEL,
};

View File

@ -0,0 +1,83 @@
/*
* Copyright (C) 2018 UC Berkeley
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_fxos8700
*
* @{
* @file
* @brief Default configuration for FXOS8700 devices
*
* @author Hyung-Sin Kim <hs.kim@cs.berkeley.edu>
*/
#ifndef FXOS8700_PARAMS_H
#define FXOS8700_PARAMS_H
#include "board.h"
#include "fxos8700.h"
#include "saul_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Default configuration parameters for the FXOS8700 driver
*
* The valid address range is 0x1E - 0x1F depending on the configuration of the
* address pins SA0 and SA1.
*
* @{
*/
#ifndef FXOS8700_PARAM_I2C
#define FXOS8700_PARAM_I2C I2C_DEV(0)
#endif
#ifndef FXOS8700_PARAM_ADDR
#define FXOS8700_PARAM_ADDR 0x1E
#endif
#ifndef FXOS8700_PARAM_ACC_RANGE
#define FXOS8700_PARAM_ACC_RANGE FXOS8700_REG_XYZ_DATA_CFG_FS__8G
#endif
#ifndef FXOS8700_PARAM_RENEW_INTERVAL
#define FXOS8700_PARAM_RENEW_INTERVAL 1000000ul
#endif
#ifndef FXOS8700_PARAMS
#define FXOS8700_PARAMS { .i2c = FXOS8700_PARAM_I2C, \
.addr = FXOS8700_PARAM_ADDR, \
.acc_range = FXOS8700_PARAM_ACC_RANGE, \
.renew_interval = FXOS8700_PARAM_RENEW_INTERVAL }
#endif
#ifndef FXOS8700_SAUL_INFO
#define FXOS8700_SAUL_INFO { .name = "fxos8700" }
#endif
/**@}*/
/**
* @brief FXOS8700 configuration
*/
static const fxos8700_params_t fxos8700_params[] =
{
FXOS8700_PARAMS
};
/**
* @brief Additional meta information to keep in the SAUL registry
*/
static const saul_reg_info_t fxos8700_saul_info[] =
{
FXOS8700_SAUL_INFO
};
#ifdef __cplusplus
}
#endif
#endif /* FXOS8700_PARAMS_H */
/** @} */

View File

@ -0,0 +1,210 @@
/*
* Copyright (C) 2018 UC Berkeley
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_fxos8700
* @{
*
* @file
* @brief Register definitions for FXOS8700 devices
*
* @author Michael Andersen <m.andersen@cs.berkeley.edu>
* @author Hyung-Sin Kim <hs.kim@cs.berkeley.edu>
*/
#ifndef FXOS8700_REGS_H
#define FXOS8700_REGS_H
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @name FXOS8700 register addresses
* @{
*/
#define FXOS8700_REG_STATUS (0x00)
#define FXOS8700_REG_OUT_X_MSB (0x01)
#define FXOS8700_REG_OUT_X_LSB (0x02)
#define FXOS8700_REG_OUT_Y_MSB (0x03)
#define FXOS8700_REG_OUT_Y_LSB (0x04)
#define FXOS8700_REG_OUT_Z_MSB (0x05)
#define FXOS8700_REG_OUT_Z_LSB (0x06)
#define FXOS8700_REG_F_SETUP (0x09)
#define FXOS8700_REG_TRIG_CFG (0x0A)
#define FXOS8700_REG_SYSMOD (0x0B)
#define FXOS8700_REG_INT_SOURCE (0x0C)
#define FXOS8700_REG_WHO_AM_I (0x0D)
#define FXOS8700_REG_XYZ_DATA_CFG (0x0E)
#define FXOS8700_REG_HP_FILTER_CUTOFF (0x0F)
#define FXOS8700_REG_PL_STATUS (0x10)
#define FXOS8700_REG_PL_CFG (0x11)
#define FXOS8700_REG_PL_COUNT (0x12)
#define FXOS8700_REG_PL_BF_ZCOMP (0x13)
#define FXOS8700_REG_PL_THS_REG (0x14)
#define FXOS8700_REG_A_FFMT_CFG (0x15)
#define FXOS8700_REG_A_FFMT_SRC (0x16)
#define FXOS8700_REG_A_FFMT_THS (0x17)
#define FXOS8700_REG_A_FFMT_COUNT (0x18)
#define FXOS8700_REG_TRANSIENT_CFG (0x1D)
#define FXOS8700_REG_TRANSIENT_SRC (0x1E)
#define FXOS8700_REG_TRANSIENT_THS (0x1F)
#define FXOS8700_REG_TRANSIENT_COUNT (0x20)
#define FXOS8700_REG_PULSE_CFG (0x21)
#define FXOS8700_REG_PULSE_SRC (0x22)
#define FXOS8700_REG_PULSE_THSX (0x23)
#define FXOS8700_REG_PULSE_THSY (0x24)
#define FXOS8700_REG_PULSE_THSZ (0x25)
#define FXOS8700_REG_PULSE_TMLT (0x26)
#define FXOS8700_REG_PULSE_LTCY (0x27)
#define FXOS8700_REG_PULSE_WIND (0x28)
#define FXOS8700_REG_ASLP_COUNT (0x29)
#define FXOS8700_REG_CTRL_REG1 (0x2A)
#define FXOS8700_REG_CTRL_REG2 (0x2B)
#define FXOS8700_REG_CTRL_REG3 (0x2C)
#define FXOS8700_REG_CTRL_REG4 (0x2D)
#define FXOS8700_REG_CTRL_REG5 (0x2E)
#define FXOS8700_REG_OFF_X (0x2F)
#define FXOS8700_REG_OFF_Y (0x30)
#define FXOS8700_REG_OFF_Z (0x31)
#define FXOS8700_REG_M_DR_STATUS (0x32)
#define FXOS8700_REG_M_OUT_X_MSB (0x33)
#define FXOS8700_REG_M_OUT_X_LSB (0x34)
#define FXOS8700_REG_M_OUT_Y_MSB (0x35)
#define FXOS8700_REG_M_OUT_Y_LSB (0x36)
#define FXOS8700_REG_M_OUT_Z_MSB (0x37)
#define FXOS8700_REG_M_OUT_Z_LSB (0x38)
#define FXOS8700_REG_CMP_X_MSB (0x39)
#define FXOS8700_REG_CMP_X_LSB (0x3A)
#define FXOS8700_REG_CMP_Y_MSB (0x3B)
#define FXOS8700_REG_CMP_Y_LSB (0x3C)
#define FXOS8700_REG_CMP_Z_MSB (0x3D)
#define FXOS8700_REG_CMP_Z_LSB (0x3E)
#define FXOS8700_REG_M_OFF_X_MSB (0x3F)
#define FXOS8700_REG_M_OFF_X_LSB (0x40)
#define FXOS8700_REG_M_OFF_Y_MSB (0x41)
#define FXOS8700_REG_M_OFF_Y_LSB (0x42)
#define FXOS8700_REG_M_OFF_Z_MSB (0x43)
#define FXOS8700_REG_M_OFF_Z_LSB (0x44)
#define FXOS8700_REG_MAX_X_MSB (0x45)
#define FXOS8700_REG_MAX_X_LSB (0x46)
#define FXOS8700_REG_MAX_Y_MSB (0x47)
#define FXOS8700_REG_MAX_Y_LSB (0x48)
#define FXOS8700_REG_MAX_Z_MSB (0x49)
#define FXOS8700_REG_MAX_Z_LSB (0x4A)
#define FXOS8700_REG_MIN_X_MSB (0x4B)
#define FXOS8700_REG_MIN_X_LSB (0x4C)
#define FXOS8700_REG_MIN_Y_MSB (0x4D)
#define FXOS8700_REG_MIN_Y_LSB (0x4E)
#define FXOS8700_REG_MIN_Z_MSB (0x4F)
#define FXOS8700_REG_MIN_Z_LSB (0x50)
#define FXOS8700_REG_TEMP (0x51)
#define FXOS8700_REG_M_THS_CFG (0x52)
#define FXOS8700_REG_M_THS_SRC (0x53)
#define FXOS8700_REG_M_THS_X_MSB (0x54)
#define FXOS8700_REG_M_THS_X_LSB (0x55)
#define FXOS8700_REG_M_THS_Y_MSB (0x56)
#define FXOS8700_REG_M_THS_Y_LSB (0x57)
#define FXOS8700_REG_M_THS_Z_MSB (0x58)
#define FXOS8700_REG_M_THS_Z_LSB (0x59)
#define FXOS8700_REG_M_THS_COUNT (0x5A)
#define FXOS8700_REG_M_CTRL_REG1 (0x5B)
#define FXOS8700_REG_M_CTRL_REG2 (0x5C)
#define FXOS8700_REG_M_CTRL_REG3 (0x5D)
#define FXOS8700_REG_M_INT_SRC (0x5E)
#define FXOS8700_REG_A_VECM_CFG (0x5F)
#define FXOS8700_REG_A_VECM_THS_MSB (0x60)
#define FXOS8700_REG_A_VECM_THS_LSB (0x61)
#define FXOS8700_REG_A_VECM_CNT (0x62)
#define FXOS8700_REG_A_VECM_INITX_MSB (0x63)
#define FXOS8700_REG_A_VECM_INITX_LSB (0x64)
#define FXOS8700_REG_A_VECM_INITY_MSB (0x65)
#define FXOS8700_REG_A_VECM_INITY_LSB (0x66)
#define FXOS8700_REG_A_VECM_INITZ_MSB (0x67)
#define FXOS8700_REG_A_VECM_INITZ_LSB (0x68)
#define FXOS8700_REG_M_VECM_CFG (0x69)
#define FXOS8700_REG_M_VECM_THS_MSB (0x6A)
#define FXOS8700_REG_M_VECM_THS_LSB (0x6B)
#define FXOS8700_REG_M_VECM_CNT (0x6C)
#define FXOS8700_REG_M_VECM_INITX_MSB (0x6D)
#define FXOS8700_REG_M_VECM_INITX_LSB (0x6E)
#define FXOS8700_REG_M_VECM_INITY_MSB (0x6F)
#define FXOS8700_REG_M_VECM_INITY_LSB (0x70)
#define FXOS8700_REG_M_VECM_INITZ_MSB (0x71)
#define FXOS8700_REG_M_VECM_INITZ_LSB (0x72)
#define FXOS8700_REG_A_FFMT_THS_X_MSB (0x73)
#define FXOS8700_REG_A_FFMT_THS_X_LSB (0x74)
#define FXOS8700_REG_A_FFMT_THS_Y_MSB (0x75)
#define FXOS8700_REG_A_FFMT_THS_Y_LSB (0x76)
#define FXOS8700_REG_A_FFMT_THS_Z_MSB (0x77)
#define FXOS8700_REG_A_FFMT_THS_Z_LSB (0x78)
/** @} */
/**
* @name Device ID
* @{
*/
#define FXOS8700_WHO_AM_I_VAL (0xC7)
/** @} */
/**
* @name Data ready status
* @{
*/
#define FXOS8700_REG_STATUS_MASK__XYZ_READY (0x08)
#define FXOS8700_REG_M_DR_STATUS_MASK__XYZ_READY (0x08)
/** @} */
/**
* @name Output data rate (ODR) and Active mode configuration
* @{
*/
#define FXOS8700_REG_CTRL_REG1_MASK__ODR (0x38)
#define FXOS8700_REG_CTRL_REG1_ODR__400HZ (0x00)
#define FXOS8700_REG_CTRL_REG1_ODR__200HZ (0x08)
#define FXOS8700_REG_CTRL_REG1_ODR__100HZ (0x10)
#define FXOS8700_REG_CTRL_REG1_ODR__50HZ (0x18)
#define FXOS8700_REG_CTRL_REG1_ODR__25HZ (0x20)
#define FXOS8700_REG_CTRL_REG1_MASK__ACTIVE (0x01)
/** @} */
/**
* @name Sensing mode configuration
* @{
*/
#define FXOS8700_REG_M_CTRL_REG1_MASK__HMS (0x03)
#define FXOS8700_REG_M_CTRL_REG1_HMS__ACC_ONLY (0x00)
#define FXOS8700_REG_M_CTRL_REG1_HMS__MAG_ONLY (0x01)
#define FXOS8700_REG_M_CTRL_REG1_HMS__HYBRID (0x03)
/** @} */
/**
* @name Burst-read mode configuration
* @{
*/
#define FXOS8700_REG_M_CTRL_REG2_MASK__HYB_AUTOINC_MODE (0x20)
/** @} */
/**
* @name Accelerator full-scale range configuration
* @{
*/
#define FXOS8700_REG_XYZ_DATA_CFG_MASK__FS (0x03)
#define FXOS8700_REG_XYZ_DATA_CFG_FS__2G (0x00)
#define FXOS8700_REG_XYZ_DATA_CFG_FS__4G (0x01)
#define FXOS8700_REG_XYZ_DATA_CFG_FS__8G (0x02)
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* FXOS8700_REGS_H */
/** @} */

163
drivers/include/fxos8700.h Normal file
View File

@ -0,0 +1,163 @@
/*
* Copyright (C) 2018 UC Berkeley
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup drivers_fxos8700 FXOS8700 3-axis accelerometer/magnetometer
* @ingroup drivers_sensors
* @brief Driver for the FXOS8700 3-axis accelerometer/magnetometer
*
* The connection between the MCU and the FXOS8700 is based on the
* I2C-interface.
*
* @{
*
* @file
* @brief Interface definition for the FXOS8700 sensor driver
*
* @author Michael Andersen <m.andersen@cs.berkeley.edu>
* @author Hyung-Sin Kim <hs.kim@cs.berkeley.edu>
*/
#ifndef FXOS8700_H
#define FXOS8700_H
#include <stdint.h>
#include "periph/i2c.h"
#include "fxos8700_regs.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Default raw value mode for accelerator
*
* If set to 0, measurements will be converted to mg.
* If set to 1, raw adc readings will be returned.
*/
#ifndef FXOS8700_USE_ACC_RAW_VALUES
#define FXOS8700_USE_ACC_RAW_VALUES (0)
#endif
/**
* @brief FXOS8700 specific return values
*/
enum {
FXOS8700_OK = 0, /**< everything went as expected */
FXOS8700_ADDRERR = -1, /**< no FXOS8700 device found on the bus */
FXOS8700_NOBUS = -2, /**< errors while initializing the I2C bus */
FXOS8700_NODEV = -3, /**< no FXOS8700 device found on the bus */
FXOS8700_BUSERR = -4 /**< error during I2C communication */
};
/**
* @brief Parameters needed for device initialization
*/
typedef struct {
i2c_t i2c; /**< I2C device that sensor is connected to */
uint8_t addr; /**< I2C address of this particular sensor */
uint8_t acc_range; /**< Accelerator full-scale range */
uint32_t renew_interval; /**< Interval for cache renewal */
} fxos8700_params_t;
/**
* @brief Individual 3-axis measurement
*/
typedef struct {
int16_t x; /**< x axis of 3-axis measurement */
int16_t y; /**< y axis of 3-axis measurement */
int16_t z; /**< z axis of 3-axis measurement */
} fxos8700_measurement_t;
/**
* @brief Device descriptor for a FXOS8700 device
*/
typedef struct {
uint8_t config; /**< sensor configuration including active mode */
fxos8700_measurement_t acc_cached; /**< cached 3-axis acceleration */
fxos8700_measurement_t mag_cached; /**< cached 3-axis magnetic field */
uint32_t last_read_time; /**< last time when cached data was refreshed */
fxos8700_params_t p; /**< configuration parameters */
} fxos8700_t;
/**
* @brief Initialize an FXOS8700 device
*
* @param[out] dev device descriptor
* @param[in] params parameters for device
*
* @return FXOS8700_OK on success
* @return FXOS8700_NOBUS on I2C initialization error
* @return FXOS8700_BUSERR on I2C communication error
* @return FXOS8700_ADDRERR on invalid address
* @return FXOS8700_NODEV if no FXOS8700 device found on bus
*/
int fxos8700_init(fxos8700_t* dev, const fxos8700_params_t* params);
/**
* @brief Convenience function for turning on the FXOS8700
*
* This function will trigger a new conversion, wait for the conversion to be
* finished and the get the results from the device.
*
* @param[in] dev device descriptor of sensor
*
* @return FXOS8700_OK on success
* @return FXOS8700_BUSERR on I2C communication failures
*/
int fxos8700_set_active(const fxos8700_t* dev);
/**
* @brief Convenience function for turning off the FXOS8700
*
* This function will trigger a new conversion, wait for the conversion to be
* finished and the get the results from the device.
*
* @param[in] dev device descriptor of sensor
*
* @return FXOS8700_OK on success
* @return FXOS8700_BUSERR on I2C communication failures
*/
int fxos8700_set_idle(const fxos8700_t* dev);
/**
* @brief Convenience function for reading acceleration and magnetic field
*
* This function will trigger a new conversion, wait for the conversion to be
* finished and the get the results from the device.
*
* @param[in] dev device descriptor of sensor
* @param[out] acc 3-axis acceleration [in milli grativy acceleration (mg) ]
* @param[out] mag 3-axis magnetic field [in degree milli Gauss (mGs) ]
*
* @return FXOS8700_OK on success
* @return FXOS8700_BUSERR on I2C communication failures
*/
int fxos8700_read(const fxos8700_t* dev, fxos8700_measurement_t* acc, fxos8700_measurement_t* mag);
/**
* @brief Extended read function including caching capability
*
* This function will return cached values if they are within the sampling
* period (FXOS8700_RENEW_INTERVAL), or will trigger a new conversion, wait for
* the conversion to be finished and the get the results from the device.
*
* @param[in] dev device descriptor of sensor
* @param[out] acc 3-axis acceleration [in milli grativy acceleration (mg) ]
* @param[out] mag 3-axis magnetic field [in degree milli Gauss (mGs) ]
*
* @return FXOS8700_OK on success
* @return FXOS8700_BUSERR on I2C communication failures
*/
int fxos8700_read_cached(const void* dev, fxos8700_measurement_t* acc, fxos8700_measurement_t* mag);
#ifdef __cplusplus
}
#endif
#endif /* FXOS8700_H */
/** @} */

View File

@ -353,6 +353,10 @@ auto_init_mpu9150();
extern void auto_init_hdc1000(void);
auto_init_hdc1000();
#endif
#ifdef MODULE_FXOS8700
extern void auto_init_fxos8700(void);
auto_init_fxos8700();
#endif
#ifdef MODULE_HTS221
extern void auto_init_hts221(void);
auto_init_hts221();

View File

@ -0,0 +1,76 @@
/*
* Copyright (C) 2018 UC Berkeley
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
*/
/*
* @ingroup auto_init_saul
* @{
*
* @file
* @brief Auto initialization for FXOS8700 devices
*
* @author Hyung-Sin Kim <hs.kim@cs.berkeley.edu>
*
* @}
*/
#ifdef MODULE_FXOS8700
#include "log.h"
#include "saul_reg.h"
#include "fxos8700_params.h"
/**
* @brief Define the number of configured sensors
*/
#define FXOS8700_NUM (sizeof(fxos8700_params)/sizeof(fxos8700_params[0]))
/**
* @brief Allocate memory for the device descriptors
*/
static fxos8700_t fxos8700_devs[FXOS8700_NUM];
/**
* @brief Memory for the SAUL registry entries
*/
static saul_reg_t saul_entries[FXOS8700_NUM * 2];
/**
* @name Reference the driver struct
* @{
*/
extern saul_driver_t fxos8700_saul_acc_driver;
extern saul_driver_t fxos8700_saul_mag_driver;
/** @} */
void auto_init_fxos8700(void)
{
for (unsigned i = 0; i < FXOS8700_NUM; i++) {
LOG_DEBUG("[auto_init_saul] initializing fxos8700 #%u\n", i);
int res = fxos8700_init(&fxos8700_devs[i], &fxos8700_params[i]);
if (res != 0) {
LOG_ERROR("[auto_init_saul] error initializing fxos8700 #%u\n", i);
}
else {
saul_entries[(i * 2)].dev = &(fxos8700_devs[i]);
saul_entries[(i * 2)].name = fxos8700_saul_info[i].name;
saul_entries[(i * 2)].driver = &fxos8700_saul_acc_driver;
saul_entries[(i * 2) + 1].dev = &(fxos8700_devs[i]);
saul_entries[(i * 2) + 1].name = fxos8700_saul_info[i].name;
saul_entries[(i * 2) + 1].driver = &fxos8700_saul_mag_driver;
saul_reg_add(&(saul_entries[(i * 2)]));
saul_reg_add(&(saul_entries[(i * 2) + 1]));
}
}
}
#else
typedef int dont_be_pedantic;
#endif /* MODULE_FXOS8700 */

View File

@ -0,0 +1,5 @@
include ../Makefile.tests_common
USEMODULE += fxos8700
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,12 @@
# About
This is a manual test application for the FXOS8700 driver.
# Usage
This test application will initialize the FXOS8700 sensor with the configuration
as specified in the default `fxos8700_params.h` file.
If you want to use this test application with different parameters, you can
simply override the default FXOS8700_PARAMS.
After initialization, the sensor reads the 3-axis acceleration and 3-axis
magnetic field values every second and prints them to STDOUT.

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2018 UC Berkeley
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup tests
* @{
*
* @file
* @brief Test application for the PULSE_COUNTER driver
*
* @author Hyung-Sin Kim <hs.kim@cs.berkeley.edu>
*
* @}
*/
#include <stdio.h>
#include "xtimer.h"
#include "fxos8700_params.h"
int main(void)
{
fxos8700_t dev;
puts("FXOS8700 driver test application\n");
/* Initialization */
if (fxos8700_init(&dev, &fxos8700_params[0])) {
puts("[Failed]");
return 1;
}
else {
puts("[OK]\n");
}
while (1) {
/* Acceleration and Magnetic field reading */
fxos8700_measurement_t acc, mag;
if (fxos8700_read(&dev, &acc, &mag) != FXOS8700_OK) {
puts("Read failure\n");
}
else {
printf("acceleration: (%d, %d, %d)\n", acc.x, acc.y, acc.z);
printf("magnetic field: (%d, %d, %d)\n", mag.x, mag.y, mag.z);
}
xtimer_usleep(US_PER_SEC);
}
return 0;
}