From 396b76c03959c5449e5b90b695df96b729f86c86 Mon Sep 17 00:00:00 2001 From: daniel-k <github@daniel-krebs.net> Date: Tue, 1 Sep 2015 17:05:23 +0200 Subject: [PATCH] drivers/at30tse75x: add device driver for AT30TSE75x temperature sensor --- Makefile.dep | 4 + drivers/at30tse75x/Makefile | 1 + drivers/at30tse75x/at30tse75x.c | 317 ++++++++++++++++++++++++++++ drivers/include/at30tse75x.h | 312 +++++++++++++++++++++++++++ sys/shell/commands/Makefile | 3 + sys/shell/commands/sc_at30tse75x.c | 160 ++++++++++++++ sys/shell/commands/shell_commands.c | 7 + tests/driver_at30tse75x/Makefile | 12 ++ tests/driver_at30tse75x/main.c | 35 +++ 9 files changed, 851 insertions(+) create mode 100644 drivers/at30tse75x/Makefile create mode 100644 drivers/at30tse75x/at30tse75x.c create mode 100644 drivers/include/at30tse75x.h create mode 100644 sys/shell/commands/sc_at30tse75x.c create mode 100644 tests/driver_at30tse75x/Makefile create mode 100644 tests/driver_at30tse75x/main.c diff --git a/Makefile.dep b/Makefile.dep index 0c29e594ef..d2eb6eb02a 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -425,6 +425,10 @@ ifneq (,$(filter ltc4150,$(USEMODULE))) USEMODULE += xtimer endif +ifneq (,$(filter at30tse75x,$(USEMODULE))) + USEMODULE += xtimer +endif + ifneq (,$(filter pthread,$(USEMODULE))) USEMODULE += xtimer USEMODULE += vtimer diff --git a/drivers/at30tse75x/Makefile b/drivers/at30tse75x/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/drivers/at30tse75x/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/drivers/at30tse75x/at30tse75x.c b/drivers/at30tse75x/at30tse75x.c new file mode 100644 index 0000000000..1ae6065c98 --- /dev/null +++ b/drivers/at30tse75x/at30tse75x.c @@ -0,0 +1,317 @@ +/* + * Copyright (C) Daniel Krebs + * + * 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. + */ + +/** + * @file + * @brief Driver for the AT30TSE75x temperature sensor with serial EEPROM + * + * @author Daniel Krebs <github@daniel-krebs.net> + */ + + +#include "periph/i2c.h" +#include "xtimer.h" + +#include "at30tse75x.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +static inline float temperature_to_float(uint16_t temp) +{ + /* Integer part is 8-bit signed */ + int8_t temp_int = (temp & AT30TSE75X_INTEGER_MASK) >> + AT30TSE75X_INTEGER_SHIFT; + /* Fractional part is multiple of 0.0625 */ + uint8_t frac_multiplier = (temp & AT30TSE75X_FRACTIONAL_MASK) >> + AT30TSE75X_FRACTIONAL_SHIFT; + + return temp_int + (frac_multiplier * AT30TSE75X_FRACTIONAL_BASE); +} + +static int at30tse75x_get_register(at30tse75x_t* dev, uint8_t reg, uint16_t* data) +{ + i2c_acquire(dev->i2c); + xtimer_spin(AT30TSE75X_BUS_FREE_TIME_US); + if(i2c_read_regs(dev->i2c, dev->addr, reg, (char*) data, 2) <= 0) { + DEBUG("[at30tse75x] Can't read register 0x%x\n", reg); + i2c_release(dev->i2c); + return -1; + } + i2c_release(dev->i2c); + + return 0; +} + +static int at30tse75x_set_register(at30tse75x_t* dev, uint8_t reg, uint16_t* data) +{ + i2c_acquire(dev->i2c); + xtimer_spin(AT30TSE75X_BUS_FREE_TIME_US); + if(i2c_write_regs(dev->i2c, dev->addr, reg, (char*) data, 2) <= 0) { + DEBUG("[at30tse75x] Can't write to register 0x%x\n", reg); + i2c_release(dev->i2c); + return -1; + } + i2c_release(dev->i2c); + + return 0; +} + +static int at30tse75x_reset(at30tse75x_t* dev) +{ + i2c_acquire(dev->i2c); + xtimer_spin(AT30TSE75X_BUS_FREE_TIME_US); + if(i2c_write_byte(dev->i2c, 0x00, AT30TSE75X_CMD__GENERAL_CALL_RESET) != 1) { + i2c_release(dev->i2c); + return -1; + } + i2c_release(dev->i2c); + /* Wait for reset to complete */ + xtimer_usleep(500); + return 0; +} + +int at30tse75x_get_config(at30tse75x_t* dev, uint8_t* data) +{ + i2c_acquire(dev->i2c); + xtimer_spin(AT30TSE75X_BUS_FREE_TIME_US); + if(i2c_read_reg(dev->i2c, dev->addr, AT30TSE75X_REG__CONFIG, (char*) data) <= 0) { + DEBUG("[at30tse75x] Can't read CONFIG register\n"); + i2c_release(dev->i2c); + return -1; + } + i2c_release(dev->i2c); + + return 0; +} + +int at30tse75x_set_config(at30tse75x_t* dev, uint8_t data) +{ + i2c_acquire(dev->i2c); + xtimer_spin(AT30TSE75X_BUS_FREE_TIME_US); + if(i2c_write_reg(dev->i2c, dev->addr, AT30TSE75X_REG__CONFIG, (char) data) <= 0) { + DEBUG("[at30tse75x] Can't write to CONFIG register\n"); + i2c_release(dev->i2c); + return -1; + } + i2c_release(dev->i2c); + + return 0; +} + +int at30tse75x_set_resolution(at30tse75x_t* dev, at30tse75x_resolution_t resolution) +{ + uint8_t config; + + if(resolution < AT30TSE75X_RESOLUTION_9BIT || + resolution > AT30TSE75X_RESOLUTION_12BIT) { + return -2; + } + + if(at30tse75x_get_config(dev, &config) != 0) { + return -1; + } + + config &= ~(AT30TSE75X_CONFIG__RESOLUTION_MASK); + config |= resolution << AT30TSE75X_CONFIG__RESOLUTION_SHIFT; + + if(at30tse75x_set_config(dev, config) != 0) { + return -1; + } + + return 0; +} + +int at30tse75x_set_mode(at30tse75x_t* dev, at30tse75x_mode_t mode) +{ + uint8_t config; + if(at30tse75x_get_config(dev, &config) != 0) { + return -1; + } + + switch(mode) { + case AT30TSE75X_MODE_ONE_SHOT: + config |= AT30TSE75X_CONFIG__SHUTDOWN_BIT; + /* Don't touch alarm mode */ + break; + case AT30TSE75X_MODE_COMPARATOR: + config &= ~(AT30TSE75X_CONFIG__SHUTDOWN_BIT); + config &= ~(AT30TSE75X_CONFIG__ALARM_MODE_BIT); + break; + case AT30TSE75X_MODE_INTERRUPT: + config &= ~(AT30TSE75X_CONFIG__SHUTDOWN_BIT); + config |= AT30TSE75X_CONFIG__ALARM_MODE_BIT; + break; + default: + return -2; + } + + if(at30tse75x_set_config(dev, config) != 0) { + return -1; + } + + return 0; +} + +int at30tse75x_set_alarm_polarity(at30tse75x_t* dev, at30tse75x_alarm_polatity_t polarity) +{ + uint8_t config; + if(at30tse75x_get_config(dev, &config) != 0) { + return -1; + } + + switch(polarity) { + case AT30TSE75X_ALARM_ACTIVE_HIGH: + config |= AT30TSE75X_CONFIG__ALERT_POL_BIT; + break; + case AT30TSE75X_ALARM_ACTIVE_LOW: + config &= ~(AT30TSE75X_CONFIG__ALERT_POL_BIT); + break; + default: + return -2; + } + + if(at30tse75x_set_config(dev, config) != 0) { + return -1; + } + + return 0; +} + +int at30tse75x_set_fault_tolerance(at30tse75x_t* dev, at30tse75x_fault_tolerance_t tolerance) +{ + if(tolerance < AT30TSE75X_ALARM_AFTER_1 || + tolerance > AT30TSE75X_ALARM_AFTER_6) { + return -2; + } + + uint8_t config; + if(at30tse75x_get_config(dev, &config) != 0) { + return -1; + } + + config &= ~(AT30TSE75X_CONFIG__FTQ_MASK); + config |= tolerance << AT30TSE75X_CONFIG__FTQ_SHIFT; + + if(at30tse75x_set_config(dev, config) != 0) { + return -1; + } + + return 0; +} + +int at30tse75x_set_limit_low(at30tse75x_t* dev, int8_t t_low) +{ + uint16_t tmp = (t_low << 8) | (0x00); + return at30tse75x_set_register(dev, AT30TSE75X_REG__LIMIT_LOW, &tmp); +} + +int at30tse75x_set_limit_high(at30tse75x_t* dev, int8_t t_high) +{ + uint16_t tmp = (t_high << 8) | (0x00); + return at30tse75x_set_register(dev, AT30TSE75X_REG__LIMIT_HIGH, &tmp); +} + +int at30tse75x_save_config(at30tse75x_t* dev) +{ + i2c_acquire(dev->i2c); + xtimer_spin(AT30TSE75X_BUS_FREE_TIME_US); + if(i2c_write_byte(dev->i2c, dev->addr, AT30TSE75X_CMD__SAVE_TO_NVRAM) != 1) { + i2c_release(dev->i2c); + return -1; + } + i2c_release(dev->i2c); + /* Wait for copy to complete */ + xtimer_usleep(5000); + return 0; +} + +int at30tse75x_restore_config(at30tse75x_t* dev) +{ + i2c_acquire(dev->i2c); + xtimer_spin(AT30TSE75X_BUS_FREE_TIME_US); + if(i2c_write_byte(dev->i2c, dev->addr, AT30TSE75X_CMD__RESTORE_FROM_NVRAM) != 1) { + i2c_release(dev->i2c); + return -1; + } + i2c_release(dev->i2c); + /* Wait for copy to complete */ + xtimer_usleep(200); + return 0; +} + +int at30tse75x_get_temperature(at30tse75x_t* dev, float* temperature) +{ + uint16_t tmp; + uint8_t config; + + if(at30tse75x_get_config(dev, &config) != 0) { + return -1; + } + + /* If sensor is shutdown trigger One-Shot mode*/ + if(config & AT30TSE75X_CONFIG__SHUTDOWN_BIT) { + + config |= AT30TSE75X_CONFIG__OS_BIT; + if(at30tse75x_set_config(dev, config) != 0) { + return -1; + } + + /* Use resolution to calculate conversion time */ + uint8_t resolution = (config & AT30TSE75X_CONFIG__RESOLUTION_MASK) >> + AT30TSE75X_CONFIG__RESOLUTION_SHIFT; + + /* Wait until conversion is finished */ + xtimer_usleep((uint32_t)(25000 << resolution)); + } + + /* Read temperature */ + if(at30tse75x_get_register(dev, AT30TSE75X_REG__TEMPERATURE, &tmp) != 0) { + return -1; + } + + /* Convert fixed point to float */ + *temperature = temperature_to_float(tmp); + + return 0; +} + +int at30tse75x_init(at30tse75x_t* dev, i2c_t i2c, i2c_speed_t speed, uint8_t addr) +{ + uint8_t config; + + dev->i2c = i2c; + + if( (addr < 0x48) || (addr > 0x4f) ) { + DEBUG("[at30tse75x] Invalid address\n"); + return -2; + } + dev->addr = addr; + + i2c_acquire(dev->i2c); + if(i2c_init_master(dev->i2c, speed) != 0) { + DEBUG("[at30tse75x] Can't initialize I2C master\n"); + i2c_release(dev->i2c); + return -1; + } + i2c_release(dev->i2c); + + /* Reset the device */ + if(at30tse75x_reset(dev) != 0) { + return -1; + } + + /* Poll the device, fail if unavailable */ + if(at30tse75x_get_config(dev, &config) != 0) { + return -1; + } + + DEBUG("[at30tse75x] Config: 0x%x\n", config); + + return 0; +} diff --git a/drivers/include/at30tse75x.h b/drivers/include/at30tse75x.h new file mode 100644 index 0000000000..1c35d8ff53 --- /dev/null +++ b/drivers/include/at30tse75x.h @@ -0,0 +1,312 @@ +/* + * Copyright (C) Daniel Krebs + * + * 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 at30tse75x AT30TSE75x temperature sensor with EEPROM + * @ingroup drivers + * + * The connection between the MCU and the AT30TSE75x is based on the + * I2C-interface. There are 3 versions of this IC, with either 2/4/8 Kb of + * EEPROM. + * + * @{ + * + * @file + * @brief Driver for the AT30TSE75x temperature sensor with serial EEPROM + * + * @author Daniel Krebs <github@daniel-krebs.net> + */ + +#ifndef AT30TSE75X_H_ +#define AT30TSE75X_H_ + +#include <stdint.h> +#include "periph/i2c.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name AT30TSE75x I2C addresses + * @{ + */ +#define AT30TSE75X_TEMP_ADDR (0x48) +#define AT30TSE75X_EEPROM_ADDR (0x50) +/** @} */ + +/** + * @name AT30TSE75x register addresses + * @{ + */ +#define AT30TSE75X_REG__TEMPERATURE (0x00) +#define AT30TSE75X_REG__CONFIG (0x01) +#define AT30TSE75X_REG__LIMIT_LOW (0x02) +#define AT30TSE75X_REG__LIMIT_HIGH (0x03) +#define AT30TSE75X_REG__NV_CONFIG (0x11) +#define AT30TSE75X_REG__NV_LIMIT_LOW (0x12) +#define AT30TSE75X_REG__NV_LIMIR_HIGH (0x13) +/** @} */ + +/** + * @name AT30TSE75x number formatting + * @{ + */ +#define AT30TSE75X_INTEGER_MASK (0x00ff) +#define AT30TSE75X_INTEGER_SHIFT (0) +#define AT30TSE75X_FRACTIONAL_MASK (0xf000) +#define AT30TSE75X_FRACTIONAL_SHIFT (12) +#define AT30TSE75X_FRACTIONAL_BASE (0.0625f) +/** @} */ + + +/** + * @name AT30TSE75x configuration register + * + * Only upper byte can be read/written, so treat as 8-bit register. + * @{ + */ +#define AT30TSE75X_CONFIG__OS_BIT (1 << 7) +#define AT30TSE75X_CONFIG__RESOLUTION_MASK (0x60) +#define AT30TSE75X_CONFIG__RESOLUTION_SHIFT (5) +#define AT30TSE75X_CONFIG__FTQ_MASK (0x18) +#define AT30TSE75X_CONFIG__FTQ_SHIFT (3) +#define AT30TSE75X_CONFIG__ALERT_POL_BIT (1 << 2) +#define AT30TSE75X_CONFIG__ALARM_MODE_BIT (1 << 1) +#define AT30TSE75X_CONFIG__SHUTDOWN_BIT (1 << 0) +/** @} */ + +/** + * @name AT30TSE75x commands + * + * @{ + */ +#define AT30TSE75X_CMD__SAVE_TO_NVRAM (0x48) +#define AT30TSE75X_CMD__RESTORE_FROM_NVRAM (0xb8) +#define AT30TSE75X_CMD__GENERAL_CALL_RESET (0x06) +#define AT30TSE75X_CMD__GENERAL_CALL_RELATCH (0x04) +/** @} */ + +/** + * @name AT30TSE75x constants + * + * @{ + */ +#define AT30TSE75X_BUS_FREE_TIME_US (1U) +/** @} */ + +/** + * @name AT30TSE75x configuration types + * + * @brief Temperature resolution + * + * @{ + */ +typedef enum { + AT30TSE75X_RESOLUTION_9BIT = 0, + AT30TSE75X_RESOLUTION_10BIT = 1, + AT30TSE75X_RESOLUTION_11BIT = 2, + AT30TSE75X_RESOLUTION_12BIT = 3 +} at30tse75x_resolution_t; +/** @} */ + +/** + * @brief Operation mode + * + * The device can run in continous or one-shot mode. While in one-shot mode it + * is effectively shutdown and only wakes up to perform a single measurement. + * When in comparator or interrupt mode, the device samples contiously the + * temperature and sets the ALERT pin according to the chosen mode. + * @{ + */ +typedef enum { + AT30TSE75X_MODE_COMPARATOR, + AT30TSE75X_MODE_INTERRUPT, + AT30TSE75X_MODE_ONE_SHOT +} at30tse75x_mode_t; +/** @} */ + +/** + * @brief After how many limit exceeding measurements the ALERT pin is set + * @{ + */ +typedef enum { + AT30TSE75X_ALARM_AFTER_1 = 0, + AT30TSE75X_ALARM_AFTER_2 = 1, + AT30TSE75X_ALARM_AFTER_4 = 2, + AT30TSE75X_ALARM_AFTER_6 = 3 +} at30tse75x_fault_tolerance_t; +/** @} */ + +/** + * @brief Polarity of the ALERT pin + * @{ + */ +typedef enum { + AT30TSE75X_ALARM_ACTIVE_LOW, + AT30TSE75X_ALARM_ACTIVE_HIGH +} at30tse75x_alarm_polatity_t; +/** @} */ + +/** + * @brief Device descriptor for a AT30TSE75x device + * @{ + */ +typedef struct { + i2c_t i2c; /**< I2C device that sensor is connected to */ + uint8_t addr; /**< I2C address of this particular sensor */ +} at30tse75x_t; +/** @} */ + +/** + * @brief Initialize a AT30TSE75x device + * + * @param[out] dev device descriptor + * @param[in] i2c I2C bus the device is connected to + * @param[in] speed I2C speed to use + * @param[in] addr I2C address of the device + * + * The valid address range is 0x48 - 0x4f depending on the configuration of the + * address pins A0-A2. + * + * @return 0 on success + * @return -1 on error + * @return -2 on invalid address + */ +int at30tse75x_init(at30tse75x_t* dev, i2c_t i2c, i2c_speed_t speed, uint8_t addr); + +/** + * @brief Save configuration register to non-volatile backup register + * + * @param[in] dev device descriptor + * + * @return 0 on success + * @return -1 on error + */ +int at30tse75x_save_config(at30tse75x_t* dev); + +/** + * @brief Restore configuration register from non-volatile backup register + * + * @param[in] dev device descriptor + * + * @return 0 on success + * @return -1 on error + */ +int at30tse75x_restore_config(at30tse75x_t* dev); + +/** + * @brief Get content of configuration register + * + * @param[in] dev device descriptor + * @param[out] data buffer where config register will be written to + * + * @return 0 on success + * @return -1 on error + */ +int at30tse75x_get_config(at30tse75x_t* dev, uint8_t* data); + +/** + * @brief Set content of configuration register + * + * @param[in] dev device descriptor + * @param[in] data new value for configuration register + * + * @return 0 on success + * @return -1 on error + */ +int at30tse75x_set_config(at30tse75x_t* dev, uint8_t data); + +/** + * @brief Set temperature resolution + * + * @param[in] dev device descriptor + * @param[in] resolution temperature resolution + * + * @return 0 on success + * @return -1 on error + * @return -2 on bad user input + */ +int at30tse75x_set_resolution(at30tse75x_t* dev, at30tse75x_resolution_t resolution); + +/** + * @brief Set operation mode + * + * @param[in] dev device descriptor + * @param[in] mode operation mode + * + * @return 0 on success + * @return -1 on device error + * @return -2 on bad user input + */ +int at30tse75x_set_mode(at30tse75x_t* dev, at30tse75x_mode_t mode); + +/** + * @brief Set polarity of ALERT pin + * + * @param[in] dev device descriptor + * @param[in] polarity polarity of ALERT pin + * + * @return 0 on success + * @return -1 on device error + * @return -2 on bad user input + */ +int at30tse75x_set_alarm_polarity(at30tse75x_t* dev, at30tse75x_alarm_polatity_t polarity); + +/** + * @brief Set tolerance to outlying measurements + * + * @param[in] dev device descriptor + * @param[in] tolerance tolerance + * + * @return 0 on success + * @return -1 on device error + * @return -2 on bad user input + */ +int at30tse75x_set_fault_tolerance(at30tse75x_t* dev, at30tse75x_fault_tolerance_t tolerance); + +/** + * @brief Set T_Low limit + * + * @param[in] dev device descriptor + * @param[in] t_low lower temperature limit + * + * @return 0 on success + * @return -1 on device error + * @return -2 on bad user input + */ +int at30tse75x_set_limit_low(at30tse75x_t* dev, int8_t t_low); + +/** + * @brief Set T_High limit + * + * @param[in] dev device descriptor + * @param[in] t_high upper temperature limit + * + * @return 0 on success + * @return -1 on error + */ +int at30tse75x_set_limit_high(at30tse75x_t* dev, int8_t t_high); + +/** + * @brief Get measured temperature + * + * @param[in] dev device descriptor + * @param[out] temperature float buffer where temperature will be written to + * + * @return 0 on success + * @return -1 on error + */ +int at30tse75x_get_temperature(at30tse75x_t* dev, float* temperature); + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif /* AT30TSE75X_H_ */ diff --git a/sys/shell/commands/Makefile b/sys/shell/commands/Makefile index 4e6f14cc65..27ef3c0a16 100644 --- a/sys/shell/commands/Makefile +++ b/sys/shell/commands/Makefile @@ -38,6 +38,9 @@ endif ifneq (,$(filter lsm303dlhc,$(USEMODULE))) SRC += sc_lsm303dlhc.c endif +ifneq (,$(filter at30tse75x,$(USEMODULE))) + SRC += sc_at30tse75x.c +endif ifneq (,$(filter gnrc_netif,$(USEMODULE))) SRC += sc_netif.c endif diff --git a/sys/shell/commands/sc_at30tse75x.c b/sys/shell/commands/sc_at30tse75x.c new file mode 100644 index 0000000000..32304f43aa --- /dev/null +++ b/sys/shell/commands/sc_at30tse75x.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2015 Daniel Krebs + * + * 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 sys_shell_commands + * @{ + * + * @file + * @brief Provides shell commands to test AT30TSE75x temperature sensor + * + * @author Daniel Krebs <github@daniel-krebs.net> + * + * @} + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdbool.h> +#include "at30tse75x.h" + +#ifdef MODULE_AT30TSE75X + +static bool initialized = false; +static at30tse75x_t dev; + +int _at30tse75x_handler(int argc, char **argv) +{ + if(argc <= 1) { + printf("Usage: %s init|read|mode|resolution|save|restore|config\n", argv[0]); + return -1; + } + + if(strcmp(argv[1], "init") == 0) { + if(argc == 2) { + printf("Usage: %s init #I2C [addr]\n" + " e.g. %s init 0\n", argv[0], argv[0]); + return -1; + } + + int error; + unsigned addr = 0x48; /* default to A0-A2 connected to GND */ + + /* Try to parse i2c dev */ + i2c_t i2c_dev = (i2c_t) strtol(argv[2], &argv[1] + 1, 10); + + /* Address given */ + if(argc == 4) { + char* hex = strstr(argv[3], "0x"); + if(hex) { + addr = strtoul(hex+2, NULL, 16); + } + } + + error = at30tse75x_init(&dev, i2c_dev, I2C_SPEED_NORMAL, addr); + if (error) { + printf("Error initializing AT30TSE75x sensor on I2C #%u @ 0x%x\n", i2c_dev, addr); + initialized = false; + return 1; + } + else { + printf("Initialized AT30TSE75x sensor on I2C #%u @ 0x%x\n", i2c_dev, addr); + initialized = true; + } + } else { + if(!initialized) { + puts("Please initialize first"); + return -1; + } + if(strcmp(argv[1], "read") == 0) { + float temperature; + if(at30tse75x_get_temperature(&dev, &temperature) != 0) { + puts("Reading temperature failed"); + return -1; + } + printf("Temperature: %i.%03u °C\n", + (int)temperature, + (unsigned)((temperature - (int)temperature) * 1000)); + } else if(strcmp(argv[1], "mode") == 0) { + if(argc == 2) { + printf("Usage: %s mode one-shot|comparator|interrupt\n", argv[0]); + return -1; + } + at30tse75x_mode_t mode; + if(strcmp(argv[2], "one-shot") == 0) { + mode = AT30TSE75X_MODE_ONE_SHOT; + } else if(strcmp(argv[2], "comparator") == 0) { + mode = AT30TSE75X_MODE_COMPARATOR; + } else if(strcmp(argv[2], "interrupt") == 0) { + mode = AT30TSE75X_MODE_INTERRUPT; + } else { + puts("Invalid mode"); + return -1; + } + if(at30tse75x_set_mode(&dev, mode) != 0) { + return -1; + } + printf("Mode set to %s\n", argv[2]); + } else if(strcmp(argv[1], "resolution") == 0) { + if(argc == 2) { + printf("Usage: %s resolution 9|10|11|12\n", argv[0]); + return -1; + } + unsigned resolution = strtoul(argv[2], NULL, 10); + if(at30tse75x_set_resolution(&dev, resolution - 9) != 0) { + return -1; + } + printf("Resolution set to %u bits\n", resolution); + } else if(strcmp(argv[1], "save") == 0) { + uint8_t config; + if(at30tse75x_get_config(&dev, &config) != 0) { + return -1; + } + if(at30tse75x_save_config(&dev) != 0) { + return -1; + } + printf("Config (0x%x) saved\n", config); + } else if(strcmp(argv[1], "restore") == 0) { + uint8_t config; + if(at30tse75x_restore_config(&dev) != 0) { + return -1; + } + if(at30tse75x_get_config(&dev, &config) != 0) { + return -1; + } + printf("Config restored to 0x%x\n", config); + + } else if(strcmp(argv[1], "config") == 0) { + if(argc == 2) { + uint8_t config; + if(at30tse75x_get_config(&dev, &config) != 0) { + return -1; + } + printf("Config: 0x%x\n", config); + } else { + /* Try to parse config in hex format */ + uint8_t config; + char* hex = strstr(argv[2], "0x"); + if(!hex) { + printf("Usage: %s config 0x__" + " to set config\n", argv[0]); + return -1; + } + config = strtoul(hex+2, NULL, 16); + if(at30tse75x_set_config(&dev, config) != 0) { + return -1; + } + printf("Config set to: 0x%x\n", config); + } + } + } + return 0; +} + +#endif /* MODULE_AT30TSE75X */ diff --git a/sys/shell/commands/shell_commands.c b/sys/shell/commands/shell_commands.c index c5978a823f..c1b675ea10 100644 --- a/sys/shell/commands/shell_commands.c +++ b/sys/shell/commands/shell_commands.c @@ -69,6 +69,10 @@ extern int _get_current_handler(int argc, char **argv); extern int _reset_current_handler(int argc, char **argv); #endif +#ifdef MODULE_AT30TSE75X +extern int _at30tse75x_handler(int argc, char **argv); +#endif + #if FEATURE_PERIPH_RTC extern int _rtc_handler(int argc, char **argv); #endif @@ -167,6 +171,9 @@ const shell_command_t _shell_command_list[] = { {"cur", "Prints current and average power consumption.", _get_current_handler}, {"rstcur", "Resets coulomb counter.", _reset_current_handler}, #endif +#ifdef MODULE_AT30TSE75X + {"at30tse75x", "Test AT30TSE75X temperature sensor", _at30tse75x_handler}, +#endif #ifdef MODULE_MCI {DISK_READ_SECTOR_CMD, "Reads the specified sector of inserted memory card", _read_sector}, {DISK_READ_BYTES_CMD, "Reads the specified bytes from inserted memory card", _read_bytes}, diff --git a/tests/driver_at30tse75x/Makefile b/tests/driver_at30tse75x/Makefile new file mode 100644 index 0000000000..45917d2b2a --- /dev/null +++ b/tests/driver_at30tse75x/Makefile @@ -0,0 +1,12 @@ +APPLICATION = driver_at30tse75x +include ../Makefile.tests_common + +FEATURES_REQUIRED = periph_i2c + +USEMODULE += at30tse75x +USEMODULE += shell +USEMODULE += shell_commands + +CFLAGS += -DDEVELHELP + +include $(RIOTBASE)/Makefile.include diff --git a/tests/driver_at30tse75x/main.c b/tests/driver_at30tse75x/main.c new file mode 100644 index 0000000000..6a0f24bafa --- /dev/null +++ b/tests/driver_at30tse75x/main.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2015 Daniel Krebs + * + * 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 tests + * @{ + * + * @file + * @brief Test application for AT30TSE75x temperature sensor + * + * @author Daniel Krebs <github@daniel-krebs.net> + * + * @} + */ + +#include <stdio.h> + +#include "shell.h" +#include "shell_commands.h" + +int main(void) +{ + puts("AT30TSE75x device driver test"); + + char line_buf[SHELL_DEFAULT_BUFSIZE]; + + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); + + return 0; +} -- GitLab