mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
edc43201db
This should not change any generated binary
2000 lines
86 KiB
C
2000 lines
86 KiB
C
/*
|
||
* Copyright (C) 2018 Gunar Schorcht
|
||
*
|
||
* 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
|
||
* directory for more details.
|
||
*/
|
||
|
||
/**
|
||
* @defgroup drivers_l3gxxxx L3Gxxxx 3-axis gyroscope sensor family
|
||
* @ingroup drivers_sensors
|
||
* @ingroup drivers_saul
|
||
* @brief Device Driver for ST L3Gxxxx 3-axis gyroscope sensor family
|
||
*
|
||
* \section l3gxxxx Driver for ST L3Gxxxx 3-axis gyroscope sensor family
|
||
*
|
||
* ## Table of contents {#l3gxxxx_toc}
|
||
*
|
||
* 1. [Overview](#l3gxxxx_overview)
|
||
* 1. [About the sensor](#l3gxxxx_about)
|
||
* 2. [Supported features](#l3gxxxx_supported)
|
||
* 2. [Measurement Process](#l3gxxxx_measurement_process)
|
||
* 1. [Sensor modes](#l3gxxxx_sensor_modes)
|
||
* 2. [Output Data Rates and Filters](#l3gxxxx_odr_filters)
|
||
* 3. [Using the driver (basic functionality)](#l3gxxxx_using_driver)
|
||
* 1. [Initialization](#l3gxxxx_initialization)
|
||
* 2. [Output data format](#l3gxxxx_output_data)
|
||
* 3. [Fetching data](#l3gxxxx_fetching_data)
|
||
* 4. [Using the FIFO](#l3gxxxx_fifo)
|
||
* 1. [Configuration of the FIFO](#l3gxxxx_fifo_config)
|
||
* 2. [Reading data from the FIFO](#l3gxxxx_fifo_read_data)
|
||
* 5. [Using Interrupts](#l3gxxxx_interrupts)
|
||
* 1. [Data interrupts (data ready and FIFO status) on signal `INT2/DRDY`]
|
||
* (#l3gxxxx_data_interrupt)
|
||
* 2. [Event interrupts (Axes movement and wake-up) on signal `INT1`]
|
||
* (#l3gxxxx_event_interrupt)
|
||
* 3. [Interrupt context problem](#l3gxxxx_interrupt_context)
|
||
* 4. [Interrupt signal properties](#l3gxxxx_interrupt_signal)
|
||
* 6. [Power Saving](#l3gxxxx_power_saving)
|
||
* 7. [Low level functions](#l3gxxxx_low_level)
|
||
* 8. [Default configuration](#l3gxxxx_default_configuration)
|
||
*
|
||
* # Overview {#l3gxxxx_overview}
|
||
*
|
||
* ## About the sensor {#l3gxxxx_about}
|
||
*
|
||
* ST L3Gxxxx sensors are low-power **3-axis angular rate sensors** connected
|
||
* to **I2C** or **SPI** with a full scale of up to **2000 dps**. It supports
|
||
* different measuring rates with a user selectable bandwidth.
|
||
*
|
||
* **Main features** of the sensor are:
|
||
* - 3 selectable full scales of ±245, ±500, and ±2000 dps
|
||
* - 7 measuring rates from 12.5 Hz to 800 Hz with 4 bandwidths
|
||
* - 16 bit angular rate value data output
|
||
* - 2 dedicated interrupt signals for data and event interrupts
|
||
* - integrated high-pass filters with 3 modes and 10 different cutoff
|
||
* frequencies
|
||
* - embedded temperature sensor with 8 bit data output
|
||
* - embedded 32 levels of 16 bit data output FIFO
|
||
* - I2C and SPI digital interface
|
||
* - embedded power-down and sleep mode with fast power-on and wake-up
|
||
*
|
||
* [Back to Table of Contents](#l3gxxxx_toc)
|
||
*
|
||
* ## Supported Features {#l3gxxxx_supported}
|
||
*
|
||
* The driver supports the following sensors of the L3Gxxxx 3-axis gyro sensor
|
||
* family. Used sensor variant has to be specified by using the respective
|
||
* pseudomodule.
|
||
*
|
||
* <center>
|
||
* | Sensor Variant | Pseudomodule | Vendor Status |
|
||
* |:-----------------|:--------------|:--------------------------------|
|
||
* | L3GD20H | `l3gd20h` | Not recommended for new designs |
|
||
* | L3GD20 | `l3gd20` | Obsolete |
|
||
* | L3G4200D | `l3g4200_ng` | Obsolete |
|
||
* | A3G4250D | `a3g4250d` | Active |
|
||
* | I3G4250D | `i3g4250d` | Active |
|
||
* </center><br>
|
||
*
|
||
* The driver is modular and supports different levels of functionality, which
|
||
* can be enabled using pseudomodules according to the requirements of the
|
||
* application. This ensures that the driver only uses as much ROM
|
||
* and RAM as really needed.
|
||
*
|
||
* As basic functionality the driver supports
|
||
* - a static configuration of the sensor by a default configuration parameter
|
||
* set of type #l3gxxxx_params_t as defined in the file l3gxxxx_params.h
|
||
* - the polling of raw output data or angular rates in millidegrees per
|
||
* second (mdps)
|
||
* - the power-down and power-up of the sensor
|
||
* - the use of the I2C or SPI interface
|
||
*
|
||
* The following pseudomodules are used to enable additional functionalities:
|
||
* <center>
|
||
* | Pseudomodule | Functionality |
|
||
* |:--------------------|:--------------------------------------------------------|
|
||
* | `l3gxxxx_i2c` | I2C interface enabled |
|
||
* | `l3gxxxx_spi` | SPI interface enabled |
|
||
* | `l3gxxxx_low_odr` | Low output data rates enabled (L3GD20H only) |
|
||
* | `l3gxxxx_fifo` | 32 level FIFO enabled |
|
||
* | `l3gxxxx_irq_data` | Data interrupt (`INT2/DRDY`) handling enabled |
|
||
* | `l3gxxxx_irq_event` | Event interrupt (`INT1`) handling enabled |
|
||
* | `l3gxxxx_sleep` | Sleep and wake-up functions enabled |
|
||
* | `l3gxxxx_config` | Functions for changing configurations at runtime nabled |
|
||
* </center><br>
|
||
*
|
||
* The following table shows the mapping of which modules have to be used
|
||
* to enable which functions of the L3Gxxxx.
|
||
*
|
||
* <center>
|
||
* | Feature | Module |
|
||
* |:------------------------------------------------------------- |:--------------------|
|
||
* | 16 bit angular rate data output (raw and angular rate) | `l3gxxxx` |
|
||
* | Full scales of ±245, ±500, and ±2000 dps | `l3gxxxx` |
|
||
* | Using high-pass filter (HPF) and low-pass filter (LPF1/LPF2) | `l3gxxxx` |
|
||
* | Output data rates (ODR) from 100 Hz to 800 Hz | `l3gxxxx` |
|
||
* | Output data rates (ODR) from 12.5 Hz to 50 Hz (L3GD20H only) | `l3gxxxx_low_odr` |
|
||
* | Polling data | `l3gxxxx` |
|
||
* | SAUL sensor interface | `l3gxxxx` |
|
||
* | Power-down and power-up functionality | `l3gxxxx` |
|
||
* | Sleep and wake-up functionality | `l3gxxxx_sleep` |
|
||
* | 32 level FIFO handling | `l3gxxxx_fifo` |
|
||
* | Data interrupt (`INT2/DRDY`) handling (data ready and FIFO) | `l3gxxxx_irq_data` |
|
||
* | Event interrupt (`INT1`) handling (Axes movement and wake-up) | `l3gxxxx_irq_event` |
|
||
* | Configuration of all sensor functions at runtime | `l3gxxxx_config` |
|
||
* | I2C interface | `l3gxxxx_i2c` |
|
||
* | SPI interface (SPI mode 3) | `l3gxxxx_spi` |
|
||
* </center><br>
|
||
*
|
||
* @note
|
||
* - Multiple L3Gxxxx sensors of same type with both SPI and I2C interfaces
|
||
* can be used simultaneously. If neither the I2C nor the SPI interface
|
||
* are enabled by using the modules `l3gxxxx_i2c` or `l3gxxxx_spi`,
|
||
* the I2C interface is used by default.<br>
|
||
* <br>
|
||
* - In default configuration, the sensor is configured with
|
||
* an output data rate (ODR) of 100 Hz with a LPF2 cutoff frequency
|
||
* of 25 Hz (#L3GXXXX_ODR_100_25) and a full scale of 245 dps
|
||
* (#L3GXXXX_SCALE_245_DPS). The data are filtered with HPF and LPF2,
|
||
* where the HPF is used in normal mode with reset (#L3GXXXX_HPF_NORMAL)
|
||
* and a cutoff frequency of 8 Hz (see #l3gxxxx_config_hpf).<br>
|
||
* <br>
|
||
* This configuration can either be changed by overriding default
|
||
* parameters #CONFIG_L3GXXXX_ODR, #CONFIG_L3GXXXX_SCALE,
|
||
* #CONFIG_L3GXXXX_FILTER_SEL, #CONFIG_L3GXXXX_HPF_MODE and
|
||
* #CONFIG_L3GXXXX_HPF_CUTOFF or by using functions #l3gxxxx_set_mode,
|
||
* #l3gxxxx_set_scale, #l3gxxxx_select_output_filter, #l3gxxxx_config_hpf
|
||
* if module `l3gxxxx_config` is enabled.<br>
|
||
* <br>
|
||
* - If module 'l3gxxxx_fifo' is used, the FIFO is enabled in mode
|
||
* #L3GXXXX_FIFO with a watermark level (threshold) of 23, i.e. the
|
||
* interrupt #L3GXXXX_INT_FIFO_WATERMARK is triggered (if enabled) when
|
||
* the 24th sample is stored in the FIFO.<br>
|
||
* <br>
|
||
* This configuration can be changed either by overriding the default
|
||
* configuration parameters #CONFIG_L3GXXXX_FIFO_MODE and
|
||
* #CONFIG_L3GXXXX_FIFO_WATERMARK or by function #l3gxxxx_set_fifo_mode
|
||
* if module `l3gxxxx_config` is used.<br>
|
||
* <br>
|
||
* - If the handling of data interrupts on signal `INT2/DRDY` is
|
||
* enabled by module `l3gxxxx_irq_data`, it depends on whether module
|
||
* `l3gxxxx_fifo` is used, which data interrupts are enabled
|
||
* by default. If `l3gxxxx_fifo` is used, #L3GXXXX_INT_FIFO_WATERMARK and
|
||
* #L3GXXXX_INT_FIFO_OVERRUN interrupts are enabled by default. Otherwise
|
||
* only #L3GXXXX_INT_DATA_READY is enabled by default.<br>
|
||
* <br>
|
||
* This configuration can be changed using function #l3gxxxx_enable_int.<br>
|
||
* <br>
|
||
* - If the handling of event interrupts on signal `INT1` is enabled
|
||
* by module `l3gxxxx_irq_event`, the high event interrupt is enabled by
|
||
* default for all axes. This means that for each individual axis an
|
||
* interrupt is generated when the absolute value of its angular rate
|
||
* exceeds a threshold value of ~30 dps (high event).<br>
|
||
* <br>
|
||
* The axis data are filtered with HPF and LPF2. The interrupt signal
|
||
* `INT1` is triggered when the data for one axis becomes greater than
|
||
* the specified threshold (OR condition). The interrupt is latched
|
||
* by default.<br>
|
||
* <br>
|
||
* This configuration can be changed either by overriding the default
|
||
* configuration parameters #CONFIG_L3GXXXX_INT1_X_THRESH,
|
||
* #CONFIG_L3GXXXX_INT1_Y_THRESH, #CONFIG_L3GXXXX_INT1_Z_THRESH,
|
||
* #CONFIG_L3GXXXX_INT1_X_LT_THRESH, #CONFIG_L3GXXXX_INT1_X_GT_THRESH,
|
||
* #CONFIG_L3GXXXX_INT1_Y_LT_THRESH, #CONFIG_L3GXXXX_INT1_Y_GT_THRESH,
|
||
* #CONFIG_L3GXXXX_INT1_Z_LT_THRESH, #CONFIG_L3GXXXX_INT1_Z_GT_THRESH,
|
||
* #CONFIG_L3GXXXX_INT1_FILTER, #CONFIG_L3GXXXX_INT1_AND and
|
||
* #CONFIG_L3GXXXX_INT1_LATCH or at runtime using function
|
||
* #l3gxxxx_set_int_event_cfg function.<br>
|
||
* <br>
|
||
* The `INT1` signal is a HIGH active push/pull output.
|
||
*
|
||
* [Back to Table of Contents](#l3gxxxx_toc)
|
||
*
|
||
* # Measurement Process {#l3gxxxx_measurement_process}
|
||
*
|
||
* ## Sensor modes {#l3gxxxx_sensor_modes}
|
||
*
|
||
* L3Gxxxx sensors provide different operating modes.
|
||
*
|
||
* - **Power-down mode** is configured automatically after power up boot
|
||
* sequence. In this mode, all gyros are switched off. Therefore, it takes
|
||
* up to 100 ms to switch to another mode. The power consumption in this mode
|
||
* is about 1 uA.
|
||
*
|
||
* - **Normal mode** is the normal measurement mode. All gyros are switched on
|
||
* and at least one axis is enabled for measurements. Measurements are
|
||
* performed at a defined output data rate (**ODR**). The power consumption
|
||
* in this mode is about 5 mA.
|
||
*
|
||
* - **Sleep mode** is the normal mode when no axes era enabled for
|
||
* measurement. In this modes, all gyros are kept switched on. Therefore,
|
||
* it only takes 1/ODR to switch to normal mode if low pass filtering is
|
||
* disabled or 6/ODR if low pass filtering is enabled. The power consumption
|
||
* in this mode is about 2.5 mA.
|
||
*
|
||
* [Back to Table of Contents](#l3gxxxx_toc)
|
||
*
|
||
* ## Output Data Rates and Filters {#l3gxxxx_odr_filters}
|
||
*
|
||
* In normal mode, measurements are performed at a defined output rate (ODR)
|
||
* with a user selectable bandwidth.
|
||
*
|
||
* ### Used filter selection
|
||
*
|
||
* L3Gxxxx sensors integrate a combination
|
||
* of two low pass filters (LPF) and one high pass filter (HPF).
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
* +---------------> L3GXXXX_NO_FILTER
|
||
* | +----- +
|
||
* +------------+--->| |---> L3GXXXX_LPF2_ONLY
|
||
* | | LPF2 |
|
||
* +-----+ +------+ | +-----+ +--->| |---> L3GXXXX_HPF_AND_LPF2
|
||
* | | | | | | | | +------+
|
||
* | ADC |-->| LPF1 |--+-->| HPF |--+---------------> L3GXXXX_HPF_ONLY
|
||
* | | | | | |
|
||
* +-----+ +------+ +-----+
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* First, raw sensor data are always filtered by LPF1 with a cutoff frequency
|
||
* that is fixed for the selected output data rate (ODR), see #l3gxxxx_odr_t.
|
||
* Resulting data can then optionally be filtered by HPF and/or LPF2. Both
|
||
* filters can be used or bypassed.
|
||
*
|
||
* The figure above shows possible **filter selections** and the driver symbols
|
||
* defined by #l3gxxxx_filter_sel_t. These can be used to set the filter
|
||
* combination separately for the output data and the data for event interrupt
|
||
* generation.
|
||
*
|
||
* <center>
|
||
* | Driver symbol | High pass filter (HPF) used | Low pass filter 2 (LPF2) used |
|
||
* |:----------------------|:---------------------------:|:------------------------------:
|
||
* | #L3GXXXX_NO_FILTER | - | - |
|
||
* | #L3GXXXX_HPF_ONLY | x | - |
|
||
* | #L3GXXXX_LPF2_ONLY | - | x |
|
||
* | #L3GXXXX_HPF_AND_LPF2 | x | x |
|
||
* </center><br>
|
||
*
|
||
* The default filter selection for the output data is #L3GXXXX_HPF_AND_LPF2
|
||
* and is defined by the default configuration parameter
|
||
* #CONFIG_L3GXXXX_FILTER_SEL. If the module `l3gxxxx_config` is used, it can
|
||
* be changed at runtime using function #l3gxxxx_select_output_filter.
|
||
*
|
||
* The default filter selection for event interrupt generation is
|
||
* #L3GXXXX_HPF_AND_LPF2 and is defined by default configuration parameter
|
||
* #CONFIG_L3GXXXX_INT1_FILTER. It can be changed at runtime with function
|
||
* #l3gxxxx_set_int_event_cfg.
|
||
*
|
||
* @note Since same filters are used for the output data as well as the
|
||
* data used for event interrupt generation (selective axes movement / wake-up),
|
||
* the configuration of the filters always affects both data. If the HPF is
|
||
* enabled for filtering the output data, it is also active for filtering the
|
||
* sensor data used for interrupt generation if the LPF2 is enabled for
|
||
* interrupt generation. The other way around, the HPF is also active for
|
||
* filtering the output data when it is enabled for interrupt generation and
|
||
* when the LPF2 is enabled for the output data.
|
||
*
|
||
* ### High pass filter mode
|
||
*
|
||
* The high pass filter (HPF) can be used in different modes.
|
||
*
|
||
* <center>
|
||
* | Driver symbol | HPF mode |
|
||
* |:-----------------------|:------------------------|
|
||
* | #L3GXXXX_HPF_NORMAL | Normal mode |
|
||
* | #L3GXXXX_HPF_REFERENCE | Reference mode |
|
||
* | #L3GXXXX_HPF_AUTORESET | Auto-reset on interrupt |
|
||
* </center><br>
|
||
*
|
||
* In normal mode, the HPF can be reset by reading the REFERENCE
|
||
* register, which instantly deletes the DC component
|
||
* of the angular rate. In reference mode, output data are the difference
|
||
* of raw sensor data and the contents of the REFERENCE register. In autoreset
|
||
* mode, HPF is automatically reset when a configured event interrupt occurs.
|
||
*
|
||
* The default HPF mode is #L3GXXXX_HPF_NORMAL and is defined by the
|
||
* default configuration parameter #CONFIG_L3GXXXX_HPF_MODE. If module
|
||
* `l3gxxxx_config` is used, it can be changed at runtime using
|
||
* function #l3gxxxx_config_hpf.
|
||
*
|
||
* ### Output data rates and filter cutoff frequencies
|
||
*
|
||
* The cutoff frequencies of LPF1 and LPF2 are determined by used output
|
||
* data rate #l3gxxxx_odr_t. The following **output data rates (ODR)**
|
||
* and the LPF1/LPF2 cutoff frequencies are defined
|
||
* (Reference: Application Note AN4506):
|
||
*
|
||
* <center>
|
||
* | Mode | ODR [Hz] | LPF1 cutoff [Hz] | LPF2 cutoff [Hz] | Driver symbol |
|
||
* |:------- |:--------:|:----------------:|:----------------:|:---------------------|
|
||
* | Normal | 100 | 32 | 12.5 | #L3GXXXX_ODR_100_12 |
|
||
* | Normal | 100 | 32 | 25 | #L3GXXXX_ODR_100_25 |
|
||
* | Normal | 200 | 63.3 | 12.5 | #L3GXXXX_ODR_200_12 |
|
||
* | Normal | 200 | 63.3 | 25 | #L3GXXXX_ODR_200_25 |
|
||
* | Normal | 200 | 63.3 | 50 | #L3GXXXX_ODR_200_50 |
|
||
* | Normal | 200 | 63.3 | 70 | #L3GXXXX_ODR_200_70 |
|
||
* | Normal | 400 | 128 | 20 | #L3GXXXX_ODR_400_20 |
|
||
* | Normal | 400 | 128 | 25 | #L3GXXXX_ODR_400_25 |
|
||
* | Normal | 400 | 128 | 50 | #L3GXXXX_ODR_400_50 |
|
||
* | Normal | 400 | 128 | 110 | #L3GXXXX_ODR_400_110 |
|
||
* | Normal | 800 | 211 | 30 | #L3GXXXX_ODR_800_30 |
|
||
* | Normal | 800 | 211 | 35 | #L3GXXXX_ODR_800_35 |
|
||
* | Normal | 800 | 211 | 30 | #L3GXXXX_ODR_800_30 |
|
||
* | Normal | 800 | 211 | 100 | #L3GXXXX_ODR_800_100 |
|
||
* | Low ODR | 12.5 | 3.9 | - | #L3GXXXX_ODR_12 |
|
||
* | Low ODR | 25 | 7.8 | - | #L3GXXXX_ODR_25 |
|
||
* | Low ODR | 50 | 16 | 16.6 | #L3GXXXX_ODR_50 |
|
||
* </center><br>
|
||
*
|
||
* @note Low ODRs are only available on L3GD20H and if module `l3gxxxx_low_odr`
|
||
* is used.
|
||
*
|
||
* The default output data rate (ODR) is #L3GXXXX_ODR_100_12 and defined by
|
||
* the default configuration parameter #CONFIG_L3GXXXX_ODR. If module
|
||
* `l3gxxxx_config` is used, it can be changed at runtime using
|
||
* function #l3gxxxx_set_mode, for example:
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||
* l3gxxxx_set_mode(&dev, L3GXXXX_ODR_400_20, true, true, false);
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* The **cutoff frequencies** of the HPF depend on the selected output data
|
||
* rate (ODR) and are specified by an index from 0 to 9, as shown in the
|
||
* following table. All frequencies are given in Hz.
|
||
*
|
||
* <center>
|
||
* | ODR [Hz] | 12.5 | 25 | 50 | 100 | 200 | 400 | 800 |
|
||
* |---------:|:-----:|:-----:|:-----:|:----:|:----:|:----:|:---:|
|
||
* | 0 | 1 | 2 | 4 | 8 | 15 | 30 | 56 |
|
||
* | 1 | 0.5 | 1 | 2 | 4 | 8 | 15 | 30 |
|
||
* | 2 | 0.2 | 0.5 | 1 | 2 | 4 | 8 | 15 |
|
||
* | 3 | 0.1 | 0.2 | 0.5 | 1 | 2 | 4 | 8 |
|
||
* | 4 | 0.05 | 0.1 | 0.2 | 0.5 | 1 | 2 | 4 |
|
||
* | 5 | 0.02 | 0.05 | 0.1 | 0.2 | 0.5 | 1 | 2 |
|
||
* | 6 | 0.01 | 0.02 | 0.05 | 0.1 | 0.2 | 0.5 | 1 |
|
||
* | 7 | 0.005 | 0.01 | 0.02 | 0.05 | 0.1 | 0.2 | 0.5 |
|
||
* | 8 | 0.002 | 0.005 | 0.01 | 0.02 | 0.05 | 0.1 | 0.2 |
|
||
* | 9 | 0.001 | 0.002 | 0.005 | 0.01 | 0.02 | 0.05 | 0.1 |
|
||
* </center><br>
|
||
*
|
||
* The default cutoff frequency of HPF is 8 Hz (index 0) and set by the
|
||
* default configuration parameter #CONFIG_L3GXXXX_HPF_CUTOFF. If module
|
||
* `l3gxxxx_config` is used, it can be changed at runtime using function
|
||
* #l3gxxxx_config_hpf,
|
||
* for example:
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||
* l3gxxxx_config_hpf(&dev, L3GXXXX_HPF_NORMAL, 0);
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* [Back to Table of Contents](#l3gxxxx_toc)
|
||
*
|
||
* # Using the driver {#l3gxxxx_using_driver}
|
||
*
|
||
* ## Initialization {#l3gxxxx_initialization}
|
||
*
|
||
* The **easiest way to use the driver** is simply to initialize the sensor
|
||
* with function #l3gxxxx_init using the default configuration parameter set
|
||
* #l3gxxxx_params as defined in file l3gxxxx_params.h.
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||
* static l3gxxxx_t dev;
|
||
*
|
||
* if (l3gxxxx_init(&dev, &l3gxxxx_params[0]) != L3DG20H_OK) {
|
||
* ... // error handling
|
||
* }
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* After this initialization, the sensor is fully operational and data can
|
||
* be fetched either by polling or interrupt driven.
|
||
*
|
||
* @note Function #l3gxxxx_init resets the sensor completely. All registers
|
||
* are reset to default values and the embedded FIFO is cleared.
|
||
*
|
||
* The default configuration parameter set defines
|
||
* - the communication interface,
|
||
* - the output data rate (ODR) including LPF1/LPF2 cutoff frequencies,
|
||
* - the filter combination and HPF cutoff frequency,
|
||
* - the sensitivity level selected by full scale,
|
||
* - the FIFO parameters if module `l3gxxxx_fifo` is used,
|
||
* - the data interrupt (`INT2/DRDY`) pin if module `l3gxxxx_irq_data` is used, and
|
||
* - the event interrupt (`INT1`) configuration if module `l3gxxxx_irq_event` is used.
|
||
*
|
||
* Most of these configuration parameters can also be changed at runtime
|
||
* by respective functions if the module `l3gxxxx_config` is used or by
|
||
* overriding default configuration parameters. Detailed information about
|
||
* the default configuration can be found in section
|
||
* [Configuration](#l3gxxxx_default_configuration).
|
||
*
|
||
* [Back to Table of Contents](#l3gxxxx_toc)
|
||
*
|
||
* ## Output data format {#l3gxxxx_output_data}
|
||
*
|
||
* In normal mode, the sensor determines periodically the angular rate for all
|
||
* axes that are enabled for measurement and produces raw output data
|
||
* with the selected output data rate (ODR).
|
||
*
|
||
* These **raw output data** are 16-bit signed integer values in two’s
|
||
* complement representation. Their range and their resolution depend on the
|
||
* sensitivity of the sensor which is selected by the **full scale** value.
|
||
* L3Gxxxx sensors allow to select the following full scales:
|
||
*
|
||
* <center>
|
||
* | Full Scale | Sensitivity | Driver symbol | Remark |
|
||
* | -----------:|------------:|:------------------------|:--------------------------|
|
||
* | ±245 dps | 8.75 mdps | #L3GXXXX_SCALE_245_DPS | |
|
||
* | ±500 dps | 17.50 mdps | #L3GXXXX_SCALE_500_DPS | not available on A3G4250D |
|
||
* | ±2000 dps | 70.00 mdps | #L3GXXXX_SCALE_2000_DPS | not available on A3G4250D |
|
||
* </center><br>
|
||
*
|
||
* @note On the A34250D, only 245 dps (#L3GXXXX_SCALE_245_DPS) is available
|
||
* as full scale value.
|
||
*
|
||
* The default full scale value is ±245 dps which is defined by the default
|
||
* configuration parameter #CONFIG_L3GXXXX_SCALE. If module `l3gxxxx_config`
|
||
* is used, it can be changed at runtime using function #l3gxxxx_set_scale,
|
||
* for example:
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||
* l3gxxxx_set_scale(&dev, L3GXXXX_SCALE_500_DPS);
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* [Back to Table of Contents](#l3gxxxx_toc)
|
||
*
|
||
* ## Fetching data {#l3gxxxx_fetching_data}
|
||
*
|
||
* To get the information whether new data are available, the user task can
|
||
* either use
|
||
*
|
||
* - the function #l3gxxxx_data_ready to check periodically whether new
|
||
* output data are available, or
|
||
* - the data ready interrupt (`INT2/DRDY`) which is triggered as soon as new
|
||
* output data are available (see below).
|
||
*
|
||
* Last measurement results can then be fetched either
|
||
*
|
||
* - as 16 bit raw output data of type #l3gxxxx_raw_data_t using function
|
||
* #l3gxxxx_read_raw or
|
||
* - as 32 bit integer angular rates type #l3gxxxx_data_t in
|
||
* millidegrees per second (mdps) using function #l3gxxxx_read.
|
||
*
|
||
* It is recommended to use function #l3gxxxx_read since the driver already
|
||
* converts raw output data to angular rates according to the selected
|
||
* full scale value.
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||
* while (1)
|
||
* {
|
||
* l3gxxxx_data_t data;
|
||
*
|
||
* // execute task every 20 ms
|
||
* xtimer_usleep(20 * US_PER_MS);
|
||
* ...
|
||
* // test for new data and fetch them if available
|
||
* if ((l3gxxxx_data_ready(&dev) > 0) &&
|
||
* (l3gxxxx_read(&dev, &data) == L3GXXXX_OK)) {
|
||
* // do something with data
|
||
* ...
|
||
* }
|
||
* }
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* @note
|
||
* The functions #l3gxxxx_read and #l3gxxxx_read_raw always return the last
|
||
* available results. If these functions are called more often than
|
||
* measurements are performed, some measurement results are retrieved
|
||
* multiple times. If these functions are called too rarely, some measurement
|
||
* results will be lost.
|
||
*
|
||
* [Back to Table of Contents](#l3gxxxx_toc)
|
||
*
|
||
* # Using the FIFO {#l3gxxxx_fifo}
|
||
*
|
||
* In order to limit the rate at which the host processor has to fetch the
|
||
* data, L3Gxxxx sensors embed a FIFO buffer. This is in particular helpful
|
||
* at high output data rates. The FIFO buffer can work in seven different
|
||
* modes and is able to store up to 32 data samples. Please refer the
|
||
* [datasheet](http://www.st.com/resource/en/datasheet/l3gd20.pdf) or
|
||
* [application note](http://www.st.com/resource/en/application_note/dm00119036.pdf)
|
||
* for more details.
|
||
*
|
||
* <center>
|
||
* | Driver symbol | FIFO mode | Remark |
|
||
* |---------------------------|-----------------------|:------------------------|
|
||
* | #L3GXXXX_BYPASS | Bypass mode | FIFO is not used |
|
||
* | #L3GXXXX_FIFO | FIFO mode | |
|
||
* | #L3GXXXX_STREAM | Stream mode | |
|
||
* | #L3GXXXX_STREAM_TO_FIFO | Stream-to-FIFO mode | L3GD20H and L3GD20 only |
|
||
* | #L3GXXXX_BYPASS_TO_STREAM | Bypass-to-Stream mode | L3GD20H and L3GD20 only |
|
||
* | #L3GXXXX_DYNAMIC_STREAM | Dynamic Stream mode | L3GD20H only |
|
||
* | #L3GXXXX_BYPASS_TO_FIFO | Bypass to FIFO mode | L3GD20H only |
|
||
* </center><br>
|
||
*
|
||
* A watermark level (threshold) can be set for the FIFO. If the number of
|
||
* data samples in the FIFO exceeds this value, the watermark flag is set
|
||
* and the interrupt #L3GXXXX_INT_FIFO_WATERMARK is triggered, if enabled.
|
||
* This interrupt can be used to gather a minimum number of samples of raw
|
||
* output data before the data are fetched as a single read operation from
|
||
* the sensor.
|
||
*
|
||
* ## Configuration of the FIFO {#l3gxxxx_fifo_config}
|
||
*
|
||
* The default FIFO mode is defined by the default configuration parameter
|
||
* #CONFIG_L3GXXXX_FIFO_MODE. The default watermark level (threshold) of
|
||
* the FIFO is defined by the default configuration parameter
|
||
* #CONFIG_L3GXXXX_FIFO_WATERMARK.
|
||
*
|
||
* If module `l3gxxxx_config` is used, both configuration parameters can be
|
||
* changed at runtime with function #l3gxxxx_set_fifo_mode. This function
|
||
* takes two parameters, the FIFO mode and the watermark level.
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||
* ...
|
||
* // set the FIFO mode with a watermark level (threshold) of 10, i.e. the
|
||
* // watermark flag is set or the interrupt is triggered for the 11th sample
|
||
* l3gxxxx_set_fifo_mode(&dev, L3GXXXX_STREAM, 10);
|
||
* ...
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* @note To clear the FIFO at any time, set the FIFO mode to #L3GXXXX_BYPASS
|
||
* and back to the desired FIFO mode.
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||
* l3gxxxx_set_fifo_mode(&dev, L3GXXXX_BYPASS, 0);
|
||
* l3gxxxx_set_fifo_mode(&dev, L3GXXXX_STREAM, 10);
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* ## Reading data from FIFO {#l3gxxxx_fifo_read_data}
|
||
*
|
||
* To read data from the FIFO, just use either
|
||
*
|
||
* - function #l3gxxxx_read_raw_fifo to get all raw output data stored
|
||
* in the FIFO or
|
||
* - function #l3gxxxx_read_fifo to get all data stored in the FIFO
|
||
* and converted to angular rates in mdps (millidegrees per second).
|
||
*
|
||
* Both functions clear the FIFO and return the number of samples read
|
||
* from the FIFO.
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||
* l3gxxxx_data_fifo_t data;
|
||
*
|
||
* while (1)
|
||
* {
|
||
* // execute task every 500 ms
|
||
* xtimer_usleep(500 * US_PER_MS);
|
||
* ...
|
||
* // test for new data
|
||
* if (l3gxxxx_data_ready(&dev) > 0) {
|
||
*
|
||
* // fetch data from fifo
|
||
* int num = l3gxxxx_read_fifo(dev, data);
|
||
*
|
||
* for (int i = 0; i < num; i++) {
|
||
* // do something with data[i] ...
|
||
* }
|
||
* }
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* [Back to Table of Contents](#l3gxxxx_toc)
|
||
*
|
||
* # Using Interrupts {#l3gxxxx_interrupts}
|
||
*
|
||
* L3Gxxxx sensors allow to activate interrupts on two different signals:
|
||
*
|
||
* - for data (data ready and FIFO status) on signal `INT2/DRDY`, and
|
||
* - for events (axis movement and wake-up) on signal `INT1`.
|
||
*
|
||
* [Back to Table of Contents](#l3gxxxx_toc)
|
||
*
|
||
* ## Data interrupts (data ready and FIFO status) on signal INT2/DRDY {#l3gxxxx_data_interrupt}
|
||
*
|
||
* Interrupts on signal `INT2/DRDY` can be generated by the following sources:
|
||
*
|
||
* <center>
|
||
* | Interrupt source | Driver symbol |
|
||
* |:-----------------------------------------|:----------------------------|
|
||
* | Output data are ready to be read | #L3GXXXX_INT_DATA_READY |
|
||
* | FIFO content exceeds the watermark level | #L3GXXXX_INT_FIFO_WATERMARK |
|
||
* | FIFO is completely filled | #L3GXXXX_INT_FIFO_OVERRUN |
|
||
* | FIFO becomes empty | #L3GXXXX_INT_FIFO_EMPTY |
|
||
* </center><br>
|
||
*
|
||
* #L3GXXXX_INT_DATA is the bitwise OR combination of these symbols.
|
||
*
|
||
* @note Using data interrupts requires to enable module `l3gxxxx_irq_data`.
|
||
*
|
||
* Each interrupt source can be enabled or disabled separately with
|
||
* function #l3gxxxx_enable_int.
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||
* l3gxxxx_enable_int(&dev, L3GXXXX_INT_DATA_READY, true);
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
* If `l3gxxxx_fifo` is used, #L3GXXXX_INT_FIFO_WATERMARK and
|
||
* #L3GXXXX_INT_FIFO_OVERRUN interrupts are enabled by default. Otherwise
|
||
* only #L3GXXXX_INT_DATA_READY is enabled by default.
|
||
*
|
||
* The MCU GPIO pin used for the `INT2/DRDY` interrupt signal has to be defined
|
||
* by the hardware configuration parameter #L3GXXXX_INT2_PIN.
|
||
*
|
||
* Once a data interrupt is enabled, function #l3gxxxx_wait_int can be
|
||
* used to wait for an interrupt on signal `INT2/DRDY`. This function
|
||
* returns a structure with the interrupt sources of type #l3gxxxx_int_src_t
|
||
* which contains a flag for each possible data interrupt source in
|
||
* member #l3gxxxx_int_src_t::data that can be tested for true.
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||
* l3gxxxx_int_src_t int_src = l3gxxxx_wait_int(&dev);
|
||
*
|
||
* if (int_src.data.data_ready) {
|
||
* l3gxxxx_read(&dev, &data)
|
||
* ...
|
||
* }
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* If module `l3gxxxx_fifo` is used, the corresponding interrupt sources can
|
||
* be tested.
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||
* l3gxxxx_int_src_t int_src = l3gxxxx_wait_int(&dev);
|
||
*
|
||
* ...
|
||
* if (int_src.data.fifo_threshold) {
|
||
* l3gxxxx_read(&dev, &data);
|
||
* ...
|
||
* }
|
||
* if (int_src.data.fifo_overrun) {
|
||
* printf("FIFO overrun");
|
||
* }
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* [Back to Table of Contents](#l3gxxxx_toc)
|
||
*
|
||
* ## Event interrupts (axes movement and wake-up) on signal INT1 {#l3gxxxx_event_interrupt}
|
||
*
|
||
* This interrupt signal allows to recognize independent rotations of
|
||
* the X, Y and Z axes. For this purpose, a separate threshold can be
|
||
* defined for each axis. If activated, the angular rate of each axis
|
||
* is compared with its threshold to check whether it is below or above
|
||
* the threshold. The results of all activated comparisons are combined
|
||
* OR or AND to generate the interrupt signal.
|
||
*
|
||
* The configuration of the thresholds, the activated comparisons and
|
||
* selected AND/OR combination allows to recognize special situations
|
||
* like selective axis movement (SA) or axes movement wake-up (WU).
|
||
*
|
||
* - **Selective axis movement recognition (SA)** means that only one
|
||
* axis is rotating. This is the case if the angular rate of selected
|
||
* axis is above its threshold AND angular rates of all other axes are
|
||
* below their thresholds.
|
||
*
|
||
* - **Axis movement wake-up (WU)** means that the angular rate of any
|
||
* axis is above its threshold (OR).
|
||
*
|
||
* @note Using event interrupts requires to enable module `l3gxxxx_irq_event`.
|
||
*
|
||
* The MCU GPIO pin used for the `INT1` interrupt signal is defined by the
|
||
* hardware configuration parameter #L3GXXXX_INT1_PIN.
|
||
*
|
||
* The default configuration for event interrupts is defined by
|
||
* #L3GXXXX_INT1_PARAMS. This configuration can be changed either by
|
||
* overriding default configuration parameters
|
||
* #CONFIG_L3GXXXX_INT1_X_THRESH, #CONFIG_L3GXXXX_INT1_Y_THRESH,
|
||
* #CONFIG_L3GXXXX_INT1_Z_THRESH,
|
||
* #CONFIG_L3GXXXX_INT1_X_LT_THRESH, #CONFIG_L3GXXXX_INT1_X_GT_THRESH,
|
||
* #CONFIG_L3GXXXX_INT1_Y_LT_THRESH, #CONFIG_L3GXXXX_INT1_Y_GT_THRESH,
|
||
* #CONFIG_L3GXXXX_INT1_Z_LT_THRESH, #CONFIG_L3GXXXX_INT1_Z_GT_THRESH,
|
||
* #CONFIG_L3GXXXX_INT1_FILTER, #CONFIG_L3GXXXX_INT1_AND and
|
||
* #CONFIG_L3GXXXX_INT1_LATCH or at runtime using function
|
||
* #l3gxxxx_set_int_event_cfg with a set of parameters
|
||
* of type #l3gxxxx_int_event_cfg_t that contains the configuration.
|
||
* For example, selective axis movement recognition (SA) for the z-axis
|
||
* could be configured as following. With this configuration, the event
|
||
* interrupt is only triggered if all conditions are met.
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||
* l3gxxxx_int_event_cfg_t int_cfg;
|
||
*
|
||
* // thresholds
|
||
* int_cfg.x_threshold = 100;
|
||
* int_cfg.y_threshold = 100;
|
||
* int_cfg.z_threshold = 1000;
|
||
*
|
||
* // X axis below threshold enabled
|
||
* int_cfg.x_low_enabled = true;
|
||
* int_cfg.x_high_enabled = false;
|
||
*
|
||
* // Y axis below threshold enabled
|
||
* int_cfg.y_low_enabled = true;
|
||
* int_cfg.y_high_enabled = false;
|
||
*
|
||
* // Z axis below threshold enabled
|
||
* int_cfg.z_low_enabled = false;
|
||
* int_cfg.z_high_enabled = true;
|
||
*
|
||
* // AND combination of all conditions
|
||
* int_cfg.and_or = true;
|
||
*
|
||
* // further parameters
|
||
* int_cfg.filter = L3GXXXX_HPF_ONLY;
|
||
* int_cfg.latch = true;
|
||
* int_cfg.duration = 0;
|
||
* int_cfg.wait = false;
|
||
*
|
||
* // set the configuration and enable the interrupt
|
||
* l3gxxxx_set_int_event_cfg(&dev, &int_cfg);
|
||
* l3gxxxx_enable_int(&dev, L3GXXXX_INT_EVENT, true);
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* The data structure #l3gxxxx_int_event_cfg_t defines
|
||
* - whether the interrupt signal should be latched until the interrupt
|
||
* source is read by function #l3gxxxx_wait_int,
|
||
* - which filters are applied to the data used for interrupt generation,
|
||
* - which time measured in 1/ODR an interrupt condition has to be given before
|
||
* the interrupt is generated, and
|
||
* - whether this time is also used when interrupt condition is no
|
||
* longer given before interrupt signal is reset.
|
||
*
|
||
* @note
|
||
* - If the interrupt is configured to be latched, the interrupt signal is
|
||
* active until the interrupt source is read by function #l3gxxxx_wait_int
|
||
* AND next raw output data are available. Otherwise the interrupt signal is
|
||
* active as long as the interrupt condition is satisfied.
|
||
* - The driver function #l3gxxxx_wait_int uses the leading flank of the
|
||
* interrupt signal to detect an interrupt and read the interrupt source.
|
||
*
|
||
* Function #l3gxxxx_enable_int is used to enable or disable the
|
||
* event interrupt generation (#L3GXXXX_INT_EVENT).
|
||
*
|
||
* As with data interrupts function #l3gxxxx_wait_int can be used to
|
||
* wait for an interrupt on signal `INT1` if event interrupts are enabled.
|
||
* This function returns a structure with the interrupt sources of type
|
||
* #l3gxxxx_int_src_t which contains a flag for each possible event interrupt
|
||
* source in member #l3gxxxx_int_src_t::event that can be tested for true.
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||
* l3gxxxx_int_src_t int_src = l3gxxxx_wait_int(&dev);
|
||
*
|
||
* if (int_src.event.x_low) {
|
||
* printf("x below ");
|
||
* }
|
||
* if (int_src.event.x_high) {
|
||
* printf("x above ");
|
||
* }
|
||
* ...
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* Activating all threshold comparisons and using the OR combination is the
|
||
* most flexible way to realize functions like selective axis movement by
|
||
* combining the different interrupt sources as required by the application.
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||
* l3gxxxx_int_event_cfg_t int_cfg;
|
||
*
|
||
* // thresholds
|
||
* int_cfg.x_threshold = 100;
|
||
* int_cfg.y_threshold = 100;
|
||
* int_cfg.z_threshold = 100;
|
||
*
|
||
* // X axis below and above threshold enabled
|
||
* int_cfg.x_low_enabled = true;
|
||
* int_cfg.x_high_enabled = true;
|
||
*
|
||
* // Y axis below and above threshold enabled
|
||
* int_cfg.y_low_enabled = true;
|
||
* int_cfg.y_high_enabled = true;
|
||
*
|
||
* // Z axis below and above threshold enabled
|
||
* int_cfg.z_low_enabled = true;
|
||
* int_cfg.z_high_enabled = true;
|
||
*
|
||
* // OR combination of all conditions
|
||
* int_cfg.and_or = false;
|
||
* ...
|
||
* // set the configuration and enable the interrupt
|
||
* l3gxxxx_set_int_event_cfg(&dev, &int_cfg);
|
||
* l3gxxxx_enable_int(&dev, l3gxxxx_int_event, true);
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* Following example shows the selective axis movement recognition (SA)
|
||
* for the Z-axis.
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||
* l3gxxxx_int_src_t int_src = l3gxxxx_wait_int(&dev);
|
||
*
|
||
* if (int_src.event.y_low && int_src.event.y_low && int_src.event.z_high) {
|
||
* // selective axis movement of Z-axis
|
||
* ...
|
||
* }
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* ## Interrupt context problem {#l3gxxxx_interrupt_context}
|
||
*
|
||
* All functions of the driver require direct access to the sensor via
|
||
* I2C or SPI which does not work in interrupt context.
|
||
*
|
||
* Therefore, the driver prevents the direct use of the interrupts and
|
||
* application specific ISRs. The only way to use interrupts is to call
|
||
* the function #l3gxxxx_wait_int which enables the interrupt signals
|
||
* for the configured MCU GPIO pins and then blocks the calling thread
|
||
* until an interrupt is triggered.
|
||
*
|
||
* Once an interrupt is triggered, the driver handles the interrupt with
|
||
* an internal ISR and then returns from the #l3gxxxx_wait_int function.
|
||
* The return value is a structure with the interrupt sources of type
|
||
* #l3gxxxx_int_src_t, which contains a flag for each possible interrupt
|
||
* source that can be tested for true.
|
||
*
|
||
* [Back to Table of Contents](#l3gxxxx_toc)
|
||
*
|
||
* ## Interrupt signal properties {#l3gxxxx_interrupt_signal}
|
||
*
|
||
* By default, interrupt signals are high active push/pull outputs.
|
||
*
|
||
* # Power Saving {#l3gxxxx_power_saving}
|
||
*
|
||
* L3Gxxxx sensors offer two modes for power saving:
|
||
*
|
||
* - **Power-down** mode
|
||
* - **Sleep** mode
|
||
*
|
||
* While in power-down mode almost all internal blocks of the device including
|
||
* the gyros are switched off, in sleep mode only the measuring functions for
|
||
* all three axes are deactivated. Therefore, the time to continue measurements
|
||
* after sleep mode is drastically shorter than after power down.
|
||
*
|
||
* <center>
|
||
* | Starting mode | Target mode | Turn-on time typical |
|
||
* | ------------- | ----------- | ---------------------|
|
||
* | Power-down | Normal | 100 ms |
|
||
* | Power-down | Sleep | 100 ms |
|
||
* | Sleep | Normal | 1/ODR when LPF2 disabled <br> 6/ODR when LPF2 enabled |
|
||
* </center><br>
|
||
*
|
||
* L3Gxxxx sensors can be powered down when no measurements are required
|
||
* using the function #l3gxxxx_power_down. The power consumption is reduced
|
||
* to some uA in power-down mode. To restart the L3Gxxxx in previous
|
||
* measurement mode, the #l3gxxxx_power_up function can be used.
|
||
*
|
||
* If module `l3gxxxx_sleep` is enabled, the sleep mode can be activated with
|
||
* function #l3gxxxx_sleep. The power consumption is then reduced from 4.8 mA
|
||
* to 2.4 mA and thus to half. The #l3gxxxx_wake_up function continues the
|
||
* measurement in previous operation mode.
|
||
*
|
||
* [Back to Table of Contents](#l3gxxxx_toc)
|
||
*
|
||
* # Low level functions {#l3gxxxx_low_level}
|
||
*
|
||
* L3Gxxxx sensors are complex and flexible sensors with a lot of
|
||
* features. It can be used for a big number of different use cases.
|
||
* Since it is impossible to implement a high level interface
|
||
* which is generic enough to cover all the functionality of the sensor
|
||
* for all different use cases, there are two low level interface
|
||
* functions that allow direct read and write access to the registers
|
||
* of the sensor.
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||
* bool l3gxxxx_reg_read(l3gxxxx_sensor_t* dev, uint8_t reg, uint8_t *data, uint16_t len);
|
||
* bool l3gxxxx_reg_write(l3gxxxx_sensor_t* dev, uint8_t reg, uint8_t *data, uint16_t len);
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* @warning
|
||
* These functions should only be used to do something special that
|
||
* is not covered by the high level interface AND if you exactly
|
||
* know what you do and what it might affect. Please be aware that
|
||
* it might affect the high level interface.
|
||
*
|
||
* [Back to Table of Contents](#l3gxxxx_toc)
|
||
*
|
||
* # Default configuration {#l3gxxxx_default_configuration}
|
||
*
|
||
* Default sensor hardware configurations are set in file `l3gxxxx_params.h`
|
||
* using the following defines:
|
||
*
|
||
* <center>
|
||
* | Hardware configuration | Driver name | Default Value |
|
||
* |:-----------------------|:------------------|:--------------------|
|
||
* | I2C device | #L3GXXXX_I2C_DEV | I2C_DEV(0) |
|
||
* | I2C address | #L3GXXXX_I2C_ADDR | #L3GXXXX_I2C_ADDR_2 |
|
||
* | SPI device | #L3GXXXX_SPI_DEV | SPI_DEV(0) |
|
||
* | SPI clock frequency | #L3GXXXX_SPI_CLK | SPI_CLK_1MHZ |
|
||
* | SPI CS signal | #L3GXXXX_SPI_CS | GPIO_PIN(0, 0) |
|
||
* | `INT1` MCU pin | #L3GXXXX_INT1_PIN | GPIO_PIN(0, 1) |
|
||
* | `INT2/DRDY` MCU pin | #L3GXXXX_INT2_PIN | GPIO_PIN(0, 2) |
|
||
* </center><br>
|
||
*
|
||
* These hardware configurations can be overridden either by the board
|
||
* definition or by defining them in the `CFLAGS` variable in the make
|
||
* command, for example:
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
* DRIVER=l3gd20h USEMODULE='l3gxxxx_irq_data` \
|
||
* CLFAGS='-DL3GXXXX_INT2_PIN=GPIO_PIN\(0, 5\)' \
|
||
* BOARD=... make -C tests/drivers/l3gxxxx
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* The default configuration of the sensor is defined in file
|
||
* `l3gxxxx_params.h` using the following defines:
|
||
*
|
||
* <center>
|
||
* | Configuration parameter | Driver name | Default Value |
|
||
* |:-------------------------------------|:------------------------------|:----------------------|
|
||
* | ODR and LPF2 cutoff frequency | #CONFIG_L3GXXXX_ODR | #L3GXXXX_ODR_100_25 |
|
||
* | Full scale | #CONFIG_L3GXXXX_SCALE | #L3GXXXX_SCALE_245_DPS|
|
||
* | Filter selection used for output data| #CONFIG_L3GXXXX_FILTER_SEL | #L3GXXXX_HPF_AND_LPF2 |
|
||
* | HPF mode used for output data | #CONFIG_L3GXXXX_HPF_MODE | #L3GXXXX_HPF_NORMAL |
|
||
* | HPF cutoff frequency 8 Hz | #CONFIG_L3GXXXX_HPF_CUTOFF | 0 |
|
||
* | FIFO mode if FIFO is used | #CONFIG_L3GXXXX_FIFO_MODE | #L3GXXXX_FIFO |
|
||
* | FIFO threshold value if FIFO is used | #CONFIG_L3GXXXX_FIFO_WATERMARK| 23 |
|
||
* | INT1 threshold for X axis (~30 dps) | #CONFIG_L3GXXXX_INT1_X_THRESH | 4012 |
|
||
* | INT1 threshold for Y axis (~30 dps) | #CONFIG_L3GXXXX_INT1_Y_THRESH | 4012 |
|
||
* | INT1 threshold for Z axis (~30 dps) | #CONFIG_L3GXXXX_INT1_Z_THRESH | 4012 |
|
||
* | INT1 interrupt enable for X > X threshold | #CONFIG_L3GXXXX_INT1_X_GT_THRESH | true |
|
||
* | INT1 interrupt enable for Y > Y threshold | #CONFIG_L3GXXXX_INT1_Y_GT_THRESH | true |
|
||
* | INT1 interrupt enable for Z > Z threshold | #CONFIG_L3GXXXX_INT1_Z_GT_THRESH | true |
|
||
* | INT1 interrupt enable for X < X threshold | #CONFIG_L3GXXXX_INT1_X_LT_THRESH | false |
|
||
* | INT1 interrupt enable for Y < Y threshold | #CONFIG_L3GXXXX_INT1_Y_LT_THRESH | false |
|
||
* | INT1 interrupt enable for Z < Z threshold | #CONFIG_L3GXXXX_INT1_Z_LT_THRESH | false |
|
||
* | INT1 filter selection | #CONFIG_L3GXXXX_INT1_FILTER | #L3GXXXX_HPF_AND_LPF2 |
|
||
* | INT1 interrupt combination | #CONFIG_L3GXXXX_INT1_AND | false |
|
||
* | INT1 interrupt latch enabled | #CONFIG_L3GXXXX_INT1_LATCH | true |
|
||
* </center><br>
|
||
*
|
||
* Single or all parameters of the default configuration can be overridden
|
||
* either by defining them in the variable `CFLAGS` in the make command
|
||
* line or by placing a modified file `l3gxxxx_params.h` in the
|
||
* application directory, for example:
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
* DRIVER=l3gd20h USEMODULE='l3gxxxx_low_odr l3gxxxx_irq_data` \
|
||
* CLFAGS='-DCONFIG_L3GXXXX_ODR=L3GXXXX_ODR_12 -DL3GXXXX_INT2_PIN=GPIO_PIN\(0,5\)' \
|
||
* BOARD=... make -C tests/drivers/l3gxxxx
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* @author Gunar Schorcht <gunar@schorcht.net>
|
||
*
|
||
* @{
|
||
* @file
|
||
* @brief Device Driver for ST L3Gxxxx 3-axis gyroscope sensor family
|
||
*/
|
||
|
||
#ifndef L3GXXXX_H
|
||
#define L3GXXXX_H
|
||
|
||
#ifdef __cplusplus
|
||
extern "C"
|
||
{
|
||
#endif
|
||
|
||
#include <stdbool.h>
|
||
#include <stdint.h>
|
||
|
||
#include "mutex.h"
|
||
#include "periph/gpio.h"
|
||
#include "periph/i2c.h"
|
||
#include "periph/spi.h"
|
||
|
||
#include "l3gxxxx_regs.h"
|
||
|
||
#if !IS_USED(MODULE_L3GD20H) && !IS_USED(MODULE_L3GD20) \
|
||
&& !IS_USED(MODULE_L3G4200D_NG) \
|
||
&& !IS_USED(MODULE_A3G4250D) \
|
||
&& !IS_USED(MODULE_I3G4250D)
|
||
#error Please select your sensor variant by using the respective pseudomodule.
|
||
#endif
|
||
|
||
/**
|
||
* @name L3Gxxxx addresses
|
||
* @{
|
||
*/
|
||
#if IS_USED(MODULE_L3GD20H) || IS_USED(MODULE_L3GD20)
|
||
#define L3GXXXX_I2C_ADDR_1 (0x6a) /**< SDO pin is low */
|
||
#define L3GXXXX_I2C_ADDR_2 (0x6b) /**< SDO pin is high */
|
||
#else
|
||
#define L3GXXXX_I2C_ADDR_1 (0x68) /**< SDO pin is low */
|
||
#define L3GXXXX_I2C_ADDR_2 (0x69) /**< SDO pin is high */
|
||
#endif
|
||
/** @} */
|
||
|
||
/**
|
||
* @name L3Gxxxx chip ids
|
||
* @{
|
||
*/
|
||
#define L3GXXXX_CHIP_ID_L3GD20H (0xd7) /**< Chip ID for L3GD20H */
|
||
#define L3GXXXX_CHIP_ID_L3GD20 (0xd4) /**< Chip ID for L3GD20 */
|
||
#define L3GXXXX_CHIP_ID_X3G42XXD (0xd3) /**< Chip ID for L3G4200D, I3G4250D, A3G4250D */
|
||
/** @} */
|
||
|
||
/** Definition of error codes */
|
||
typedef enum {
|
||
L3GXXXX_OK, /**< success */
|
||
L3GXXXX_ERROR_I2C, /**< I2C communication error */
|
||
L3GXXXX_ERROR_SPI, /**< SPI communication error */
|
||
L3GXXXX_ERROR_WRONG_CHIP_ID, /**< wrong chip id read from WHO_AM_I reg */
|
||
L3GXXXX_ERROR_INV_DEV, /**< invalid device type used */
|
||
L3GXXXX_ERROR_INV_MODE, /**< sensor mode is invalid or not available */
|
||
L3GXXXX_ERROR_INV_FIFO_MODE, /**< FIFO mode is invalid or not available */
|
||
L3GXXXX_ERROR_INV_INT_TYPE, /**< invalid interrupt type used */
|
||
L3GXXXX_ERROR_NO_NEW_DATA, /**< no new data are available */
|
||
L3GXXXX_ERROR_RAW_DATA, /**< reading raw output data failed */
|
||
L3GXXXX_ERROR_RAW_DATA_FIFO, /**< reading raw output data from FIFO failed */
|
||
L3GXXXX_ERROR_NO_INT1_PIN, /**< `INT1` signal pin not configured */
|
||
L3GXXXX_ERROR_NO_INT2_PIN, /**< `INT2/DRDY` signal pin not configured */
|
||
L3GXXXX_ERROR_BYPASS_MODE, /**< sensor is in bypass mode */
|
||
L3GXXXX_ERROR_FIFO_MODE, /**< sensor is in FIFO mode */
|
||
} l3gxxxx_error_codes_t;
|
||
|
||
/**
|
||
* @brief Sensor output data rates (ODR) and LPF2 cutoff frequencies
|
||
*
|
||
* The following output data rates (ODR) and the LPF1/LPF2 cutoff frequencies
|
||
* are defined (Reference: Application Note AN4506):
|
||
*
|
||
* <center>
|
||
* | Mode | ODR [Hz] | LPF1 cutoff [Hz] | LPF2 cutoff [Hz] |
|
||
* |:-----------------------|:--------:|:----------------:|:----------------:|
|
||
* | High ODR | | | |
|
||
* | L3GXXXX_ODR_100_12 | 100 | 32 | 12.5 |
|
||
* | L3GXXXX_ODR_100_25 | 100 | 32 | 25 |
|
||
* | L3GXXXX_ODR_200_12 | 200 | 63.3 | 12.5 |
|
||
* | L3GXXXX_ODR_200_25 | 200 | 63.3 | 25 |
|
||
* | L3GXXXX_ODR_200_50 | 200 | 63.3 | 50 |
|
||
* | L3GXXXX_ODR_200_70 | 200 | 63.3 | 70 |
|
||
* | L3GXXXX_ODR_400_20 | 400 | 128 | 20 |
|
||
* | L3GXXXX_ODR_400_25 | 400 | 128 | 25 |
|
||
* | L3GXXXX_ODR_400_50 | 400 | 128 | 50 |
|
||
* | L3GXXXX_ODR_400_110 | 400 | 128 | 110 |
|
||
* | L3GXXXX_ODR_800_30 | 800 | 211 | 30 |
|
||
* | L3GXXXX_ODR_800_35 | 800 | 211 | 35 |
|
||
* | L3GXXXX_ODR_800_50 | 800 | 211 | 50 |
|
||
* | L3GXXXX_ODR_800_100 | 800 | 211 | 100 |
|
||
* | | | | |
|
||
* | Low ODR (L3GD20H only) | | | |
|
||
* | L3GXXXX_ODR_12 | 12.5 | 3.9 | - |
|
||
* | L3GXXXX_ODR_25 | 25 | 7.8 | - |
|
||
* | L3GXXXX_ODR_50 | 50 | 16 | 16.6 |
|
||
* </center><br>
|
||
*
|
||
* Detailed information about the filter chain and possible
|
||
* filter combinations can be found in the section
|
||
* [Output data rates and filters](#l3gxxxx_odr_filters).
|
||
*
|
||
* While LPF1 is always used, LPF2 and HPF have to be explicitly enabled
|
||
* by the configuration parameter l3gxxxx_params_t::filter_sel or the
|
||
* #l3gxxxx_select_output_filter function if module `l3gxxxx_config` is
|
||
* used. #L3GXXXX_ODR_100_25 is used by the default configuration.
|
||
*
|
||
* @note Low data rates 12.5 Hz, 25 Hz and 50 Hz are only supported by L3GXXXX.
|
||
*/
|
||
typedef enum {
|
||
L3GXXXX_ODR_100_12 = 0x00, /**< High ODR 100 Hz, LPF1 cutoff 32 Hz, LPF2 cutoff 12.5 Hz */
|
||
L3GXXXX_ODR_100_25 = 0x01, /**< High ODR 100 Hz, LPF1 cutoff 32 Hz, LPF2 cutoff 25 Hz */
|
||
L3GXXXX_ODR_200_12 = 0x04, /**< High ODR 200 Hz, LPF1 cutoff 63.3 Hz, LPF2 cutoff 12.5 Hz */
|
||
L3GXXXX_ODR_200_25 = 0x05, /**< High ODR 200 Hz, LPF1 cutoff 63.3 Hz, LPF2 cutoff 25 Hz */
|
||
L3GXXXX_ODR_200_50 = 0x06, /**< High ODR 200 Hz, LPF1 cutoff 63.3 Hz, LPF2 cutoff 50 Hz */
|
||
L3GXXXX_ODR_200_70 = 0x07, /**< High ODR 200 Hz, LPF1 cutoff 63.3 Hz, LPF2 cutoff 70 Hz */
|
||
L3GXXXX_ODR_400_20 = 0x08, /**< High ODR 400 Hz, LPF1 cutoff 128 Hz, LPF2 cutoff 20 Hz */
|
||
L3GXXXX_ODR_400_25 = 0x09, /**< High ODR 400 Hz, LPF1 cutoff 128 Hz, LPF2 cutoff 25 Hz */
|
||
L3GXXXX_ODR_400_50 = 0x0a, /**< High ODR 400 Hz, LPF1 cutoff 128 Hz, LPF2 cutoff 50 Hz */
|
||
L3GXXXX_ODR_400_110 = 0x0b, /**< High ODR 400 Hz, LPF1 cutoff 128 Hz, LPF2 cutoff 110 Hz */
|
||
L3GXXXX_ODR_800_30 = 0x0c, /**< High ODR 400 Hz, LPF1 cutoff 211 Hz, LPF2 cutoff 30 Hz */
|
||
L3GXXXX_ODR_800_35 = 0x0d, /**< High ODR 400 Hz, LPF1 cutoff 211 Hz, LPF2 cutoff 35 Hz */
|
||
L3GXXXX_ODR_800_50 = 0x0e, /**< High ODR 400 Hz, LPF1 cutoff 211 Hz, LPF2 cutoff 50 Hz */
|
||
L3GXXXX_ODR_800_100 = 0x0f, /**< High ODR 400 Hz, LPF1 cutoff 211 Hz, LPF2 cutoff 100 Hz */
|
||
#if IS_USED(MODULE_L3GD20H) || IS_USED(MODULE_L3GXXXX_LOW_ODR) || DOXYGEN
|
||
L3GXXXX_ODR_12 = 0x10, /**< Low ODR 12.5 Hz, LPF1 cutoff 3.9 Hz, LPF2 not used */
|
||
L3GXXXX_ODR_25 = 0x14, /**< Low ODR 25 Hz, LPF1 cutoff 7.8 Hz, LPF2 not used */
|
||
L3GXXXX_ODR_50 = 0x18, /**< Low ODR 50 Hz, LPF1 cutoff 16 Hz, LPF2 cutoff 16.6 Hz */
|
||
#endif
|
||
} l3gxxxx_odr_t;
|
||
|
||
/**
|
||
* @brief Full scale in degrees per second (dps)
|
||
*
|
||
* The full scale value determines the sensitivity of the sensor and thus
|
||
* the range and resolution of the sensor's output data. The resolution
|
||
* of the output data is about Full Scale/INT16_MAX.
|
||
*
|
||
* @note On the A34250D, only 245 dps (#L3GXXXX_SCALE_245_DPS) is
|
||
* available as full scale value.
|
||
*/
|
||
typedef enum {
|
||
L3GXXXX_SCALE_245_DPS = 0, /**< 245 dps (default) */
|
||
L3GXXXX_SCALE_500_DPS = 1, /**< 500 dps */
|
||
L3GXXXX_SCALE_2000_DPS = 2, /**< 2000 dps */
|
||
} l3gxxxx_scale_t;
|
||
|
||
/**
|
||
* @brief FIFO mode
|
||
*
|
||
* The integrated FIFO with up to 32 data samples can be used in different
|
||
* modes. The mode defines the behavior of FIFO when it becomes full.
|
||
*/
|
||
typedef enum {
|
||
L3GXXXX_BYPASS = 0, /**< FIFO is not used (default) */
|
||
|
||
L3GXXXX_FIFO = 1, /**< Data samples are stored in the FIFO until
|
||
it is full */
|
||
L3GXXXX_STREAM = 2, /**< FIFO is used as ring buffer and newest
|
||
data samples are stored continuously */
|
||
#if IS_USED(MODULE_L3GD20H) || IS_USED(MODULE_L3GD20) || DOXYGEN
|
||
L3GXXXX_STREAM_TO_FIFO = 3, /**< FIFO is used in Stream mode until an
|
||
interrupt, switches then to FIFO mode
|
||
(L3GD20H and L3GD20 only) */
|
||
L3GXXXX_BYPASS_TO_STREAM = 4, /**< FIFO is not used until an interrupt,
|
||
switches then to Stream mode
|
||
(L3GD20H and L3GD20 only) */
|
||
#endif
|
||
#if IS_USED(MODULE_L3GD20H) || DOXYGEN
|
||
L3GXXXX_DYNAMIC_STREAM = 6, /**< like Stream mode, but differs in reading
|
||
the first data sample after emptying
|
||
(L3GD20H only) */
|
||
L3GXXXX_BYPASS_TO_FIFO = 7 /**< FIFO is not used until an interrupt,
|
||
switches then to FIFO mode
|
||
(L3GD20H only) */
|
||
#endif
|
||
} l3gxxxx_fifo_mode_t;
|
||
|
||
/**
|
||
* @brief High pass filter (HPF) and low pass filter 2 (LPF2) selection
|
||
*
|
||
* L3Gxxxx sensors integrate a combination of two low pass filters (LPF) and
|
||
* one high pass filter (HPF).
|
||
*
|
||
* First, raw sensor data are always filtered by LPF1 with a cutoff frequency
|
||
* that is fixed for the selected output data rate (ODR), see #l3gxxxx_odr_t.
|
||
* Resulting data can then optionally be filtered by HPF and/or LPF2. Both
|
||
* filters can be used or bypassed.
|
||
*
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
* +---------------> L3GXXXX_NO_FILTER
|
||
* | +----- +
|
||
* +------------+--->| |---> L3GXXXX_LPF2_ONLY
|
||
* | | LPF2 |
|
||
* +-----+ +------+ | +-----+ +--->| |---> L3GXXXX_HPF_AND_LPF2
|
||
* | | | | | | | | +------+
|
||
* | ADC |-->| LPF1 |--+-->| HPF |--+---------------> L3GXXXX_HPF_ONLY
|
||
* | | | | | |
|
||
* +-----+ +------+ +-----+
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
* #l3gxxxx_filter_sel_t defines the possible filter combinations that can
|
||
* be used to select the filters for the output data and for the
|
||
* interrupt generation separately.
|
||
*
|
||
* The default filter selection for the output data is #L3GXXXX_HPF_AND_LPF2
|
||
* and is defined by the default configuration parameter
|
||
* #CONFIG_L3GXXXX_FILTER_SEL. If the module `l3gxxxx_config` is used, it can
|
||
* be changed at runtime using function #l3gxxxx_select_output_filter.
|
||
*
|
||
* The default filter selection for event interrupt generation is
|
||
* #L3GXXXX_HPF_AND_LPF2 and is defined by default configuration parameter
|
||
* #CONFIG_L3GXXXX_INT1_FILTER. It can be changed at runtime with function
|
||
* #l3gxxxx_set_int_event_cfg.
|
||
*
|
||
* @note Since same filters are used for the output data as well as the
|
||
* data used for event interrupt generation (selective axes movement / wake-up),
|
||
* the configuration of the filters always affects both data. If the HPF is
|
||
* enabled for filtering the output data, it is also active for filtering the
|
||
* sensor data used for interrupt generation if the LPF2 is enabled for
|
||
* interrupt generation. The other way around, the HPF is also active for
|
||
* filtering the output data when it is enabled for interrupt generation and
|
||
* when the LPF2 is enabled for the output data.
|
||
*
|
||
* The cutoff frequencies of LPF1 and LPF2 are determined by the used output
|
||
* data rate #l3gxxxx_odr_t, see section [Output Data Rates and Filters]
|
||
* (#l3gxxxx_odr_filters). The default cutoff frequency of HPF is 8 Hz and
|
||
* set by the default configuration parameter #CONFIG_L3GXXXX_HPF_CUTOFF.
|
||
* If module `l3gxxxx_config` is used, it can be changed at runtime using
|
||
* function #l3gxxxx_config_hpf.
|
||
*/
|
||
typedef enum {
|
||
L3GXXXX_NO_FILTER = 0, /**< HPF not used, LPF2 not used (default) */
|
||
L3GXXXX_HPF_ONLY = 1, /**< HPF used, LPF2 not used */
|
||
L3GXXXX_LPF2_ONLY = 2, /**< HPF not used, LPF2 used */
|
||
L3GXXXX_HPF_AND_LPF2 = 3 /**< HPF used, LPF2 used */
|
||
} l3gxxxx_filter_sel_t;
|
||
|
||
/**
|
||
* @brief HPF (high pass filter) modes
|
||
*
|
||
* The high pass filter can be used in different modes.
|
||
*/
|
||
typedef enum {
|
||
L3GXXXX_HPF_NORMAL = 0, /**< Normal mode, HPF is reset by reading
|
||
the REFERENCE register */
|
||
L3GXXXX_HPF_REFERENCE = 1, /**< Reference mode, output data are the
|
||
difference to the REFERENCE register */
|
||
L3GXXXX_HPF_AUTORESET = 3 /**< Autoreset mode, HPF is automatically reset
|
||
when a configured event interrupt occurs */
|
||
} l3gxxxx_hpf_mode_t;
|
||
|
||
/**
|
||
* @brief Interrupt types
|
||
*
|
||
* L3Gxxxx sensors support different types of interrupts. These are on the
|
||
* one hand the various data interrupts on signal `INT2/DRDY` and on the
|
||
* other hand event interrupts on signal `INT1`.
|
||
*
|
||
* The enumeration values correspond to the according bits in register
|
||
* CTRL3 (#L3GXXXX_REG_CTRL3).
|
||
*
|
||
* #L3GXXXX_INT_DATA combines the various data interrupts to an ORed value.
|
||
*/
|
||
typedef enum {
|
||
/**
|
||
* Data interrupt on signal `INT2/DRDY`: Output data are ready to be read.
|
||
*/
|
||
L3GXXXX_INT_DATA_READY = L3GXXXX_INT2_DRDY,
|
||
/**
|
||
* Data interrupt on signal `INT2/DRDY`: FIFO filling exceeds the
|
||
* watermark level (threshold)
|
||
*/
|
||
L3GXXXX_INT_FIFO_WATERMARK = L3GXXXX_INT2_WTM,
|
||
/**
|
||
* Data interrupt on signal `INT2/DRDY`: FIFO is completely filled
|
||
*/
|
||
L3GXXXX_INT_FIFO_OVERRUN = L3GXXXX_INT2_ORUN,
|
||
/**
|
||
* Data interrupt on signal `INT2/DRDY`: FIFO becomes empty
|
||
*/
|
||
L3GXXXX_INT_FIFO_EMPTY = L3GXXXX_INT2_EMPTY,
|
||
/**
|
||
* Event interrupt on signal `INT1`: Angular rate of one or more axes
|
||
* is lower or higher than the configured threshold.
|
||
*/
|
||
L3GXXXX_INT_EVENT = L3GXXXX_INT1_IG,
|
||
} l3gxxxx_int_types_t;
|
||
|
||
/**
|
||
* @brief Data interrupts (Data ready and FIFO status)
|
||
*
|
||
* This define combines the data interrupt types of #l3gxxxx_int_types_t
|
||
* that use the `INT2/DRDY` signal to an ORed value.
|
||
*/
|
||
#define L3GXXXX_INT_DATA (L3GXXXX_INT_DATA_READY | \
|
||
L3GXXXX_INT_FIFO_WATERMARK | \
|
||
L3GXXXX_INT_FIFO_OVERRUN | \
|
||
L3GXXXX_INT_FIFO_EMPTY)
|
||
|
||
/**
|
||
* @brief Event interrupt generator configuration (axis movement and wake-up)
|
||
*
|
||
* memset to 0 to disable all interrupt conditions (default)
|
||
*/
|
||
typedef struct {
|
||
uint16_t x_threshold; /**< X threshold value in full scale / INT16_MAX */
|
||
uint16_t y_threshold; /**< Y threshold value in full scale / INT16_MAX */
|
||
uint16_t z_threshold; /**< Z threshold value in full scale / INT16_MAX */
|
||
|
||
bool x_low_enabled; /**< Interrupt enabled for |X| < X threshold (X low event) */
|
||
bool x_high_enabled; /**< Interrupt enabled for |X| > X threshold (X high event) */
|
||
|
||
bool y_low_enabled; /**< Interrupt enabled for |Y| < Y threshold (Y low event) */
|
||
bool y_high_enabled; /**< Interrupt enabled for |Y| > Y threshold (Y high event) */
|
||
|
||
bool z_low_enabled; /**< Interrupt enabled for |Z| < Z threshold (Z low event) */
|
||
bool z_high_enabled; /**< Interrupt enabled for |Z| > Z threshold (Y high event) */
|
||
|
||
l3gxxxx_filter_sel_t filter; /**< HPF and LPF2 filter selection used
|
||
for threshold comparison */
|
||
|
||
bool and_or; /**< Combination of interrupt events (true=AND, false=OR):<br>
|
||
AND - all enabled axes passed their thresholds<br>
|
||
OR - at least one axis passed its threshold */
|
||
bool latch; /**< Latch the interrupt when true until the interrupt
|
||
source has been read by function l3gxxxx_wait_int. */
|
||
uint8_t duration; /**< Duration in 1/ODR an interrupt condition has to be
|
||
given before the interrupt is generated. */
|
||
bool wait; /**< When true, duration is also used when interrupt
|
||
condition in no longer given before interrupt
|
||
signal is reset. */
|
||
bool counter_mode; /**< DCRM is not documented and not used therefore. */
|
||
} l3gxxxx_int_event_cfg_t;
|
||
|
||
/**
|
||
* @brief Event interrupt sources (axis movement and wake-up)
|
||
*/
|
||
typedef union {
|
||
struct {
|
||
uint8_t x_low :1; /**< true on |X| < X threshold (X low event) */
|
||
uint8_t x_high:1; /**< true on |X| > X threshold (X high event) */
|
||
uint8_t y_low :1; /**< true on |Y| < Y threshold (Y low event) */
|
||
uint8_t y_high:1; /**< true on |Y| > Y threshold (Y high event) */
|
||
uint8_t z_low :1; /**< true on |Z| < Z threshold (Z low event) */
|
||
uint8_t z_high:1; /**< true on |Z| > Z threshold (Z high event) */
|
||
uint8_t active:1; /**< true when one or more events have been generated */
|
||
uint8_t unused:1; /**< not used */
|
||
};
|
||
uint8_t val; /**< event interrupt sources as value that
|
||
can be used for bitwise operations */
|
||
} l3gxxxx_int_event_src_t;
|
||
|
||
/**
|
||
* @brief Data interrupt sources (data ready and FIFO status)
|
||
*/
|
||
typedef union {
|
||
struct {
|
||
uint8_t fifo_empty :1; /**< true when FIFO is empty */
|
||
uint8_t fifo_overrun :1; /**< true when FIFO is completely filled */
|
||
uint8_t fifo_watermark:1; /**< true when FIFO filling > watermark */
|
||
uint8_t data_ready :1; /**< true when data are ready to read */
|
||
uint8_t unused :4; /**< not used */
|
||
};
|
||
uint8_t val; /**< data interrupt sources as value that
|
||
can be used for bitwise operations */
|
||
} l3gxxxx_int_data_src_t;
|
||
|
||
/**
|
||
* @brief Composite type for all possible interrupt sources
|
||
*
|
||
* This type combines the possible interrupt sources for event interrupts on
|
||
* signal `INT1` (l3gxxxx_int_event_src_t) with those for data interrupts on
|
||
* signal `INT2/DRDY` (l3gxxxx_int_data_src_t).
|
||
*/
|
||
typedef struct {
|
||
l3gxxxx_int_event_src_t event; /**< event interrupt sources */
|
||
l3gxxxx_int_data_src_t data; /**< data interrupt sources */
|
||
} l3gxxxx_int_src_t;
|
||
|
||
/**
|
||
* @brief `INT1`, `INT2/DRDY` sensor signal activity level
|
||
*/
|
||
typedef enum {
|
||
L3GXXXX_HIGH = 0, /**< INT signals are High active (default) */
|
||
L3GXXXX_LOW /**< INT signals are Low active */
|
||
} l3gxxxx_int_pin_level_t;
|
||
|
||
/**
|
||
* @brief `INT1`, `INT2/DRDY` sensor signal type
|
||
*/
|
||
typedef enum {
|
||
L3GXXXX_PUSH_PULL = 0, /**< INT pins are push/pull outputs (default) */
|
||
L3GXXXX_OPEN_DRAIN /**< INT pins are open-drain */
|
||
} l3gxxxx_int_pin_type_t;
|
||
|
||
/**
|
||
* @brief Raw output data set as two's complements
|
||
*/
|
||
typedef struct {
|
||
int16_t x; /**< X angular rate (roll) as 16 bit two's complements */
|
||
int16_t y; /**< Y angular rate (pitch) as 16 bit two's complements */
|
||
int16_t z; /**< Z angular rate (yaw) as 16 bit two's complements */
|
||
} l3gxxxx_raw_data_t;
|
||
|
||
/**
|
||
* @brief Angular rates in millidegrees per seconds (mdps)
|
||
*/
|
||
typedef struct {
|
||
int32_t x; /**< X angular rate (roll) */
|
||
int32_t y; /**< Y angular rate (pitch) */
|
||
int32_t z; /**< Z angular rate (yaw) */
|
||
} l3gxxxx_data_t;
|
||
|
||
/**
|
||
* @brief Raw output data FIFO type
|
||
*/
|
||
typedef l3gxxxx_raw_data_t l3gxxxx_raw_data_fifo_t[32];
|
||
|
||
/**
|
||
* @brief Angular rates FIFO type
|
||
*/
|
||
typedef l3gxxxx_data_t l3gxxxx_data_fifo_t[32];
|
||
|
||
/**
|
||
* @brief L3Gxxxx interface types
|
||
*/
|
||
typedef enum {
|
||
#if IS_USED(MODULE_L3GXXXX_I2C) || DOXYGEN
|
||
L3GXXXX_I2C, /**< I2C interface used */
|
||
#endif
|
||
#if IS_USED(MODULE_L3GXXXX_SPI) || DOXYGEN
|
||
L3GXXXX_SPI, /**< SPI interface used */
|
||
#endif
|
||
} l3gxxxx_if_t;
|
||
|
||
#if IS_USED(MODULE_L3GXXXX_I2C) || DOXYGEN
|
||
/**
|
||
* @brief L3Gxxxx I2C interface parameters
|
||
*/
|
||
typedef struct {
|
||
i2c_t dev; /**< I2C device used */
|
||
uint8_t addr; /**< I2C slave address */
|
||
} l3gxxxx_i2c_params_t;
|
||
#endif
|
||
|
||
#if IS_USED(MODULE_L3GXXXX_SPI) || DOXYGEN
|
||
/**
|
||
* @brief L3Gxxxx SPI interface parameters
|
||
*/
|
||
typedef struct {
|
||
spi_t dev; /**< SPI device used */
|
||
spi_clk_t clk; /**< SPI clock speed */
|
||
gpio_t cs; /**< SPI chip Select pin */
|
||
} l3gxxxx_spi_params_t;
|
||
#endif
|
||
|
||
/**
|
||
* @brief L3Gxxxx Hardware interface parameters union
|
||
*/
|
||
typedef struct {
|
||
l3gxxxx_if_t type; /**< I2C/SPI interface type selector */
|
||
union {
|
||
#if IS_USED(MODULE_L3GXXXX_I2C) || DOXYGEN
|
||
l3gxxxx_i2c_params_t i2c; /**< I2C interface parameters */
|
||
#endif
|
||
#if IS_USED(MODULE_L3GXXXX_SPI) || DOXYGEN
|
||
l3gxxxx_spi_params_t spi; /**< SPI interface parameters */
|
||
#endif
|
||
};
|
||
} l3gxxxx_if_params_t;
|
||
|
||
/**
|
||
* @brief L3Gxxxx device initialization parameters
|
||
*/
|
||
typedef struct {
|
||
l3gxxxx_if_params_t if_params; /**< Interface parameters (I2C/SPI) */
|
||
|
||
l3gxxxx_odr_t odr; /**< ODR and LPF2 cutoff frequency */
|
||
l3gxxxx_scale_t scale; /**< Full scale */
|
||
|
||
l3gxxxx_filter_sel_t filter_sel; /**< HPF/LPF2 filter selection */
|
||
l3gxxxx_hpf_mode_t hpf_mode; /**< HPF mode */
|
||
uint8_t hpf_cutoff; /**< HPF cutoff frequency 0..9, see
|
||
l3gxxxx_config_hpf for details */
|
||
#if IS_USED(MODULE_L3GXXXX_FIFO) || DOXYGEN
|
||
l3gxxxx_fifo_mode_t fifo_mode; /**< FIFO operation mode */
|
||
uint8_t fifo_watermark; /**< FIFO watermark setting 0..31 */
|
||
#endif
|
||
|
||
#if IS_USED(MODULE_L3GXXXX_IRQ_DATA) || DOXYGEN
|
||
gpio_t int2_pin; /**< MCU GPIO pin for data interrupts
|
||
on signal `INT2/DRDY` pin */
|
||
#endif
|
||
|
||
#if IS_USED(MODULE_L3GXXXX_IRQ_EVENT) || DOXYGEN
|
||
l3gxxxx_int_event_cfg_t int1_cfg; /**< event interrupt parameters */
|
||
gpio_t int1_pin; /**< MCU GPIO pin for event interrupts
|
||
on signal `INT1` */
|
||
#endif
|
||
|
||
} l3gxxxx_params_t;
|
||
|
||
/**
|
||
* @brief L3Gxxxx sensor device data structure type
|
||
*/
|
||
typedef struct {
|
||
l3gxxxx_params_t params; /**< Device initialization parameters */
|
||
l3gxxxx_int_types_t int_type; /**< Type of the last interrupt triggered */
|
||
mutex_t int_lock; /**< Used to lock the calling thread while
|
||
waiting for an interrupt */
|
||
enum { /**< Sensor detected at runtime */
|
||
L3GD20H, /**< L3GD20H detected */
|
||
L3GD20, /**< L3GD20 detected */
|
||
X3G42XXD /**< L3G400D, I3G4250D or A3G4250D detected */
|
||
} sensor; /**< recognized sensor type */
|
||
} l3gxxxx_t;
|
||
|
||
/**
|
||
* @name Sensor initialization and configuration
|
||
* @{
|
||
*/
|
||
|
||
/**
|
||
* @brief Initialize the L3Gxxxx sensor device
|
||
*
|
||
* This function resets the sensor and initializes it according to the
|
||
* given configuration parameter set. All registers are reset to their
|
||
* default values. The FIFO is cleared.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor to be initialized
|
||
* @param[in] params L3Gxxxx configuration parameters
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_init(l3gxxxx_t *dev, const l3gxxxx_params_t *params);
|
||
|
||
#if IS_USED(MODULE_L3GXXXX_CONFIG) || DOXYGEN
|
||
/**
|
||
* @brief Set sensor mode
|
||
*
|
||
* @note This function is available only if module `l3gxxxx_config` is used.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
* @param[in] odr output data rate (ODR) and LPF2 cutoff frequency
|
||
* @param[in] x enable X axis measurements if true
|
||
* @param[in] y enable Y axis measurements if true
|
||
* @param[in] z enable Z axis measurements if true
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_set_mode(l3gxxxx_t *dev,
|
||
l3gxxxx_odr_t odr, bool x, bool y, bool z);
|
||
|
||
/**
|
||
* @brief Set full scale
|
||
*
|
||
* @note This function is available only if module `l3gxxxx_config` is used.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
* @param[in] scale fulle scale
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_set_scale(l3gxxxx_t *dev, l3gxxxx_scale_t scale);
|
||
|
||
#endif /* IS_USED(MODULE_L3GXXXX_CONFIG) || DOXYGEN */
|
||
/** @} */
|
||
|
||
/**
|
||
* @name Power saving functions
|
||
* @{
|
||
*/
|
||
/**
|
||
* @brief Power down the sensor
|
||
*
|
||
* Changes the sensor operation mode to power-down mode. In this mode almost all
|
||
* internal blocks including the gyros are switched off. I2C and SPI interfaces
|
||
* are still active. The content of the configuration registers is preserved.
|
||
*
|
||
* @param[in] dev Device descriptor of L3Gxxxx device to read from
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_power_down (l3gxxxx_t *dev);
|
||
|
||
/**
|
||
* @brief Power up the sensor
|
||
*
|
||
* Swichtes the sensor back into the last active operation mode. It takes
|
||
* up to 100 ms since the gyros have to be switched on.
|
||
*
|
||
* @param[in] dev Device descriptor of L3Gxxxx device to read from
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_power_up (l3gxxxx_t *dev);
|
||
|
||
#if IS_USED(MODULE_L3GXXXX_SLEEP) || DOXYGEN
|
||
/**
|
||
* @brief Sleep mode
|
||
*
|
||
* Activates the sleep mode of the sensor. In this mode, measurements for all
|
||
* axes are disabled, but the gyroscopes remain on. To return from sleep mode,
|
||
* function #l3gxxxx_wake_up is used.
|
||
*
|
||
* @note This function is available only if module `l3gxxxx_sleep` is used.
|
||
*
|
||
* @param[in] dev Device descriptor of L3Gxxxx device to read from
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_sleep (l3gxxxx_t *dev);
|
||
|
||
/**
|
||
* @brief Wake-up the sensor
|
||
*
|
||
* Swichtes the sensor back into the last active operation mode. It takes only
|
||
* 1/ODR when LPF2 is disabled and 6/ODR when LPF2 is enabled to
|
||
* continue measurements.
|
||
*
|
||
* @note This function is available only if module `l3gxxxx_sleep` is used.
|
||
*
|
||
* @param[in] dev Device descriptor of L3Gxxxx device to read from
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_wake_up (l3gxxxx_t *dev);
|
||
|
||
#endif /* IS_USED(MODULE_L3GXXXX_SLEEP) || DOXYGEN */
|
||
/** @} */
|
||
|
||
/**
|
||
* @name Basic sensor data handling
|
||
* @{
|
||
*/
|
||
|
||
/**
|
||
* @brief Data ready status function
|
||
*
|
||
* This function returns the number of new data samples that are ready to be
|
||
* read or 0 if no new data samples are available.
|
||
*
|
||
* If the FIFO is not used or used in bypass mode (#L3GXXXX_BYPASS), the
|
||
* maximum number of available data samples is 1. If another FIFO mode is
|
||
* used, the number of available data samples is equal to the number of
|
||
* new data samples in the FIFO.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
*
|
||
* @return number of data samples available for read or negative error code,
|
||
* see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_data_ready(const l3gxxxx_t *dev);
|
||
|
||
/**
|
||
* @brief Read last sample of angular rates in millidegree per second (mpds)
|
||
*
|
||
* Raw output data are read from the sensor and converted to angular rates
|
||
* in millidegrees per second (mdps). The resolution of the angular rates
|
||
* depends on the configured full scale value as follows:
|
||
*
|
||
* <center>
|
||
* | Full Scale | Resolution | Driver symbol | Remark |
|
||
* | -----------:|-----------------:|:------------------------|:--------------------------|
|
||
* | ±245 dps | 8.75 mdps / LSB | #L3GXXXX_SCALE_245_DPS | |
|
||
* | ±500 dps | 17.50 mdps / LSB | #L3GXXXX_SCALE_500_DPS | not available on A3G4250D |
|
||
* | ±2000 dps | 70.00 mdps / LSB | #L3GXXXX_SCALE_2000_DPS | not available on A3G4250D |
|
||
* </center><br>
|
||
*
|
||
* @note If the FIFO is enabled by module `l3gxxxxx_fifo`, the function
|
||
* returns only the last sample. To read all samples from the FIFO, function
|
||
* l3gxxxx_read_fifo has to be used.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
* @param[out] data last sample of angular rates in mdps
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_read(const l3gxxxx_t *dev, l3gxxxx_data_t *data);
|
||
|
||
/**
|
||
* @brief Read last sample of raw output data as 16 bit two's complements
|
||
*
|
||
* @note If the FIFO is enabled by module `l3gxxxxx_fifo`, the function
|
||
* returns only the last sample. To read all samples from the FIFO, function
|
||
* l3gxxxx_read_raw_fifo has to be used.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
* @param raw last sample of raw output data as 16 bit two's
|
||
* complements
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_read_raw(const l3gxxxx_t *dev, l3gxxxx_raw_data_t *raw);
|
||
|
||
/** @} */
|
||
|
||
#if IS_USED(MODULE_L3GXXXX_FIFO) || DOXYGEN
|
||
|
||
/**
|
||
* @name FIFO handling
|
||
* @{
|
||
*/
|
||
|
||
#if IS_USED(MODULE_L3GXXXX_CONFIG) || DOXYGEN
|
||
/**
|
||
* @brief Set FIFO mode and watermark level (threshold)
|
||
*
|
||
* The FIFO buffer can work in seven different modes and is able to store
|
||
* up to 32 data samples, see #l3gxxxx_fifo_mode_t. The use of the FIFO allows
|
||
* to reduce the interaction events of the MCU with the sensor and thus to
|
||
* save power.
|
||
*
|
||
* The watermark level can be used to define the number of raw output data
|
||
* samples that have to be stored in the FIFO before the watermark flag is
|
||
* set and the #L3GXXXX_INT_FIFO_WATERMARK is triggered, if enabled. The
|
||
* watermark flag is set and the interrupt #L3GXXXX_INT_FIFO_WATERMARK is
|
||
* triggered when the number of samples stored in the FIFO becomes greater
|
||
* than this watermark level (threshold).
|
||
*
|
||
* @note This function is available only if modules `l3gxxxx_fifo`
|
||
* and `l3gxxxx_config` are used.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
* @param[in] mode FIFO mode
|
||
* @param[in] watermark FIFO watermark (ignored in bypass mode)
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_set_fifo_mode(l3gxxxx_t *dev,
|
||
l3gxxxx_fifo_mode_t mode, uint8_t watermark);
|
||
|
||
#endif /* IS_USED(MODULE_L3GXXXX_CONFIG) || DOXYGEN */
|
||
|
||
/**
|
||
* @brief Get all samples of angular rates stored in the FIFO (unit mdps)
|
||
*
|
||
* This function reads all samples of raw output data from the FIFO and
|
||
* converts them to angular rates in millidegrees per second (mdps) according
|
||
* to the configured full scale. For details about the resolution of these
|
||
* angular rates see l3gxxxx_read.
|
||
*
|
||
* In bypass mode (#L3GXXXX_BYPASS), it returns only the last sample.
|
||
*
|
||
* @note This function is available only if module `l3gxxxx_fifo` is used.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
* @param[out] data array for up to 32 samples of angular rates in mdps
|
||
*
|
||
* @return number of data samples read on success, or negative error code,
|
||
* see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_read_fifo(const l3gxxxx_t *dev,
|
||
l3gxxxx_data_fifo_t data);
|
||
|
||
/**
|
||
* @brief Get all samples of raw output data stored in the FIFO
|
||
*
|
||
* This function reads all samples of raw output data from the FIFO.
|
||
* In bypass mode (#L3GXXXX_BYPASS), it returns only the last raw
|
||
* output data sample.
|
||
*
|
||
* @note This function is available only if module `l3gxxxx_fifo` is used.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
* @param[out] raw array for up to 32 raw output data as two's complement
|
||
*
|
||
* @return number of data samples read on success, or negative error code,
|
||
* see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_read_raw_fifo(const l3gxxxx_t *dev,
|
||
l3gxxxx_raw_data_fifo_t raw);
|
||
|
||
#endif /* IS_USED(MODULE_L3GXXXX_FIFO) || DOXYGEN */
|
||
/** @} */
|
||
|
||
#if IS_USED(MODULE_L3GXXXX_CONFIG) || DOXYGEN
|
||
/**
|
||
* @name Filter configuration and handling
|
||
* @{
|
||
*/
|
||
|
||
/**
|
||
* @brief Filter selection for raw output data
|
||
*
|
||
* L3Gxxxx supports a combination of a high pass filter (HPF) and a second
|
||
* low pass filter (LPF2). This function selects the combination of the HPF
|
||
* and the LPF2 applied to raw output data.
|
||
*
|
||
* @note
|
||
* - This function is available only if module `l3gxxxx_config` is used.
|
||
* - The filter selection for the output data also affects the filter
|
||
* selection for event interrupt generation. If the HPF is enabled for
|
||
* filtering the output data, it is also active for filtering the sensor
|
||
* data used for interrupt generation if the LPF2 is enabled for interrupt
|
||
* generation.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
* @param[in] filter selected filters for output values
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_select_output_filter(l3gxxxx_t *dev,
|
||
l3gxxxx_filter_sel_t filter);
|
||
|
||
/**
|
||
* @brief Config HPF (high pass filter) for output data
|
||
*
|
||
* The cutoff frequency of the HPF depends on the selected output data rate
|
||
* (ODR). The following table shows the possible values of parameter \p cutoff
|
||
* and the cutoff frequencies for the according ODRs. All frequencies are
|
||
* given in Hz.
|
||
*
|
||
* <center>
|
||
* | cutoff / ODR | 12.5 | 25 | 50 | 100 | 200 | 400 | 800 |
|
||
* |-------------:|:-----:|:-----:|:-----:|:----:|:----:|:----:|:---:|
|
||
* | 0 | 1 | 2 | 4 | 8 | 15 | 30 | 56 |
|
||
* | 1 | 0.5 | 1 | 2 | 4 | 8 | 15 | 30 |
|
||
* | 2 | 0.2 | 0.5 | 1 | 2 | 4 | 8 | 15 |
|
||
* | 3 | 0.1 | 0.2 | 0.5 | 1 | 2 | 4 | 8 |
|
||
* | 4 | 0.05 | 0.1 | 0.2 | 0.5 | 1 | 2 | 4 |
|
||
* | 5 | 0.02 | 0.05 | 0.1 | 0.2 | 0.5 | 1 | 2 |
|
||
* | 6 | 0.01 | 0.02 | 0.05 | 0.1 | 0.2 | 0.5 | 1 |
|
||
* | 7 | 0.005 | 0.01 | 0.02 | 0.05 | 0.1 | 0.2 | 0.5 |
|
||
* | 8 | 0.002 | 0.005 | 0.01 | 0.02 | 0.05 | 0.1 | 0.2 |
|
||
* | 9 | 0.001 | 0.002 | 0.005 | 0.01 | 0.02 | 0.05 | 0.1 |
|
||
* </center><br>
|
||
*
|
||
* @note This function is available only if module `l3gxxxx_config` is used.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
* @param[in] mode high pass filter mode, see #l3gxxxx_hpf_mode_t
|
||
* @param[in] cutoff cutoff frequency (depends on ODR) [0 ... 9]
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_config_hpf(const l3gxxxx_t *dev,
|
||
l3gxxxx_hpf_mode_t mode, uint8_t cutoff);
|
||
|
||
/**
|
||
* @brief Set HPF (high pass filter) reference
|
||
*
|
||
* Used to set the reference for HPF in reference mode #L3GXXXX_HPF_REFERENCE
|
||
* and to reset the HPF in autoreset mode #L3GXXXX_HPF_AUTORESET.
|
||
* Reference is given as two's complement.
|
||
*
|
||
* @note This function is available only if module `l3gxxxx_config` is used.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
* @param[in] ref reference in #L3GXXXX_HPF_REFERENCE mode, otherwise ignored
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_set_hpf_ref(const l3gxxxx_t *dev, int8_t ref);
|
||
|
||
/**
|
||
* @brief Get HPF (high pass filter) reference
|
||
*
|
||
* Returns the content of the REFERENCE register. In normal mode
|
||
* #L3GXXXX_HPF_NORMAL, it is also used to reset the HPF.
|
||
*
|
||
* @note This function is available only if module `l3gxxxx_config` is used.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
* @param[out] ref reference
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_get_hpf_ref(const l3gxxxx_t *dev, int8_t *ref);
|
||
|
||
#endif /* IS_USED(MODULE_L3GXXXX_CONFIG) || DOXYGEN */
|
||
/** @} */
|
||
|
||
#if IS_USED(MODULE_L3GXXXX_IRQ) || DOXYGEN
|
||
/**
|
||
* @name Interrupt configuration and handling
|
||
* @{
|
||
*/
|
||
|
||
/**
|
||
* @brief Enable or disable event and/or data interrupts on signal `INT1` and `INT2/DRDY`
|
||
*
|
||
* This function is used to enable or disable interrupts. The parameter \p mask
|
||
* is the ORed value of the interrupts that are enabled or disabled by the
|
||
* function call.
|
||
*
|
||
* @pre MCU GPIO pins for the `INT1` signal respectively the `INT2/DRDY`
|
||
* signal have to be defined for enabled interrupts
|
||
* (l3gxxxx_params_t::int1_pin and l3gxxxx_params_t::int2_pin).
|
||
*
|
||
* @note This function is available only if module `l3gxxxx_irq_data` and/or
|
||
* module `l3gxxxx_irq_event` are used.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
* @param[in] mask interrupts to be enabled or disabled
|
||
* @param[in] enable enable the interrupts if true, otherwise disable them
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_enable_int(const l3gxxxx_t *dev,
|
||
l3gxxxx_int_types_t mask, bool enable);
|
||
|
||
/**
|
||
* @brief Wait for event and/or data interrupts on signals `INT1` and `INT2/DRDY`
|
||
*
|
||
* The function waits for a configured interrupt and returns the sources of
|
||
* triggered interrupts. Since data interrupts (data ready and FIFO status)
|
||
* and event interrupts (axis movement and wake-up) use different signals,
|
||
* both data and event interrupts can occur simultaneously. The return
|
||
* value of type l3gxxxx_int_src_t contains all sources for which the interrupt
|
||
* conditions are fulfilled at the same time.
|
||
*
|
||
* @pre MCU GPIO pins for the `INT1` signal respectively the `INT2/DRDY`
|
||
* signal have to be defined for enabled interrupts
|
||
* (l3gxxxx_params_t::int1_pin and l3gxxxx_params_t::int2_pin).
|
||
*
|
||
* @note This function is available only if module `l3gxxxx_irq_data` and/or
|
||
* module `l3gxxxx_irq_event` are used.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
l3gxxxx_int_src_t l3gxxxx_wait_int(l3gxxxx_t *dev);
|
||
|
||
#if IS_USED(MODULE_L3GXXXX_IRQ_EVENT) || DOXYGEN
|
||
/**
|
||
* @brief Set new configuration for event interrupt generation
|
||
*
|
||
* The event interrupt generator produces interrupts (axis movement and wake-up)
|
||
* on signal `INT1` whenever the angular rate of one or more axes becomes higher
|
||
* or lower than defined thresholds.
|
||
*
|
||
* This function can be used at runtime to change the configuration of
|
||
* the interrupt conditions for event interrupt generation. This includes
|
||
* thresholds for all axes, enabled threshold interrupts, filter selection
|
||
* used for interrupt generation and other parameters, see
|
||
* l3gxxxx_int_event_cfg_t for details.
|
||
*
|
||
* @note This function is available only if module `l3gxxxx_irq_event` is used.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
* @param[in] cfg event interrupt generator configuration
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_set_int_event_cfg(const l3gxxxx_t *dev,
|
||
const l3gxxxx_int_event_cfg_t *cfg);
|
||
|
||
#if IS_USED(MODULE_L3GXXXX_CONFIG) || DOXYGEN
|
||
/**
|
||
* @brief Get current configuration of event interrupt generation
|
||
*
|
||
* This function can be used to retrieve the configuration of interrupt
|
||
* conditions currently used to generate event interrupts. See
|
||
* l3gxxxx_int_event_cfg_t for details.
|
||
*
|
||
* @note This function is available only if module `l3gxxxx_irq_event` and
|
||
* module `l3gxxxx_irq_config` are used.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
* @param[out] cfg event interrupt generator configuration
|
||
*
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_get_int_event_cfg(const l3gxxxx_t *dev,
|
||
l3gxxxx_int_event_cfg_t *cfg);
|
||
|
||
#endif /* IS_USED(MODULE_L3GXXXX_CONFIG) || DOXYGEN */
|
||
#endif /* IS_USED(MODULE_L3GXXXX_IRQ_EVENT) || DOXYGEN */
|
||
|
||
/** @} */
|
||
|
||
#endif /* IS_USED(MODULE_L3GXXXX_IRQ) || DOXYGEN */
|
||
|
||
/**
|
||
* @name Low level interface functions
|
||
* @{
|
||
*/
|
||
|
||
/**
|
||
* @brief Direct write to register
|
||
*
|
||
* @note This function should only be used to do something special that
|
||
* is not covered by the high level interface AND if you exactly know what you
|
||
* do and what effects it might have. Please be aware that it might affect the
|
||
* high level interface.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
* @param[in] reg address of the first register to be changed
|
||
* @param[in] data pointer to the data to be written to the register
|
||
* @param[in] len number of bytes to be written to the register
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_reg_write(const l3gxxxx_t *dev,
|
||
uint8_t reg, const uint8_t *data, uint8_t len);
|
||
|
||
/**
|
||
* @brief Direct read from register
|
||
*
|
||
* @note This function should only be used to do something special that
|
||
* is not covered by the high level interface AND if you exactly know what you
|
||
* do and what effects it might have. Please be aware that it might affect the
|
||
* high level interface.
|
||
*
|
||
* @param[in] dev device descriptor of the L3Gxxxx sensor
|
||
* @param[in] reg address of the first register to be read
|
||
* @param[out] data pointer to the data to be read from the register
|
||
* @param[in] len number of bytes to be read from the register
|
||
* @retval L3GXXXX_OK on success
|
||
* @retval L3GXXXX_ERROR_* negative error code, see #l3gxxxx_error_codes_t
|
||
*/
|
||
int l3gxxxx_reg_read(const l3gxxxx_t *dev,
|
||
uint8_t reg, uint8_t *data, uint8_t len);
|
||
/** @} */
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* L3GXXXX_H */
|
||
/** @} */
|