~ruther/simple-clock

ref: 2efb21b56ba8335d924100ee52d616e9f94fd9ac simple-clock/source/src/clock_app.rs -rw-r--r-- 4.0 KiB
2efb21b5 — František Boháček feat(src): add calendar freezing possibility 2 years 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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use core::marker::PhantomData;

use alloc::boxed::Box;
use stm32f1xx_hal::rtc::Rtc;

use crate::{
    brightness_manager::BrightnessManager, button::ButtonState,
    clock_display_viewer::{ClockDisplayViewer, DisplayView}, clock_state::ClockState,
};

pub struct ClockApp {
    rtc: Rtc,
    display: ClockDisplayViewer,
    state: ClockState,
    buttons: [Box<dyn ClockButton + Send>; 4],
    brightness: BrightnessManager,
    current_view: DisplayView
}

struct AppState<'a> {
    rtc: &'a mut Rtc,
    display: &'a mut ClockDisplayViewer,
    state: &'a mut ClockState,
    brightness: &'a mut BrightnessManager,
    current_view: &'a mut DisplayView
}

trait ClockButton {
    fn handle(&self, state: ButtonState, state: AppState);
}

struct ButtonSwitchView;
struct ButtonChangeTime;

struct Up;
struct Down;
struct ButtonBrightness<Direction> {
    direction: PhantomData<Direction>,
}

pub enum ClockInterrupt {
    Rtc,
    DisplayTimer,
}

impl ClockApp {
    pub fn new(rtc: Rtc, display: ClockDisplayViewer, state: ClockState) -> Self {
        Self {
            rtc,
            display,
            state,
            current_view: DisplayView::ClockView,
            buttons: [
                Box::new(ButtonSwitchView),
                Box::new(ButtonChangeTime),
                Box::new(ButtonBrightness::<Down> {
                    direction: PhantomData::<Down>,
                }),
                Box::new(ButtonBrightness::<Up> {
                    direction: PhantomData::<Up>,
                }),
            ],
            brightness: BrightnessManager::new(),
        }
    }

    pub fn interrupt(&mut self, interrupt: ClockInterrupt) {
        match interrupt {
            ClockInterrupt::Rtc => {
                self.state.second_elapsed();
                self.rtc.clear_second_flag();
            }
            ClockInterrupt::DisplayTimer => {
                let _ = self.display.update(&self.state);
                self.brightness.update(&self.state);
                self.brightness.apply_brightness(&mut self.display);
            }
        }
    }

    pub fn handle_button(&mut self, index: usize, state: ButtonState) {
        self.buttons[index].handle(
            state,
            AppState {
                rtc: &mut self.rtc,
                display: &mut self.display,
                state: &mut self.state,
                brightness: &mut self.brightness,
                current_view: &mut self.current_view
            },
        );
    }

    pub fn display(&mut self) -> &mut ClockDisplayViewer {
        &mut self.display
    }
}

impl ClockButton for ButtonSwitchView {
    fn handle(&self, state: ButtonState, app: AppState) {
        match state {
            ButtonState::JustPressed => {
                let display = app.display;
                let current_view = *app.current_view as usize;
                let new_view = ((current_view + 1) % core::mem::variant_count::<DisplayView>()).try_into().unwrap();
                display.set_current_view(new_view);
                *app.current_view = new_view;
            }
            _ => (),
        }
    }
}

impl ClockButton for ButtonBrightness<Down> {
    fn handle(&self, state: ButtonState, app: AppState) {
        match state {
            ButtonState::JustPressed => {
                app.brightness
                    .set_brightness(app.brightness.brightness() as i8 - 10);
            }
            _ => (),
        }
    }
}

impl ClockButton for ButtonBrightness<Up> {
    fn handle(&self, state: ButtonState, app: AppState) {
        match state {
            ButtonState::JustPressed => {
                app.brightness
                    .set_brightness(app.brightness.brightness() as i8 + 10);
            }
            _ => (),
        }
    }
}

impl ClockButton for ButtonChangeTime {
    fn handle(&self, state: ButtonState, app: AppState) {
        match state {
            ButtonState::JustPressed => {
                app.rtc.set_time(app.rtc.current_time() + 2);
            }
            _ => (),
        }
    }
}