1 /*
2  * Copyright (c) 2024 TDK Invensense
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/device.h>
9 #include <zephyr/devicetree.h>
10 #include <zephyr/drivers/sensor.h>
11 #include <zephyr/drivers/sensor/tdk_apex.h>
12 #include <stdio.h>
13 
14 static struct sensor_trigger data_trigger;
15 
16 /* Flag set from IMU device irq handler */
17 static volatile int irq_from_device;
18 
19 /*
20  * Get a device structure from a devicetree node from alias
21  * "tdk_apex_sensor0".
22  */
get_tdk_apex_device(void)23 static const struct device *get_tdk_apex_device(void)
24 {
25 	const struct device *const dev = DEVICE_DT_GET(DT_ALIAS(tdk_apex_sensor0));
26 
27 	if (!device_is_ready(dev)) {
28 		printk("\nError: Device \"%s\" is not ready; "
29 		       "check the driver initialization logs for errors.\n",
30 		       dev->name);
31 		return NULL;
32 	}
33 
34 	printk("Found device \"%s\", getting sensor data\n", dev->name);
35 	return dev;
36 }
37 
now_str(void)38 static const char *now_str(void)
39 {
40 	static char buf[16]; /* ...HH:MM:SS.MMM */
41 	uint32_t now = k_uptime_get_32();
42 	unsigned int ms = now % MSEC_PER_SEC;
43 	unsigned int s;
44 	unsigned int min;
45 	unsigned int h;
46 
47 	now /= MSEC_PER_SEC;
48 	s = now % 60U;
49 	now /= 60U;
50 	min = now % 60U;
51 	now /= 60U;
52 	h = now;
53 
54 	snprintf(buf, sizeof(buf), "%u:%02u:%02u.%03u", h, min, s, ms);
55 	return buf;
56 }
57 
handle_tdk_apex_drdy(const struct device * dev,const struct sensor_trigger * trig)58 static void handle_tdk_apex_drdy(const struct device *dev, const struct sensor_trigger *trig)
59 {
60 	if (trig->type == SENSOR_TRIG_MOTION) {
61 		int rc = sensor_sample_fetch_chan(dev, trig->chan);
62 
63 		if (rc < 0) {
64 			printf("sample fetch failed: %d\n", rc);
65 			printf("cancelling trigger due to failure: %d\n", rc);
66 			(void)sensor_trigger_set(dev, trig, NULL);
67 			return;
68 		} else if (rc == 0) {
69 			irq_from_device = 1;
70 		}
71 	}
72 }
73 
main(void)74 int main(void)
75 {
76 	const struct device *dev = get_tdk_apex_device();
77 	struct sensor_value apex_mode;
78 
79 	if (dev == NULL) {
80 		return 0;
81 	}
82 
83 	sensor_attr_get(dev, SENSOR_CHAN_APEX_MOTION, SENSOR_ATTR_CONFIGURATION, &apex_mode);
84 	if (apex_mode.val1 == TDK_APEX_PEDOMETER) {
85 		printf("Pedometer data sample.\n");
86 	} else if (apex_mode.val1 == TDK_APEX_TILT) {
87 		printf("Tilt data sample.\n");
88 	} else if (apex_mode.val1 == TDK_APEX_WOM) {
89 		printf("WOM data sample.\n");
90 	} else if (apex_mode.val1 == TDK_APEX_SMD) {
91 		printf("SMD data sample.\n");
92 	}
93 	apex_mode.val2 = 0;
94 	sensor_attr_set(dev, SENSOR_CHAN_APEX_MOTION, SENSOR_ATTR_CONFIGURATION, &apex_mode);
95 
96 	data_trigger = (struct sensor_trigger){
97 		.type = SENSOR_TRIG_MOTION,
98 		.chan = SENSOR_CHAN_APEX_MOTION,
99 	};
100 	if (sensor_trigger_set(dev, &data_trigger, handle_tdk_apex_drdy) < 0) {
101 		printf("Cannot configure data trigger!!!\n");
102 		return 0;
103 	}
104 
105 	printf("Configured for APEX data collecting.\n");
106 
107 	k_sleep(K_MSEC(1000));
108 
109 	while (1) {
110 
111 		if (irq_from_device) {
112 			if (apex_mode.val1 == TDK_APEX_PEDOMETER) {
113 				struct sensor_value apex_pedometer[3];
114 
115 				sensor_channel_get(dev, SENSOR_CHAN_APEX_MOTION, apex_pedometer);
116 
117 				printf("[%s]: STEP_DET     count: %d steps  cadence: %.1f steps/s  "
118 				       "activity: %s\n",
119 				       now_str(), apex_pedometer[0].val1,
120 				       sensor_value_to_double(&apex_pedometer[2]),
121 				       apex_pedometer[1].val1 == 1   ? "Walk"
122 				       : apex_pedometer[1].val1 == 2 ? "Run"
123 								     : "Unknown");
124 			} else if (apex_mode.val1 == TDK_APEX_TILT) {
125 				struct sensor_value apex_tilt;
126 
127 				sensor_channel_get(dev, SENSOR_CHAN_APEX_MOTION, &apex_tilt);
128 
129 				printf("[%s]: %s\n", now_str(),
130 				       apex_tilt.val1 ? "TILT" : "Unknown trig");
131 			} else if (apex_mode.val1 == TDK_APEX_WOM) {
132 				struct sensor_value apex_wom[3];
133 
134 				sensor_channel_get(dev, SENSOR_CHAN_APEX_MOTION, apex_wom);
135 
136 				printf("[%s]: WOM x=%d y=%d z=%d\n", now_str(), apex_wom[0].val1,
137 				       apex_wom[1].val1, apex_wom[2].val1);
138 			} else if (apex_mode.val1 == TDK_APEX_SMD) {
139 				struct sensor_value apex_smd;
140 
141 				sensor_channel_get(dev, SENSOR_CHAN_APEX_MOTION, &apex_smd);
142 
143 				printf("[%s]: %s\n", now_str(),
144 				       apex_smd.val1 ? "SMD" : "Unknown trig");
145 			}
146 			irq_from_device = 0;
147 		}
148 	}
149 	return 0;
150 }
151