1 /*
2 * Copyright 2024 Navimatix GmbH
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/drivers/gpio.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/ztest_assert.h>
10 #include <stdbool.h>
11 #include <stdint.h>
12 #include <zephyr/ztest.h>
13 #include <zephyr/drivers/stepper.h>
14
15 struct drv84xx_api_fixture {
16 const struct device *dev;
17 stepper_event_callback_t callback;
18 };
19
20 struct k_poll_signal stepper_signal;
21 struct k_poll_event stepper_event;
22
drv84xx_api_print_event_callback(const struct device * dev,enum stepper_event event,void * dummy)23 static void drv84xx_api_print_event_callback(const struct device *dev, enum stepper_event event,
24 void *dummy)
25 {
26 switch (event) {
27 case STEPPER_EVENT_STEPS_COMPLETED:
28 k_poll_signal_raise(&stepper_signal, STEPPER_EVENT_STEPS_COMPLETED);
29 break;
30 case STEPPER_EVENT_LEFT_END_STOP_DETECTED:
31 k_poll_signal_raise(&stepper_signal, STEPPER_EVENT_LEFT_END_STOP_DETECTED);
32 break;
33 case STEPPER_EVENT_RIGHT_END_STOP_DETECTED:
34 k_poll_signal_raise(&stepper_signal, STEPPER_EVENT_RIGHT_END_STOP_DETECTED);
35 break;
36 case STEPPER_EVENT_STALL_DETECTED:
37 k_poll_signal_raise(&stepper_signal, STEPPER_EVENT_STALL_DETECTED);
38 break;
39 default:
40 break;
41 }
42 }
43
drv84xx_api_setup(void)44 static void *drv84xx_api_setup(void)
45 {
46 static struct drv84xx_api_fixture fixture = {
47 .dev = DEVICE_DT_GET(DT_ALIAS(stepper)),
48 .callback = drv84xx_api_print_event_callback,
49 };
50
51 k_poll_signal_init(&stepper_signal);
52 k_poll_event_init(&stepper_event, K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY,
53 &stepper_signal);
54
55 zassert_not_null(fixture.dev);
56 return &fixture;
57 }
58
drv84xx_api_before(void * f)59 static void drv84xx_api_before(void *f)
60 {
61 struct drv84xx_api_fixture *fixture = f;
62 (void)stepper_set_reference_position(fixture->dev, 0);
63 (void)stepper_set_micro_step_res(fixture->dev, 1);
64 k_poll_signal_reset(&stepper_signal);
65 }
66
drv84xx_api_after(void * f)67 static void drv84xx_api_after(void *f)
68 {
69 struct drv84xx_api_fixture *fixture = f;
70 (void)stepper_disable(fixture->dev);
71 }
72
ZTEST_F(drv84xx_api,test_micro_step_res_set)73 ZTEST_F(drv84xx_api, test_micro_step_res_set)
74 {
75 (void)stepper_set_micro_step_res(fixture->dev, 4);
76 enum stepper_micro_step_resolution res;
77 (void)stepper_get_micro_step_res(fixture->dev, &res);
78 zassert_equal(res, 4, "Micro step resolution not set correctly, should be %d but is %d", 4,
79 res);
80 }
81
ZTEST_F(drv84xx_api,test_actual_position_set)82 ZTEST_F(drv84xx_api, test_actual_position_set)
83 {
84 int32_t pos = 100u;
85 (void)stepper_set_reference_position(fixture->dev, pos);
86 (void)stepper_get_actual_position(fixture->dev, &pos);
87 zassert_equal(pos, 100u, "Actual position should be %u but is %u", 100u, pos);
88 }
89
ZTEST_F(drv84xx_api,test_move_to_positive_direction_movement)90 ZTEST_F(drv84xx_api, test_move_to_positive_direction_movement)
91 {
92 int32_t pos = 50;
93
94 (void)stepper_enable(fixture->dev);
95 (void)stepper_set_microstep_interval(fixture->dev, 20000000);
96 (void)stepper_set_event_callback(fixture->dev, fixture->callback, NULL);
97 (void)stepper_move_to(fixture->dev, pos);
98 (void)k_poll(&stepper_event, 1, K_SECONDS(5));
99 unsigned int signaled;
100 int result;
101
102 k_poll_signal_check(&stepper_signal, &signaled, &result);
103 zassert_equal(signaled, 1, "No event detected");
104 zassert_equal(result, STEPPER_EVENT_STEPS_COMPLETED,
105 "Event was not STEPPER_EVENT_STEPS_COMPLETED event");
106 (void)stepper_get_actual_position(fixture->dev, &pos);
107 zassert_equal(pos, 50u, "Target position should be %d but is %d", 50u, pos);
108 }
109
ZTEST_F(drv84xx_api,test_move_to_negative_direction_movement)110 ZTEST_F(drv84xx_api, test_move_to_negative_direction_movement)
111 {
112 int32_t pos = -50;
113
114 (void)stepper_enable(fixture->dev);
115 (void)stepper_set_microstep_interval(fixture->dev, 20000000);
116 (void)stepper_set_event_callback(fixture->dev, fixture->callback, NULL);
117 (void)stepper_move_to(fixture->dev, pos);
118 (void)k_poll(&stepper_event, 1, K_SECONDS(5));
119 unsigned int signaled;
120 int result;
121
122 k_poll_signal_check(&stepper_signal, &signaled, &result);
123 zassert_equal(signaled, 1, "No event detected");
124 zassert_equal(result, STEPPER_EVENT_STEPS_COMPLETED,
125 "Event was not STEPPER_EVENT_STEPS_COMPLETED event");
126 (void)stepper_get_actual_position(fixture->dev, &pos);
127 zassert_equal(pos, -50, "Target position should be %d but is %d", -50, pos);
128 }
129
ZTEST_F(drv84xx_api,test_move_to_identical_current_and_target_position)130 ZTEST_F(drv84xx_api, test_move_to_identical_current_and_target_position)
131 {
132 int32_t pos = 0;
133
134 (void)stepper_enable(fixture->dev);
135 (void)stepper_set_microstep_interval(fixture->dev, 20000000);
136 (void)stepper_set_event_callback(fixture->dev, fixture->callback, NULL);
137 (void)stepper_move_to(fixture->dev, pos);
138 (void)k_poll(&stepper_event, 1, K_SECONDS(5));
139 unsigned int signaled;
140 int result;
141
142 k_poll_signal_check(&stepper_signal, &signaled, &result);
143 zassert_equal(signaled, 1, "No event detected");
144 zassert_equal(result, STEPPER_EVENT_STEPS_COMPLETED,
145 "Event was not STEPPER_EVENT_STEPS_COMPLETED event");
146 (void)stepper_get_actual_position(fixture->dev, &pos);
147 zassert_equal(pos, 0, "Target position should not have changed from %d but is %d", 0, pos);
148 }
149
ZTEST_F(drv84xx_api,test_move_to_is_moving_true_while_moving)150 ZTEST_F(drv84xx_api, test_move_to_is_moving_true_while_moving)
151 {
152 int32_t pos = 50;
153 bool moving = false;
154
155 (void)stepper_enable(fixture->dev);
156 (void)stepper_set_microstep_interval(fixture->dev, 20000000);
157 (void)stepper_set_event_callback(fixture->dev, fixture->callback, NULL);
158 (void)stepper_move_to(fixture->dev, pos);
159 (void)stepper_is_moving(fixture->dev, &moving);
160 zassert_true(moving, "Driver should be in state is_moving while moving");
161 }
162
ZTEST_F(drv84xx_api,test_move_to_is_moving_false_when_completed)163 ZTEST_F(drv84xx_api, test_move_to_is_moving_false_when_completed)
164 {
165 int32_t pos = 50;
166 bool moving = false;
167
168 (void)stepper_enable(fixture->dev);
169 (void)stepper_set_microstep_interval(fixture->dev, 20000000);
170 (void)stepper_set_event_callback(fixture->dev, fixture->callback, NULL);
171 (void)stepper_move_to(fixture->dev, pos);
172 (void)k_poll(&stepper_event, 1, K_SECONDS(5));
173 unsigned int signaled;
174 int result;
175
176 k_poll_signal_check(&stepper_signal, &signaled, &result);
177 zassert_equal(signaled, 1, "No event detected");
178 zassert_equal(result, STEPPER_EVENT_STEPS_COMPLETED,
179 "Event was not STEPPER_EVENT_STEPS_COMPLETED event");
180 (void)stepper_is_moving(fixture->dev, &moving);
181 zassert_false(moving, "Driver should not be in state is_moving after finishing");
182 }
183
ZTEST_F(drv84xx_api,test_move_by_zero_steps_no_movement)184 ZTEST_F(drv84xx_api, test_move_by_zero_steps_no_movement)
185 {
186 int32_t steps = 0;
187
188 (void)stepper_enable(fixture->dev);
189 (void)stepper_set_microstep_interval(fixture->dev, 20000000);
190 (void)stepper_set_event_callback(fixture->dev, fixture->callback, NULL);
191 (void)stepper_move_by(fixture->dev, steps);
192 (void)k_poll(&stepper_event, 1, K_SECONDS(5));
193 unsigned int signaled;
194 int result;
195
196 k_poll_signal_check(&stepper_signal, &signaled, &result);
197 zassert_equal(signaled, 1, "No event detected");
198 zassert_equal(result, STEPPER_EVENT_STEPS_COMPLETED,
199 "Event was not STEPPER_EVENT_STEPS_COMPLETED event");
200 (void)stepper_get_actual_position(fixture->dev, &steps);
201 zassert_equal(steps, 0, "Target position should be %d but is %d", 0, steps);
202 }
203
ZTEST_F(drv84xx_api,test_move_by_is_moving_true_while_moving)204 ZTEST_F(drv84xx_api, test_move_by_is_moving_true_while_moving)
205 {
206 int32_t steps = 50;
207 bool moving = false;
208
209 (void)stepper_enable(fixture->dev);
210 (void)stepper_set_microstep_interval(fixture->dev, 20000000);
211 (void)stepper_set_event_callback(fixture->dev, fixture->callback, NULL);
212 (void)stepper_move_by(fixture->dev, steps);
213 (void)stepper_is_moving(fixture->dev, &moving);
214 zassert_true(moving, "Driver should be in state is_moving");
215 }
216
ZTEST_F(drv84xx_api,test_move_by_is_moving_false_when_completed)217 ZTEST_F(drv84xx_api, test_move_by_is_moving_false_when_completed)
218 {
219 int32_t steps = 50;
220 bool moving = true;
221
222 (void)stepper_enable(fixture->dev);
223 (void)stepper_set_microstep_interval(fixture->dev, 20000000);
224 (void)stepper_set_event_callback(fixture->dev, fixture->callback, NULL);
225 (void)stepper_move_by(fixture->dev, steps);
226 (void)k_poll(&stepper_event, 1, K_SECONDS(5));
227 unsigned int signaled;
228 int result;
229
230 k_poll_signal_check(&stepper_signal, &signaled, &result);
231 zassert_equal(signaled, 1, "No event detected");
232 zassert_equal(result, STEPPER_EVENT_STEPS_COMPLETED,
233 "Event was not STEPPER_EVENT_STEPS_COMPLETED event");
234 (void)stepper_is_moving(fixture->dev, &moving);
235 zassert_false(moving, "Driver should not be in state is_moving after completion");
236 }
237
ZTEST_F(drv84xx_api,test_run_positive_direction_correct_position)238 ZTEST_F(drv84xx_api, test_run_positive_direction_correct_position)
239 {
240 uint64_t step_interval = 20000000;
241 int32_t steps = 0;
242
243 (void)stepper_enable(fixture->dev);
244 (void)stepper_set_microstep_interval(fixture->dev, step_interval);
245 (void)stepper_run(fixture->dev, STEPPER_DIRECTION_POSITIVE);
246 k_busy_wait(110000);
247
248 (void)stepper_get_actual_position(fixture->dev, &steps);
249 zassert_true(IN_RANGE(steps, 4, 6), "Current position should be between 4 and 6 but is %d",
250 steps);
251 }
252
ZTEST_F(drv84xx_api,test_run_negative_direction_correct_position)253 ZTEST_F(drv84xx_api, test_run_negative_direction_correct_position)
254 {
255 uint64_t step_interval = 20000000;
256 int32_t steps = 0;
257
258 (void)stepper_enable(fixture->dev);
259 (void)stepper_set_microstep_interval(fixture->dev, step_interval);
260 (void)stepper_run(fixture->dev, STEPPER_DIRECTION_NEGATIVE);
261 k_busy_wait(110000);
262
263 (void)stepper_get_actual_position(fixture->dev, &steps);
264 zassert_true(IN_RANGE(steps, -6, 4),
265 "Current position should be between -6 and -4 but is %d", steps);
266 }
267
ZTEST_F(drv84xx_api,test_run_zero_step_interval_correct_position)268 ZTEST_F(drv84xx_api, test_run_zero_step_interval_correct_position)
269 {
270 uint64_t step_interval = 0;
271 int32_t steps = 0;
272
273 (void)stepper_enable(fixture->dev);
274 (void)stepper_set_microstep_interval(fixture->dev, step_interval);
275 (void)stepper_run(fixture->dev, STEPPER_DIRECTION_POSITIVE);
276 k_msleep(100);
277
278 zassert_equal(steps, 0, "Current position should not have changed from %d but is %d", 0,
279 steps);
280 }
281
ZTEST_F(drv84xx_api,test_run_is_moving_true_when_step_interval_greater_zero)282 ZTEST_F(drv84xx_api, test_run_is_moving_true_when_step_interval_greater_zero)
283 {
284 uint64_t step_interval = 20000000;
285 bool moving = false;
286
287 (void)stepper_enable(fixture->dev);
288 (void)stepper_set_microstep_interval(fixture->dev, step_interval);
289 (void)stepper_run(fixture->dev, STEPPER_DIRECTION_POSITIVE);
290 (void)stepper_is_moving(fixture->dev, &moving);
291 zassert_true(moving, "Driver should be in state is_moving");
292 (void)stepper_disable(fixture->dev);
293 }
294
295 ZTEST_SUITE(drv84xx_api, NULL, drv84xx_api_setup, drv84xx_api_before, drv84xx_api_after, NULL);
296