From c9bdbd1a74b7d1fe2205cb7f16a73176d5d71b30 Mon Sep 17 00:00:00 2001 From: Joakim Gebart Date: Sun, 24 May 2015 17:20:23 +0200 Subject: [PATCH] lis3dh: Refactor, add INT1 handling, improve FIFO mode --- drivers/include/lis3dh.h | 115 +++++++++++++++++++++---------------- drivers/lis3dh/lis3dh.c | 79 +++++++++++++++++++------ tests/driver_lis3dh/main.c | 71 +++++++++++++++++------ 3 files changed, 181 insertions(+), 84 deletions(-) diff --git a/drivers/include/lis3dh.h b/drivers/include/lis3dh.h index 9313c908e..b2cf6b912 100644 --- a/drivers/include/lis3dh.h +++ b/drivers/include/lis3dh.h @@ -16,7 +16,7 @@ * @brief Device driver interface for the LIS3DH accelerometer * * - * @author Joakim Gebart */ #ifndef LIS3DH_H_ @@ -243,7 +243,7 @@ typedef enum { * @brief High pass filter enabled for CLICK function. * * 0. filter bypassed - * 1. filter enabled@ + * 1. filter enabled */ #define LIS3DH_CTRL_REG2_HPCLICK_MASK (1 << 2) @@ -387,17 +387,17 @@ typedef enum { /** @} */ /** - * @brief Scale parameters + * @name Scale parameters * * Use these names when calling lis3dh_set_scale() */ -typedef enum { - LIS3DH_SCALE_2G = (0), /**< Scale: +/- 2G */ - LIS3DH_SCALE_4G = (LIS3DH_CTRL_REG4_FS0_MASK), /**< Scale: +/- 4G */ - LIS3DH_SCALE_8G = (LIS3DH_CTRL_REG4_FS1_MASK), /**< Scale: +/- 8G */ - /** Scale: +/- 16G */ - LIS3DH_SCALE_16G = (LIS3DH_CTRL_REG4_FS1_MASK | LIS3DH_CTRL_REG4_FS0_MASK) -} lis3dh_scale_t; +/** @{ */ +#define LIS3DH_SCALE_2G (0) /**< Scale: +/- 2G */ +#define LIS3DH_SCALE_4G (LIS3DH_CTRL_REG4_FS0_MASK) /**< Scale: +/- 4G */ +#define LIS3DH_SCALE_8G (LIS3DH_CTRL_REG4_FS1_MASK) /**< Scale: +/- 8G */ +/** Scale: +/- 16G */ +#define LIS3DH_SCALE_16G (LIS3DH_CTRL_REG4_FS1_MASK | LIS3DH_CTRL_REG4_FS0_MASK) +/** @} */ /** * @brief High resolution output mode @@ -643,38 +643,40 @@ typedef enum { /** - * @brief Allowed values for the Output Data Rate of the sensor. + * @name Output Data Rates (ODR) * * Use these when calling lis3dh_set_odr(odr). */ -typedef enum { - LIS3DH_ODR_POWERDOWN = (0x00 << LIS3DH_CTRL_REG1_ODR_SHIFT), - LIS3DH_ODR_1Hz = (0x01 << LIS3DH_CTRL_REG1_ODR_SHIFT), - LIS3DH_ODR_10Hz = (0x02 << LIS3DH_CTRL_REG1_ODR_SHIFT), - LIS3DH_ODR_25Hz = (0x03 << LIS3DH_CTRL_REG1_ODR_SHIFT), - LIS3DH_ODR_50Hz = (0x04 << LIS3DH_CTRL_REG1_ODR_SHIFT), - LIS3DH_ODR_100Hz = (0x05 << LIS3DH_CTRL_REG1_ODR_SHIFT), - LIS3DH_ODR_200Hz = (0x06 << LIS3DH_CTRL_REG1_ODR_SHIFT), - LIS3DH_ODR_400Hz = (0x07 << LIS3DH_CTRL_REG1_ODR_SHIFT), - LIS3DH_ODR_LP1600Hz = (0x08 << LIS3DH_CTRL_REG1_ODR_SHIFT), - LIS3DH_ODR_NP1250Hz_LP5000HZ = (0x09 << LIS3DH_CTRL_REG1_ODR_SHIFT) -} lis3dh_odr_t; +/** @{ */ +#define LIS3DH_ODR_POWERDOWN (0x00 << LIS3DH_CTRL_REG1_ODR_SHIFT) +#define LIS3DH_ODR_1Hz (0x01 << LIS3DH_CTRL_REG1_ODR_SHIFT) +#define LIS3DH_ODR_10Hz (0x02 << LIS3DH_CTRL_REG1_ODR_SHIFT) +#define LIS3DH_ODR_25Hz (0x03 << LIS3DH_CTRL_REG1_ODR_SHIFT) +#define LIS3DH_ODR_50Hz (0x04 << LIS3DH_CTRL_REG1_ODR_SHIFT) +#define LIS3DH_ODR_100Hz (0x05 << LIS3DH_CTRL_REG1_ODR_SHIFT) +#define LIS3DH_ODR_200Hz (0x06 << LIS3DH_CTRL_REG1_ODR_SHIFT) +#define LIS3DH_ODR_400Hz (0x07 << LIS3DH_CTRL_REG1_ODR_SHIFT) +#define LIS3DH_ODR_LP1600Hz (0x08 << LIS3DH_CTRL_REG1_ODR_SHIFT) +/* Normal mode 1250 Hz and Low power mode 5000 Hz share the same setting */ +#define LIS3DH_ODR_NP1250Hz (0x09 << LIS3DH_CTRL_REG1_ODR_SHIFT) +#define LIS3DH_ODR_LP5000HZ (0x09 << LIS3DH_CTRL_REG1_ODR_SHIFT) +/** @} */ /** - * @brief Allowed FIFO modes. + * @name FIFO modes. * - * Used when calling lis3dh_set_fifo_mode() + * Used when calling lis3dh_set_fifo() */ -typedef enum { - /** FIFO mode: Bypass */ - LIS3DH_FIFO_MODE_BYPASS = (0x00 << LIS3DH_FIFO_CTRL_REG_FM_SHIFT), - /** FIFO mode: FIFO */ - LIS3DH_FIFO_MODE_FIFO = (0x01 << LIS3DH_FIFO_CTRL_REG_FM_SHIFT), - /** FIFO mode: Stream */ - LIS3DH_FIFO_MODE_STREAM = (0x02 << LIS3DH_FIFO_CTRL_REG_FM_SHIFT), - /** FIFO mode: Stream to FIFO */ - LIS3DH_FIFO_MODE_STREAM_TO_FIFO = (0x03 << LIS3DH_FIFO_CTRL_REG_FM_SHIFT) -} lis3dh_fifo_mode_t; +/** @{ */ +/** FIFO mode: Bypass */ +#define LIS3DH_FIFO_MODE_BYPASS (0x00 << LIS3DH_FIFO_CTRL_REG_FM_SHIFT) +/** FIFO mode: FIFO */ +#define LIS3DH_FIFO_MODE_FIFO (0x01 << LIS3DH_FIFO_CTRL_REG_FM_SHIFT) +/** FIFO mode: Stream */ +#define LIS3DH_FIFO_MODE_STREAM (0x02 << LIS3DH_FIFO_CTRL_REG_FM_SHIFT) +/** FIFO mode: Stream to FIFO */ +#define LIS3DH_FIFO_MODE_STREAM_TO_FIFO (0x03 << LIS3DH_FIFO_CTRL_REG_FM_SHIFT) +/** @} */ /** * @brief Device descriptor for LIS3DH sensors @@ -712,7 +714,7 @@ lis3dh_data_t; * @return 0 on success * @return -1 on error */ -int lis3dh_init(lis3dh_t *dev, spi_t spi, gpio_t cs_pin, gpio_t int1_pin, gpio_t int2_pin, lis3dh_scale_t scale); +int lis3dh_init(lis3dh_t *dev, spi_t spi, gpio_t cs_pin, gpio_t int1_pin, gpio_t int2_pin, uint8_t scale); /** * @brief Read 3D acceleration data from the accelerometer @@ -792,51 +794,64 @@ int lis3dh_set_aux_adc(lis3dh_t *dev, const uint8_t enable, const uint8_t temper int lis3dh_set_axes(lis3dh_t *dev, const uint8_t axes); /** - * @brief Set the FIFO mode. + * @brief Enable/disable the FIFO. * * @param[in] dev Device descriptor of sensor - * @param[in] mode The chosen FIFO mode. + * @param[in] mode FIFO mode, see data sheet for details. + * @param[in] watermark Watermark level for FIFO level interrupts * * @return 0 on success * @return -1 on error */ -int lis3dh_set_fifo_mode(lis3dh_t *dev, const lis3dh_fifo_mode_t mode); +int lis3dh_set_fifo(lis3dh_t *dev, const uint8_t mode, const uint8_t watermark); /** - * @brief Enable/disable the FIFO. + * Set the output data rate of the sensor. * * @param[in] dev Device descriptor of sensor - * @param[in] enable If zero, disable the FIFO, otherwise enables the FIFO. + * @param[in] odr Chosen output data rate. * * @return 0 on success * @return -1 on error */ -int lis3dh_set_fifo(lis3dh_t *dev, const uint8_t enable); +int lis3dh_set_odr(lis3dh_t *dev, const uint8_t odr); /** - * Set the output data rate of the sensor. + * @brief Set the full scale range of the sensor. + * + * Valid values for scale is 2, 4, 8, 16 and represents the full range of the + * sensor. * * @param[in] dev Device descriptor of sensor - * @param[in] odr Chosen output data rate. + * @param[in] scale The chosen sensitivity scale. * * @return 0 on success * @return -1 on error */ -int lis3dh_set_odr(lis3dh_t *dev, const lis3dh_odr_t odr); +int lis3dh_set_scale(lis3dh_t *dev, const uint8_t scale); /** - * @brief Set the full scale range of the sensor. + * @brief Set INT1 pin function * - * Valid values for scale is 2, 4, 8, 16 and represents the full range of the - * sensor. + * Set the bits of CTRL_REG3 for choosing sources for the INT1 pin. * * @param[in] dev Device descriptor of sensor - * @param scale The chosen sensitivity scale. + * @param[in] mode CTRL_REG3 value, see data sheet for details. * * @return 0 on success * @return -1 on error */ -int lis3dh_set_scale(lis3dh_t *dev, const lis3dh_scale_t scale); +int lis3dh_set_int1(lis3dh_t *dev, const uint8_t mode); + +/** + * @brief Get the current number of elements in the FIFO + * + * @param[in] dev Device descriptor of sensor + * + * @return number of elements in device FIFO on success + * @return -1 on error + */ +int lis3dh_get_fifo_level(lis3dh_t *dev); #ifdef __cplusplus } diff --git a/drivers/lis3dh/lis3dh.c b/drivers/lis3dh/lis3dh.c index 35d7a7027..057897223 100644 --- a/drivers/lis3dh/lis3dh.c +++ b/drivers/lis3dh/lis3dh.c @@ -30,7 +30,7 @@ static int lis3dh_read_regs(const lis3dh_t *dev, const lis3dh_reg_t reg, const u uint8_t *buf); -int lis3dh_init(lis3dh_t *dev, spi_t spi, gpio_t cs_pin, gpio_t int1_pin, gpio_t int2_pin, lis3dh_scale_t scale) +int lis3dh_init(lis3dh_t *dev, spi_t spi, gpio_t cs_pin, gpio_t int1_pin, gpio_t int2_pin, uint8_t scale) { uint8_t in; @@ -54,11 +54,29 @@ int lis3dh_init(lis3dh_t *dev, spi_t spi, gpio_t cs_pin, gpio_t int1_pin, gpio_t return -1; } - /* Set block data update and little endian mode. */ + /* Clear all settings */ + lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG1, LIS3DH_CTRL_REG1_XYZEN_MASK); + /* Disable HP filter */ + lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG2, 0); + /* Disable INT1 interrupt sources */ + lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG3, 0); + /* Set block data update and little endian, set Normal mode (LP=0, HR=1) */ lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG4, (LIS3DH_CTRL_REG4_BDU_ENABLE | - LIS3DH_CTRL_REG4_BLE_LITTLE_ENDIAN)); + LIS3DH_CTRL_REG4_BLE_LITTLE_ENDIAN | + LIS3DH_CTRL_REG4_HR_MASK)); + /* Disable FIFO */ + lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG5, 0); + /* Reset INT2 settings */ + lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG6, 0); + + /* Configure scale */ lis3dh_set_scale(dev, scale); + + /* Initialize the interrupt pins */ + gpio_init(dev->int1, GPIO_DIR_IN, GPIO_NOPULL); + gpio_init(dev->int2, GPIO_DIR_IN, GPIO_NOPULL); + return 0; } @@ -124,27 +142,37 @@ int lis3dh_set_axes(lis3dh_t *dev, const uint8_t axes) return lis3dh_write_bits(dev, LIS3DH_REG_CTRL_REG1, LIS3DH_CTRL_REG1_XYZEN_MASK, axes); } -int lis3dh_set_fifo_mode(lis3dh_t *dev, const lis3dh_fifo_mode_t mode) -{ - return lis3dh_write_bits(dev, LIS3DH_REG_FIFO_CTRL_REG, LIS3DH_FIFO_CTRL_REG_FM_MASK, - mode); -} - -int lis3dh_set_fifo(lis3dh_t *dev, const uint8_t enable) +int lis3dh_set_fifo(lis3dh_t *dev, const uint8_t mode, const uint8_t watermark) { - return lis3dh_write_bits(dev, LIS3DH_REG_CTRL_REG5, LIS3DH_CTRL_REG5_FIFO_EN_MASK, - (enable ? LIS3DH_CTRL_REG5_FIFO_EN_MASK : 0)); + int status; + uint8_t reg; + reg = (watermark << LIS3DH_FIFO_CTRL_REG_FTH_SHIFT) + & LIS3DH_FIFO_CTRL_REG_FTH_MASK; + reg |= mode; + status = lis3dh_write_reg(dev, LIS3DH_REG_FIFO_CTRL_REG, reg); + if (status < 0) { + /* communication error */ + return status; + } + if (mode != 0x00) { + status = lis3dh_write_bits(dev, LIS3DH_REG_CTRL_REG5, + LIS3DH_CTRL_REG5_FIFO_EN_MASK, LIS3DH_CTRL_REG5_FIFO_EN_MASK); + } else { + status = lis3dh_write_bits(dev, LIS3DH_REG_CTRL_REG5, + LIS3DH_CTRL_REG5_FIFO_EN_MASK, 0); + } + return status; } -int lis3dh_set_odr(lis3dh_t *dev, const lis3dh_odr_t odr) +int lis3dh_set_odr(lis3dh_t *dev, const uint8_t odr) { - return lis3dh_write_bits(dev, LIS3DH_REG_CTRL_REG1, LIS3DH_CTRL_REG1_ODR_MASK, - odr); + return lis3dh_write_bits(dev, LIS3DH_REG_CTRL_REG1, + LIS3DH_CTRL_REG1_ODR_MASK, odr); } -int lis3dh_set_scale(lis3dh_t *dev, const lis3dh_scale_t scale) +int lis3dh_set_scale(lis3dh_t *dev, const uint8_t scale) { - /* Sensor full range is -32768 -- +32767 */ + /* Sensor full range is -32768 -- +32767 (measurements are left adjusted) */ /* => Scale factor is scale/32768 */ switch (scale) { @@ -167,6 +195,23 @@ int lis3dh_set_scale(lis3dh_t *dev, const lis3dh_scale_t scale) scale); } +int lis3dh_set_int1(lis3dh_t *dev, const uint8_t mode) +{ + return lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG3, mode); +} + +int lis3dh_get_fifo_level(lis3dh_t *dev) +{ + uint8_t reg; + int level; + + if (lis3dh_read_regs(dev, LIS3DH_REG_FIFO_SRC_REG, 1, ®) != 0) { + return -1; + } + level = (reg & LIS3DH_FIFO_SRC_REG_FSS_MASK) >> LIS3DH_FIFO_SRC_REG_FSS_SHIFT; + return level; +} + /** * @brief Read sequential registers from the LIS3DH. diff --git a/tests/driver_lis3dh/main.c b/tests/driver_lis3dh/main.c index e218c3a5b..45f48f733 100644 --- a/tests/driver_lis3dh/main.c +++ b/tests/driver_lis3dh/main.c @@ -23,6 +23,7 @@ #include "board.h" #include "vtimer.h" #include "periph/spi.h" +#include "periph/gpio.h" #include "lis3dh.h" /* Check for definition of hardware pins, default to board.h values if not set. */ @@ -60,16 +61,26 @@ #define ODR LIS3DH_ODR_100Hz #define SLEEP (100 * 1000U) #define SPI_CONF (SPI_CONF_SECOND_FALLING) +#define SPI_SPEED (SPI_SPEED_10MHZ) + +#define WATERMARK_LEVEL 16 + +static volatile int int1_count = 0; + +static void test_int1(void *arg) +{ + volatile int *int1_count_ptr = arg; + ++(*int1_count_ptr); +} int main(void) { lis3dh_t dev; lis3dh_data_t acc_data; - int16_t temperature; puts("LIS3DH accelerometer driver test application\n"); printf("Initializing SPI_%i... ", TEST_LIS3DH_SPI); - if (spi_init_master(TEST_LIS3DH_SPI, SPI_CONF, SPI_SPEED_10MHZ) == 0) { + if (spi_init_master(TEST_LIS3DH_SPI, SPI_CONF, SPI_SPEED) == 0) { puts("[OK]"); } else { @@ -114,8 +125,8 @@ int main(void) return 1; } - puts("Disable FIFO mode... "); - if (lis3dh_set_fifo(&dev, 0) == 0) { + puts("Enable streaming FIFO mode... "); + if (lis3dh_set_fifo(&dev, LIS3DH_FIFO_MODE_STREAM, WATERMARK_LEVEL) == 0) { puts("[OK]"); } else { @@ -132,23 +143,49 @@ int main(void) return 1; } + puts("Set INT1 watermark function... "); + if (lis3dh_set_int1(&dev, LIS3DH_CTRL_REG3_I1_WTM_MASK) == 0) { + puts("[OK]"); + } + else { + puts("[Failed]\n"); + return 1; + } + + puts("Set INT1 callback"); + if (gpio_init_int(dev.int1, GPIO_NOPULL, GPIO_RISING, test_int1, (void*)&int1_count) == 0) { + puts("[OK]"); + } + else { + puts("[Failed]\n"); + return 1; + } + puts("LIS3DH init done.\n"); while (1) { - lis3dh_read_xyz(&dev, &acc_data); - if (lis3dh_read_xyz(&dev, &acc_data) != 0) { - puts("Reading acceleration data... "); - puts("[Failed]\n"); - return 1; + int fifo_level; + + fifo_level = lis3dh_get_fifo_level(&dev); + printf("int1_count = %d\n", int1_count); + printf("Reading %d measurements\n", fifo_level); + while (fifo_level > 0) { + int16_t temperature; + int int1; + if (lis3dh_read_xyz(&dev, &acc_data) != 0) { + puts("Reading acceleration data... "); + puts("[Failed]\n"); + } + if (lis3dh_read_aux_adc3(&dev, &temperature) != 0) { + puts("Reading temperature data... "); + puts("[Failed]\n"); + return 1; + } + int1 = gpio_read(dev.int1); + printf("X: %6d Y: %6d Z: %6d Temp: %6d, INT1: %08x\n", + acc_data.acc_x, acc_data.acc_y, acc_data.acc_z, temperature, int1); + --fifo_level; } - if (lis3dh_read_aux_adc3(&dev, &temperature) != 0) { - puts("Reading temperature data... "); - puts("[Failed]\n"); - return 1; - } - - printf("Sensor data - X: %6i Y: %6i Z: %6i Temp: %6i\n", - acc_data.acc_x, acc_data.acc_y, acc_data.acc_z, temperature); vtimer_usleep(SLEEP); }