1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2024 Fabian Blatz <fabianblatz@gmail.com>
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include "step_dir_stepper_timing_source.h"
7 #include "step_dir_stepper_common.h"
8 
stepper_movement_delay(const struct device * dev)9 static k_timeout_t stepper_movement_delay(const struct device *dev)
10 {
11 	const struct step_dir_stepper_common_data *data = dev->data;
12 
13 	if (data->microstep_interval_ns == 0) {
14 		return K_FOREVER;
15 	}
16 
17 	return K_NSEC(data->microstep_interval_ns);
18 }
19 
stepper_work_step_handler(struct k_work * work)20 static void stepper_work_step_handler(struct k_work *work)
21 {
22 	struct k_work_delayable *dwork = k_work_delayable_from_work(work);
23 	struct step_dir_stepper_common_data *data =
24 		CONTAINER_OF(dwork, struct step_dir_stepper_common_data, stepper_dwork);
25 
26 	stepper_handle_timing_signal(data->dev);
27 }
28 
step_work_timing_source_init(const struct device * dev)29 int step_work_timing_source_init(const struct device *dev)
30 {
31 	struct step_dir_stepper_common_data *data = dev->data;
32 
33 	k_work_init_delayable(&data->stepper_dwork, stepper_work_step_handler);
34 
35 	return 0;
36 }
37 
step_work_timing_source_update(const struct device * dev,const uint64_t microstep_interval_ns)38 int step_work_timing_source_update(const struct device *dev, const uint64_t microstep_interval_ns)
39 {
40 	ARG_UNUSED(dev);
41 	ARG_UNUSED(microstep_interval_ns);
42 	return 0;
43 }
44 
step_work_timing_source_start(const struct device * dev)45 int step_work_timing_source_start(const struct device *dev)
46 {
47 	struct step_dir_stepper_common_data *data = dev->data;
48 
49 	return k_work_reschedule(&data->stepper_dwork, stepper_movement_delay(dev));
50 }
51 
step_work_timing_source_stop(const struct device * dev)52 int step_work_timing_source_stop(const struct device *dev)
53 {
54 	struct step_dir_stepper_common_data *data = dev->data;
55 
56 	return k_work_cancel_delayable(&data->stepper_dwork);
57 }
58 
step_work_timing_source_needs_reschedule(const struct device * dev)59 bool step_work_timing_source_needs_reschedule(const struct device *dev)
60 {
61 	ARG_UNUSED(dev);
62 	return true;
63 }
64 
step_work_timing_source_is_running(const struct device * dev)65 bool step_work_timing_source_is_running(const struct device *dev)
66 {
67 	struct step_dir_stepper_common_data *data = dev->data;
68 
69 	return k_work_delayable_is_pending(&data->stepper_dwork);
70 }
71 
72 const struct stepper_timing_source_api step_work_timing_source_api = {
73 	.init = step_work_timing_source_init,
74 	.update = step_work_timing_source_update,
75 	.start = step_work_timing_source_start,
76 	.needs_reschedule = step_work_timing_source_needs_reschedule,
77 	.stop = step_work_timing_source_stop,
78 	.is_running = step_work_timing_source_is_running,
79 };
80