From 9664deb3e817b616dd1e8f73a89c0703a0771464 Mon Sep 17 00:00:00 2001 From: Elwin Date: Sun, 23 Jun 2024 11:31:15 +0200 Subject: Neotrellis Freertos support --- puzzle/dummy/CMakeLists.txt | 4 +- puzzle/neo/CMakeLists.txt | 52 +++++++++++ puzzle/neo/FreeRTOSConfig.h | 52 +++++++++++ puzzle/neo/arduino-neopuzzle/arduino-neopuzzle.ino | 95 -------------------- puzzle/neo/console-neopuzzle/neo.cpp | 100 --------------------- puzzle/neo/lib | 1 + puzzle/neo/main.cpp | 98 ++++++++++++++++++++ puzzle/neo/makefile | 20 +++++ puzzle/neo/mod.c | 6 ++ puzzle/readme.md | 2 + 10 files changed, 233 insertions(+), 197 deletions(-) create mode 100644 puzzle/neo/CMakeLists.txt create mode 100644 puzzle/neo/FreeRTOSConfig.h delete mode 100644 puzzle/neo/arduino-neopuzzle/arduino-neopuzzle.ino delete mode 100644 puzzle/neo/console-neopuzzle/neo.cpp create mode 120000 puzzle/neo/lib create mode 100644 puzzle/neo/main.cpp create mode 100644 puzzle/neo/makefile create mode 100644 puzzle/neo/mod.c diff --git a/puzzle/dummy/CMakeLists.txt b/puzzle/dummy/CMakeLists.txt index 6acc4c8..0d508ae 100644 --- a/puzzle/dummy/CMakeLists.txt +++ b/puzzle/dummy/CMakeLists.txt @@ -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/neo/CMakeLists.txt b/puzzle/neo/CMakeLists.txt new file mode 100644 index 0000000..db3aadc --- /dev/null +++ b/puzzle/neo/CMakeLists.txt @@ -0,0 +1,52 @@ +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) +# add_compile_options(-O0) # no optimizations + +# 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]") + +# freertos +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_HEAP 4) + +# used for testing +# set(ARDUINO_BOARD "Raspberry Pi Pico W [rp2040.rpipicow]") +# add_compile_definitions(USE_TINYUSB) +# include_directories(/home/loek/.arduino15/packages/rp2040/hardware/rp2040/3.9.2/libraries/Adafruit_TinyUSB_Arduino/src/arduino) + +project(pb_mod_dummy 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 + ) + +#Adafruit workarround +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 +#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/arduino-neopuzzle/arduino-neopuzzle.ino b/puzzle/neo/arduino-neopuzzle/arduino-neopuzzle.ino deleted file mode 100644 index b334677..0000000 --- a/puzzle/neo/arduino-neopuzzle/arduino-neopuzzle.ino +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#define MATRIX_SIZE 8 -#define LED_COLOR_ON 0xFFFFFF // Color of the LEDs in ON state -#define LED_COLOR_OFF 0x000000 // Color of the LEDs in OFF state - -Adafruit_NeoTrellis t_array[MATRIX_SIZE / 4][MATRIX_SIZE / 4] = { - {Adafruit_NeoTrellis(0x2E), Adafruit_NeoTrellis(0x2F)}, - {Adafruit_NeoTrellis(0x30), Adafruit_NeoTrellis(0x32)} -}; - -Adafruit_MultiTrellis trellis((Adafruit_NeoTrellis *)t_array, MATRIX_SIZE / 4, MATRIX_SIZE / 4); - -bool neoMatrix[MATRIX_SIZE][MATRIX_SIZE]; // To track state of each pixel - -enum NeoState { - NEO_UNINITIALIZED, - NEO_PLAYING, - NEO_SOLVED -}; - -NeoState neoState = NEO_UNINITIALIZED; - -void setup() { - Serial.begin(115200); - while (!Serial); // Wait for Serial to be ready - - if (!trellis.begin()) { - Serial.println("Failed to initialize NeoTrellis"); - while (1) delay(1); - } - - // Initialize the matrix with a checkerboard pattern - bool toggle = false; - for (int i = 0; i < MATRIX_SIZE; i++) { - for (int j = 0; j < MATRIX_SIZE; j++) { - neoMatrix[i][j] = toggle; - toggle = !toggle; - trellis.setPixelColor(i * MATRIX_SIZE + j, neoMatrix[i][j] ? LED_COLOR_ON : LED_COLOR_OFF); - } - toggle = !toggle; - } - trellis.show(); - neoState = NEO_PLAYING; - - // Register the callback for each key - for (int i = 0; i < MATRIX_SIZE * MATRIX_SIZE; i++) { - trellis.activateKey(i, SEESAW_KEYPAD_EDGE_RISING, true); - trellis.activateKey(i, SEESAW_KEYPAD_EDGE_FALLING, true); - trellis.registerCallback(i, buttonCallback); - } -} - -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; -} 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 -#include - -#define MATRIX_SIZE 8 - -enum NeoState { - NEO_UNINITIALIZED, - NEO_PLAYING, - NEO_SOLVED -}; - -// Simulate the 8x8 LED matrix with a 2D array -std::array, 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, 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/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/main.cpp b/puzzle/neo/main.cpp new file mode 100644 index 0000000..13a6859 --- /dev/null +++ b/puzzle/neo/main.cpp @@ -0,0 +1,98 @@ +#include +#include +#include + +#define MATRIX_SIZE 8 +#define LED_COLOR_ON 0xFFFFFF // Color of the LEDs in ON state +#define LED_COLOR_OFF 0x000000 // Color of the LEDs in OFF state + +Adafruit_NeoTrellis t_array[MATRIX_SIZE / 4][MATRIX_SIZE / 4] = { + {Adafruit_NeoTrellis(0x2E), Adafruit_NeoTrellis(0x2F)}, + {Adafruit_NeoTrellis(0x30), Adafruit_NeoTrellis(0x32)} +}; + +Adafruit_MultiTrellis trellis((Adafruit_NeoTrellis *)t_array, MATRIX_SIZE / 4, MATRIX_SIZE / 4); + +bool neoMatrix[MATRIX_SIZE][MATRIX_SIZE]; // To track state of each pixel + +enum NeoState { + NEO_UNINITIALIZED, + NEO_PLAYING, + NEO_SOLVED +}; + +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 + + if (!trellis.begin()) { + Serial.println("Failed to initialize NeoTrellis"); + while (1) delay(1); + } + + // Initialize the matrix with a checkerboard pattern + bool toggle = false; + for (int i = 0; i < MATRIX_SIZE; i++) { + for (int j = 0; j < MATRIX_SIZE; j++) { + neoMatrix[i][j] = toggle; + toggle = !toggle; + trellis.setPixelColor(i * MATRIX_SIZE + j, neoMatrix[i][j] ? LED_COLOR_ON : LED_COLOR_OFF); + } + toggle = !toggle; + } + trellis.show(); + neoState = NEO_PLAYING; + + // Register the callback for each key + for (int i = 0; i < MATRIX_SIZE * MATRIX_SIZE; i++) { + trellis.activateKey(i, SEESAW_KEYPAD_EDGE_RISING, true); + trellis.activateKey(i, SEESAW_KEYPAD_EDGE_FALLING, true); + trellis.registerCallback(i, buttonCallback); + } +} + +void loop() { + trellis.read(); // Process button events + delay(20); +} \ No newline at end of file diff --git a/puzzle/neo/makefile b/puzzle/neo/makefile new file mode 100644 index 0000000..509d8e3 --- /dev/null +++ b/puzzle/neo/makefile @@ -0,0 +1,20 @@ +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 + diff --git a/puzzle/neo/mod.c b/puzzle/neo/mod.c new file mode 100644 index 0000000..058a585 --- /dev/null +++ b/puzzle/neo/mod.c @@ -0,0 +1,6 @@ +#include "pb.h" +#include "pb-mod.h" + +const char * PB_MOD_NAME = "dummy"; +const i2c_addr_t PB_MOD_ADDR = PB_ADDR_MOD_DUMMY; + diff --git a/puzzle/readme.md b/puzzle/readme.md index 959c506..21cddd3 100644 --- a/puzzle/readme.md +++ b/puzzle/readme.md @@ -19,6 +19,8 @@ of these subfolders, make sure you have done the following: - Install the official Arduino IDE - Open "Tools" > "Board" > "Board manager" - Install the "Arduino AVR Boards" package (1.8.6 works at the time of writing) +- Install the Adafruit seesaw library and dependicies (for the neotrellis puzzle) +- Install the TM1637 library from Avishay Orpaz [arduino-cmake]: https://github.com/a9183756-gh/Arduino-CMake-Toolchain -- cgit v1.2.3