aboutsummaryrefslogtreecommitdiff
path: root/puzzle/vault/main.cpp
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-06-22 18:24:07 +0200
committerLoek Le Blansch <loek@pipeframe.xyz>2024-06-22 18:24:07 +0200
commitd6440954806d381dae5b3df65b43192f897018c6 (patch)
tree0f16b75795d9926c5ea4a8ef52a695365837a8e4 /puzzle/vault/main.cpp
parent9a24fe708770d717ecb8cbe45fe24922d21b5838 (diff)
parent9c255363bb578ada6bb53d15e5ca12fa8b39986b (diff)
Merge branch 'prot/vault-puzzle' of github.com:lonkaars/puzzelbox
Diffstat (limited to 'puzzle/vault/main.cpp')
-rw-r--r--puzzle/vault/main.cpp165
1 files changed, 165 insertions, 0 deletions
diff --git a/puzzle/vault/main.cpp b/puzzle/vault/main.cpp
new file mode 100644
index 0000000..76e5f65
--- /dev/null
+++ b/puzzle/vault/main.cpp
@@ -0,0 +1,165 @@
+#include <Arduino.h>
+#include <Wire.h>
+#include <TM1637Display.h>
+
+#define TOTAL_LEVELS 5
+#define ROWS 4
+#define COLS 3
+#define CLK 2
+#define DIO 3
+#define SOLVED_PIN 53
+#define I2C_MODULE_ADDRESS 0x08 // Address of the puzzle module
+#define HANDSHAKE_RECEIVED {0x70, 0x75, 0x7a, 0x62, 0x75, 0x73} // Magic command for the handshake
+#define HANDSHAKE_SEND {0x67, 0x61, 0x6d, 0x69, 0x6e, 0x67} // Magic command for the handshake
+#define REQUEST_STATE_CMD 0x53 // 'S' to request the game state
+
+const int ROW_PINS[ROWS] = {7, 6, 5, 4};
+const int COL_PINS[COLS] = {10, 9, 8};
+const char* validButtons[TOTAL_LEVELS] = {"A2", "B1", "D3", "C2", "C3"};
+const char bombCode[] = "1234";
+
+TM1637Display display(CLK, DIO);
+
+typedef enum {
+ STATE_UNINITIALIZED = 0x00,
+ STATE_RESET = 0x01,
+ STATE_PLAYING = 0x02,
+ STATE_SOLVED = 0x03,
+ STATE_ERROR = 0x04
+} PuzzleState;
+
+PuzzleState puzzleState = STATE_UNINITIALIZED;
+int currentLevel = 0;
+
+void requestEvent() {
+ if (puzzleState == STATE_PLAYING) {
+ uint8_t responseData[] = HANDSHAKE_SEND;
+ Wire.write(responseData, sizeof(responseData));
+ Serial.println("Handshake response sent.");
+ }
+}
+
+void blink_display(char num) {
+ while(puzzleState == STATE_UNINITIALIZED || puzzleState == STATE_ERROR) {
+ display.showNumberDecEx(0, 0b11111111, true); // Display "0000" with all digits on
+ delay(500);
+ display.clear();
+ delay(500);
+ }
+}
+
+void display_final_code(const char* code) {
+ uint8_t segs[4] = {0, 0, 0, 0};
+ int numDigits = strlen(code);
+ numDigits = numDigits > 4 ? 4 : numDigits;
+
+ for (int i = 0; i < numDigits; i++) {
+ segs[i] = display.encodeDigit(code[i] - '0');
+ }
+
+ display.setSegments(segs, numDigits, 0);
+}
+
+void check_button_press() {
+ for (int col = 0; col < COLS; col++) {
+ digitalWrite(COL_PINS[col], LOW);
+ for (int row = 0; row < ROWS; row++) {
+ if (digitalRead(ROW_PINS[row]) == LOW) {
+ delay(50);
+ if (digitalRead(ROW_PINS[row]) == LOW) {
+ char keyPress[3] = {'A' + row, '1' + col, '\0'};
+ Serial.print("Keypress detected: ");
+ Serial.println(keyPress);
+ if (strcmp(keyPress, validButtons[currentLevel]) == 0) {
+ currentLevel++;
+ if (currentLevel >= TOTAL_LEVELS) {
+ puzzleState = STATE_SOLVED;
+ Serial.println("Puzzle solved!");
+ display.showNumberDec(currentLevel + 1, true);
+ digitalWrite(SOLVED_PIN, HIGH);
+ } else {
+ puzzleState = STATE_PLAYING;
+ }
+ } else {
+ currentLevel = 0;
+ }
+ while (digitalRead(ROW_PINS[row]) == LOW) {} // Ensure button release
+ }
+ }
+ }
+ digitalWrite(COL_PINS[col], HIGH);
+ }
+}
+
+void initialize_system() {
+ for (int i = 0; i < ROWS; i++) {
+ pinMode(ROW_PINS[i], INPUT_PULLUP);
+ }
+ for (int i = 0; i < COLS; i++) {
+ pinMode(COL_PINS[i], OUTPUT);
+ digitalWrite(COL_PINS[i], HIGH);
+ }
+ Serial.println("GPIO and display initialized.");
+}
+
+void receiveEvent(int howMany) {
+ if (howMany == 6) {
+ uint8_t expectedBytes[] = HANDSHAKE_RECEIVED;
+ uint8_t receivedBytes[6];
+ bool match = true;
+
+ for (int i = 0; i < 6; i++) {
+ receivedBytes[i] = Wire.read();
+ if (receivedBytes[i] != expectedBytes[i]) {
+ match = false;
+ break;
+ }
+ }
+
+ if (match) {
+ Serial.println("Correct handshake data received.");
+ puzzleState = STATE_PLAYING;
+ initialize_system();
+ } else {
+ Serial.println("Incorrect handshake data received.");
+ puzzleState = STATE_ERROR;
+ }
+ } else {
+ Serial.print("Received wrong number of bytes: ");
+ Serial.println(howMany);
+ puzzleState = STATE_ERROR;
+ }
+}
+
+
+void setup() {
+ Serial.begin(115200);
+ pinMode(SOLVED_PIN, OUTPUT);
+ digitalWrite(SOLVED_PIN, LOW);
+ display.setBrightness(0x0f);
+
+ Wire.begin(I2C_MODULE_ADDRESS);
+ Wire.onRequest(requestEvent);
+ Wire.onReceive(receiveEvent);
+
+ // Initialize display with blinking zeros to indicate no connection or initialization state
+ blink_display('0');
+}
+
+void loop() {
+ switch(puzzleState) {
+ case STATE_PLAYING:
+ check_button_press();
+ delay(100);
+ break;
+ case STATE_SOLVED:
+ display_final_code(bombCode);
+ digitalWrite(SOLVED_PIN, HIGH);
+ Serial.println("Final display shown. Puzzle complete.");
+ break;
+ case STATE_ERROR:
+ case STATE_UNINITIALIZED:
+ blink_display('0');
+ break;
+ }
+} \ No newline at end of file