#include #include #include void animation_reset(struct animation *ani) { if (!ani) return; ani->state = ANI_RED; ani->step = 0u; ani->last_tick = systick_get_global_tick(); ani->next_interval = 0ul; } static void clear_dmx_universe(uint8_t *universe, uint32_t len) { uint32_t idx; for (idx = 0; idx < len; idx++) { universe[idx] = 0u; } } static enum animation_state next_col_state(enum animation_state current) { enum animation_state next; switch (current) { case ANI_RED: next = ANI_GREEN; break; case ANI_GREEN: next = ANI_BLUE; break; case ANI_BLUE: next = ANI_RAINBOW; break; default: next = ANI_RED; break; } return next; } void animation_process(struct animation *ani, uint8_t *dmx_universe) { uint32_t tick; uint32_t new_tick; uint32_t i; if (!ani || !dmx_universe) return; /* Check if time for next step is reached */ tick = systick_get_global_tick(); /* Calculate next tick. Overflow expected */ new_tick = ani->last_tick + ani->next_interval; if (new_tick < ani->last_tick) { /* Tick overflowed. */ if (!(tick >= new_tick && tick < ani->last_tick)) return; } else { if (tick < new_tick) return; } ani->last_tick = tick; switch (ani->state) { case ANI_RED: case ANI_GREEN: case ANI_BLUE: for (i = 0; i < 32; i++) { dmx_universe[i * 4 + 0] = ani->state == ANI_RED ? (uint8_t)ani->step : 0u; dmx_universe[i * 4 + 1] = ani->state == ANI_GREEN ? (uint8_t)ani->step : 0u; dmx_universe[i * 4 + 2] = ani->state == ANI_BLUE ? (uint8_t)ani->step : 0u; dmx_universe[i * 4 + 3] = 0u; } if (ani->step + 10 > 0xFFul) { ani->step = 0; ani->state = next_col_state(ani->state); } else { ani->step += 10; } ani->next_interval = 20; break; case ANI_RAINBOW: /* TODO: Implement Rainbow mode */ ani->next_interval = 10; clear_dmx_universe(dmx_universe, 129u); ani->state = ANI_FLASH_WHITE; break; case ANI_FLASH_WHITE: dmx_universe[128] = ani->step & 1 ? 0xFF : 0; ani->next_interval = ani->step & 1 ? 60 : 260; ani->step += 1u; if (ani->step >= 11u) { ani->state = ANI_RED; ani->step = 0u; } break; } }