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
|
#include <Wire.h>
// Definitions for GPIO numbers, change these according to your hardware setup
#define TOTAL_LEVELS 5
#define TAG "VaultPuzzle"
// Key Matrix Pin Configuration
#define ROWS 4
#define COLS 3
const int ROW_PINS[ROWS] = {32, 33, 25, 26}; // Update these pin numbers based on your Arduino setup
const int COL_PINS[COLS] = {27, 14, 12}; // Update these pin numbers based on your Arduino setup
typedef enum {
STATE_UNINITIALIZED,
STATE_RESET,
STATE_PLAYING,
STATE_SOLVED,
STATE_ERROR
} PuzzleState;
const char* validButtons[TOTAL_LEVELS] = {"A3", "F1", "U4", "C2", "L1"};
PuzzleState puzzleState = STATE_UNINITIALIZED;
int currentLevel = 0;
// Function prototypes
void send_i2c_update(PuzzleState state);
void display_code(int level);
void initialize_system();
void check_button_press();
void update_state_after_button_press(bool validPress);
void setup() {
Serial.begin(9600);
Wire.begin(); // Initialize I2C as master
initialize_system();
Serial.println("GPIO and I2C initialized.");
}
void loop() {
while (puzzleState != STATE_SOLVED) {
check_button_press();
delay(100); // Non-blocking delay
}
}
void send_i2c_update(PuzzleState state) {
uint8_t data;
switch (state) {
case STATE_UNINITIALIZED: data = 0x00; break;
case STATE_RESET: data = 0x01; break;
case STATE_PLAYING: data = 0x02; break;
case STATE_SOLVED: data = 0x03; break;
case STATE_ERROR: data = 0x04; break;
default: data = 0xFF; // Unknown state
}
Serial.print("Sending state "); Serial.println(state);
Wire.beginTransmission(I2C_SLAVE_ADDR);
Wire.write(data);
byte error = Wire.endTransmission();
if (error == 0) {
Serial.print("State update sent successfully.");
} else {
Serial.print("Failed to send state update via I2C.");
}
}
void display_code(int level) {
Serial.print("Displaying code for level "); Serial.println(level);
Wire.beginTransmission(I2C_SLAVE_ADDR);
Wire.write(level);
byte error = Wire.endTransmission();
if (error == 0) {
Serial.print("Code for level "); Serial.print(level); Serial.println(" displayed successfully.");
} else {
Serial.print("Failed to display code for level "); Serial.print(level); Serial.println(" via I2C.");
}
}
void initialize_system() {
// Configure the rows as input with pull-up
for (int i = 0; i < ROWS; i++) {
pinMode(ROW_PINS[i], INPUT_PULLUP);
}
// Configure the columns as output
for (int i = 0; i < COLS; i++) {
pinMode(COL_PINS[i], OUTPUT);
digitalWrite(COL_PINS[i], HIGH);
}
}
void check_button_press() {
char keyPress[3] = {0};
for (int col = 0; col < COLS; col++) {
digitalWrite(COL_PINS[col], LOW); // Activate column
for (int row = 0; row < ROWS; row++) {
if (digitalRead(ROW_PINS[row]) == LOW) { // Detect if any row is activated
keyPress[0] = 'A' + row;
keyPress[1] = '1' + col;
keyPress[2] = '\0';
Serial.print("Keypress detected: "); Serial.println(keyPress);
update_state_after_button_press(strcmp(keyPress, validButtons[currentLevel]) == 0);
while (digitalRead(ROW_PINS[row]) == LOW) {} // Wait for release
}
}
digitalWrite(COL_PINS[col], HIGH); // Deactivate column
}
}
void update_state_after_button_press(bool validPress) {
if (validPress) {
if (currentLevel >= TOTAL_LEVELS) {
puzzleState = STATE_SOLVED;
Serial.println("Puzzle solved!");
send_i2c_update(puzzleState);
} else {
puzzleState = STATE_PLAYING;
currentLevel++;
display_code(currentLevel);
}
} else {
puzzleState = STATE_ERROR;
Serial.println("Error in input");
}
send_i2c_update(puzzleState);
}
|