drivers: sensor: Add support for MMA8451Q (3-axis accelerometer)
Only basic features supported initially but more could be added from: https://www.nxp.com/docs/en/data-sheet/MMA8451Q.pdf fixes #9006 A sample app will be provided in a separate PR. Signed-off-by: Lars Knudsen <larsgk@gmail.com>
This commit is contained in:
parent
fd1fec8ad6
commit
9c0d7813e5
|
@ -29,6 +29,7 @@ add_subdirectory_ifdef(CONFIG_LSM9DS0_MFD lsm9ds0_mfd)
|
|||
add_subdirectory_ifdef(CONFIG_MAX30101 max30101)
|
||||
add_subdirectory_ifdef(CONFIG_MAX44009 max44009)
|
||||
add_subdirectory_ifdef(CONFIG_MCP9808 mcp9808)
|
||||
add_subdirectory_ifdef(CONFIG_MMA8451Q mma8451q)
|
||||
add_subdirectory_ifdef(CONFIG_MPU6050 mpu6050)
|
||||
add_subdirectory_ifdef(CONFIG_PMS7003 pms7003)
|
||||
add_subdirectory_ifdef(CONFIG_TEMP_NRF5 nrf5)
|
||||
|
|
|
@ -101,6 +101,8 @@ source "drivers/sensor/max44009/Kconfig"
|
|||
|
||||
source "drivers/sensor/mcp9808/Kconfig"
|
||||
|
||||
source "drivers/sensor/mma8451q/Kconfig"
|
||||
|
||||
source "drivers/sensor/mpu6050/Kconfig"
|
||||
|
||||
source "drivers/sensor/nrf5/Kconfig"
|
||||
|
|
9
drivers/sensor/mma8451q/CMakeLists.txt
Normal file
9
drivers/sensor/mma8451q/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# Copyright (c) 2018 Lars Knudsen
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_MMA8451Q mma8451q.c)
|
58
drivers/sensor/mma8451q/Kconfig
Normal file
58
drivers/sensor/mma8451q/Kconfig
Normal file
|
@ -0,0 +1,58 @@
|
|||
# Kconfig - MMA8451Q Accelerometer sensor configuration options
|
||||
#
|
||||
# Copyright (c) 2018 Lars Knudsen
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
menuconfig MMA8451Q
|
||||
bool "MMA8451Q Accelerometer driver"
|
||||
depends on I2C
|
||||
help
|
||||
Enable driver for MMA8451Q Accelerometer.
|
||||
|
||||
if !HAS_DTS_I2C_DEVICE
|
||||
|
||||
config MMA8451Q_NAME
|
||||
string "Device name"
|
||||
depends on MMA8451Q
|
||||
default "MMA8451Q"
|
||||
|
||||
config MMA8451Q_I2C_NAME
|
||||
string "I2C device name"
|
||||
depends on MMA8451Q
|
||||
default I2C_0_NAME
|
||||
|
||||
config MMA8451Q_I2C_ADDRESS
|
||||
hex
|
||||
prompt "I2C address for MMA8451Q Sensor"
|
||||
depends on MMA8451Q
|
||||
default 0x1D
|
||||
help
|
||||
I2C address of the MMA8451Q sensor.
|
||||
0x1D: I2C_ADDR
|
||||
|
||||
endif # !HAS_DTS_I2C_DEVICE
|
||||
|
||||
config MMA8451Q_WHOAMI
|
||||
hex "WHOAMI value"
|
||||
depends on MMA8451Q
|
||||
default 0x1A
|
||||
help
|
||||
The whoami value for MMA8451Q (0x1A).
|
||||
|
||||
choice
|
||||
prompt "Range"
|
||||
depends on MMA8451Q
|
||||
default MMA8451Q_RANGE_2G
|
||||
|
||||
config MMA8451Q_RANGE_8G
|
||||
bool "8g (0.976 mg/LSB)"
|
||||
|
||||
config MMA8451Q_RANGE_4G
|
||||
bool "4g (0.488 mg/LSB)"
|
||||
|
||||
config MMA8451Q_RANGE_2G
|
||||
bool "2g (0.244 mg/LSB)"
|
||||
|
||||
endchoice
|
182
drivers/sensor/mma8451q/mma8451q.c
Normal file
182
drivers/sensor/mma8451q/mma8451q.c
Normal file
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Lars Knudsen
|
||||
* Copyright (c) 2016 Freescale Semiconductor, Inc. (sample conversion)
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <device.h>
|
||||
#include <i2c.h>
|
||||
#include <kernel.h>
|
||||
#include <misc/util.h>
|
||||
#include <sensor.h>
|
||||
|
||||
#include "mma8451q.h"
|
||||
|
||||
/* Data-sheet: https://www.nxp.com/docs/en/data-sheet/MMA8451Q.pdf */
|
||||
|
||||
static int mma8451q_sample_fetch(struct device *dev, enum sensor_channel chan)
|
||||
{
|
||||
const struct mma8451q_config *config = dev->config->config_info;
|
||||
struct mma8451q_data *data = dev->driver_data;
|
||||
|
||||
u8_t buf[6];
|
||||
|
||||
/* Read data from all three axes at the same time. */
|
||||
if (i2c_burst_read(data->i2c, config->i2c_address,
|
||||
MMA8451Q_OUT_X_MSB, buf, 6) < 0) {
|
||||
SYS_LOG_ERR("Could not read accelerometer data");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
data->x = (buf[0] << 8) | buf[1];
|
||||
data->y = (buf[2] << 8) | buf[3];
|
||||
data->z = (buf[4] << 8) | buf[5];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mma8451q_accel_convert(struct sensor_value *val, s16_t raw,
|
||||
enum mma8451q_range range)
|
||||
{
|
||||
u8_t frac_bits;
|
||||
s64_t micro_ms2;
|
||||
|
||||
/* The range encoding is convenient to compute the number of fractional
|
||||
* bits:
|
||||
* - 2g mode (range = 0) has 14 fractional bits
|
||||
* - 4g mode (range = 1) has 13 fractional bits
|
||||
* - 8g mode (range = 2) has 12 fractional bits
|
||||
*/
|
||||
frac_bits = 14 - range;
|
||||
|
||||
/* Convert units to micro m/s^2. Intermediate results before the shift
|
||||
* are 40 bits wide.
|
||||
*/
|
||||
micro_ms2 = (raw * SENSOR_G) >> frac_bits;
|
||||
|
||||
/* The maximum possible value is 8g, which in units of micro m/s^2
|
||||
* always fits into 32-bits. Cast down to s32_t so we can use a
|
||||
* faster divide.
|
||||
*/
|
||||
val->val1 = (s32_t) micro_ms2 / 1000000;
|
||||
val->val2 = (s32_t) micro_ms2 % 1000000;
|
||||
}
|
||||
|
||||
static int mma8451q_channel_get(struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
const struct mma8451q_config *config = dev->config->config_info;
|
||||
struct mma8451q_data *data = dev->driver_data;
|
||||
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_ACCEL_X:
|
||||
mma8451q_accel_convert(val, data->x, config->range);
|
||||
break;
|
||||
|
||||
case SENSOR_CHAN_ACCEL_Y:
|
||||
mma8451q_accel_convert(val, data->y, config->range);
|
||||
break;
|
||||
|
||||
case SENSOR_CHAN_ACCEL_Z:
|
||||
mma8451q_accel_convert(val, data->z, config->range);
|
||||
break;
|
||||
|
||||
case SENSOR_CHAN_ACCEL_XYZ:
|
||||
mma8451q_accel_convert(val++, data->x, config->range);
|
||||
mma8451q_accel_convert(val++, data->y, config->range);
|
||||
mma8451q_accel_convert(val++, data->z, config->range);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api mma8451q_driver_api = {
|
||||
.sample_fetch = mma8451q_sample_fetch,
|
||||
.channel_get = mma8451q_channel_get,
|
||||
};
|
||||
|
||||
int mma8451q_init(struct device *dev)
|
||||
{
|
||||
const struct mma8451q_config *config = dev->config->config_info;
|
||||
struct mma8451q_data *data = dev->driver_data;
|
||||
|
||||
data->i2c = device_get_binding(config->i2c_name);
|
||||
if (data->i2c == NULL) {
|
||||
SYS_LOG_ERR("Failed to get pointer to %s device!",
|
||||
config->i2c_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
u8_t whoami;
|
||||
|
||||
if (i2c_reg_read_byte(data->i2c, config->i2c_address,
|
||||
MMA8451Q_REG_WHOAMI, &whoami)) {
|
||||
SYS_LOG_ERR("Could not get WHOAMI value");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (whoami != config->whoami) {
|
||||
SYS_LOG_ERR("WHOAMI value received 0x%x, expected 0x%x",
|
||||
whoami, MMA8451Q_REG_WHOAMI);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (i2c_reg_write_byte(data->i2c, config->i2c_address,
|
||||
MMA8451Q_CTRL_REG1, 0) < 0) {
|
||||
SYS_LOG_ERR("Could not set accel in config mode");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (i2c_reg_write_byte(data->i2c, config->i2c_address,
|
||||
MMA8451Q_XYZ_DATA_CFG, config->range) < 0) {
|
||||
SYS_LOG_ERR("Could not set range");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (i2c_reg_write_byte(data->i2c, config->i2c_address,
|
||||
MMA8451Q_CTRL_REG2, 0) < 0) {
|
||||
SYS_LOG_ERR("Could not set to normal mode");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (i2c_reg_write_byte(data->i2c, config->i2c_address,
|
||||
MMA8451Q_CTRL_REG3, 0) < 0) {
|
||||
SYS_LOG_ERR("Could not set to low polarity, push-pull output");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (i2c_reg_write_byte(data->i2c, config->i2c_address,
|
||||
MMA8451Q_CTRL_REG1, 0x09) < 0) {
|
||||
SYS_LOG_ERR("Could not set data rate to 800Hz");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
SYS_LOG_DBG("Init complete");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mma8451q_config mma8451q_config = {
|
||||
.i2c_name = CONFIG_MMA8451Q_I2C_NAME,
|
||||
.i2c_address = CONFIG_MMA8451Q_I2C_ADDRESS,
|
||||
.whoami = CONFIG_MMA8451Q_WHOAMI,
|
||||
#if CONFIG_MMA8451Q_RANGE_8G
|
||||
.range = MMA8451Q_RANGE_8G,
|
||||
#elif CONFIG_MMA8451Q_RANGE_4G
|
||||
.range = MMA8451Q_RANGE_4G,
|
||||
#else
|
||||
.range = MMA8451Q_RANGE_2G,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct mma8451q_data mma8451q_data;
|
||||
|
||||
DEVICE_AND_API_INIT(mma8451q, CONFIG_MMA8451Q_NAME, mma8451q_init,
|
||||
&mma8451q_data, &mma8451q_config, POST_KERNEL,
|
||||
CONFIG_SENSOR_INIT_PRIORITY, &mma8451q_driver_api);
|
59
drivers/sensor/mma8451q/mma8451q.h
Normal file
59
drivers/sensor/mma8451q/mma8451q.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Lars Knudsen
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _SENSOR_MMA8451Q
|
||||
#define _SENSOR_MMA8451Q
|
||||
|
||||
#include <device.h>
|
||||
#include <misc/util.h>
|
||||
|
||||
#define MMA8451Q_OUT_X_MSB 0x01
|
||||
#define MMA8451Q_OUT_Y_MSB 0x03
|
||||
#define MMA8451Q_OUT_Z_MSB 0x05
|
||||
|
||||
#define MMA8451Q_REG_WHOAMI 0x0d
|
||||
|
||||
#define MMA8451Q_XYZ_DATA_CFG 0x0E
|
||||
|
||||
#define MMA8451Q_CTRL_REG1 0x2A
|
||||
#define MMA8451Q_CTRL_REG2 0x2B
|
||||
#define MMA8451Q_CTRL_REG3 0x2C
|
||||
#define MMA8451Q_CTRL_REG4 0x2D
|
||||
#define MMA8451Q_CTRL_REG5 0x2E
|
||||
|
||||
#define MMA8451Q_NUM_ACCEL_CHANNELS 3
|
||||
|
||||
enum mma8451q_channel {
|
||||
MMA8451Q_CHANNEL_ACCEL_X = 0,
|
||||
MMA8451Q_CHANNEL_ACCEL_Y,
|
||||
MMA8451Q_CHANNEL_ACCEL_Z,
|
||||
};
|
||||
|
||||
enum mma8451q_range {
|
||||
MMA8451Q_RANGE_2G = 0,
|
||||
MMA8451Q_RANGE_4G,
|
||||
MMA8451Q_RANGE_8G,
|
||||
};
|
||||
|
||||
struct mma8451q_config {
|
||||
char *i2c_name;
|
||||
u8_t i2c_address;
|
||||
u8_t whoami;
|
||||
enum mma8451q_range range;
|
||||
};
|
||||
|
||||
struct mma8451q_data {
|
||||
struct device *i2c;
|
||||
s16_t x;
|
||||
s16_t y;
|
||||
s16_t z;
|
||||
};
|
||||
|
||||
#define SYS_LOG_DOMAIN "MMA8451Q"
|
||||
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_SENSOR_LEVEL
|
||||
#include <logging/sys_log.h>
|
||||
|
||||
#endif /* _SENSOR_MMA8451Q_ */
|
22
dts/bindings/sensor/nxp,mma8451q.yaml
Normal file
22
dts/bindings/sensor/nxp,mma8451q.yaml
Normal file
|
@ -0,0 +1,22 @@
|
|||
#
|
||||
# Copyright (c) 2018, Lars Knudsen
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
---
|
||||
title: MMA8451Q 3-axis Accelerometer
|
||||
id: nxp,mma8451q
|
||||
version: 0.1
|
||||
|
||||
description: >
|
||||
This is a representation of the MMA8451Q 3-axis Accelerometer
|
||||
sensor
|
||||
|
||||
inherits:
|
||||
!include i2c-device.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
constraint: "nxp,mma8451q"
|
||||
|
||||
...
|
Loading…
Reference in a new issue