Skip to content

Commit

Permalink
drivers: sensor: tmp1075: Add tmp1075 sensor driver and sample
Browse files Browse the repository at this point in the history
TI tmp1075 driver implemented based on tmp108 driver.
The driver initializes the sensor based on the DTS.
See sample app.overlay.

Added sample to show example driver usage.
To see default DTS configuration option inspect `ti,tmp1075.yaml`
bindings file.

Signed-off-by: Paweł Czaplewski <[email protected]>
  • Loading branch information
Paplewski committed Jul 3, 2024
1 parent 3d72998 commit d9d4f86
Show file tree
Hide file tree
Showing 15 changed files with 613 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/sensor/ti/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ add_subdirectory_ifdef(CONFIG_TMP108 tmp108)
add_subdirectory_ifdef(CONFIG_TMP112 tmp112)
add_subdirectory_ifdef(CONFIG_TMP114 tmp114)
add_subdirectory_ifdef(CONFIG_TMP116 tmp116)
add_subdirectory_ifdef(CONFIG_TMP1075 tmp1075)
# zephyr-keep-sorted-stop

Check failure on line 23 in drivers/sensor/ti/CMakeLists.txt

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

KeepSorted

drivers/sensor/ti/CMakeLists.txt:23 sorted block is not sorted, sort by running: "ex -s -c '5,22 sort i|x' drivers/sensor/ti/CMakeLists.txt"
1 change: 1 addition & 0 deletions drivers/sensor/ti/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ source "drivers/sensor/ti/tmp108/Kconfig"
source "drivers/sensor/ti/tmp112/Kconfig"
source "drivers/sensor/ti/tmp114/Kconfig"
source "drivers/sensor/ti/tmp116/Kconfig"
source "drivers/sensor/ti/tmp1075/Kconfig"
# zephyr-keep-sorted-stop

Check failure on line 23 in drivers/sensor/ti/Kconfig

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

KeepSorted

drivers/sensor/ti/Kconfig:23 sorted block is not sorted, sort by running: "ex -s -c '5,22 sort i|x' drivers/sensor/ti/Kconfig"
5 changes: 5 additions & 0 deletions drivers/sensor/ti/tmp1075/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# SPDX-License-Identifier: Apache-2.0

zephyr_library()

zephyr_library_sources(tmp1075.c tmp1075_trigger.c)
21 changes: 21 additions & 0 deletions drivers/sensor/ti/tmp1075/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# TMP1075 temperature sensor configuration options

menuconfig TMP1075
bool "TMP1075 Temperature Sensor"
default y
depends on DT_HAS_TI_TMP1075_ENABLED
select I2C

help
Enable the driver for Texas Instruments TMP1075 High-Accuracy Digital
Temperature Sensors.

if TMP1075

config TMP1075_ALERT_INTERRUPTS
bool "Allow interrupts to service over and under temp alerts"
help
This will set up interrupts to service under and over temp alerts
see TMP1075 spec sheet for more information on how these work.

endif # TMP1075
254 changes: 254 additions & 0 deletions drivers/sensor/ti/tmp1075/tmp1075.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
/*
* Copyright (c) 2024 Arrow Electronics.
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT ti_tmp1075

#include <zephyr/device.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/util.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/sys/__assert.h>
#include <zephyr/logging/log.h>

#include "tmp1075.h"

LOG_MODULE_REGISTER(TMP1075, CONFIG_SENSOR_LOG_LEVEL);

#define I2C_REG_ADDR_SIZE 1
#define I2C_REG_SENSOR_SIZE sizeof(uint16_t)
#define I2C_BUFFER_SIZE I2C_REG_ADDR_SIZE + I2C_REG_SENSOR_SIZE

#define I2C_REG_ADDR_OFFSET 0
#define I2C_WRITE_DATA_OFFSET 1

static int tmp1075_reg_read(const struct tmp1075_config *cfg, uint8_t reg, uint16_t *val)
{
if (i2c_burst_read_dt(&cfg->bus, reg, (uint8_t *)val, sizeof(*val)) < 0) {
return -EIO;
}
*val = sys_be16_to_cpu(*val);
return 0;
}

static int tmp1075_reg_write(const struct tmp1075_config *cfg, uint8_t reg, uint16_t val)
{
uint8_t buf[I2C_REG_ADDR_SIZE + I2C_REG_SENSOR_SIZE];

buf[I2C_REG_ADDR_OFFSET] = reg;
sys_put_be16(val, &buf[I2C_WRITE_DATA_OFFSET]);

return i2c_write_dt(&cfg->bus, buf, sizeof(buf));
}

#if CONFIG_TMP1075_ALERT_INTERRUPTS
static int set_threshold_attribute(const struct device *dev, uint8_t reg, int16_t value,
const char *error_msg)
{
if (tmp1075_reg_write(dev->config, reg, value) < 0) {
LOG_ERR("Failed to set %s attribute!", error_msg);
return -EIO;
}
return 0;
}
#endif

static int tmp1075_attr_set(const struct device *dev, enum sensor_channel chan,
enum sensor_attribute attr, const struct sensor_value *val)
{
if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
return -ENOTSUP;
}

switch (attr) {
#if CONFIG_TMP1075_ALERT_INTERRUPTS
case SENSOR_ATTR_LOWER_THRESH:
return set_threshold_attribute(dev, TMP1075_REG_TLOW, val->val1 << 8,
"SENSOR_ATTR_LOWER_THRESH");

case SENSOR_ATTR_UPPER_THRESH:
return set_threshold_attribute(dev, TMP1075_REG_THIGH, val->val1 << 8,
"SENSOR_ATTR_UPPER_THRESH");
#endif

default:
return -ENOTSUP;
}
}

#if CONFIG_TMP1075_ALERT_INTERRUPTS
static int get_threshold_attribute(const struct device *dev, uint8_t reg, struct sensor_value *val,
const char *error_msg)
{
uint16_t value;

if (tmp1075_reg_read(dev->config, reg, &value) < 0) {
LOG_ERR("Failed to get %s attribute!", error_msg);
return -EIO;
}
val->val1 = value >> 8;
return 0;
}
#endif

static int tmp1075_attr_get(const struct device *dev, enum sensor_channel chan,
enum sensor_attribute attr, struct sensor_value *val)
{
if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
return -ENOTSUP;
}

switch (attr) {
#if CONFIG_TMP1075_ALERT_INTERRUPTS
case SENSOR_ATTR_LOWER_THRESH:
return get_threshold_attribute(dev, TMP1075_REG_TLOW, val,
"SENSOR_ATTR_LOWER_THRESH");

case SENSOR_ATTR_UPPER_THRESH:
return get_threshold_attribute(dev, TMP1075_REG_THIGH, val,
"SENSOR_ATTR_UPPER_THRESH");
#endif

default:
return -ENOTSUP;
}
}

static int tmp1075_sample_fetch(const struct device *dev, enum sensor_channel chan)
{
struct tmp1075_data *drv_data = dev->data;
const struct tmp1075_config *cfg = dev->config;
uint16_t val;

__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_AMBIENT_TEMP);

if (tmp1075_reg_read(cfg, TMP1075_REG_TEMPERATURE, &val) < 0) {
return -EIO;
}
drv_data->sample = arithmetic_shift_right((int16_t)val, TMP1075_DATA_NORMAL_SHIFT);
return 0;
}

static int tmp1075_channel_get(const struct device *dev, enum sensor_channel chan,
struct sensor_value *val)
{
struct tmp1075_data *drv_data = dev->data;
int32_t uval;

if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
return -ENOTSUP;
}

uval = (int32_t)drv_data->sample * TMP1075_TEMP_SCALE;
val->val1 = uval / uCELSIUS_IN_CELSIUS;
val->val2 = uval % uCELSIUS_IN_CELSIUS;

return 0;
}

static const struct sensor_driver_api tmp1075_driver_api = {
.attr_set = tmp1075_attr_set,
.attr_get = tmp1075_attr_get,
.sample_fetch = tmp1075_sample_fetch,
.channel_get = tmp1075_channel_get,
#ifdef CONFIG_TMP1075_ALERT_INTERRUPTS
.trigger_set = tmp1075_trigger_set,
#endif
};

#ifdef CONFIG_TMP1075_ALERT_INTERRUPTS
static int setup_interrupts(const struct device *dev)
{
struct tmp1075_data *drv_data = dev->data;
const struct tmp1075_config *config = dev->config;
const struct gpio_dt_spec *alert_gpio = &config->alert_gpio;
int result;

if (!device_is_ready(alert_gpio->port)) {
LOG_ERR("tmp1075: gpio controller %s not ready", alert_gpio->port->name);
return -ENODEV;
}

result = gpio_pin_configure_dt(alert_gpio, GPIO_INPUT);

if (result < 0) {
return result;
}

gpio_init_callback(&drv_data->temp_alert_gpio_cb, tmp1075_trigger_handle_alert,
BIT(alert_gpio->pin));

result = gpio_add_callback(alert_gpio->port, &drv_data->temp_alert_gpio_cb);

if (result < 0) {
return result;
}

result = gpio_pin_interrupt_configure_dt(alert_gpio, GPIO_INT_EDGE_BOTH);

if (result < 0) {
return result;
}

return 0;
}
#endif

int tmp1075_init(const struct device *dev)
{
const struct tmp1075_config *cfg = dev->config;
struct tmp1075_data *data = dev->data;

if (!device_is_ready(cfg->bus.bus)) {
LOG_ERR("I2C dev %s not ready", cfg->bus.bus->name);
return -EINVAL;
}
#ifdef CONFIG_TMP1075_ALERT_INTERRUPTS
int result = setup_interrupts(dev);

if (result < 0) {
LOG_ERR("Couldn't setup interrupts");
return -EIO;
}
#endif
data->tmp1075_dev = dev;

uint16_t config_reg = 0;

TMP1075_SET_ONE_SHOT_CONVERSION(config_reg, cfg->one_shot);
TMP1075_SET_CONVERSION_RATE(config_reg, cfg->cr);
TMP1075_SET_CONSECUTIVE_FAULT_MEASUREMENTS(config_reg, cfg->cf);
TMP1075_SET_ALERT_PIN_POLARITY(config_reg, cfg->alert_pol);
TMP1075_SET_ALERT_PIN_FUNCTION(config_reg, cfg->interrupt_mode);
TMP1075_SET_SHUTDOWN_MODE(config_reg, cfg->shutdown_mode);

int rc = tmp1075_reg_write(dev->config, TMP1075_REG_CONFIG, config_reg);

if (rc == 0) {
data->config_reg = config_reg;
}
return rc;
}

#define TMP1075_INST(inst) \
static struct tmp1075_data tmp1075_data_##inst; \
static const struct tmp1075_config tmp1075_config_##inst = { \
.cr = DT_INST_ENUM_IDX(inst, conversion_rate), \
.cf = DT_INST_ENUM_IDX(inst, consecutive_fault_measurements), \
.alert_pol = DT_INST_PROP(inst, alert_pin_active_high), \
.interrupt_mode = DT_INST_PROP(inst, interrupt_mode), \
.shutdown_mode = DT_INST_PROP(inst, shutdown_mode), \
.bus = I2C_DT_SPEC_INST_GET(inst), \
.alert_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, alert_gpios, {0}), \
}; \
\
SENSOR_DEVICE_DT_INST_DEFINE(inst, tmp1075_init, NULL, &tmp1075_data_##inst, \
&tmp1075_config_##inst, POST_KERNEL, \
CONFIG_SENSOR_INIT_PRIORITY, &tmp1075_driver_api);

DT_INST_FOREACH_STATUS_OKAY(TMP1075_INST)
75 changes: 75 additions & 0 deletions drivers/sensor/ti/tmp1075/tmp1075.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2024 Arrow Electronics.
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_DRIVERS_SENSOR_TMP1075_TMP1075_H_
#define ZEPHYR_DRIVERS_SENSOR_TMP1075_TMP1075_H_

#include <zephyr/device.h>
#include <zephyr/sys/util.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/i2c.h>

/* Extended resolution is not supported on TMP1075 */
#define TMP1075_DATA_NORMAL_SHIFT 4
#define uCELSIUS_IN_CELSIUS 1000000

#define TMP1075_REG_TEMPERATURE 0x00
#define TMP1075_REG_CONFIG 0x01
#define TMP1075_REG_TLOW 0x02
#define TMP1075_REG_THIGH 0x03

/* Scale in micro degrees Celsius -> 0.0625°C per ADC bit resolution */
#define TMP1075_TEMP_SCALE 62500

/* Macro to set or clear the TMP1075_OS (One-shot conversion mode) bit based on a boolean value */
#define TMP1075_SET_ONE_SHOT_CONVERSION(reg, enable) \
((reg) = ((reg) & ~(1 << 15)) | ((enable) << 15))

/* Macro to set the TMP1075_R (Conversion rate) bits */
#define TMP1075_SET_CONVERSION_RATE(reg, rate) ((reg) |= ((rate) << 13))

/* Macro to set the TMP1075_F (Consecutive fault measurements) bits */
#define TMP1075_SET_CONSECUTIVE_FAULT_MEASUREMENTS(reg, faults) ((reg) |= ((faults) << 11))

/* Macro to set or clear the TMP1075_POL (Polarity of output pin) bit based on a boolean value */
#define TMP1075_SET_ALERT_PIN_POLARITY(reg, activeHigh) \
((reg) = ((reg) & ~(1 << 10)) | ((activeHigh) << 10))

/* Macro to set or clear the TMP1075_TM (ALERT pin function) bit based on a boolean value */
#define TMP1075_SET_ALERT_PIN_FUNCTION(reg, interruptMode) \
((reg) = ((reg) & ~(1 << 9)) | ((interruptMode) << 9))

/* Macro to set or clear the TMP1075_SD (Shutdown mode) bit based on a boolean value */
#define TMP1075_SET_SHUTDOWN_MODE(reg, shutdown) ((reg) = ((reg) & ~(1 << 8)) | ((shutdown) << 8))

struct tmp1075_data {
const struct device *tmp1075_dev;
int16_t sample;
uint16_t config_reg;
struct sensor_trigger temp_alert_trigger;
sensor_trigger_handler_t temp_alert_handler;
struct gpio_callback temp_alert_gpio_cb;
bool over_threshold;
};

struct tmp1075_config {
const struct i2c_dt_spec bus;
const struct gpio_dt_spec alert_gpio;
uint8_t cr;
uint8_t cf;
bool alert_pol: 1;
bool one_shot: 1;
bool interrupt_mode: 1;
bool shutdown_mode: 1;
};

int tmp1075_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
sensor_trigger_handler_t handler);

void tmp1075_trigger_handle_alert(const struct device *port, struct gpio_callback *cb,
gpio_port_pins_t pins);

#endif
Loading

0 comments on commit d9d4f86

Please sign in to comment.