/
hacksense.pde
136 lines (126 loc) · 3 KB
/
hacksense.pde
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
// pinout
#define BTN_M 14
#define BTN_P 15
// button debouncing
#include <Bounce.h>
Bounce bouncer_m = Bounce(BTN_M, 10);
Bounce bouncer_p = Bounce(BTN_P, 10);
// serial comm
#define READ 0x80
// internal states
char ucounter; // state adjusted by the user
char scounter; // last state received from server
// LED display
#define NDIGITS 4
#define NMAP 25
unsigned long lastep = micros(); // last digit change
char digits[NDIGITS]; // currently displayed content
char digit = 0; // currently lit digit
char digitmap[NMAP][9] = { // digits
"01111110",
"10110000",
"21101101",
"31111001",
"40110011",
"51011011",
"61011111",
"71110000",
"81111111",
"91111011",
";1000010", // upper-left corner (⸢)
"?0011000", // lower-right corner (⸥)
"H0110111",
".0000000", // empty digit
"q1000000", // clock states
"w1100000",
"e1110000",
"r1111000",
"t1111100",
"z1111110",
"a0111110",
"s0011110",
"d0001110",
"f0000110",
"g0000010"
};
// LED "clock"
char clockpos;
unsigned int cpcount;
char clockseq[] = ".......qwertzasdfg.";
#define CPLIMIT 200 /* delay between clockseq items (ms) */
void setup() {
for (int i = 2; i <= 12; i++) {
pinMode(i, OUTPUT);
}
pinMode(BTN_P, INPUT);
pinMode(BTN_M, INPUT);
digitalWrite(BTN_P, HIGH); // enable internal pullup resistors
digitalWrite(BTN_M, HIGH);
digits[0] = ';'; // startup logo (⸢HS⸥)
digits[1] = 'H';
digits[2] = '5';
digits[3] = '?';
setcp(0);
Serial.begin(9600);
recv_state();
digits[1] = '.'; // always empty
}
void loop() {
if (bouncer_m.update() && bouncer_m.read() == HIGH && ucounter > 0) {
ucounter--;
setcp(0);
}
if (bouncer_p.update() && bouncer_p.read() == HIGH && ucounter < 99) {
ucounter++;
setcp(0);
}
digits[0] = clockseq[clockpos];
digits[2] = floor(ucounter / 10) + '0';
if (digits[2] == '0') digits[2] = '.'; // do not display 0x
digits[3] = ucounter % 10 + '0';
stepleds();
if (scounter != ucounter && millis() - cpcount > CPLIMIT) {
if (clockpos == strlen(clockseq) - 1) { // timeout -> submit
setcp(0);
scounter = ucounter;
Serial.print(scounter, BYTE);
recv_state();
} else { // spin the clock
setcp(clockpos + 1);
}
}
}
void recv_state() {
while (!Serial.available()) {
Serial.print(READ, BYTE);
unsigned long start = millis();
while (millis() - start < 500) stepleds();
}
ucounter = scounter = Serial.read();
while (Serial.available()) {
Serial.read(); // clear the buffer
}
}
void stepleds() {
unsigned long now = micros();
if (now - lastep > 4000) {
lastep = now;
} else {
return; // every digit is lit for 4 ms
}
for (int i = 0; i < NDIGITS; i++) { // select digit
digitalWrite(i + 2, digit == i ? HIGH : LOW);
}
for (int i = 0; i < NMAP; i++) { // look up the character
if (digitmap[i][0] == digits[digit]) { // if found...
for (int j = 0; j < 7; j++) { // ...set it segment by segment
digitalWrite(j + 6, digitmap[i][j + 1] == '1' ? LOW : HIGH);
}
}
}
if (++digit == NDIGITS) digit = 0; // next digit
}
void setcp(char val) {
cpcount = millis();
clockpos = val;
}