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
|
/**
* Simon game based on this wikipedia article:
* https://en.wikipedia.org/wiki/Simon_(game)
*/
#define CFG_DEBOUNCE_DELAY 200
#define CFG_MAX_GAME_LEN 512
#define PINOUT_LED_BLU 0
#define PINOUT_SWC_BLU 1
#define PINOUT_LED_RED 2
#define PINOUT_SWC_RED 3
#define PINOUT_LED_YLW 4
#define PINOUT_SWC_YLW 5
#define PINOUT_LED_GRE 6
#define PINOUT_SWC_GRE 7
#define PINOUT_BUZZ A0
#define PINOUT_NOISE A1
#define TONE_BLU 329.63
#define TONE_YLW 277.18
#define TONE_RED 440.00
#define TONE_GRE 164.81
const int clockwise_leds[] = { PINOUT_LED_BLU, PINOUT_LED_YLW, PINOUT_LED_GRE, PINOUT_LED_RED };
const int clockwise_buttons[] = { PINOUT_SWC_BLU, PINOUT_SWC_YLW, PINOUT_SWC_GRE, PINOUT_SWC_RED };
const int clockwise_tones[] = { TONE_BLU, TONE_YLW, TONE_GRE, TONE_RED };
#define CFG_BN_COUNT 4
unsigned long bn_timings[CFG_BN_COUNT], led_timeouts[CFG_BN_COUNT];
unsigned char bn_state[CFG_BN_COUNT], bn_state_old[CFG_BN_COUNT], led_state[CFG_BN_COUNT];
#define QUARTER_TL 0
#define QUARTER_TR 1
#define QUARTER_BL 2
#define QUARTER_BR 3
int turn_number;
int entered;
int combination[CFG_MAX_GAME_LEN];
typedef struct {
unsigned char index;
bool down;
unsigned long timestamp;
} bn_event;
void generate_combination() {
for (int i = 0; i < CFG_MAX_GAME_LEN; i++)
combination[i] = random(4);
}
void setup() {
pinMode(PINOUT_LED_RED, OUTPUT);
pinMode(PINOUT_LED_GRE, OUTPUT);
pinMode(PINOUT_LED_YLW, OUTPUT);
pinMode(PINOUT_LED_BLU, OUTPUT);
pinMode(PINOUT_BUZZ, OUTPUT);
pinMode(PINOUT_SWC_RED, INPUT_PULLUP);
pinMode(PINOUT_SWC_GRE, INPUT_PULLUP);
pinMode(PINOUT_SWC_YLW, INPUT_PULLUP);
pinMode(PINOUT_SWC_BLU, INPUT_PULLUP);
pinMode(PINOUT_NOISE, INPUT); // random noise channel for RNG
randomSeed(analogRead(PINOUT_NOISE));
}
void bn_scan() {
memcpy(&bn_state_old, bn_state, sizeof(bn_state_old));
memset(&bn_state, 0, sizeof(bn_state));
for (int i = 0; i < CFG_BN_COUNT; i++)
bn_state[i] = !digitalRead(clockwise_buttons[i]);
}
void bn_onevent(bn_event ev) {
if (ev.down) {
bool bounce = bn_timings[ev.index] + CFG_DEBOUNCE_DELAY > millis();
bn_timings[ev.index] = ev.timestamp;
if (bounce) return;
}
if (ev.down) {
led_set_timeout(ev.index, 200);
tone(PINOUT_BUZZ, clockwise_tones[ev.index], 200);
}
}
void bn_event_gen() {
for(int i = 0; i < CFG_BN_COUNT; i++) {
if (bn_state[i] == bn_state_old[i]) continue;
bn_event event = {
.index = (unsigned char) i,
.down = bn_state[i],
.timestamp = millis()
};
bn_onevent(event);
}
}
void led_set_timeout(unsigned int led, unsigned long duration_millis) {
led_timeouts[led] = millis() + duration_millis;
led_state[led] = 1;
digitalWrite(clockwise_leds[led], HIGH);
}
void led_update() {
unsigned long current_time = millis();
for (int i = 0; i < CFG_BN_COUNT; i++) {
if (led_timeouts[i] > current_time) continue;
if (led_state[i] == 0) continue;
led_state[i] = 0;
digitalWrite(clockwise_leds[i], LOW);
}
}
void loop() {
bn_scan();
bn_event_gen();
led_update();
}
|