Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
/*
 * Copyright (c) 2021 Jimmy Johnson <catch22@fastmail.net>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/drivers/sensor.h>
#include <zephyr/logging/log.h>
#include <zephyr/kernel.h>

#include "tmp108.h"

#define TMP108_ONE_SHOT_RETRY_TIME_IN_MS 10

LOG_MODULE_DECLARE(TMP108, CONFIG_SENSOR_LOG_LEVEL);

void tmp108_trigger_handle_one_shot(struct k_work *work)
{
	struct k_work_delayable *delayable_work = CONTAINER_OF(work,
							       struct k_work_delayable,
							       work);

	struct tmp108_data *drv_data = CONTAINER_OF(delayable_work,
						    struct tmp108_data,
						    scheduled_work);

	struct sensor_trigger sensor_trigger_type = {
		.chan = SENSOR_CHAN_AMBIENT_TEMP,
		.type = SENSOR_TRIG_DATA_READY
	};

	uint16_t config = 0;
	bool shutdown_mode = false;

	tmp108_reg_read(drv_data->tmp108_dev, TI_TMP108_REG_CONF, &config);

	/* check shutdown mode which indicates a one shot read was successful */
	shutdown_mode = (config & (TI_TMP108_CONF_M1 | TI_TMP108_CONF_M0)) == 0;

	if (shutdown_mode == true) {
		ti_tmp108_read_temp(drv_data->tmp108_dev);
	} else {
		LOG_ERR("Temperature one shot mode read failed, retrying");
		/* Typical wake up time is 27 ms, retry if the read fails
		 * assuming the chip should wake up and take a reading by the time
		 * 27 ms for the initial wake up time and call of this thread
		 * plus 10 ms time has passed
		 */
		k_work_reschedule(&drv_data->scheduled_work,
				  K_MSEC(TMP108_ONE_SHOT_RETRY_TIME_IN_MS));
		return;
	}

	/* Successful read, call set callbacks */
	if (drv_data->data_ready_handler) {
		drv_data->data_ready_handler(drv_data->tmp108_dev,
					     &sensor_trigger_type);
	}
}

void tmp108_trigger_handle_alert(const struct device *gpio,
				 struct gpio_callback *cb,
				 gpio_port_pins_t pins)
{

	struct tmp108_data *drv_data = CONTAINER_OF(cb,
						    struct tmp108_data,
						    temp_alert_gpio_cb);

	struct sensor_trigger sensor_trigger_type = {
		.chan = SENSOR_CHAN_AMBIENT_TEMP,
		.type = SENSOR_TRIG_THRESHOLD
	};

	/* Successful read, call set callbacks */
	if (drv_data->temp_alert_handler) {
		drv_data->temp_alert_handler(drv_data->tmp108_dev,
					     &sensor_trigger_type);
	}
}

int tmp_108_trigger_set(const struct device *dev,
			const struct sensor_trigger *trig,
			sensor_trigger_handler_t handler)
{
	struct tmp108_data *drv_data = dev->data;

	if (trig->type == SENSOR_TRIG_DATA_READY) {
		drv_data->data_ready_handler = handler;
		drv_data->data_ready_trigger = *trig;
		return 0;
	}

	if (trig->type == SENSOR_TRIG_THRESHOLD) {
		drv_data->temp_alert_handler = handler;
		drv_data->temp_alert_trigger = *trig;
		return 0;
	}

	return -ENOTSUP;
}