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:
parent
681678e3f3
commit
aa5ffe5a6d
@ -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)))
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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" }
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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, ¶ms_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, ¶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, 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;
|
||||
|
Loading…
Reference in New Issue
Block a user