~ruther/map-led-strip

ref: d8e7cb5329e8290f34eed57b5ff3037350ea273e map-led-strip/src/animations/animation_manager.rs -rw-r--r-- 1.9 KiB
d8e7cb53 — František Boháček fix: do not call apply on animation after last step 1 year, 9 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use embedded_hal::timer::CountDown;
use fugit::MicrosDurationU64;
use nb::Error::{Other, WouldBlock};
use crate::animations::animation::{Animation, AnimationError};
use crate::animations::animation_storage::AnimationStorage;
use crate::map::Map;

pub struct AnimationManager<Timer> {
    timer: Timer,
    storage: AnimationStorage,
}

impl<Timer: CountDown<Time=MicrosDurationU64>> AnimationManager<Timer> {
    pub fn new(timer: Timer) -> Self {
        Self {
            timer,
            storage: AnimationStorage::new(),
        }
    }

    pub fn storage(&mut self) -> &mut AnimationStorage {
        &mut self.storage
    }

    pub fn update(&mut self, map: &mut Map) -> nb::Result<(), AnimationError> {
        let step_result;
        {
            let mut animation = if let Some(animation) = self.storage.animation() {
                animation
            } else { // animation is not set, no job to do
                return Ok(());
            };

            let mut timer_ran_off = false;
            if animation.is_started() {
                timer_ran_off = match self.timer.wait() {
                    Err(_) => return Err(WouldBlock),
                    _ => true // timer has reached next step
                };
            }

            step_result = if !animation.is_started() || timer_ran_off {
                animation.next()
            } else {
                return Err(WouldBlock);
            };

            if !step_result.is_err() {
                animation.apply(map)?;
            }
        }

        let step = match step_result {
            Ok(step) => step,
            Err(err) if err == AnimationError::LastStep => {
                self.storage.remove_animation();
                return Ok(());
            }
            Err(err) => {
                return Err(Other(err));
            }
        };

        self.timer.start(step.duration());
        Ok(())
    }
}
Do not follow this link