drivers: sensor: adi: Move to vendor subdirectory
Organizes sensor drivers by vendor to distribute maintainership responsibilities. Signed-off-by: Maureen Helm <maureen.helm@analog.com>
This commit is contained in:
parent
8acada0608
commit
8714f53188
45 changed files with 33 additions and 16 deletions
11
drivers/sensor/adi/adxl372/CMakeLists.txt
Normal file
11
drivers/sensor/adi/adxl372/CMakeLists.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# Copyright (c) 2018 Analog Devices Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(adxl372.c)
|
||||
zephyr_library_sources(adxl372_spi.c)
|
||||
zephyr_library_sources(adxl372_i2c.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_ADXL372_TRIGGER adxl372_trigger.c)
|
124
drivers/sensor/adi/adxl372/Kconfig
Normal file
124
drivers/sensor/adi/adxl372/Kconfig
Normal file
|
@ -0,0 +1,124 @@
|
|||
# Micropower, 3-Axis, +/-200g Digital Accelerometer
|
||||
|
||||
# Copyright (c) 2018 Analog Devices Inc.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
menuconfig ADXL372
|
||||
bool "ADXL372 Three Axis High-g I2C/SPI accelerometer"
|
||||
default y
|
||||
depends on DT_HAS_ADI_ADXL372_ENABLED
|
||||
select I2C if $(dt_compat_on_bus,$(DT_COMPAT_ADI_ADXL372),i2c)
|
||||
select SPI if $(dt_compat_on_bus,$(DT_COMPAT_ADI_ADXL372),spi)
|
||||
help
|
||||
Enable driver for ADXL372 Three-Axis Digital Accelerometers.
|
||||
|
||||
if ADXL372
|
||||
|
||||
choice ADXL372_OP_MODE
|
||||
prompt "Operating mode"
|
||||
default ADXL372_PEAK_DETECT_MODE
|
||||
|
||||
config ADXL372_PEAK_DETECT_MODE
|
||||
bool "Max Peak detect mode"
|
||||
help
|
||||
In most high-g applications, a single (3-axis) acceleration sample at
|
||||
the peak of an impact event contains sufficient information
|
||||
about the event, and the full acceleration history is not required.
|
||||
In this mode the device returns only the over threshold
|
||||
Peak Acceleration between two consecutive sample fetches.
|
||||
|
||||
config ADXL372_MEASUREMENT_MODE
|
||||
bool "Measurement Mode"
|
||||
help
|
||||
In this mode, acceleration data is provided continuously at the
|
||||
output data rate (ODR).
|
||||
|
||||
endchoice
|
||||
|
||||
config ADXL372_ACTIVITY_THRESHOLD
|
||||
int "Activity threshold in mg"
|
||||
range 0 200000
|
||||
default 500
|
||||
help
|
||||
Threshold for activity detection.
|
||||
|
||||
config ADXL372_INACTIVITY_THRESHOLD
|
||||
int "In-activity threshold in mg"
|
||||
range 0 200000
|
||||
default 400
|
||||
help
|
||||
Threshold for in-activity detection.
|
||||
|
||||
config ADXL372_ACTIVITY_TIME
|
||||
int "Activity time"
|
||||
range 0 255
|
||||
default 1
|
||||
help
|
||||
The activity timer implements a robust activity detection that
|
||||
minimizes false positive motion triggers. When the timer is used,
|
||||
only sustained motion can trigger activity detection.
|
||||
Number of multiples of 3.3 ms activity timer for which above threshold
|
||||
acceleration is required to detect activity. It is 3.3 ms per code
|
||||
for 6400 Hz ODR, and it is 6.6 ms per code for 3200 Hz ODR and below.
|
||||
|
||||
config ADXL372_INACTIVITY_TIME
|
||||
int "In-activity time"
|
||||
range 0 255
|
||||
default 2
|
||||
help
|
||||
The time that all enabled axes must be lower than the inactivity
|
||||
threshold for an inactivity event to be detected. Number of multiples
|
||||
of 26 ms inactivity timer for which below threshold acceleration is
|
||||
required to detect inactivity. It is 26 ms per code for 3200 Hz ODR
|
||||
and below, and it is 13 ms per code for 6400 Hz ODR.
|
||||
|
||||
config ADXL372_REFERENCED_ACTIVITY_DETECTION_MODE
|
||||
bool "Use referenced activity/in-activity detection"
|
||||
default y
|
||||
help
|
||||
Activity detection can be configured as referenced or absolute.
|
||||
When using absolute activity detection, acceleration samples are
|
||||
compared directly to a user set threshold to determine whether
|
||||
motion is present. In many applications, it is advantageous for
|
||||
activity detection to be based not on an absolute threshold,
|
||||
but on a deviation from a reference point or orientation.
|
||||
|
||||
choice ADXL372_TRIGGER_MODE
|
||||
prompt "Trigger mode"
|
||||
default ADXL372_TRIGGER_NONE
|
||||
help
|
||||
Specify the type of triggering used by the driver.
|
||||
|
||||
config ADXL372_TRIGGER_NONE
|
||||
bool "No trigger"
|
||||
|
||||
config ADXL372_TRIGGER_GLOBAL_THREAD
|
||||
bool "Use global thread"
|
||||
depends on GPIO
|
||||
select ADXL372_TRIGGER
|
||||
|
||||
config ADXL372_TRIGGER_OWN_THREAD
|
||||
bool "Use own thread"
|
||||
depends on GPIO
|
||||
select ADXL372_TRIGGER
|
||||
|
||||
endchoice
|
||||
|
||||
config ADXL372_TRIGGER
|
||||
bool
|
||||
|
||||
config ADXL372_THREAD_PRIORITY
|
||||
int "Thread priority"
|
||||
depends on ADXL372_TRIGGER_OWN_THREAD && ADXL372_TRIGGER
|
||||
default 10
|
||||
help
|
||||
Priority of thread used by the driver to handle interrupts.
|
||||
|
||||
config ADXL372_THREAD_STACK_SIZE
|
||||
int "Thread stack size"
|
||||
depends on ADXL372_TRIGGER_OWN_THREAD && ADXL372_TRIGGER
|
||||
default 1024
|
||||
help
|
||||
Stack size of thread used by the driver to handle interrupts.
|
||||
|
||||
endif # ADXL372
|
892
drivers/sensor/adi/adxl372/adxl372.c
Normal file
892
drivers/sensor/adi/adxl372/adxl372.c
Normal file
|
@ -0,0 +1,892 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Analog Devices Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT adi_adxl372
|
||||
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <string.h>
|
||||
#include <zephyr/init.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
#include <zephyr/sys/__assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "adxl372.h"
|
||||
|
||||
LOG_MODULE_REGISTER(ADXL372, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
/**
|
||||
* Set the threshold for activity detection for a single axis
|
||||
* @param dev - The device structure.
|
||||
* @param axis_reg_h - The high part of the activity register.
|
||||
* @param act - The activity config structure.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_set_activity_threshold(const struct device *dev,
|
||||
uint8_t axis_reg_h,
|
||||
const struct adxl372_activity_threshold *act)
|
||||
{
|
||||
int ret;
|
||||
uint8_t val;
|
||||
struct adxl372_data *data = dev->data;
|
||||
|
||||
ret = data->hw_tf->write_reg(dev, axis_reg_h++, act->thresh >> 3);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (axis_reg_h) {
|
||||
case ADXL372_X_THRESH_ACT_L:
|
||||
case ADXL372_X_THRESH_INACT_L:
|
||||
case ADXL372_X_THRESH_ACT2_L:
|
||||
val = (act->thresh << 5) | (act->referenced << 1) | act->enable;
|
||||
break;
|
||||
default:
|
||||
val = (act->thresh << 5) | act->enable;
|
||||
}
|
||||
|
||||
return data->hw_tf->write_reg(dev, axis_reg_h, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the threshold for activity detection for all 3-axis
|
||||
* @param dev - The device structure.
|
||||
* @param axis_reg_h - The high part of the activity register.
|
||||
* @param act - The activity config structure.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_set_activity_threshold_xyz(const struct device *dev,
|
||||
uint8_t axis_reg_h,
|
||||
const struct adxl372_activity_threshold *act)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
ret = adxl372_set_activity_threshold(dev, axis_reg_h, act);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
axis_reg_h += 2U;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode of operation.
|
||||
* @param dev - The device structure.
|
||||
* @param op_mode - Mode of operation.
|
||||
* Accepted values: ADXL372_STANDBY
|
||||
* ADXL372_WAKE_UP
|
||||
* ADXL372_INSTANT_ON
|
||||
* ADXL372_FULL_BW_MEASUREMENT
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_set_op_mode(const struct device *dev,
|
||||
enum adxl372_op_mode op_mode)
|
||||
{
|
||||
struct adxl372_data *data = dev->data;
|
||||
|
||||
return data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL,
|
||||
ADXL372_POWER_CTL_MODE_MSK,
|
||||
ADXL372_POWER_CTL_MODE(op_mode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Autosleep. When set to 1, autosleep is enabled, and the device enters
|
||||
* wake-up mode automatically upon detection of inactivity.
|
||||
* @param dev - The device structure.
|
||||
* @param enable - Accepted values: true
|
||||
* false
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_set_autosleep(const struct device *dev, bool enable)
|
||||
{
|
||||
struct adxl372_data *data = dev->data;
|
||||
|
||||
return data->hw_tf->write_reg_mask(dev, ADXL372_MEASURE,
|
||||
ADXL372_MEASURE_AUTOSLEEP_MSK,
|
||||
ADXL372_MEASURE_AUTOSLEEP_MODE(enable));
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the desired output signal bandwidth.
|
||||
* @param dev - The device structure.
|
||||
* @param bw - bandwidth.
|
||||
* Accepted values: ADXL372_BW_200HZ
|
||||
* ADXL372_BW_400HZ
|
||||
* ADXL372_BW_800HZ
|
||||
* ADXL372_BW_1600HZ
|
||||
* ADXL372_BW_3200HZ
|
||||
* ADXL372_BW_LPF_DISABLED
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_set_bandwidth(const struct device *dev,
|
||||
enum adxl372_bandwidth bw)
|
||||
{
|
||||
int ret;
|
||||
uint8_t mask;
|
||||
struct adxl372_data *data = dev->data;
|
||||
|
||||
if (bw == ADXL372_BW_LPF_DISABLED) {
|
||||
mask = ADXL372_POWER_CTL_LPF_DIS_MSK;
|
||||
} else {
|
||||
mask = 0U;
|
||||
}
|
||||
|
||||
ret = data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL,
|
||||
ADXL372_POWER_CTL_LPF_DIS_MSK, mask);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return data->hw_tf->write_reg_mask(dev, ADXL372_MEASURE,
|
||||
ADXL372_MEASURE_BANDWIDTH_MSK,
|
||||
ADXL372_MEASURE_BANDWIDTH_MODE(bw));
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the desired high-pass filter corner.
|
||||
* @param dev - The device structure.
|
||||
* @param c - bandwidth.
|
||||
* Accepted values: ADXL372_HPF_CORNER_0
|
||||
* ADXL372_HPF_CORNER_1
|
||||
* ADXL372_HPF_CORNER_2
|
||||
* ADXL372_HPF_CORNER_3
|
||||
* ADXL372_HPF_DISABLED
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_set_hpf_corner(const struct device *dev,
|
||||
enum adxl372_hpf_corner c)
|
||||
{
|
||||
|
||||
int ret;
|
||||
uint8_t mask;
|
||||
struct adxl372_data *data = dev->data;
|
||||
|
||||
if (c == ADXL372_HPF_DISABLED) {
|
||||
mask = ADXL372_POWER_CTL_HPF_DIS_MSK;
|
||||
} else {
|
||||
mask = 0U;
|
||||
}
|
||||
|
||||
ret = data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL,
|
||||
ADXL372_POWER_CTL_HPF_DIS_MSK, mask);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return data->hw_tf->write_reg(dev, ADXL372_HPF, ADXL372_HPF_CORNER(c));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Link/Loop Activity Processing.
|
||||
* @param dev - The device structure.
|
||||
* @param mode - Mode of operation.
|
||||
* Accepted values: ADXL372_DEFAULT
|
||||
* ADXL372_LINKED
|
||||
* ADXL372_LOOPED
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_set_act_proc_mode(const struct device *dev,
|
||||
enum adxl372_act_proc_mode mode)
|
||||
{
|
||||
struct adxl372_data *data = dev->data;
|
||||
|
||||
return data->hw_tf->write_reg_mask(dev, ADXL372_MEASURE,
|
||||
ADXL372_MEASURE_LINKLOOP_MSK,
|
||||
ADXL372_MEASURE_LINKLOOP_MODE(mode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Output data rate.
|
||||
* @param dev - The device structure.
|
||||
* @param odr - Output data rate.
|
||||
* Accepted values: ADXL372_ODR_400HZ
|
||||
* ADXL372_ODR_800HZ
|
||||
* ADXL372_ODR_1600HZ
|
||||
* ADXL372_ODR_3200HZ
|
||||
* ADXL372_ODR_6400HZ
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_set_odr(const struct device *dev, enum adxl372_odr odr)
|
||||
{
|
||||
struct adxl372_data *data = dev->data;
|
||||
|
||||
return data->hw_tf->write_reg_mask(dev, ADXL372_TIMING,
|
||||
ADXL372_TIMING_ODR_MSK,
|
||||
ADXL372_TIMING_ODR_MODE(odr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Select instant on threshold
|
||||
* @param dev - The device structure.
|
||||
* @param mode - 0 = low threshold, 1 = high threshold.
|
||||
* Accepted values: ADXL372_INSTANT_ON_LOW_TH
|
||||
* ADXL372_INSTANT_ON_HIGH_TH
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_set_instant_on_th(const struct device *dev,
|
||||
enum adxl372_instant_on_th_mode mode)
|
||||
{
|
||||
struct adxl372_data *data = dev->data;
|
||||
|
||||
return data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL,
|
||||
ADXL372_POWER_CTL_INSTANT_ON_TH_MSK,
|
||||
ADXL372_POWER_CTL_INSTANT_ON_TH_MODE(mode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Timer Rate for Wake-Up Mode.
|
||||
* @param dev - The device structure.
|
||||
* @param wur - wake up mode rate
|
||||
* Accepted values: ADXL372_WUR_52ms
|
||||
* ADXL372_WUR_104ms
|
||||
* ADXL372_WUR_208ms
|
||||
* ADXL372_WUR_512ms
|
||||
* ADXL372_WUR_2048ms
|
||||
* ADXL372_WUR_4096ms
|
||||
* ADXL372_WUR_8192ms
|
||||
* ADXL372_WUR_24576ms
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_set_wakeup_rate(const struct device *dev,
|
||||
enum adxl372_wakeup_rate wur)
|
||||
{
|
||||
struct adxl372_data *data = dev->data;
|
||||
|
||||
return data->hw_tf->write_reg_mask(dev, ADXL372_TIMING,
|
||||
ADXL372_TIMING_WAKE_UP_RATE_MSK,
|
||||
ADXL372_TIMING_WAKE_UP_RATE_MODE(wur));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the activity timer
|
||||
* @param dev - The device structure.
|
||||
* @param time - The value set in this register.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_set_activity_time(const struct device *dev, uint8_t time)
|
||||
{
|
||||
struct adxl372_data *data = dev->data;
|
||||
|
||||
return data->hw_tf->write_reg(dev, ADXL372_TIME_ACT, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the inactivity timer
|
||||
* @param dev - The device structure.
|
||||
* @param time - is the 16-bit value set by the TIME_INACT_L register
|
||||
* (eight LSBs) and the TIME_INACT_H register (eight MSBs).
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_set_inactivity_time(const struct device *dev,
|
||||
uint16_t time)
|
||||
{
|
||||
int ret;
|
||||
struct adxl372_data *data = dev->data;
|
||||
|
||||
ret = data->hw_tf->write_reg(dev, ADXL372_TIME_INACT_H, time >> 8);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return data->hw_tf->write_reg(dev, ADXL372_TIME_INACT_L, time & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the filter settling period.
|
||||
* @param dev - The device structure.
|
||||
* @param mode - settle period
|
||||
* Accepted values: ADXL372_FILTER_SETTLE_370
|
||||
* ADXL372_FILTER_SETTLE_16
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_set_filter_settle(const struct device *dev,
|
||||
enum adxl372_filter_settle mode)
|
||||
{
|
||||
struct adxl372_data *data = dev->data;
|
||||
|
||||
return data->hw_tf->write_reg_mask(dev, ADXL372_POWER_CTL,
|
||||
ADXL372_POWER_CTL_FIL_SETTLE_MSK,
|
||||
ADXL372_POWER_CTL_FIL_SETTLE_MODE(mode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the INT1 and INT2 interrupt pins.
|
||||
* @param dev - The device structure.
|
||||
* @param int1 - INT1 interrupt pins.
|
||||
* @param int2 - INT2 interrupt pins.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_interrupt_config(const struct device *dev,
|
||||
uint8_t int1,
|
||||
uint8_t int2)
|
||||
{
|
||||
int ret;
|
||||
struct adxl372_data *data = dev->data;
|
||||
|
||||
ret = data->hw_tf->write_reg(dev, ADXL372_INT1_MAP, int1);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return data->hw_tf->write_reg(dev, ADXL372_INT2_MAP, int2);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the STATUS, STATUS2, FIFO_ENTRIES and FIFO_ENTRIES2 registers data
|
||||
* @param dev - The device structure.
|
||||
* @param status1 - Data stored in the STATUS1 register
|
||||
* @param status2 - Data stored in the STATUS2 register
|
||||
* @param fifo_entries - Number of valid data samples present in the
|
||||
* FIFO buffer (0 to 512)
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int adxl372_get_status(const struct device *dev,
|
||||
uint8_t *status1,
|
||||
uint8_t *status2,
|
||||
uint16_t *fifo_entries)
|
||||
{
|
||||
struct adxl372_data *data = dev->data;
|
||||
uint8_t buf[4], length = 1U;
|
||||
int ret;
|
||||
|
||||
if (status2) {
|
||||
length++;
|
||||
}
|
||||
|
||||
if (fifo_entries) {
|
||||
length += 2U;
|
||||
}
|
||||
|
||||
ret = data->hw_tf->read_reg_multiple(dev, ADXL372_STATUS_1, buf, length);
|
||||
|
||||
*status1 = buf[0];
|
||||
|
||||
if (status2) {
|
||||
*status2 = buf[1];
|
||||
}
|
||||
|
||||
if (fifo_entries) {
|
||||
*fifo_entries = ((buf[2] & 0x3) << 8) | buf[3];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Software reset.
|
||||
* @param dev - The device structure.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_reset(const struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct adxl372_data *data = dev->data;
|
||||
|
||||
ret = adxl372_set_op_mode(dev, ADXL372_STANDBY);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
/* Writing code 0x52 resets the device */
|
||||
ret = data->hw_tf->write_reg(dev, ADXL372_RESET, ADXL372_RESET_CODE);
|
||||
k_sleep(K_MSEC(1));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the operating parameters for the FIFO.
|
||||
* @param dev - The device structure.
|
||||
* @param mode - FIFO Mode. Specifies FIFO operating mode.
|
||||
* Accepted values: ADXL372_FIFO_BYPASSED
|
||||
* ADXL372_FIFO_STREAMED
|
||||
* ADXL372_FIFO_TRIGGERED
|
||||
* ADXL372_FIFO_OLD_SAVED
|
||||
* @param format - FIFO Format. Specifies the data is stored in the FIFO buffer.
|
||||
* Accepted values: ADXL372_XYZ_FIFO
|
||||
* ADXL372_X_FIFO
|
||||
* ADXL372_Y_FIFO
|
||||
* ADXL372_XY_FIFO
|
||||
* ADXL372_Z_FIFO
|
||||
* ADXL372_XZ_FIFO
|
||||
* ADXL372_YZ_FIFO
|
||||
* ADXL372_XYZ_PEAK_FIFO
|
||||
* @param fifo_samples - FIFO Samples. Watermark number of FIFO samples that
|
||||
* triggers a FIFO_FULL condition when reached.
|
||||
* Values range from 0 to 512.
|
||||
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_configure_fifo(const struct device *dev,
|
||||
enum adxl372_fifo_mode mode,
|
||||
enum adxl372_fifo_format format,
|
||||
uint16_t fifo_samples)
|
||||
{
|
||||
struct adxl372_data *data = dev->data;
|
||||
uint8_t fifo_config;
|
||||
int ret;
|
||||
|
||||
if (fifo_samples > 512) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* All FIFO modes must be configured while in standby mode.
|
||||
*/
|
||||
ret = adxl372_set_op_mode(dev, ADXL372_STANDBY);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
fifo_config = (ADXL372_FIFO_CTL_FORMAT_MODE(format) |
|
||||
ADXL372_FIFO_CTL_MODE_MODE(mode) |
|
||||
ADXL372_FIFO_CTL_SAMPLES_MODE(fifo_samples));
|
||||
|
||||
ret = data->hw_tf->write_reg(dev, ADXL372_FIFO_CTL, fifo_config);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
ret = data->hw_tf->write_reg(dev, ADXL372_FIFO_SAMPLES, fifo_samples & 0xFF);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
data->fifo_config.fifo_format = format;
|
||||
data->fifo_config.fifo_mode = mode;
|
||||
data->fifo_config.fifo_samples = fifo_samples;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve 3-axis acceleration data
|
||||
* @param dev - The device structure.
|
||||
* @param maxpeak - Retrieve the highest magnitude (x, y, z) sample recorded
|
||||
* since the last read of the MAXPEAK registers
|
||||
* @param accel_data - pointer to a variable of type adxl372_xyz_accel_data
|
||||
* where (x, y, z) acceleration data will be stored.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int adxl372_get_accel_data(const struct device *dev, bool maxpeak,
|
||||
struct adxl372_xyz_accel_data *accel_data)
|
||||
{
|
||||
struct adxl372_data *data = dev->data;
|
||||
uint8_t buf[6];
|
||||
uint8_t status1;
|
||||
int ret;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_ADXL372_TRIGGER)) {
|
||||
do {
|
||||
adxl372_get_status(dev, &status1, NULL, NULL);
|
||||
} while (!(ADXL372_STATUS_1_DATA_RDY(status1)));
|
||||
}
|
||||
|
||||
ret = data->hw_tf->read_reg_multiple(dev, maxpeak ? ADXL372_X_MAXPEAK_H :
|
||||
ADXL372_X_DATA_H, buf, 6);
|
||||
|
||||
accel_data->x = (buf[0] << 8) | (buf[1] & 0xF0);
|
||||
accel_data->y = (buf[2] << 8) | (buf[3] & 0xF0);
|
||||
accel_data->z = (buf[4] << 8) | (buf[5] & 0xF0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adxl372_attr_set_odr(const struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
enum sensor_attribute attr,
|
||||
const struct sensor_value *val)
|
||||
{
|
||||
enum adxl372_odr odr;
|
||||
|
||||
switch (val->val1) {
|
||||
case 400:
|
||||
odr = ADXL372_ODR_400HZ;
|
||||
break;
|
||||
case 800:
|
||||
odr = ADXL372_ODR_800HZ;
|
||||
break;
|
||||
case 1600:
|
||||
odr = ADXL372_ODR_1600HZ;
|
||||
break;
|
||||
case 3200:
|
||||
odr = ADXL372_ODR_3200HZ;
|
||||
break;
|
||||
case 6400:
|
||||
odr = ADXL372_ODR_6400HZ;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return adxl372_set_odr(dev, odr);
|
||||
}
|
||||
|
||||
static int adxl372_attr_set_thresh(const struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
enum sensor_attribute attr,
|
||||
const struct sensor_value *val)
|
||||
{
|
||||
const struct adxl372_dev_config *cfg = dev->config;
|
||||
struct adxl372_activity_threshold threshold;
|
||||
int64_t llvalue;
|
||||
int32_t value;
|
||||
int64_t micro_ms2 = val->val1 * 1000000LL + val->val2;
|
||||
uint8_t reg;
|
||||
|
||||
llvalue = llabs((micro_ms2 * 10) / SENSOR_G);
|
||||
|
||||
if (llvalue > 2047) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
value = (int32_t) llvalue;
|
||||
|
||||
threshold.thresh = value;
|
||||
threshold.enable = cfg->activity_th.enable;
|
||||
threshold.referenced = cfg->activity_th.referenced;
|
||||
|
||||
if (attr == SENSOR_ATTR_UPPER_THRESH) {
|
||||
reg = ADXL372_X_THRESH_ACT_H;
|
||||
} else {
|
||||
reg = ADXL372_X_THRESH_INACT_H;
|
||||
}
|
||||
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_ACCEL_X:
|
||||
return adxl372_set_activity_threshold(dev, reg, &threshold);
|
||||
case SENSOR_CHAN_ACCEL_Y:
|
||||
return adxl372_set_activity_threshold(dev, reg + 2, &threshold);
|
||||
case SENSOR_CHAN_ACCEL_Z:
|
||||
return adxl372_set_activity_threshold(dev, reg + 4, &threshold);
|
||||
case SENSOR_CHAN_ACCEL_XYZ:
|
||||
return adxl372_set_activity_threshold_xyz(dev, reg, &threshold);
|
||||
default:
|
||||
LOG_ERR("attr_set() not supported on this channel");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
static int adxl372_attr_set(const struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
enum sensor_attribute attr,
|
||||
const struct sensor_value *val)
|
||||
{
|
||||
switch (attr) {
|
||||
case SENSOR_ATTR_SAMPLING_FREQUENCY:
|
||||
return adxl372_attr_set_odr(dev, chan, attr, val);
|
||||
case SENSOR_ATTR_UPPER_THRESH:
|
||||
case SENSOR_ATTR_LOWER_THRESH:
|
||||
return adxl372_attr_set_thresh(dev, chan, attr, val);
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
static int adxl372_sample_fetch(const struct device *dev,
|
||||
enum sensor_channel chan)
|
||||
{
|
||||
const struct adxl372_dev_config *cfg = dev->config;
|
||||
struct adxl372_data *data = dev->data;
|
||||
|
||||
return adxl372_get_accel_data(dev, cfg->max_peak_detect_mode,
|
||||
&data->sample);
|
||||
}
|
||||
|
||||
static void adxl372_accel_convert(struct sensor_value *val, int16_t value)
|
||||
{
|
||||
/*
|
||||
* Sensor resolution is 100mg/LSB, 12-bit value needs to be right
|
||||
* shifted by 4 or divided by 16. Overall this results in a scale of 160
|
||||
*/
|
||||
int32_t micro_ms2 = value * (SENSOR_G / (16 * 1000 / 100));
|
||||
|
||||
val->val1 = micro_ms2 / 1000000;
|
||||
val->val2 = micro_ms2 % 1000000;
|
||||
}
|
||||
|
||||
static int adxl372_channel_get(const struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
struct adxl372_data *data = dev->data;
|
||||
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_ACCEL_X:
|
||||
adxl372_accel_convert(val, data->sample.x);
|
||||
break;
|
||||
case SENSOR_CHAN_ACCEL_Y:
|
||||
adxl372_accel_convert(val, data->sample.y);
|
||||
break;
|
||||
case SENSOR_CHAN_ACCEL_Z:
|
||||
adxl372_accel_convert(val, data->sample.z);
|
||||
break;
|
||||
case SENSOR_CHAN_ACCEL_XYZ:
|
||||
adxl372_accel_convert(val++, data->sample.x);
|
||||
adxl372_accel_convert(val++, data->sample.y);
|
||||
adxl372_accel_convert(val, data->sample.z);
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api adxl372_api_funcs = {
|
||||
.attr_set = adxl372_attr_set,
|
||||
.sample_fetch = adxl372_sample_fetch,
|
||||
.channel_get = adxl372_channel_get,
|
||||
#ifdef CONFIG_ADXL372_TRIGGER
|
||||
.trigger_set = adxl372_trigger_set,
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
static int adxl372_probe(const struct device *dev)
|
||||
{
|
||||
const struct adxl372_dev_config *cfg = dev->config;
|
||||
struct adxl372_data *data = dev->data;
|
||||
uint8_t dev_id, part_id;
|
||||
int ret;
|
||||
|
||||
ret = data->hw_tf->read_reg(dev, ADXL372_DEVID, &dev_id);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
ret = data->hw_tf->read_reg(dev, ADXL372_PARTID, &part_id);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (dev_id != ADXL372_DEVID_VAL || part_id != ADXL372_PARTID_VAL) {
|
||||
LOG_ERR("failed to read id (0x%X:0x%X)", dev_id, part_id);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ADXL372_TRIGGER
|
||||
data->act_proc_mode = ADXL372_LINKED,
|
||||
#else
|
||||
data->act_proc_mode = ADXL372_LOOPED,
|
||||
#endif
|
||||
|
||||
/* Device settings */
|
||||
ret = adxl372_set_op_mode(dev, ADXL372_STANDBY);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adxl372_reset(dev);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adxl372_set_hpf_corner(dev, cfg->hpf);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adxl372_set_bandwidth(dev, cfg->bw);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adxl372_set_odr(dev, cfg->odr);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adxl372_set_wakeup_rate(dev, cfg->wur);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adxl372_set_autosleep(dev, cfg->autosleep);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adxl372_set_instant_on_th(dev, cfg->th_mode);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adxl372_set_activity_threshold_xyz(dev, ADXL372_X_THRESH_ACT_H,
|
||||
&cfg->activity_th);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adxl372_set_activity_threshold_xyz(dev, ADXL372_X_THRESH_INACT_H,
|
||||
&cfg->inactivity_th);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adxl372_set_activity_time(dev, cfg->activity_time);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adxl372_set_inactivity_time(dev, cfg->inactivity_time);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adxl372_set_filter_settle(dev, cfg->filter_settle);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adxl372_configure_fifo(dev, cfg->fifo_config.fifo_mode,
|
||||
cfg->fifo_config.fifo_format,
|
||||
cfg->fifo_config.fifo_samples);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ADXL372_TRIGGER
|
||||
if (adxl372_init_interrupt(dev) < 0) {
|
||||
LOG_ERR("Failed to initialize interrupt!");
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = adxl372_interrupt_config(dev, cfg->int1_config, cfg->int2_config);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adxl372_set_op_mode(dev, cfg->op_mode);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return adxl372_set_act_proc_mode(dev, data->act_proc_mode);
|
||||
}
|
||||
|
||||
static int adxl372_init(const struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
const struct adxl372_dev_config *cfg = dev->config;
|
||||
|
||||
ret = cfg->bus_init(dev);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to initialize sensor bus");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (adxl372_probe(dev) < 0) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0
|
||||
#warning "ADXL372 driver enabled without any devices"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Device creation macro, shared by ADXL372_DEFINE_SPI() and
|
||||
* ADXL372_DEFINE_I2C().
|
||||
*/
|
||||
|
||||
#define ADXL372_DEVICE_INIT(inst) \
|
||||
SENSOR_DEVICE_DT_INST_DEFINE(inst, \
|
||||
adxl372_init, \
|
||||
NULL, \
|
||||
&adxl372_data_##inst, \
|
||||
&adxl372_config_##inst, \
|
||||
POST_KERNEL, \
|
||||
CONFIG_SENSOR_INIT_PRIORITY, \
|
||||
&adxl372_api_funcs);
|
||||
|
||||
/*
|
||||
* Instantiation macros used when a device is on a SPI bus.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ADXL372_TRIGGER
|
||||
#define ADXL372_CFG_IRQ(inst) \
|
||||
.interrupt = GPIO_DT_SPEC_INST_GET(inst, int1_gpios),
|
||||
#else
|
||||
#define ADXL372_CFG_IRQ(inst)
|
||||
#endif /* CONFIG_ADXL372_TRIGGER */
|
||||
|
||||
#define ADXL372_CONFIG(inst) \
|
||||
.bw = DT_INST_PROP(inst, bw), \
|
||||
.hpf = DT_INST_PROP(inst, hpf), \
|
||||
.odr = DT_INST_PROP(inst, odr), \
|
||||
.max_peak_detect_mode = IS_ENABLED(CONFIG_ADXL372_PEAK_DETECT_MODE), \
|
||||
.th_mode = ADXL372_INSTANT_ON_LOW_TH, \
|
||||
.autosleep = false, \
|
||||
.wur = ADXL372_WUR_52ms, \
|
||||
.activity_th.thresh = CONFIG_ADXL372_ACTIVITY_THRESHOLD / 100, \
|
||||
.activity_th.referenced = \
|
||||
IS_ENABLED(CONFIG_ADXL372_REFERENCED_ACTIVITY_DETECTION_MODE), \
|
||||
.activity_th.enable = 1, \
|
||||
.activity_time = CONFIG_ADXL372_ACTIVITY_TIME, \
|
||||
.inactivity_th.thresh = CONFIG_ADXL372_INACTIVITY_THRESHOLD / 100, \
|
||||
.inactivity_th.referenced = \
|
||||
IS_ENABLED(CONFIG_ADXL372_REFERENCED_ACTIVITY_DETECTION_MODE), \
|
||||
.inactivity_th.enable = 1, \
|
||||
.inactivity_time = CONFIG_ADXL372_INACTIVITY_TIME, \
|
||||
.filter_settle = ADXL372_FILTER_SETTLE_370, \
|
||||
.fifo_config.fifo_mode = ADXL372_FIFO_STREAMED, \
|
||||
.fifo_config.fifo_format = ADXL372_XYZ_PEAK_FIFO, \
|
||||
.fifo_config.fifo_samples = 128, \
|
||||
.op_mode = ADXL372_FULL_BW_MEASUREMENT, \
|
||||
|
||||
#define ADXL372_CONFIG_SPI(inst) \
|
||||
{ \
|
||||
.bus_init = adxl372_spi_init, \
|
||||
.spi = SPI_DT_SPEC_INST_GET(inst, SPI_WORD_SET(8) | \
|
||||
SPI_TRANSFER_MSB, 0), \
|
||||
ADXL372_CONFIG(inst) \
|
||||
COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \
|
||||
(ADXL372_CFG_IRQ(inst)), ()) \
|
||||
}
|
||||
|
||||
#define ADXL372_DEFINE_SPI(inst) \
|
||||
static struct adxl372_data adxl372_data_##inst; \
|
||||
static const struct adxl372_dev_config adxl372_config_##inst = \
|
||||
ADXL372_CONFIG_SPI(inst); \
|
||||
ADXL372_DEVICE_INIT(inst)
|
||||
|
||||
/*
|
||||
* Instantiation macros used when a device is on an I2C bus.
|
||||
*/
|
||||
|
||||
#define ADXL372_CONFIG_I2C(inst) \
|
||||
{ \
|
||||
.bus_init = adxl372_i2c_init, \
|
||||
.i2c = I2C_DT_SPEC_INST_GET(inst), \
|
||||
ADXL372_CONFIG(inst) \
|
||||
COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \
|
||||
(ADXL372_CFG_IRQ(inst)), ()) \
|
||||
}
|
||||
|
||||
#define ADXL372_DEFINE_I2C(inst) \
|
||||
static struct adxl372_data adxl372_data_##inst; \
|
||||
static const struct adxl372_dev_config adxl372_config_##inst = \
|
||||
ADXL372_CONFIG_I2C(inst); \
|
||||
ADXL372_DEVICE_INIT(inst)
|
||||
/*
|
||||
* Main instantiation macro. Use of COND_CODE_1() selects the right
|
||||
* bus-specific macro at preprocessor time.
|
||||
*/
|
||||
|
||||
#define ADXL372_DEFINE(inst) \
|
||||
COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
|
||||
(ADXL372_DEFINE_SPI(inst)), \
|
||||
(ADXL372_DEFINE_I2C(inst)))
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(ADXL372_DEFINE)
|
375
drivers/sensor/adi/adxl372/adxl372.h
Normal file
375
drivers/sensor/adi/adxl372/adxl372.h
Normal file
|
@ -0,0 +1,375 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Analog Devices Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_SENSOR_ADXL372_ADXL372_H_
|
||||
#define ZEPHYR_DRIVERS_SENSOR_ADXL372_ADXL372_H_
|
||||
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
|
||||
#include <zephyr/drivers/spi.h>
|
||||
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */
|
||||
|
||||
/*
|
||||
* ADXL372 registers definition
|
||||
*/
|
||||
#define ADXL372_DEVID 0x00u /* Analog Devices accelerometer ID */
|
||||
#define ADXL372_DEVID_MST 0x01u /* Analog Devices MEMS device ID */
|
||||
#define ADXL372_PARTID 0x02u /* Device ID */
|
||||
#define ADXL372_REVID 0x03u /* product revision ID*/
|
||||
#define ADXL372_STATUS_1 0x04u /* Status register 1 */
|
||||
#define ADXL372_STATUS_2 0x05u /* Status register 2 */
|
||||
#define ADXL372_FIFO_ENTRIES_2 0x06u /* Valid data samples in the FIFO */
|
||||
#define ADXL372_FIFO_ENTRIES_1 0x07u /* Valid data samples in the FIFO */
|
||||
#define ADXL372_X_DATA_H 0x08u /* X-axis acceleration data [11:4] */
|
||||
#define ADXL372_X_DATA_L 0x09u /* X-axis acceleration data [3:0] */
|
||||
#define ADXL372_Y_DATA_H 0x0Au /* Y-axis acceleration data [11:4] */
|
||||
#define ADXL372_Y_DATA_L 0x0Bu /* Y-axis acceleration data [3:0] */
|
||||
#define ADXL372_Z_DATA_H 0x0Cu /* Z-axis acceleration data [11:4] */
|
||||
#define ADXL372_Z_DATA_L 0x0Du /* Z-axis acceleration data [3:0] */
|
||||
#define ADXL372_X_MAXPEAK_H 0x15u /* X-axis MaxPeak acceleration data */
|
||||
#define ADXL372_X_MAXPEAK_L 0x16u /* X-axis MaxPeak acceleration data */
|
||||
#define ADXL372_Y_MAXPEAK_H 0x17u /* Y-axis MaxPeak acceleration data */
|
||||
#define ADXL372_Y_MAXPEAK_L 0x18u /* Y-axis MaxPeak acceleration data */
|
||||
#define ADXL372_Z_MAXPEAK_H 0x19u /* Z-axis MaxPeak acceleration data */
|
||||
#define ADXL372_Z_MAXPEAK_L 0x1Au /* Z-axis MaxPeak acceleration data */
|
||||
#define ADXL372_OFFSET_X 0x20u /* X axis offset */
|
||||
#define ADXL372_OFFSET_Y 0x21u /* Y axis offset */
|
||||
#define ADXL372_OFFSET_Z 0x22u /* Z axis offset */
|
||||
#define ADXL372_X_THRESH_ACT_H 0x23u /* X axis Activity Threshold [15:8] */
|
||||
#define ADXL372_X_THRESH_ACT_L 0x24u /* X axis Activity Threshold [7:0] */
|
||||
#define ADXL372_Y_THRESH_ACT_H 0x25u /* Y axis Activity Threshold [15:8] */
|
||||
#define ADXL372_Y_THRESH_ACT_L 0x26u /* Y axis Activity Threshold [7:0] */
|
||||
#define ADXL372_Z_THRESH_ACT_H 0x27u /* Z axis Activity Threshold [15:8] */
|
||||
#define ADXL372_Z_THRESH_ACT_L 0x28u /* Z axis Activity Threshold [7:0] */
|
||||
#define ADXL372_TIME_ACT 0x29u /* Activity Time */
|
||||
#define ADXL372_X_THRESH_INACT_H 0x2Au /* X axis Inactivity Threshold */
|
||||
#define ADXL372_X_THRESH_INACT_L 0x2Bu /* X axis Inactivity Threshold */
|
||||
#define ADXL372_Y_THRESH_INACT_H 0x2Cu /* Y axis Inactivity Threshold */
|
||||
#define ADXL372_Y_THRESH_INACT_L 0x2Du /* Y axis Inactivity Threshold */
|
||||
#define ADXL372_Z_THRESH_INACT_H 0x2Eu /* Z axis Inactivity Threshold */
|
||||
#define ADXL372_Z_THRESH_INACT_L 0x2Fu /* Z axis Inactivity Threshold */
|
||||
#define ADXL372_TIME_INACT_H 0x30u /* Inactivity Time [15:8] */
|
||||
#define ADXL372_TIME_INACT_L 0x31u /* Inactivity Time [7:0] */
|
||||
#define ADXL372_X_THRESH_ACT2_H 0x32u /* X axis Activity2 Threshold [15:8] */
|
||||
#define ADXL372_X_THRESH_ACT2_L 0x33u /* X axis Activity2 Threshold [7:0] */
|
||||
#define ADXL372_Y_THRESH_ACT2_H 0x34u /* Y axis Activity2 Threshold [15:8] */
|
||||
#define ADXL372_Y_THRESH_ACT2_L 0x35u /* Y axis Activity2 Threshold [7:0] */
|
||||
#define ADXL372_Z_THRESH_ACT2_H 0x36u /* Z axis Activity2 Threshold [15:8] */
|
||||
#define ADXL372_Z_THRESH_ACT2_L 0x37u /* Z axis Activity2 Threshold [7:0] */
|
||||
#define ADXL372_HPF 0x38u /* High Pass Filter */
|
||||
#define ADXL372_FIFO_SAMPLES 0x39u /* FIFO Samples */
|
||||
#define ADXL372_FIFO_CTL 0x3Au /* FIFO Control */
|
||||
#define ADXL372_INT1_MAP 0x3Bu /* Interrupt 1 mapping control */
|
||||
#define ADXL372_INT2_MAP 0x3Cu /* Interrupt 2 mapping control */
|
||||
#define ADXL372_TIMING 0x3Du /* Timing */
|
||||
#define ADXL372_MEASURE 0x3Eu /* Measure */
|
||||
#define ADXL372_POWER_CTL 0x3Fu /* Power control */
|
||||
#define ADXL372_SELF_TEST 0x40u /* Self Test */
|
||||
#define ADXL372_RESET 0x41u /* Reset */
|
||||
#define ADXL372_FIFO_DATA 0x42u /* FIFO Data */
|
||||
|
||||
#define ADXL372_DEVID_VAL 0xADu /* Analog Devices accelerometer ID */
|
||||
#define ADXL372_MST_DEVID_VAL 0x1Du /* Analog Devices MEMS device ID */
|
||||
#define ADXL372_PARTID_VAL 0xFAu /* Device ID */
|
||||
#define ADXL372_REVID_VAL 0x02u /* product revision ID*/
|
||||
#define ADXL372_RESET_CODE 0x52u /* Writing code 0x52 resets the device */
|
||||
|
||||
#define ADXL372_READ 0x01u
|
||||
#define ADXL372_REG_READ(x) (((x & 0xFF) << 1) | ADXL372_READ)
|
||||
#define ADXL372_REG_WRITE(x) ((x & 0xFF) << 1)
|
||||
#define ADXL372_TO_I2C_REG(x) ((x) >> 1)
|
||||
|
||||
/* ADXL372_POWER_CTL */
|
||||
#define ADXL372_POWER_CTL_INSTANT_ON_TH_MSK BIT(5)
|
||||
#define ADXL372_POWER_CTL_INSTANT_ON_TH_MODE(x) (((x) & 0x1) << 5)
|
||||
#define ADXL372_POWER_CTL_FIL_SETTLE_MSK BIT(4)
|
||||
#define ADXL372_POWER_CTL_FIL_SETTLE_MODE(x) (((x) & 0x1) << 4)
|
||||
#define ADXL372_POWER_CTL_LPF_DIS_MSK BIT(3)
|
||||
#define ADXL372_POWER_CTL_LPF_DIS_MODE(x) (((x) & 0x1) << 3)
|
||||
#define ADXL372_POWER_CTL_HPF_DIS_MSK BIT(2)
|
||||
#define ADXL372_POWER_CTL_HPF_DIS_MODE(x) (((x) & 0x1) << 2)
|
||||
#define ADXL372_POWER_CTL_MODE_MSK GENMASK(1, 0)
|
||||
#define ADXL372_POWER_CTL_MODE(x) (((x) & 0x3) << 0)
|
||||
|
||||
/* ADXL372_MEASURE */
|
||||
#define ADXL372_MEASURE_AUTOSLEEP_MSK BIT(6)
|
||||
#define ADXL372_MEASURE_AUTOSLEEP_MODE(x) (((x) & 0x1) << 6)
|
||||
#define ADXL372_MEASURE_LINKLOOP_MSK GENMASK(5, 4)
|
||||
#define ADXL372_MEASURE_LINKLOOP_MODE(x) (((x) & 0x3) << 4)
|
||||
#define ADXL372_MEASURE_LOW_NOISE_MSK BIT(3)
|
||||
#define ADXL372_MEASURE_LOW_NOISE_MODE(x) (((x) & 0x1) << 3)
|
||||
#define ADXL372_MEASURE_BANDWIDTH_MSK GENMASK(2, 0)
|
||||
#define ADXL372_MEASURE_BANDWIDTH_MODE(x) (((x) & 0x7) << 0)
|
||||
|
||||
/* ADXL372_TIMING */
|
||||
#define ADXL372_TIMING_ODR_MSK GENMASK(7, 5)
|
||||
#define ADXL372_TIMING_ODR_MODE(x) (((x) & 0x7) << 5)
|
||||
#define ADXL372_TIMING_WAKE_UP_RATE_MSK GENMASK(4, 2)
|
||||
#define ADXL372_TIMING_WAKE_UP_RATE_MODE(x) (((x) & 0x7) << 2)
|
||||
#define ADXL372_TIMING_EXT_CLK_MSK BIT(1)
|
||||
#define ADXL372_TIMING_EXT_CLK_MODE(x) (((x) & 0x1) << 1)
|
||||
#define ADXL372_TIMING_EXT_SYNC_MSK BIT(0)
|
||||
#define ADXL372_TIMING_EXT_SYNC_MODE(x) (((x) & 0x1) << 0)
|
||||
|
||||
/* ADXL372_FIFO_CTL */
|
||||
#define ADXL372_FIFO_CTL_FORMAT_MSK GENMASK(5, 3)
|
||||
#define ADXL372_FIFO_CTL_FORMAT_MODE(x) (((x) & 0x7) << 3)
|
||||
#define ADXL372_FIFO_CTL_MODE_MSK GENMASK(2, 1)
|
||||
#define ADXL372_FIFO_CTL_MODE_MODE(x) (((x) & 0x3) << 1)
|
||||
#define ADXL372_FIFO_CTL_SAMPLES_MSK BIT(0)
|
||||
#define ADXL372_FIFO_CTL_SAMPLES_MODE(x) (((x) > 0xFF) ? 1 : 0)
|
||||
|
||||
/* ADXL372_STATUS_1 */
|
||||
#define ADXL372_STATUS_1_DATA_RDY(x) (((x) >> 0) & 0x1)
|
||||
#define ADXL372_STATUS_1_FIFO_RDY(x) (((x) >> 1) & 0x1)
|
||||
#define ADXL372_STATUS_1_FIFO_FULL(x) (((x) >> 2) & 0x1)
|
||||
#define ADXL372_STATUS_1_FIFO_OVR(x) (((x) >> 3) & 0x1)
|
||||
#define ADXL372_STATUS_1_USR_NVM_BUSY(x) (((x) >> 5) & 0x1)
|
||||
#define ADXL372_STATUS_1_AWAKE(x) (((x) >> 6) & 0x1)
|
||||
#define ADXL372_STATUS_1_ERR_USR_REGS(x) (((x) >> 7) & 0x1)
|
||||
|
||||
/* ADXL372_STATUS_2 */
|
||||
#define ADXL372_STATUS_2_INACT(x) (((x) >> 4) & 0x1)
|
||||
#define ADXL372_STATUS_2_ACTIVITY(x) (((x) >> 5) & 0x1)
|
||||
#define ADXL372_STATUS_2_ACTIVITY2(x) (((x) >> 6) & 0x1)
|
||||
|
||||
/* ADXL372_INT1_MAP */
|
||||
#define ADXL372_INT1_MAP_DATA_RDY_MSK BIT(0)
|
||||
#define ADXL372_INT1_MAP_DATA_RDY_MODE(x) (((x) & 0x1) << 0)
|
||||
#define ADXL372_INT1_MAP_FIFO_RDY_MSK BIT(1)
|
||||
#define ADXL372_INT1_MAP_FIFO_RDY_MODE(x) (((x) & 0x1) << 1)
|
||||
#define ADXL372_INT1_MAP_FIFO_FULL_MSK BIT(2)
|
||||
#define ADXL372_INT1_MAP_FIFO_FULL_MODE(x) (((x) & 0x1) << 2)
|
||||
#define ADXL372_INT1_MAP_FIFO_OVR_MSK BIT(3)
|
||||
#define ADXL372_INT1_MAP_FIFO_OVR_MODE(x) (((x) & 0x1) << 3)
|
||||
#define ADXL372_INT1_MAP_INACT_MSK BIT(4)
|
||||
#define ADXL372_INT1_MAP_INACT_MODE(x) (((x) & 0x1) << 4)
|
||||
#define ADXL372_INT1_MAP_ACT_MSK BIT(5)
|
||||
#define ADXL372_INT1_MAP_ACT_MODE(x) (((x) & 0x1) << 5)
|
||||
#define ADXL372_INT1_MAP_AWAKE_MSK BIT(6)
|
||||
#define ADXL372_INT1_MAP_AWAKE_MODE(x) (((x) & 0x1) << 6)
|
||||
#define ADXL372_INT1_MAP_LOW_MSK BIT(7)
|
||||
#define ADXL372_INT1_MAP_LOW_MODE(x) (((x) & 0x1) << 7)
|
||||
|
||||
/* ADXL372_INT2_MAP */
|
||||
#define ADXL372_INT2_MAP_DATA_RDY_MSK BIT(0)
|
||||
#define ADXL372_INT2_MAP_DATA_RDY_MODE(x) (((x) & 0x1) << 0)
|
||||
#define ADXL372_INT2_MAP_FIFO_RDY_MSK BIT(1)
|
||||
#define ADXL372_INT2_MAP_FIFO_RDY_MODE(x) (((x) & 0x1) << 1)
|
||||
#define ADXL372_INT2_MAP_FIFO_FULL_MSK BIT(2)
|
||||
#define ADXL372_INT2_MAP_FIFO_FULL_MODE(x) (((x) & 0x1) << 2)
|
||||
#define ADXL372_INT2_MAP_FIFO_OVR_MSK BIT(3)
|
||||
#define ADXL372_INT2_MAP_FIFO_OVR_MODE(x) (((x) & 0x1) << 3)
|
||||
#define ADXL372_INT2_MAP_INACT_MSK BIT(4)
|
||||
#define ADXL372_INT2_MAP_INACT_MODE(x) (((x) & 0x1) << 4)
|
||||
#define ADXL372_INT2_MAP_ACT_MSK BIT(5)
|
||||
#define ADXL372_INT2_MAP_ACT_MODE(x) (((x) & 0x1) << 5)
|
||||
#define ADXL372_INT2_MAP_AWAKE_MSK BIT(6)
|
||||
#define ADXL372_INT2_MAP_AWAKE_MODE(x) (((x) & 0x1) << 6)
|
||||
#define ADXL372_INT2_MAP_LOW_MSK BIT(7)
|
||||
#define ADXL372_INT2_MAP_LOW_MODE(x) (((x) & 0x1) << 7)
|
||||
|
||||
/* ADXL372_HPF */
|
||||
#define ADXL372_HPF_CORNER(x) (((x) & 0x3) << 0)
|
||||
|
||||
enum adxl372_axis {
|
||||
ADXL372_X_AXIS,
|
||||
ADXL372_Y_AXIS,
|
||||
ADXL372_Z_AXIS
|
||||
};
|
||||
|
||||
enum adxl372_op_mode {
|
||||
ADXL372_STANDBY,
|
||||
ADXL372_WAKE_UP,
|
||||
ADXL372_INSTANT_ON,
|
||||
ADXL372_FULL_BW_MEASUREMENT
|
||||
};
|
||||
|
||||
enum adxl372_bandwidth {
|
||||
ADXL372_BW_200HZ,
|
||||
ADXL372_BW_400HZ,
|
||||
ADXL372_BW_800HZ,
|
||||
ADXL372_BW_1600HZ,
|
||||
ADXL372_BW_3200HZ,
|
||||
ADXL372_BW_LPF_DISABLED = 0xC,
|
||||
};
|
||||
|
||||
enum adxl372_hpf_corner {
|
||||
ADXL372_HPF_CORNER_0,
|
||||
ADXL372_HPF_CORNER_1,
|
||||
ADXL372_HPF_CORNER_2,
|
||||
ADXL372_HPF_CORNER_3,
|
||||
ADXL372_HPF_DISABLED,
|
||||
};
|
||||
|
||||
enum adxl372_act_proc_mode {
|
||||
ADXL372_DEFAULT,
|
||||
ADXL372_LINKED,
|
||||
ADXL372_LOOPED
|
||||
};
|
||||
|
||||
enum adxl372_odr {
|
||||
ADXL372_ODR_400HZ,
|
||||
ADXL372_ODR_800HZ,
|
||||
ADXL372_ODR_1600HZ,
|
||||
ADXL372_ODR_3200HZ,
|
||||
ADXL372_ODR_6400HZ
|
||||
};
|
||||
|
||||
enum adxl372_instant_on_th_mode {
|
||||
ADXL372_INSTANT_ON_LOW_TH,
|
||||
ADXL372_INSTANT_ON_HIGH_TH
|
||||
};
|
||||
|
||||
enum adxl372_wakeup_rate {
|
||||
ADXL372_WUR_52ms,
|
||||
ADXL372_WUR_104ms,
|
||||
ADXL372_WUR_208ms,
|
||||
ADXL372_WUR_512ms,
|
||||
ADXL372_WUR_2048ms,
|
||||
ADXL372_WUR_4096ms,
|
||||
ADXL372_WUR_8192ms,
|
||||
ADXL372_WUR_24576ms
|
||||
};
|
||||
|
||||
enum adxl372_filter_settle {
|
||||
ADXL372_FILTER_SETTLE_370,
|
||||
ADXL372_FILTER_SETTLE_16
|
||||
};
|
||||
|
||||
enum adxl372_fifo_format {
|
||||
ADXL372_XYZ_FIFO,
|
||||
ADXL372_X_FIFO,
|
||||
ADXL372_Y_FIFO,
|
||||
ADXL372_XY_FIFO,
|
||||
ADXL372_Z_FIFO,
|
||||
ADXL372_XZ_FIFO,
|
||||
ADXL372_YZ_FIFO,
|
||||
ADXL372_XYZ_PEAK_FIFO,
|
||||
};
|
||||
|
||||
enum adxl372_fifo_mode {
|
||||
ADXL372_FIFO_BYPASSED,
|
||||
ADXL372_FIFO_STREAMED,
|
||||
ADXL372_FIFO_TRIGGERED,
|
||||
ADXL372_FIFO_OLD_SAVED
|
||||
};
|
||||
|
||||
struct adxl372_fifo_config {
|
||||
enum adxl372_fifo_mode fifo_mode;
|
||||
enum adxl372_fifo_format fifo_format;
|
||||
uint16_t fifo_samples;
|
||||
};
|
||||
|
||||
struct adxl372_activity_threshold {
|
||||
uint16_t thresh;
|
||||
bool referenced;
|
||||
bool enable;
|
||||
};
|
||||
|
||||
struct adxl372_xyz_accel_data {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t z;
|
||||
};
|
||||
|
||||
struct adxl372_transfer_function {
|
||||
int (*read_reg_multiple)(const struct device *dev, uint8_t reg_addr,
|
||||
uint8_t *value, uint16_t len);
|
||||
int (*write_reg)(const struct device *dev, uint8_t reg_addr,
|
||||
uint8_t value);
|
||||
int (*read_reg)(const struct device *dev, uint8_t reg_addr,
|
||||
uint8_t *value);
|
||||
int (*write_reg_mask)(const struct device *dev, uint8_t reg_addr,
|
||||
uint32_t mask, uint8_t value);
|
||||
};
|
||||
|
||||
struct adxl372_data {
|
||||
struct adxl372_xyz_accel_data sample;
|
||||
const struct adxl372_transfer_function *hw_tf;
|
||||
struct adxl372_fifo_config fifo_config;
|
||||
enum adxl372_act_proc_mode act_proc_mode;
|
||||
#ifdef CONFIG_ADXL372_TRIGGER
|
||||
struct gpio_callback gpio_cb;
|
||||
|
||||
sensor_trigger_handler_t th_handler;
|
||||
const struct sensor_trigger *th_trigger;
|
||||
sensor_trigger_handler_t drdy_handler;
|
||||
const struct sensor_trigger *drdy_trigger;
|
||||
const struct device *dev;
|
||||
|
||||
#if defined(CONFIG_ADXL372_TRIGGER_OWN_THREAD)
|
||||
K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_ADXL372_THREAD_STACK_SIZE);
|
||||
struct k_sem gpio_sem;
|
||||
struct k_thread thread;
|
||||
#elif defined(CONFIG_ADXL372_TRIGGER_GLOBAL_THREAD)
|
||||
struct k_work work;
|
||||
#endif
|
||||
#endif /* CONFIG_ADXL372_TRIGGER */
|
||||
};
|
||||
|
||||
struct adxl372_dev_config {
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
|
||||
struct i2c_dt_spec i2c;
|
||||
#endif
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
|
||||
struct spi_dt_spec spi;
|
||||
#endif
|
||||
int (*bus_init)(const struct device *dev);
|
||||
#ifdef CONFIG_ADXL372_TRIGGER
|
||||
struct gpio_dt_spec interrupt;
|
||||
#endif
|
||||
|
||||
enum adxl372_bandwidth bw;
|
||||
enum adxl372_hpf_corner hpf;
|
||||
enum adxl372_odr odr;
|
||||
|
||||
bool max_peak_detect_mode;
|
||||
|
||||
/* Device Settings */
|
||||
bool autosleep;
|
||||
|
||||
struct adxl372_activity_threshold activity_th;
|
||||
struct adxl372_activity_threshold activity2_th;
|
||||
struct adxl372_activity_threshold inactivity_th;
|
||||
struct adxl372_fifo_config fifo_config;
|
||||
|
||||
enum adxl372_wakeup_rate wur;
|
||||
enum adxl372_instant_on_th_mode th_mode;
|
||||
enum adxl372_filter_settle filter_settle;
|
||||
enum adxl372_op_mode op_mode;
|
||||
|
||||
uint16_t inactivity_time;
|
||||
uint8_t activity_time;
|
||||
uint8_t int1_config;
|
||||
uint8_t int2_config;
|
||||
};
|
||||
|
||||
int adxl372_spi_init(const struct device *dev);
|
||||
int adxl372_i2c_init(const struct device *dev);
|
||||
|
||||
#ifdef CONFIG_ADXL372_TRIGGER
|
||||
int adxl372_get_status(const struct device *dev,
|
||||
uint8_t *status1, uint8_t *status2, uint16_t *fifo_entries);
|
||||
|
||||
int adxl372_trigger_set(const struct device *dev,
|
||||
const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler);
|
||||
|
||||
int adxl372_init_interrupt(const struct device *dev);
|
||||
#endif /* CONFIG_ADXL372_TRIGGER */
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_SENSOR_ADXL372_ADXL372_H_ */
|
104
drivers/sensor/adi/adxl372/adxl372_i2c.c
Normal file
104
drivers/sensor/adi/adxl372/adxl372_i2c.c
Normal file
|
@ -0,0 +1,104 @@
|
|||
/* adxl372_i2c.c - I2C routines for ADXL372 driver
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT adi_adxl372
|
||||
|
||||
#include <string.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "adxl372.h"
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
|
||||
|
||||
LOG_MODULE_DECLARE(ADXL372, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static int adxl372_bus_access(const struct device *dev, uint8_t reg,
|
||||
void *data, size_t length)
|
||||
{
|
||||
const struct adxl372_dev_config *config = dev->config;
|
||||
|
||||
if (reg & ADXL372_READ) {
|
||||
return i2c_burst_read_dt(&config->i2c,
|
||||
ADXL372_TO_I2C_REG(reg),
|
||||
(uint8_t *) data, length);
|
||||
} else {
|
||||
if (length != 1) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return i2c_reg_write_byte_dt(&config->i2c,
|
||||
ADXL372_TO_I2C_REG(reg),
|
||||
*(uint8_t *)data);
|
||||
}
|
||||
}
|
||||
|
||||
static int adxl372_i2c_reg_read(const struct device *dev, uint8_t reg_addr,
|
||||
uint8_t *reg_data)
|
||||
{
|
||||
return adxl372_bus_access(dev, ADXL372_REG_READ(reg_addr), reg_data, 1);
|
||||
}
|
||||
|
||||
static int adxl372_i2c_reg_read_multiple(const struct device *dev,
|
||||
uint8_t reg_addr,
|
||||
uint8_t *reg_data,
|
||||
uint16_t count)
|
||||
{
|
||||
return adxl372_bus_access(dev, ADXL372_REG_READ(reg_addr),
|
||||
reg_data, count);
|
||||
}
|
||||
|
||||
static int adxl372_i2c_reg_write(const struct device *dev,
|
||||
uint8_t reg_addr,
|
||||
uint8_t reg_data)
|
||||
{
|
||||
return adxl372_bus_access(dev, ADXL372_REG_WRITE(reg_addr),
|
||||
®_data, 1);
|
||||
}
|
||||
|
||||
|
||||
int adxl372_i2c_reg_write_mask(const struct device *dev,
|
||||
uint8_t reg_addr,
|
||||
uint32_t mask,
|
||||
uint8_t data)
|
||||
{
|
||||
int ret;
|
||||
uint8_t tmp;
|
||||
|
||||
ret = adxl372_i2c_reg_read(dev, reg_addr, &tmp);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
tmp &= ~mask;
|
||||
tmp |= data;
|
||||
|
||||
return adxl372_i2c_reg_write(dev, reg_addr, tmp);
|
||||
}
|
||||
|
||||
static const struct adxl372_transfer_function adxl372_i2c_transfer_fn = {
|
||||
.read_reg_multiple = adxl372_i2c_reg_read_multiple,
|
||||
.write_reg = adxl372_i2c_reg_write,
|
||||
.read_reg = adxl372_i2c_reg_read,
|
||||
.write_reg_mask = adxl372_i2c_reg_write_mask,
|
||||
};
|
||||
|
||||
int adxl372_i2c_init(const struct device *dev)
|
||||
{
|
||||
struct adxl372_data *data = dev->data;
|
||||
const struct adxl372_dev_config *config = dev->config;
|
||||
|
||||
data->hw_tf = &adxl372_i2c_transfer_fn;
|
||||
|
||||
if (!device_is_ready(config->i2c.bus)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */
|
119
drivers/sensor/adi/adxl372/adxl372_spi.c
Normal file
119
drivers/sensor/adi/adxl372/adxl372_spi.c
Normal file
|
@ -0,0 +1,119 @@
|
|||
/* adxl372_spi.c - SPI routines for ADXL372 driver
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2022 Analog Devices
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT adi_adxl372
|
||||
|
||||
#include <string.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "adxl372.h"
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
|
||||
|
||||
LOG_MODULE_DECLARE(ADXL372, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static int adxl372_bus_access(const struct device *dev, uint8_t reg,
|
||||
void *data, size_t length)
|
||||
{
|
||||
const struct adxl372_dev_config *config = dev->config;
|
||||
|
||||
const struct spi_buf buf[2] = {
|
||||
{
|
||||
.buf = ®,
|
||||
.len = 1
|
||||
}, {
|
||||
.buf = data,
|
||||
.len = length
|
||||
}
|
||||
};
|
||||
|
||||
struct spi_buf_set tx = {
|
||||
.buffers = buf,
|
||||
};
|
||||
|
||||
if (reg & ADXL372_READ) {
|
||||
const struct spi_buf_set rx = {
|
||||
.buffers = buf,
|
||||
.count = 2
|
||||
};
|
||||
|
||||
tx.count = 1;
|
||||
|
||||
return spi_transceive_dt(&config->spi, &tx, &rx);
|
||||
}
|
||||
|
||||
tx.count = 2;
|
||||
|
||||
return spi_write_dt(&config->spi, &tx);
|
||||
}
|
||||
|
||||
static int adxl372_spi_reg_read(const struct device *dev, uint8_t reg_addr,
|
||||
uint8_t *reg_data)
|
||||
{
|
||||
return adxl372_bus_access(dev, ADXL372_REG_READ(reg_addr), reg_data, 1);
|
||||
}
|
||||
|
||||
static int adxl372_spi_reg_read_multiple(const struct device *dev,
|
||||
uint8_t reg_addr,
|
||||
uint8_t *reg_data,
|
||||
uint16_t count)
|
||||
{
|
||||
return adxl372_bus_access(dev, ADXL372_REG_READ(reg_addr),
|
||||
reg_data, count);
|
||||
}
|
||||
|
||||
static int adxl372_spi_reg_write(const struct device *dev,
|
||||
uint8_t reg_addr,
|
||||
uint8_t reg_data)
|
||||
{
|
||||
return adxl372_bus_access(dev, ADXL372_REG_WRITE(reg_addr),
|
||||
®_data, 1);
|
||||
}
|
||||
|
||||
int adxl372_spi_reg_write_mask(const struct device *dev,
|
||||
uint8_t reg_addr,
|
||||
uint32_t mask,
|
||||
uint8_t data)
|
||||
{
|
||||
int ret;
|
||||
uint8_t tmp;
|
||||
|
||||
ret = adxl372_spi_reg_read(dev, reg_addr, &tmp);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
tmp &= ~mask;
|
||||
tmp |= data;
|
||||
|
||||
return adxl372_spi_reg_write(dev, reg_addr, tmp);
|
||||
}
|
||||
|
||||
static const struct adxl372_transfer_function adxl372_spi_transfer_fn = {
|
||||
.read_reg_multiple = adxl372_spi_reg_read_multiple,
|
||||
.write_reg = adxl372_spi_reg_write,
|
||||
.read_reg = adxl372_spi_reg_read,
|
||||
.write_reg_mask = adxl372_spi_reg_write_mask,
|
||||
};
|
||||
|
||||
int adxl372_spi_init(const struct device *dev)
|
||||
{
|
||||
struct adxl372_data *data = dev->data;
|
||||
const struct adxl372_dev_config *config = dev->config;
|
||||
|
||||
data->hw_tf = &adxl372_spi_transfer_fn;
|
||||
|
||||
if (!spi_is_ready_dt(&config->spi)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */
|
193
drivers/sensor/adi/adxl372/adxl372_trigger.c
Normal file
193
drivers/sensor/adi/adxl372/adxl372_trigger.c
Normal file
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Analog Devices Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT adi_adxl372
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
#include "adxl372.h"
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_DECLARE(ADXL372, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static void adxl372_thread_cb(const struct device *dev)
|
||||
{
|
||||
const struct adxl372_dev_config *cfg = dev->config;
|
||||
struct adxl372_data *drv_data = dev->data;
|
||||
uint8_t status1, status2;
|
||||
int ret;
|
||||
|
||||
/* Clear the status */
|
||||
if (adxl372_get_status(dev, &status1, &status2, NULL) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (drv_data->th_handler != NULL) {
|
||||
/* In max peak mode we wait until we settle below the inactivity
|
||||
* threshold and then call the trigger handler.
|
||||
*/
|
||||
if (cfg->max_peak_detect_mode &&
|
||||
ADXL372_STATUS_2_INACT(status2)) {
|
||||
drv_data->th_handler(dev, drv_data->th_trigger);
|
||||
} else if (!cfg->max_peak_detect_mode &&
|
||||
(ADXL372_STATUS_2_INACT(status2) ||
|
||||
ADXL372_STATUS_2_ACTIVITY(status2))) {
|
||||
drv_data->th_handler(dev, drv_data->th_trigger);
|
||||
}
|
||||
}
|
||||
|
||||
if ((drv_data->drdy_handler != NULL) &&
|
||||
ADXL372_STATUS_1_DATA_RDY(status1)) {
|
||||
drv_data->drdy_handler(dev, drv_data->drdy_trigger);
|
||||
}
|
||||
|
||||
ret = gpio_pin_interrupt_configure_dt(&cfg->interrupt,
|
||||
GPIO_INT_EDGE_TO_ACTIVE);
|
||||
__ASSERT(ret == 0, "Interrupt configuration failed");
|
||||
}
|
||||
|
||||
static void adxl372_gpio_callback(const struct device *dev,
|
||||
struct gpio_callback *cb, uint32_t pins)
|
||||
{
|
||||
struct adxl372_data *drv_data =
|
||||
CONTAINER_OF(cb, struct adxl372_data, gpio_cb);
|
||||
const struct adxl372_dev_config *cfg = drv_data->dev->config;
|
||||
|
||||
gpio_pin_interrupt_configure_dt(&cfg->interrupt, GPIO_INT_DISABLE);
|
||||
|
||||
#if defined(CONFIG_ADXL372_TRIGGER_OWN_THREAD)
|
||||
k_sem_give(&drv_data->gpio_sem);
|
||||
#elif defined(CONFIG_ADXL372_TRIGGER_GLOBAL_THREAD)
|
||||
k_work_submit(&drv_data->work);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ADXL372_TRIGGER_OWN_THREAD)
|
||||
static void adxl372_thread(void *p1, void *p2, void *p3)
|
||||
{
|
||||
ARG_UNUSED(p2);
|
||||
ARG_UNUSED(p3);
|
||||
|
||||
struct adxl372_data *drv_data = p1;
|
||||
|
||||
while (true) {
|
||||
k_sem_take(&drv_data->gpio_sem, K_FOREVER);
|
||||
adxl372_thread_cb(drv_data->dev);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_ADXL372_TRIGGER_GLOBAL_THREAD)
|
||||
static void adxl372_work_cb(struct k_work *work)
|
||||
{
|
||||
struct adxl372_data *drv_data =
|
||||
CONTAINER_OF(work, struct adxl372_data, work);
|
||||
|
||||
adxl372_thread_cb(drv_data->dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
int adxl372_trigger_set(const struct device *dev,
|
||||
const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler)
|
||||
{
|
||||
const struct adxl372_dev_config *cfg = dev->config;
|
||||
struct adxl372_data *drv_data = dev->data;
|
||||
uint8_t int_mask, int_en, status1, status2;
|
||||
int ret;
|
||||
|
||||
ret = gpio_pin_interrupt_configure_dt(&cfg->interrupt,
|
||||
GPIO_INT_DISABLE);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (trig->type) {
|
||||
case SENSOR_TRIG_THRESHOLD:
|
||||
drv_data->th_handler = handler;
|
||||
drv_data->th_trigger = trig;
|
||||
int_mask = ADXL372_INT1_MAP_ACT_MSK |
|
||||
ADXL372_INT1_MAP_INACT_MSK;
|
||||
break;
|
||||
case SENSOR_TRIG_DATA_READY:
|
||||
drv_data->drdy_handler = handler;
|
||||
drv_data->drdy_trigger = trig;
|
||||
int_mask = ADXL372_INT1_MAP_DATA_RDY_MSK;
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Unsupported sensor trigger");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (handler) {
|
||||
int_en = int_mask;
|
||||
} else {
|
||||
int_en = 0U;
|
||||
}
|
||||
|
||||
ret = drv_data->hw_tf->write_reg_mask(dev, ADXL372_INT1_MAP, int_mask, int_en);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adxl372_get_status(dev, &status1, &status2, NULL); /* Clear status */
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpio_pin_interrupt_configure_dt(&cfg->interrupt,
|
||||
GPIO_INT_EDGE_TO_ACTIVE);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int adxl372_init_interrupt(const struct device *dev)
|
||||
{
|
||||
const struct adxl372_dev_config *cfg = dev->config;
|
||||
struct adxl372_data *drv_data = dev->data;
|
||||
int ret;
|
||||
|
||||
if (!gpio_is_ready_dt(&cfg->interrupt)) {
|
||||
LOG_ERR("GPIO port %s not ready", cfg->interrupt.port->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = gpio_pin_configure_dt(&cfg->interrupt, GPIO_INPUT);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpio_init_callback(&drv_data->gpio_cb,
|
||||
adxl372_gpio_callback,
|
||||
BIT(cfg->interrupt.pin));
|
||||
|
||||
ret = gpio_add_callback(cfg->interrupt.port, &drv_data->gpio_cb);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to set gpio callback!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
drv_data->dev = dev;
|
||||
|
||||
#if defined(CONFIG_ADXL372_TRIGGER_OWN_THREAD)
|
||||
k_sem_init(&drv_data->gpio_sem, 0, K_SEM_MAX_LIMIT);
|
||||
|
||||
k_thread_create(&drv_data->thread, drv_data->thread_stack,
|
||||
CONFIG_ADXL372_THREAD_STACK_SIZE,
|
||||
adxl372_thread, drv_data,
|
||||
NULL, NULL, K_PRIO_COOP(CONFIG_ADXL372_THREAD_PRIORITY),
|
||||
0, K_NO_WAIT);
|
||||
#elif defined(CONFIG_ADXL372_TRIGGER_GLOBAL_THREAD)
|
||||
drv_data->work.handler = adxl372_work_cb;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue