From 644dbb12243b6d1a078526ca4b92f92cfa324007 Mon Sep 17 00:00:00 2001 From: smlng <s@mlng.net> Date: Mon, 10 Apr 2017 22:16:45 +0200 Subject: [PATCH] driver, mag3110: rework --- boards/pba-d-01-kw2x/include/mag3110_params.h | 50 ++++ drivers/include/mag3110.h | 63 +++-- drivers/mag3110/include/mag3110_params.h | 66 +++++ drivers/mag3110/mag3110.c | 227 +++++++++--------- tests/driver_mag3110/Makefile | 14 -- tests/driver_mag3110/main.c | 47 ++-- 6 files changed, 283 insertions(+), 184 deletions(-) create mode 100644 boards/pba-d-01-kw2x/include/mag3110_params.h create mode 100644 drivers/mag3110/include/mag3110_params.h diff --git a/boards/pba-d-01-kw2x/include/mag3110_params.h b/boards/pba-d-01-kw2x/include/mag3110_params.h new file mode 100644 index 0000000000..bfa29c13d6 --- /dev/null +++ b/boards/pba-d-01-kw2x/include/mag3110_params.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2017 HAW Hamburg + * + * 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. + */ + +/** + * @ingroup boards_pba-d-01-kw2x + * @{ + * + * @file + * @brief MAG3110 board specific configuration + * + * @author Sebastian Meiling <s@mlng.net> + */ + +#ifndef MAG3110_PARAMS_H +#define MAG3110_PARAMS_H + +#include "board.h" +#include "saul_reg.h" +#include "mag3110.h" +#include "mag3110_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief MAG3310 configuration + */ +static const mag3110_params_t mag3110_params[] = +{ + { + .i2c = MAG3110_I2C, + .addr = MAG3110_ADDR, + .type = MAG3110_ID, + .dros = MAG3110_DROS_DEFAULT, + .offset = { 0, 0, 0 } + } +}; + +#ifdef __cplusplus +} +#endif + +#endif /* MAG3110_PARAMS_H */ +/** @} */ diff --git a/drivers/include/mag3110.h b/drivers/include/mag3110.h index 0c924fd357..5669e0a3c7 100644 --- a/drivers/include/mag3110.h +++ b/drivers/include/mag3110.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 PHYTEC Messtechnik GmbH + * 2017 HAW Hamburg * * 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 @@ -25,6 +26,7 @@ * @brief Interface definition for the MAG3110 magnetometer driver. * * @author Johann Fischer <j.fischer@phytec.de> + * @author Sebastian Meiling <s@mlng.net> */ #ifndef MAG3110_H @@ -39,6 +41,16 @@ extern "C" { #endif +/** + * @brief Named return values + */ +enum { + MAG3110_OK, /**< all good */ + MAG3110_ERROR_I2C, /**< I2C communication failed */ + MAG3110_ERROR_DEV, /**< Device MAG3110 not found */ + MAG3110_ERROR_CNF, /**< Device configuration failed */ +}; + #ifndef MAG3110_I2C_ADDRESS #define MAG3110_I2C_ADDRESS 0x0E /**< Magnetometer Default Address */ #endif @@ -77,41 +89,45 @@ extern "C" #define MAG3110_DROS_0008_128 31 /**< Output Rate 0.08 Hz, Over Sample Ratio 128 */ #define MAG3110_DROS_DEFAULT MAG3110_DROS_0125_128 /**< Default Setting for testing */ +/** + * @brief Configuration parameters + */ +typedef struct { + i2c_t i2c; /**< I2C bus the device is connected to */ + uint8_t addr; /**< I2C bus address of the device */ + uint8_t type; /**< device type */ + uint8_t dros; /**< sampling rate to use */ + int16_t offset[3]; /**< data offset in X, Y, and Z direction */ +} mag3110_params_t; + /** * @brief Device descriptor for MAG3110 magnetometer. */ typedef struct { - i2c_t i2c; /**< I2C device, the magnetometer is connected to */ - uint8_t addr; /**< the magnetometer's slave address on the I2C bus */ - bool initialized; /**< magnetometer status, true if magnetometer is initialized */ + mag3110_params_t params; /**< device configuration parameters */ } mag3110_t; /** - * @brief MAG3110 magnetometer test. - * This function looks for Device ID of the MAG3110 magnetometer. - * - * @param[in] dev device descriptor of magnetometer - * - * @return 0 on success - * @return -1 on error + * @brief Data type for the result data */ -int mag3110_test(mag3110_t *dev); +typedef struct { + int16_t x; /**< acceleration in X direction */ + int16_t y; /**< acceleration in Y direction */ + int16_t z; /**< acceleration in Z direction */ +} mag3110_data_t; /** * @brief Initialise the MAG3110 magnetometer driver. * * @param[out] dev device descriptor of magnetometer to initialize - * @param[in] i2c I2C bus the magnetometer is connected to - * @param[in] address magnetometer's I2C slave address - * @param[in] dros data rate and over sampling selection + * @param[in] params configuration parameters * * @return 0 on success - * @return -1 if dros parameter is wrong - * @return -2 if initialization of I2C bus failed - * @return -3 if magnetometer test failed - * @return -4 if magnetometer configuration failed + * @return -1 if I2C communication failed + * @return -2 if magnetometer test failed + * @return -3 if magnetometer configuration failed */ -int mag3110_init(mag3110_t *dev, i2c_t i2c, uint8_t address, uint8_t dros); +int mag3110_init(mag3110_t *dev, const mag3110_params_t *params); /** * @brief Set user offset correction. @@ -163,16 +179,13 @@ int mag3110_is_ready(mag3110_t *dev); * To get the actual values for the magnetic field in \f$\mu T\f$, * one have to divide the returned values from the magnetometer by 10. * - * @param[in] dev device descriptor of magnetometer - * @param[out] x x-axis magnetic field strength - * @param[out] y y-axis magnetic field strength - * @param[out] z z-axis magnetic field strength - * @param[out] status magnetometer status register + * @param[in] dev device descriptor of accelerometer + * @param[out] data the current magnetic field strength * * @return 0 on success * @return -1 on error */ -int mag3110_read(mag3110_t *dev, int16_t *x, int16_t *y, int16_t *z, uint8_t *status); +int mag3110_read(mag3110_t *dev, mag3110_data_t *data); /** * @brief Read die temperature. diff --git a/drivers/mag3110/include/mag3110_params.h b/drivers/mag3110/include/mag3110_params.h new file mode 100644 index 0000000000..9ec57f8151 --- /dev/null +++ b/drivers/mag3110/include/mag3110_params.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2017 HAW Hamburg + * + * 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. + */ + +/** + * @ingroup drivers_mag3110 + * @{ + * + * @file + * @brief Default configuration for MAG3110 devices + * + * @author Sebastian Meiling <s@mlng.net> + */ + +#ifndef MAG3110_PARAMS_H +#define MAG3110_PARAMS_H + +#include "board.h" +#include "saul_reg.h" +#include "mag3110.h" +#include "mag3110_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Default configuration parameters for the MAG3110 driver + * @{ + */ +#ifndef MAG3110_PARAM_I2C +#define MAG3110_PARAM_I2C (I2C_DEV(0)) +#endif +#ifndef MAG3110_PARAM_ADDR +#define MAG3110_PARAM_ADDR (MAG3110_I2C_ADDRESS) +#endif +#ifndef MAG3110_PARAM_OFFSET +#define MAG3110_PARAM_OFFSET { 0, 0, 0 } +#endif +#ifndef MAG3110_PARAMS +#define MAG3110_PARAMS { .i2c = MAG3110_PARAM_I2C, \ + .addr = MAG3110_PARAM_ADDR, \ + .type = MAG3110_ID, \ + .dros = MAG3110_DROS_DEFAULT, \ + .offset = MAG3110_PARAM_OFFSET } +#endif +/**@}*/ + +/** + * @brief MAG3110 configuration + */ +static const mag3110_params_t mag3110_params[] = +{ + MAG3110_PARAMS +}; + +#ifdef __cplusplus +} +#endif + +#endif /* MAG3110_PARAMS_H */ +/** @} */ diff --git a/drivers/mag3110/mag3110.c b/drivers/mag3110/mag3110.c index c135c4ba5e..752f56d769 100644 --- a/drivers/mag3110/mag3110.c +++ b/drivers/mag3110/mag3110.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 PHYTEC Messtechnik GmbH + * 2017 HAW Hamburg * * 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 @@ -16,92 +17,91 @@ * * @author Johann Fischer <j.fischer@phytec.de> * @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de> + * @author Sebastian Meiling <s@mlng.net> * * @} */ #include <stdint.h> #include <stdbool.h> +#include <string.h> + +#include "log.h" #include "periph/i2c.h" + #include "mag3110.h" #include "mag3110_reg.h" #define ENABLE_DEBUG (0) #include "debug.h" -#define I2C_SPEED I2C_SPEED_FAST - -int mag3110_test(mag3110_t *dev) -{ - uint8_t reg; - - /* Acquire exclusive access to the bus. */ - i2c_acquire(dev->i2c); - if (i2c_read_regs(dev->i2c, dev->addr, MAG3110_WHO_AM_I, ®, 1) != 1) { - /* Release the bus for other threads. */ - i2c_release(dev->i2c); - return -1; - } - i2c_release(dev->i2c); - - if (reg != MAG3110_ID) { - return -1; - } +#define I2C_SPEED I2C_SPEED_FAST - return 0; -} +#define BUS (dev->params.i2c) +#define ADDR (dev->params.addr) -int mag3110_init(mag3110_t *dev, i2c_t i2c, uint8_t address, uint8_t dros) +int mag3110_init(mag3110_t *dev, const mag3110_params_t *params) { uint8_t reg; - /* write device descriptor */ - dev->i2c = i2c; - dev->addr = address; - dev->initialized = false; + assert(dev); + assert(params); - if (dros > MAG3110_DROS_0008_128) { - return -1; - } + /* write device descriptor */ + memcpy(dev, params, sizeof(mag3110_params_t)); - i2c_acquire(dev->i2c); + i2c_acquire(BUS); /* initialize the I2C bus */ - if (i2c_init_master(i2c, I2C_SPEED) < 0) { - i2c_release(dev->i2c); - return -2; - } - i2c_release(dev->i2c); - - if (mag3110_test(dev)) { - return -3; + if (i2c_init_master(BUS, I2C_SPEED) < 0) { + i2c_release(BUS); + LOG_ERROR("mag3110_init: failed!\n"); + return -MAG3110_ERROR_I2C; + } + /* test device */ + i2c_read_regs(BUS, ADDR, MAG3110_WHO_AM_I, ®, 1); + if (reg != dev->params.type) { + i2c_release(BUS); + LOG_ERROR("mag3110_init: invalid WHO_AM_I value (0x%02x)!\n", (int)reg); + return -MAG3110_ERROR_DEV; } - /* enable automatic magnetic sensor reset */ reg = MAG3110_CTRL_REG2_AUTO_MRST_EN; - - i2c_acquire(dev->i2c); - if (i2c_write_regs(dev->i2c, dev->addr, MAG3110_CTRL_REG2, ®, 1) != 1) { - i2c_release(dev->i2c); - return -4; - } - - reg = MAG3110_CTRL_REG1_DROS(dros); - - if (i2c_write_regs(dev->i2c, dev->addr, MAG3110_CTRL_REG1, ®, 1) != 1) { - i2c_release(dev->i2c); - return -4; + if (i2c_write_regs(BUS, ADDR, MAG3110_CTRL_REG2, ®, 1) != 1) { + i2c_release(BUS); + LOG_ERROR("mag3110_init: failed to enable auto reset!\n"); + return -MAG3110_ERROR_CNF; + } + /* set sample rate */ + reg = MAG3110_CTRL_REG1_DROS(dev->params.dros); + if (i2c_write_regs(BUS, ADDR, MAG3110_CTRL_REG1, ®, 1) != 1) { + i2c_release(BUS); + LOG_ERROR("mag3110_init: failed to set sample rate!\n"); + return -MAG3110_ERROR_CNF; + } + /* set device active */ + if (i2c_read_regs(BUS, ADDR, MAG3110_CTRL_REG1, ®, 1) != 1) { + i2c_release(BUS); + LOG_ERROR("mag3110_init: failed to read device state!\n"); + return -MAG3110_ERROR_I2C; } - i2c_release(dev->i2c); - - dev->initialized = true; - - return 0; + reg |= MAG3110_CTRL_REG1_AC; + if (i2c_write_regs(BUS, ADDR, MAG3110_CTRL_REG1, ®, 1) != 1) { + i2c_release(BUS); + LOG_ERROR("mag3110_init: failed to set device active!\n"); + return -MAG3110_ERROR_CNF; + } + i2c_release(BUS); + /* write user offsets */ + return mag3110_set_user_offset(dev, dev->params.offset[0], + dev->params.offset[1], dev->params.offset[2]); } int mag3110_set_user_offset(mag3110_t *dev, int16_t x, int16_t y, int16_t z) { uint8_t buf[6]; + assert(dev); + buf[0] = (x >> 8); buf[1] = x; buf[2] = (y >> 8); @@ -109,115 +109,114 @@ int mag3110_set_user_offset(mag3110_t *dev, int16_t x, int16_t y, int16_t z) buf[4] = (z >> 8); buf[5] = z; - i2c_acquire(dev->i2c); - if (i2c_write_regs(dev->i2c, dev->addr, MAG3110_OFF_X_MSB, buf, 6) != 6) { - i2c_release(dev->i2c); - return -1; + DEBUG("[mag3110] setting user offset to X: %3i, Y: %3i, Z: %3i\n", + (int)x, (int)y, (int)z); + + i2c_acquire(BUS); + if (i2c_write_regs(BUS, ADDR, MAG3110_OFF_X_MSB, buf, 6) != 6) { + i2c_release(BUS); + LOG_ERROR("mag3110_set_user_offset: failed to set offsets!\n"); + return -MAG3110_ERROR_I2C; } - i2c_release(dev->i2c); + i2c_release(BUS); - return 0; + return MAG3110_OK; } int mag3110_set_active(mag3110_t *dev) { uint8_t reg; - if (dev->initialized == false) { - return -1; - } + assert(dev); - i2c_acquire(dev->i2c); - if (i2c_read_regs(dev->i2c, dev->addr, MAG3110_CTRL_REG1, ®, 1) != 1) { - i2c_release(dev->i2c); - return -1; + i2c_acquire(BUS); + if (i2c_read_regs(BUS, ADDR, MAG3110_CTRL_REG1, ®, 1) != 1) { + i2c_release(BUS); + return -MAG3110_ERROR_I2C; } reg |= MAG3110_CTRL_REG1_AC; - if (i2c_write_regs(dev->i2c, dev->addr, MAG3110_CTRL_REG1, ®, 1) != 1) { - i2c_release(dev->i2c); - return -1; + if (i2c_write_regs(BUS, ADDR, MAG3110_CTRL_REG1, ®, 1) != 1) { + i2c_release(BUS); + return -MAG3110_ERROR_I2C; } - i2c_release(dev->i2c); + i2c_release(BUS); - return 0; + return MAG3110_OK; } int mag3110_set_standby(mag3110_t *dev) { uint8_t reg; - i2c_acquire(dev->i2c); - if (i2c_read_regs(dev->i2c, dev->addr, MAG3110_CTRL_REG1, ®, 1) != 1) { - i2c_release(dev->i2c); - return -1; + assert(dev); + + i2c_acquire(BUS); + if (i2c_read_regs(BUS, ADDR, MAG3110_CTRL_REG1, ®, 1) != 1) { + i2c_release(BUS); + return -MAG3110_ERROR_I2C; } reg &= ~MAG3110_CTRL_REG1_AC; - if (i2c_write_regs(dev->i2c, dev->addr, MAG3110_CTRL_REG1, ®, 1) != 1) { - i2c_release(dev->i2c); - return -1; + if (i2c_write_regs(BUS, ADDR, MAG3110_CTRL_REG1, ®, 1) != 1) { + i2c_release(BUS); + return -MAG3110_ERROR_I2C; } - i2c_release(dev->i2c); + i2c_release(BUS); - return 0; + return MAG3110_OK; } int mag3110_is_ready(mag3110_t *dev) { uint8_t reg; - if (dev->initialized == false) { - return -1; - } + assert(dev); - i2c_acquire(dev->i2c); - if (i2c_read_regs(dev->i2c, dev->addr, MAG3110_DR_STATUS, ®, 1) != 1) { - i2c_release(dev->i2c); - return -1; + i2c_acquire(BUS); + if (i2c_read_regs(BUS, ADDR, MAG3110_DR_STATUS, ®, 1) != 1) { + i2c_release(BUS); + return -MAG3110_ERROR_I2C; } - i2c_release(dev->i2c); + i2c_release(BUS); return (int)(reg & MAG3110_DR_STATUS_ZYXDR); } -int mag3110_read(mag3110_t *dev, int16_t *x, int16_t *y, int16_t *z, uint8_t *status) +int mag3110_read(mag3110_t *dev, mag3110_data_t *data) { uint8_t buf[7]; - if (dev->initialized == false) { - return -1; - } + assert(dev); - i2c_acquire(dev->i2c); - if (i2c_read_regs(dev->i2c, dev->addr, MAG3110_DR_STATUS, buf, 7) != 7) { - i2c_release(dev->i2c); - return -1; + i2c_acquire(BUS); + if (i2c_read_regs(BUS, ADDR, MAG3110_DR_STATUS, buf, 7) != 7) { + i2c_release(BUS); + return -MAG3110_ERROR_I2C; } - i2c_release(dev->i2c); - - *status = buf[0]; - *x = ((int16_t)buf[1] << 8) | buf[2]; - *y = ((int16_t)buf[3] << 8) | buf[4]; - *z = ((int16_t)buf[5] << 8) | buf[6]; + i2c_release(BUS); + /* TODO: implement state handling, if needed? + uint8_t status = buf[0]; + */ + data->x = ((int16_t)buf[1] << 8) | buf[2]; + data->y = ((int16_t)buf[3] << 8) | buf[4]; + data->z = ((int16_t)buf[5] << 8) | buf[6]; - return 0; + return MAG3110_OK; } int mag3110_read_dtemp(mag3110_t *dev, int8_t *dtemp) { - if (dev->initialized == false) { - return -1; - } + assert(dev); - i2c_acquire(dev->i2c); - if (i2c_read_regs(dev->i2c, dev->addr, MAG3110_DIE_TEMP, dtemp, 1) != 1) { - i2c_release(dev->i2c); - return -1; + i2c_acquire(BUS); + if (i2c_read_regs(BUS, ADDR, MAG3110_DIE_TEMP, dtemp, 1) != 1) { + i2c_release(BUS); + return -MAG3110_ERROR_I2C; } - i2c_release(dev->i2c); + i2c_release(BUS); - return 0; + return MAG3110_OK; } diff --git a/tests/driver_mag3110/Makefile b/tests/driver_mag3110/Makefile index 8c1fe5502d..9462018592 100644 --- a/tests/driver_mag3110/Makefile +++ b/tests/driver_mag3110/Makefile @@ -6,18 +6,4 @@ FEATURES_REQUIRED = periph_i2c USEMODULE += mag3110 USEMODULE += xtimer -# set default device parameters in case they are undefined -TEST_MAG3110_I2C ?= I2C_DEV\(0\) -TEST_MAG3110_ADDR ?= 0x0E -TEST_MAG3110_USER_OFFSET_X ?= -2000 -TEST_MAG3110_USER_OFFSET_Y ?= 180 -TEST_MAG3110_USER_OFFSET_Z ?= 210 - -# export parameters -CFLAGS += -DTEST_MAG3110_I2C=$(TEST_MAG3110_I2C) -CFLAGS += -DTEST_MAG3110_ADDR=$(TEST_MAG3110_ADDR) -CFLAGS += -DTEST_MAG3110_USER_OFFSET_X=$(TEST_MAG3110_USER_OFFSET_X) -CFLAGS += -DTEST_MAG3110_USER_OFFSET_Y=$(TEST_MAG3110_USER_OFFSET_Y) -CFLAGS += -DTEST_MAG3110_USER_OFFSET_Z=$(TEST_MAG3110_USER_OFFSET_Z) - include $(RIOTBASE)/Makefile.include diff --git a/tests/driver_mag3110/main.c b/tests/driver_mag3110/main.c index 603d12bc2a..003872d838 100644 --- a/tests/driver_mag3110/main.c +++ b/tests/driver_mag3110/main.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2014 Freie Universität Berlin * Copyright (C) 2014 PHYTEC Messtechnik GmbH + * 2017 HAW Hamburg * * 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 @@ -16,57 +17,41 @@ * * @author Hauke Petersen <hauke.petersen@fu-berlin.de> * @author Johann Fischer <j.fischer@phytec.de> + * @author Sebastian Meiling <s@mlng.net> * * @} */ -#ifndef TEST_MAG3110_I2C -#error "TEST_MAG3110_I2C not defined" -#endif -#ifndef TEST_MAG3110_ADDR -#error "TEST_MAG3110_ADDR not defined" -#endif - #include <stdio.h> +#include "timex.h" #include "xtimer.h" + #include "mag3110.h" +#include "mag3110_params.h" + +#define SLEEP (1U * US_PER_SEC) -#define SLEEP (1000 * 1000U) +static mag3110_t dev; int main(void) { - mag3110_t dev; + mag3110_data_t data; int8_t temp; - int16_t x, y, z; - uint8_t status; puts("MAG3110 magnetometer driver test application\n"); - printf("Initializing MAG3110 magnetometer at I2C_%i... ", TEST_MAG3110_I2C); - if (mag3110_init(&dev, TEST_MAG3110_I2C, TEST_MAG3110_ADDR, MAG3110_DROS_DEFAULT) == 0) { - puts("[OK]\n"); - } - else { - puts("[Failed]"); - return -1; - } - - if (mag3110_set_user_offset(&dev, TEST_MAG3110_USER_OFFSET_X, - TEST_MAG3110_USER_OFFSET_Y, - TEST_MAG3110_USER_OFFSET_Z )) { - puts("Set user offset correction failed."); - return -1; - } - - if (mag3110_set_active(&dev)) { - puts("Measurement start failed."); + printf("Initializing MAG3110 magnetometer at I2C_%i... ", + mag3110_params[0].i2c); + if (mag3110_init(&dev, &mag3110_params[0]) != MAG3110_OK) { + puts("[FAILED]"); return -1; } + puts("[SUCCESS]"); while (1) { xtimer_usleep(SLEEP); - mag3110_read(&dev, &x, &y, &z, &status); - printf("Field strength: X: %d Y: %d Z: %d S: %2x\n", x, y, z, status); + mag3110_read(&dev, &data); + printf("Field strength: X: %d Y: %d Z: %d\n", data.x, data.y, data.z); mag3110_read_dtemp(&dev, &temp); printf("Die Temperature T: %d\n", temp); } -- GitLab