From a407d920293ebc1d442abcc5bb4e43fc8a6cbe65 Mon Sep 17 00:00:00 2001 From: Elwin Hammer Date: Tue, 21 May 2024 20:52:34 +0200 Subject: Feedback applied --- .../arduino-vaultpuzzle/arduino-vaultpuzzle.ino | 129 ++++++++++++++++++++ puzzle/vault/console-vaultpuzzle/vault.cpp | 130 +++++++++++++++++++++ 2 files changed, 259 insertions(+) create mode 100644 puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino create mode 100644 puzzle/vault/console-vaultpuzzle/vault.cpp (limited to 'puzzle/vault') diff --git a/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino b/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino new file mode 100644 index 0000000..977fc01 --- /dev/null +++ b/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino @@ -0,0 +1,129 @@ +#include + +// Definitions for GPIO numbers, change these according to your hardware setup +#define TOTAL_LEVELS 5 +#define TAG "VaultPuzzle" + +// Define the I2C slave address +#define I2C_SLAVE_ADDR 0x40 // Replace 0x40 with your actual I2C slave device address + +// Key Matrix Pin Configuration +#define ROWS 4 +#define COLS 3 + +//TODO Update these pin numbers based on your Arduino setup +const int ROW_PINS[ROWS] = {32, 33, 25, 26}; +const int COL_PINS[COLS] = {27, 14, 12}; + +typedef enum { + STATE_UNINITIALIZED = 0x00, + STATE_RESET = 0x01, + STATE_PLAYING = 0x02, + STATE_SOLVED = 0x03, +} 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(115200); + Wire.begin(); // Initialize I2C as master + initialize_system(); + Serial.println("GPIO and I2C initialized."); +} + +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 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 = STATE_UNINITIALIZED; break; + case STATE_RESET: data = STATE_RESET; break; + case STATE_PLAYING: data = STATE_PLAYING; break; + case STATE_SOLVED: data = STATE_SOLVED; 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.println("State update sent successfully."); + } else { + Serial.println("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 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); + } + } +} diff --git a/puzzle/vault/console-vaultpuzzle/vault.cpp b/puzzle/vault/console-vaultpuzzle/vault.cpp new file mode 100644 index 0000000..3566b3e --- /dev/null +++ b/puzzle/vault/console-vaultpuzzle/vault.cpp @@ -0,0 +1,130 @@ +#include +#include +#include + +// Definitions for puzzle requirements +constexpr int TOTAL_LEVELS = 5; + +// Enumeration for the states of the puzzle +enum PuzzleState { + STATE_UNINITIALIZED, + STATE_RESET, + STATE_PLAYING, + STATE_SOLVED, + STATE_ERROR +}; + +// This array maps each level to the correct button press +const std::array validButtons = {"A3", "F1", "U4", "C2", "L1"}; + +PuzzleState puzzleState = STATE_UNINITIALIZED; +int currentLevel = 0; + +// Function prototypes +void displayCode(int level); +void sendI2CUpdate(PuzzleState state); + +// Simulate sending an I2C update +void sendI2CUpdate(PuzzleState state) { + std::cout << "Sending state " << state << " to main controller via I2C.\n"; +} + +// Simulate checking if the vault door is closed +bool isVaultClosed() { + return true; // Return true if the door sensor indicates closed +} + +// Function to display a code on the 7-segment display +void displayCode(int level) { + std::cout << "Displaying code for level " << level << " on the 7-segment display.\n"; +} + +// Function to initialize the puzzle +void initializePuzzle() { + if (isVaultClosed()) { + puzzleState = STATE_RESET; + currentLevel = 1; // Start at level 1 + std::cout << "Puzzle initialized. Starting at level " << currentLevel << ".\n"; + displayCode(currentLevel); // Show the first code + } else { + std::cout << "Vault door is open. Please close the door to start the puzzle.\n"; + } +} + +// Function to lock the vault +void lockVault() { + std::cout << "Vault locked.\n"; +} + +// Function to unlock the vault +void unlockVault() { + std::cout << "Vault unlocked!\n"; +} + +// Function to simulate the buzzer sound +void playErrorSound() { + std::cout << "Playing error sound.\n"; +} + +// Function to simulate blinking the 7-segment display +void blinkDisplay() { + std::cout << "7-segment display is blinking to indicate an error.\n"; +} + +// Validate the button press for the current level +bool isValidButtonPress(const std::string& button, int level) { + return button == validButtons[level - 1]; +} + +// Function to update the state of the puzzle based on the current level +void updateStateAfterButtonPress(bool validPress) { + if (validPress) { + if (currentLevel >= TOTAL_LEVELS) { + puzzleState = STATE_SOLVED; + unlockVault(); + } else { + puzzleState = STATE_PLAYING; + displayCode(currentLevel); + } + } else { + puzzleState = STATE_ERROR; + playErrorSound(); + blinkDisplay(); + lockVault(); + currentLevel = 1; // Reset to level 1 + displayCode(currentLevel); + } + sendI2CUpdate(puzzleState); // Notify main controller of the state change +} + +int main() { + initializePuzzle(); + + std::string buttonInput; + + while (puzzleState != STATE_SOLVED) { + std::cout << "Enter the button pressed for level " << currentLevel << " (format Xn, e.g., A3): "; + std::getline(std::cin, buttonInput); + + if (!buttonInput.empty() && isValidButtonPress(buttonInput, currentLevel)) { + currentLevel++; + if (currentLevel > TOTAL_LEVELS) { + puzzleState = STATE_SOLVED; + unlockVault(); + std::cout << "The puzzle is solved and the vault is open!\n"; + } else { + displayCode(currentLevel); + } + } else { + playErrorSound(); + blinkDisplay(); + lockVault(); + puzzleState = STATE_RESET; + currentLevel = 1; + displayCode(currentLevel); + } + sendI2CUpdate(puzzleState); + } + + return 0; +} -- cgit v1.2.3 From 080d68f36e923c8e7b4014025e6c3120f4f785db Mon Sep 17 00:00:00 2001 From: Elwin Hammer Date: Thu, 23 May 2024 09:40:27 +0200 Subject: Update arduino-vaultpuzzle.ino --- puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'puzzle/vault') diff --git a/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino b/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino index 977fc01..384479b 100644 --- a/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino +++ b/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino @@ -12,8 +12,8 @@ #define COLS 3 //TODO Update these pin numbers based on your Arduino setup -const int ROW_PINS[ROWS] = {32, 33, 25, 26}; -const int COL_PINS[COLS] = {27, 14, 12}; +const int ROW_PINS[ROWS] = {7, 6, 5, 4}; +const int COL_PINS[COLS] = {10, 9, 8}; typedef enum { STATE_UNINITIALIZED = 0x00, @@ -22,7 +22,7 @@ typedef enum { STATE_SOLVED = 0x03, } PuzzleState; -const char* validButtons[TOTAL_LEVELS] = {"A3", "F1", "U4", "C2", "L1"}; +const char* validButtons[TOTAL_LEVELS] = {"A2", "B1", "D3", "C2", "C1"}; PuzzleState puzzleState = STATE_UNINITIALIZED; int currentLevel = 0; -- cgit v1.2.3 From 358ce069644dfc56592b7d1cfa655d1eb9c4d5f0 Mon Sep 17 00:00:00 2001 From: Elwin Hammer Date: Thu, 23 May 2024 17:31:49 +0200 Subject: Code working according to game logic from console app --- .../arduino-vaultpuzzle/arduino-vaultpuzzle.ino | 135 ++++++++++++--------- 1 file changed, 78 insertions(+), 57 deletions(-) (limited to 'puzzle/vault') diff --git a/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino b/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino index 384479b..4dd8ac8 100644 --- a/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino +++ b/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino @@ -1,16 +1,24 @@ #include +#include // Definitions for GPIO numbers, change these according to your hardware setup #define TOTAL_LEVELS 5 #define TAG "VaultPuzzle" -// Define the I2C slave address -#define I2C_SLAVE_ADDR 0x40 // Replace 0x40 with your actual I2C slave device address - // Key Matrix Pin Configuration #define ROWS 4 #define COLS 3 +// Module connection pins (Digital Pins for TM1637) +#define CLK 2 +#define DIO 3 + +// Pin to indicate puzzle solved state +#define SOLVED_PIN 53 + +// Initialize the TM1637 display +TM1637Display display(CLK, DIO); + //TODO Update these pin numbers based on your Arduino setup const int ROW_PINS[ROWS] = {7, 6, 5, 4}; const int COL_PINS[COLS] = {10, 9, 8}; @@ -20,6 +28,7 @@ typedef enum { STATE_RESET = 0x01, STATE_PLAYING = 0x02, STATE_SOLVED = 0x03, + STATE_ERROR = 0x04 } PuzzleState; const char* validButtons[TOTAL_LEVELS] = {"A2", "B1", "D3", "C2", "C1"}; @@ -27,17 +36,35 @@ 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 play_error_sound(); +void blink_display(); void setup() { - Serial.begin(115200); - Wire.begin(); // Initialize I2C as master + Serial.begin(115200); // Initialize default Serial for debug messages + pinMode(SOLVED_PIN, OUTPUT); // Initialize the solved indicator pin + digitalWrite(SOLVED_PIN, LOW); // Start with the solved pin LOW + + display.setBrightness(0x0f); // Set the brightness of the TM1637 display initialize_system(); - Serial.println("GPIO and I2C initialized."); + Serial.println("GPIO and display initialized."); + + // Test to light up all segments + uint8_t allOn[] = {0xFF, 0xFF, 0xFF, 0xFF}; // All segments on + display.setSegments(allOn); + delay(2000); // Keep it on for 2 seconds before proceeding + + // Initialize the game + if (true) { // Simulating isVaultClosed + puzzleState = STATE_RESET; + currentLevel = 0; + display_code(currentLevel); + } else { + Serial.println("Vault door is open. Please close the door to start the puzzle."); + } } void initialize_system() { @@ -58,42 +85,20 @@ void loop() { check_button_press(); delay(100); // Non-blocking delay } -} - -void send_i2c_update(PuzzleState state) { - uint8_t data; - switch (state) { - case STATE_UNINITIALIZED: data = STATE_UNINITIALIZED; break; - case STATE_RESET: data = STATE_RESET; break; - case STATE_PLAYING: data = STATE_PLAYING; break; - case STATE_SOLVED: data = STATE_SOLVED; 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.println("State update sent successfully."); - } else { - Serial.println("Failed to send state update via I2C."); - } + // When puzzle is solved, you might want to display a final message and set the solved pin high + if (puzzleState == STATE_SOLVED) { + digitalWrite(SOLVED_PIN, HIGH); // Set the solved pin high + display.showNumberDec(currentLevel, true); // Show final level or a special message + Serial.println("Final display shown. Puzzle complete."); + while (1) { delay(1000); } // Hold on the final display + } } 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."); - } + // Display the level on the TM1637 4-digit 7-segment display + display.showNumberDec(level, true); // True to show leading zeros + Serial.print("Code for level "); Serial.print(level); Serial.println(" displayed successfully."); } void check_button_press() { @@ -102,28 +107,44 @@ void check_button_press() { 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 + delay(50); // Debounce delay + if (digitalRead(ROW_PINS[row]) == LOW) { // Confirm the button is still pressed + keyPress[0] = 'A' + row; + keyPress[1] = '1' + col; + keyPress[2] = '\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); // Display the final level + digitalWrite(SOLVED_PIN, HIGH); // Set the solved pin high + } else { + puzzleState = STATE_PLAYING; + display_code(currentLevel); + } + } else { + play_error_sound(); + blink_display(); + puzzleState = STATE_ERROR; + currentLevel = 0; + display_code(currentLevel); + } + 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); - } - } +void play_error_sound() { + // Simulate error sound - connect a buzzer to play actual sound + Serial.println("Playing error sound."); +} + +void blink_display() { + // Simulate blinking the display - use LEDs or other methods to show visual feedback + Serial.println("7-segment display is blinking to indicate an error."); } -- cgit v1.2.3