Repository navigation
Expand file tree
/
Copy patharmed_state.ino
More file actions
135 lines (115 loc) · 2.95 KB
/
Copy patharmed_state.ino
File metadata and controls
135 lines (115 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
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
// State variables
unsigned long armBegin;
unsigned long nextBeep;
unsigned long defusingSince;
void armed_setup() {
// Initiate variables
armBegin = millis();
nextBeep = millis();
defusingSince = -1;
fillStrip(255, 0, 0);
digitalWrite(PIN_DEFUSE_LED, HIGH);
armed_updateLCD();
// Loop to update the LCD
t.every(250, [](void *) -> bool {
if(currentState != STATE_ARMED) {
return false; // Don't repeat
}
// Check if we should be defusing right now or not
if(digitalRead(PIN_DEFUSE_BTN) == 0) {
if(defusingSince == -1) {
// Just started defusing!
defusingSince = millis();
}
}else{
defusingSince = -1;
}
armed_updateLCD();
return true; // Repeat
});
}
void armed_loop() {
// Beep if we need to!
if(millis() > nextBeep) {
int waitMS = armed_beep();
nextBeep = millis() + waitMS;
}
// Check if we should explode
if(millisArmed() > (unsigned long) config_explodeTime * 1000) {
// Explode!!!
setState(STATE_EXPLODED);
beep(400, 250, 3);
}
// Check if we should be defused
if(millisDefusing() > (unsigned long) config_defuseTime * 1000) {
// Defuse!!
setState(STATE_DEFUSED);
beep(50, 125, 4);
}
}
void armed_updateLCD() {
lcd.clear();
// Print state
if(defusingSince == -1) {
lcdPrintCenter("Armed", 1);
}else{
lcdPrintCenter("Armed (defusing)", 0);
}
// Print a bar graph of the defusing time if we are defusing
if(defusingSince != -1) {
drawBarGraph(LCD_COLS - 4, 2, 1, millisDefusing(), (unsigned long) config_defuseTime * 1000);
}
}
/**
* Time between beeps is an exponential function
*
* A0 = 1.04865151217746
* A1 = 0.244017811416199
* A2 = 1.76379778668885
*
* Y(bps) = A0 * E^(A1*X + A2*X^2)
* X = % OF TIME PASSED (0.0 - 1.0)
* Y = BEEPS PER SECOND
*/
#define BEEP_A0 1.04865151217746
#define BEEP_A1 0.244017811416199
#define BEEP_A2 1.76379778668885
#define BOMB_BEEP_LENGTH 125
int armed_beep() {
// Calculate next beep time
float x = (float) millisArmed() / ((float) config_explodeTime * 1000.0);
float n = BEEP_A1 * x + BEEP_A2 * x * x;
float bps = BEEP_A0 * exp(n);
// Convert bps (beeps per second) to a wait time in milliseconds
int waitMS = (int) (1000.0 / bps);
// Beep and flash LED strip
int bombBeepLength = BOMB_BEEP_LENGTH;
if(waitMS <= bombBeepLength) {
bombBeepLength = waitMS - 10;
}
if(bombBeepLength > 0) {
beep(BOMB_BEEP_LENGTH, 1);
fillStrip(255, 0, 0);
t.in(BOMB_BEEP_LENGTH, [](void *) -> bool {
if(currentState == STATE_ARMED) {
fillStrip(50, 0, 0);
}
});
}
return waitMS;
}
/**
* How many milliseconds the bomb has been armed for
*/
unsigned long millisArmed() {
return millis() - armBegin;
}
/**
* How many milliseconds the bomb is in a defusing state (0 if not in a defusing state)
*/
unsigned long millisDefusing() {
if(defusingSince == -1) {
return 0;
}
return millis() - defusingSince;
}