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.
107114static 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}
237245static 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
254248static 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