diff options
Diffstat (limited to 'puzzle')
-rw-r--r-- | puzzle/dummy/CMakeLists.txt | 14 | ||||
-rw-r--r-- | puzzle/dummy/FreeRTOSConfig.h | 4 | ||||
-rw-r--r-- | puzzle/dummy/index.dox | 9 | ||||
-rw-r--r-- | puzzle/dummy/makefile | 16 | ||||
-rw-r--r-- | puzzle/neo/CMakeLists.txt | 44 | ||||
-rw-r--r-- | puzzle/neo/FreeRTOSConfig.h | 52 | ||||
-rw-r--r-- | puzzle/neo/console-neopuzzle/neo.cpp | 100 | ||||
-rw-r--r-- | puzzle/neo/index.dox | 14 | ||||
l--------- | puzzle/neo/lib | 1 | ||||
-rw-r--r-- | puzzle/neo/main.cpp (renamed from puzzle/neo/arduino-neopuzzle/arduino-neopuzzle.ino) | 79 | ||||
-rw-r--r-- | puzzle/neo/makefile | 8 | ||||
-rw-r--r-- | puzzle/neo/mod.c | 6 | ||||
-rw-r--r-- | puzzle/readme.md | 22 | ||||
-rw-r--r-- | puzzle/vault/CMakeLists.txt | 41 | ||||
-rw-r--r-- | puzzle/vault/FreeRTOSConfig.h | 52 | ||||
-rw-r--r-- | puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino | 150 | ||||
-rw-r--r-- | puzzle/vault/console-vaultpuzzle/vault.cpp | 130 | ||||
-rw-r--r-- | puzzle/vault/index.dox | 11 | ||||
l--------- | puzzle/vault/lib | 1 | ||||
-rw-r--r-- | puzzle/vault/main.cpp | 187 | ||||
-rw-r--r-- | puzzle/vault/makefile | 8 | ||||
-rw-r--r-- | puzzle/vault/mod.c | 6 |
22 files changed, 505 insertions, 450 deletions
diff --git a/puzzle/dummy/CMakeLists.txt b/puzzle/dummy/CMakeLists.txt index 6acc4c8..7edce2b 100644 --- a/puzzle/dummy/CMakeLists.txt +++ b/puzzle/dummy/CMakeLists.txt @@ -11,14 +11,13 @@ add_compile_definitions(DEBUG) # arduino set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/lib/Arduino-CMake-Toolchain/Arduino-toolchain.cmake) -# set(ARDUINO_BOARD "Arduino Uno [avr.uno]") -set(ARDUINO_BOARD "Arduino Mega or Mega 2560 [avr.mega]") +set(ARDUINO_BOARD "Arduino Uno [avr.uno]") +# set(ARDUINO_BOARD "Arduino Mega or Mega 2560 [avr.mega]") -# freertos +# freertos (used for memory management only) add_library(freertos_config INTERFACE) target_include_directories(freertos_config SYSTEM INTERFACE .) -# set(FREERTOS_PORT GCC_ATMEGA) # Arduino Uno -set(FREERTOS_PORT GCC_ATMEGA) # Arduino Uno +set(FREERTOS_PORT GCC_ATMEGA) set(FREERTOS_HEAP 4) # used for testing @@ -29,6 +28,7 @@ set(FREERTOS_HEAP 4) project(pb_mod_dummy C CXX) add_subdirectory(lib/pbdrv) +include(lib/pbdrv/ext/freertos/include.cmake) add_subdirectory(lib/FreeRTOS-Kernel) add_executable(main @@ -36,10 +36,10 @@ add_executable(main mod.c ) -target_link_libraries(main +target_link_libraries(main PUBLIC pbdrv-mod ) -target_link_arduino_libraries(main +target_link_arduino_libraries(main PUBLIC core Wire ) diff --git a/puzzle/dummy/FreeRTOSConfig.h b/puzzle/dummy/FreeRTOSConfig.h index 1cfdd71..1d98f78 100644 --- a/puzzle/dummy/FreeRTOSConfig.h +++ b/puzzle/dummy/FreeRTOSConfig.h @@ -17,8 +17,8 @@ #define configSTACK_DEPTH_TYPE uint16_t #define configSUPPORT_STATIC_ALLOCATION 0 #define configSUPPORT_DYNAMIC_ALLOCATION 1 -// #define configTOTAL_HEAP_SIZE (1024) -#define configTOTAL_HEAP_SIZE (7 * 1024) +#define configTOTAL_HEAP_SIZE (1024) +// #define configTOTAL_HEAP_SIZE (7 * 1024) #define configCHECK_FOR_STACK_OVERFLOW 0 #define configUSE_MALLOC_FAILED_HOOK 0 #define configUSE_DAEMON_TASK_STARTUP_HOOK 0 diff --git a/puzzle/dummy/index.dox b/puzzle/dummy/index.dox new file mode 100644 index 0000000..918bf7f --- /dev/null +++ b/puzzle/dummy/index.dox @@ -0,0 +1,9 @@ +// vim:ft=doxygen +/** +\ingroup puz +\defgroup puz_dummy Dummy +\brief Demo puzzle module + +The dummy puzzle module consists of an empty Arduino sketch, and can be used as +a starting point for developing new puzzle modules. +*/ diff --git a/puzzle/dummy/makefile b/puzzle/dummy/makefile index 509d8e3..6b8341b 100644 --- a/puzzle/dummy/makefile +++ b/puzzle/dummy/makefile @@ -3,18 +3,6 @@ TARGET = $(BUILD_DIR)/main.elf include ../../lazy.mk export SERIAL_PORT ?= /dev/ttyACM0 -flash: upload-main; -upload-main: $(TARGET) - -test: test_a test_b; - -test_a: - $(MAKE) -C . clean - $(MAKE) -E CMFLAGS+=-D\ CMAKE_CXX_FLAGS=-DTEST_A -C . - $(MAKE) -E SERIAL_PORT=/dev/ttyACM0 -C . flash - -test_b: - $(MAKE) -C . clean - $(MAKE) -E CMFLAGS+=-D\ CMAKE_CXX_FLAGS=-DTEST_B -C . - $(MAKE) -E SERIAL_PORT=/dev/ttyACM1 -C . flash +flash: upload; +upload: $(TARGET) diff --git a/puzzle/neo/CMakeLists.txt b/puzzle/neo/CMakeLists.txt new file mode 100644 index 0000000..6c45f13 --- /dev/null +++ b/puzzle/neo/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 3.29) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_EXPORT_COMPILE_COMMANDS 1) + +# enable debug features +set(CMAKE_BUILD_TYPE Debug) +add_compile_definitions(DEBUG) + +# arduino +set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/lib/Arduino-CMake-Toolchain/Arduino-toolchain.cmake) +set(ARDUINO_BOARD "Arduino Mega or Mega 2560 [avr.mega]") + +# freertos +add_library(freertos_config INTERFACE) +target_include_directories(freertos_config SYSTEM INTERFACE .) +set(FREERTOS_PORT GCC_ATMEGA) +set(FREERTOS_HEAP 4) + +project(pb_mod_neo C CXX) + +add_subdirectory(lib/pbdrv) +add_subdirectory(lib/FreeRTOS-Kernel) + +add_executable(main + main.cpp + mod.c + ) + +target_link_libraries(main PUBLIC + pbdrv-mod + ) +target_link_arduino_libraries(main PUBLIC + core + Wire + Adafruit_seesaw + ) + +# fugly workaround +target_link_arduino_libraries(_arduino_lib_Adafruit_seesaw_Library PUBLIC "Adafruit BusIO") + +target_enable_arduino_upload(main) + diff --git a/puzzle/neo/FreeRTOSConfig.h b/puzzle/neo/FreeRTOSConfig.h new file mode 100644 index 0000000..c0acc49 --- /dev/null +++ b/puzzle/neo/FreeRTOSConfig.h @@ -0,0 +1,52 @@ +#pragma once + +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configMAX_PRIORITIES 32 +#define configMINIMAL_STACK_SIZE ((configSTACK_DEPTH_TYPE) 192) +#define configUSE_16_BIT_TICKS 1 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_APPLICATION_TASK_TAG 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 1 +#define configSTACK_DEPTH_TYPE uint16_t +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 +// #define configTOTAL_HEAP_SIZE (1024) +#define configTOTAL_HEAP_SIZE (5 * 1024) +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_MALLOC_FAILED_HOOK 0 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 0 +#define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_TRACE_FACILITY 0 +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) +#define configTIMER_QUEUE_LENGTH 10 +#define configTIMER_TASK_STACK_DEPTH 92 + +#include <assert.h> +#define configASSERT(x) assert(x) + +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_xTaskResumeFromISR 1 +#define INCLUDE_xQueueGetMutexHolder 1 + diff --git a/puzzle/neo/console-neopuzzle/neo.cpp b/puzzle/neo/console-neopuzzle/neo.cpp deleted file mode 100644 index 56d90f7..0000000 --- a/puzzle/neo/console-neopuzzle/neo.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include <iostream> -#include <array> - -#define MATRIX_SIZE 8 - -enum NeoState { - NEO_UNINITIALIZED, - NEO_PLAYING, - NEO_SOLVED -}; - -// Simulate the 8x8 LED matrix with a 2D array -std::array<std::array<bool, MATRIX_SIZE>, MATRIX_SIZE> neoMatrix; - -NeoState neoState = NEO_UNINITIALIZED; - -// Helper function to toggle LEDs if within bounds -void toggleIfValid(int x, int y) { - if (x >= 0 && x < MATRIX_SIZE && y >= 0 && y < MATRIX_SIZE) { - neoMatrix[x][y] = !neoMatrix[x][y]; - } -} - -void initializeNeoMatrix() { - // The initial pattern from the Appendix A example (assuming red is 'true'/on and white is 'false'/off) - std::array<std::array<bool, MATRIX_SIZE>, MATRIX_SIZE> initialPattern = {{ - {false, true, false, true, false, true, false, true}, - {true, false, true, false, true, false, true, false}, - {false, true, false, true, false, true, false, true}, - {true, false, true, false, true, false, true, false}, - {false, true, false, true, false, true, false, true}, - {true, false, true, false, true, false, true, false}, - {false, true, false, true, false, true, false, true}, - {true, false, true, false, true, false, true, false} - }}; - - for (int i = 0; i < MATRIX_SIZE; i++) { - for (int j = 0; j < MATRIX_SIZE; j++) { - neoMatrix[i][j] = initialPattern[i][j]; - } - } - - neoState = NEO_PLAYING; -} - - -void printNeoMatrix() { - // Print the matrix state to the console - for (int i = 0; i < MATRIX_SIZE; i++) { - for (int j = 0; j < MATRIX_SIZE; j++) { - std::cout << (neoMatrix[i][j] ? 1 : 0) << " "; - } - std::cout << std::endl; - } -} - -void toggleAdjacentLEDs(int x, int y) { - // Toggle the LED at (x, y) and adjacent LEDs - toggleIfValid(x, y); // Center - toggleIfValid(x - 1, y); // Up - toggleIfValid(x + 1, y); // Down - toggleIfValid(x, y - 1); // Left - toggleIfValid(x, y + 1); // Right -} - - -bool isNeoPuzzleSolved() { - for (int i = 0; i < MATRIX_SIZE; i++) { - for (int j = 0; j < MATRIX_SIZE; j++) { - if (neoMatrix[i][j]) return false; // If any LED is on, puzzle is not solved - } - } - return true; -} - -/// Integration needed -int main() { - initializeNeoMatrix(); - printNeoMatrix(); - - while (neoState != NEO_SOLVED) { - int x, y; - std::cout << "Enter the coordinates of the button pressed (x y): "; - std::cin >> x >> y; - - if (x >= 0 && x < MATRIX_SIZE && y >= 0 && y < MATRIX_SIZE) { - toggleAdjacentLEDs(x, y); - printNeoMatrix(); - - if (isNeoPuzzleSolved()) { - neoState = NEO_SOLVED; - std::cout << "The NeoTrellis puzzle is solved!\n"; - } - } else { - std::cout << "Invalid coordinates. Please enter values between 0 and " << MATRIX_SIZE - 1 << ".\n"; - } - } - - return 0; -} diff --git a/puzzle/neo/index.dox b/puzzle/neo/index.dox new file mode 100644 index 0000000..87822e0 --- /dev/null +++ b/puzzle/neo/index.dox @@ -0,0 +1,14 @@ +// vim:ft=doxygen +/** +\ingroup puz +\defgroup puz_neo Neo +\brief NeoTrellis puzzle module + +\par Setup +- Use the Arduino IDE library manager to install the "Adafruit seesaw Library" + library and its dependencies + +\warning There is another library named "Adafruit NeoTrellis M4 Library", this +is not the right library. + +*/ diff --git a/puzzle/neo/lib b/puzzle/neo/lib new file mode 120000 index 0000000..58677dd --- /dev/null +++ b/puzzle/neo/lib @@ -0,0 +1 @@ +../../lib
\ No newline at end of file diff --git a/puzzle/neo/arduino-neopuzzle/arduino-neopuzzle.ino b/puzzle/neo/main.cpp index b334677..13a6859 100644 --- a/puzzle/neo/arduino-neopuzzle/arduino-neopuzzle.ino +++ b/puzzle/neo/main.cpp @@ -1,3 +1,4 @@ +#include <Arduino.h> #include <Wire.h> #include <Adafruit_NeoTrellis.h> @@ -22,6 +23,45 @@ enum NeoState { NeoState neoState = NEO_UNINITIALIZED; +void toggleAdjacentLEDs(int x, int y) { + for (int dx = -1; dx <= 1; ++dx) { + for (int dy = -1; dy <= 1; ++dy) { + if (dx == 0 && dy == 0) continue; // Skip the center button itself + int nx = x + dx, ny = y + dy; + if (nx >= 0 && nx < MATRIX_SIZE && ny >= 0 && ny < MATRIX_SIZE) { + neoMatrix[nx][ny] = !neoMatrix[nx][ny]; + trellis.setPixelColor(nx * MATRIX_SIZE + ny, neoMatrix[nx][ny] ? LED_COLOR_ON : LED_COLOR_OFF); + } + } + } +} + + +bool isNeoPuzzleSolved() { + for (int i = 0; i < MATRIX_SIZE; i++) { + for (int j = 0; j < MATRIX_SIZE; j++) { + if (neoMatrix[i][j]) return false; // If any LED is on, puzzle is not solved + } + } + return true; +} + +TrellisCallback buttonCallback(keyEvent evt) { + int x = evt.bit.NUM / MATRIX_SIZE; + int y = evt.bit.NUM % MATRIX_SIZE; + + if (evt.bit.EDGE == SEESAW_KEYPAD_EDGE_RISING) { + toggleAdjacentLEDs(x, y); + trellis.show(); + if (isNeoPuzzleSolved()) { + neoState = NEO_SOLVED; + Serial.println("The NeoTrellis puzzle is solved!"); + } + } + return 0; +} + + void setup() { Serial.begin(115200); while (!Serial); // Wait for Serial to be ready @@ -55,41 +95,4 @@ void setup() { void loop() { trellis.read(); // Process button events delay(20); -} - -TrellisCallback buttonCallback(keyEvent evt) { - int x = evt.bit.NUM / MATRIX_SIZE; - int y = evt.bit.NUM % MATRIX_SIZE; - - if (evt.bit.EDGE == SEESAW_KEYPAD_EDGE_RISING) { - toggleAdjacentLEDs(x, y); - trellis.show(); - if (isNeoPuzzleSolved()) { - neoState = NEO_SOLVED; - Serial.println("The NeoTrellis puzzle is solved!"); - } - } - return 0; -} - -void toggleAdjacentLEDs(int x, int y) { - for (int dx = -1; dx <= 1; ++dx) { - for (int dy = -1; dy <= 1; ++dy) { - if (dx == 0 && dy == 0) continue; // Skip the center button itself - int nx = x + dx, ny = y + dy; - if (nx >= 0 && nx < MATRIX_SIZE && ny >= 0 && ny < MATRIX_SIZE) { - neoMatrix[nx][ny] = !neoMatrix[nx][ny]; - trellis.setPixelColor(nx * MATRIX_SIZE + ny, neoMatrix[nx][ny] ? LED_COLOR_ON : LED_COLOR_OFF); - } - } - } -} - -bool isNeoPuzzleSolved() { - for (int i = 0; i < MATRIX_SIZE; i++) { - for (int j = 0; j < MATRIX_SIZE; j++) { - if (neoMatrix[i][j]) return false; // If any LED is on, puzzle is not solved - } - } - return true; -} +}
\ No newline at end of file diff --git a/puzzle/neo/makefile b/puzzle/neo/makefile new file mode 100644 index 0000000..26e9157 --- /dev/null +++ b/puzzle/neo/makefile @@ -0,0 +1,8 @@ +TARGET = $(BUILD_DIR)/main.elf + +include ../../lazy.mk + +export SERIAL_PORT ?= /dev/ttyACM0 +flash: upload-main; +upload-main: $(TARGET) + diff --git a/puzzle/neo/mod.c b/puzzle/neo/mod.c new file mode 100644 index 0000000..7157d22 --- /dev/null +++ b/puzzle/neo/mod.c @@ -0,0 +1,6 @@ +#include "pb.h" +#include "pb-mod.h" + +const char * PB_MOD_NAME = "neotrellis"; +const i2c_addr_t PB_MOD_ADDR = PB_ADDR_MOD_NEOTRELLIS; + diff --git a/puzzle/readme.md b/puzzle/readme.md index 59c10b1..1b572ba 100644 --- a/puzzle/readme.md +++ b/puzzle/readme.md @@ -1,15 +1,15 @@ -# puzzles - -This folder contains the source code for all puzzle modules. +\defgroup puz puzzle +\brief Puzzle modules ## Arduino-based puzzle modules -Because of the poorly designed hardware (21-22) used during development -(23-24), some puzzle modules ended up being developed using Arduino boards. All -libraries in this repository use CMake for building (for consistency), which -also means the Arduino based puzzle modules use CMake. The CMakeLists.txt of -some puzzles uses the [Arduino-CMake-Toolchain][arduino-cmake]. To build any of -these subfolders, make sure you have done the following: +> [!NOTE] +> Because of the poorly designed hardware (21-22) used during development +> (23-24), all puzzle modules ended up being developed using Arduino boards. + +The Arduino based puzzle modules also use CMake with the +[Arduino-CMake-Toolchain][arduino-cmake]. To build any of these puzzles, make +sure you have done the following: - Install the official Arduino IDE - Open "Tools" > "Board" > "Board manager" @@ -17,6 +17,8 @@ these subfolders, make sure you have done the following: [arduino-cmake]: https://github.com/a9183756-gh/Arduino-CMake-Toolchain +<!-- + ## ESP-based puzzle modules ### ESP-IDF SDK Setup instructions @@ -29,3 +31,5 @@ these subfolders, make sure you have done the following: - [For windows](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/windows-setup.html#get-started-windows-first-steps) - [For Linux](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/linux-macos-setup.html#get-started-linux-macos-first-steps) +--> + diff --git a/puzzle/vault/CMakeLists.txt b/puzzle/vault/CMakeLists.txt new file mode 100644 index 0000000..bc13c8c --- /dev/null +++ b/puzzle/vault/CMakeLists.txt @@ -0,0 +1,41 @@ +cmake_minimum_required(VERSION 3.29) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_EXPORT_COMPILE_COMMANDS 1) + +# enable debug features +set(CMAKE_BUILD_TYPE Debug) +add_compile_definitions(DEBUG) + +# arduino +set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/lib/Arduino-CMake-Toolchain/Arduino-toolchain.cmake) +set(ARDUINO_BOARD "Arduino Mega or Mega 2560 [avr.mega]") + +# freertos +add_library(freertos_config INTERFACE) +target_include_directories(freertos_config SYSTEM INTERFACE .) +set(FREERTOS_PORT GCC_ATMEGA) +set(FREERTOS_HEAP 4) + +project(pb_mod_vault C CXX) + +add_subdirectory(lib/pbdrv) +add_subdirectory(lib/FreeRTOS-Kernel) + +add_executable(main + main.cpp + mod.c + ) + +target_link_libraries(main PUBLIC + pbdrv-mod + ) +target_link_arduino_libraries(main PUBLIC + core + Wire + TM1637 + ) + +target_enable_arduino_upload(main) + diff --git a/puzzle/vault/FreeRTOSConfig.h b/puzzle/vault/FreeRTOSConfig.h new file mode 100644 index 0000000..c0acc49 --- /dev/null +++ b/puzzle/vault/FreeRTOSConfig.h @@ -0,0 +1,52 @@ +#pragma once + +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configMAX_PRIORITIES 32 +#define configMINIMAL_STACK_SIZE ((configSTACK_DEPTH_TYPE) 192) +#define configUSE_16_BIT_TICKS 1 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_APPLICATION_TASK_TAG 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 1 +#define configSTACK_DEPTH_TYPE uint16_t +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 +// #define configTOTAL_HEAP_SIZE (1024) +#define configTOTAL_HEAP_SIZE (5 * 1024) +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_MALLOC_FAILED_HOOK 0 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 0 +#define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_TRACE_FACILITY 0 +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) +#define configTIMER_QUEUE_LENGTH 10 +#define configTIMER_TASK_STACK_DEPTH 92 + +#include <assert.h> +#define configASSERT(x) assert(x) + +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_xTaskResumeFromISR 1 +#define INCLUDE_xQueueGetMutexHolder 1 + diff --git a/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino b/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino deleted file mode 100644 index 4dd8ac8..0000000 --- a/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino +++ /dev/null @@ -1,150 +0,0 @@ -#include <Wire.h> -#include <TM1637Display.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 - -// 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}; - -typedef enum { - STATE_UNINITIALIZED = 0x00, - STATE_RESET = 0x01, - STATE_PLAYING = 0x02, - STATE_SOLVED = 0x03, - STATE_ERROR = 0x04 -} PuzzleState; - -const char* validButtons[TOTAL_LEVELS] = {"A2", "B1", "D3", "C2", "C1"}; -PuzzleState puzzleState = STATE_UNINITIALIZED; -int currentLevel = 0; - -// Function prototypes -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); // 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 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() { - // 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 - } - // 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); - // 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() { - 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 - 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 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."); -} diff --git a/puzzle/vault/console-vaultpuzzle/vault.cpp b/puzzle/vault/console-vaultpuzzle/vault.cpp deleted file mode 100644 index 3566b3e..0000000 --- a/puzzle/vault/console-vaultpuzzle/vault.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include <iostream> -#include <string> -#include <array> - -// 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<std::string, TOTAL_LEVELS> 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; -} diff --git a/puzzle/vault/index.dox b/puzzle/vault/index.dox new file mode 100644 index 0000000..15eae1f --- /dev/null +++ b/puzzle/vault/index.dox @@ -0,0 +1,11 @@ +// vim:ft=doxygen +/** +\ingroup puz +\defgroup puz_vault Vault +\brief Vault puzzle module + +\par Setup +- Use the Arduino IDE library manager to install the "TM1637" library (by + Avishay Orpaz) and its dependencies + +*/ diff --git a/puzzle/vault/lib b/puzzle/vault/lib new file mode 120000 index 0000000..58677dd --- /dev/null +++ b/puzzle/vault/lib @@ -0,0 +1 @@ +../../lib
\ No newline at end of file diff --git a/puzzle/vault/main.cpp b/puzzle/vault/main.cpp new file mode 100644 index 0000000..2e4cafc --- /dev/null +++ b/puzzle/vault/main.cpp @@ -0,0 +1,187 @@ +#include <Arduino.h> +#include <TM1637Display.h> +#include "lib/pbdrv/pb-types.h" +#include "lib/pbdrv/pb-mod.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"; +const uint8_t SEGMENT_MAP[] = { + 0b00111111, // 0 + 0b00000110, // 1 + 0b01011011, // 2 + 0b01001111, // 3 + 0b01100110, // 4 + 0b01101101, // 5 + 0b01111101, // 6 + 0b00000111, // 7 + 0b01111111, // 8 + 0b01101111, // 9 + 0b01110111, // A + 0b01111100, // B + 0b00111001, // C + 0b01011110, // D + 0b01111001, // E + 0b01110001 // F + // Add other letters if needed +}; + +// This array of level codes matches the codes you might display per level. +const char* levelCodes[TOTAL_LEVELS] = {"A1", "B2", "D1", "C3", "A2"}; + + +// Puzzle state +pb_global_state_t puzzleState = PB_GS_NOINIT; + +TM1637Display display(CLK, DIO); + +int currentLevel = 0; + +void blink_display(int num) { + if (num == 1) { + // Display "1111" with leading zeros shown if necessary + display.showNumberDecEx(1111, 0b11111111, true); + } else if (num == 0) { + // Display "0000" with leading zeros shown if necessary + display.showNumberDecEx(0, 0b11111111, true); + } + 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) { + pb_hook_mod_state_write(PB_GS_SOLVED); + Serial.println("Puzzle solved!"); + display.showNumberDec(currentLevel + 1, true); + digitalWrite(SOLVED_PIN, HIGH); + } + } 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 display_code_for_level(int level) { + char code[3] = {0}; // Temp storage for level code + strncpy(code, levelCodes[level], 2); // Copy the level-specific code + + uint8_t segs[4] = {0}; // Segments to send to the display + + // Check if the first character is a letter and map it + if (isalpha(code[0])) { + if (code[0] >= 'A' && code[0] <= 'F') { + segs[0] = SEGMENT_MAP[code[0] - 'A' + 10]; // Maps A-F to their segment patterns + } else { + // Handle unexpected characters or extend SEGMENT_MAP for more letters + segs[0] = 0; // Display nothing for undefined letters + } + } else { + // Assume it's a number and map directly + segs[0] = SEGMENT_MAP[code[0] - '0']; + } + + // Check if the second character is a digit and map it + if (isdigit(code[1])) { + segs[1] = SEGMENT_MAP[code[1] - '0']; + } else { + // Handle unexpected characters + segs[1] = 0; // Display nothing for undefined digits + } + + // Set only the first two segments, leave others blank + display.setSegments(segs, 2, 0); // Display on leftmost two digits +} + + +pb_global_state_t pb_hook_mod_state_read() { + return puzzleState; +} + +void pb_hook_mod_state_write(pb_global_state_t state) { + puzzleState = state; +} + +void setup() { + Serial.begin(115200); + pinMode(SOLVED_PIN, OUTPUT); + digitalWrite(SOLVED_PIN, LOW); + display.setBrightness(0x0f); + initialize_system(); +} + +void loop() { + switch(puzzleState) { + case PB_GS_PLAYING: + display_code_for_level(currentLevel); + check_button_press(); + delay(100); + break; + case PB_GS_SOLVED: + Serial.println("STATE = PB_GS_SOLVED"); + display_final_code(bombCode); + digitalWrite(SOLVED_PIN, HIGH); + break; + case PB_GS_NOINIT: + Serial.println("STATE = PB_GS_NOINIT"); + blink_display(0); + break; + case PB_GS_IDLE: + Serial.println("STATE = PB_GS_IDLE"); + blink_display(1); + break; + } +}
\ No newline at end of file diff --git a/puzzle/vault/makefile b/puzzle/vault/makefile new file mode 100644 index 0000000..f33ca7e --- /dev/null +++ b/puzzle/vault/makefile @@ -0,0 +1,8 @@ +TARGET = $(BUILD_DIR)/main.elf + +include ../../lazy.mk + +export SERIAL_PORT ?= /dev/ttyUSB0 +flash: upload; +upload: $(TARGET) + diff --git a/puzzle/vault/mod.c b/puzzle/vault/mod.c new file mode 100644 index 0000000..bae8a3d --- /dev/null +++ b/puzzle/vault/mod.c @@ -0,0 +1,6 @@ +#include "pb.h" +#include "pb-mod.h" + +const char * PB_MOD_NAME = "vault"; +const i2c_addr_t PB_MOD_ADDR = PB_ADDR_MOD_VAULT; + |