Skip to content

Commit 920c812

Browse files
committed
pbio/light/animation: Fix lockup on restarting animation during animation frame.
Fixes pybricks/support#1295
1 parent a047055 commit 920c812

File tree

2 files changed

+15
-7
lines changed

2 files changed

+15
-7
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@
2424
loops ([support#1668]).
2525
- Fixed program restarting if the stop button was held to end the program
2626
without an exception ([support#1863]).
27+
- Fixed program lockup when restarting a hub light or light matrix animation
28+
at exact multiples of its animation interval ([support#1295]).
2729

30+
[support#1295]: https://github.com/pybricks/support/issues/1295
2831
[support#1623]: https://github.com/pybricks/support/issues/1623
2932
[support#1661]: https://github.com/pybricks/support/issues/1661
3033
[support#1668]: https://github.com/pybricks/support/issues/1668

lib/pbio/src/light/animation.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@ void pbio_light_animation_start(pbio_light_animation_t *animation) {
5050
pbio_light_animation_list_head = animation;
5151

5252
process_start(&pbio_light_animation_process);
53-
// HACK: init timer since we don't call etimer_set()
54-
timer_set(&animation->timer.timer, 0);
55-
// fake a timer event to load the first cell and start the timer
56-
process_post_synch(&pbio_light_animation_process, PROCESS_EVENT_TIMER, &animation->timer);
53+
// Fake a timer event to load the first cell.
54+
PROCESS_CONTEXT_BEGIN(&pbio_light_animation_process);
55+
etimer_set(&animation->timer, 0);
56+
PROCESS_CONTEXT_END(&pbio_light_animation_process);
5757

5858
assert(animation->next_animation != PBIO_LIGHT_ANIMATION_STOPPED);
5959
}
@@ -117,10 +117,15 @@ PROCESS_THREAD(pbio_light_animation_process, ev, data) {
117117
PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER);
118118
struct etimer *timer = data;
119119
pbio_light_animation_t *animation = PBIO_CONTAINER_OF(timer, pbio_light_animation_t, timer);
120-
clock_time_t interval = animation->next(animation);
121-
if (pbio_light_animation_is_started(animation)) {
122-
etimer_reset_with_new_interval(&animation->timer, interval);
120+
121+
// Like all etimer events, only handle expired etimers. Need this check
122+
// in case the timer was stopped or reset before this event was handled.
123+
if (!etimer_expired(&animation->timer) || !pbio_light_animation_is_started(animation)) {
124+
continue;
123125
}
126+
127+
clock_time_t interval = animation->next(animation);
128+
etimer_reset_with_new_interval(&animation->timer, interval);
124129
}
125130

126131
PROCESS_END();

0 commit comments

Comments
 (0)