~ruther/simple-clock

ref: 2960f7a05ffe247364fe4605d630298fa57117be simple-clock/source/src/lib.rs -rw-r--r-- 4.8 KiB
2960f7a0 — František Boháček feat(src): add clock edit mode 1 year, 8 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
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
#![cfg_attr(test, no_main)]
#![no_std]
#![feature(variant_count)]
#![feature(adt_const_params)]

use defmt_rtt as _; // global logger

use embedded_alloc::Heap;

use panic_probe as _;

pub mod brightness_manager;
pub mod button;
pub mod calendar;
pub mod clock_app;
pub mod clock_display;
pub mod clock_display_viewer;
pub mod clock_state;
pub mod count_down;
pub mod display;
pub mod linear_interpolation;
pub mod mono_timer;
pub mod number_digits;
pub mod seven_segments;
pub mod app_mode;

extern crate alloc;

#[global_allocator]
static HEAP: Heap = Heap::empty();

// same panicking *behavior* as `panic-probe` but doesn't print a panic message
// this prevents the panic message being printed *twice* when `defmt::panic` is invoked
#[defmt::panic_handler]
fn panic() -> ! {
    cortex_m::asm::udf()
}

/// Terminates the application and makes `probe-run` exit with exit-code = 0
pub fn exit() -> ! {
    loop {
        cortex_m::asm::bkpt();
    }
}

#[cfg(test)]
#[defmt_test::tests]
mod unit_tests {
    use crate::{
        calendar::Calendar,
        linear_interpolation::{LinearInterpolation, Point},
    };
    use defmt::assert_eq;

    #[init]
    fn init() {
        use core::mem::MaybeUninit;
        const HEAP_SIZE: usize = 512;
        static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
        unsafe { crate::HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) }
    }

    #[test]
    fn interpolation() {
        let li = LinearInterpolation::new(alloc::vec![
            Point::new(0, 0xFFFF - 12000),
            Point::new(100, 0xFFFF - 3000),
        ]);

        assert_eq!(li.interpolate(0).unwrap(), 0xFFFF - 12000);
        assert_eq!(li.interpolate(50).unwrap(), 0xFFFF - 7500);
        assert_eq!(li.interpolate(90).unwrap(), 0xFFFF - 3000 - 900);
        assert_eq!(li.interpolate(100).unwrap(), 0xFFFF - 3000);
    }

    #[test]
    fn calendar_to_leap_year() {
        let base = Calendar::new(0, 0, 0, 1, 1, 2023);
        let end_of_leap_year = Calendar::with_base_year(2023, 0, 0, 0, 31, 12, 2024);
        let end_of_leap_year_ticks = end_of_leap_year.to_ticks();
        assert_eq!(end_of_leap_year_ticks, (365 + 365) * 24 * 60 * 60);
        let end_of_leap_year_from_ticks =
            Calendar::from_ticks(base.clone(), end_of_leap_year_ticks);
        assert_eq!(end_of_leap_year_from_ticks.day(), 31);
        assert_eq!(end_of_leap_year_from_ticks.month(), 12);
        assert_eq!(end_of_leap_year_from_ticks.year(), 2024);
        assert_eq!(end_of_leap_year_from_ticks.hours(), 0);
        assert_eq!(end_of_leap_year_from_ticks.minutes(), 0);
        assert_eq!(end_of_leap_year_from_ticks.seconds(), 0);
    }

    #[test]
    fn calendar_past_leap_year() {
        let base = Calendar::new(0, 0, 0, 1, 1, 2023);
        let end_of_leap_year = Calendar::with_base_year(2023, 0, 0, 0, 31, 12, 2025);
        let end_of_leap_year_ticks = end_of_leap_year.to_ticks();
        assert_eq!(end_of_leap_year_ticks, (365 + 366 + 364) * 24 * 60 * 60);
        let end_of_leap_year_from_ticks =
            Calendar::from_ticks(base.clone(), end_of_leap_year_ticks);
        assert_eq!(end_of_leap_year_from_ticks.day(), 31);
        assert_eq!(end_of_leap_year_from_ticks.month(), 12);
        assert_eq!(end_of_leap_year_from_ticks.year(), 2025);
        assert_eq!(end_of_leap_year_from_ticks.hours(), 0);
        assert_eq!(end_of_leap_year_from_ticks.minutes(), 0);
        assert_eq!(end_of_leap_year_from_ticks.seconds(), 0);
    }

    #[test]
    fn calendar_basic_ticks() {
        let base = Calendar::new(0, 0, 0, 1, 1, 2023);
        assert_eq!(base.to_ticks(), 0);
        assert_eq!(Calendar::from_ticks(base.clone(), 0).to_ticks(), 0);
        assert_eq!(Calendar::from_ticks(base.clone(), 120).to_ticks(), 120);

        let two_days = Calendar::from_ticks(base.clone(), 2 * 24 * 60 * 60);
        assert_eq!(two_days.month(), 1);
        assert_eq!(two_days.year(), 2023);
        assert_eq!(two_days.day(), 3);
        assert_eq!(two_days.to_ticks(), 2 * 24 * 60 * 60);

        let one_month = Calendar::from_ticks(base.clone(), 31 * 24 * 60 * 60);
        assert_eq!(one_month.day(), 1);
        assert_eq!(one_month.month(), 2);
        assert_eq!(one_month.year(), 2023);
        assert_eq!(one_month.hours(), 0);
        assert_eq!(one_month.minutes(), 0);
        assert_eq!(one_month.seconds(), 0);
        assert_eq!(one_month.to_ticks(), 31 * 24 * 60 * 60);

        assert_eq!(
            Calendar::from_ticks(base.clone(), (31 + 28) * 24 * 60 * 60).to_ticks(),
            (31 + 28) * 24 * 60 * 60
        );
        assert_eq!(
            Calendar::from_ticks(base.clone(), 13423544).to_ticks(),
            13423544
        );
        assert_eq!(
            Calendar::from_ticks(base.clone(), 315360000).to_ticks(),
            315360000
        );
    }
}
Do not follow this link