1 /*
2  * Copyright (c) 2019 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/device.h>
9 #include <zephyr/drivers/sensor.h>
10 #include <stdio.h>
11 #include <zephyr/sys/util.h>
12 
13 #define LUX_ALERT_DELTA 50
14 
15 static volatile bool alerted;
16 struct k_sem sem;
17 
trigger_handler(const struct device * dev,const struct sensor_trigger * trig)18 static void trigger_handler(const struct device *dev,
19 			    const struct sensor_trigger *trig)
20 {
21 #ifdef CONFIG_ISL29035_TRIGGER
22 	alerted = !alerted;
23 	k_sem_give(&sem);
24 #endif /* CONFIG_ISL29035_TRIGGER */
25 }
26 
now_str(void)27 static const char *now_str(void)
28 {
29 	static char buf[16]; /* ...HH:MM:SS.MMM */
30 	uint32_t now = k_uptime_get_32();
31 	unsigned int ms = now % MSEC_PER_SEC;
32 	unsigned int s;
33 	unsigned int min;
34 	unsigned int h;
35 
36 	now /= MSEC_PER_SEC;
37 	s = now % 60U;
38 	now /= 60U;
39 	min = now % 60U;
40 	now /= 60U;
41 	h = now;
42 
43 	snprintf(buf, sizeof(buf), "%u:%02u:%02u.%03u",
44 		 h, min, s, ms);
45 	return buf;
46 }
47 
process_sample(const struct device * dev)48 static void process_sample(const struct device *dev)
49 {
50 	static bool last_alerted;
51 	struct sensor_value val;
52 
53 	if (sensor_sample_fetch(dev) < 0) {
54 		printf("Sensor sample update error\n");
55 		return;
56 	}
57 
58 	if (sensor_channel_get(dev, SENSOR_CHAN_LIGHT, &val) < 0) {
59 		printf("Cannot read ISL29035 value\n");
60 		return;
61 	}
62 
63 	int lux = val.val1;
64 
65 	if (IS_ENABLED(CONFIG_ISL29035_TRIGGER)
66 	    && (alerted != last_alerted)) {
67 		static int last_lux;
68 		int rc;
69 		struct sensor_trigger trig = {
70 			.type = SENSOR_TRIG_THRESHOLD,
71 			.chan = SENSOR_CHAN_ALL,
72 		};
73 		struct sensor_value lo_thr = { MAX(lux - LUX_ALERT_DELTA, 0), };
74 		struct sensor_value hi_thr = { lux + LUX_ALERT_DELTA };
75 
76 		printf("ALERT %d lux outside range centered on %d lux."
77 		       "\nNext alert outside %d .. %d\n",
78 		       lux, last_lux, lo_thr.val1, hi_thr.val1);
79 		last_lux = lux;
80 		last_alerted = alerted;
81 
82 		rc = sensor_attr_set(dev, SENSOR_CHAN_LIGHT,
83 				     SENSOR_ATTR_LOWER_THRESH, &lo_thr);
84 		if (rc == 0) {
85 			rc = sensor_attr_set(dev, SENSOR_CHAN_LIGHT,
86 					     SENSOR_ATTR_UPPER_THRESH, &hi_thr);
87 		}
88 		if (rc == 0) {
89 			rc = sensor_trigger_set(dev, &trig, trigger_handler);
90 		}
91 		if (rc != 0) {
92 			printf("Alert configuration failed: %d\n", rc);
93 		}
94 	}
95 
96 	printf("[%s] %s: %g\n", now_str(),
97 	       IS_ENABLED(CONFIG_ISL29035_MODE_ALS)
98 	       ? "Ambient light sense"
99 	       : "IR sense",
100 	       sensor_value_to_double(&val));
101 }
102 
main(void)103 int main(void)
104 {
105 	const struct device *const dev = DEVICE_DT_GET_ONE(isil_isl29035);
106 
107 	if (!device_is_ready(dev)) {
108 		printk("sensor: device not ready.\n");
109 		return 0;
110 	}
111 
112 	k_sem_init(&sem, 0, 1);
113 	alerted = true;
114 	while (true) {
115 		process_sample(dev);
116 
117 		if (IS_ENABLED(CONFIG_ISL29035_TRIGGER)) {
118 			k_sem_take(&sem, K_SECONDS(10));
119 		} else {
120 			k_sleep(K_SECONDS(1));
121 		}
122 	}
123 	return 0;
124 }
125