|  | /* | 
|  | * Copyright (c) 2019 Peter Bigot Consulting, LLC | 
|  | * Copyright (c) 2016 Intel Corporation. | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #include <zephyr/kernel.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_JC42_TRIGGER | 
|  |  | 
|  | static struct sensor_trigger sensor_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 | 
|  |  | 
|  | int main(void) | 
|  | { | 
|  | const struct device *const dev = DEVICE_DT_GET_ANY(jedec_jc_42_4_temp); | 
|  | int rc; | 
|  |  | 
|  | if (dev == NULL) { | 
|  | printf("Device not found.\n"); | 
|  | return 0; | 
|  | } | 
|  | if (!device_is_ready(dev)) { | 
|  | printf("Device %s is not ready.\n", dev->name); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | #ifdef CONFIG_JC42_TRIGGER | 
|  | rc = set_window_ucel(dev, TEMP_INITIAL_CEL * UCEL_PER_CEL); | 
|  | if (rc == 0) { | 
|  | sensor_trig.type = SENSOR_TRIG_THRESHOLD; | 
|  | sensor_trig.chan = SENSOR_CHAN_AMBIENT_TEMP; | 
|  | rc = sensor_trigger_set(dev, &sensor_trig, trigger_handler); | 
|  | } | 
|  |  | 
|  | if (rc != 0) { | 
|  | printf("Trigger set failed: %d\n", rc); | 
|  | return 0; | 
|  | } | 
|  | 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)); | 
|  | } | 
|  | return 0; | 
|  | } |