1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

drivers/lis2dh12: added interrupt function

This commit is contained in:
Jan Mohr 2020-02-25 15:37:34 +01:00 committed by Jan Mohr
parent 681678e3f3
commit aa5ffe5a6d
7 changed files with 339 additions and 14 deletions

View File

@ -323,14 +323,18 @@ ifneq (,$(filter lc709203f,$(USEMODULE)))
FEATURES_REQUIRED += periph_gpio_irq
endif
ifneq (,$(filter lis2dh12_int,$(USEMODULE)))
FEATURES_REQUIRED += periph_gpio_irq
endif
ifneq (,$(filter lis2dh12%,$(USEMODULE)))
USEMODULE += lis2dh12
ifneq (,$(filter lis2dh12_spi,$(USEMODULE)))
FEATURES_REQUIRED += periph_gpio
FEATURES_REQUIRED += periph_spi
else
FEATURES_REQUIRED += periph_i2c
endif
USEMODULE += lis2dh12
endif
ifneq (,$(filter lis3dh,$(USEMODULE)))

View File

@ -40,9 +40,9 @@
#include "saul.h"
#include "periph/gpio.h"
#ifdef MODULE_LIS2DH12_SPI
#include "periph/spi.h"
#include "periph/gpio.h"
#else
#include "periph/i2c.h"
#endif
@ -88,12 +88,16 @@ typedef enum {
* @brief LIS2DH12 configuration parameters
*/
typedef struct {
#ifdef MODULE_LIS2DH12_SPI
#if MODULE_LIS2DH12_SPI || DOXYGEN
spi_t spi; /**< SPI bus the device is connected to */
gpio_t cs; /**< connected chip select pin */
#else
i2c_t i2c; /**< I2C bus the device is connected to */
uint8_t addr; /**< device address on the I2C bus */
#endif
#if MODULE_LIS2DH12_INT || DOXYGEN
gpio_t int1_pin; /**< first interrupt pin */
gpio_t int2_pin; /**< second interrupt pin */
#endif
lis2dh12_scale_t scale; /**< sampling sensitivity used */
lis2dh12_rate_t rate; /**< sampling rate used */
@ -114,13 +118,121 @@ 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_NODATA= -4, /**< no data available */
};
#if MODULE_LIS2DH12_INT || DOXYGEN
/*
* @brief Interrupt lines
*/
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_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
*/
#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 */
/**
* @brief Export the SAUL interface for this driver
*/
extern const saul_driver_t lis2dh12_saul_driver;
#if MODULE_LIS2DH12_INT || DOXYGEN
/**
* @brief Set the interrupt values in LIS2DH12 sensor device
*
* @param[in] dev device descriptor
* @param[in] params device interrupt configuration
* @param[in] int_line number of interrupt line (LIS2DH12_INT1 or LIS2DH12_INT2)
*
* @return LIS2DH12_OK on success
* @return LIS2DH12_NOBUS on bus errors
*/
int lis2dh12_set_int(const lis2dh12_t *dev, const lis2dh12_int_params_t *params, uint8_t int_line);
/**
* @brief Read an interrupt event on LIS2DH12 sensor device
*
* @param[in] dev device descriptor
* @param[out] data device interrupt data
* @param[in] int_line number of interrupt line (LIS2DH12_INT1 or LIS2DH12_INT2)
*
* @return LIS2DH12_OK on success
* @return LIS2DH12_NOBUS on bus errors
*/
int lis2dh12_read_int_src(const lis2dh12_t *dev, uint8_t *data, uint8_t int_line);
#endif /* MODULE_LIS2DH12_INT */
/**
* @brief Initialize the given LIS2DH12 sensor device
*

View File

@ -53,6 +53,14 @@ extern "C" {
#endif
#ifndef LIS2DH12_PARAM_INT_PIN1
#define LIS2DH12_PARAM_INT_PIN1 GPIO_UNDEF
#endif
#ifndef LIS2DH12_PARAM_INT_PIN2
#define LIS2DH12_PARAM_INT_PIN2 GPIO_UNDEF
#endif
#ifndef LIS2DH12_PARAM_SCALE
#define LIS2DH12_PARAM_SCALE LIS2DH12_SCALE_2G
#endif
@ -61,10 +69,22 @@ extern "C" {
#endif
#ifndef LIS2DH12_PARAMS
#define LIS2DH12_PARAMS { LIS2DH12_PARAMS_BUSCFG, \
.scale = LIS2DH12_PARAM_SCALE, \
.rate = LIS2DH12_PARAM_RATE, }
#endif
#ifdef MODULE_LIS2DH12_INT
#define LIS2DH12_PARAMS { \
LIS2DH12_PARAMS_BUSCFG, \
.int1_pin = LIS2DH12_PARAM_INT_PIN1, \
.int2_pin = LIS2DH12_PARAM_INT_PIN2, \
.scale = LIS2DH12_PARAM_SCALE, \
.rate = LIS2DH12_PARAM_RATE, \
}
#else /* MODULE_LIS2DH12_INT */
#define LIS2DH12_PARAMS { \
LIS2DH12_PARAMS_BUSCFG, \
.scale = LIS2DH12_PARAM_SCALE, \
.rate = LIS2DH12_PARAM_RATE, \
}
#endif /* MODULE_LIS2DH12_INT */
#endif /* LIS2DH12_PARAMS */
#ifndef LIS2DH12_SAULINFO
#define LIS2DH12_SAULINFO { .name = "lis2dh12" }

View File

@ -172,6 +172,13 @@ int lis2dh12_read(const lis2dh12_t *dev, int16_t *data)
/* read sampled data from the device */
_acquire(dev);
/* first check if valid data is available */
if ((_read(dev, REG_STATUS_REG) & LIS2DH12_STATUS_ZYXDA) == 0) {
_release(dev);
return LIS2DH12_NODATA;
}
_read_burst(dev, REG_OUT_X_L, raw, 6);
_release(dev);
@ -187,6 +194,78 @@ int lis2dh12_read(const lis2dh12_t *dev, int16_t *data)
return LIS2DH12_OK;
}
#ifdef MODULE_LIS2DH12_INT
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);
_acquire(dev);
gpio_t pin = GPIO_UNDEF;
switch (int_line){
/* first interrupt line (INT1) */
case LIS2DH12_INT1:
pin = dev->p->int1_pin;
assert (pin != GPIO_UNDEF);
if (gpio_init_int(pin, GPIO_IN, GPIO_RISING, params->cb, params->arg)) {
return LIS2DH12_NOINT;
}
_write(dev, REG_CTRL_REG3, params->int_type);
_write(dev, REG_INT1_CFG, params->int_config);
_write(dev, REG_INT1_THS, params->int_threshold);
_write(dev, REG_INT1_DURATION, params->int_duration);
break;
/* second interrupt line (INT2) */
case LIS2DH12_INT2:
pin = dev->p->int2_pin;
assert (pin != GPIO_UNDEF);
if (gpio_init_int(pin, GPIO_IN, GPIO_RISING, params->cb, params->arg)) {
return LIS2DH12_NOINT;
}
_write(dev, REG_CTRL_REG6, params->int_type);
_write(dev, REG_INT2_CFG, params->int_config);
_write(dev, REG_INT2_THS, params->int_threshold);
_write(dev, REG_INT2_DURATION, params->int_duration);
break;
}
_release(dev);
return LIS2DH12_OK;
}
int lis2dh12_read_int_src(const lis2dh12_t *dev, uint8_t *data, uint8_t int_line)
{
assert(dev && data);
assert(int_line == LIS2DH12_INT1 || int_line == LIS2DH12_INT2);
_acquire(dev);
switch (int_line) {
/* first interrupt line (INT1) */
case LIS2DH12_INT1:
*data = _read(dev, REG_INT1_SRC);
break;
/* second interrupt line (INT2) */
case LIS2DH12_INT2:
*data = _read(dev, REG_INT2_SRC);
break;
}
_release(dev);
return LIS2DH12_OK;
}
#endif /* MODULE_LIS2DH12_INT */
int lis2dh12_poweron(const lis2dh12_t *dev)
{
assert(dev);

View File

@ -49,6 +49,7 @@ PSEUDOMODULES += ina3221_alerts
PSEUDOMODULES += l2filter_blacklist
PSEUDOMODULES += l2filter_whitelist
PSEUDOMODULES += lis2dh12_i2c
PSEUDOMODULES += lis2dh12_int
PSEUDOMODULES += lis2dh12_spi
PSEUDOMODULES += log
PSEUDOMODULES += log_printfnoformat

View File

@ -1,10 +1,13 @@
include ../Makefile.tests_common
# as default we use the SPI mode for now, as the I2C mode is not supported, yet
# use lis2dh12_spi for SPI-Mode and lis2dh12_i2c for I2C-Mode
DRIVER ?= lis2dh12_spi
USEMODULE += fmt
USEMODULE += xtimer
USEMODULE += $(DRIVER)
# for using lis2dh12 with interrupt function
USEMODULE += lis2dh12_int
include $(RIOTBASE)/Makefile.include

View File

@ -22,10 +22,11 @@
#include "fmt.h"
#include "xtimer.h"
#include "mutex.h"
#include "lis2dh12.h"
#include "lis2dh12_params.h"
/* delay between sensor data reads */
#define DELAY (100UL * US_PER_MS)
/* allocate some memory to hold one formatted string for each sensor output, so
@ -35,8 +36,64 @@ static char str_out[3][8];
/* 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;
/* 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 callback function. */
static void lis2dh12_int_cb(void* _ctx) {
lis_ctx *control = _ctx;
*control->flags |= control->line;
mutex_unlock(control->lock);
}
/* print interrupt register */
static void lis2dh12_int_reg_content(lis2dh12_t *dev, uint8_t pin){
assert(pin == LIS2DH12_INT1 || pin == LIS2DH12_INT2);
uint8_t buffer;
lis2dh12_read_int_src(dev, &buffer, pin);
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));
}
#endif
int main(void)
{
#ifdef MODULE_LIS2DH12_INT
uint8_t flags = 0;
#endif
puts("LIS2DH12 accelerometer driver test application\n");
puts("Initializing LIS2DH12 sensor... ");
@ -48,13 +105,64 @@ int main(void)
return 1;
}
xtimer_ticks32_t last_wakeup = xtimer_now();
#ifdef MODULE_LIS2DH12_INT
/* enable interrupt Pins */
if (lis2dh12_params[0].int1_pin != GPIO_UNDEF) {
/* 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, &params_int1, LIS2DH12_INT1);
}
/* create and set the interrupt params */
if (lis2dh12_params[0].int2_pin != GPIO_UNDEF) {
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, &params_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, quitting now");
return 1;
puts("error: unable to retrieve data from sensor");
continue;
}
/* format data */
@ -65,8 +173,6 @@ int main(void)
/* print data to STDIO */
printf("X: %8s Y: %8s Z: %8s\n", str_out[0], str_out[1], str_out[2]);
xtimer_periodic_wakeup(&last_wakeup, DELAY);
}
return 0;