1 /*
2  * Copyright (c) 2023 Benjamin Cabé <benjamin@zephyrproject.org>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/device.h>
8 #include <zephyr/devicetree.h>
9 #include <zephyr/drivers/display.h>
10 #include <zephyr/drivers/sensor.h>
11 
12 #include <lvgl.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <zephyr/kernel.h>
16 
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(app, CONFIG_LOG_DEFAULT_LEVEL);
19 
20 static lv_obj_t *chart1;
21 static lv_chart_series_t *ser_x;
22 static lv_chart_series_t *ser_y;
23 static lv_chart_series_t *ser_z;
24 static lv_timer_t *sensor_timer;
25 
26 const struct device *accel_sensor;
27 
28 /* Timer handler: fetches sensor data and appends it to the chart */
sensor_timer_cb(lv_timer_t * timer)29 static void sensor_timer_cb(lv_timer_t *timer)
30 {
31 	struct sensor_value accel[3];
32 	int rc = sensor_sample_fetch(accel_sensor);
33 
34 	if (rc == 0) {
35 		rc = sensor_channel_get(accel_sensor, SENSOR_CHAN_ACCEL_XYZ, accel);
36 	}
37 	if (rc < 0) {
38 		LOG_ERR("ERROR: Update failed: %d\n", rc);
39 		return;
40 	}
41 	lv_chart_set_next_value(chart1, ser_x, sensor_value_to_double(&accel[0]));
42 	lv_chart_set_next_value(chart1, ser_y, sensor_value_to_double(&accel[1]));
43 	lv_chart_set_next_value(chart1, ser_z, sensor_value_to_double(&accel[2]));
44 }
45 
create_accelerometer_chart(lv_obj_t * parent)46 static void create_accelerometer_chart(lv_obj_t *parent)
47 {
48 	chart1 = lv_chart_create(parent);
49 	lv_obj_set_size(chart1, LV_HOR_RES, LV_VER_RES);
50 	lv_chart_set_type(chart1, LV_CHART_TYPE_LINE);
51 	lv_chart_set_div_line_count(chart1, 5, 8);
52 	lv_chart_set_range(chart1, LV_CHART_AXIS_PRIMARY_Y, -20, 20); /* roughly -/+ 2G */
53 	lv_chart_set_update_mode(chart1, LV_CHART_UPDATE_MODE_SHIFT);
54 
55 	ser_x = lv_chart_add_series(chart1, lv_palette_main(LV_PALETTE_RED),
56 				    LV_CHART_AXIS_PRIMARY_Y);
57 	ser_y = lv_chart_add_series(chart1, lv_palette_main(LV_PALETTE_BLUE),
58 				    LV_CHART_AXIS_PRIMARY_Y);
59 	ser_z = lv_chart_add_series(chart1, lv_palette_main(LV_PALETTE_GREEN),
60 				    LV_CHART_AXIS_PRIMARY_Y);
61 
62 	lv_chart_set_point_count(chart1, CONFIG_SAMPLE_CHART_POINTS_PER_SERIES);
63 
64 	/* Do not display point markers on the data */
65 	lv_obj_set_style_size(chart1, 0, 0, LV_PART_INDICATOR);
66 }
67 
main(void)68 int main(void)
69 {
70 	const struct device *display_dev;
71 	int ret;
72 
73 	display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));
74 	if (!device_is_ready(display_dev)) {
75 		LOG_ERR("Device not ready, aborting test");
76 		return -ENODEV;
77 	}
78 
79 	accel_sensor = DEVICE_DT_GET(DT_ALIAS(accel0));
80 	if (!device_is_ready(accel_sensor)) {
81 		LOG_ERR("Device %s is not ready\n", accel_sensor->name);
82 		return -ENODEV;
83 	}
84 
85 	create_accelerometer_chart(lv_screen_active());
86 	sensor_timer = lv_timer_create(sensor_timer_cb,
87 					1000 / CONFIG_SAMPLE_ACCEL_SAMPLING_RATE,
88 					NULL);
89 	lv_timer_handler();
90 	ret = display_blanking_off(display_dev);
91 	if (ret < 0 && ret != -ENOSYS) {
92 		LOG_ERR("Failed to turn blanking off (error %d)", ret);
93 		return 0;
94 	}
95 
96 	while (1) {
97 		uint32_t sleep_ms = lv_timer_handler();
98 
99 		k_msleep(MIN(sleep_ms, INT32_MAX));
100 	}
101 
102 	return 0;
103 }
104