Skip to content

Commit

Permalink
drivers/mlx90393: added mlx90393_int and mlx90393_woc pseudo modules
Browse files Browse the repository at this point in the history
  • Loading branch information
mi6527ri committed Mar 12, 2024
1 parent 9eeb5df commit 4844ad3
Show file tree
Hide file tree
Showing 7 changed files with 262 additions and 85 deletions.
110 changes: 84 additions & 26 deletions drivers/include/mlx90393.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

/**
* @defgroup drivers_mlx90393 MLX90393
* @defgroup drivers_mlx90393 MLX90393 3-axis magnetometer
* @ingroup drivers_sensors
* @ingroup drivers_saul
* @brief Device driver for the MLX90393 3-axis magnetometer
Expand Down Expand Up @@ -41,15 +41,28 @@
* type #mlx90393_params_t as defined in the file `mlx90393_params.h
* - SAUL sensor interface
*
* The following pseudomodules are used to choose the communication bus:
* The following pseudomodules are used to choose the communication bus or add
* additional functionalities:
* <center>
* Pseudomodule | Bus
* Pseudomodule | Functionality
* :-------------------|:-------------------------------------------------------
* `mlx90393_i2c` | I2C
* `mlx90393_spi` | SPI
* `mlx90393_i2c` | Use I2C bus
* `mlx90393_spi` | Use SPI bus
* `mlx90393_int` | Data ready interrupt handling
* `mlx90393_woc` | Wake-up on change mode
* </center>
* <br>
*
* @note
* - If the handling of data ready interrupts is enabled by module `mlx90393_int`,
* the GPIO pin for the interrupt signal must be defined by the configuration parameter
* mlx90393_params_t::int_pin. The default configuration of this GPIO pin
* is defined by #MLX90393_PARAM_INT_PIN that can be overridden by the
* board definition. The interrupt signal is HIGH active. With the use of the module
* `mlx90393_int` polling is no longer supported.
* - For the Wake-up on change measurement mode the use of interrupt is mandatory.
* If the module `mlx90393_woc` is used, the module `mlx90393_int` is added automatically.
*
* # Using the driver
*
* ## Operation modes
Expand Down Expand Up @@ -129,18 +142,25 @@
* ## Using Interrupts
*
* The MLX90393 sensor supports the use of data-ready interrupts to signal when data is available.
* To use interrupts, connect the INT pin of the MLX90393 to the designated interrupt pin on the
* MCU, as configured in the parameters.
* When calling the function #mlx90393_read, it will block the calling thread until an interrupt
* is triggered. Once an interrupt is triggered, the driver handles the interrupt with an internal
* ISR and then proceeds with reading and converting data and finally returns from the
* #mlx90393_read function.
* To use interrupts, add the module `mlx90393_int`, connect the INT pin of the MLX90393 to the
* designated interrupt pin on the MCU, as configured in the parameters.
* In single measurement and burst mode, when calling the function #mlx90393_read,
* it will block the calling thread until an interrupt is triggered. Once an interrupt is
* triggered, the driver handles the interrupt with an internal ISR and then proceeds with
* reading and converting data and finally returns from the #mlx90393_read function.
* In wake-up on change mode the #mlx90393_enable_woc function can be used to activate the
* interrupt which is triggered, when the user defined threshold is crossed.
* Additionally a callback function for handling the interrupt and its argument are
* passed to the function.
* @warning
* The passed callback function is called in interrupt context and should not be used to access
* the sensor or execute time-consuming code.
*
* ## Power Saving
*
* The MLX90393 sensor can be shutdown into idle mode when no continuous measurements are
* required using the function #mlx90393_stop_cont. The power consumption is then reduced to
* max. 5 uA. To restart the MLX90393 in previous continuous measurement mode,
* a maximum of 5 uA. To restart the MLX90393 in previous continuous measurement mode,
* the #mlx90393_start_cont function can be used.
* In single measurement mode, once the measurement is completed, the sensor transitions into
* idle mode, awaiting a new command from the master to initiate another acquisition.
Expand All @@ -156,9 +176,9 @@
#define MLX90393_H

#include "periph/gpio.h"
#if MODULE_MLX90393_SPI
#if IS_USED(MODULE_MLX90393_SPI)
#include "periph/spi.h"
#elif MODULE_MLX90393_I2C
#elif IS_USED(MODULE_MLX90393_I2C)
#include "periph/i2c.h"
#endif

Expand All @@ -184,10 +204,12 @@ typedef struct {
typedef enum {
MLX90393_MODE_BURST, /**< Burst mode */
MLX90393_MODE_SINGLE_MEASUREMENT, /**< Single measurement mode */
#if IS_USED(MODULE_MLX90393_WOC) || DOXYGEN
MLX90393_MODE_WOC_ABSOLUTE, /**< Wake-up on change mode,
compared to first measurement */
MLX90393_MODE_WOC_RELATIVE, /**< Wake-up on change mode,
compared to previous measurement */
#endif
} mlx90393_mode_t;

/**
Expand Down Expand Up @@ -266,6 +288,7 @@ typedef struct {
mlx90393_oversampling_ratio_t temp; /**< Oversampling ratio temperature sensor */
} mlx90393_oversampling_t;

#if IS_USED(MODULE_MLX90393_WOC) || DOXYGEN
/**
* @brief Thresholds for wake-up on change mode
*/
Expand All @@ -275,26 +298,39 @@ typedef struct {
int temp; /**< Threshold for temperature */
} mlx90393_threshold_t;

/**
* @brief Signature of callback function triggered from wake-up on change interrupt
*
* @param[in] arg argument for the callback
*/
typedef void (*mlx90393_cb_t)(void *arg);

#endif

/**
* @brief Device configuration parameters
*/
typedef struct {
#if MODULE_MLX90393_SPI || DOXYGEN
spi_t spi; /**< SPI bus */
gpio_t cs_pin; /**< Connected chip select pin */
spi_clk_t clk; /**< clock speed for the SPI bus */
#elif MODULE_MLX90393_I2C || DOXYGEN
i2c_t i2c; /**< I2C device */
uint8_t addr; /**< Magnometer I2C address */
#if IS_USED(MODULE_MLX90393_SPI) || DOXYGEN
spi_t spi; /**< SPI bus */
gpio_t cs_pin; /**< Connected chip select pin */
spi_clk_t clk; /**< clock speed for the SPI bus */
#elif IS_USED(MODULE_MLX90393_I2C) || DOXYGEN
i2c_t i2c; /**< I2C device */
uint8_t addr; /**< Magnometer I2C address */
#endif
mlx90393_mode_t mode; /**< Measurement mode */
#if IS_USED(MODULE_MLX90393_INT) || DOXYGEN
gpio_t int_pin; /**< Interrupt pin */
#endif
mlx90393_gain_t gain; /**< Analog chain gain */
mlx90393_resolution_t resolution; /**< Desired 16-bit output value from the 19-bit ADC */
mlx90393_odr_t odr; /**< Output data rate */
mlx90393_oversampling_t oversampling; /**< Oversampling ratio */
mlx90393_digital_filter_t dig_filt; /**< Digital filter applicable to ADC */
#if IS_USED(MODULE_MLX90393_WOC) || DOXYGEN
mlx90393_threshold_t threshold; /**< Threshold for wake-up on change mode */
#endif
} mlx90393_params_t;

/**
Expand All @@ -304,7 +340,9 @@ typedef struct {
const mlx90393_params_t *params; /**< Device configuration parameters */
uint16_t ref_temp; /**< Reference temperature for converting raw temp data
in centi celsius */
#if !IS_USED(MODULE_MLX90393_INT) || DOXYGEN
uint8_t conversion_time; /**< Conversion time for single measurement mode */
#endif
} mlx90393_t;

/**
Expand All @@ -317,9 +355,9 @@ typedef struct {
* If wake-up on change mode is used, configuring a valid interrupt pin is mandatory.
*
* @note Some configurations of oversampling and digital filter are not permitted:
* - OSR_0 and DIG_FILT_0
* - OSR_0 and DIG_FILT_1
* - OSR_1 and DIG_FILT_0
* - #MLX90393_OSR_0 and #MLX90393_DIG_FILT_0
* - #MLX90393_OSR_0 and #MLX90393_DIG_FILT_1
* - #MLX90393_OSR_1 and #MLX90393_DIG_FILT_0
* In such cases, the function will return with -EINVAL.
*
* @note The conversion time increases with higher oversampling rates and digital filters.
Expand Down Expand Up @@ -370,7 +408,7 @@ int mlx90393_read(mlx90393_t *dev, mlx90393_data_t *data);
* Burst and Wake-up on change measurement modes are stopped and the device
* is forced into idle mode. Once stopped, the modes can be restarted with mlx90393_start_cont.
*
* @param[in] dev Device descriptor of MLX90393 device to read from
* @param[in] dev Device descriptor of MLX90393 device
*
* @retval 0 on success
* @retval -EIO SPI or I2C communication error
Expand All @@ -389,14 +427,34 @@ int mlx90393_stop_cont(mlx90393_t *dev);
* - Device must be initialized with mlx90393_init
* - Continuous measurement was stopped with mlx90393_stop_cont
*
* @param[in] dev Device descriptor of MLX90393 device to read from
* @param[in] dev Device descriptor of MLX90393 device
*
* @retval 0 on success
* @retval -EIO SPI or I2C communication error
* @retval -EFAULT device error
*/
int mlx90393_start_cont(mlx90393_t *dev);

#if IS_USED(MODULE_MLX90393_WOC) || DOXYGEN
/**
* @brief Activate wake-up on change interrupt
*
* Activates the interrupt which is triggered if the user defined woc threshold is crossed.
* The passed callback function is called when the interrupt occurs. After the interrupt
* the measurement data can be read with mlx90393_read.
*
* @warning
* The passed callback function is called in interrupt context and should not be used to access
* the sensor or execute time-consuming code.
*
* @param[in] dev Device descriptor of MLX90393 device
* @param cb Callback to be executed when interrupt occurs
* @param arg Callback argument
*/
void mlx90393_enable_woc(mlx90393_t *dev, mlx90393_cb_t cb, void *arg);

#endif

#ifdef __cplusplus
}
#endif
Expand Down
11 changes: 9 additions & 2 deletions drivers/mlx90393/Makefile.dep
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
ifneq (,$(filter mlx90393,$(USEMODULE)))
FEATURES_REQUIRED += periph_gpio
FEATURES_REQUIRED += periph_gpio_irq
USEMODULE += ztimer
USEMODULE += ztimer_msec
endif
Expand All @@ -12,3 +10,12 @@ endif
ifneq (,$(filter mlx90393_spi,$(USEMODULE)))
FEATURES_REQUIRED += periph_spi
endif

ifneq (,$(filter mlx90393_woc,$(USEMODULE)))
USEMODULE += mlx90393_int
endif

ifneq (,$(filter mlx90393_int,$(USEMODULE)))
FEATURES_REQUIRED += periph_gpio
FEATURES_REQUIRED += periph_gpio_irq
endif
2 changes: 2 additions & 0 deletions drivers/mlx90393/Makefile.include
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# include variants of the MLX90393 drivers as pseudo modules
PSEUDOMODULES += mlx90393_i2c
PSEUDOMODULES += mlx90393_spi
PSEUDOMODULES += mlx90393_int
PSEUDOMODULES += mlx90393_woc

USEMODULE_INCLUDES_mlx90393 := $(LAST_MAKEFILEDIR)/include
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_mlx90393)
2 changes: 1 addition & 1 deletion drivers/mlx90393/include/mlx90393_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ extern "C" {
*/
#define MLX90393_TEMP_OFFSET 3500 /**< Temperature offset in centi celsius */
#define MLX90393_TEMP_RESOLUTION 452 /**< Temperature sensor resolution
* (45.2 * 10 for avoiding float values) */
(45.2 * 10 for avoiding float values) */

/**
* @brief Magnetic flux conversion constants
Expand Down
29 changes: 19 additions & 10 deletions drivers/mlx90393/include/mlx90393_params.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,15 @@ extern "C" {
#define MLX90393_PARAM_MODE (MLX90393_MODE_BURST)
#endif

#if IS_USED(MODULE_MLX90393_INT) || DOXYGEN
#ifndef MLX90393_PARAM_INT_PIN
/**
* @brief Default interrupt pin
*/
#define MLX90393_PARAM_INT_PIN (GPIO_PIN(PORT_C, 8))
#define MLX90393_PARAM_INT_PIN .int_pin = (GPIO_PIN(PORT_C, 8)),
#endif
#else
#define MLX90393_PARAM_INT_PIN
#endif

#ifndef MLX90393_PARAM_GAIN
Expand Down Expand Up @@ -84,20 +88,25 @@ extern "C" {
#define MLX90393_PARAM_DIG_FILT (MLX90393_DIG_FILT_1)
#endif

#if IS_USED(MODULE_MLX90393_WOC) || DOXYGEN
#ifndef MLX90393_PARAM_THRESHOLD
/**
* @brief Default thresholds for Wake-up On Change mode
*/
#define MLX90393_PARAM_THRESHOLD \
.threshold = \
{ \
.xy = 0xFFFF, \
.z = 1000, \
.temp = 0xFFFF \
}
},
#endif
#else
#define MLX90393_PARAM_THRESHOLD
#endif

/* Default configuration for SPI mode */
#if MODULE_MLX90393_SPI
#if IS_USED(MODULE_MLX90393_SPI) || DOXYGEN

#ifndef MLX90393_PARAM_SPI
/**
Expand Down Expand Up @@ -129,18 +138,18 @@ extern "C" {
.cs_pin = MLX90393_PARAM_SPI_CS_PIN, \
.clk = MLX90393_PARAM_SPI_CLK, \
.mode = MLX90393_PARAM_MODE, \
.int_pin = MLX90393_PARAM_INT_PIN, \
.gain = MLX90393_PARAM_GAIN, \
.resolution = MLX90393_PARAM_RES, \
.odr = MLX90393_PARAM_ODR, \
.oversampling = MLX90393_PARAM_OSR, \
.dig_filt = MLX90393_PARAM_DIG_FILT, \
.threshold = MLX90393_PARAM_THRESHOLD \
MLX90393_PARAM_INT_PIN \
MLX90393_PARAM_THRESHOLD \
}
#endif

/* Default configuration for I2C mode */
#elif MODULE_MLX90393_I2C
#elif IS_USED(MODULE_MLX90393_I2C) || DOXYGEN

#ifndef MLX90393_PARAM_I2C
/**
Expand All @@ -164,13 +173,13 @@ extern "C" {
.i2c = MLX90393_PARAM_I2C, \
.addr = MLX90393_PARAM_I2C_ADDR, \
.mode = MLX90393_PARAM_MODE, \
.int_pin = MLX90393_PARAM_INT_PIN, \
.gain = MLX90393_PARAM_GAIN, \
.resolution = MLX90393_PARAM_RES, \
.odr = MLX90393_PARAM_ODR, \
.oversampling = MLX90393_PARAM_OSR, \
.dig_filt = MLX90393_PARAM_DIG_FILT, \
.threshold = MLX90393_PARAM_THRESHOLD \
MLX90393_PARAM_INT_PIN \
MLX90393_PARAM_THRESHOLD \
}
#endif
#endif
Expand All @@ -181,9 +190,9 @@ extern "C" {
*/
static const mlx90393_params_t mlx90393_params[] =
{
#if MODULE_MLX90393_SPI
#if IS_USED(MODULE_MLX90393_SPI)
MLX90393_PARAMS_SPI
#elif MODULE_MLX90393_I2C
#elif IS_USED(MODULE_MLX90393_I2C)
MLX90393_PARAMS_I2C
#endif
};
Expand Down
Loading

0 comments on commit 4844ad3

Please sign in to comment.