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:
parent
689333ff04
commit
beaf08bcb2
@ -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
|
||||
|
@ -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
|
||||
|
1
drivers/fxos8700/Makefile
Normal file
1
drivers/fxos8700/Makefile
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
235
drivers/fxos8700/fxos8700.c
Normal file
235
drivers/fxos8700/fxos8700.c
Normal 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;
|
||||
}
|
69
drivers/fxos8700/fxos8700_saul.c
Normal file
69
drivers/fxos8700/fxos8700_saul.c
Normal 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,
|
||||
};
|
83
drivers/fxos8700/include/fxos8700_params.h
Normal file
83
drivers/fxos8700/include/fxos8700_params.h
Normal 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 */
|
||||
/** @} */
|
210
drivers/fxos8700/include/fxos8700_regs.h
Normal file
210
drivers/fxos8700/include/fxos8700_regs.h
Normal 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
163
drivers/include/fxos8700.h
Normal 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 */
|
||||
/** @} */
|
@ -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();
|
||||
|
76
sys/auto_init/saul/auto_init_fxos8700.c
Normal file
76
sys/auto_init/saul/auto_init_fxos8700.c
Normal 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 */
|
5
tests/driver_fxos8700/Makefile
Normal file
5
tests/driver_fxos8700/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
USEMODULE += fxos8700
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
12
tests/driver_fxos8700/README.md
Normal file
12
tests/driver_fxos8700/README.md
Normal 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.
|
55
tests/driver_fxos8700/main.c
Normal file
55
tests/driver_fxos8700/main.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user