diff --git a/lib/pbio/include/pbio/light_animation.h b/lib/pbio/include/pbio/light_animation.h index 643509c26..90bce226f 100644 --- a/lib/pbio/include/pbio/light_animation.h +++ b/lib/pbio/include/pbio/light_animation.h @@ -7,7 +7,8 @@ #include #include -#include +#include +#include typedef struct _pbio_light_animation_t pbio_light_animation_t; @@ -24,17 +25,44 @@ typedef uint32_t (*pbio_light_animation_next_t)(pbio_light_animation_t *animatio struct _pbio_light_animation_t { /** Animation update timer. */ - struct etimer timer; + pbio_os_timer_t timer; /** Animation iterator callback. */ pbio_light_animation_next_t next; /** Linked list */ pbio_light_animation_t *next_animation; }; +#if PBIO_CONFIG_LIGHT + +void pbio_light_animation_init_module(void); void pbio_light_animation_init(pbio_light_animation_t *animation, pbio_light_animation_next_t next); void pbio_light_animation_start(pbio_light_animation_t *animation); void pbio_light_animation_stop(pbio_light_animation_t *animation); void pbio_light_animation_stop_all(void); bool pbio_light_animation_is_started(pbio_light_animation_t *animation); +#else // PBIO_CONFIG_LIGHT + +static inline void pbio_light_animation_init_module(void) { +} + +static inline void pbio_light_animation_init(pbio_light_animation_t *animation, pbio_light_animation_next_t next) { +} + +static inline void pbio_light_animation_start(pbio_light_animation_t *animation) { +} + +static inline void pbio_light_animation_stop(pbio_light_animation_t *animation) { +} + +static inline void pbio_light_animation_stop_all(void) { +} + +static inline bool pbio_light_animation_is_started(pbio_light_animation_t *animation) { + return false; +} + +#endif // PBIO_CONFIG_LIGHT + + #endif // _PBIO_LIGHT_ANIMATION_H_ diff --git a/lib/pbio/src/light/animation.c b/lib/pbio/src/light/animation.c index 980365864..fa7333cb4 100644 --- a/lib/pbio/src/light/animation.c +++ b/lib/pbio/src/light/animation.c @@ -8,11 +8,9 @@ #include #include -#include - -#include - #include +#include +#include /** * This is used as a value for the next_animation field to indicate when an @@ -20,7 +18,6 @@ */ #define PBIO_LIGHT_ANIMATION_STOPPED ((pbio_light_animation_t *)1) -PROCESS(pbio_light_animation_process, "light animation"); static pbio_light_animation_t *pbio_light_animation_list_head; /** @@ -46,14 +43,12 @@ void pbio_light_animation_init(pbio_light_animation_t *animation, pbio_light_ani void pbio_light_animation_start(pbio_light_animation_t *animation) { assert(animation->next_animation == PBIO_LIGHT_ANIMATION_STOPPED); + // Insert at head of active list. animation->next_animation = pbio_light_animation_list_head; pbio_light_animation_list_head = animation; - process_start(&pbio_light_animation_process); // 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); + pbio_os_timer_set(&animation->timer, 0); assert(animation->next_animation != PBIO_LIGHT_ANIMATION_STOPPED); } @@ -69,13 +64,8 @@ void pbio_light_animation_stop(pbio_light_animation_t *animation) { assert(pbio_light_animation_list_head != NULL); assert(animation->next_animation != PBIO_LIGHT_ANIMATION_STOPPED); - etimer_stop(&animation->timer); - if (pbio_light_animation_list_head == animation) { pbio_light_animation_list_head = animation->next_animation; - if (pbio_light_animation_list_head == NULL) { - process_exit(&pbio_light_animation_process); - } } else { for (pbio_light_animation_t *a = pbio_light_animation_list_head; a != NULL; a = a->next_animation) { if (a->next_animation == animation) { @@ -110,20 +100,22 @@ bool pbio_light_animation_is_started(pbio_light_animation_t *animation) { return animation->next_animation != PBIO_LIGHT_ANIMATION_STOPPED; } -PROCESS_THREAD(pbio_light_animation_process, ev, data) { - PROCESS_BEGIN(); +static pbio_error_t pbio_light_animation_process_thread(pbio_os_state_t *state, void *context) { - for (;;) { - PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER && etimer_expired(data)); - struct etimer *timer = data; - pbio_light_animation_t *animation = PBIO_CONTAINER_OF(timer, pbio_light_animation_t, timer); - if (pbio_light_animation_is_started(animation)) { - clock_time_t interval = animation->next(animation); - etimer_reset_with_new_interval(&animation->timer, interval); + for (pbio_light_animation_t *a = pbio_light_animation_list_head; a != NULL; a = a->next_animation) { + if (pbio_os_timer_is_expired(&a->timer)) { + pbio_os_timer_set(&a->timer, a->next(a)); } } - PROCESS_END(); + // This process does not have a state. It is effectively just a poll handler. + return PBIO_ERROR_AGAIN; +} + +void pbio_light_animation_init_module(void) { + + static pbio_os_process_t pbio_light_animation_process; + pbio_os_process_start(&pbio_light_animation_process, pbio_light_animation_process_thread, NULL); } #endif // PBIO_CONFIG_LIGHT diff --git a/lib/pbio/src/main.c b/lib/pbio/src/main.c index a108c2896..b9bfbb5e6 100644 --- a/lib/pbio/src/main.c +++ b/lib/pbio/src/main.c @@ -32,6 +32,7 @@ void pbio_init(bool start_processes) { pbio_battery_init(); pbio_imu_init(); + pbio_light_animation_init_module(); if (!start_processes) { return; diff --git a/lib/pbio/test/src/test_animation.c b/lib/pbio/test/src/test_animation.c index 65e044dce..cf70d4469 100644 --- a/lib/pbio/test/src/test_animation.c +++ b/lib/pbio/test/src/test_animation.c @@ -15,8 +15,6 @@ #define TEST_ANIMATION_TIME 10 -PROCESS_NAME(pbio_light_animation_process); - static uint8_t test_animation_set_hsv_call_count; static uint32_t test_animation_next(pbio_light_animation_t *animation) { @@ -24,36 +22,42 @@ static uint32_t test_animation_next(pbio_light_animation_t *animation) { return TEST_ANIMATION_TIME; } -static PT_THREAD(test_light_animation(struct pt *pt)) { - PT_BEGIN(pt); +#define YIELD(state) \ + do { \ + do_yield_now = 1; \ + PBIO_OS_ASYNC_SET_CHECKPOINT(state); \ + if (do_yield_now) { \ + return PBIO_ERROR_AGAIN; \ + } \ + } while (0) + +static pbio_error_t test_light_animation(pbio_os_state_t *state, void *context) { + PBIO_OS_ASYNC_BEGIN(state); static pbio_light_animation_t test_animation; pbio_light_animation_init(&test_animation, test_animation_next); - // process should not be running yet - tt_want(!process_is_running(&pbio_light_animation_process)); + // animation should not be started yet tt_want(!pbio_light_animation_is_started(&test_animation)); - // starting animation should start process and set a timer at 0ms to call + // starting animation should set a timer at 0ms to call // next() after handling pending events pbio_light_animation_start(&test_animation); tt_want(pbio_light_animation_is_started(&test_animation)); - tt_want(process_is_running(&pbio_light_animation_process)); - pbio_handle_pending_events(); + YIELD(state); tt_want_uint_op(test_animation_set_hsv_call_count, ==, 1); // next() should not be called again until after a delay - pbio_test_clock_tick(TEST_ANIMATION_TIME - 1); - PT_YIELD(pt); + pbio_test_clock_tick(TEST_ANIMATION_TIME - 2); + YIELD(state); tt_want_uint_op(test_animation_set_hsv_call_count, ==, 1); pbio_test_clock_tick(1); - PT_YIELD(pt); + YIELD(state); tt_want_uint_op(test_animation_set_hsv_call_count, ==, 2); - // stopping the animation stops the process + // stopping the animation stops the animation pbio_light_animation_stop(&test_animation); tt_want(!pbio_light_animation_is_started(&test_animation)); - tt_want(!process_is_running(&pbio_light_animation_process)); // exercise multiple animations for code coverage static pbio_light_animation_t test_animation2; @@ -65,27 +69,23 @@ static PT_THREAD(test_light_animation(struct pt *pt)) { pbio_light_animation_stop(&test_animation); tt_want(!pbio_light_animation_is_started(&test_animation)); tt_want(pbio_light_animation_is_started(&test_animation2)); - tt_want(process_is_running(&pbio_light_animation_process)); pbio_light_animation_stop(&test_animation2); tt_want(!pbio_light_animation_is_started(&test_animation)); tt_want(!pbio_light_animation_is_started(&test_animation2)); - tt_want(!process_is_running(&pbio_light_animation_process)); // stopping all animations stops the process pbio_light_animation_start(&test_animation); pbio_light_animation_start(&test_animation2); tt_want(pbio_light_animation_is_started(&test_animation)); tt_want(pbio_light_animation_is_started(&test_animation2)); - tt_want(process_is_running(&pbio_light_animation_process)); pbio_light_animation_stop_all(); tt_want(!pbio_light_animation_is_started(&test_animation)); tt_want(!pbio_light_animation_is_started(&test_animation2)); - tt_want(!process_is_running(&pbio_light_animation_process)); - PT_END(pt); + PBIO_OS_ASYNC_END(PBIO_SUCCESS); } struct testcase_t pbio_light_animation_tests[] = { - PBIO_PT_THREAD_TEST(test_light_animation), + PBIO_PT_THREAD_TEST_WITH_PBIO_OS(test_light_animation), END_OF_TESTCASES };