Browse Source
This patch adds a driver for the jc42 compatible temperature sensors. All sensors compatible with jc42.4 should work. Examples include the mcp9808 and more.pr/spi.typo

9 changed files with 484 additions and 0 deletions
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Koen Zandberg |
||||
* |
||||
* 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_jc42 JC42 compliant temperature sensor driver |
||||
* @ingroup drivers_sensors |
||||
* |
||||
* @brief JC42 compliant temperature sensor driver |
||||
* |
||||
* ## Description |
||||
* |
||||
* The connection between the MCU and jc42 compliant temperature sensors is |
||||
* based on a I2C-interface. There are multiple jc42 compliant temperature |
||||
* sensors available such as the mcp9804 and the MAX6604. This driver reads the |
||||
* temperature from these sensors. The sensors support a alarm wire, but this |
||||
* is not supported by this driver. |
||||
* |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Driver for jc42 compliant temperature sensors |
||||
* |
||||
* @author Koen Zandberg <koen@bergzand.net> |
||||
*/ |
||||
|
||||
#ifndef JC42_TEMP_H_ |
||||
#define JC42_TEMP_H_ |
||||
|
||||
#include <stdint.h> |
||||
#include "periph/i2c.h" |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @name jc42 status return codes |
||||
* @{ |
||||
*/ |
||||
#define JC42_OK (0) |
||||
#define JC42_NOI2C (-1) |
||||
#define JC42_NODEV (-2) |
||||
/** @} */ |
||||
|
||||
|
||||
/**
|
||||
* @brief Device descriptor for a jc42 device |
||||
*/ |
||||
typedef struct { |
||||
i2c_t i2c; /**< I2C device that sensor is connected to */ |
||||
uint8_t addr; /**< I2C address of this particular sensor */ |
||||
} jc42_t; |
||||
|
||||
/**
|
||||
* @brief Device initialization parameters |
||||
*/ |
||||
typedef struct { |
||||
i2c_t i2c; /**< I2C device that sensor is connected to */ |
||||
i2c_speed_t speed; /**< I2C device speed */ |
||||
uint8_t addr; /**< Configured address of the sensor */ |
||||
} jc42_params_t; |
||||
|
||||
/**
|
||||
* @brief export SAUL endpoint |
||||
*/ |
||||
extern const saul_driver_t jc42_temperature_saul_driver; |
||||
|
||||
/**
|
||||
* @brief Initialize a jc42 device |
||||
* |
||||
* @param[out] dev device descriptor |
||||
* @param[in] params jc42 initialization struct |
||||
* |
||||
* |
||||
* @return 0 on success |
||||
* @return -1 on error |
||||
*/ |
||||
int jc42_init(jc42_t* dev, jc42_params_t* params); |
||||
|
||||
/**
|
||||
* @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 jc42_get_config(jc42_t* dev, uint16_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 jc42_set_config(jc42_t* dev, uint16_t data); |
||||
|
||||
|
||||
/**
|
||||
* @brief Get measured temperature |
||||
* |
||||
* @param[in] dev device descriptor |
||||
* @param[out] temperature uint16_t buffer where temperature will be written to in centi-degree |
||||
* |
||||
* @return 0 on success |
||||
* @return -1 on error |
||||
*/ |
||||
int jc42_get_temperature(jc42_t* dev, uint16_t* temperature); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
/** @} */ |
||||
#endif /* JC42_TEMP_H_ */ |
@ -0,0 +1,2 @@
|
||||
MODULE = jc42
|
||||
include $(RIOTBASE)/Makefile.base |
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Koen Zandberg |
||||
* |
||||
* 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_sensors |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Internal addresses, registers, constants for jc42 sensors. |
||||
* |
||||
* @author Koen Zandberg <koen@bergzand.net> |
||||
*/ |
||||
|
||||
#ifndef JC42_INTERNAL_H_ |
||||
#define JC42_INTERNAL_H_ |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @name JC42 register addresses |
||||
* @{ |
||||
*/ |
||||
#define JC42_REG_CAP (0x00) |
||||
#define JC42_REG_CONFIG (0x01) |
||||
#define JC42_REG_TEMP_UPPER (0x02) |
||||
#define JC42_REG_TEMP_LOWER (0x03) |
||||
#define JC42_REG_TEMP_CRITICAL (0x04) |
||||
#define JC42_REG_TEMP (0x05) |
||||
#define JC42_REG_MANID (0x06) |
||||
#define JC42_REG_DEVICEID (0x07) |
||||
|
||||
#define jc42_BUS_FREE_TIME_US (1) |
||||
/** @} */ |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
/** @} */ |
||||
|
||||
|
||||
#endif /* JC42_INTERNAL_H_ */ |
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Koen Zandberg <koen@bergzand.net> |
||||
* |
||||
* 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_jc42 |
||||
* |
||||
* @{ |
||||
* @file |
||||
* @brief Default configuration for jc42 |
||||
* |
||||
* @author Koen Zandberg <koen@bergzand.net> |
||||
*/ |
||||
|
||||
#ifndef JC42_PARAMS_H |
||||
#define JC42_PARAMS_H |
||||
|
||||
#include "board.h" |
||||
#include "jc42.h" |
||||
#include "periph/i2c.h" |
||||
#include "saul_reg.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Set default configuration parameters for the JC42 |
||||
* @{ |
||||
*/ |
||||
#ifndef JC42_PARAM_I2C_DEV |
||||
#define JC42_PARAM_I2C_DEV (0) |
||||
#endif |
||||
#ifndef JC42_PARAM_ADDR |
||||
#define JC42_PARAM_ADDR (0x18) |
||||
#endif |
||||
#ifndef JC42_PARAM_SPEED |
||||
#define JC42_PARAM_SPEED I2C_SPEED_FAST |
||||
#endif |
||||
|
||||
#define JC42_PARAMS_DEFAULT {.i2c = JC42_PARAM_I2C_DEV, \ |
||||
.speed = JC42_PARAM_SPEED, \
|
||||
.addr = JC42_PARAM_ADDR } |
||||
/**@}*/ |
||||
|
||||
/**
|
||||
* @brief Configure JC42 |
||||
*/ |
||||
static const jc42_params_t jc42_params[] = |
||||
{ |
||||
#ifdef JC42_PARAMS_BOARD |
||||
JC42_PARAMS_BOARD, |
||||
#else |
||||
JC42_PARAMS_DEFAULT, |
||||
#endif |
||||
}; |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* JC42_PARAMS_H */ |
||||
/** @} */ |
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Koen Zandberg |
||||
* |
||||
* 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_jc42 |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Device driver implementation for the JEDEC jc42.4 compliant temperature sensors |
||||
* |
||||
* @author Koen Zandberg <koen@bergzand.net> |
||||
* |
||||
* @} |
||||
*/ |
||||
|
||||
|
||||
#include "periph/i2c.h" |
||||
#include "byteorder.h" |
||||
#include "xtimer.h" |
||||
#include "saul.h" |
||||
|
||||
#include "jc42.h" |
||||
#include "jc42_params.h" |
||||
#include "jc42_internal.h" |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
|
||||
static int jc42_get_register(jc42_t* dev, uint8_t reg, uint16_t* data) |
||||
{ |
||||
i2c_acquire(dev->i2c); |
||||
if (i2c_read_regs(dev->i2c, dev->addr, reg, data, 2) <= 0) { |
||||
DEBUG("[jc42] Problem reading register 0x%x\n", reg); |
||||
i2c_release(dev->i2c); |
||||
return JC42_NODEV; |
||||
} |
||||
i2c_release(dev->i2c); |
||||
return JC42_OK; |
||||
} |
||||
|
||||
static int jc42_set_register(jc42_t* dev, uint8_t reg, uint16_t* data) |
||||
{ |
||||
i2c_acquire(dev->i2c); |
||||
if (i2c_write_regs(dev->i2c, dev->addr, reg, data, 2) <= 0) { |
||||
DEBUG("[jc42] Problem writing to register 0x%x\n", reg); |
||||
i2c_release(dev->i2c); |
||||
return JC42_NODEV; |
||||
} |
||||
i2c_release(dev->i2c); |
||||
|
||||
return JC42_OK; |
||||
} |
||||
|
||||
int jc42_get_config(jc42_t* dev, uint16_t* data) |
||||
{ |
||||
return jc42_get_register(dev, JC42_REG_CONFIG, data); |
||||
} |
||||
|
||||
int jc42_set_config(jc42_t* dev, uint16_t data) |
||||
{ |
||||
return jc42_set_register(dev, JC42_REG_CONFIG, &data); |
||||
} |
||||
|
||||
int jc42_get_temperature(jc42_t* dev, uint16_t* temperature) |
||||
{ |
||||
struct { signed int x:12;} s; |
||||
uint16_t tmp; |
||||
|
||||
/* Read temperature */ |
||||
if(jc42_get_register(dev, JC42_REG_TEMP, &tmp) != 0) { |
||||
return JC42_NODEV; |
||||
} |
||||
tmp = NTOHS(tmp); |
||||
/* Convert fixed point to uint16_t */ |
||||
*temperature = ((s.x = tmp)*100)>>4; |
||||
return JC42_OK; |
||||
} |
||||
|
||||
int jc42_init(jc42_t* dev, jc42_params_t* params) |
||||
{ |
||||
uint16_t config; |
||||
dev->i2c = params->i2c; |
||||
dev->addr = params->addr; |
||||
i2c_acquire(dev->i2c); |
||||
if(i2c_init_master(dev->i2c, params->speed) != 0) { |
||||
DEBUG("[jc42] Problem initializing I2C master\n"); |
||||
i2c_release(dev->i2c); |
||||
return JC42_NOI2C; |
||||
} |
||||
i2c_release(dev->i2c); |
||||
|
||||
/* Poll the device, fail if unavailable */ |
||||
if(jc42_get_config(dev, &config) != 0) { |
||||
return JC42_NODEV; |
||||
} |
||||
|
||||
DEBUG("[jc42] Config: 0x%x\n", config); |
||||
|
||||
return JC42_OK; |
||||
} |
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Koen Zandberg <koen@bergzand.net> |
||||
* |
||||
* 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_jc42 |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief SAUL adaption for jc42 compatible device |
||||
* |
||||
* @author Koen Zandberg <koen@bergzand.net> |
||||
* |
||||
* @} |
||||
*/ |
||||
|
||||
#include <string.h> |
||||
|
||||
#include "saul.h" |
||||
#include "jc42.h" |
||||
|
||||
|
||||
|
||||
static int read_temperature(void *dev, phydat_t *res) |
||||
{ |
||||
uint16_t temperature; |
||||
jc42_t *d = (jc42_t *)dev; |
||||
|
||||
jc42_get_temperature(d, &temperature); |
||||
res->val[0] = temperature; |
||||
res->unit = UNIT_TEMP_C; |
||||
res->scale = -2; |
||||
return 1; |
||||
} |
||||
|
||||
const saul_driver_t jc42_temperature_saul_driver = { |
||||
.read = read_temperature, |
||||
.write = saul_notsup, |
||||
.type = SAUL_SENSE_TEMP |
||||
}; |
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Koen Zandberg |
||||
* |
||||
* 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 auto_init_saul |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Auto initialization of jc42 compatible driver. |
||||
* |
||||
* @author Koen Zandberg <koen@bergzand.net> |
||||
* |
||||
* @} |
||||
*/ |
||||
|
||||
#ifdef MODULE_JC42 |
||||
|
||||
#include "log.h" |
||||
#include "saul_reg.h" |
||||
|
||||
#include "jc42.h" |
||||
#include "jc42_params.h" |
||||
|
||||
/**
|
||||
* @brief Define the number of configured sensors |
||||
*/ |
||||
#define JC42_NUMOF (sizeof(jc42_params) / sizeof(jc42_params[0])) |
||||
|
||||
/**
|
||||
* @brief Allocation of memory for device descriptors |
||||
*/ |
||||
static jc42_t jc42_devs[JC42_NUMOF]; |
||||
|
||||
/**
|
||||
* @brief Memory for the SAUL registry entries |
||||
*/ |
||||
static saul_reg_t saul_entries[JC42_NUMOF]; |
||||
|
||||
/**
|
||||
* @brief Reference the driver structs. |
||||
* @{ |
||||
*/ |
||||
extern const saul_driver_t jc42_temperature_saul_driver; |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Allocate and configure entries to the SAUL registry |
||||
*/ |
||||
saul_reg_t jc42_saul_reg_info[]= |
||||
{ |
||||
{ |
||||
.name= "jc42", |
||||
.driver = &jc42_temperature_saul_driver |
||||
} |
||||
}; |
||||
|
||||
void auto_init_jc42(void) |
||||
{ |
||||
for (unsigned i = 0; i < JC42_NUMOF; i++) { |
||||
const jc42_params_t *p = &jc42_params[i]; |
||||
if (jc42_init(&jc42_devs[i], |
||||
(jc42_params_t*) p) < 0) { |
||||
LOG_ERROR("Unable to initialize jc42 sensor #%i\n", i); |
||||
return; |
||||
} |
||||
|
||||
|
||||
/* temperature */ |
||||
saul_entries[i].dev = &(jc42_devs[i]); |
||||
saul_entries[i].name = jc42_saul_reg_info[i].name; |
||||
saul_entries[i].driver = &jc42_temperature_saul_driver; |
||||
|
||||
/* register to saul */ |
||||
saul_reg_add(&(saul_entries[i])); |
||||
} |
||||
} |
||||
#else |
||||
typedef int dont_be_pedantic; |
||||
#endif /* MODULE_JC42 */ |
Loading…
Reference in new issue