Skip to content

Commit

Permalink
pbio/light/animation: Fix lockup on restarting animation during anima…
Browse files Browse the repository at this point in the history
…tion frame.

Fixes pybricks/support#1295
  • Loading branch information
laurensvalk committed Oct 3, 2024
1 parent a047055 commit 920c812
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 7 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@
loops ([support#1668]).
- Fixed program restarting if the stop button was held to end the program
without an exception ([support#1863]).
- Fixed program lockup when restarting a hub light or light matrix animation
at exact multiples of its animation interval ([support#1295]).

[support#1295]: https://github.com/pybricks/support/issues/1295
[support#1623]: https://github.com/pybricks/support/issues/1623
[support#1661]: https://github.com/pybricks/support/issues/1661
[support#1668]: https://github.com/pybricks/support/issues/1668
Expand Down
19 changes: 12 additions & 7 deletions lib/pbio/src/light/animation.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ void pbio_light_animation_start(pbio_light_animation_t *animation) {
pbio_light_animation_list_head = animation;

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

assert(animation->next_animation != PBIO_LIGHT_ANIMATION_STOPPED);
}
Expand Down Expand Up @@ -117,10 +117,15 @@ PROCESS_THREAD(pbio_light_animation_process, ev, data) {
PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER);
struct etimer *timer = data;
pbio_light_animation_t *animation = PBIO_CONTAINER_OF(timer, pbio_light_animation_t, timer);
clock_time_t interval = animation->next(animation);
if (pbio_light_animation_is_started(animation)) {
etimer_reset_with_new_interval(&animation->timer, interval);

// Like all etimer events, only handle expired etimers. Need this check
// in case the timer was stopped or reset before this event was handled.
if (!etimer_expired(&animation->timer) || !pbio_light_animation_is_started(animation)) {
continue;
}

clock_time_t interval = animation->next(animation);
etimer_reset_with_new_interval(&animation->timer, interval);
}

PROCESS_END();
Expand Down

0 comments on commit 920c812

Please sign in to comment.