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
/// Représente le niveau de charge de la batterie, avec des variantes allant de "Empty" (vide) à "Full" (plein).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum BatteryCharge {
Empty = 0, // 0% - Batterie vide. Pas super utile pour un programme ça di donc, si y'a plus de batterie.
Critical = 1, // ~20% - Batterie critique
Low = 2, // ~40% - Batterie faible
Medium = 3, // ~60% - Batterie moyenne
High = 4, // ~80% - Batterie élevée
Full = 5, // 100% - Batterie pleine
}
impl From<u8> for BatteryCharge {
fn from(val: u8) -> Self {
match val {
0 => BatteryCharge::Empty,
1 => BatteryCharge::Critical,
2 => BatteryCharge::Low,
3 => BatteryCharge::Medium,
4 => BatteryCharge::High,
_ => BatteryCharge::Full,
}
}
}
impl BatteryCharge {
pub fn to_str(&self) -> &'static str {
match self {
BatteryCharge::Empty => "Empty",
BatteryCharge::Critical => "Critical",
BatteryCharge::Low => "Low",
BatteryCharge::Medium => "Medium",
BatteryCharge::High => "High",
BatteryCharge::Full => "Full",
}
}
}
#[cfg(target_os = "none")]
pub fn level() -> BatteryCharge {
let result: u8;
unsafe {
core::arch::asm!( // Obtenir le niveau de charge de la batterie via un appel système (svc)
"svc {svc_num}",
"mov {out}, r0",
svc_num = const 4,
out = out(reg) result,
options(nostack, nomem)
);
}
BatteryCharge::from(result)
}
#[cfg(not(target_os = "none"))]
pub fn level() -> BatteryCharge {
BatteryCharge::High // Valeur Dummy pour les cibles non-embarquées
}
#[cfg(target_os = "none")]
pub fn voltage() -> f32 {
let result: f32;
unsafe {
core::arch::asm!(
"svc {svc_num}",
"vmov {out}, s0",
svc_num = const 5,
out = out(reg) result,
options(nostack, nomem)
);
}
result
}
#[cfg(not(target_os = "none"))]
pub fn voltage() -> f32 {
4.2 // Valeur Dummy pour les cibles non-embarquées
}
#[cfg(target_os = "none")]
pub fn is_charging() -> bool {
let result: u8;
unsafe {
core::arch::asm!(
"svc {svc_num}",
"mov {out}, r0",
svc_num = const 3,
out = out(reg) result,
options(nostack, nomem)
);
}
result != 0
}
#[cfg(not(target_os = "none"))]
pub fn is_charging() -> bool {
false // Valeur Dummy pour les cibles non-embarquées
}
pub fn percentage() -> u8 {
let voltage = voltage();
// Constants for typical Li-ion battery
const V_MIN: f32 = 3.0; // 0% - Minimum safe voltage
const V_MAX: f32 = 4.2; // 100% - Maximum charge voltage
// Clamp the voltage within the valid range
let voltage_clamped = voltage.max(V_MIN).min(V_MAX);
// Linear calculation of percentage
// NOTE: In reality, the discharge curve of a Li-ion battery is not perfectly linear !
// but this approximation is sufficient for a general estimate
let percentage = ((voltage_clamped - V_MIN) / (V_MAX - V_MIN)) * 100.0;
(percentage + 0.5) as u8
}