mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #15871 from jan-mo/feat/20210120_lis2dh12_extension
driver_lis2dh12: functionality extension
This commit is contained in:
commit
753c833109
@ -39,6 +39,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "saul.h"
|
||||
#include "lis2dh12_registers.h"
|
||||
|
||||
#include "periph/gpio.h"
|
||||
#ifdef MODULE_LIS2DH12_SPI
|
||||
@ -71,19 +72,31 @@ typedef enum {
|
||||
/**
|
||||
* @brief Available sampling rates
|
||||
*
|
||||
* @note The device does also support some additional rates for specific low-
|
||||
* power modes, but those are as of now not supported by this driver
|
||||
*/
|
||||
typedef enum {
|
||||
LIS2DH12_RATE_1HZ = 0x17, /**< sample with 1Hz */
|
||||
LIS2DH12_RATE_10HZ = 0x27, /**< sample with 10Hz */
|
||||
LIS2DH12_RATE_25HZ = 0x37, /**< sample with 25Hz */
|
||||
LIS2DH12_RATE_50HZ = 0x47, /**< sample with 50Hz */
|
||||
LIS2DH12_RATE_100HZ = 0x57, /**< sample with 100Hz */
|
||||
LIS2DH12_RATE_200HZ = 0x67, /**< sample with 200Hz */
|
||||
LIS2DH12_RATE_400HZ = 0x77, /**< sample with 400Hz */
|
||||
LIS2DH12_RATE_1HZ = 0x1, /**< sample with 1Hz @ all power modes */
|
||||
LIS2DH12_RATE_10HZ = 0x2, /**< sample with 10Hz @ all power modes */
|
||||
LIS2DH12_RATE_25HZ = 0x3, /**< sample with 25Hz @ all power modes */
|
||||
LIS2DH12_RATE_50HZ = 0x4, /**< sample with 50Hz @ all power modes */
|
||||
LIS2DH12_RATE_100HZ = 0x5, /**< sample with 100Hz @ all power modes */
|
||||
LIS2DH12_RATE_200HZ = 0x6, /**< sample with 200Hz @ all power modes */
|
||||
LIS2DH12_RATE_400HZ = 0x7, /**< sample with 400Hz @ all power modes */
|
||||
LIS2DH12_RATE_1620HZ = 0x8, /**< sample with 1620HZ @ Low Power*/
|
||||
LIS2DH12_RATE_VERYHIGH = 0x9, /**< sample with 1344Hz @ High resolution or \
|
||||
5376Hz @ Low Power*/
|
||||
} lis2dh12_rate_t;
|
||||
|
||||
/**
|
||||
* @brief Available power modes
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
LIS2DH12_POWER_DOWN = 0, /**< power down the device */
|
||||
LIS2DH12_POWER_LOW = 1, /**< low power mode */
|
||||
LIS2DH12_POWER_NORMAL = 2, /**< normal mode */
|
||||
LIS2DH12_POWER_HIGH = 3, /**< high resolution */
|
||||
} lis2dh12_powermode_t;
|
||||
|
||||
/**
|
||||
* @brief LIS2DH12 configuration parameters
|
||||
*/
|
||||
@ -101,14 +114,63 @@ typedef struct {
|
||||
#endif
|
||||
lis2dh12_scale_t scale; /**< sampling sensitivity used */
|
||||
lis2dh12_rate_t rate; /**< sampling rate used */
|
||||
lis2dh12_powermode_t powermode; /**< power mode used*/
|
||||
} lis2dh12_params_t;
|
||||
|
||||
/**
|
||||
* @brief LIS2DH12 high pass modes
|
||||
*/
|
||||
typedef enum {
|
||||
LIS2DH12_HP_MODE_NORMAL = 0x0, /**< normal mode, reset by reading REG_REFERENCE */
|
||||
LIS2DH12_HP_MODE_REFERENCE = 0x1, /**< uses the reference signal for filtering */
|
||||
LIS2DH12_HP_MODE_AUTORESET = 0x3, /**< automatically resets on interrupt generation */
|
||||
} lis2dh12_hp_mode_t;
|
||||
|
||||
/**
|
||||
* @brief LIS2DH12 high pass cutoff frequency
|
||||
*/
|
||||
typedef enum {
|
||||
LIS2DH12_HP_FREQ_DIV50 = 0, /**< cutoff freq is ODR divided by 50 */
|
||||
LIS2DH12_HP_FREQ_DIV100 = 1, /**< cutoff freq is ODR divided by 100 */
|
||||
LIS2DH12_HP_FREQ_DIV200 = 2, /**< cutoff freq is ODR divided by 200 */
|
||||
LIS2DH12_HP_FREQ_DIV400 = 3, /**< cutoff freq is ODR divided by 400 */
|
||||
} lis2dh12_hp_freq_t;
|
||||
|
||||
/**
|
||||
* @brief LIS2DH12 high pass config values
|
||||
*/
|
||||
typedef struct {
|
||||
lis2dh12_hp_mode_t Highpass_mode; /**< set the High pass mode */
|
||||
lis2dh12_hp_freq_t Highpass_freq; /**< set the High pass cutoff frequency \
|
||||
related to device rate */
|
||||
bool CLICK_enable; /**< enables filter for click data */
|
||||
bool INT1_enable; /**< enables filter for AOI on interrupt 1 */
|
||||
bool INT2_enable; /**< enables filter for AOI on interrupt 2 */
|
||||
bool DATA_OUT_enable; /**< enables filter for data output */
|
||||
} lis2dh12_highpass_t;
|
||||
|
||||
/**
|
||||
* @brief LIS2DH12 click config values
|
||||
*/
|
||||
typedef struct {
|
||||
bool enable_DOUBLE; /**< otherwise single click for given axis are enabled */
|
||||
bool enable_X_CLICK; /**< enable double pr single click for X axes */
|
||||
bool enable_Y_CLICK; /**< enable double pr single click for Y axes */
|
||||
bool enable_Z_CLICK; /**< enable double pr single click for Z axes */
|
||||
bool noINT_latency; /**< if "0" interrupt stays high for TIME_latency setting \
|
||||
if "1" interrupt stays high until CLICK_SRC is read */
|
||||
uint8_t CLICK_thold:7; /**< set click threshold */
|
||||
uint8_t TIME_limit:7; /**< set number of ODR cycles for time limit over threshold value */
|
||||
uint8_t TIME_latency; /**< set number of ODR cycles for latency after a click */
|
||||
uint8_t TIME_window; /**< set number of ODR cycles for window between clicks */
|
||||
} lis2dh12_click_t;
|
||||
|
||||
/**
|
||||
* @brief LIS2DH12 device descriptor
|
||||
*/
|
||||
typedef struct {
|
||||
const lis2dh12_params_t *p; /**< device configuration */
|
||||
uint16_t comp; /**< scale compensation factor */
|
||||
uint8_t comp; /**< scale compensation factor */
|
||||
} lis2dh12_t;
|
||||
|
||||
/**
|
||||
@ -118,7 +180,8 @@ enum {
|
||||
LIS2DH12_OK = 0, /**< everything was fine */
|
||||
LIS2DH12_NOBUS = -1, /**< bus interface error */
|
||||
LIS2DH12_NODEV = -2, /**< unable to talk to device */
|
||||
LIS2DH12_NOINT = -3, /**< wrong interrupt line (has to be LIS2DH12_INT1 or LIS2DH12_INT2) */
|
||||
LIS2DH12_NOINT = -3, /**< wrong interrupt line (has to be LIS2DH12_INT1
|
||||
or LIS2DH12_INT2) */
|
||||
LIS2DH12_NODATA= -4, /**< no data available */
|
||||
};
|
||||
|
||||
@ -126,81 +189,53 @@ enum {
|
||||
/*
|
||||
* @brief Interrupt lines
|
||||
*/
|
||||
enum{
|
||||
enum {
|
||||
LIS2DH12_INT1 = 1, /**< first interrupt line */
|
||||
LIS2DH12_INT2 = 2, /**< second interrupt line */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interrupt config register values
|
||||
*/
|
||||
enum {
|
||||
LIS2DH12_INT_CFG_XLIE = 0x01, /**< enable X low evnt */
|
||||
LIS2DH12_INT_CFG_XHIE = 0x02, /**< enable X high event */
|
||||
LIS2DH12_INT_CFG_YLIE = 0x04, /**< enable Y low event */
|
||||
LIS2DH12_INT_CFG_YHIE = 0x08, /**< enable Y high event */
|
||||
LIS2DH12_INT_CFG_ZLIE = 0x10, /**< enable Z low event */
|
||||
LIS2DH12_INT_CFG_ZHIE = 0x20, /**< enable Z high event */
|
||||
LIS2DH12_INT_CFG_6D = 0x40, /**< enable 6-direction detection */
|
||||
LIS2DH12_INT_CFG_AOI = 0x80, /**< and/or combination interrupt events */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interrupt type values
|
||||
*/
|
||||
enum {
|
||||
/* for interrupt 1 (CTRL_REG3) */
|
||||
LIS2DH12_INT_TYPE_I1_OVERRUN = 0x02, /**< FIFO overrun interrupt on INT1 */
|
||||
LIS2DH12_INT_TYPE_I1_WTM = 0x04, /**< FIFO watermark inter. on INT1 */
|
||||
LIS2DH12_INT_TYPE_I1_ZYXDA = 0x10, /**< ZYXDA interrupt on INT1 */
|
||||
LIS2DH12_INT_TYPE_I1_IA2 = 0x20, /**< IA2 interrupt on INT1 */
|
||||
LIS2DH12_INT_TYPE_I1_IA1 = 0x40, /**< IA1 interrupt on INT1 */
|
||||
LIS2DH12_INT_TYPE_I1_CLICK = 0x80, /**< click interrupt on INT1 */
|
||||
|
||||
/* for interrupt 2 (CTRL_REG6) */
|
||||
LIS2DH12_INT_TYPE_INT_POLARITY = 0x02, /**< INT1 and INT2 pin polarity */
|
||||
LIS2DH12_INT_TYPE_I2_ACT = 0x08, /**< enable activity interrupt on INT2 */
|
||||
LIS2DH12_INT_TYPE_I2_BOOT = 0x10, /**< enable boot on INT2 */
|
||||
LIS2DH12_INT_TYPE_I2_IA2 = 0x20, /**< IA2 on INT2 */
|
||||
LIS2DH12_INT_TYPE_I2_IA1 = 0x40, /**< IA1 on INT2 */
|
||||
LIS2DH12_INT_TYPE_I2_CLICK = 0x80, /**< click interrupt on INT2 */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Parameter for interrupt configuration
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t int_config; /**< values for configuration */
|
||||
uint8_t int_threshold:7; /**< the threshold for triggering interrupt, threshold in range 0-127 */
|
||||
uint8_t int_duration:7; /**< time between two interrupts ODR section in CTRL_REG1, duration in range 0-127 */
|
||||
uint8_t int_threshold:7; /**< the threshold for triggering interrupt,
|
||||
threshold in range 0-127 */
|
||||
uint8_t int_duration:7; /**< time between two interrupts ODR section in CTRL_REG1,
|
||||
duration in range 0-127 */
|
||||
uint8_t int_type; /**< values for type of interrupts */
|
||||
gpio_cb_t cb; /**< the callback to execute */
|
||||
void *arg; /**< the callback argument */
|
||||
} lis2dh12_int_params_t;
|
||||
|
||||
/**
|
||||
* @brief Status of INT_SRC register
|
||||
*/
|
||||
#define LIS2DH12_INT_SRC_XL (0x01) /**< X low event has occurred */
|
||||
#define LIS2DH12_INT_SRC_XH (0x02) /**< X high event has occurred */
|
||||
#define LIS2DH12_INT_SRC_YL (0x04) /**< Y low event has occurred */
|
||||
#define LIS2DH12_INT_SRC_YH (0x08) /**< Y high event has occurred */
|
||||
#define LIS2DH12_INT_SRC_ZL (0x10) /**< Z low event has occurred */
|
||||
#define LIS2DH12_INT_SRC_ZH (0x20) /**< Z high event has occurred */
|
||||
#define LIS2DH12_INT_SRC_IA (0x40) /**< 1 if interrupt occurred */
|
||||
#endif /* MODULE_LIS2DH12_INT */
|
||||
|
||||
/**
|
||||
* @brief Status of INT_SRC register
|
||||
* @brief LIS2DH12 FIFO data struct
|
||||
*/
|
||||
#define LIS2DH12_STATUS_XDA (0x01) /**< X-axis new data available */
|
||||
#define LIS2DH12_STATUS_YDA (0x02) /**< Y-axis new data available */
|
||||
#define LIS2DH12_STATUS_ZDA (0x04) /**< Z-axis new data available */
|
||||
#define LIS2DH12_STATUS_ZYXDA (0x08) /**< on X-, Y-, Z-axis new data available */
|
||||
#define LIS2DH12_STATUS_XOR (0x10) /**< X-axis data overrun */
|
||||
#define LIS2DH12_STATUS_YOR (0x20) /**< Y-axis data overrun */
|
||||
#define LIS2DH12_STATUS_ZOR (0x40) /**< Y-axis data overrun */
|
||||
#define LIS2DH12_STATUS_ZYXOR (0x80) /**< on X-, Y-, Z-axis data overrun */
|
||||
typedef struct {
|
||||
int16_t X_AXIS; /**< X raw data in FIFO */
|
||||
int16_t Y_AXIS; /**< Y raw data in FIFO */
|
||||
int16_t Z_AXIS; /**< Z raw data in FIFO */
|
||||
} lis2dh12_fifo_data_t;
|
||||
|
||||
/**
|
||||
* @brief LIS2DH12 FIFO modes
|
||||
*/
|
||||
typedef enum {
|
||||
LIS2DH12_FIFO_MODE_BYPASS = 0, /**< default mode, FIFO is bypassed */
|
||||
LIS2DH12_FIFO_MODE_FIFOMODE, /**< normal FIFO mode, stops if FIFO is full */
|
||||
LIS2DH12_FIFO_MODE_STREAM, /**< Stream mode, oldest values get overwritten */
|
||||
LIS2DH12_FIFO_MODE_STREAMtoFIFO, /**< Stream mode and on interrupt jumps to FIFO mode */
|
||||
} lis2dh12_fifo_mode_t;
|
||||
|
||||
/**
|
||||
* @brief LIS2DH12 FIFO config values
|
||||
*/
|
||||
typedef struct {
|
||||
lis2dh12_fifo_mode_t FIFO_mode; /**< set FIFO mode */
|
||||
uint8_t FIFO_watermark:5; /**< set the FIFO watermark level */
|
||||
bool FIFO_set_INT2; /**< sets the FIFO interrupt to INT2, otherwise INT1 */
|
||||
} lis2dh12_fifo_t;
|
||||
|
||||
/**
|
||||
* @brief Export the SAUL interface for this driver
|
||||
@ -233,6 +268,52 @@ int lis2dh12_set_int(const lis2dh12_t *dev, const lis2dh12_int_params_t *params,
|
||||
int lis2dh12_read_int_src(const lis2dh12_t *dev, uint8_t *data, uint8_t int_line);
|
||||
#endif /* MODULE_LIS2DH12_INT */
|
||||
|
||||
/**
|
||||
* @brief Set the FIFO configuration
|
||||
*
|
||||
* @param[in] dev device descriptor
|
||||
* @param[in] config device FIFO configuration
|
||||
*
|
||||
* @return LIS2DH12_OK on success
|
||||
*/
|
||||
int lis2dh12_set_fifo(const lis2dh12_t *dev, const lis2dh12_fifo_t *config);
|
||||
|
||||
/**
|
||||
* @brief Restart the FIFO mode
|
||||
* this sets the FIFO mode in BYPASS mode and then back to previous mode
|
||||
* Note: The LIS module disables the FIFO after interrupt automatically,
|
||||
* it is recommended to set the FIFO in BYPASS mode and then back to old
|
||||
* FIFO mode to enable the FIFO again.
|
||||
*
|
||||
* @param[in] dev device descriptor
|
||||
*
|
||||
* @return LIS2DH12_OK on success
|
||||
*/
|
||||
int lis2dh12_restart_fifo(const lis2dh12_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Read the FIFO source register
|
||||
*
|
||||
* @param[in] dev device descriptor
|
||||
* @param[out] data LIS2DH12_FIFO_SRC_REG_t content, allocate one byte
|
||||
*
|
||||
* @return LIS2DH12_OK on success
|
||||
*/
|
||||
int lis2dh12_read_fifo_src(const lis2dh12_t *dev, LIS2DH12_FIFO_SRC_REG_t *data);
|
||||
|
||||
/**
|
||||
* @brief This function will read a given number of data from FIFO
|
||||
* reads amount of data that is available in FIFO
|
||||
*
|
||||
* @param[in] dev device descriptor
|
||||
* @param[out] fifo_data FIFO data, must have space for number of data
|
||||
* @param[in] number amount of FIFO data to be read
|
||||
*
|
||||
* @return number of valid data read from FIFO
|
||||
*/
|
||||
uint8_t lis2dh12_read_fifo_data(const lis2dh12_t *dev, lis2dh12_fifo_data_t *fifo_data,
|
||||
uint8_t number);
|
||||
|
||||
/**
|
||||
* @brief Initialize the given LIS2DH12 sensor device
|
||||
*
|
||||
@ -257,7 +338,100 @@ int lis2dh12_init(lis2dh12_t *dev, const lis2dh12_params_t *params);
|
||||
int lis2dh12_read(const lis2dh12_t *dev, int16_t *data);
|
||||
|
||||
/**
|
||||
* @brief Power on the given device
|
||||
* @brief Clear the LIS2DH12 memory, clears all sampled data
|
||||
*
|
||||
* @param[in] dev device descriptor
|
||||
*
|
||||
* @return LIS2DH12_OK on success
|
||||
*/
|
||||
int lis2dh12_clear_data(const lis2dh12_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Change device scale value
|
||||
*
|
||||
* @param[in] dev device descriptor
|
||||
* @param[in] scale change to given scale value
|
||||
*
|
||||
* @return LIS2DH12_OK on success
|
||||
*/
|
||||
int lis2dh12_set_scale(lis2dh12_t *dev, lis2dh12_scale_t scale);
|
||||
|
||||
/**
|
||||
* @brief Change device sampling rate
|
||||
*
|
||||
* @param[in] dev device descriptor
|
||||
* @param[in] rate change to given sampling rate
|
||||
*
|
||||
* @return LIS2DH12_OK on success
|
||||
*/
|
||||
int lis2dh12_set_datarate(const lis2dh12_t *dev, lis2dh12_rate_t rate);
|
||||
|
||||
/**
|
||||
* @brief Change device power mode
|
||||
*
|
||||
* @param[in] dev device descriptor
|
||||
* @param[in] powermode change to given power mode
|
||||
*
|
||||
* @return LIS2DH12_OK on success
|
||||
*/
|
||||
int lis2dh12_set_powermode(const lis2dh12_t *dev, lis2dh12_powermode_t powermode);
|
||||
|
||||
/**
|
||||
* @brief Configures the high pass filter
|
||||
*
|
||||
* @param[in] dev device descriptor
|
||||
* @param[in] config device high pass configuration
|
||||
*
|
||||
* @return LIS2DH12_OK on success
|
||||
*/
|
||||
int lis2dh12_set_highpass(const lis2dh12_t *dev, const lis2dh12_highpass_t *config);
|
||||
|
||||
/**
|
||||
* @brief Set the reference value to control the high-pass reference.
|
||||
* In LIS2DH12_HP_MODE_REFERENCE the reference value is used to filter data
|
||||
* on all axis. Subtracts reference value from acceleration.
|
||||
* Note: LSB changes according to LIS2DH12_SCALE
|
||||
*
|
||||
* @param[in] dev device descriptor
|
||||
* @param[in] reference reference value [8 Bit]
|
||||
*
|
||||
* @return LIS2DH12_OK on success
|
||||
*/
|
||||
int lis2dh12_set_reference(const lis2dh12_t *dev, uint8_t reference);
|
||||
|
||||
/**
|
||||
* @brief Read the reference value
|
||||
*
|
||||
* @param[in] dev device descriptor
|
||||
* @param[out] data reference value read from device
|
||||
*
|
||||
* @return LIS2DH12_OK on success
|
||||
*/
|
||||
int lis2dh12_read_reference(const lis2dh12_t *dev, uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief Set click configuration
|
||||
*
|
||||
* @param[in] dev device descriptor
|
||||
* @param[in] config device click configuration
|
||||
*
|
||||
* @return LIS2DH12_OK on success
|
||||
*/
|
||||
int lis2dh12_set_click(const lis2dh12_t *dev, const lis2dh12_click_t *config);
|
||||
|
||||
/**
|
||||
* @brief Read click source register
|
||||
*
|
||||
* @param[in] dev device descriptor
|
||||
* @param[out] data LIS2DH12_CLICK_SRC_t content, allocate one byte
|
||||
*
|
||||
* @return LIS2DH12_OK on success
|
||||
*/
|
||||
int lis2dh12_read_click_src(const lis2dh12_t *dev, LIS2DH12_CLICK_SRC_t *data);
|
||||
|
||||
/**
|
||||
* @brief Power on the given device and resets power mode and sampling rate
|
||||
* to default values in the device descriptor parameters
|
||||
*
|
||||
* @param[in] dev device descriptor
|
||||
*
|
||||
|
@ -67,6 +67,9 @@ extern "C" {
|
||||
#ifndef LIS2DH12_PARAM_RATE
|
||||
#define LIS2DH12_PARAM_RATE LIS2DH12_RATE_100HZ
|
||||
#endif
|
||||
#ifndef LIS2DH12_PARAM_POWERMODE
|
||||
#define LIS2DH12_PARAM_POWERMODE LIS2DH12_POWER_NORMAL
|
||||
#endif
|
||||
|
||||
#ifndef LIS2DH12_PARAMS
|
||||
#ifdef MODULE_LIS2DH12_INT
|
||||
@ -76,12 +79,14 @@ extern "C" {
|
||||
.int2_pin = LIS2DH12_PARAM_INT_PIN2, \
|
||||
.scale = LIS2DH12_PARAM_SCALE, \
|
||||
.rate = LIS2DH12_PARAM_RATE, \
|
||||
.powermode = LIS2DH12_PARAM_POWERMODE, \
|
||||
}
|
||||
#else /* MODULE_LIS2DH12_INT */
|
||||
#define LIS2DH12_PARAMS { \
|
||||
LIS2DH12_PARAMS_BUSCFG, \
|
||||
.scale = LIS2DH12_PARAM_SCALE, \
|
||||
.rate = LIS2DH12_PARAM_RATE, \
|
||||
.powermode = LIS2DH12_PARAM_POWERMODE, \
|
||||
}
|
||||
#endif /* MODULE_LIS2DH12_INT */
|
||||
#endif /* LIS2DH12_PARAMS */
|
||||
|
430
drivers/lis2dh12/include/lis2dh12_registers.h
Normal file
430
drivers/lis2dh12/include/lis2dh12_registers.h
Normal file
@ -0,0 +1,430 @@
|
||||
/*
|
||||
* Copyright (C) 2021 ML!PA Consulting GmbH
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup drivers_lis2dh12
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief LIS2DH12 register definitions
|
||||
*
|
||||
* @author Jan Mohr <jan.mohr@ml-pa.com>
|
||||
*/
|
||||
|
||||
#ifndef LIS2DH12_REGISTERS_H
|
||||
#define LIS2DH12_REGISTERS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Definition of read Registers
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief STATUS_REG_AUX definitions
|
||||
*/
|
||||
enum {
|
||||
LIS2DH12_STATUS_REG_AUX_TDA = 0x04, /**< Temperature new data available */
|
||||
LIS2DH12_STATUS_REG_AUX_TOR = 0x40, /**< Temperature data overrun */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief STATUS_REG definitions
|
||||
*/
|
||||
enum {
|
||||
LIS2DH12_STATUS_REG_XDA = 0x01, /**< X-axis new data available */
|
||||
LIS2DH12_STATUS_REG_YDA = 0x02, /**< Y-axis new data available */
|
||||
LIS2DH12_STATUS_REG_ZDA = 0x04, /**< Z-axis new data available */
|
||||
LIS2DH12_STATUS_REG_ZYXDA = 0x08, /**< On X-, Y-, Z-axis new data available */
|
||||
LIS2DH12_STATUS_REG_XOR = 0x10, /**< X-axis data overrun */
|
||||
LIS2DH12_STATUS_REG_YOR = 0x20, /**< Y-axis data overrun */
|
||||
LIS2DH12_STATUS_REG_ZOR = 0x40, /**< Y-axis data overrun */
|
||||
LIS2DH12_STATUS_REG_ZYXOR = 0x80, /**< On X-, Y-, Z-axis data overrun */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief INT1_SRC and INT2_SRC definitions
|
||||
*/
|
||||
enum {
|
||||
LIS2DH12_INT_SRC_XL = 0x01, /**< X low event */
|
||||
LIS2DH12_INT_SRC_XH = 0x02, /**< X high event */
|
||||
LIS2DH12_INT_SRC_YL = 0x04, /**< Y low event */
|
||||
LIS2DH12_INT_SRC_YH = 0x08, /**< Y high event */
|
||||
LIS2DH12_INT_SRC_ZL = 0x10, /**< Z low event */
|
||||
LIS2DH12_INT_SRC_ZH = 0x20, /**< Z high event */
|
||||
LIS2DH12_INT_SRC_IA = 0x40, /**< Interrupt 1 active, at least one interrupt \
|
||||
has been generated */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interrupt config register values
|
||||
*/
|
||||
enum {
|
||||
LIS2DH12_INT_CFG_XLIE = 0x01, /**< enable X low event */
|
||||
LIS2DH12_INT_CFG_XHIE = 0x02, /**< enable X high event */
|
||||
LIS2DH12_INT_CFG_YLIE = 0x04, /**< enable Y low event */
|
||||
LIS2DH12_INT_CFG_YHIE = 0x08, /**< enable Y high event */
|
||||
LIS2DH12_INT_CFG_ZLIE = 0x10, /**< enable Z low event */
|
||||
LIS2DH12_INT_CFG_ZHIE = 0x20, /**< enable Z high event */
|
||||
LIS2DH12_INT_CFG_6D = 0x40, /**< enable 6-direction detection */
|
||||
LIS2DH12_INT_CFG_AOI = 0x80, /**< and/or combination interrupt events */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interrupt type register values
|
||||
*/
|
||||
enum {
|
||||
/* for interrupt 1 (CTRL_REG3) */
|
||||
LIS2DH12_INT_TYPE_I1_OVERRUN = 0x02, /**< FIFO overrun interrupt on INT1 */
|
||||
LIS2DH12_INT_TYPE_I1_WTM = 0x04, /**< FIFO watermark interrupt on INT1 */
|
||||
LIS2DH12_INT_TYPE_I1_ZYXDA = 0x10, /**< ZYXDA interrupt on INT1 */
|
||||
LIS2DH12_INT_TYPE_I1_IA2 = 0x20, /**< IA2 interrupt on INT1 */
|
||||
LIS2DH12_INT_TYPE_I1_IA1 = 0x40, /**< IA1 interrupt on INT1 */
|
||||
LIS2DH12_INT_TYPE_I1_CLICK = 0x80, /**< click interrupt on INT1 */
|
||||
|
||||
/* for interrupt 2 (CTRL_REG6) */
|
||||
LIS2DH12_INT_TYPE_INT_POLARITY = 0x02, /**< INT1 and INT2 pin polarity */
|
||||
LIS2DH12_INT_TYPE_I2_ACT = 0x08, /**< enable activity interrupt on INT2 */
|
||||
LIS2DH12_INT_TYPE_I2_BOOT = 0x10, /**< enable boot on INT2 */
|
||||
LIS2DH12_INT_TYPE_I2_IA2 = 0x20, /**< IA2 on INT2 */
|
||||
LIS2DH12_INT_TYPE_I2_IA1 = 0x40, /**< IA1 on INT2 */
|
||||
LIS2DH12_INT_TYPE_I2_CLICK = 0x80, /**< click interrupt on INT2 */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief CLICK_SRC definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t X_AXIS:1; /**< X click detected */
|
||||
uint8_t Y_AXIS:1; /**< Y click detected */
|
||||
uint8_t Z_AXIS:1; /**< Z click detected */
|
||||
uint8_t Sign:1; /**< Click sign, "0" positive, "1" negative */
|
||||
uint8_t SClick:1; /**< Single click detected */
|
||||
uint8_t DClick:1; /**< Double click detected */
|
||||
uint8_t IA:1; /**< Interrupt active, at least one interrupt \
|
||||
has been generated */
|
||||
uint8_t _RESERVED:1; /**< Reserved bit */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_CLICK_SRC_t;
|
||||
|
||||
/**
|
||||
* @brief FIFO_SRC_REG definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t FSS:5; /**< Number of unread samples in FIFO */
|
||||
uint8_t EMPTY:1; /**< FIFO is empty */
|
||||
uint8_t OVRN_FIFO:1; /**< Overrun in FIFO occurred */
|
||||
uint8_t WTM:1; /**< FIFO content watermark level */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_FIFO_SRC_REG_t;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
*
|
||||
* @name Definition of read/write Registers
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief CTRL_REG_0 definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t CTRL0_DEFAULT_VALUE:7; /**< Always set this to CTRL_REG0_DEFAULT */
|
||||
uint8_t SDO_PU_DISC:1; /**< disconnect pull-up on SDO/SA0 */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_CTRL_REG0_t;
|
||||
|
||||
/**
|
||||
* @brief TEMP_CFG_REG definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t _RESERVED:6; /**< Should always be zero */
|
||||
uint8_t TEMP_EN:2; /**< "00" disables Temperature sensor, "11" enables */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_TEMP_CFG_REG_t;
|
||||
|
||||
/**
|
||||
* @brief CTRL_REG1 definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t Xen:1; /**< X axis enable */
|
||||
uint8_t Yen:1; /**< Y axis enable */
|
||||
uint8_t Zen:1; /**< Z axis enable */
|
||||
uint8_t LPen:1; /**< Enable Low Power mode */
|
||||
uint8_t ODR:4; /**< Set Data rate */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_CTRL_REG1_t;
|
||||
|
||||
/**
|
||||
* @brief CTRL_REG2 definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t HP_IA1:1; /**< High pass filter enable for AOI on interrupt 1 */
|
||||
uint8_t HP_IA2:1; /**< High pass filter enable for AOI on interrupt 2 */
|
||||
uint8_t HPCLICK:1; /**< High pass filter enable for CLICK function */
|
||||
uint8_t FDS:1; /**< Enables filter output data */
|
||||
uint8_t HPCF:2; /**< High pass filter cutoff frequency */
|
||||
uint8_t HPM:2; /**< High pass filter mode selection */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_CTRL_REG2_t;
|
||||
|
||||
/**
|
||||
* @brief CTRL_REG3 definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t _RESERVED0:1; /**< Reserved bit */
|
||||
uint8_t I1_OVERRUN:1; /**< Enable FIFO overrun interrupt on INT1 */
|
||||
uint8_t I1_WTM:1; /**< Enable FIFO watermark interrupt on INT1 */
|
||||
uint8_t _RESERVED3:1; /**< Should always be "0" */
|
||||
uint8_t I1_ZYXDA:1; /**< Enable ZYXDA interrupt on INT1 */
|
||||
uint8_t I1_IA2:1; /**< Enable IA2 interrupt on INT1 */
|
||||
uint8_t I1_IA1:1; /**< Enable IA1 interrupt on INT1 */
|
||||
uint8_t I1_CLICK:1; /**< Enable CLICK interrupt on INT1 */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_CTRL_REG3_t;
|
||||
|
||||
/**
|
||||
* @brief CTRL_REG4 definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t SPIM:1; /**< SPI serial interface mode selection (SIM)*/
|
||||
uint8_t ST:2; /**< Self-test enable */
|
||||
uint8_t HR:1; /**< Operating mode */
|
||||
uint8_t FS:2; /**< Full-scale selection */
|
||||
uint8_t BLE:1; /**< Big/Little endian data selection */
|
||||
uint8_t BDU:1; /**< Block data update */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_CTRL_REG4_t;
|
||||
|
||||
/**
|
||||
* @brief CTRL_REG5 definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t D4D_INT2:1; /**< 4D detection enabled on INT2 */
|
||||
uint8_t LIR_INT2:1; /**< Latch interrupt request for INT2 */
|
||||
uint8_t D4D_INT1:1; /**< 4D detection enabled on INT1 */
|
||||
uint8_t LIR_INT1:1; /**< Latch interrupt request for INT2 */
|
||||
uint8_t _RESERVED:2; /**< Reserved bits */
|
||||
uint8_t FIFO_EN:1; /**< FIFO enable */
|
||||
uint8_t BOOT:1; /**< Clears the data content */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_CTRL_REG5_t;
|
||||
|
||||
/**
|
||||
* @brief CTRL_REG6 definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t _RESERVED0:1; /**< Reserved bit */
|
||||
uint8_t INT_POLARITY:1; /**< Set pin polarity for INT1 and INT2 */
|
||||
uint8_t _RESERVED2:1; /**< Reserved bit */
|
||||
uint8_t I2_ACT:1; /**< Enable activity interrupt on INT2 */
|
||||
uint8_t I2_BOOT:1; /**< Enable boot on INT2 */
|
||||
uint8_t I2_IA2:1; /**< Enable IA2 on INT2 */
|
||||
uint8_t I2_IA1:1; /**< Enable IA1 on INT2 */
|
||||
uint8_t I2_CLICK:1; /**< Enable CLICK interrupt on INT2 */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_CTRL_REG6_t;
|
||||
|
||||
/**
|
||||
* @brief REFERENCE definitions
|
||||
*/
|
||||
typedef union {
|
||||
uint8_t reg; /**< Set reference value */
|
||||
} LIS2DH12_REFERENCE_t;
|
||||
|
||||
/**
|
||||
* @brief FIFO_CTRL_REG definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t FTH:5; /**< Set the watermark level for FIFO */
|
||||
uint8_t TR:1; /**< Trigging selection, FIFO event triggers INT1 or INT2 */
|
||||
uint8_t FM:2; /**< FIFO mode selection */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_FIFO_CTRL_REG_t;
|
||||
|
||||
/**
|
||||
* @brief INT1_CFG definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t XLIE:1; /**< Enable interrupt on X low event */
|
||||
uint8_t XHIE:1; /**< Enable interrupt on X high event */
|
||||
uint8_t YLIE:1; /**< Enable interrupt on Y low event */
|
||||
uint8_t YHIE:1; /**< Enable interrupt on Y high event */
|
||||
uint8_t ZLIE:1; /**< Enable interrupt on Z low event */
|
||||
uint8_t ZHIE:1; /**< Enable interrupt on Z high event */
|
||||
uint8_t D6D:1; /**< 6 direction detection function enable */
|
||||
uint8_t AOI:1; /**< AND/OR combination of interrupt events */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_INT1_CFG_t;
|
||||
|
||||
/**
|
||||
* @brief INT1_THS definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t THS:7; /**< Sets threshold level, the LSB changes according to
|
||||
LIS2DH12_SCALE (@2G LSB=16mg; @4G LSB=32mg; @8G LSB=62mg
|
||||
@16G LSB=186mg) */
|
||||
uint8_t _RESERVED:1; /**< needs to be zero */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_INT1_THS_t;
|
||||
|
||||
/**
|
||||
* @brief INT1_DURATION definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t D:7; /**< Sets the minimum duration of INT1, in ODR cycles */
|
||||
uint8_t _RESERVED:1; /**< need to be zero */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_INT1_DURATION_t;
|
||||
|
||||
/**
|
||||
* @brief INT2_CFG definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t XLIE:1; /**< Enable interrupt on X low event */
|
||||
uint8_t XHIE:1; /**< Enable interrupt on X high event */
|
||||
uint8_t YLIE:1; /**< Enable interrupt on Y low event */
|
||||
uint8_t YHIE:1; /**< Enable interrupt on Y high event */
|
||||
uint8_t ZLIE:1; /**< Enable interrupt on Z low event */
|
||||
uint8_t ZHIE:1; /**< Enable interrupt on Z high event */
|
||||
uint8_t D6D:1; /**< 6 direction detection function enable */
|
||||
uint8_t AOI:1; /**< AND/OR combination of interrupt events */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_INT2_CFG_t;
|
||||
|
||||
/**
|
||||
* @brief INT2_THS definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t THS:7; /**< Sets threshold level, LSB according to LIS2DH12_SCALE */
|
||||
uint8_t _RESERVED:1; /**< needs to be zero */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_INT2_THS_t;
|
||||
|
||||
/**
|
||||
* @brief INT2_DURATION definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t D:7; /**< Sets the minimum duration of INT2, in ODR cycles */
|
||||
uint8_t _RESERVED:1; /**< need to be zero */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_INT2_DURATION_t;
|
||||
|
||||
/**
|
||||
* @brief CLICK_CFG definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t XS:1; /**< Interrupt single-click enable on X-axis */
|
||||
uint8_t XD:1; /**< Interrupt double-click enable on X-axis */
|
||||
uint8_t YS:1; /**< Interrupt single-click enable on Y-axis */
|
||||
uint8_t YD:1; /**< Interrupt double-click enable on Y-axis */
|
||||
uint8_t ZS:1; /**< Interrupt single-click enable on Z-axis */
|
||||
uint8_t ZD:1; /**< Interrupt double-click enable on Z-axis */
|
||||
uint8_t _RESERVED:2; /**< Reserved bits */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_CLICK_CFG_t;
|
||||
|
||||
/**
|
||||
* @brief CLICK_THS definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t THS:7; /**< Sets the click threshold, LSB according to LIS2DH12_SCALE */
|
||||
uint8_t LIR_CLICK:1; /**< Enables latency on interrupt kept high, \
|
||||
"0" for duration of latency window, \
|
||||
"1" kept high until CLICK_SRC is read */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_CLICK_THS_t;
|
||||
|
||||
/**
|
||||
* @brief TIME_LIMIT definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t TLI:7; /**< Click time limit, in ODR cycles */
|
||||
uint8_t _RESERVED:1; /**< reserved bit */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_TIME_LIMIT_t;
|
||||
|
||||
/**
|
||||
* @brief TIME_LATENCY definitions
|
||||
*/
|
||||
typedef union {
|
||||
uint8_t reg; /**< Sets time latency, in ODR cycles */
|
||||
} LIS2DH12_TIME_LATENCY_t;
|
||||
|
||||
/**
|
||||
* @brief TIME_WINDOW definitions
|
||||
*/
|
||||
typedef union {
|
||||
uint8_t reg; /**< Sets time window, in ODR cycles */
|
||||
} LIS2DH12_TIME_WINDOW_t;
|
||||
|
||||
/**
|
||||
* @brief ACT_THS definitions
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t ACTH:7; /**< Sets the threshold sleep-to-wake or return-to-sleep
|
||||
LSB according to LIS2DH12_SCALE */
|
||||
uint8_t _RESERVED:1; /**< reserved bit */
|
||||
} bit; /**< Structure used for bit access */
|
||||
uint8_t reg; /**< Type used for register access */
|
||||
} LIS2DH12_ACT_THS_t;
|
||||
|
||||
/**
|
||||
* @brief ACT_DURATION definitions
|
||||
*/
|
||||
typedef union {
|
||||
uint8_t reg; /**< Sleep-to-wake and return-to-sleep duration, in ODR cycles */
|
||||
} LIS2DH12_ACT_DURATION_t;
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIS2DH12_REGISTERS_H */
|
||||
/** @} */
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "lis2dh12.h"
|
||||
#include "lis2dh12_internal.h"
|
||||
#include "lis2dh12_registers.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
@ -126,13 +127,13 @@ static void _write(const lis2dh12_t *dev, uint8_t reg, uint8_t data)
|
||||
|
||||
#endif /* MODULE_LIS2DH12_SPI */
|
||||
|
||||
|
||||
int lis2dh12_init(lis2dh12_t *dev, const lis2dh12_params_t *params)
|
||||
{
|
||||
assert(dev && params);
|
||||
|
||||
dev->p = params;
|
||||
dev->comp = (1000UL * (0x02 << (dev->p->scale >> 4)));
|
||||
/* calculate shift amount to convert raw acceleration data */
|
||||
dev->comp = 4 - (dev->p->scale >> 4);
|
||||
|
||||
/* initialize the chip select line */
|
||||
if (_init_bus(dev) != LIS2DH12_OK) {
|
||||
@ -153,12 +154,22 @@ int lis2dh12_init(lis2dh12_t *dev, const lis2dh12_params_t *params)
|
||||
return LIS2DH12_NODEV;
|
||||
}
|
||||
|
||||
/* set sampling rate and scale. This also enables the device and starts
|
||||
* sampling of data */
|
||||
/* enable all axes, set sampling rate and scale */
|
||||
LIS2DH12_CTRL_REG1_t reg1 = {0};
|
||||
|
||||
reg1.bit.ODR = dev->p->rate;
|
||||
reg1.bit.Xen = 1;
|
||||
reg1.bit.Yen = 1;
|
||||
reg1.bit.Zen = 1;
|
||||
|
||||
_write(dev, REG_CTRL_REG4, dev->p->scale);
|
||||
_write(dev, REG_CTRL_REG1, dev->p->rate);
|
||||
_write(dev, REG_CTRL_REG1, reg1.reg);
|
||||
|
||||
_release(dev);
|
||||
|
||||
/* set powermode */
|
||||
lis2dh12_set_powermode(dev, dev->p->powermode);
|
||||
|
||||
DEBUG("[lis2dh12] initialization successful\n");
|
||||
return LIS2DH12_OK;
|
||||
}
|
||||
@ -174,7 +185,7 @@ int lis2dh12_read(const lis2dh12_t *dev, int16_t *data)
|
||||
_acquire(dev);
|
||||
|
||||
/* first check if valid data is available */
|
||||
if ((_read(dev, REG_STATUS_REG) & LIS2DH12_STATUS_ZYXDA) == 0) {
|
||||
if ((_read(dev, REG_STATUS_REG) & LIS2DH12_STATUS_REG_ZYXDA) == 0) {
|
||||
_release(dev);
|
||||
return LIS2DH12_NODATA;
|
||||
}
|
||||
@ -184,11 +195,7 @@ int lis2dh12_read(const lis2dh12_t *dev, int16_t *data)
|
||||
|
||||
/* calculate the actual g-values for the x, y, and z dimension */
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int32_t tmp = ((raw[i * 2] >> 6) | (raw[(i * 2) + 1] << 2));
|
||||
if (tmp & 0x00000200) {
|
||||
tmp |= 0xfffffc00;
|
||||
}
|
||||
data[i] = (int16_t)((tmp * dev->comp) / 512);
|
||||
data[i] = (int16_t)((raw[i*2 + 1] << 8) | raw[i*2]) >> dev->comp;
|
||||
}
|
||||
|
||||
return LIS2DH12_OK;
|
||||
@ -198,9 +205,8 @@ int lis2dh12_read(const lis2dh12_t *dev, int16_t *data)
|
||||
int lis2dh12_set_int(const lis2dh12_t *dev, const lis2dh12_int_params_t *params, uint8_t int_line)
|
||||
{
|
||||
assert (int_line == LIS2DH12_INT1 || int_line == LIS2DH12_INT2);
|
||||
assert (dev && params->int_config && params->int_type);
|
||||
assert (params->int_threshold >= 0);
|
||||
assert (params->int_duration >= 0);
|
||||
assert (dev && params);
|
||||
assert (params->cb);
|
||||
|
||||
_acquire(dev);
|
||||
|
||||
@ -266,13 +272,274 @@ int lis2dh12_read_int_src(const lis2dh12_t *dev, uint8_t *data, uint8_t int_line
|
||||
}
|
||||
#endif /* MODULE_LIS2DH12_INT */
|
||||
|
||||
int lis2dh12_set_fifo(const lis2dh12_t *dev, const lis2dh12_fifo_t *config) {
|
||||
|
||||
assert(dev && config);
|
||||
|
||||
LIS2DH12_CTRL_REG5_t reg5 = {0};
|
||||
LIS2DH12_FIFO_CTRL_REG_t fifo_reg = {0};
|
||||
|
||||
if (config->FIFO_mode != LIS2DH12_FIFO_MODE_BYPASS) {
|
||||
reg5.bit.FIFO_EN = 1;
|
||||
}
|
||||
fifo_reg.bit.TR = config->FIFO_set_INT2;
|
||||
fifo_reg.bit.FM = config->FIFO_mode;
|
||||
fifo_reg.bit.FTH = config->FIFO_watermark;
|
||||
|
||||
_acquire(dev);
|
||||
_write(dev, REG_CTRL_REG5, reg5.reg);
|
||||
_write(dev, REG_FIFO_CTRL_REG, fifo_reg.reg);
|
||||
_release(dev);
|
||||
|
||||
return LIS2DH12_OK;
|
||||
}
|
||||
|
||||
int lis2dh12_restart_fifo(const lis2dh12_t *dev) {
|
||||
|
||||
assert(dev);
|
||||
|
||||
_acquire(dev);
|
||||
uint8_t reg5 = _read(dev, REG_CTRL_REG5);
|
||||
LIS2DH12_FIFO_CTRL_REG_t fifo_reg = {0};
|
||||
fifo_reg.reg = _read(dev, REG_FIFO_CTRL_REG);
|
||||
|
||||
uint8_t fifo_mode_old = fifo_reg.bit.FM;
|
||||
fifo_reg.bit.FM = LIS2DH12_FIFO_MODE_BYPASS;
|
||||
|
||||
/* switch to Bypass mode */
|
||||
_write(dev, REG_FIFO_CTRL_REG, fifo_reg.reg);
|
||||
|
||||
fifo_reg.bit.FM = fifo_mode_old;
|
||||
|
||||
_write(dev, REG_CTRL_REG5, reg5);
|
||||
_write(dev, REG_FIFO_CTRL_REG, fifo_reg.reg);
|
||||
_release(dev);
|
||||
|
||||
return LIS2DH12_OK;
|
||||
}
|
||||
|
||||
int lis2dh12_read_fifo_src(const lis2dh12_t *dev, LIS2DH12_FIFO_SRC_REG_t *data) {
|
||||
|
||||
assert(dev && data);
|
||||
|
||||
_acquire(dev);
|
||||
data->reg = _read(dev, REG_FIFO_SRC_REG);
|
||||
_release(dev);
|
||||
|
||||
return LIS2DH12_OK;
|
||||
}
|
||||
|
||||
uint8_t lis2dh12_read_fifo_data(const lis2dh12_t *dev, lis2dh12_fifo_data_t *fifo_data,
|
||||
uint8_t number) {
|
||||
|
||||
assert(dev && fifo_data);
|
||||
/* check max FIFO length */
|
||||
assert(number <= 32);
|
||||
|
||||
_acquire(dev);
|
||||
/* check if number is available */
|
||||
LIS2DH12_FIFO_SRC_REG_t src_reg = {0};
|
||||
src_reg.reg = _read(dev, REG_FIFO_SRC_REG);
|
||||
|
||||
if (src_reg.bit.FSS <= number) {
|
||||
number = src_reg.bit.FSS;
|
||||
}
|
||||
|
||||
if (src_reg.bit.EMPTY) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* calculate X, Y and Z values */
|
||||
for (uint8_t i = 0; i < number; i++){
|
||||
fifo_data[i].X_AXIS = (int16_t)(_read(dev, REG_OUT_X_L) | (_read(dev, REG_OUT_X_H) << 8))
|
||||
>> dev->comp;
|
||||
fifo_data[i].Y_AXIS = (int16_t)(_read(dev, REG_OUT_Y_L) | (_read(dev, REG_OUT_Y_H) << 8))
|
||||
>> dev->comp;
|
||||
fifo_data[i].Z_AXIS = (int16_t)(_read(dev, REG_OUT_Z_L) | (_read(dev, REG_OUT_Z_H) << 8))
|
||||
>> dev->comp;
|
||||
}
|
||||
|
||||
_release(dev);
|
||||
|
||||
return number;
|
||||
}
|
||||
|
||||
int lis2dh12_clear_data(const lis2dh12_t *dev) {
|
||||
|
||||
assert(dev);
|
||||
|
||||
LIS2DH12_CTRL_REG5_t ctrl_reg5 = {0};
|
||||
ctrl_reg5.bit.BOOT = 1;
|
||||
|
||||
_acquire(dev);
|
||||
_write(dev, REG_CTRL_REG5, ctrl_reg5.reg);
|
||||
_release(dev);
|
||||
|
||||
return LIS2DH12_OK;
|
||||
}
|
||||
|
||||
int lis2dh12_set_reference(const lis2dh12_t *dev, uint8_t reference) {
|
||||
|
||||
assert(dev);
|
||||
|
||||
_acquire(dev);
|
||||
_write(dev, REG_REFERENCE, reference);
|
||||
_release(dev);
|
||||
|
||||
return LIS2DH12_OK;
|
||||
}
|
||||
|
||||
int lis2dh12_read_reference(const lis2dh12_t *dev, uint8_t *data) {
|
||||
|
||||
assert(dev);
|
||||
|
||||
_acquire(dev);
|
||||
*data = _read(dev, REG_REFERENCE);
|
||||
_release(dev);
|
||||
|
||||
return LIS2DH12_OK;
|
||||
}
|
||||
|
||||
int lis2dh12_set_highpass(const lis2dh12_t *dev, const lis2dh12_highpass_t *config) {
|
||||
|
||||
assert(dev && config);
|
||||
|
||||
LIS2DH12_CTRL_REG2_t data = {0};
|
||||
|
||||
data.bit.HPM = config->Highpass_mode;
|
||||
data.bit.HPCF = config->Highpass_freq;
|
||||
data.bit.FDS = config->DATA_OUT_enable;
|
||||
data.bit.HP_IA1 = config->INT1_enable;
|
||||
data.bit.HP_IA2 = config->INT2_enable;
|
||||
data.bit.HPCLICK = config->CLICK_enable;
|
||||
|
||||
_acquire(dev);
|
||||
_write(dev, REG_CTRL_REG2, data.reg);
|
||||
_release(dev);
|
||||
|
||||
return LIS2DH12_OK;
|
||||
}
|
||||
|
||||
int lis2dh12_set_click(const lis2dh12_t *dev, const lis2dh12_click_t *config) {
|
||||
assert(dev);
|
||||
|
||||
LIS2DH12_CLICK_CFG_t click_CFG = {0};
|
||||
if (config->enable_DOUBLE) {
|
||||
click_CFG.bit.XD = config->enable_X_CLICK;
|
||||
click_CFG.bit.YD = config->enable_Y_CLICK;
|
||||
click_CFG.bit.ZD = config->enable_Z_CLICK;
|
||||
}
|
||||
else {
|
||||
click_CFG.bit.XS = config->enable_X_CLICK;
|
||||
click_CFG.bit.YS = config->enable_Y_CLICK;
|
||||
click_CFG.bit.ZS = config->enable_Z_CLICK;
|
||||
}
|
||||
|
||||
LIS2DH12_CLICK_THS_t click_thold = {0};
|
||||
click_thold.bit.LIR_CLICK = config->noINT_latency;
|
||||
click_thold.bit.THS = config->CLICK_thold;
|
||||
|
||||
_acquire(dev);
|
||||
_write(dev, REG_CLICK_CFG, click_CFG.reg);
|
||||
_write(dev, REG_CLICK_THS, click_thold.reg);
|
||||
_write(dev, REG_TIME_LIMIT, config->TIME_limit);
|
||||
_write(dev, REG_TIME_LATENCY, config->TIME_latency);
|
||||
_write(dev, REG_TIME_WINDOW, config->TIME_window);
|
||||
_release(dev);
|
||||
|
||||
return LIS2DH12_OK;
|
||||
}
|
||||
|
||||
int lis2dh12_read_click_src(const lis2dh12_t *dev, LIS2DH12_CLICK_SRC_t *data) {
|
||||
assert(dev && data);
|
||||
|
||||
_acquire(dev);
|
||||
data->reg = _read(dev, REG_CLICK_SRC);
|
||||
_release(dev);
|
||||
|
||||
return LIS2DH12_OK;
|
||||
}
|
||||
|
||||
int lis2dh12_set_powermode(const lis2dh12_t *dev, lis2dh12_powermode_t powermode) {
|
||||
|
||||
assert(dev);
|
||||
|
||||
LIS2DH12_CTRL_REG1_t reg1 = {0};
|
||||
LIS2DH12_CTRL_REG4_t reg4 = {0};
|
||||
|
||||
_acquire(dev);
|
||||
reg1.reg = _read(dev, REG_CTRL_REG1);
|
||||
reg4.reg = _read(dev, REG_CTRL_REG4);
|
||||
|
||||
/* set power mode */
|
||||
if (powermode == LIS2DH12_POWER_LOW) {
|
||||
reg1.bit.LPen = 1;
|
||||
reg4.bit.HR = 0;
|
||||
}
|
||||
else if (powermode == LIS2DH12_POWER_HIGH) {
|
||||
reg1.bit.LPen = 0;
|
||||
reg4.bit.HR = 1;
|
||||
}
|
||||
else if (powermode == LIS2DH12_POWER_NORMAL) {
|
||||
reg1.bit.LPen = 0;
|
||||
reg4.bit.HR = 0;
|
||||
}
|
||||
else { /* power down mode */
|
||||
reg1.bit.ODR = 0;
|
||||
}
|
||||
|
||||
_write(dev, REG_CTRL_REG1, reg1.reg);
|
||||
_write(dev, REG_CTRL_REG4, reg4.reg);
|
||||
_release(dev);
|
||||
|
||||
return LIS2DH12_OK;
|
||||
}
|
||||
|
||||
int lis2dh12_set_datarate(const lis2dh12_t *dev, lis2dh12_rate_t rate) {
|
||||
|
||||
assert(dev);
|
||||
assert(rate <= 0x9);
|
||||
|
||||
LIS2DH12_CTRL_REG1_t reg1 = {0};
|
||||
|
||||
_acquire(dev);
|
||||
reg1.reg = _read(dev, REG_CTRL_REG1);
|
||||
|
||||
reg1.bit.ODR = rate;
|
||||
|
||||
_write(dev, REG_CTRL_REG1, reg1.reg);
|
||||
_release(dev);
|
||||
|
||||
return LIS2DH12_OK;
|
||||
}
|
||||
|
||||
int lis2dh12_set_scale(lis2dh12_t *dev, lis2dh12_scale_t scale) {
|
||||
|
||||
assert(dev);
|
||||
assert((scale>>4) <= 0x3);
|
||||
|
||||
LIS2DH12_CTRL_REG4_t reg4 = {0};
|
||||
|
||||
_acquire(dev);
|
||||
reg4.reg = _read(dev, REG_CTRL_REG4);
|
||||
|
||||
reg4.bit.FS = scale >> 4;
|
||||
|
||||
_write(dev, REG_CTRL_REG4, reg4.reg);
|
||||
_release(dev);
|
||||
|
||||
dev->comp = 4 - (scale >> 4);
|
||||
|
||||
return LIS2DH12_OK;
|
||||
}
|
||||
|
||||
int lis2dh12_poweron(const lis2dh12_t *dev)
|
||||
{
|
||||
assert(dev);
|
||||
|
||||
_acquire(dev);
|
||||
_write(dev, REG_CTRL_REG1, dev->p->rate);
|
||||
_release(dev);
|
||||
/* set default param values */
|
||||
lis2dh12_set_datarate(dev, dev->p->rate);
|
||||
lis2dh12_set_powermode(dev, dev->p->powermode);
|
||||
|
||||
return LIS2DH12_OK;
|
||||
}
|
||||
@ -281,9 +548,8 @@ int lis2dh12_poweroff(const lis2dh12_t *dev)
|
||||
{
|
||||
assert(dev);
|
||||
|
||||
_acquire(dev);
|
||||
_write(dev, REG_CTRL_REG1, 0);
|
||||
_release(dev);
|
||||
/* set datarate to zero */
|
||||
lis2dh12_set_datarate(dev, 0);
|
||||
|
||||
return LIS2DH12_OK;
|
||||
}
|
||||
|
@ -19,7 +19,6 @@
|
||||
#ifndef LIS2DH12_INTERNAL_H
|
||||
#define LIS2DH12_INTERNAL_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -73,6 +72,7 @@ extern "C" {
|
||||
* @{
|
||||
*/
|
||||
#define WHO_AM_I_VAL (0x33)
|
||||
#define CTRL_REG0_DEFAULT (0x10)
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -5,6 +5,7 @@ DRIVER ?= lis2dh12_spi
|
||||
|
||||
USEMODULE += fmt
|
||||
USEMODULE += xtimer
|
||||
USEMODULE += shell
|
||||
USEMODULE += $(DRIVER)
|
||||
|
||||
# for using lis2dh12 with interrupt function
|
||||
|
11
tests/driver_lis2dh12/Makefile.ci
Normal file
11
tests/driver_lis2dh12/Makefile.ci
Normal file
@ -0,0 +1,11 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-duemilanove \
|
||||
arduino-leonardo \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
nucleo-f031k6 \
|
||||
nucleo-l011k4 \
|
||||
samd10-xmini \
|
||||
stm32f030f4-demo \
|
||||
#
|
@ -2,6 +2,7 @@
|
||||
# application configuration. This is only needed during migration.
|
||||
CONFIG_MODULE_FMT=y
|
||||
CONFIG_MODULE_XTIMER=y
|
||||
CONFIG_MODULE_SHELL=y
|
||||
CONFIG_MODULE_LIS2DH12=y
|
||||
CONFIG_MODULE_LIS2DH12_SPI=y
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Freie Universität Berlin
|
||||
* Copyright (C) 2020 ML!PA Consulting GmbH
|
||||
*
|
||||
* 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
|
||||
@ -11,170 +11,699 @@
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Test application for the LIS2DH12 accelerometer driver
|
||||
* @brief Test application for LIS2DH12 accelerometer driver
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Jan Mohr <jan.mohr@ml-pa.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "fmt.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "stdlib.h"
|
||||
#include "xtimer.h"
|
||||
#include "mutex.h"
|
||||
#include "fmt.h"
|
||||
#include "thread.h"
|
||||
#include "shell.h"
|
||||
|
||||
#include "lis2dh12.h"
|
||||
#include "lis2dh12_params.h"
|
||||
#include "lis2dh12_registers.h"
|
||||
|
||||
/* delay between sensor data reads */
|
||||
#define DELAY (100UL * US_PER_MS)
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
/* allocate some memory to hold one formatted string for each sensor output, so
|
||||
* one string for the X, Y, and Z reading, respectively */
|
||||
static char str_out[3][8];
|
||||
#define REFERENCE_DEFAULT 10 /* LSB according to SCALE */
|
||||
|
||||
#define THOLD_SHOCK_MILLIG_DEFAULT 1500
|
||||
#define NUM_DATA_SHOCK_DETECT 7 /* detect shock in NUM last FIFO samples */
|
||||
|
||||
/* device specific */
|
||||
#define NUM_AXES 3
|
||||
#define NUM_FIFO_VALUES 32
|
||||
|
||||
/* axis define for click */
|
||||
#define X_CLICK 1
|
||||
#define Y_CLICK 2
|
||||
#define Z_CLICK 3
|
||||
#define DCLICK_DEFAULT 40 /* default threshold for double click */
|
||||
|
||||
#ifdef MODULE_LIS2DH12_INT
|
||||
static kernel_pid_t lis2dh12_process;
|
||||
#endif /* MODULE_LIS2DH12_INT */
|
||||
|
||||
int __attribute__((weak)) shell_lis2dh12_cmd(int argc, char** argv);
|
||||
|
||||
static const shell_command_t shell_commands[] = {
|
||||
{ "lis", "Command with multiple subcommands.", shell_lis2dh12_cmd },
|
||||
{ NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
char lis2dh12_process_stack[THREAD_STACKSIZE_MAIN];
|
||||
|
||||
/* setting the double click order */
|
||||
static LIS2DH12_CLICK_SRC_t click_src_reg;
|
||||
static lis2dh12_click_t click_cfg = {
|
||||
.enable_DOUBLE = true,
|
||||
.enable_X_CLICK = true,
|
||||
.enable_Y_CLICK = true,
|
||||
.enable_Z_CLICK = true,
|
||||
.noINT_latency = true,
|
||||
.CLICK_thold = DCLICK_DEFAULT,
|
||||
.TIME_limit = 4, /* 4 ODR cycles -> 40ms */
|
||||
.TIME_latency = 16, /* 16 ODR cycles -> 160ms */
|
||||
.TIME_window = 10, /* 10 ODR cycles -> 100ms */
|
||||
};
|
||||
|
||||
/* allocate device descriptor */
|
||||
static lis2dh12_t dev;
|
||||
|
||||
#ifdef MODULE_LIS2DH12_INT
|
||||
/* control interrupt */
|
||||
typedef struct {
|
||||
uint8_t line;
|
||||
mutex_t *lock;
|
||||
uint8_t *flags;
|
||||
} lis_ctx;
|
||||
/* Interrupt lines */
|
||||
static uint8_t line1 = 1;
|
||||
static uint8_t line2 = 2;
|
||||
|
||||
/* timer lock */
|
||||
static uint8_t isr_flags;
|
||||
static mutex_t isr_mtx = MUTEX_INIT_LOCKED;
|
||||
static lis_ctx ctx[2] = {
|
||||
{
|
||||
.line = 1,
|
||||
.lock = &isr_mtx,
|
||||
.flags = &isr_flags,
|
||||
}, {
|
||||
.line = 2,
|
||||
.lock = &isr_mtx,
|
||||
.flags = &isr_flags,
|
||||
}
|
||||
/* Interrupt params */
|
||||
static lis2dh12_int_params_t params_int1 = {0};
|
||||
static lis2dh12_int_params_t params_int2 = {0};
|
||||
|
||||
/* Interrupt source register */
|
||||
static uint8_t int1_src;
|
||||
#endif /* MODULE_LIS2DH12_INT */
|
||||
|
||||
/* FIFO data memory */
|
||||
static lis2dh12_fifo_data_t data_fifo[NUM_FIFO_VALUES];
|
||||
/* FIFO configuration */
|
||||
static lis2dh12_fifo_t fifo_cfg = {
|
||||
.FIFO_set_INT2 = false,
|
||||
.FIFO_watermark = 10,
|
||||
.FIFO_mode = LIS2DH12_FIFO_MODE_STREAMtoFIFO,
|
||||
};
|
||||
|
||||
/* interrupt callback function. */
|
||||
static void lis2dh12_int_cb(void* _ctx) {
|
||||
lis_ctx *control = _ctx;
|
||||
/* Memory to print current data */
|
||||
static char str_out[3][8];
|
||||
|
||||
*control->flags |= control->line;
|
||||
/* current lis acceleration data */
|
||||
static int16_t data_lis[3];
|
||||
|
||||
mutex_unlock(control->lock);
|
||||
/* highpass configuration */
|
||||
lis2dh12_highpass_t highpass_cfg = {
|
||||
.Highpass_mode = LIS2DH12_HP_MODE_REFERENCE,
|
||||
.Highpass_freq = LIS2DH12_HP_FREQ_DIV100,
|
||||
.CLICK_enable = false,
|
||||
.INT1_enable = false,
|
||||
.INT2_enable = false,
|
||||
.DATA_OUT_enable = false,
|
||||
};
|
||||
|
||||
/* reference data */
|
||||
static uint8_t reference_value;
|
||||
|
||||
/* shock threshold */
|
||||
static int16_t shock_thold;
|
||||
|
||||
#ifdef MODULE_LIS2DH12_INT
|
||||
/* previous values */
|
||||
static int16_t old_data_lis[3];
|
||||
static uint8_t int1_src_old;
|
||||
|
||||
/* lis2dh12 interrupt callback function. */
|
||||
static void lis2dh12_int_cb(void* l) {
|
||||
|
||||
/* disable IRQ until lis_process is done */
|
||||
gpio_irq_disable(dev.p->int1_pin);
|
||||
gpio_irq_disable(dev.p->int2_pin);
|
||||
|
||||
/* reset click source */
|
||||
lis2dh12_read_click_src(&dev, &click_src_reg);
|
||||
DEBUG("[INT]: CLICK_SRC 0x%x\n", click_src_reg.reg);
|
||||
|
||||
uint8_t line = *(uint8_t*)l;
|
||||
printf("Info: INT_line: %d\n", line);
|
||||
|
||||
lis2dh12_read_reference(&dev, &reference_value);
|
||||
DEBUG("[INT]: REF: 0x%x\n", reference_value);
|
||||
|
||||
lis2dh12_read_int_src(&dev, &int1_src, 1);
|
||||
DEBUG("[INT]: INT_SRC 0x%x\n", int1_src);
|
||||
DEBUG("[INT]: INT_SRC - IA %d; ZH %d; ZL %d; YH %d; YL %d; XH %d; XL %d.\n",
|
||||
int1_src & LIS2DH12_INT_SRC_IA,
|
||||
int1_src & LIS2DH12_INT_SRC_ZH, int1_src & LIS2DH12_INT_SRC_ZL,
|
||||
int1_src & LIS2DH12_INT_SRC_YH, int1_src & LIS2DH12_INT_SRC_YL,
|
||||
int1_src & LIS2DH12_INT_SRC_XH, int1_src & LIS2DH12_INT_SRC_XL);
|
||||
|
||||
thread_wakeup(lis2dh12_process);
|
||||
}
|
||||
#endif /* MODULE_LIS2DH12_INT */
|
||||
|
||||
void lis2dh12_test_init(void) {
|
||||
|
||||
if (IS_USED(MODULE_LIS2DH12_SPI)) {
|
||||
puts("using SPI mode, for I2C mode select the lis2dh12_i2c module");
|
||||
} else {
|
||||
puts("using I2C mode, for SPI mode select the lis2dh12_spi module");
|
||||
}
|
||||
|
||||
/* init lis */
|
||||
if (lis2dh12_init(&dev, &lis2dh12_params[0]) == LIS2DH12_OK) {
|
||||
puts("lis2dh12 [Initialized]");
|
||||
}
|
||||
else {
|
||||
puts("lis2dh12 [Failed]");
|
||||
}
|
||||
|
||||
/* change LIS settings */
|
||||
lis2dh12_set_powermode(&dev, LIS2DH12_POWER_LOW);
|
||||
lis2dh12_set_datarate(&dev, LIS2DH12_RATE_100HZ);
|
||||
lis2dh12_set_scale(&dev, LIS2DH12_SCALE_4G);
|
||||
|
||||
#ifdef MODULE_LIS2DH12_INT
|
||||
/* set interrupt pins */
|
||||
gpio_t pin1 = dev.p->int1_pin;
|
||||
gpio_t pin2 = dev.p->int2_pin;
|
||||
|
||||
/* set Interrupt params */
|
||||
if (gpio_is_valid(pin1)) {
|
||||
/* enables interrupt on all axes above the threshold value */
|
||||
params_int1.int_config = LIS2DH12_INT_CFG_XHIE
|
||||
| LIS2DH12_INT_CFG_YHIE
|
||||
| LIS2DH12_INT_CFG_ZHIE;
|
||||
params_int1.int_duration = 1;
|
||||
params_int1.cb = lis2dh12_int_cb;
|
||||
params_int1.arg = &line1;
|
||||
}
|
||||
if (gpio_is_valid(pin2)) {
|
||||
/* enables interrupt on Y-axis below the threshold value */
|
||||
params_int2.int_config = LIS2DH12_INT_CFG_YLIE;
|
||||
params_int2.int_duration = 1;
|
||||
params_int2.cb = lis2dh12_int_cb;
|
||||
params_int2.arg = &line2;
|
||||
}
|
||||
|
||||
if (gpio_init_int(pin1, GPIO_IN, GPIO_RISING, lis2dh12_int_cb, &line1)) {
|
||||
DEBUG("[lis_init]: INT1 failed\n");
|
||||
}
|
||||
else {
|
||||
DEBUG("[lis_init]: INT1 done\n");
|
||||
}
|
||||
|
||||
if (gpio_init_int(pin2, GPIO_IN, GPIO_RISING, lis2dh12_int_cb, &line2)) {
|
||||
DEBUG("[lis_init]: INT2 failed\n");
|
||||
}
|
||||
else {
|
||||
DEBUG("[lis_init]: INT2 done\n");
|
||||
}
|
||||
#endif /* MODULE_LIS2DH12_INT */
|
||||
|
||||
/* enable FIFO */
|
||||
lis2dh12_set_fifo(&dev, &fifo_cfg);
|
||||
|
||||
/* enable click detection */
|
||||
lis2dh12_set_click(&dev, &click_cfg);
|
||||
|
||||
/* set default shock value */
|
||||
shock_thold = THOLD_SHOCK_MILLIG_DEFAULT;
|
||||
|
||||
/* read registers to reset device */
|
||||
lis2dh12_read_click_src(&dev, &click_src_reg);
|
||||
lis2dh12_read_reference(&dev, &reference_value);
|
||||
#ifdef MODULE_LIS2DH12_INT
|
||||
lis2dh12_read_int_src(&dev, &int1_src, 1);
|
||||
#endif /* MODULE_LIS2DH12_INT */
|
||||
}
|
||||
|
||||
/* print interrupt register */
|
||||
static void lis2dh12_int_reg_content(lis2dh12_t *dev, uint8_t pin){
|
||||
#ifdef MODULE_LIS2DH12_INT
|
||||
void* lis2dh12_test_process(void* arg) {
|
||||
(void) arg;
|
||||
while (1) {
|
||||
/* start processing */
|
||||
DEBUG("[Process]: start process\n");
|
||||
|
||||
assert(pin == LIS2DH12_INT1 || pin == LIS2DH12_INT2);
|
||||
/* read FIFO_src before getting data */
|
||||
LIS2DH12_FIFO_SRC_REG_t fifo_src;
|
||||
lis2dh12_read_fifo_src(&dev, &fifo_src);
|
||||
DEBUG("[Process]: FIFO SRC 0x%x\n", fifo_src.reg);
|
||||
DEBUG("[Process]: WTM %x, OVRN %d, EMPTY %d, FSS %d\n", fifo_src.bit.WTM,
|
||||
fifo_src.bit.OVRN_FIFO, fifo_src.bit.EMPTY, fifo_src.bit.FSS);
|
||||
|
||||
uint8_t buffer;
|
||||
lis2dh12_read_int_src(dev, &buffer, pin);
|
||||
/* get fifo data */
|
||||
uint8_t number_read = lis2dh12_read_fifo_data(&dev, data_fifo, NUM_FIFO_VALUES);
|
||||
|
||||
printf("content SRC_Reg_%d: 0x%02x\n", pin, buffer);
|
||||
printf("\t XL %d\n", !!(buffer & LIS2DH12_INT_SRC_XL));
|
||||
printf("\t XH %d\n", !!(buffer & LIS2DH12_INT_SRC_XH));
|
||||
printf("\t YL %d\n", !!(buffer & LIS2DH12_INT_SRC_YL));
|
||||
printf("\t YH %d\n", !!(buffer & LIS2DH12_INT_SRC_YH));
|
||||
printf("\t ZL %d\n", !!(buffer & LIS2DH12_INT_SRC_ZL));
|
||||
printf("\t ZH %d\n", !!(buffer & LIS2DH12_INT_SRC_ZH));
|
||||
printf("\t IA %d\n", !!(buffer & LIS2DH12_INT_SRC_IA));
|
||||
/* read FIFO_src after getting data */
|
||||
lis2dh12_read_fifo_src(&dev, &fifo_src);
|
||||
DEBUG("[Process]: FIFO SRC 0x%x\n", fifo_src.reg);
|
||||
DEBUG("[Process]: WTM %x, OVRN %d, EMPTY %d, FSS %d\n", fifo_src.bit.WTM,
|
||||
fifo_src.bit.OVRN_FIFO, fifo_src.bit.EMPTY, fifo_src.bit.FSS);
|
||||
|
||||
/* display FIFO data */
|
||||
if (ENABLE_DEBUG) {
|
||||
for (int i = 0; i < number_read; i++){
|
||||
printf("[Process]: X[%2d] %d\n", i, data_fifo[i].X_AXIS);
|
||||
printf("[Process]: Y[%2d] %d\n", i, data_fifo[i].Y_AXIS);
|
||||
printf("[Process]: Z[%2d] %d\n", i, data_fifo[i].Z_AXIS);
|
||||
}
|
||||
}
|
||||
|
||||
/* After the Interrupt the FIFO needs to be enabled again. */
|
||||
lis2dh12_restart_fifo(&dev);
|
||||
|
||||
/* check if shock occurred*/
|
||||
uint16_t max_data_X = 0;
|
||||
uint16_t max_data_Y = 0;
|
||||
uint16_t max_data_Z = 0;
|
||||
|
||||
bool X_shock_pos = false;
|
||||
bool Y_shock_pos = false;
|
||||
bool Z_shock_pos = false;
|
||||
|
||||
for (uint8_t entry = NUM_FIFO_VALUES - NUM_DATA_SHOCK_DETECT; entry < NUM_FIFO_VALUES;
|
||||
entry++) {
|
||||
uint16_t abs_X = data_fifo[entry].X_AXIS >= 0 ? data_fifo[entry].X_AXIS :
|
||||
-1*data_fifo[entry].X_AXIS;
|
||||
uint16_t abs_Y = data_fifo[entry].Y_AXIS >= 0 ? data_fifo[entry].Y_AXIS :
|
||||
-1*data_fifo[entry].Y_AXIS;
|
||||
uint16_t abs_Z = data_fifo[entry].Z_AXIS >= 0 ? data_fifo[entry].Z_AXIS :
|
||||
-1*data_fifo[entry].Z_AXIS;
|
||||
|
||||
/* check X shock direction */
|
||||
if (max_data_X <= abs_X) {
|
||||
max_data_X = abs_X;
|
||||
X_shock_pos = (data_fifo[entry].X_AXIS >= 0);
|
||||
}
|
||||
/* check Y shock direction */
|
||||
if (max_data_Y <= abs_Y) {
|
||||
max_data_Y = abs_Y;
|
||||
Y_shock_pos = (data_fifo[entry].Y_AXIS >= 0);
|
||||
}
|
||||
/* check Z shock direction */
|
||||
if (max_data_Z <= abs_Z) {
|
||||
max_data_Z = abs_Z;
|
||||
Z_shock_pos = (data_fifo[entry].Z_AXIS >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG("[Process]: oldX %d, oldY %d, oldZ %d\n", old_data_lis[0], old_data_lis[1],
|
||||
old_data_lis[2]);
|
||||
DEBUG("[Process]: maxX %d, maxY %d, maxZ %d\n", max_data_X, max_data_Y, max_data_Z);
|
||||
|
||||
/* X shock */
|
||||
int16_t diff_value = max_data_X - old_data_lis[0];
|
||||
if (diff_value >= shock_thold) {
|
||||
if (X_shock_pos) {
|
||||
puts("positive X shock detected.");
|
||||
}
|
||||
else {
|
||||
puts("negative X shock detected.");
|
||||
}
|
||||
}
|
||||
/* Y shock */
|
||||
diff_value = max_data_Y - old_data_lis[1];
|
||||
if (diff_value >= shock_thold) {
|
||||
if (Y_shock_pos) {
|
||||
puts("positive Y shock detected.");
|
||||
}
|
||||
else {
|
||||
puts("negative Y shock detected.");
|
||||
}
|
||||
}
|
||||
/* Z shock */
|
||||
diff_value = max_data_Z - old_data_lis[2];
|
||||
if (diff_value >= shock_thold) {
|
||||
if (Z_shock_pos) {
|
||||
puts("positive Z shock detected.");
|
||||
}
|
||||
else {
|
||||
puts("negative Z shock detected.");
|
||||
}
|
||||
}
|
||||
|
||||
/* check for roll */
|
||||
/* roll conditions
|
||||
*
|
||||
* only 180°, changes can be detected with 6D reg in INT1_SRC
|
||||
* change in ZH and ZL -> X-roll (device flipped from top to bottom)
|
||||
* change in YH and YL -> Z-roll
|
||||
* change in XH and XL -> Y-roll
|
||||
*/
|
||||
DEBUG("[Process]: OLD - IA %d; ZH %d; ZL %d; YH %d; YL %d; XH %d; XL %d.\n",
|
||||
int1_src_old & LIS2DH12_INT_SRC_IA,
|
||||
int1_src_old & LIS2DH12_INT_SRC_ZH, int1_src_old & LIS2DH12_INT_SRC_ZL,
|
||||
int1_src_old & LIS2DH12_INT_SRC_YH, int1_src_old & LIS2DH12_INT_SRC_YL,
|
||||
int1_src_old & LIS2DH12_INT_SRC_XH, int1_src_old & LIS2DH12_INT_SRC_XL);
|
||||
|
||||
DEBUG("[Process]: NEW - IA %d; ZH %d; ZL %d; YH %d; YL %d; XH %d; XL %d.\n",
|
||||
int1_src & LIS2DH12_INT_SRC_IA,
|
||||
int1_src & LIS2DH12_INT_SRC_ZH, int1_src & LIS2DH12_INT_SRC_ZL,
|
||||
int1_src & LIS2DH12_INT_SRC_YH, int1_src & LIS2DH12_INT_SRC_YL,
|
||||
int1_src & LIS2DH12_INT_SRC_XH, int1_src & LIS2DH12_INT_SRC_XL);
|
||||
|
||||
if (((int1_src_old & LIS2DH12_INT_SRC_ZH) != (int1_src & LIS2DH12_INT_SRC_ZH))
|
||||
&& ((int1_src_old & LIS2DH12_INT_SRC_ZL) != (int1_src & LIS2DH12_INT_SRC_ZL))) {
|
||||
printf("X roll detected.\n");
|
||||
}
|
||||
if (((int1_src_old & LIS2DH12_INT_SRC_XH) != (int1_src & LIS2DH12_INT_SRC_XH))
|
||||
&& ((int1_src_old & LIS2DH12_INT_SRC_YL) != (int1_src & LIS2DH12_INT_SRC_YL))) {
|
||||
printf("Z roll detected.\n");
|
||||
}
|
||||
if (((int1_src_old & LIS2DH12_INT_SRC_YH) != (int1_src & LIS2DH12_INT_SRC_YH))
|
||||
&& ((int1_src_old & LIS2DH12_INT_SRC_XL) != (int1_src & LIS2DH12_INT_SRC_XL))) {
|
||||
printf("Y roll detected.\n");
|
||||
}
|
||||
|
||||
int1_src_old = int1_src;
|
||||
|
||||
/* check click order */
|
||||
/*
|
||||
* idea is to do a sequence of double clicks, to enable the device
|
||||
*
|
||||
*/
|
||||
/* click_src read during interrupt callback */
|
||||
DEBUG("[Process]: clickSRC 0x%x\n", click_src_reg.reg);
|
||||
|
||||
if (click_src_reg.bit.IA && click_src_reg.bit.DClick) {
|
||||
/* X-Double */
|
||||
if (click_src_reg.bit.X_AXIS && !click_src_reg.bit.Y_AXIS
|
||||
&& !click_src_reg.bit.Z_AXIS) {
|
||||
int8_t sign = click_src_reg.bit.Sign ? -1 : 1;
|
||||
printf("got X-DCLICK, sign %d\n", sign);
|
||||
}
|
||||
/* Y-Double */
|
||||
if (!click_src_reg.bit.X_AXIS && click_src_reg.bit.Y_AXIS
|
||||
&& !click_src_reg.bit.Z_AXIS) {
|
||||
int8_t sign = click_src_reg.bit.Sign ? -1 : 1;
|
||||
printf("got Y-DCLICK, sign %d\n", sign);
|
||||
}
|
||||
/* Z-Double */
|
||||
if (!click_src_reg.bit.X_AXIS && !click_src_reg.bit.Y_AXIS
|
||||
&& click_src_reg.bit.Z_AXIS) {
|
||||
int8_t sign = click_src_reg.bit.Sign ? -1 : 1;
|
||||
printf("got Z-DCLICK, sign %d\n", sign);
|
||||
}
|
||||
}
|
||||
|
||||
/* enable IRQ again */
|
||||
gpio_irq_enable(dev.p->int1_pin);
|
||||
gpio_irq_enable(dev.p->int2_pin);
|
||||
|
||||
/* thread will sleep until next wokeup_lis */
|
||||
thread_sleep();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif /* MODULE_LIS2DH12_INT */
|
||||
|
||||
int shell_lis2dh12_cmd(int argc, char **argv) {
|
||||
|
||||
printf("Command: lis %s %s\n", (argc > 1) ? argv[1] : "",
|
||||
(argc > 2) ? argv[2] : "");
|
||||
#ifdef MODULE_LIS2DH12_INT
|
||||
const char * usage = "USAGE: lis <subcommand> [arg], with subcommand "
|
||||
"in (enable, disable, read, read_fifo, clear_data, "
|
||||
"set-click, set-thold-shock, set-thold-inter, "
|
||||
"set-highpass, change_rate, change_power, change_scale).";
|
||||
#else
|
||||
const char * usage = "USAGE: lis <subcommand> [arg], with subcommand "
|
||||
"in (enable, disable, read, read_fifo, clear_data, "
|
||||
"change_rate, change_power, change_scale).";
|
||||
#endif /* MODULE_LIS2DH12_INT */
|
||||
|
||||
/* MISSING command */
|
||||
if (argc < 2) {
|
||||
printf("Error: Missing sub-command. %s\n", usage);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* enable disable device */
|
||||
else if (strncmp(argv[1], "enable", sizeof("enable")) == 0) {
|
||||
if (lis2dh12_poweron(&dev) != LIS2DH12_OK) {
|
||||
puts("unable to poweron device.");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else if (strncmp(argv[1], "disable", sizeof("disable")) == 0) {
|
||||
if (lis2dh12_poweroff(&dev) != LIS2DH12_OK) {
|
||||
puts("unable to poweroff device.");
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* read acceleration data */
|
||||
else if (strncmp(argv[1], "read", sizeof("read")) == 0) {
|
||||
uint8_t amount = (argc < 3) ? 1 : atoi(argv[2]);
|
||||
uint8_t amt = 0;
|
||||
|
||||
/* read sensor data */
|
||||
for (amt = 0; amt < amount; amt++){
|
||||
if (lis2dh12_read(&dev, data_lis) != LIS2DH12_OK) {
|
||||
puts("error: no data from sensor");
|
||||
return -1;
|
||||
}
|
||||
/* format data */
|
||||
for (int i = 0; i < 3; i++) {
|
||||
size_t len = fmt_s16_dfp(str_out[i], data_lis[i], -3);
|
||||
str_out[i][len] = '\0';
|
||||
}
|
||||
|
||||
/* print data to STDIO */
|
||||
printf("X: %6s Y: %6s Z: %6s\n", str_out[0], str_out[1], str_out[2]);
|
||||
|
||||
xtimer_msleep(250);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else if (strncmp(argv[1], "read_fifo", sizeof("read_fifo")) == 0) {
|
||||
uint8_t number = 0;
|
||||
if ((argc < 3) || (number = atoi(argv[2])) > 32) {
|
||||
puts("Error: Missing parameter.");
|
||||
puts("The command should contain number of FIFO values to read (max. 32)).");
|
||||
puts("USAGE: lis read_fifo [number]");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* read raw data from FIFO */
|
||||
uint8_t number_read = lis2dh12_read_fifo_data(&dev, data_fifo, number);
|
||||
|
||||
DEBUG("[lis_command]: fifo_read %d elements.\n", number_read);
|
||||
|
||||
/* print data */
|
||||
for (int entry = 0; entry < number_read; entry++){
|
||||
|
||||
/* format data */
|
||||
size_t len = fmt_s16_dfp(str_out[0], data_fifo[entry].X_AXIS, -3);
|
||||
str_out[0][len] = '\0';
|
||||
len = fmt_s16_dfp(str_out[1], data_fifo[entry].Y_AXIS, -3);
|
||||
str_out[1][len] = '\0';
|
||||
len = fmt_s16_dfp(str_out[2], data_fifo[entry].Z_AXIS, -3);
|
||||
str_out[2][len] = '\0';
|
||||
|
||||
printf("[%2d] X: %6s Y: %6s Z: %6s\n", entry, str_out[0], str_out[1], str_out[2]);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* clear memory */
|
||||
else if (strncmp(argv[1], "clear_data", sizeof("clear_data")) == 0) {
|
||||
|
||||
lis2dh12_clear_data(&dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef MODULE_LIS2DH12_INT
|
||||
/* set commands */
|
||||
else if (strncmp(argv[1], "set-click", sizeof("set-click")) == 0) {
|
||||
uint8_t thold = 0;
|
||||
if ((argc < 3) || (thold = atoi(argv[2])) > 127) {
|
||||
puts("Error: Missing parameter.");
|
||||
puts("The command should contain a threshold value below 128. "
|
||||
"The LSB changes according to selected SCALE "
|
||||
"(@2G LSB=16mg; @4G LSB=32mg; @8G LSB=62mg: @16G LSB=186mg).");
|
||||
puts("USAGE: lis set-click [thold]");
|
||||
return -1;
|
||||
}
|
||||
|
||||
click_cfg.CLICK_thold = thold;
|
||||
lis2dh12_set_click(&dev, &click_cfg);
|
||||
|
||||
/* enable click interrupt */
|
||||
params_int1.int_type = LIS2DH12_INT_TYPE_I1_CLICK;
|
||||
lis2dh12_set_int(&dev, ¶ms_int1, LIS2DH12_INT1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (strncmp(argv[1], "set-thold-shock", sizeof("set-thold-shock")) == 0) {
|
||||
uint16_t thold = 0;
|
||||
if ((argc < 3) || !(thold = atoi(argv[2]))) {
|
||||
puts("Error: Missing parameter.");
|
||||
puts("The command should contain a threshold value in [mg] below the max SCALE. "
|
||||
"(@2G below 2000; @4G below 4000; and so on)");
|
||||
puts("USAGE: lis set-thold-shock [thold]");
|
||||
return -1;
|
||||
}
|
||||
shock_thold = thold;
|
||||
return 1;
|
||||
}
|
||||
else if (strncmp(argv[1], "set-thold-inter", sizeof("set-thold-inter")) == 0) {
|
||||
uint8_t line = 0;
|
||||
if ((argc < 4) || (line = atoi(argv[3])) > 2) {
|
||||
puts("Error: Missing parameter.");
|
||||
puts("The command should contain threshold value and interrupt line (1 or 2). "
|
||||
"The threshold LSB changes according to selected SCALE "
|
||||
"(@2G LSB=16mg; @4G LSB=32mg; @8G LSB=62mg: @16G LSB=186mg).");
|
||||
puts("To disable interrupt set thold to 0.");
|
||||
puts("USAGE: lis set-thold-inter [thold] [line]");
|
||||
return -1;
|
||||
}
|
||||
uint8_t thold = atoi(argv[2]);
|
||||
if (line == 1) {
|
||||
if (!thold) {
|
||||
params_int1.int_config = 0;
|
||||
}
|
||||
else {
|
||||
/* enables all axes for acceleration above threshold */
|
||||
params_int1.int_config = LIS2DH12_INT_CFG_XHIE
|
||||
| LIS2DH12_INT_CFG_YHIE
|
||||
| LIS2DH12_INT_CFG_ZHIE;
|
||||
}
|
||||
params_int1.int_type = LIS2DH12_INT_TYPE_I1_IA1;
|
||||
params_int1.int_threshold = thold;
|
||||
|
||||
lis2dh12_set_int(&dev, ¶ms_int1, LIS2DH12_INT1);
|
||||
}
|
||||
else if (line == 2){
|
||||
if (!thold) {
|
||||
params_int2.int_config = 0;
|
||||
}
|
||||
else {
|
||||
/* enables Y-axis for acceleration under the threshold */
|
||||
params_int2.int_config = LIS2DH12_INT_CFG_YLIE;
|
||||
}
|
||||
params_int2.int_type = LIS2DH12_INT_TYPE_I2_IA2;
|
||||
params_int2.int_threshold = thold;
|
||||
lis2dh12_set_int(&dev, ¶ms_int2, LIS2DH12_INT2);
|
||||
}
|
||||
if (thold) {
|
||||
printf("Info: Interrupt thold = %d on line %d.\n", thold, line);
|
||||
}
|
||||
else {
|
||||
printf("Info: Interrupt disabled.\n");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
else if (strncmp(argv[1], "set-highpass", sizeof("set-highpass")) == 0) {
|
||||
uint8_t out = 0;
|
||||
uint8_t reference = atoi(argv[2]);
|
||||
if ((argc < 4) || (out = atoi(argv[3])) > 3) {
|
||||
puts("Error: Missing parameter.");
|
||||
puts("The command should contains the number of an output which gets filtered "
|
||||
"and the reference value less than 255. "
|
||||
"Possible outputs are IA1 (1) or IA2 (2) or CLICK (3) "
|
||||
"or (0) to disable the filter.");
|
||||
puts("USAGE: lis set-highpass [reference] [out_number]");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (out) {
|
||||
/* enable filter for output */
|
||||
highpass_cfg.DATA_OUT_enable = 0;
|
||||
|
||||
/* enable HP for interrupt */
|
||||
if (out == 1) {
|
||||
highpass_cfg.INT1_enable = 1;
|
||||
}
|
||||
else if (out == 2) {
|
||||
highpass_cfg.INT2_enable = 1;
|
||||
}
|
||||
else {
|
||||
/* enable filter for click function */
|
||||
highpass_cfg.CLICK_enable = 1;
|
||||
}
|
||||
printf("Info: Filter set to %d on output %d.\n", reference, out);
|
||||
}
|
||||
else {
|
||||
printf("Info: Filter disabled.\n");
|
||||
}
|
||||
|
||||
lis2dh12_set_reference(&dev, reference);
|
||||
lis2dh12_set_highpass(&dev, &highpass_cfg);
|
||||
return 1;
|
||||
}
|
||||
#endif /* MODULE_LIS2DH12_INT */
|
||||
|
||||
/* change sampling rate */
|
||||
else if (strncmp(argv[1], "change_rate", sizeof("change_rate")) == 0) {
|
||||
uint8_t rate = 0;
|
||||
if ((argc < 3) || (rate = atoi(argv[2])) > 9) {
|
||||
puts("Error: Missing parameter.");
|
||||
puts("The command should contain a number for sampling rate. "
|
||||
"Possible outputs are 1Hz (1), 10Hz (2), 25Hz (3), "
|
||||
"50Hz (4), 100Hz (5), 200Hz (6) or 400Hz (7).");
|
||||
puts("USAGE: lis change_rate [samplingrate]");
|
||||
return -1;
|
||||
}
|
||||
|
||||
lis2dh12_set_datarate(&dev, rate);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* change power mode */
|
||||
else if (strncmp(argv[1], "change_power", sizeof("change_power")) == 0) {
|
||||
uint8_t power = 0;
|
||||
if ((argc < 3) || (power = atoi(argv[2])) > 9) {
|
||||
puts("Error: Missing parameter.");
|
||||
puts("The command should contain a number for power mode. "
|
||||
"Possible outputs are POWER_DOWN (0), POWER_LOW (1), "
|
||||
"POWER_NORMAL (2) or POWER_HIGH (3).");
|
||||
puts("USAGE: lis change_power [powermode]");
|
||||
return -1;
|
||||
}
|
||||
|
||||
lis2dh12_set_powermode(&dev, power);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* change scale value */
|
||||
else if (strncmp(argv[1], "change_scale", sizeof("change_scale")) == 0) {
|
||||
uint8_t scale = 0;
|
||||
if ((argc < 3) || (scale = atoi(argv[2])) > 3) {
|
||||
puts("Error: Missing parameter.");
|
||||
puts("The command should contain a number for scale value. "
|
||||
"Possible values are SCALE_2G (0), SCALE_4G (1), "
|
||||
"SCALE_8G (2) or SCALE_16G (3).");
|
||||
puts("USAGE: lis change_scale [scale]");
|
||||
return -1;
|
||||
}
|
||||
|
||||
lis2dh12_set_scale(&dev, scale<<4);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* UNKNOWN */
|
||||
else {
|
||||
printf("Error: Unknown sub-command. %s\n", usage);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
||||
#ifdef MODULE_LIS2DH12_INT
|
||||
uint8_t flags = 0;
|
||||
#endif
|
||||
/* processing lis2dh12 acceleration data */
|
||||
lis2dh12_process = thread_create(lis2dh12_process_stack, sizeof(lis2dh12_process_stack),
|
||||
THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_SLEEPING,
|
||||
lis2dh12_test_process, NULL, "lis2dh12_process");
|
||||
#endif /* MODULE_LIS2DH12_INT */
|
||||
|
||||
puts("LIS2DH12 accelerometer driver test application\n");
|
||||
/* init lis */
|
||||
lis2dh12_test_init();
|
||||
|
||||
puts("Initializing LIS2DH12 sensor... ");
|
||||
if (lis2dh12_init(&dev, &lis2dh12_params[0]) == LIS2DH12_OK) {
|
||||
puts("[OK]");
|
||||
}
|
||||
else {
|
||||
puts("[Failed]\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef MODULE_LIS2DH12_INT
|
||||
/* enable interrupt Pins */
|
||||
if (gpio_is_valid(lis2dh12_params[0].int1_pin)) {
|
||||
/* create and set the interrupt params */
|
||||
lis2dh12_int_params_t params_int1 = {
|
||||
.int_type = LIS2DH12_INT_TYPE_I1_IA1,
|
||||
.int_config = LIS2DH12_INT_CFG_XLIE,
|
||||
.int_threshold = 31,
|
||||
.int_duration = 1,
|
||||
.cb = lis2dh12_int_cb,
|
||||
.arg = &ctx[0],
|
||||
};
|
||||
lis2dh12_set_int(&dev, ¶ms_int1, LIS2DH12_INT1);
|
||||
}
|
||||
|
||||
/* create and set the interrupt params */
|
||||
if (gpio_is_valid(lis2dh12_params[0].int2_pin)) {
|
||||
lis2dh12_int_params_t params_int2 = {
|
||||
.int_type = LIS2DH12_INT_TYPE_I2_IA2,
|
||||
.int_config = LIS2DH12_INT_CFG_YLIE,
|
||||
.int_threshold = 31,
|
||||
.int_duration = 1,
|
||||
.cb = lis2dh12_int_cb,
|
||||
.arg = &ctx[1],
|
||||
};
|
||||
lis2dh12_set_int(&dev, ¶ms_int2, LIS2DH12_INT2);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
|
||||
#ifdef MODULE_LIS2DH12_INT
|
||||
if (xtimer_mutex_lock_timeout(&isr_mtx, DELAY) == 0) {
|
||||
flags = isr_flags;
|
||||
isr_flags = 0;
|
||||
}
|
||||
|
||||
/* check interrupt 1 and read register */
|
||||
if (flags & 0x1) {
|
||||
printf("reads interrupt %d\n", LIS2DH12_INT1);
|
||||
lis2dh12_int_reg_content(&dev, LIS2DH12_INT1);
|
||||
flags &= ~(0x1);
|
||||
}
|
||||
/* check interrupt 2 and read register */
|
||||
if (flags & 0x2) {
|
||||
printf("reads interrupt %d\n", LIS2DH12_INT2);
|
||||
lis2dh12_int_reg_content(&dev, LIS2DH12_INT2);
|
||||
flags &= ~(0x2);
|
||||
}
|
||||
#else
|
||||
xtimer_usleep(DELAY);
|
||||
#endif
|
||||
|
||||
/* read sensor data */
|
||||
int16_t data[3];
|
||||
if (lis2dh12_read(&dev, data) != LIS2DH12_OK) {
|
||||
puts("error: unable to retrieve data from sensor");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* format data */
|
||||
for (int i = 0; i < 3; i++) {
|
||||
size_t len = fmt_s16_dfp(str_out[i], data[i], -3);
|
||||
str_out[i][len] = '\0';
|
||||
}
|
||||
|
||||
/* print data to STDIO */
|
||||
printf("X: %8s Y: %8s Z: %8s\n", str_out[0], str_out[1], str_out[2]);
|
||||
}
|
||||
/* running shell */
|
||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user