1 /*
2 * Copyright (c) 2021 Titouan Christophe
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 <zephyr/drivers/gpio.h>
11
12 #include "display_7seg.h"
13
14 /*
15 * Get button configuration from the devicetree sw0 alias. This is mandatory.
16 */
17 #define SW0_NODE DT_ALIAS(sw0)
18 #if !DT_NODE_HAS_STATUS(SW0_NODE, okay)
19 #error "Unsupported board: sw0 devicetree alias is not defined"
20 #endif
21
22 #define N_MODES ARRAY_SIZE(modes)
23 #define N_SENSORS ARRAY_SIZE(sensors)
24 #define LEFT sensors[0]
25 #define CENTER sensors[1]
26 #define RIGHT sensors[2]
27
28 typedef void (*fsm_state)(void);
29
30 static int64_t last_mode_change;
31
32 static const struct device *const sensors[] = {
33 DEVICE_DT_GET(DT_NODELABEL(vl53l0x_l_x_nucleo_53l0a1)),
34 DEVICE_DT_GET(DT_NODELABEL(vl53l0x_c_x_nucleo_53l0a1)),
35 DEVICE_DT_GET(DT_NODELABEL(vl53l0x_r_x_nucleo_53l0a1)),
36 };
37
mode_show_distance(void)38 static void mode_show_distance(void)
39 {
40 int ret;
41 double distance;
42 struct sensor_value value;
43
44 ret = sensor_sample_fetch(CENTER);
45 if (ret) {
46 printk("sensor_sample_fetch(%s) failed -> %d\n", CENTER->name, ret);
47 display_chars(TEXT_Err);
48 return;
49 }
50
51 ret = sensor_channel_get(CENTER, SENSOR_CHAN_DISTANCE, &value);
52 if (ret) {
53 printk("sensor_channel_get(%s) failed -> %d\n", CENTER->name, ret);
54 display_chars(TEXT_Err);
55 return;
56 }
57 distance = sensor_value_to_double(&value);
58 if (distance < 1.25) {
59 display_number(100 * distance, 10);
60 } else {
61 display_chars(DISPLAY_OFF);
62 }
63 }
64
mode_show_presence(void)65 static void mode_show_presence(void)
66 {
67 int i, ret;
68 struct sensor_value value;
69 uint8_t text[4] = { CHAR_OFF, CHAR_OFF, CHAR_OFF, CHAR_OFF };
70
71 for (i = 0; i < N_SENSORS; i++) {
72 ret = sensor_sample_fetch(sensors[i]);
73 if (ret) {
74 printk("sensor_sample_fetch(%s) failed -> %d\n",
75 sensors[i]->name, ret);
76 display_chars(TEXT_Err);
77 return;
78 }
79 ret = sensor_channel_get(sensors[i],
80 SENSOR_CHAN_PROX,
81 &value);
82 if (ret) {
83 printk("sensor_channel_get(%s) failed -> %d\n",
84 sensors[i]->name, ret);
85 display_chars(TEXT_Err);
86 return;
87 }
88
89 if (value.val1) {
90 text[i] = CHAR_UNDERSCORE | CHAR_DASH | CHAR_OVERLINE;
91 }
92 }
93 display_chars(text);
94 }
95
96 static size_t current_mode;
97 static fsm_state modes[] = {
98 mode_show_distance,
99 mode_show_presence,
100 };
101
change_mode(const struct device * dev,struct gpio_callback * cb,uint32_t pins)102 static void change_mode(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
103 {
104 (void) dev;
105 (void) cb;
106 (void) pins;
107
108 int64_t now = k_uptime_get();
109
110 if (now - last_mode_change > 300) {
111 current_mode = (current_mode + 1) % N_MODES;
112 last_mode_change = now;
113 }
114 }
115
116
main(void)117 int main(void)
118 {
119 struct gpio_callback button_cb_data;
120 const uint8_t Hello[4] = { CHAR_H, CHAR_E, CHAR_PIPE | CHAR_1, CHAR_0 };
121 const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios);
122
123 display_chars(Hello);
124 k_sleep(K_MSEC(1000));
125
126 if (!gpio_is_ready_dt(&button)) {
127 printk("Error: button device %s is not ready\n",
128 button.port->name);
129 return 0;
130 }
131
132 gpio_pin_configure_dt(&button, GPIO_INPUT);
133 gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_RISING);
134 gpio_init_callback(&button_cb_data, change_mode, BIT(button.pin));
135 gpio_add_callback(button.port, &button_cb_data);
136
137 while (1) {
138 modes[current_mode]();
139 }
140 return 0;
141 }
142