-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwires.rs
More file actions
91 lines (76 loc) · 2.95 KB
/
wires.rs
File metadata and controls
91 lines (76 loc) · 2.95 KB
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
//! For interacting with either simple or complicated wires.
use defmt::info;
use embedded_hal::digital::InputPin;
use rp_pico::hal::gpio::{DynPinId, FunctionSioInput, Pin, PullDown};
type Wire = Pin<DynPinId, FunctionSioInput, PullDown>;
/// An implementation for the complicated and simple wire module.
///
/// `Do not` connect pins directly to 3.3/5v output. A resistor is needed to separate the wires.
/// Though multiple pins can share the same resistor.
///
/// ## Example arrangement
/// ................... -> defuse wire
/// 3.3V -> 1K resistor ^v-> penalty wire
/// .................... -> penalty wire
pub struct Wires<const PENALTY_WIRES: usize, const DISARM_WIRES: usize> {
/// These wries should not be cut.
penalty: [Option<Wire>; PENALTY_WIRES],
/// This wire should be cut.
disarm: [Option<Wire>; DISARM_WIRES],
}
impl<const PENALTY_WIRES: usize, const DISARM_WIRES: usize> Wires<PENALTY_WIRES, DISARM_WIRES> {
/// Penalty wires will cause a [`mistake`][Self::mistake] when cut.
/// Once `all` the disarm wires are cut, this module will be permanently defused.
///
/// Simple wires will only have one disarm wire.
/// Complicated wires will have multiple diarm wires.
///
/// Reinserting any wire will not undo any effect.
/// If a disarm wire is replaced, the module remains disarmed.
/// If a penalty wire is replaced, the penalty will not be triggered again when it is removed.
pub fn new(penalty: [Wire; PENALTY_WIRES], disarm: [Wire; DISARM_WIRES]) -> Self {
Self {
penalty: penalty.map(Some),
disarm: disarm.map(Some),
}
}
/// Returns the amount of mistakes that have been made since this method was last called,
/// `not` the total amount of mistakes.
///
/// After a module has been disarmed, this method will always return 0.
pub fn mistakes(&mut self) -> usize {
if self.disarm.iter().all(|wire| wire.is_none()) {
return 0;
}
let mut mistakes = 0;
for wire in &mut self.penalty {
let Some(intact_wire) = wire else {
continue;
};
if intact_wire.is_high().unwrap() {
continue;
}
info!("Player cut bad wire: {:?}", intact_wire.id().num);
mistakes += 1;
*wire = None;
}
mistakes
}
/// Returns true if this module has been disarmed.
///
/// Subsequent calls will continue to return true, even if wires are replaced.
pub fn success(&mut self) -> bool {
// Update wires
for wire in &mut self.disarm {
let Some(intact_wire) = wire else {
continue;
};
if intact_wire.is_high().unwrap() {
continue;
}
info!("Player cut correct wire: {:?}", intact_wire.id().num);
*wire = None;
}
self.disarm.iter().all(|wire| wire.is_none())
}
}