Linux Audio

Check our new training course

Loading...
/*
 * Copyright (c) 2019 Peter Bigot Consulting, LLC
 * Copyright (c) 2016 Intel Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/zephyr.h>
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>
#include <stdio.h>

#define UCEL_PER_CEL 1000000
#define UCEL_PER_MCEL 1000
#define TEMP_INITIAL_CEL 25
#define TEMP_WINDOW_HALF_UCEL 500000

static const char *now_str(void)
{
	static char buf[16]; /* ...HH:MM:SS.MMM */
	uint32_t now = k_uptime_get_32();
	unsigned int ms = now % MSEC_PER_SEC;
	unsigned int s;
	unsigned int min;
	unsigned int h;

	now /= MSEC_PER_SEC;
	s = now % 60U;
	now /= 60U;
	min = now % 60U;
	now /= 60U;
	h = now;

	snprintf(buf, sizeof(buf), "%u:%02u:%02u.%03u",
		 h, min, s, ms);
	return buf;
}

#ifdef CONFIG_MCP9808_TRIGGER

static struct sensor_trigger trig;

static int set_window(const struct device *dev,
		      const struct sensor_value *temp)
{
	const int temp_ucel = temp->val1 * UCEL_PER_CEL + temp->val2;
	const int low_ucel = temp_ucel - TEMP_WINDOW_HALF_UCEL;
	const int high_ucel = temp_ucel + TEMP_WINDOW_HALF_UCEL;
	struct sensor_value val = {
		.val1 = low_ucel / UCEL_PER_CEL,
		.val2 = low_ucel % UCEL_PER_CEL,
	};
	int rc = sensor_attr_set(dev, SENSOR_CHAN_AMBIENT_TEMP,
				 SENSOR_ATTR_LOWER_THRESH, &val);
	if (rc == 0) {
		val.val1 = high_ucel / UCEL_PER_CEL,
		val.val2 = high_ucel % UCEL_PER_CEL,
		rc = sensor_attr_set(dev, SENSOR_CHAN_AMBIENT_TEMP,
				     SENSOR_ATTR_UPPER_THRESH, &val);
	}

	if (rc == 0) {
		printf("Alert on temp outside [%d, %d] milli-Celsius\n",
		       low_ucel / UCEL_PER_MCEL,
		       high_ucel / UCEL_PER_MCEL);
	}

	return rc;
}

static inline int set_window_ucel(const struct device *dev,
				  int temp_ucel)
{
	struct sensor_value val = {
		.val1 = temp_ucel / UCEL_PER_CEL,
		.val2 = temp_ucel % UCEL_PER_CEL,
	};

	return set_window(dev, &val);
}

static void trigger_handler(const struct device *dev,
			    const struct sensor_trigger *trig)
{
	struct sensor_value temp;
	static size_t cnt;
	int rc;

	++cnt;
	rc = sensor_sample_fetch(dev);
	if (rc != 0) {
		printf("sensor_sample_fetch error: %d\n", rc);
		return;
	}
	rc = sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp);
	if (rc != 0) {
		printf("sensor_channel_get error: %d\n", rc);
		return;
	}

	printf("trigger fired %u, temp %g deg C\n", cnt,
	       sensor_value_to_double(&temp));
	set_window(dev, &temp);
}
#endif

void main(void)
{
	const struct device *dev = DEVICE_DT_GET_ANY(microchip_mcp9808);
	int rc;

	if (dev == NULL) {
		printf("Device not found.\n");
		return;
	}
	if (!device_is_ready(dev)) {
		printf("Device %s is not ready.\n", dev->name);
		return;
	}

#ifdef CONFIG_MCP9808_TRIGGER
	rc = set_window_ucel(dev, TEMP_INITIAL_CEL * UCEL_PER_CEL);
	if (rc == 0) {
		trig.type = SENSOR_TRIG_THRESHOLD;
		trig.chan = SENSOR_CHAN_AMBIENT_TEMP;
		rc = sensor_trigger_set(dev, &trig, trigger_handler);
	}

	if (rc != 0) {
		printf("Trigger set failed: %d\n", rc);
		return;
	}
	printk("Trigger set got %d\n", rc);
#endif

	while (1) {
		struct sensor_value temp;

		rc = sensor_sample_fetch(dev);
		if (rc != 0) {
			printf("sensor_sample_fetch error: %d\n", rc);
			break;
		}

		rc = sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp);
		if (rc != 0) {
			printf("sensor_channel_get error: %d\n", rc);
			break;
		}

		printf("%s: %g C\n", now_str(),
		       sensor_value_to_double(&temp));

		k_sleep(K_SECONDS(2));
	}
}