driver: sensor: Add BMM150 Geomagnetic sensor driver

This patch implements BMM150 driver with polling mode and its tested
with original BMM150 sensor hardware. Driver works on I2C
interface as of now.

Following datasheet is taken as reference while developing driver.
http://www.mouser.com/ds/2/783/BST-BMM150-DS001-01-786480.pdf

Signed-off-by: Punit Vara <punit.vara@intel.com>
This commit is contained in:
Punit Vara 2017-05-31 10:34:40 +05:30 committed by Anas Nashif
commit bd359d09c8
6 changed files with 848 additions and 0 deletions

View file

@ -56,6 +56,8 @@ source "drivers/sensor/bmg160/Kconfig"
source "drivers/sensor/bmi160/Kconfig"
source "drivers/sensor/bmm150/Kconfig"
source "drivers/sensor/dht/Kconfig"
source "drivers/sensor/fxas21002/Kconfig"

View file

@ -8,6 +8,7 @@ obj-$(CONFIG_BMC150_MAGN) += bmc150_magn/
obj-$(CONFIG_BME280) += bme280/
obj-$(CONFIG_BMG160) += bmg160/
obj-$(CONFIG_BMI160) += bmi160/
obj-$(CONFIG_BMM150) += bmm150/
obj-$(CONFIG_DHT) += dht/
obj-$(CONFIG_FXAS21002) += fxas21002/
obj-$(CONFIG_FXOS8700) += fxos8700/

View file

@ -0,0 +1,74 @@
# Kconfig - BMM150 Geomagnetic sensor configuration options
#
# Copyright (c) 2017 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
menuconfig BMM150
bool "BMM150 I2C Geomagnetic Chip"
depends on SENSOR && I2C
default n
help
Enable driver for BMM150 I2C-based Geomagnetic sensor.
if BMM150
config BMM150_DEV_NAME
string "BMM150 device name"
default "bmm150"
config BMM150_I2C_ADDR
hex "BMM150 I2C slave address"
default 0x10
help
Specify the I2C slave address for the BMM150.
Possible addresses are 0x10,0x11,0x12,0x13.
config BMM150_I2C_MASTER_DEV_NAME
string "I2C master where BMM150 is connected"
default "I2C_0"
help
Specify the device name of the I2C master device to which BMM150
is connected.
choice
prompt "Default preset"
default BMM150_PRESET_REGULAR
help
Specify the default preset (x/y oversampling, z oversampling, sampling
frequency).
config BMM150_PRESET_LOW_POWER
bool "Low power (3, 3, 10)"
config BMM150_PRESET_REGULAR
bool "Regular (9, 15, 10)"
config BMM150_PRESET_ENHANCED_REGULAR
bool "Enhanced regular (15, 27, 10)"
config BMM150_PRESET_HIGH_ACCURACY
bool "High accuracy (47, 83, 20)"
endchoice
config BMM150_SAMPLING_RATE_RUNTIME
bool "Enable dynamic sampling rate"
default n
help
Enable alteration of sampling rate attribute at runtime.
config BMM150_SAMPLING_REP_XY
bool "Enable dynamic XY oversampling"
default n
help
Enable alteration of XY oversampling at runtime.
config BMM150_SAMPLING_REP_Z
bool "Enable dynamic Z oversampling"
default n
help
Enable alteration of Z oversampling at runtime.
endif # BMM150

View file

@ -0,0 +1 @@
obj-$(CONFIG_BMM150) += bmm150.o

View file

@ -0,0 +1,606 @@
/* bmm150.c - Driver for Bosch BMM150 Geomagnetic Sensor */
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "bmm150.h"
static const struct {
int freq;
u8_t reg_val;
} bmm150_samp_freq_table[] = { { 2, 0x01 },
{ 6, 0x02 },
{ 8, 0x03 },
{ 10, 0x00 },
{ 15, 0x04 },
{ 20, 0x05 },
{ 25, 0x06 },
{ 30, 0x07 } };
static const struct bmm150_preset {
u8_t rep_xy;
u8_t rep_z;
u8_t odr;
} bmm150_presets_table[] = {
[BMM150_LOW_POWER_PRESET] = { 3, 3, 10 },
[BMM150_REGULAR_PRESET] = { 9, 15, 10 },
[BMM150_ENHANCED_REGULAR_PRESET] = { 15, 27, 10 },
[BMM150_HIGH_ACCURACY_PRESET] = { 47, 83, 20 }
};
static int bmm150_set_power_mode(struct device *dev,
enum bmm150_power_modes mode,
int state)
{
struct bmm150_data *data = dev->driver_data;
const struct bmm150_config *config = dev->config->config_info;
switch (mode) {
case BMM150_POWER_MODE_SUSPEND:
if (i2c_reg_update_byte(data->i2c,
config->i2c_slave_addr,
BMM150_REG_POWER,
BMM150_MASK_POWER_CTL,
!state) < 0) {
return -EIO;
}
k_busy_wait(5 * USEC_PER_MSEC);
return 0;
case BMM150_POWER_MODE_SLEEP:
return i2c_reg_update_byte(data->i2c,
config->i2c_slave_addr,
BMM150_REG_OPMODE_ODR,
BMM150_MASK_OPMODE,
BMM150_MODE_SLEEP <<
BMM150_SHIFT_OPMODE);
break;
case BMM150_POWER_MODE_NORMAL:
return i2c_reg_update_byte(data->i2c,
config->i2c_slave_addr,
BMM150_REG_OPMODE_ODR,
BMM150_MASK_OPMODE,
BMM150_MODE_NORMAL <<
BMM150_SHIFT_OPMODE);
break;
}
return -ENOTSUP;
}
static int bmm150_set_odr(struct device *dev, u8_t val)
{
struct bmm150_data *data = dev->driver_data;
const struct bmm150_config *config = dev->config->config_info;
u8_t i;
for (i = 0; i < ARRAY_SIZE(bmm150_samp_freq_table); ++i) {
if (val <= bmm150_samp_freq_table[i].freq) {
return i2c_reg_update_byte(data->i2c,
config->i2c_slave_addr,
BMM150_REG_OPMODE_ODR,
BMM150_MASK_ODR,
(bmm150_samp_freq_table[i].
reg_val <<
BMM150_SHIFT_ODR));
}
}
return -ENOTSUP;
}
#if defined(BMM150_SET_ATTR)
static int bmm150_read_rep_xy(struct device *dev)
{
struct bmm150_data *data = dev->driver->data;
const struct bmm150_config *config = dev->config->config_info;
u8_t reg_val;
if (i2c_reg_read_byte(data->i2c, config->i2c_slave_addr,
BMM150_REG_REP_XY, &reg_val) < 0) {
return -EIO;
}
data->rep_xy = BMM150_REGVAL_TO_REPXY((u8_t)(reg_val));
return 0;
}
static int bmm150_read_rep_z(struct device *dev)
{
struct bmm150_data *data = dev->driver_data;
const struct bmm150_config *config = dev->config->config_info;
u8_t reg_val;
if (i2c_reg_read_byte(data->i2c, config->i2c_slave_addr,
BMM150_REG_REP_Z, &reg_val) < 0) {
return -EIO;
}
data->rep_z = BMM150_REGVAL_TO_REPZ((int)(reg_val));
return 0;
}
static int bmm150_compute_max_odr(struct device *dev, int rep_xy,
int rep_z, int *max_odr)
{
struct bmm150_data *data = dev->driver_data;
if (rep_xy == 0) {
if (data->rep_xy <= 0) {
if (bmm150_read_rep_xy(dev) < 0) {
return -EIO;
}
}
rep_xy = data->rep_xy;
}
if (rep_z == 0) {
if (data->rep_z <= 0) {
if (bmm150_read_rep_z(dev) < 0) {
return -EIO;
}
}
rep_z = data->rep_z;
}
/* Equation reference Datasheet 4.2.4 */
*max_odr = 1000000 / (145 * rep_xy + 500 * rep_z + 980);
return 0;
}
#endif
#if defined(BMM150_SET_ATTR_REP)
static int bmm150_read_odr(struct device *dev)
{
struct bmm150_data *data = dev->driver_data;
const struct bmm150_config *config = dev->config->config_info;
u8_t i, odr_val, reg_val;
if (i2c_reg_read_byte(data->i2c, config->i2c_slave_addr,
BMM150_REG_OPMODE_ODR, &reg_val) < 0) {
return -EIO;
}
odr_val = (reg_val & BMM150_MASK_ODR) >> BMM150_SHIFT_ODR;
for (i = 0; i < ARRAY_SIZE(bmm150_samp_freq_table); ++i) {
if (bmm150_samp_freq_table[i].reg_val == odr_val) {
data->odr = bmm150_samp_freq_table[i].freq;
return 0;
}
}
return -ENOTSUP;
}
#endif
#if defined(CONFIG_BMM150_SAMPLING_REP_XY)
static int bmm150_write_rep_xy(struct device *dev, int val)
{
struct bmm150_data *data = dev->driver_data;
const struct bmm150_config *config = dev->config->config_info;
if (i2c_reg_update_byte(data->i2c, config->i2c_slave_addr,
BMM150_REG_REP_XY,
BMM150_REG_REP_DATAMASK,
BMM150_REPXY_TO_REGVAL(val)) < 0) {
return -EIO;
}
data->rep_xy = val;
return 0;
}
#endif
#if defined(CONFIG_BMM150_SAMPLING_REP_Z)
static int bmm150_write_rep_z(struct device *dev, int val)
{
struct bmm150_data *data = dev->driver_data;
const struct bmm150_config *config = dev->config->config_info;
if (i2c_reg_update_byte(data->i2c, config->i2c_slave_addr,
BMM150_REG_REP_Z,
BMM150_REG_REP_DATAMASK,
BMM150_REPZ_TO_REGVAL(val)) < 0) {
return -EIO;
}
data->rep_z = val;
return 0;
}
#endif
/* Reference Datasheet 4.3.2 */
static s32_t bmm150_compensate_xy(struct bmm150_trim_regs *tregs,
s16_t xy, uint16_t rhall, bool is_x)
{
s8_t txy1, txy2;
s16_t val;
u16_t prevalue;
s32_t temp1, temp2, temp3;
if (xy == BMM150_XY_OVERFLOW_VAL) {
return INT32_MIN;
}
if (!rhall) {
rhall = tregs->xyz1;
}
if (is_x) {
txy1 = tregs->x1;
txy2 = tregs->x2;
} else {
txy1 = tregs->y1;
txy2 = tregs->y2;
}
prevalue = (u16_t)((((s32_t)tregs->xyz1) << 14) / rhall);
val = (s16_t)((prevalue) - ((u16_t)0x4000));
temp1 = (((s32_t)tregs->xy2) * ((((s32_t)val) * ((s32_t)val)) >> 7));
temp2 = ((s32_t)val) * ((s32_t)(((s16_t)tregs->xy1) << 7));
temp3 = (((((temp1 + temp2) >> 9) +
((s32_t)0x100000)) * ((s32_t)(((s16_t)txy2) +
((s16_t)0xA0)))) >> 12);
val = ((s16_t)((((s32_t)xy) * temp3) >> 13)) + (((s16_t)txy1) << 3);
return (int32_t)val;
}
static s32_t bmm150_compensate_z(struct bmm150_trim_regs *tregs,
s16_t z, u16_t rhall)
{
s32_t val, temp1, temp2;
s16_t temp3;
if (z == BMM150_Z_OVERFLOW_VAL) {
return INT32_MIN;
}
temp1 = (((s32_t)(z - tregs->z4)) << 15);
temp2 = ((((s32_t)tregs->z3) *
((s32_t)(((s16_t)rhall) - ((s16_t)tregs->xyz1)))) >> 2);
temp3 = ((s16_t)(((((s32_t)tregs->z1) *
((((s16_t)rhall) << 1))) + (1 << 15)) >> 16));
val = ((temp1 - temp2) / (tregs->z2 + temp3));
return val;
}
static int bmm150_sample_fetch(struct device *dev, enum sensor_channel chan)
{
struct bmm150_data *drv_data = dev->driver_data;
const struct bmm150_config *config = dev->config->config_info;
u16_t values[BMM150_AXIS_XYZR_MAX];
s16_t raw_x, raw_y, raw_z;
u16_t rhall;
__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL ||
chan == SENSOR_CHAN_MAGN_ANY);
if (i2c_burst_read(drv_data->i2c, config->i2c_slave_addr,
BMM150_REG_X_L, (u8_t *)values,
sizeof(values)) < 0) {
SYS_LOG_ERR("failed to read sample");
return -EIO;
}
raw_x = (s16_t)sys_le16_to_cpu(values[BMM150_AXIS_X]) >>
BMM150_SHIFT_XY_L;
raw_y = (s16_t)sys_le16_to_cpu(values[BMM150_AXIS_Y]) >>
BMM150_SHIFT_XY_L;
raw_z = (s16_t)sys_le16_to_cpu(values[BMM150_AXIS_Z]) >>
BMM150_SHIFT_Z_L;
rhall = sys_le16_to_cpu(values[BMM150_RHALL]) >>
BMM150_SHIFT_RHALL_L;
drv_data->sample_x = bmm150_compensate_xy(&drv_data->tregs,
raw_x, rhall, true);
drv_data->sample_y = bmm150_compensate_xy(&drv_data->tregs,
raw_y, rhall, false);
drv_data->sample_z = bmm150_compensate_z(&drv_data->tregs,
raw_z, rhall);
return 0;
}
/*
* Datasheet specify raw units are 16 LSB/uT and this function converts it to
* Gauss
*/
static void bmm150_convert(struct sensor_value *val, int raw_val)
{
/* val = raw_val / 1600 */
val->val1 = raw_val / 1600;
val->val2 = ((s32_t)raw_val * (1000000 / 1600)) % 1000000;
}
static int bmm150_channel_get(struct device *dev,
enum sensor_channel chan,
struct sensor_value *val)
{
struct bmm150_data *drv_data = dev->driver_data;
switch (chan) {
case SENSOR_CHAN_MAGN_X:
bmm150_convert(val, drv_data->sample_x);
break;
case SENSOR_CHAN_MAGN_Y:
bmm150_convert(val, drv_data->sample_y);
break;
case SENSOR_CHAN_MAGN_Z:
bmm150_convert(val, drv_data->sample_x);
break;
case SENSOR_CHAN_MAGN_ANY:
bmm150_convert(val, drv_data->sample_x);
bmm150_convert(val + 1, drv_data->sample_y);
bmm150_convert(val + 2, drv_data->sample_z);
break;
default:
return -EINVAL;
}
return 0;
}
#if defined(BMM150_SET_ATTR_REP)
static inline int bmm150_attr_set_rep(struct device *dev,
enum sensor_channel chan,
const struct sensor_value *val)
{
struct bmm150_data *data = dev->driver_data;
int max_odr;
switch (chan) {
#if defined(CONFIG_BMM150_SAMPLING_REP_XY)
case SENSOR_CHAN_MAGN_X:
case SENSOR_CHAN_MAGN_Y:
if (val->val1 < 1 || val->val1 > 511) {
return -EINVAL;
}
if (bmm150_compute_max_odr(dev, val->val1, 0,
&max_odr) < 0) {
return -EIO;
}
if (data->odr <= 0) {
if (bmm150_read_odr(dev) < 0) {
return -EIO;
}
}
if (data->odr > max_odr) {
return -EINVAL;
}
if (bmm150_write_rep_xy(dev, val->val1) < 0) {
return -EIO;
}
break;
#endif
#if defined(CONFIG_BMM150_SAMPLING_REP_Z)
case SENSOR_CHAN_MAGN_Z:
if (val->val1 < 1 || val->val1 > 256) {
return -EINVAL;
}
if (bmm150_compute_max_odr(dev, 0, val->val1,
&max_odr) < 0) {
return -EIO;
}
if (data->odr <= 0) {
if (bmm150_read_odr(dev) < 0) {
return -EIO;
}
}
if (data->odr > max_odr) {
return -EINVAL;
}
if (bmm150_write_rep_z(dev, val->val1) < 0) {
return -EIO;
}
break;
#endif
default:
return -EINVAL;
}
return 0;
}
#endif
#if defined(BMM150_SET_ATTR)
static int bmm150_attr_set(struct device *dev,
enum sensor_channel chan,
enum sensor_attribute attr,
const struct sensor_value *val)
{
struct bmm150_magn_data *data = dev->driver_data;
switch (attr) {
#if defined(CONFIG_BMM150_SAMPLING_RATE_RUNTIME)
case SENSOR_ATTR_SAMPLING_FREQUENCY:
if (data->max_odr <= 0) {
if (bmm150_compute_max_odr(dev, 0, 0,
&data->max_odr) < 0) {
return -EIO;
}
}
if (data->max_odr < val->val1) {
SYS_LOG_ERR("not supported with current oversampling");
return -ENOTSUP;
}
if (bmm150_set_odr(dev, (u8_t)(val->val1)) < 0) {
return -EIO;
}
break;
#endif
#if defined(BMM150_SET_ATTR_REP)
case SENSOR_ATTR_OVERSAMPLING:
bmm150_attr_set_rep(dev, chan, val);
break;
#endif
default:
return -EINVAL;
}
return 0;
}
#endif
static const struct sensor_driver_api bmm150_api_funcs = {
#if defined(BMM150_SET_ATTR)
.attr_set = bmm150_attr_set,
#endif
.sample_fetch = bmm150_sample_fetch,
.channel_get = bmm150_channel_get,
};
static int bmm150_init_chip(struct device *dev)
{
struct bmm150_data *data = dev->driver_data;
const struct bmm150_config *config = dev->config->config_info;
u8_t chip_id;
struct bmm150_preset preset;
if (bmm150_set_power_mode(dev, BMM150_POWER_MODE_NORMAL, 0) < 0) {
SYS_LOG_ERR("failed to bring up device from normal mode");
return -EIO;
}
if (bmm150_set_power_mode(dev, BMM150_POWER_MODE_SUSPEND, 1) < 0) {
SYS_LOG_ERR("failed to bring up device in suspend mode");
return -EIO;
}
if (bmm150_set_power_mode(dev, BMM150_POWER_MODE_SUSPEND, 0)
< 0) {
SYS_LOG_ERR("failed to bring up device from suspend mode");
return -EIO;
}
if (i2c_reg_read_byte(data->i2c, config->i2c_slave_addr,
BMM150_REG_CHIP_ID, &chip_id) < 0) {
SYS_LOG_ERR("failed reading chip id");
goto err_poweroff;
}
if (chip_id != BMM150_CHIP_ID_VAL) {
SYS_LOG_ERR("invalid chip id 0x%x", chip_id);
goto err_poweroff;
}
preset = bmm150_presets_table[BMM150_DEFAULT_PRESET];
if (bmm150_set_odr(dev, preset.odr) < 0) {
SYS_LOG_ERR("failed to set ODR to %d",
preset.odr);
goto err_poweroff;
}
if (i2c_reg_write_byte(data->i2c, config->i2c_slave_addr,
BMM150_REG_REP_XY,
BMM150_REPXY_TO_REGVAL(preset.rep_xy))
< 0) {
SYS_LOG_ERR("failed to set REP XY to %d",
preset.rep_xy);
goto err_poweroff;
}
if (i2c_reg_write_byte(data->i2c, config->i2c_slave_addr,
BMM150_REG_REP_Z,
BMM150_REPZ_TO_REGVAL(preset.rep_z)) < 0) {
SYS_LOG_ERR("failed to set REP Z to %d",
preset.rep_z);
goto err_poweroff;
}
if (bmm150_set_power_mode(dev, BMM150_POWER_MODE_NORMAL, 1)
< 0) {
SYS_LOG_ERR("failed to power on device");
}
if (i2c_burst_read(data->i2c, config->i2c_slave_addr,
BMM150_REG_TRIM_START, (u8_t *)&data->tregs,
sizeof(data->tregs)) < 0) {
SYS_LOG_ERR("failed to read trim regs");
goto err_poweroff;
}
data->rep_xy = 0;
data->rep_z = 0;
data->odr = 0;
data->max_odr = 0;
data->sample_x = 0;
data->sample_y = 0;
data->sample_z = 0;
data->tregs.xyz1 = sys_le16_to_cpu(data->tregs.xyz1);
data->tregs.z1 = sys_le16_to_cpu(data->tregs.z1);
data->tregs.z2 = sys_le16_to_cpu(data->tregs.z2);
data->tregs.z3 = sys_le16_to_cpu(data->tregs.z3);
data->tregs.z4 = sys_le16_to_cpu(data->tregs.z4);
return 0;
err_poweroff:
bmm150_set_power_mode(dev, BMM150_POWER_MODE_NORMAL, 0);
bmm150_set_power_mode(dev, BMM150_POWER_MODE_SUSPEND, 1);
return -EIO;
}
static int bmm150_init(struct device *dev)
{
const struct bmm150_config *const config =
dev->config->config_info;
struct bmm150_data *data = dev->driver_data;
data->i2c = device_get_binding(config->i2c_master_dev_name);
if (!data->i2c) {
SYS_LOG_ERR("i2c master not found: %s",
config->i2c_master_dev_name);
return -EINVAL;
}
if (bmm150_init_chip(dev) < 0) {
SYS_LOG_ERR("failed to initialize chip");
return -EIO;
}
return 0;
}
static const struct bmm150_config bmm150_config = {
.i2c_master_dev_name = CONFIG_BMM150_I2C_MASTER_DEV_NAME,
.i2c_slave_addr = BMM150_I2C_ADDR,
};
static struct bmm150_data bmm150_data;
DEVICE_AND_API_INIT(bmm150, CONFIG_BMM150_DEV_NAME, bmm150_init,
&bmm150_data, &bmm150_config, POST_KERNEL,
CONFIG_SENSOR_INIT_PRIORITY, &bmm150_api_funcs);

View file

@ -0,0 +1,164 @@
/* sensor_bmm150.h - header file for BMM150 Geomagnetic sensor driver */
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _SENSOR_BMM150_H_
#define _SENSOR_BMM150_H_
#include <zephyr/types.h>
#include <i2c.h>
#include <stdint.h>
#include <misc/util.h>
#include <kernel.h>
#include <device.h>
#include <sensor.h>
#include <misc/byteorder.h>
#include <misc/__assert.h>
#include <gpio.h>
#define BMM150_REG_CHIP_ID 0x40
#define BMM150_CHIP_ID_VAL 0x32
#define BMM150_REG_X_L 0x42
#define BMM150_REG_X_M 0x43
#define BMM150_REG_Y_L 0x44
#define BMM150_REG_Y_M 0x45
#define BMM150_SHIFT_XY_L 3
#define BMM150_REG_Z_L 0x46
#define BMM150_REG_Z_M 0x47
#define BMM150_SHIFT_Z_L 1
#define BMM150_REG_RHALL_L 0x48
#define BMM150_REG_RHALL_M 0x49
#define BMM150_SHIFT_RHALL_L 2
#define BMM150_REG_INT_STATUS 0x4A
#define BMM150_REG_POWER 0x4B
#define BMM150_MASK_POWER_CTL BIT(0)
#define BMM150_REG_OPMODE_ODR 0x4C
#define BMM150_MASK_OPMODE (BIT(2) | BIT(1))
#define BMM150_SHIFT_OPMODE 1
#define BMM150_MODE_NORMAL 0x00
#define BMM150_MODE_FORCED 0x01
#define BMM150_MODE_SLEEP 0x03
#define BMM150_MASK_ODR (BIT(5) | BIT(4) | BIT(3))
#define BMM150_SHIFT_ODR 3
#define BMM150_REG_LOW_THRESH 0x4F
#define BMM150_REG_HIGH_THRESH 0x50
#define BMM150_REG_REP_XY 0x51
#define BMM150_REG_REP_Z 0x52
#define BMM150_REG_REP_DATAMASK 0xFF
#define BMM150_REG_TRIM_START 0x5D
#define BMM150_REG_TRIM_END 0x71
#define BMM150_XY_OVERFLOW_VAL -4096
#define BMM150_Z_OVERFLOW_VAL -16384
#define BMM150_REGVAL_TO_REPXY(regval) (((regval) * 2) + 1)
#define BMM150_REGVAL_TO_REPZ(regval) ((regval) + 1)
#define BMM150_REPXY_TO_REGVAL(rep) (((rep) - 1) / 2)
#define BMM150_REPZ_TO_REGVAL(rep) ((rep) - 1)
#define BMM150_REG_INT 0x4D
#define BMM150_REG_INT_DRDY 0x4E
#define BMM150_MASK_DRDY_EN BIT(7)
#define BMM150_SHIFT_DRDY_EN 7
#define BMM150_DRDY_INT3 BIT(6)
#define BMM150_MASK_DRDY_Z_EN BIT(5)
#define BMM150_MASK_DRDY_Y_EN BIT(4)
#define BMM150_MASK_DRDY_X_EN BIT(3)
#define BMM150_MASK_DRDY_DR_POLARITY BIT(2)
#define BMM150_SHIFT_DRDY_DR_POLARITY 2
#define BMM150_MASK_DRDY_LATCHING BIT(1)
#define BMM150_MASK_DRDY_INT3_POLARITY BIT(0)
#define BMM150_I2C_ADDR CONFIG_BMM150_I2C_ADDR
#if defined(CONFIG_BMM150_SAMPLING_REP_XY) || \
defined(CONFIG_BMM150_SAMPLING_REP_Z)
#define BMM150_SET_ATTR_REP
#endif
#if defined(CONFIG_BMM150_MAGN_SAMPLING_RATE_RUNTIME) || \
defined(BMM150_MAGN_SET_ATTR_REP)
#define BMM150_MAGN_SET_ATTR
#endif
struct bmm150_config {
char *i2c_master_dev_name;
u16_t i2c_slave_addr;
};
struct bmm150_trim_regs {
s8_t x1;
s8_t y1;
u16_t reserved1;
u8_t reserved2;
s16_t z4;
s8_t x2;
s8_t y2;
u16_t reserved3;
s16_t z2;
u16_t z1;
u16_t xyz1;
s16_t z3;
s8_t xy2;
u8_t xy1;
} __packed;
struct bmm150_data {
struct device *i2c;
struct k_sem sem;
struct bmm150_trim_regs tregs;
int rep_xy, rep_z, odr, max_odr;
int sample_x, sample_y, sample_z;
};
enum bmm150_power_modes {
BMM150_POWER_MODE_SUSPEND,
BMM150_POWER_MODE_SLEEP,
BMM150_POWER_MODE_NORMAL
};
enum bmm150_axis {
BMM150_AXIS_X,
BMM150_AXIS_Y,
BMM150_AXIS_Z,
BMM150_RHALL,
BMM150_AXIS_XYZ_MAX = BMM150_RHALL,
BMM150_AXIS_XYZR_MAX
};
enum bmm150_presets {
BMM150_LOW_POWER_PRESET,
BMM150_REGULAR_PRESET,
BMM150_ENHANCED_REGULAR_PRESET,
BMM150_HIGH_ACCURACY_PRESET
};
#if defined(CONFIG_BMM150_PRESET_LOW_POWER)
#define BMM150_DEFAULT_PRESET BMM150LOW_POWER_PRESET
#elif defined(CONFIG_BMM150_PRESET_REGULAR)
#define BMM150_DEFAULT_PRESET BMM150_REGULAR_PRESET
#elif defined(CONFIG_BMM150_PRESET_ENHANCED_REGULAR)
#define BMM150_DEFAULT_PRESET BMM150_ENHANCED_REGULAR_PRESET
#elif defined(CONFIG_BMM150_PRESET_HIGH_ACCURACY)
#define BMM150_DEFAULT_PRESET BMM150_HIGH_ACCURACY_PRESET
#endif
#define SYS_LOG_DOMAIN "BMM150"
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_SENSOR_LEVEL
#include <logging/sys_log.h>
#endif /* __SENSOR_BMM150_H__ */