1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

drivers/jc42: Add JEDEC JC42.4 temperature sensors

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.
This commit is contained in:
Koen Zandberg 2016-12-15 19:55:49 +01:00
parent a42f4c0c2a
commit 0f22e13ccb
9 changed files with 484 additions and 0 deletions

View File

@ -64,6 +64,9 @@ endif
ifneq (,$(filter bmp180,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/bmp180/include
endif
ifneq (,$(filter jc42,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/jc42/include
endif
ifneq (,$(filter cc2420,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/cc2420/include
endif

125
drivers/include/jc42.h Normal file
View File

@ -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_ */

2
drivers/jc42/Makefile Normal file
View File

@ -0,0 +1,2 @@
MODULE = jc42
include $(RIOTBASE)/Makefile.base

View File

@ -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_ */

View File

@ -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 */
/** @} */

105
drivers/jc42/jc42.c Normal file
View File

@ -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;
}

44
drivers/jc42/jc42_saul.c Normal file
View File

@ -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
};

View File

@ -294,6 +294,10 @@ void auto_init(void)
extern void auto_init_bmp180(void);
auto_init_bmp180();
#endif
#ifdef MODULE_JC42
extern void auto_init_jc42(void);
auto_init_jc42();
#endif
#endif /* MODULE_AUTO_INIT_SAUL */

View File

@ -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 */