Skip to content

Commit b7d7703

Browse files
committed
pybricks.robotics.DriveBase: Use new awaitable.
1 parent 54a72fa commit b7d7703

File tree

1 file changed

+28
-34
lines changed

1 file changed

+28
-34
lines changed

pybricks/robotics/pb_type_drivebase.c

Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include <pybricks/parameters.h>
1818
#include <pybricks/robotics.h>
1919
#include <pybricks/tools.h>
20-
#include <pybricks/tools/pb_type_awaitable.h>
20+
#include <pybricks/tools/pb_type_async.h>
2121

2222
#include <pybricks/util_mp/pb_kwarg_helper.h>
2323
#include <pybricks/util_mp/pb_obj_helper.h>
@@ -33,7 +33,7 @@ struct _pb_type_DriveBase_obj_t {
3333
mp_obj_t heading_control;
3434
mp_obj_t distance_control;
3535
#endif
36-
mp_obj_t awaitables;
36+
pb_type_async_t *last_awaitable;
3737
};
3838

3939
// pybricks.robotics.DriveBase.reset
@@ -78,41 +78,49 @@ static mp_obj_t pb_type_DriveBase_make_new(const mp_obj_type_t *type, size_t n_a
7878
self->distance_control = pb_type_Control_obj_make_new(&self->db->control_distance);
7979
#endif
8080

81-
// List of awaitables associated with this drivebase. By keeping track,
82-
// we can cancel them as needed when a new movement is started.
83-
self->awaitables = mp_obj_new_list(0, NULL);
81+
self->last_awaitable = NULL;
8482

8583
return MP_OBJ_FROM_PTR(self);
8684
}
8785

88-
static bool pb_type_DriveBase_test_completion(mp_obj_t self_in, uint32_t end_time) {
89-
90-
pb_type_DriveBase_obj_t *self = MP_OBJ_TO_PTR(self_in);
86+
static pbio_error_t pb_type_drivebase_iterate_once(pbio_os_state_t *state, mp_obj_t parent_obj) {
87+
pb_type_DriveBase_obj_t *self = MP_OBJ_TO_PTR(parent_obj);
9188

9289
// Handle I/O exceptions like port unplugged.
9390
if (!pbio_drivebase_update_loop_is_running(self->db)) {
9491
pb_assert(PBIO_ERROR_NO_DEV);
9592
}
9693

9794
// Get completion state.
98-
return pbio_drivebase_is_done(self->db);
95+
return pbio_drivebase_is_done(self->db) ? PBIO_SUCCESS : PBIO_ERROR_AGAIN;
9996
}
10097

101-
static void pb_type_DriveBase_cancel(mp_obj_t self_in) {
98+
// pybricks.robotics.DriveBase.stop
99+
static mp_obj_t pb_type_DriveBase_stop(mp_obj_t self_in) {
100+
101+
// Cancel awaitables.
102102
pb_type_DriveBase_obj_t *self = MP_OBJ_TO_PTR(self_in);
103+
pb_type_async_schedule_cancel(self->last_awaitable);
104+
105+
// Stop hardware.
103106
pb_assert(pbio_drivebase_stop(self->db, PBIO_CONTROL_ON_COMPLETION_COAST));
107+
108+
return mp_const_none;
104109
}
110+
MP_DEFINE_CONST_FUN_OBJ_1(pb_type_DriveBase_stop_obj, pb_type_DriveBase_stop);
111+
105112

106113
// All drive base methods use the same kind of completion awaitable.
107114
static mp_obj_t await_or_wait(pb_type_DriveBase_obj_t *self) {
108-
return pb_type_awaitable_await_or_wait(
109-
MP_OBJ_FROM_PTR(self),
110-
self->awaitables,
111-
pb_type_awaitable_end_time_none,
112-
pb_type_DriveBase_test_completion,
113-
pb_type_awaitable_return_none,
114-
pb_type_DriveBase_cancel,
115-
PB_TYPE_AWAITABLE_OPT_CANCEL_ALL);
115+
116+
pb_type_async_t config = {
117+
.parent_obj = MP_OBJ_FROM_PTR(self),
118+
.iter_once = pb_type_drivebase_iterate_once,
119+
.close = pb_type_DriveBase_stop,
120+
};
121+
// New operation always wins; ongoing awaitable motion is cancelled.
122+
pb_type_async_schedule_cancel(self->last_awaitable);
123+
return pb_type_async_wait_or_await(&config, &self->last_awaitable);
116124
}
117125

118126
// pybricks.robotics.DriveBase.straight
@@ -229,33 +237,19 @@ static mp_obj_t pb_type_DriveBase_drive(size_t n_args, const mp_obj_t *pos_args,
229237
mp_int_t turn_rate = pb_obj_get_int(turn_rate_in);
230238

231239
// Cancel awaitables but not hardware. Drive forever will handle this.
232-
pb_type_awaitable_update_all(self->awaitables, PB_TYPE_AWAITABLE_OPT_CANCEL_ALL);
240+
pb_type_async_schedule_cancel(self->last_awaitable);
233241

234242
pb_assert(pbio_drivebase_drive_forever(self->db, speed, turn_rate));
235243
return mp_const_none;
236244
}
237245
static MP_DEFINE_CONST_FUN_OBJ_KW(pb_type_DriveBase_drive_obj, 1, pb_type_DriveBase_drive);
238246

239-
// pybricks.robotics.DriveBase.stop
240-
static mp_obj_t pb_type_DriveBase_stop(mp_obj_t self_in) {
241-
242-
// Cancel awaitables.
243-
pb_type_DriveBase_obj_t *self = MP_OBJ_TO_PTR(self_in);
244-
pb_type_awaitable_update_all(self->awaitables, PB_TYPE_AWAITABLE_OPT_CANCEL_ALL);
245-
246-
// Stop hardware.
247-
pb_type_DriveBase_cancel(self_in);
248-
249-
return mp_const_none;
250-
}
251-
MP_DEFINE_CONST_FUN_OBJ_1(pb_type_DriveBase_stop_obj, pb_type_DriveBase_stop);
252-
253247
// pybricks.robotics.DriveBase.brake
254248
static mp_obj_t pb_type_DriveBase_brake(mp_obj_t self_in) {
255249

256250
// Cancel awaitables.
257251
pb_type_DriveBase_obj_t *self = MP_OBJ_TO_PTR(self_in);
258-
pb_type_awaitable_update_all(self->awaitables, PB_TYPE_AWAITABLE_OPT_CANCEL_ALL);
252+
pb_type_async_schedule_cancel(self->last_awaitable);
259253

260254
// Stop hardware.
261255
pb_assert(pbio_drivebase_stop(self->db, PBIO_CONTROL_ON_COMPLETION_BRAKE));

0 commit comments

Comments
 (0)