From 58e4a4ad81e193fbaef39affbc31bd8e99b62aa6 Mon Sep 17 00:00:00 2001 From: Nengzhuo Cai Date: Sun, 5 Oct 2025 11:19:08 -0400 Subject: [PATCH 01/17] FE Compiles --- .gitmodules | 18 + Applications/Shell/Shell.cpp | 4 + Applications/Shell/Shell.h | 4 +- CMakeLists.txt | 24 +- Devices/MatrixBlock5/ApplicationList.txt | 45 ++ Devices/MatrixBlock5/CMakeLists.txt | 194 ++++++++ Devices/MatrixBlock5/Config.cmake | 5 + Devices/MatrixBlock5/Drivers/BKP.cpp | 34 ++ Devices/MatrixBlock5/Drivers/Keypad.cpp | 184 +++++++ Devices/MatrixBlock5/Drivers/LED.cpp | 65 +++ Devices/MatrixBlock5/Drivers/NVS.cpp | 56 +++ Devices/MatrixBlock5/Drivers/NVS.h | 56 +++ Devices/MatrixBlock5/Drivers/dcd_stm32f1.c | 123 +++++ Devices/MatrixBlock5/Family.cpp | 313 ++++++++++++ Devices/MatrixBlock5/Family.h | 163 ++++++ Devices/MatrixBlock5/FreeRTOSConfig.h | 193 +++++++ Devices/MatrixBlock5/MatrixOSConfig.h | 46 ++ Devices/MatrixBlock5/STM32F103RETX_FLASH.ld | 177 +++++++ .../Variants/MatrixFounderEdition/Config.h | 137 +++++ .../MatrixFounderEdition/FounderEdition.cpp | 30 ++ .../FounderEdition.cpp.bak | 307 ++++++++++++ .../STM32F103RETX_FLASH.ld | 177 +++++++ .../Variants/MatrixFounderEdition/note.txt | 1 + .../MatrixFounderEdition/stm32f1xx_hal_conf.h | 378 ++++++++++++++ Devices/MatrixBlock5/family.mk | 74 +++ Devices/MatrixBlock5/main.cpp | 98 ++++ Devices/MatrixBlock5/note.txt | 1 + Devices/MatrixBlock5/startup_stm32f103xe.s | 470 ++++++++++++++++++ .../MatrixBlock5/toolchain-stm32f103.cmake | 41 ++ Devices/MatrixESP32/Config.cmake | 5 + Devices/MatrixESP32/MatrixOSConfig.h | 4 - Library/CMSIS_5 | 1 + Library/FreeRTOS-Kernel | 1 + OS/FileSystem/CMakeLists.txt | 30 +- OS/Framework/Color/Color.cpp | 1 + OS/Framework/Storage/SavedVar.h | 2 +- OS/System/System.cpp | 4 + OS/UI/UIUtilities.h | 1 + OS/USB/CMakeLists.txt | 40 +- OS/USB/TinyUSB/tusb_config.h | 4 + OS/USB/TinyUSB/usb_descriptors.cpp | 4 + OS/USB/USB.h | 7 +- Platform/CMakeLists.txt | 26 - Platform/STM32F1/WS2812/CMakeLists.txt | 20 + Platform/STM32F1/WS2812/WS2812.cpp | 148 ++++++ Platform/STM32F1/WS2812/WS2812.h | 22 + Platform/STM32F1/cmsis_device_f1 | 1 + Platform/STM32F1/stm32f1xx_hal_driver | 1 + 48 files changed, 3686 insertions(+), 54 deletions(-) create mode 100644 Devices/MatrixBlock5/ApplicationList.txt create mode 100644 Devices/MatrixBlock5/CMakeLists.txt create mode 100644 Devices/MatrixBlock5/Config.cmake create mode 100644 Devices/MatrixBlock5/Drivers/BKP.cpp create mode 100644 Devices/MatrixBlock5/Drivers/Keypad.cpp create mode 100644 Devices/MatrixBlock5/Drivers/LED.cpp create mode 100644 Devices/MatrixBlock5/Drivers/NVS.cpp create mode 100644 Devices/MatrixBlock5/Drivers/NVS.h create mode 100644 Devices/MatrixBlock5/Drivers/dcd_stm32f1.c create mode 100644 Devices/MatrixBlock5/Family.cpp create mode 100644 Devices/MatrixBlock5/Family.h create mode 100644 Devices/MatrixBlock5/FreeRTOSConfig.h create mode 100644 Devices/MatrixBlock5/MatrixOSConfig.h create mode 100644 Devices/MatrixBlock5/STM32F103RETX_FLASH.ld create mode 100644 Devices/MatrixBlock5/Variants/MatrixFounderEdition/Config.h create mode 100644 Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp create mode 100644 Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp.bak create mode 100644 Devices/MatrixBlock5/Variants/MatrixFounderEdition/STM32F103RETX_FLASH.ld create mode 100644 Devices/MatrixBlock5/Variants/MatrixFounderEdition/note.txt create mode 100644 Devices/MatrixBlock5/Variants/MatrixFounderEdition/stm32f1xx_hal_conf.h create mode 100644 Devices/MatrixBlock5/family.mk create mode 100644 Devices/MatrixBlock5/main.cpp create mode 100644 Devices/MatrixBlock5/note.txt create mode 100644 Devices/MatrixBlock5/startup_stm32f103xe.s create mode 100644 Devices/MatrixBlock5/toolchain-stm32f103.cmake create mode 100644 Devices/MatrixESP32/Config.cmake create mode 160000 Library/CMSIS_5 create mode 160000 Library/FreeRTOS-Kernel delete mode 100644 Platform/CMakeLists.txt create mode 100644 Platform/STM32F1/WS2812/CMakeLists.txt create mode 100644 Platform/STM32F1/WS2812/WS2812.cpp create mode 100644 Platform/STM32F1/WS2812/WS2812.h create mode 160000 Platform/STM32F1/cmsis_device_f1 create mode 160000 Platform/STM32F1/stm32f1xx_hal_driver diff --git a/.gitmodules b/.gitmodules index 5a13a8de..6b7098dc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -11,3 +11,21 @@ path = Library/ArduinoJson url = https://github.com/bblanchon/ArduinoJson.git branch = 7.x +[submodule "Library/FreeRTOS-Kernel"] + path = Library/FreeRTOS-Kernel + url = https://github.com/FreeRTOS/FreeRTOS-Kernel.git +[submodule "Library/cmsis_device_f1"] + path = Library/cmsis_device_f1 + url = https://github.com/STMicroelectronics/cmsis_device_f1.git +[submodule "Library/stm32f1xx_hal_driver"] + path = Library/stm32f1xx_hal_driver + url = https://github.com/STMicroelectronics/stm32f1xx_hal_driver.git +[submodule "Library/CMSIS_5"] + path = Library/CMSIS_5 + url = https://github.com/ARM-software/CMSIS_5.git +[submodule "Platform/STM32F1/cmsis_device_f1"] + path = Platform/STM32F1/cmsis_device_f1 + url = https://github.com/STMicroelectronics/cmsis_device_f1.git +[submodule "Platform/STM32F1/stm32f1xx_hal_driver"] + path = Platform/STM32F1/stm32f1xx_hal_driver + url = https://github.com/STMicroelectronics/stm32f1xx_hal_driver.git diff --git a/Applications/Shell/Shell.cpp b/Applications/Shell/Shell.cpp index f648b3b4..35409384 100644 --- a/Applications/Shell/Shell.cpp +++ b/Applications/Shell/Shell.cpp @@ -66,7 +66,9 @@ void Shell::InitializeFolderSystem() { } // Then discover and add Python applications +#if DEVICE_STORAGE DiscoverPythonApps(); +#endif // Try to load existing folder vectors from NVS bool folders_loaded = false; @@ -359,6 +361,7 @@ uint8_t Shell::GetAppFolder(uint32_t app_id, const ApplicationEntry& app_entry) return 0; } +#if DEVICE_STORAGE void Shell::DiscoverPythonApps() { MLOGI("Shell", "Starting Python application discovery"); @@ -385,6 +388,7 @@ void Shell::DiscoverPythonApps() { MLOGI("Shell", "Python application discovery completed: %d apps added", python_app_infos.size()); } +#endif void Shell::ApplicationLauncher() { uint8_t tap_counter = 0; diff --git a/Applications/Shell/Shell.h b/Applications/Shell/Shell.h index 29ca0556..41fe316f 100644 --- a/Applications/Shell/Shell.h +++ b/Applications/Shell/Shell.h @@ -84,8 +84,10 @@ class Shell : public Application { void MoveAppToFolder(uint32_t app_id, uint8_t folder_id); // Python application discovery +#if DEVICE_STORAGE void DiscoverPythonApps(); - +#endif + // Helper functions for NVS void SaveFolderVector(uint8_t folder_id); void LoadFolderVector(uint8_t folder_id); diff --git a/CMakeLists.txt b/CMakeLists.txt index 6da50b17..e2167acb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,15 @@ cmake_minimum_required(VERSION 3.16) +if(NOT DEFINED DEVICE) + message(FATAL_ERROR "You must specify -DDEVICE=") +endif() + +if(NOT DEFINED FAMILY) + set(FAMILY_PATH ${CMAKE_SOURCE_DIR}/Devices/${DEVICE}) +else() + set(FAMILY_PATH ${CMAKE_SOURCE_DIR}/Devices/${FAMILY}) +endif() + project(MatrixOS-${DEVICE}) # # Global C flags @@ -83,7 +93,19 @@ else() message( FATAL_ERROR "MODE is not defined" ) endif() +# Load device feature flags before processing subdirectories +if(NOT EXISTS ${FAMILY_PATH}/Config.cmake) + message(FATAL_ERROR "Config.cmake not found in ${FAMILY_PATH}. Please create this file to define DEVICE_STORAGE and DEVICE_BATTERY.") +endif() +include(${FAMILY_PATH}/Config.cmake) + +# Pass device feature flags as compile definitions to all targets +add_compile_definitions( + DEVICE_STORAGE=${DEVICE_STORAGE} + DEVICE_BATTERY=${DEVICE_BATTERY} +) + +add_subdirectory(${FAMILY_PATH}) add_subdirectory(Devices) add_subdirectory(OS) -add_subdirectory(${FAMILY_PATH}) add_subdirectory(Applications) diff --git a/Devices/MatrixBlock5/ApplicationList.txt b/Devices/MatrixBlock5/ApplicationList.txt new file mode 100644 index 00000000..868e98f9 --- /dev/null +++ b/Devices/MatrixBlock5/ApplicationList.txt @@ -0,0 +1,45 @@ +# Applications List - MatrixBlock5 +# Format: +# FolderName - Regular application (sandboxed) +# [System]FolderName - System application (privileged) +# git:URL@branch/hash - Clone git repository at specific branch/commit +# [System]git:URL@branch - System application from git repository +# Applications register their class via RegisterApplicationClass() in their CMakeLists.txt +# Git applications are cloned to {FAMILY_PATH}/Applications/ directory +# Use # for comments and empty lines are allowed +# +# Git URL Examples: +# git:https://github.com/user/myapp@main +# git:https://github.com/user/myapp@v1.2.3 +# git:https://github.com/user/myapp@abc123d +# [System]git:https://github.com/user/sysapp@feature-branch + +# Device UI +Setting +BrightnessControl + +# System Apps +[System]Shell +#MSC + +# User Facing Apps +Performance +#Note +#REDACTED +#Companion +#CustomControlMap +#Lighting +#Dice +#Reversi +#Strum +#[System]Python + +# Boot animation +{FAMILY_PATH}/Applications/BootAnimation + +# Device-specific applications (if any) +# {FAMILY_PATH}/Applications/FactoryMenu +# {FAMILY_PATH}/Applications/ForceCalibration + +# Example application template +#git:https://github.com/203-Systems/Matrix-OS-APP-Template.git@master \ No newline at end of file diff --git a/Devices/MatrixBlock5/CMakeLists.txt b/Devices/MatrixBlock5/CMakeLists.txt new file mode 100644 index 00000000..44806bc4 --- /dev/null +++ b/Devices/MatrixBlock5/CMakeLists.txt @@ -0,0 +1,194 @@ +# MatrixBlock5 uses STM32F103 +set(DEVICE_TARGET "STM32F103") + +# Set up STM32CubeIDE toolchain if available +if(NOT DEFINED STM32_TOOLCHAIN_PATH) + message(FATAL_ERROR "STM32 toolchain not defined. Please set STM32_TOOLCHAIN_PATH environment variable.") +endif() + +# Include the STM32 toolchain file +include(${CMAKE_CURRENT_SOURCE_DIR}/toolchain-stm32f103.cmake) + +# Common compiler flags for STM32F103 +set(COMMON_FLAGS "-mcpu=cortex-m3 -mthumb -mfloat-abi=soft -mabi=aapcs -nostartfiles") +set(CMAKE_C_FLAGS "${COMMON_FLAGS} -std=gnu11 -Wno-unused-command-line-argument") +set(CMAKE_CXX_FLAGS "${COMMON_FLAGS} -fno-rtti -fno-exceptions -Wno-unused-command-line-argument") +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_ASM_FLAGS "${COMMON_FLAGS} -x assembler-with-cpp") + +# Force Thumb mode for all compilation and assembly +# Add -w to suppress all compiler warnings as well +# Use -mthumb-interwork to improve Thumb compatibility +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb-interwork -Wa,-mthumb -Wa,-mimplicit-it=always -Wa,-mcpu=cortex-m3 -Wa,-W -w") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mthumb-interwork -Wa,-mthumb -Wa,-mimplicit-it=always -Wa,-mcpu=cortex-m3 -Wa,-W -w") +set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -mthumb-interwork -Wa,-mthumb -Wa,-mimplicit-it=always -Wa,-mcpu=cortex-m3 -Wa,-W -w") + +# Disable assembler warnings being treated as errors globally - be more aggressive +# CMake should not fail on compiler warnings +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error -Wno-error=all") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error -Wno-error=all") +set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wno-error -Wno-error=all") + +# Tell CMake to not fail on warnings +set(CMAKE_COMPILE_WARNING_AS_ERROR OFF) + +# TinyUSB compile options for STM32F1 +# These flags reduce optimization to avoid complex ARM assembly warnings +set(DEVICE_TINYUSB_COMPILE_OPTIONS + "-O0" + "-Wno-implicit-fallthrough" + "-Wno-format" + "-fno-lto" + "-fno-fat-lto-objects" +) + +# Debug flags +if(MODE STREQUAL "DEVELOPMENT" OR MODE STREQUAL "UNDEFINED") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Og") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Og") +else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Os") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Os") +endif() + +# Linker flags +set(CMAKE_EXE_LINKER_FLAGS "${COMMON_FLAGS} -specs=nosys.specs -specs=nano.specs -Wl,--gc-sections -Wl,-Map=${PROJECT_NAME}.map -T${CMAKE_CURRENT_SOURCE_DIR}/Variants/MatrixFounderEdition/STM32F103RETx_FLASH.ld") + +# Collect all device source files +file(GLOB_RECURSE DEVICE_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/Family.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/Drivers/*.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/Variants/MatrixFounderEdition/*.cpp" +) + +# STM32 HAL source files +set(STM32_HAL_SOURCES + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/stm32f1xx_hal_driver/Src/stm32f1xx_hal.c + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/stm32f1xx_hal_driver/Src/stm32f1xx_hal_cortex.c + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/stm32f1xx_hal_driver/Src/stm32f1xx_hal_rcc.c + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/stm32f1xx_hal_driver/Src/stm32f1xx_hal_rcc_ex.c + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/stm32f1xx_hal_driver/Src/stm32f1xx_hal_gpio.c + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/stm32f1xx_hal_driver/Src/stm32f1xx_hal_dma.c + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/stm32f1xx_hal_driver/Src/stm32f1xx_hal_tim.c + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/stm32f1xx_hal_driver/Src/stm32f1xx_hal_tim_ex.c + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/stm32f1xx_hal_driver/Src/stm32f1xx_hal_pwr.c + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/stm32f1xx_hal_driver/Src/stm32f1xx_hal_rtc.c + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/stm32f1xx_hal_driver/Src/stm32f1xx_hal_rtc_ex.c + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/stm32f1xx_hal_driver/Src/stm32f1xx_hal_flash.c + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/stm32f1xx_hal_driver/Src/stm32f1xx_hal_flash_ex.c + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/cmsis_device_f1/Source/Templates/system_stm32f1xx.c +) + +file(GLOB_RECURSE DEVICE_HEADERS + "${CMAKE_CURRENT_SOURCE_DIR}/*.h" + "${CMAKE_CURRENT_SOURCE_DIR}/Drivers/*.h" + "${CMAKE_CURRENT_SOURCE_DIR}/Variants/MatrixFounderEdition/*.h" +) + +add_library(MatrixOSDevice + ${DEVICE_SOURCES} + ${STM32_HAL_SOURCES} + ${DEVICE_HEADERS} + ${CMAKE_CURRENT_SOURCE_DIR}/Drivers/dcd_stm32f1.c + ${CMAKE_CURRENT_SOURCE_DIR}/startup_stm32f103xe.s +) + +target_include_directories(MatrixOSDevice PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/Variants/MatrixFounderEdition + ${CMAKE_SOURCE_DIR}/Platform/STM32F1 + ${CMAKE_SOURCE_DIR}/Library/FatFs/source + ${CMAKE_SOURCE_DIR}/Library/FreeRTOS-Kernel/include + ${CMAKE_SOURCE_DIR}/Library/FreeRTOS-Kernel/portable/GCC/ARM_CM3 + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/cmsis_device_f1/Include + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/stm32f1xx_hal_driver/Inc + ${CMAKE_SOURCE_DIR}/Library/CMSIS_5/CMSIS/Core/Include + ${CMAKE_SOURCE_DIR}/Library/tinyusb/src + ${CMAKE_SOURCE_DIR}/OS/USB/TinyUSB +) + +# Add FreeRTOSConfig.h directory to compiler include paths +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +# Add FreeRTOS library +add_library(FreeRTOS STATIC + ${CMAKE_SOURCE_DIR}/Library/FreeRTOS-Kernel/FreeRTOS/Source/list.c + ${CMAKE_SOURCE_DIR}/Library/FreeRTOS-Kernel/FreeRTOS/Source/queue.c + ${CMAKE_SOURCE_DIR}/Library/FreeRTOS-Kernel/FreeRTOS/Source/tasks.c + ${CMAKE_SOURCE_DIR}/Library/FreeRTOS-Kernel/FreeRTOS/Source/timers.c + ${CMAKE_SOURCE_DIR}/Library/FreeRTOS-Kernel/FreeRTOS/Source/event_groups.c + ${CMAKE_SOURCE_DIR}/Library/FreeRTOS-Kernel/FreeRTOS/Source/stream_buffer.c + ${CMAKE_SOURCE_DIR}/Library/FreeRTOS-Kernel/FreeRTOS/Source/portable/MemMang/heap_4.c + ${CMAKE_SOURCE_DIR}/Library/FreeRTOS-Kernel/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c +) + +# Add FreeRTOS library with proper include paths +target_include_directories(FreeRTOS PUBLIC + ${CMAKE_SOURCE_DIR}/Library/FreeRTOS-Kernel/FreeRTOS/Source/include + ${CMAKE_SOURCE_DIR}/Library/FreeRTOS-Kernel/FreeRTOS/Source/portable/GCC/ARM_CM3 + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/Variants/MatrixFounderEdition + ${CMAKE_SOURCE_DIR}/Platform/STM32F1 + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/cmsis_device_f1/Include + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/stm32f1xx_hal_driver/Inc + ${CMAKE_SOURCE_DIR}/Library/CMSIS_5/CMSIS/Core/Include +) + +# Apply Thumb mode compiler flags to FreeRTOS target +target_compile_options(FreeRTOS PUBLIC + "-Wa,-mthumb" + "-Wa,-mimplicit-it=thumb" + "-Wa,-mcpu=cortex-m3" +) + +# Add Thumb-2 definition for FreeRTOS +target_compile_definitions(FreeRTOS PUBLIC + __thumb2__=1 +) + +# STM32F103 specific definitions +# Note: VDD_VALUE, PREFETCH_ENABLE, HSE/LSE/HSI/LSI values are defined in stm32f1xx_hal_conf.h +target_compile_definitions(MatrixOSDevice PUBLIC + STM32F103xB + USE_HAL_DRIVER + CFG_TUSB_MCU=OPT_MCU_STM32F1 + __thumb2__=1 +) + +# Set C++ standard for MatrixOSDevice target +target_compile_features(MatrixOSDevice PUBLIC cxx_std_17) + +# Link with MatrixOS framework and FreeRTOS +target_link_libraries(MatrixOSDevice PUBLIC + DeviceInterface + MatrixOSFramework + FreeRTOS +) + +# Create executable +set(elf_file ${CMAKE_PROJECT_NAME}.elf) + +add_executable(${elf_file} main.cpp) +target_compile_features(${elf_file} PUBLIC cxx_std_17) + +target_link_libraries(${elf_file} + PRIVATE MatrixOS + PRIVATE MatrixOSDevice +) + +# Generate binary and hex files +add_custom_command(TARGET ${elf_file} POST_BUILD + COMMAND ${CMAKE_OBJCOPY} -O binary ${elf_file} ${PROJECT_NAME}.bin + COMMAND ${CMAKE_OBJCOPY} -O ihex ${elf_file} ${PROJECT_NAME}.hex + COMMAND ${CMAKE_SIZE} ${elf_file} + COMMENT "Generating binary and hex files" +) + +# Copy ELF file to standard location for debug tools +add_custom_command(TARGET ${elf_file} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_BINARY_DIR}/${elf_file} + ${CMAKE_BINARY_DIR}/${elf_file} + COMMENT "Copying ELF file to build root for debug tools" +) \ No newline at end of file diff --git a/Devices/MatrixBlock5/Config.cmake b/Devices/MatrixBlock5/Config.cmake new file mode 100644 index 00000000..62ba9ddd --- /dev/null +++ b/Devices/MatrixBlock5/Config.cmake @@ -0,0 +1,5 @@ +# Device feature configuration for MatrixBlock5 family +# These values must match the #define values in MatrixOSConfig.h + +set(DEVICE_STORAGE 0) +set(DEVICE_BATTERY 0) diff --git a/Devices/MatrixBlock5/Drivers/BKP.cpp b/Devices/MatrixBlock5/Drivers/BKP.cpp new file mode 100644 index 00000000..762638c4 --- /dev/null +++ b/Devices/MatrixBlock5/Drivers/BKP.cpp @@ -0,0 +1,34 @@ +#include "Device.h" + +// Undefine the BKP macro from STM32 HAL to avoid namespace conflict +#ifdef BKP +#define STM32_BKP_BASE BKP +#undef BKP +#endif + +namespace Device::BackupReg +{ + uint16_t size = 20; + + uint32_t Read(uint32_t address) { + RTC_HandleTypeDef RtcHandle; + RtcHandle.Instance = RTC; + return HAL_RTCEx_BKUPRead(&RtcHandle, address); + } + + int8_t Write(uint32_t address, uint32_t data) { + if (address >= size) + return -1; + RTC_HandleTypeDef RtcHandle; + RtcHandle.Instance = RTC; + HAL_PWR_EnableBkUpAccess(); + HAL_RTCEx_BKUPWrite(&RtcHandle, address, data); + HAL_PWR_DisableBkUpAccess(); + return 0; + } +} + +// Restore the BKP macro for STM32 HAL +#ifdef STM32_BKP_BASE +#define BKP STM32_BKP_BASE +#endif \ No newline at end of file diff --git a/Devices/MatrixBlock5/Drivers/Keypad.cpp b/Devices/MatrixBlock5/Drivers/Keypad.cpp new file mode 100644 index 00000000..b0eb3486 --- /dev/null +++ b/Devices/MatrixBlock5/Drivers/Keypad.cpp @@ -0,0 +1,184 @@ +// Define Device Keypad Function +#include "Device.h" +#include "timers.h" +#include "MatrixOSConfig.h" + +namespace Device::KeyPad +{ + StaticTimer_t keypad_timer_def; + TimerHandle_t keypad_timer; + + void Init() { + InitFN(); + InitKeyPad(); + InitTouchBar(); + } + + void InitFN() { + // FN key is already configured in Family.cpp's KeyPad_Init() + // This function is kept for API compatibility + } + + void InitKeyPad() { + // Keypad is already configured in Family.cpp's KeyPad_Init() + // This function is kept for API compatibility + } + + void InitTouchBar() { + // TODO: Initialize touch bar for STM32F103 + } + + void StartKeyPad() { + // Create FreeRTOS timer for keypad scanning + keypad_timer = xTimerCreateStatic(NULL, configTICK_RATE_HZ / keypad_scanrate, true, NULL, reinterpret_cast(Scan), &keypad_timer_def); + xTimerStart(keypad_timer, 0); + } + + void StartTouchBar() { + // TODO: Start touch bar scanning for STM32F103 + } + + void Start() { + StartKeyPad(); + StartTouchBar(); + } + + void Scan() { + ScanFN(); + ScanKeyPad(); + } + + bool ScanKeyPad() { + // MatrixBlock5 uses binary keypad scanning (no FSR support) + for (uint8_t x = 0; x < X_SIZE; x++) + { + // Activate column + HAL_GPIO_WritePin(keypad_write_ports[x], keypad_write_pins[x], GPIO_PIN_SET); + + for (uint8_t y = 0; y < Y_SIZE; y++) + { + // Read row + Fract16 read = HAL_GPIO_ReadPin(keypad_read_ports[y], keypad_read_pins[y]) * UINT16_MAX; + if (keypadState[x][y].Update(keypad_config, read)) + { + uint16_t keyID = (1 << 12) + (x << 6) + y; + if (NotifyOS(keyID, &keypadState[x][y])) + { + // Deactivate column and return if OS notification interrupted + HAL_GPIO_WritePin(keypad_write_ports[x], keypad_write_pins[x], GPIO_PIN_RESET); + return true; + } + } + } + + // Deactivate column + HAL_GPIO_WritePin(keypad_write_ports[x], keypad_write_pins[x], GPIO_PIN_RESET); + + // Small delay for settling + volatile int i; + for (i = 0; i < 5; ++i) {} + } + return false; + } + + bool ScanFN() { + Fract16 read = HAL_GPIO_ReadPin(fn_port, fn_pin) * UINT16_MAX; + if (fn_active_low) + { read = UINT16_MAX - (uint16_t)read; } + if (fnState.Update(binary_config, read)) + { + if (NotifyOS(0, &fnState)) + { return true; } + } + return false; + } + + void Clear() { + fnState.Clear(); + + for (uint8_t x = 0; x < X_SIZE; x++) + { + for (uint8_t y = 0; y < Y_SIZE; y++) + { keypadState[x][y].Clear(); } + } + + for (uint8_t i = 0; i < touchbar_size; i++) + { touchbarState[i].Clear(); } + } + + KeyInfo* GetKey(uint16_t keyID) { + uint8_t keyClass = keyID >> 12; + switch (keyClass) + { + case 0: // System + { + uint16_t index = keyID & (0b0000111111111111); + switch (index) + { + case 0: + return &fnState; + } + break; + } + case 1: // Main Grid + { + int16_t x = (keyID & (0b0000111111000000)) >> 6; + int16_t y = keyID & (0b0000000000111111); + if (x < X_SIZE && y < Y_SIZE) + return &keypadState[x][y]; + break; + } + case 2: // Touch Bar + { + uint16_t index = keyID & (0b0000111111111111); + if (index < touchbar_size) + return &touchbarState[index]; + break; + } + } + return nullptr; + } + + bool NotifyOS(uint16_t keyID, KeyInfo* keyInfo) { + KeyEvent keyEvent; + keyEvent.id = keyID; + keyEvent.info = *keyInfo; + return MatrixOS::KeyPad::NewEvent(&keyEvent); + } + + uint16_t XY2ID(Point xy) { + if (xy.x >= 0 && xy.x < 8 && xy.y >= 0 && xy.y < 8) // Main grid + { return (1 << 12) + (xy.x << 6) + xy.y; } + else if ((xy.x == -1 || xy.x == 8) && (xy.y >= 0 && xy.y < 8)) // Touch Bar + { return (2 << 12) + xy.y + (xy.x == 8) * 8; } + return UINT16_MAX; + } + + Point ID2XY(uint16_t keyID) { + uint8_t keyClass = keyID >> 12; + switch (keyClass) + { + case 1: // Main Grid + { + int16_t x = (keyID & 0b0000111111000000) >> 6; + int16_t y = keyID & (0b0000000000111111); + if (x < X_SIZE && y < Y_SIZE) + return Point(x, y); + break; + } + case 2: // TouchBar + { + uint16_t index = keyID & (0b0000111111111111); + if (index < touchbar_size) + { + if (index / 8) // Right + { return Point(X_SIZE, index % 8); } + else // Left + { return Point(-1, index % 8); } + } + break; + } + } + return Point(INT16_MIN, INT16_MIN); + } +} \ No newline at end of file diff --git a/Devices/MatrixBlock5/Drivers/LED.cpp b/Devices/MatrixBlock5/Drivers/LED.cpp new file mode 100644 index 00000000..6243939a --- /dev/null +++ b/Devices/MatrixBlock5/Drivers/LED.cpp @@ -0,0 +1,65 @@ +#include "Device.h" +#include "MatrixOSConfig.h" +#include "WS2812/WS2812.h" + +namespace Device +{ + namespace LED + { + void Init() { + // LED initialization is handled in Family.cpp's LED_Init() + // This function is kept for API compatibility + } + + void Start() { + // LED startup tasks - none needed for MatrixBlock5 + } + + void Update(Color* frameBuffer, vector& brightness) // Render LED + { + WS2812::Show(frameBuffer, brightness); + } + + uint16_t XY2Index(Point xy) { + if (xy.x >= 0 && xy.x < 8 && xy.y >= 0 && xy.y < 8) // Main grid + { return xy.x + xy.y * 8; } + return UINT16_MAX; + } + + Point Index2XY(uint16_t index) + { + if (index < 64) + { + return Point(index % 8, index / 8); + } + return Point::Invalid(); + } + + // Matrix use the following ID Struct + // CCCC IIIIIIIIIIII + // C as class (4 bits), I as index (12 bits). I could be split by the class definition, for example, class 1 + // (grid), it's split to XXXXXXX YYYYYYY. Class List: Class 0 - Raw Index - IIIIIIIIIIII Class 1 - Grid - XXXXXX + // YYYYYY Class 2 - TouchBar - IIIIIIIIIIII Class 3 - Underglow - IIIIIIIIIIII + + uint16_t ID2Index(uint16_t ledID) { + uint8_t ledClass = ledID >> 12; + switch (ledClass) + { + case 0: + if (ledID < LED::count) + return ledID; + break; + case 1: // Main Grid + { + uint16_t index = ledID & (0b0000111111111111); + if (index < 64) + return index; + break; + } + case 3: // Underglow + break; // TODO: Underglow + } + return UINT16_MAX; + } + } +} \ No newline at end of file diff --git a/Devices/MatrixBlock5/Drivers/NVS.cpp b/Devices/MatrixBlock5/Drivers/NVS.cpp new file mode 100644 index 00000000..47f7dd40 --- /dev/null +++ b/Devices/MatrixBlock5/Drivers/NVS.cpp @@ -0,0 +1,56 @@ +#include "NVS.h" + +namespace Device::NVS +{ + string tag = "NVS Driver"; + + void Init() { + // TODO: Implement NVS driver for STM32F103 + // For now, this is stubbed out + } + + void Clear() { + // TODO: Implement NVS clear + } + + bool Get(string name_space, string key, void* pointer, uint16_t length) { + // TODO: Implement NVS get + return false; + } + + bool Set(string name_space, string key, void* pointer, uint16_t length) { + // TODO: Implement NVS set + return false; + } + + bool GetString(string name_space, string key, string* string_p) { + // TODO: Implement NVS get string + return false; + } + + bool SetString(string name_space, string key, string* string_p) { + // TODO: Implement NVS set string + return false; + } + + // Additional NVS functions required by MatrixOS::NVS + std::vector Read(uint32_t hash) { + // TODO: Implement NVS read by hash + return std::vector(); + } + + bool Write(uint32_t hash, void* pointer, uint16_t length) { + // TODO: Implement NVS write by hash + return false; + } + + size_t Size(uint32_t hash) { + // TODO: Implement NVS size by hash + return 0; + } + + bool Delete(uint32_t hash) { + // TODO: Implement NVS delete by hash + return false; + } +} diff --git a/Devices/MatrixBlock5/Drivers/NVS.h b/Devices/MatrixBlock5/Drivers/NVS.h new file mode 100644 index 00000000..24007aa8 --- /dev/null +++ b/Devices/MatrixBlock5/Drivers/NVS.h @@ -0,0 +1,56 @@ +#pragma once + +#include "Device.h" +#include + +namespace Device::NVS +{ + + struct HashKey { + uint32_t hash; + uint16_t length; + uint16_t new_address = 0xFFFF; // This is what limiting the max size. If more than 64 KB is needed, maybe change + // this to uint32_t along with other changes + + HashKey() { + this->hash = 0; + this->length = 0; + } + + HashKey(uint32_t hash, uint16_t length) { + this->hash = hash; + this->length = length; + } + + bool Used() { return hash != 0xFFFFFFFF; } + bool Latest() { return new_address == 0xFFFF; } + }; + + const uint32_t direction_indicator = 0x28dc67e2; + + void Init(); + void UpdateBytesUsed(); + + uint16_t FindKey(uint32_t hash); + + HashKey* GetKey(uint16_t virtual_address); + HashKey* GetKey(uint8_t page, uint16_t local_address); + uint16_t GetVirtualAddress(HashKey* hashKey); + uint32_t GetPage(uint8_t index); + uint16_t GetFreeSpace(uint8_t page); + int8_t CheckSpace(uint16_t length); + + void CleanUpTable(uint32_t hash_to_ignore = 0); + + bool WriteKey(uint32_t hash, void* pointer, uint16_t length); + + void WriteToFlash(uint32_t pointer, uint16_t length, uint16_t* address); + void ErasePage(uint32_t address, uint32_t pages = 1); + + // Public API functions + size_t Size(uint32_t hash); + std::vector Read(uint32_t hash); + bool Write(uint32_t hash, void* pointer, uint16_t length); + bool Delete(uint32_t hash); + void Clear(); +} \ No newline at end of file diff --git a/Devices/MatrixBlock5/Drivers/dcd_stm32f1.c b/Devices/MatrixBlock5/Drivers/dcd_stm32f1.c new file mode 100644 index 00000000..bc15850b --- /dev/null +++ b/Devices/MatrixBlock5/Drivers/dcd_stm32f1.c @@ -0,0 +1,123 @@ +/** + * @file dcd_stm32f1.c + * @brief TinyUSB device controller driver stub for STM32F1 + * + * This is a stub implementation to allow linking. The actual implementation + * will need to configure the STM32F1 USB peripheral for device mode. + */ + +#include "tusb.h" + +// Initialize device controller +void dcd_init(uint8_t rhport) { + (void)rhport; + // TODO: Initialize STM32F1 USB device controller +} + +// Enable device interrupt +void dcd_int_enable(uint8_t rhport) { + (void)rhport; + // TODO: Enable USB interrupts +} + +// Disable device interrupt +void dcd_int_disable(uint8_t rhport) { + (void)rhport; + // TODO: Disable USB interrupts +} + +// Set device address +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { + (void)rhport; + (void)dev_addr; + // TODO: Set USB device address +} + +// Wake up host +void dcd_remote_wakeup(uint8_t rhport) { + (void)rhport; + // TODO: Implement remote wakeup +} + +// Connect/disconnect by enabling/disabling internal pull-up resistor +void dcd_connect(uint8_t rhport) { + (void)rhport; + // TODO: Connect device (enable pull-up) +} + +void dcd_disconnect(uint8_t rhport) { + (void)rhport; + // TODO: Disconnect device (disable pull-up) +} + +// Enable/disable SOF interrupt +void dcd_sof_enable(uint8_t rhport, bool en) { + (void)rhport; + (void)en; + // TODO: Enable/disable SOF interrupt +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + +// Open an endpoint +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { + (void)rhport; + (void)desc_ep; + // TODO: Open endpoint + return true; +} + +// Close all non-control endpoints +void dcd_edpt_close_all(uint8_t rhport) { + (void)rhport; + // TODO: Close all endpoints +} + +// Submit a transfer +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { + (void)rhport; + (void)ep_addr; + (void)buffer; + (void)total_bytes; + // TODO: Submit transfer + return true; +} + +// Stall endpoint +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { + (void)rhport; + (void)ep_addr; + // TODO: Stall endpoint +} + +// Clear stall +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { + (void)rhport; + (void)ep_addr; + // TODO: Clear endpoint stall +} + +// Interrupt handler +void dcd_int_handler(uint8_t rhport) { + (void)rhport; + // TODO: Handle USB interrupts and call appropriate dcd_event_* functions +} + +// ISO endpoint allocation (optional, for isochronous transfers) +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + // TODO: Allocate ISO endpoint + return false; +} + +// ISO endpoint activation (optional, for isochronous transfers) +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { + (void)rhport; + (void)desc_ep; + // TODO: Activate ISO endpoint + return false; +} diff --git a/Devices/MatrixBlock5/Family.cpp b/Devices/MatrixBlock5/Family.cpp new file mode 100644 index 00000000..a0aee272 --- /dev/null +++ b/Devices/MatrixBlock5/Family.cpp @@ -0,0 +1,313 @@ +#include "Device.h" +#include "MatrixOS.h" +#include "UI/UI.h" +#include "MatrixOSConfig.h" + +#include "timers.h" + +// Forward declare TinyUSB interrupt handler +extern "C" void dcd_int_handler(uint8_t rhport); + +// Variant loader function +void LoadFounderEdition(); + +namespace Device +{ + namespace KeyPad + { + void Scan(); + } + + void DeviceInit() { + LoadDeviceInfo(); + USBController::Init(); + NVS::Init(); + LED::Init(); + KeyPad::Init(); + } + + void DeviceStart() { + KeyPad::Start(); + LED::Start(); + + // Keypad scanning is now handled by FreeRTOS timer, no need to call Scan() directly + //Use keyInfo->Force() instead KeyInfo->Active() because it might still be debouncing + if (KeyPad::GetKey(KeyPad::XY2ID(Point(0, 0)))->Force() && KeyPad::GetKey(KeyPad::XY2ID(Point(1, 1)))->Force()) + { MatrixOS::SYS::ExecuteAPP("203 Systems", "Matrix Factory Menu"); } + else if (KeyPad::GetKey(KeyPad::XY2ID(Point(6, 6)))->Force() && + KeyPad::GetKey(KeyPad::XY2ID(Point(7, 7)))->Force()) + { + KeyPad::Clear(); + MatrixOS::UserVar::brightness.Set(LED::brightness_level[0]); + } + else if (KeyPad::GetKey(KeyPad::XY2ID(Point(0, 5)))->Force() && + KeyPad::GetKey(KeyPad::XY2ID(Point(1, 6)))->Force() && + KeyPad::GetKey(KeyPad::XY2ID(Point(0, 7)))->Force()) + { + MatrixOS::LED::SetColor(Point(2, 2), Color(0xFF00FF)); + MatrixOS::LED::SetColor(Point(5, 2), Color(0xFF00FF)); + MatrixOS::LED::SetColor(Point(2, 5), Color(0xFF00FF)); + MatrixOS::LED::SetColor(Point(5, 5), Color(0xFF00FF)); + MatrixOS::LED::Update(); + MatrixOS::SYS::DelayMs(1500); + NVS::Clear(); + MatrixOS::SYS::Reboot(); + } + } + + void LoadDeviceInfo() { +#ifndef FACTORY_CONFIG + // For MatrixBlock5, we'll use default device info since there's no EFUSE + DeviceInfo defaultDeviceInfo{{'M', 'B', '5', 'F'}, {'F', 'O', 'U', 'N'}, 24, 1}; + memcpy(&deviceInfo, &defaultDeviceInfo, sizeof(DeviceInfo)); +#endif + LoadVariantInfo(); + } + + void LoadVariantInfo() { + // For MatrixBlock5, we'll load the Founder Edition variant + // This will set up the GPIO configurations for the specific hardware + LoadFounderEdition(); + } + + void DeviceSettings() + { + UI deviceSettings("Device Settings", Color(0x00FFAA)); + + UIToggle touchbarToggle; + touchbarToggle.SetName("Touchbar"); + touchbarToggle.SetColor(Color(0x7957FB)); + touchbarToggle.SetValuePointer(&touchbar_enable); + touchbarToggle.OnPress([&]() -> void { touchbar_enable.Save(); }); + deviceSettings.AddUIComponent(touchbarToggle, Point(0, 0)); + + UIButton keypadCalibrationBtn; + keypadCalibrationBtn.SetName("Keypad Calibration"); + keypadCalibrationBtn.SetColor(Color::White); + keypadCalibrationBtn.OnPress([]() -> void { MatrixOS::SYS::ExecuteAPP("203 Systems", "Force Calibration"); }); + keypadCalibrationBtn.SetEnabled(KeyPad::velocity_sensitivity); + deviceSettings.AddUIComponent(keypadCalibrationBtn, Point(7, 0)); + + deviceSettings.Start(); + } + + void Bootloader() { + // TODO: Implement bootloader entry mechanism for STM32F103 + // For now, just reboot + Reboot(); + } + + void Reboot() { + NVIC_SystemReset(); + } + + void Delay(uint32_t interval) { + vTaskDelay(pdMS_TO_TICKS(interval)); + } + + uint32_t Millis() { + return ((((uint64_t)xTaskGetTickCount()) * 1000) / configTICK_RATE_HZ); + } + + void Log(string &format, va_list &valst) { + // For STM32, we can use printf or custom logging + // vprintf(format.c_str(), valst); + } + + string GetSerial() { + // For MatrixBlock5, we could use MCU unique ID if available + return "MXB5-" + std::to_string(HAL_GetUIDw0() ^ HAL_GetUIDw1() ^ HAL_GetUIDw2()); + } + + void ErrorHandler() {} + + uint64_t Micros() { + return HAL_GetTick() * 1000; // Approximate micros for STM32 + } + + /** + * @brief System Clock Configuration + * The system Clock is configured as follow : + * System Clock source = PLL (HSE) + * SYSCLK(Hz) = 72000000 + * HCLK(Hz) = 72000000 + * AHB Prescaler = 1 + * APB1 Prescaler = 2 + * APB2 Prescaler = 1 + * HSE Frequency(Hz) = 8000000 + * HSE PREDIV1 = 1 + * PLLMUL = 9 + * Flash Latency(WS) = 2 + * @param None + * @retval None + */ + void SystemClock_Config(void) { + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { ErrorHandler(); } + /** Initializes the CPU, AHB and APB buses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) + { ErrorHandler(); } + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB; + PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) + { ErrorHandler(); } + } + +} + +namespace MatrixOS::SYS +{ + void ErrorHandler(string error); +} + +extern "C" { +void USB_HP_CAN1_TX_IRQHandler(void) { + dcd_int_handler(0); +} + +void USB_LP_CAN1_RX0_IRQHandler(void) { + dcd_int_handler(0); +} + +void USBWakeUp_IRQHandler(void) { + dcd_int_handler(0); +} + +// void SysTick_Handler(void) +// { +// HAL_IncTick(); +// } + +void _init(void) { + ; +} + +void NMI_Handler(void) { + while (true) + {} +} + +void HardFault_Handler(void) { + MatrixOS::SYS::ErrorHandler("Hard Fault"); + while (true) + {} +} + +void MemManage_Handler(void) { + while (true) + {} +} + +void BusFault_Handler(void) { + while (true) + {} +} + +void UsageFault_Handler(void) { + while (true) + {} +} + +// void SVC_Handler (void) +// { +// while(true){ + +// } +// } + +void DebugMon_Handler(void) { + while (true) + {} +} + +// void PendSV_Handler (void) +// { +// while(true){ + +// } +// } + +void vApplicationMallocFailedHook(void) { + taskDISABLE_INTERRUPTS(); +} + +void vApplicationStackOverflowHook(xTaskHandle pxTask, char* pcTaskName) { + (void)pxTask; + (void)pcTaskName; + + taskDISABLE_INTERRUPTS(); +} + +/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an + * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is + * used by the Idle task. */ +void vApplicationGetIdleTaskMemory(StaticTask_t** ppxIdleTaskTCBBuffer, StackType_t** ppxIdleTaskStackBuffer, + uint32_t* pulIdleTaskStackSize) { + /* If the buffers to be provided to the Idle task are declared inside this + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. */ + static StaticTask_t xIdleTaskTCB; + static StackType_t uxIdleTaskStack[configMINIMAL_STACK_SIZE]; + + /* Pass out a pointer to the StaticTask_t structure in which the Idle task's + state will be stored. */ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + /* Pass out the array that will be used as the Idle task's stack. */ + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; +} + +/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the + * application must provide an implementation of vApplicationGetTimerTaskMemory() + * to provide the memory that is used by the Timer service task. */ +void vApplicationGetTimerTaskMemory(StaticTask_t** ppxTimerTaskTCBBuffer, StackType_t** ppxTimerTaskStackBuffer, + uint32_t* pulTimerTaskStackSize) { + /* If the buffers to be provided to the Timer task are declared inside this + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. */ + static StaticTask_t xTimerTaskTCB; + static StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH]; + + /* Pass out a pointer to the StaticTask_t structure in which the Timer + task's state will be stored. */ + *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; + + /* Pass out the array that will be used as the Timer task's stack. */ + *ppxTimerTaskStackBuffer = uxTimerTaskStack; + + /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */ + *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; +} +} + +extern "C" { +void* __dso_handle = 0; +} diff --git a/Devices/MatrixBlock5/Family.h b/Devices/MatrixBlock5/Family.h new file mode 100644 index 00000000..69870e7d --- /dev/null +++ b/Devices/MatrixBlock5/Family.h @@ -0,0 +1,163 @@ +// Declare Family specific function +#pragma once + +#include "Device.h" +#include "Framework.h" + +#include "stm32f1xx_hal.h" +#include "WS2812/WS2812.h" + +#define STM32_PLATFORM 1 + +// Family-specific defines +#define GRID_TYPE_8x8 +#define FAMILY_MATRIXBLOCK5 +#define MULTIPRESS 10 // Key Press will be process at once + +#define DEVICE_SAVED_VAR_SCOPE "Device" + +struct DeviceInfo { + char Model[4]; + char Revision[4]; + uint8_t ProductionYear; + uint8_t ProductionMonth; +}; + +namespace Device +{ + inline DeviceInfo deviceInfo; + + // Device Variable + inline CreateSavedVar(DEVICE_SAVED_VAR_SCOPE, touchbar_enable, bool, true); + inline CreateSavedVar(DEVICE_SAVED_VAR_SCOPE, bluetooth, bool, false); + + namespace HWMidi + { + inline GPIO_TypeDef* tx_port = nullptr; + inline uint16_t tx_pin = 0; + inline GPIO_TypeDef* rx_port = nullptr; + inline uint16_t rx_pin = 0; + } + + namespace LED + { + inline GPIO_TypeDef* led_port = nullptr; + inline uint16_t led_pin = 0; + inline bool underglow = false; + } + + void LoadDeviceInfo(); + void LoadVariantInfo(); + + namespace USBController + { + void Init(); + } + namespace LED + { + void Init(); + void Start(); + } + + namespace KeyPad + { + void Init(); + void InitFN(); + void InitKeyPad(); + void InitTouchBar(); + + void Start(); + void StartKeyPad(); + void StartTouchBar(); + + // If return true, meaning the scan in interrupted + void Scan(); + bool ScanKeyPad(); + bool ScanFN(); + bool ScanTouchBar(); + + inline GPIO_TypeDef* fn_port = nullptr; + inline uint16_t fn_pin = 0; + inline bool fn_active_low = true; + inline bool velocity_sensitivity = false; + + inline KeyConfig binary_config = { + .apply_curve = false, + .low_threshold = 0, + .high_threshold = 65535, + .activation_offset = 0, + .debounce = 3, + }; + + inline KeyConfig keypad_config = { + .apply_curve = true, + .low_threshold = 1536, + .high_threshold = 32767, + .activation_offset = 256, + .debounce = 10, + }; + + inline GPIO_TypeDef* keypad_write_ports[X_SIZE]; + inline uint16_t keypad_write_pins[X_SIZE]; + inline GPIO_TypeDef* keypad_read_ports[Y_SIZE]; + inline uint16_t keypad_read_pins[Y_SIZE]; + + inline uint16_t keypad_scanrate = 240; + + inline GPIO_TypeDef* touchData_Port; + inline uint16_t touchData_Pin; + inline GPIO_TypeDef* touchClock_Port; + inline uint16_t touchClock_Pin; + + inline const uint8_t touchbar_size = 16; + inline const uint16_t touchbar_scanrate = 120; + inline uint8_t touchbar_map[touchbar_size]; // Touch number as index and touch location as value (Left touch down + // and then right touch down) + + inline KeyInfo fnState; + inline KeyInfo keypadState[X_SIZE][Y_SIZE]; + inline KeyInfo touchbarState[touchbar_size]; + + namespace Binary + { + void Init(); + void Start(); + bool Scan(); + } + + namespace FSR + { + void Init(); + void Start(); + bool Scan(); + } + + bool NotifyOS(uint16_t keyID, KeyInfo* keyInfo); // Passthrough MatrixOS::KeyPad::NewEvent() result + } + + namespace NVS + { + void Init(); + } + + namespace WIFI + { + void Init(); + } + + namespace BLEMIDI + { + extern bool started; + void Init(string name); + void Start(); + void Stop(); + } + + namespace HWMidi + { + void Init(); + } + +} + +#undef USB // CMSIS defined the USB, undef so we can use USB as MatrixOS namespace \ No newline at end of file diff --git a/Devices/MatrixBlock5/FreeRTOSConfig.h b/Devices/MatrixBlock5/FreeRTOSConfig.h new file mode 100644 index 00000000..46e9a81a --- /dev/null +++ b/Devices/MatrixBlock5/FreeRTOSConfig.h @@ -0,0 +1,193 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// STM32 device definition - must be defined before including HAL headers +#ifndef STM32F103xB +#define STM32F103xB +#endif + +// Include MCU header +#include "stm32f1xx_hal.h" + +extern uint32_t SystemCoreClock; + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ (100) +#define configMAX_PRIORITIES (5) +#define configMINIMAL_STACK_SIZE (128) +#define configTOTAL_HEAP_SIZE (1024) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 2 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* Thread Local Storage */ +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 4 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 + +/* Define to trap errors during development. */ +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) +#define configASSERT(_exp) \ + do \ + { \ + if (!(_exp)) \ + { \ + volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*)0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ + if ((*ARM_CM_DHCSR) & 1UL) \ + { /* Only halt mcu if debugger is attached */ \ + taskDISABLE_INTERRUPTS(); \ + __asm("BKPT #0\n"); \ + } \ + } \ + } while (0) +#else +#define configASSERT(x) +#endif + +#ifdef __RX__ +/* Renesas RX series */ +#define vSoftwareInterruptISR INT_Excep_ICU_SWINT +#define vTickISR INT_Excep_CMT0_CMI0 +#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ / 2) +#define configKERNEL_INTERRUPT_PRIORITY 1 +#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4 + +#else + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ +#if defined(__NVIC_PRIO_BITS) +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h +#define configPRIO_BITS __NVIC_PRIO_BITS +#elif defined(__ECLIC_INTCTLBITS) +// RISC-V Bumblebee core from nuclei +#define configPRIO_BITS __ECLIC_INTCTLBITS +#else +// Fallback for Cortex-M3 (STM32F103) - 4 priority bits +#define configPRIO_BITS 4 +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1 << configPRIO_BITS) - 1) + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2 + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) + +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) + +#endif + +#endif /* __FREERTOS_CONFIG__H */ diff --git a/Devices/MatrixBlock5/MatrixOSConfig.h b/Devices/MatrixBlock5/MatrixOSConfig.h new file mode 100644 index 00000000..af79feec --- /dev/null +++ b/Devices/MatrixBlock5/MatrixOSConfig.h @@ -0,0 +1,46 @@ +#pragma once +#include "Framework.h" + +// Platform-specific attributes +// IRAM_ATTR is ESP32-specific for placing functions in IRAM +// For STM32, we don't need this attribute, so define it as empty +#define IRAM_ATTR __RAM_FUNC + +#define FUNCTION_KEY 0 // Keypad Code for main function key + +#define X_SIZE 8 +#define Y_SIZE 8 + +#define OS_SHELL APPID("203 Systems", "Shell") +#define DEFAULT_BOOTANIMATION APPID("203 Systems", "Matrix Boot") + +namespace Device +{ + // Matrix OS required + inline string name = "MatrixBlock5"; + inline string model = "MB5F"; + + inline string manufacturer_name = "203 Systems"; + inline string product_name = "MatrixBlock5"; + inline uint16_t usb_vid = 0x0203; + inline uint16_t usb_pid = 0x1041; // Different PID from Mystrix + + // MatrixOS required dimensions - defined directly for MatrixBlock5 + inline uint8_t x_size = X_SIZE; + inline uint8_t y_size = Y_SIZE; + + namespace LED + { + #define MAX_LED_LAYERS 8 + const inline uint16_t fps = 120; // Depends on the FreeRTOS tick speed + + inline uint16_t count = 64; // Only main grid, no underglow + inline uint8_t brightness_level[8] = {8, 22, 39, 60, 84, 110, 138, 169}; + #define FINE_LED_BRIGHTNESS + inline uint8_t brightness_fine_level[16] = {8, 16, 26, 38, 50, 64, 80, 96, 112, 130, 149, 169, 189, 209, 232, 255}; + + inline vector partitions = { + {"Grid", 1.0, 0, 64}, + }; + } +} \ No newline at end of file diff --git a/Devices/MatrixBlock5/STM32F103RETX_FLASH.ld b/Devices/MatrixBlock5/STM32F103RETX_FLASH.ld new file mode 100644 index 00000000..9eb998fd --- /dev/null +++ b/Devices/MatrixBlock5/STM32F103RETX_FLASH.ld @@ -0,0 +1,177 @@ +/** + ****************************************************************************** + * @file LinkerScript.ld + * @author Auto-generated by STM32CubeIDE + * @brief Linker script for STM32F103RETx Device from STM32F1 series + * 512Kbytes FLASH + * 64Kbytes RAM + * + * Set heap size, stack size and stack location according + * to application requirements. + * + * Set memory bank area and size if external memory is used + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ + +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Memories definition */ +MEMORY +{ +/* BOOTLOADER (r) : ORIGIN = 0x08000000, LENGTH = 8K */ +FLASH (rx) : ORIGIN = 0x08002000, LENGTH = 504K + +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K +} + +/* Sections */ +SECTIONS +{ + /* The startup code into "FLASH" Rom type memory */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data into "FLASH" Rom type memory */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data into "FLASH" Rom type memory */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { + . = ALIGN(4); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(4); + } >FLASH + + .ARM : { + . = ALIGN(4); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(4); + } >FLASH + + .preinit_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + } >FLASH + + .init_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + } >FLASH + + .fini_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >FLASH + + /* Used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections into "RAM" Ram type memory */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + + } >RAM AT> FLASH + + /* Uninitialized data section into "RAM" Ram type memory */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + /* Remove information from the compiler libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/Config.h b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/Config.h new file mode 100644 index 00000000..ab5ffe80 --- /dev/null +++ b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/Config.h @@ -0,0 +1,137 @@ +// Define Device Specific Macro, Value and private function +#pragma once + +#include "Family.h" + +#define GRID_8x8 +#define MODEL MXFE1 +#define MULTIPRESS 10 // Key Press will be process at once + +extern TIM_HandleTypeDef htim8; +extern DMA_HandleTypeDef hdma_tim8_ch2; + +namespace Device +{ + const string name = "Matrix Founder Edition"; + const string model = "MXFE1"; + + const string manufacturer_name = "203 Systems"; + const string product_name = "Matrix"; + const uint16_t usb_vid = 0x0203; + const uint16_t usb_pid = 0x1040; //(Device Class)0001 (Device Code)000001 (Reserved for Device ID (0~63))000000 + + const uint16_t led_count = 64; + const uint8_t x_size = 8; + const uint8_t y_size = 8; + +#define MAX_LED_LAYERS 5 + inline uint16_t keypad_scanrate = 60; + inline uint16_t fps = 120; // Depends on the FreeRTOS tick speed + + inline uint8_t brightness_level[8] = {8, 12, 24, 40, 64, 90, 128, 168}; + + const uint8_t touchbar_size = 8; // Not required by the API, private use. 16 Physical but 8 virtualized key. + + const uint16_t page_size = 2048; + const uint8_t nums_of_page = 32; // Total size has to smaller than 64kb because address constrain + const uint32_t nvs_address = 0x8070000; + + namespace KeyPad + { + inline KeyInfo fnState; + inline KeyInfo keypadState[x_size][y_size]; + inline KeyInfo touchbarState[x_size]; + + void FNScan(); + void KeyPadScan(); + void TouchBarScan(); + + bool addToList(uint16_t keyID); // Return true when list is full. + void clearList(); + bool isListFull(); + } +} + +extern "C" { +void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim); +void NMI_Handler(void); +void HardFault_Handler(void); +void MemManage_Handler(void); +void BusFault_Handler(void); +void UsageFault_Handler(void); +void SVC_Handler(void); +void DebugMon_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void); +void DMA2_Channel4_5_IRQHandler(void); +} + +struct GPIO { + GPIO_TypeDef* port; + uint16_t pin; + + GPIO(GPIO_TypeDef* port, uint16_t pin) { + this->port = port; + this->pin = pin; + } +}; + +#define FN_Pin GPIO_PIN_0 +#define FN_GPIO_Port GPIOA + +#define Key1_Pin GPIO_PIN_15 +#define Key1_GPIO_Port GPIOB +#define Key2_Pin GPIO_PIN_14 +#define Key2_GPIO_Port GPIOB +#define Key3_Pin GPIO_PIN_13 +#define Key3_GPIO_Port GPIOB +#define Key4_Pin GPIO_PIN_12 +#define Key4_GPIO_Port GPIOB +#define Key5_Pin GPIO_PIN_6 +#define Key5_GPIO_Port GPIOC +#define Key6_Pin GPIO_PIN_15 +#define Key6_GPIO_Port GPIOC +#define Key7_Pin GPIO_PIN_14 +#define Key7_GPIO_Port GPIOC +#define Key8_Pin GPIO_PIN_13 +#define Key8_GPIO_Port GPIOC + +#define KeyRead1_Pin GPIO_PIN_1 +#define KeyRead1_GPIO_Port GPIOB +#define KeyRead2_Pin GPIO_PIN_0 +#define KeyRead2_GPIO_Port GPIOB +#define KeyRead3_Pin GPIO_PIN_2 +#define KeyRead3_GPIO_Port GPIOA +#define KeyRead4_Pin GPIO_PIN_1 +#define KeyRead4_GPIO_Port GPIOA +#define KeyRead5_Pin GPIO_PIN_3 +#define KeyRead5_GPIO_Port GPIOC +#define KeyRead6_Pin GPIO_PIN_3 +#define KeyRead6_GPIO_Port GPIOA +#define KeyRead7_Pin GPIO_PIN_5 +#define KeyRead7_GPIO_Port GPIOC +#define KeyRead8_Pin GPIO_PIN_4 +#define KeyRead8_GPIO_Port GPIOC + +#define TouchData_Pin GPIO_PIN_6 +#define TouchData_GPIO_Port GPIOA +#define TouchClock_Pin GPIO_PIN_7 +#define TouchClock_GPIO_Port GPIOA + +inline GPIO keypad_write_pins[] = { + GPIO(Key1_GPIO_Port, Key1_Pin), GPIO(Key2_GPIO_Port, Key2_Pin), GPIO(Key3_GPIO_Port, Key3_Pin), + GPIO(Key4_GPIO_Port, Key4_Pin), GPIO(Key5_GPIO_Port, Key5_Pin), GPIO(Key6_GPIO_Port, Key6_Pin), + GPIO(Key7_GPIO_Port, Key7_Pin), GPIO(Key8_GPIO_Port, Key8_Pin), +}; + +inline GPIO keypad_read_pins[] = { + GPIO(KeyRead1_GPIO_Port, KeyRead1_Pin), GPIO(KeyRead2_GPIO_Port, KeyRead2_Pin), + GPIO(KeyRead3_GPIO_Port, KeyRead3_Pin), GPIO(KeyRead4_GPIO_Port, KeyRead4_Pin), + GPIO(KeyRead5_GPIO_Port, KeyRead5_Pin), GPIO(KeyRead6_GPIO_Port, KeyRead6_Pin), + GPIO(KeyRead7_GPIO_Port, KeyRead7_Pin), GPIO(KeyRead8_GPIO_Port, KeyRead8_Pin), +}; + +inline GPIO fn_pin = GPIO(FN_GPIO_Port, FN_Pin); + +inline GPIO touch_clock_pin = GPIO(TouchClock_GPIO_Port, TouchClock_Pin); +inline GPIO touch_data_pin = GPIO(TouchData_GPIO_Port, TouchData_Pin); \ No newline at end of file diff --git a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp new file mode 100644 index 00000000..f0b23e44 --- /dev/null +++ b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp @@ -0,0 +1,30 @@ +// Matrix Founder Edition Variant Configuration +#include "Device.h" + +void LoadFounderEdition() { + // TODO: Implement Founder Edition variant initialization + // This includes: + // - GPIO configuration for keypad matrix + // - WS2812 LED driver initialization using TIM1 (not TIM8 - STM32F103xB doesn't have TIM8) + // - Hardware DMA setup for LED PWM (DMA1, not DMA2) + // For now, this is stubbed out to allow compilation +} + +namespace WS2812 { + void Show(Color* frameBuffer, std::vector& brightnessMap) { + // TODO: Implement WS2812 LED update using TIM1 PWM + DMA1 for STM32F103 + // For now, this is stubbed out to allow linking + } +} + +namespace Device::USBController { + void Init() { + // TODO: Implement USB controller initialization for STM32F103 + } +} + +namespace Device::BLEMIDI { + void Start() { + // TODO: Implement BLE MIDI start (STM32F103 doesn't have BLE, stub only) + } +} diff --git a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp.bak b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp.bak new file mode 100644 index 00000000..df785cfe --- /dev/null +++ b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp.bak @@ -0,0 +1,307 @@ +// Define Device Specific Function +#include "Device.h" + +void LoadFounderEdition(); + +namespace Device +{ + namespace + { + void MX_DMA_Init(void) { + /* DMA controller clock enable */ + __HAL_RCC_DMA2_CLK_ENABLE(); + + /* DMA interrupt init */ + /* DMA2_Channel4_5_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA2_Channel4_5_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn); + } + + void MX_TIM8_Init(void) { + TIM_MasterConfigTypeDef sMasterConfig = {0}; + TIM_OC_InitTypeDef sConfigOC = {0}; + TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; + + htim8.Instance = TIM8; + htim8.Init.Prescaler = 0; + htim8.Init.CounterMode = TIM_COUNTERMODE_UP; + htim8.Init.Period = WS2812::GetTimerPeriod(); + htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim8.Init.RepetitionCounter = 0; + htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + if (HAL_TIM_PWM_Init(&htim8) != HAL_OK) + { Device::ErrorHandler(); } + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK) + { Device::ErrorHandler(); } + sConfigOC.OCMode = TIM_OCMODE_PWM1; + sConfigOC.Pulse = 0; + sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; + sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; + sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; + sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; + if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) + { Device::ErrorHandler(); } + sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; + sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; + sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; + sBreakDeadTimeConfig.DeadTime = 0; + sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; + sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; + sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; + if (HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig) != HAL_OK) + { Device::ErrorHandler(); } + + HAL_TIM_MspPostInit(&htim8); + } + } + + void USB_Init() { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /* Configure USB FS GPIOs */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + + /* Configure USB D+ D- Pins */ + GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + // USB Clock enable + __HAL_RCC_USB_CLK_ENABLE(); + } + + void LED_Init() { + MX_DMA_Init(); + MX_TIM8_Init(); + WS2812::Init(&htim8, TIM_CHANNEL_2, led_count); + } + + void KeyPad_Init() { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOC, Key8_Pin | Key7_Pin | Key6_Pin | Key5_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOB, Key4_Pin | Key3_Pin | Key2_Pin | Key1_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pins : Key8_Pin Key7_Pin Key6_Pin Key5_Pin */ + GPIO_InitStruct.Pin = Key8_Pin | Key7_Pin | Key6_Pin | Key5_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + /*Configure GPIO pins : KeyRead5_Pin KeyRead8_Pin KeyRead7_Pin */ + GPIO_InitStruct.Pin = KeyRead5_Pin | KeyRead8_Pin | KeyRead7_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + /*Configure GPIO pins : FN_Pin KeyRead4_Pin KeyRead3_Pin KeyRead6_Pin */ + GPIO_InitStruct.Pin = FN_Pin | KeyRead4_Pin | KeyRead3_Pin | KeyRead6_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /*Configure GPIO pins : KeyRead2_Pin KeyRead1_Pin */ + GPIO_InitStruct.Pin = KeyRead2_Pin | KeyRead1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /*Configure GPIO pins : Key4_Pin Key3_Pin Key2_Pin Key1_Pin */ + GPIO_InitStruct.Pin = Key4_Pin | Key3_Pin | Key2_Pin | Key1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + } + + void TouchBar_Init() { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /* Configure TouchBar GPIOs */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(TouchClock_GPIO_Port, TouchClock_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pins : TouchClock_Pin */ + GPIO_InitStruct.Pin = TouchClock_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(TouchClock_GPIO_Port, &GPIO_InitStruct); + + /*Configure GPIO pin : TouchData_Pin */ + GPIO_InitStruct.Pin = TouchData_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + HAL_GPIO_Init(TouchData_GPIO_Port, &GPIO_InitStruct); + } + + void EEPROM_Init() {} +} + +TIM_HandleTypeDef htim8; +DMA_HandleTypeDef hdma_tim8_ch2; + +extern "C" { +void DMA2_Channel4_5_IRQHandler(void) { + HAL_DMA_IRQHandler(&hdma_tim8_ch2); +} +/** + * Initializes the Global MSP. + */ +void HAL_MspInit(void) { + /* USER CODE BEGIN MspInit 0 */ + + /* USER CODE END MspInit 0 */ + + __HAL_RCC_AFIO_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + /* System interrupt init*/ + + /** DISABLE: JTAG-DP Disabled and SW-DP Disabled + */ + // __HAL_AFIO_REMAP_SWJ_DISABLE(); + + /* USER CODE BEGIN MspInit 1 */ + + /* USER CODE END MspInit 1 */ +} + +// /** +// * @brief TIM_PWM MSP Initialization +// * This function configures the hardware resources used in this example +// * @param htim_pwm: TIM_PWM handle pointer +// * @retval None +// */ +void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm) { + if (htim_pwm->Instance == TIM8) + { + /* USER CODE BEGIN TIM8_MspInit 0 */ + + /* USER CODE END TIM8_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_TIM8_CLK_ENABLE(); + + /* TIM8 DMA Init */ + /* TIM8_CH2 Init */ + hdma_tim8_ch2.Instance = DMA2_Channel5; + hdma_tim8_ch2.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_tim8_ch2.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_tim8_ch2.Init.MemInc = DMA_MINC_ENABLE; + hdma_tim8_ch2.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_tim8_ch2.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_tim8_ch2.Init.Mode = DMA_NORMAL; + hdma_tim8_ch2.Init.Priority = DMA_PRIORITY_HIGH; + if (HAL_DMA_Init(&hdma_tim8_ch2) != HAL_OK) + { Device::ErrorHandler(); } + + __HAL_LINKDMA(htim_pwm, hdma[TIM_DMA_ID_CC2], hdma_tim8_ch2); + + /* USER CODE BEGIN TIM8_MspInit 1 */ + + /* USER CODE END TIM8_MspInit 1 */ + } +} + +void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if (htim->Instance == TIM8) + { + /* USER CODE BEGIN TIM8_MspPostInit 0 */ + + /* USER CODE END TIM8_MspPostInit 0 */ + + __HAL_RCC_GPIOC_CLK_ENABLE(); + /**TIM8 GPIO Configuration + PC7 ------> TIM8_CH2 + */ + GPIO_InitStruct.Pin = GPIO_PIN_7; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + /* USER CODE BEGIN TIM8_MspPostInit 1 */ + + /* USER CODE END TIM8_MspPostInit 1 */ + } +} +// /** +// * @brief TIM_PWM MSP De-Initialization +// * This function freeze the hardware resources used in this example +// * @param htim_pwm: TIM_PWM handle pointer +// * @retval None +// */ +void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* htim_pwm) { + if (htim_pwm->Instance == TIM8) + { + /* USER CODE BEGIN TIM8_MspDeInit 0 */ + + /* USER CODE END TIM8_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_TIM8_CLK_DISABLE(); + + /* TIM8 DMA DeInit */ + HAL_DMA_DeInit(htim_pwm->hdma[TIM_DMA_ID_CC2]); + /* USER CODE BEGIN TIM8_MspDeInit 1 */ + + /* USER CODE END TIM8_MspDeInit 1 */ + } +} + +void LoadFounderEdition() { + // Configure LED + Device::LED::led_port = GPIOC; + Device::LED::led_pin = GPIO_PIN_7; + + // Configure FN key + Device::KeyPad::fn_port = GPIOA; + Device::KeyPad::fn_pin = GPIO_PIN_8; + + // Configure keypad write pins (columns) + Device::KeyPad::keypad_write_ports[0] = GPIOB; Device::KeyPad::keypad_write_pins[0] = GPIO_PIN_12; // Key1 + Device::KeyPad::keypad_write_ports[1] = GPIOB; Device::KeyPad::keypad_write_pins[1] = GPIO_PIN_13; // Key2 + Device::KeyPad::keypad_write_ports[2] = GPIOB; Device::KeyPad::keypad_write_pins[2] = GPIO_PIN_14; // Key3 + Device::KeyPad::keypad_write_ports[3] = GPIOB; Device::KeyPad::keypad_write_pins[3] = GPIO_PIN_15; // Key4 + Device::KeyPad::keypad_write_ports[4] = GPIOC; Device::KeyPad::keypad_write_pins[4] = GPIO_PIN_6; // Key5 + Device::KeyPad::keypad_write_ports[5] = GPIOC; Device::KeyPad::keypad_write_pins[5] = GPIO_PIN_7; // Key6 + Device::KeyPad::keypad_write_ports[6] = GPIOC; Device::KeyPad::keypad_write_pins[6] = GPIO_PIN_8; // Key7 + Device::KeyPad::keypad_write_ports[7] = GPIOC; Device::KeyPad::keypad_write_pins[7] = GPIO_PIN_9; // Key8 + + // Configure keypad read pins (rows) + Device::KeyPad::keypad_read_ports[0] = GPIOB; Device::KeyPad::keypad_read_pins[0] = GPIO_PIN_0; // KeyRead1 + Device::KeyPad::keypad_read_ports[1] = GPIOB; Device::KeyPad::keypad_read_pins[1] = GPIO_PIN_1; // KeyRead2 + Device::KeyPad::keypad_read_ports[2] = GPIOA; Device::KeyPad::keypad_read_pins[2] = GPIO_PIN_11; // KeyRead3 + Device::KeyPad::keypad_read_ports[3] = GPIOA; Device::KeyPad::keypad_read_pins[3] = GPIO_PIN_12; // KeyRead4 + Device::KeyPad::keypad_read_ports[4] = GPIOC; Device::KeyPad::keypad_read_pins[4] = GPIO_PIN_4; // KeyRead5 + Device::KeyPad::keypad_read_ports[5] = GPIOA; Device::KeyPad::keypad_read_pins[5] = GPIO_PIN_15; // KeyRead6 + Device::KeyPad::keypad_read_ports[6] = GPIOC; Device::KeyPad::keypad_read_pins[6] = GPIO_PIN_5; // KeyRead7 + Device::KeyPad::keypad_read_ports[7] = GPIOC; Device::KeyPad::keypad_read_pins[7] = GPIO_PIN_3; // KeyRead8 + + // Configure touchbar + Device::KeyPad::touchData_Port = GPIOA; + Device::KeyPad::touchData_Pin = GPIO_PIN_0; + Device::KeyPad::touchClock_Port = GPIOA; + Device::KeyPad::touchClock_Pin = GPIO_PIN_1; + + // Set device name and model + Device::name = "MatrixBlock5"; + Device::model = "MB5F"; + Device::product_name = "MatrixBlock5"; +} +} \ No newline at end of file diff --git a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/STM32F103RETX_FLASH.ld b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/STM32F103RETX_FLASH.ld new file mode 100644 index 00000000..c3d79b32 --- /dev/null +++ b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/STM32F103RETX_FLASH.ld @@ -0,0 +1,177 @@ +/** + ****************************************************************************** + * @file LinkerScript.ld + * @author Auto-generated by STM32CubeIDE + * @brief Linker script for STM32F103RETx Device from STM32F1 series + * 512Kbytes FLASH + * 64Kbytes RAM + * + * Set heap size, stack size and stack location according + * to application requirements. + * + * Set memory bank area and size if external memory is used + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ + +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Memories definition */ +MEMORY +{ +/* BOOTLOADER (r) : ORIGIN = 0x08000000, LENGTH = 8K */ +FLASH (rx) : ORIGIN = 0x08002000, LENGTH = 504K + +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K +} + +/* Sections */ +SECTIONS +{ + /* The startup code into "FLASH" Rom type memory */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data into "FLASH" Rom type memory */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data into "FLASH" Rom type memory */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { + . = ALIGN(4); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(4); + } >FLASH + + .ARM : { + . = ALIGN(4); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(4); + } >FLASH + + .preinit_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + } >FLASH + + .init_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + } >FLASH + + .fini_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >FLASH + + /* Used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections into "RAM" Ram type memory */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + + } >RAM AT> FLASH + + /* Uninitialized data section into "RAM" Ram type memory */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + /* Remove information from the compiler libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/note.txt b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/note.txt new file mode 100644 index 00000000..17bb8a8a --- /dev/null +++ b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/note.txt @@ -0,0 +1 @@ +This is the hardware specific code for Matrix Block 6 variants \ No newline at end of file diff --git a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/stm32f1xx_hal_conf.h b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/stm32f1xx_hal_conf.h new file mode 100644 index 00000000..e5ae9e2e --- /dev/null +++ b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/stm32f1xx_hal_conf.h @@ -0,0 +1,378 @@ +/** + ****************************************************************************** + * @file USB_Device/HID_Standalone/Inc/stm32f1xx_hal_conf.h + * @author MCD Application Team + * @brief HAL configuration template file. + * This file should be copied to the application folder and renamed + * to stm32f1xx_hal_conf.h. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2016 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F1xx_HAL_CONF_H +#define __STM32F1xx_HAL_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +/* #define HAL_ADC_MODULE_ENABLED */ +/* #define HAL_CAN_MODULE_ENABLED */ +/* #define HAL_CAN_LEGACY_MODULE_ENABLED */ +#define HAL_CORTEX_MODULE_ENABLED +/* #define HAL_CRC_MODULE_ENABLED */ +/* #define HAL_DAC_MODULE_ENABLED */ +#define HAL_DMA_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +/* #define HAL_I2C_MODULE_ENABLED */ +/* #define HAL_I2S_MODULE_ENABLED */ +/* #define HAL_IRDA_MODULE_ENABLED */ +/* #define HAL_IWDG_MODULE_ENABLED */ +/* #define HAL_NOR_MODULE_ENABLED */ +/* #define HAL_PCCARD_MODULE_ENABLED */ +// #define HAL_PCD_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +/* #define HAL_SD_MODULE_ENABLED */ +/* #define HAL_SDRAM_MODULE_ENABLED */ +/* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_SPI_MODULE_ENABLED */ +/* #define HAL_SRAM_MODULE_ENABLED */ +#define HAL_TIM_MODULE_ENABLED +// #define HAL_UART_MODULE_ENABLED +/* #define HAL_USART_MODULE_ENABLED */ +/* #define HAL_WWDG_MODULE_ENABLED */ + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined(HSE_VALUE) +#if defined(USE_STM3210C_EVAL) +#define HSE_VALUE 25000000U /*!< Value of the External oscillator in Hz */ +#else +#define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ +#endif +#endif /* HSE_VALUE */ + +#if !defined(HSE_STARTUP_TIMEOUT) +#define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined(HSI_VALUE) +#define HSI_VALUE 8000000U /*!< Value of the Internal oscillator in Hz */ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined(LSI_VALUE) +#define LSI_VALUE 40000U /*!< LSI Typical Value in Hz */ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz \ + The real value may vary depending on the variations \ + in voltage and temperature. */ + +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined(LSE_VALUE) +#define LSE_VALUE 32768U /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined(LSE_STARTUP_TIMEOUT) +#define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE 3300U /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY 0x00U /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1U + +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_PCCARD_REGISTER_CALLBACKS 0U /* PCCARD register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 1U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2U +#define MAC_ADDR1 0U +#define MAC_ADDR2 0U +#define MAC_ADDR3 0U +#define MAC_ADDR4 0U +#define MAC_ADDR5 0U + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB 8U /* 8 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB 4U /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848 PHY Address*/ +#define DP83848_PHY_ADDRESS 0x01U +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY 0x000000FFU +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY 0x00000FFFU + +#define PHY_READ_TO 0x0000FFFFU +#define PHY_WRITE_TO 0x0000FFFFU + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x0000) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x0001) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ + +#define PHY_SR ((uint16_t)0x0010) /*!< PHY status register Offset */ +#define PHY_MICR ((uint16_t)0x0011) /*!< MII Interrupt Control Register */ +#define PHY_MISR ((uint16_t)0x0012) /*!< MII Interrupt Status and Misc. Control Register */ + +#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ +#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ + +#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ +#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ + +#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ +#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ + +#define USE_SPI_CRC 1U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32f1xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32f1xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32f1xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32f1xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED +#include "stm32f1xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CAN_LEGACY_MODULE_ENABLED +#include "Legacy/stm32f1xx_hal_can_legacy.h" +#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32f1xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32f1xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32f1xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED +#include "stm32f1xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED +#include "stm32f1xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED +#include "stm32f1xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED +#include "stm32f1xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32f1xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED +#include "stm32f1xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32f1xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32f1xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32f1xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED +#include "stm32f1xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED +#include "stm32f1xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED +#include "stm32f1xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32f1xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32f1xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32f1xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32f1xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32f1xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32f1xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32f1xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32f1xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ +#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t*)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ +void assert_failed(uint8_t* file, uint32_t line); +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F1xx_HAL_CONF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Devices/MatrixBlock5/family.mk b/Devices/MatrixBlock5/family.mk new file mode 100644 index 00000000..d31e2bbe --- /dev/null +++ b/Devices/MatrixBlock5/family.mk @@ -0,0 +1,74 @@ +UF2_FAMILY_ID = 0x5ee21072 +ST_FAMILY = f1 +DEPS_SUBMODULES += lib/CMSIS_5 core/stm32$(ST_FAMILY)/cmsis_device_$(ST_FAMILY) core/stm32$(ST_FAMILY)/stm32$(ST_FAMILY)xx_hal_driver + +ST_CMSIS = core/stm32$(ST_FAMILY)/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = core/stm32$(ST_FAMILY)/stm32$(ST_FAMILY)xx_hal_driver + +# include $(DEVICE_PATH)/device.mk + +CFLAGS += \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m3 \ + -mfloat-abi=soft \ + -DCFG_TUSB_MCU=OPT_MCU_STM32F1\ + -nostartfiles + +SRC_C += \ + lib\tinyusb\src\portable\st\stm32_fsdev\dcd_stm32_fsdev.c \ + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_dma.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_tim.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_tim_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr.c\ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rtc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rtc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_flash.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_flash_ex.c + +SRC_CPP += \ + Platform\STM32F1\WS2812\WS2812.cpp \ + +INC += \ + $(DEVICE_PATH) \ + $(FAMILY_PATH)/Drivers \ + lib/CMSIS_5/CMSIS/Core/Include \ + Platform/stm32$(ST_FAMILY) \ + $(ST_CMSIS)/Include \ + $(ST_HAL_DRIVER)/Inc + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM3 + +.PHONY: build flash bootloader-flash app-flash erase monitor dfu-flash dfu + +build: + cmake -B $(BUILD) -Wno-dev . -DCMAKE_TOOLCHAIN_FILE=$(FAMILY_PATH)/toolchain-stm32f103.cmake -DFAMILY=$(FAMILY) -DDEVICE=$(DEVICE) -DMODE=$(MODE) -DSTM32_TOOLCHAIN_PATH="C:/Program Files/Raspberry Pi/Pico SDK v1.5.1/gcc-arm-none-eabi" -G"Unix Makefiles" + cmake --build $(BUILD) -- -j8 + +$(BUILD)/$(PROJECT)-$(DEVICE).bin: + cmake -B $(BUILD) -Wno-dev . -DCMAKE_TOOLCHAIN_FILE=$(FAMILY_PATH)/toolchain-stm32f103.cmake -DFAMILY=$(FAMILY) -DDEVICE=$(DEVICE) -DMODE=$(MODE) -DSTM32_TOOLCHAIN_PATH="C:/Program Files/Raspberry Pi/Pico SDK v1.5.1/gcc-arm-none-eabi" -G"Unix Makefiles" + cmake --build $(BUILD) -- -j8 + +flash bootloader-flash app-flash erase monitor dfu-flash dfu: + @echo "Flash commands not implemented for STM32 yet" + +uf2: $(BUILD)/$(PROJECT)-$(DEVICE).uf2 + +$(BUILD)/$(PROJECT)-$(DEVICE).uf2: $(BUILD)/$(PROJECT)-$(DEVICE).bin + @echo CREATE $@ + python Tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -b 0x0 -c -o $@ $^ + +upload: + python Tools/uf2/utils/uf2upload.py -f $(BUILD)/$(PROJECT)-$(DEVICE).uf2 -d "$(UF2_MODEL)" -l + +uf2-upload: $(BUILD)/$(PROJECT)-$(DEVICE).uf2 upload + +menuconfig: + @echo "Menuconfig not available for STM32" diff --git a/Devices/MatrixBlock5/main.cpp b/Devices/MatrixBlock5/main.cpp new file mode 100644 index 00000000..4abcaf79 --- /dev/null +++ b/Devices/MatrixBlock5/main.cpp @@ -0,0 +1,98 @@ +/** + * @file main.cpp + * @brief Main entry point for MatrixBlock5 device + */ + +#include "MatrixOS.h" +#include "Device.h" +#include "stm32f1xx_hal.h" + +// System Clock Configuration +void SystemClock_Config(void); + +// Forward declaration from OS/main.cpp +namespace MatrixOS::SYS { + void Begin(void); +} + +int main(void) { + // HAL initialization + HAL_Init(); + + // Configure the system clock + SystemClock_Config(); + + // Initialize device hardware + Device::DeviceInit(); + + // Start MatrixOS (this initializes FreeRTOS and starts the scheduler) + MatrixOS::SYS::Begin(); + + // We should never get here as Begin() starts the scheduler and never returns + while (1) { + } +} + +/** + * @brief System Clock Configuration + * The system Clock is configured as follow: + * System Clock source = PLL (HSE) + * SYSCLK(Hz) = 72000000 + * HCLK(Hz) = 72000000 + * AHB Prescaler = 1 + * APB1 Prescaler = 2 + * APB2 Prescaler = 1 + * HSE Frequency(Hz) = 8000000 + * HSE PREDIV1 = 1 + * PLLMUL = 9 + * Flash Latency(WS) = 2 + */ +void SystemClock_Config(void) { + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { + Device::ErrorHandler(); + } + + /** Initializes the CPU, AHB and APB buses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { + Device::ErrorHandler(); + } + + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB; + PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { + Device::ErrorHandler(); + } +} + +// FreeRTOS Tick Hook - Called from FreeRTOS tick interrupt +// We use this to call HAL_IncTick() for STM32 HAL timebase +extern "C" void vApplicationTickHook(void) { + HAL_IncTick(); +} + +// Error Handler +extern "C" void _Error_Handler(char *file, int line) { + while (1) { + } +} diff --git a/Devices/MatrixBlock5/note.txt b/Devices/MatrixBlock5/note.txt new file mode 100644 index 00000000..c04096d0 --- /dev/null +++ b/Devices/MatrixBlock5/note.txt @@ -0,0 +1 @@ +This is the hardware specific code for Matrix Block 5 variants (Matrix Prototype 1.2, Matrix Prototype 1.5, Matrix Prototype 2.1, and Matrix Founder Edition) \ No newline at end of file diff --git a/Devices/MatrixBlock5/startup_stm32f103xe.s b/Devices/MatrixBlock5/startup_stm32f103xe.s new file mode 100644 index 00000000..771aa8a5 --- /dev/null +++ b/Devices/MatrixBlock5/startup_stm32f103xe.s @@ -0,0 +1,470 @@ +/** + *************** (C) COPYRIGHT 2017 STMicroelectronics ************************ + * @file startup_stm32f103xe.s + * @author MCD Application Team + * @brief STM32F103xE Devices vector table for Atollic toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Configure the clock system + * - Configure external SRAM mounted on STM3210E-EVAL board + * to be used as data memory (optional, to be enabled by user) + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M3 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017-2021 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m3 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss + +.equ BootRAM, 0xF1E0F85F +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + +/* Call the clock system initialization function.*/ + bl SystemInit + +/* Copy the data segment initializers from flash to SRAM */ + ldr r0, =_sdata + ldr r1, =_edata + ldr r2, =_sidata + movs r3, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +LoopCopyDataInit: + adds r4, r0, r3 + cmp r4, r1 + bcc CopyDataInit + +/* Zero fill the bss segment. */ + ldr r2, =_sbss + ldr r4, =_ebss + movs r3, #0 + b LoopFillZerobss + +FillZerobss: + str r3, [r2] + adds r2, r2, #4 + +LoopFillZerobss: + cmp r2, r4 + bcc FillZerobss + +/* Call static constructors */ + bl __libc_init_array +/* Call the application's entry point.*/ + bl main + bx lr +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * + * @param None + * @retval : None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M3. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + .word WWDG_IRQHandler + .word PVD_IRQHandler + .word TAMPER_IRQHandler + .word RTC_IRQHandler + .word FLASH_IRQHandler + .word RCC_IRQHandler + .word EXTI0_IRQHandler + .word EXTI1_IRQHandler + .word EXTI2_IRQHandler + .word EXTI3_IRQHandler + .word EXTI4_IRQHandler + .word DMA1_Channel1_IRQHandler + .word DMA1_Channel2_IRQHandler + .word DMA1_Channel3_IRQHandler + .word DMA1_Channel4_IRQHandler + .word DMA1_Channel5_IRQHandler + .word DMA1_Channel6_IRQHandler + .word DMA1_Channel7_IRQHandler + .word ADC1_2_IRQHandler + .word USB_HP_CAN1_TX_IRQHandler + .word USB_LP_CAN1_RX0_IRQHandler + .word CAN1_RX1_IRQHandler + .word CAN1_SCE_IRQHandler + .word EXTI9_5_IRQHandler + .word TIM1_BRK_IRQHandler + .word TIM1_UP_IRQHandler + .word TIM1_TRG_COM_IRQHandler + .word TIM1_CC_IRQHandler + .word TIM2_IRQHandler + .word TIM3_IRQHandler + .word TIM4_IRQHandler + .word I2C1_EV_IRQHandler + .word I2C1_ER_IRQHandler + .word I2C2_EV_IRQHandler + .word I2C2_ER_IRQHandler + .word SPI1_IRQHandler + .word SPI2_IRQHandler + .word USART1_IRQHandler + .word USART2_IRQHandler + .word USART3_IRQHandler + .word EXTI15_10_IRQHandler + .word RTC_Alarm_IRQHandler + .word USBWakeUp_IRQHandler + .word TIM8_BRK_IRQHandler + .word TIM8_UP_IRQHandler + .word TIM8_TRG_COM_IRQHandler + .word TIM8_CC_IRQHandler + .word ADC3_IRQHandler + .word FSMC_IRQHandler + .word SDIO_IRQHandler + .word TIM5_IRQHandler + .word SPI3_IRQHandler + .word UART4_IRQHandler + .word UART5_IRQHandler + .word TIM6_IRQHandler + .word TIM7_IRQHandler + .word DMA2_Channel1_IRQHandler + .word DMA2_Channel2_IRQHandler + .word DMA2_Channel3_IRQHandler + .word DMA2_Channel4_5_IRQHandler + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word BootRAM /* @0x1E0. This is for boot in RAM mode for + STM32F10x High Density devices. */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMPER_IRQHandler + .thumb_set TAMPER_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Channel1_IRQHandler + .thumb_set DMA1_Channel1_IRQHandler,Default_Handler + + .weak DMA1_Channel2_IRQHandler + .thumb_set DMA1_Channel2_IRQHandler,Default_Handler + + .weak DMA1_Channel3_IRQHandler + .thumb_set DMA1_Channel3_IRQHandler,Default_Handler + + .weak DMA1_Channel4_IRQHandler + .thumb_set DMA1_Channel4_IRQHandler,Default_Handler + + .weak DMA1_Channel5_IRQHandler + .thumb_set DMA1_Channel5_IRQHandler,Default_Handler + + .weak DMA1_Channel6_IRQHandler + .thumb_set DMA1_Channel6_IRQHandler,Default_Handler + + .weak DMA1_Channel7_IRQHandler + .thumb_set DMA1_Channel7_IRQHandler,Default_Handler + + .weak ADC1_2_IRQHandler + .thumb_set ADC1_2_IRQHandler,Default_Handler + + .weak USB_HP_CAN1_TX_IRQHandler + .thumb_set USB_HP_CAN1_TX_IRQHandler,Default_Handler + + .weak USB_LP_CAN1_RX0_IRQHandler + .thumb_set USB_LP_CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_IRQHandler + .thumb_set TIM1_BRK_IRQHandler,Default_Handler + + .weak TIM1_UP_IRQHandler + .thumb_set TIM1_UP_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_IRQHandler + .thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak USBWakeUp_IRQHandler + .thumb_set USBWakeUp_IRQHandler,Default_Handler + + .weak TIM8_BRK_IRQHandler + .thumb_set TIM8_BRK_IRQHandler,Default_Handler + + .weak TIM8_UP_IRQHandler + .thumb_set TIM8_UP_IRQHandler,Default_Handler + + .weak TIM8_TRG_COM_IRQHandler + .thumb_set TIM8_TRG_COM_IRQHandler,Default_Handler + + .weak TIM8_CC_IRQHandler + .thumb_set TIM8_CC_IRQHandler,Default_Handler + + .weak ADC3_IRQHandler + .thumb_set ADC3_IRQHandler,Default_Handler + + .weak FSMC_IRQHandler + .thumb_set FSMC_IRQHandler,Default_Handler + + .weak SDIO_IRQHandler + .thumb_set SDIO_IRQHandler,Default_Handler + + .weak TIM5_IRQHandler + .thumb_set TIM5_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak UART4_IRQHandler + .thumb_set UART4_IRQHandler,Default_Handler + + .weak UART5_IRQHandler + .thumb_set UART5_IRQHandler,Default_Handler + + .weak TIM6_IRQHandler + .thumb_set TIM6_IRQHandler,Default_Handler + + .weak TIM7_IRQHandler + .thumb_set TIM7_IRQHandler,Default_Handler + + .weak DMA2_Channel1_IRQHandler + .thumb_set DMA2_Channel1_IRQHandler,Default_Handler + + .weak DMA2_Channel2_IRQHandler + .thumb_set DMA2_Channel2_IRQHandler,Default_Handler + + .weak DMA2_Channel3_IRQHandler + .thumb_set DMA2_Channel3_IRQHandler,Default_Handler + + .weak DMA2_Channel4_5_IRQHandler + .thumb_set DMA2_Channel4_5_IRQHandler,Default_Handler + diff --git a/Devices/MatrixBlock5/toolchain-stm32f103.cmake b/Devices/MatrixBlock5/toolchain-stm32f103.cmake new file mode 100644 index 00000000..568cda24 --- /dev/null +++ b/Devices/MatrixBlock5/toolchain-stm32f103.cmake @@ -0,0 +1,41 @@ +# STM32F103 CMake Toolchain File + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR ARM) + +# Use Raspberry Pi Pico SDK toolchain +set(STM32_TOOLCHAIN_PATH "C:/Program Files/Raspberry Pi/Pico SDK v1.5.1/gcc-arm-none-eabi") + +if(WIN32) + set(TOOLCHAIN_PREFIX "${STM32_TOOLCHAIN_PATH}/bin/arm-none-eabi-") + set(CMAKE_C_COMPILER "${TOOLCHAIN_PREFIX}gcc.exe") + set(CMAKE_CXX_COMPILER "${TOOLCHAIN_PREFIX}g++.exe") + set(CMAKE_ASM_COMPILER "${TOOLCHAIN_PREFIX}gcc.exe") + set(CMAKE_OBJCOPY "${TOOLCHAIN_PREFIX}objcopy.exe") + set(CMAKE_SIZE "${TOOLCHAIN_PREFIX}size.exe") +else() + set(TOOLCHAIN_PREFIX "${STM32_TOOLCHAIN_PATH}/bin/arm-none-eabi-") + set(CMAKE_C_COMPILER "${TOOLCHAIN_PREFIX}gcc") + set(CMAKE_CXX_COMPILER "${TOOLCHAIN_PREFIX}g++") + set(CMAKE_ASM_COMPILER "${TOOLCHAIN_PREFIX}gcc") + set(CMAKE_OBJCOPY "${TOOLCHAIN_PREFIX}objcopy") + set(CMAKE_SIZE "${TOOLCHAIN_PREFIX}size") +endif() + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +set(CMAKE_C_FLAGS_INIT "-mcpu=cortex-m3 -mthumb -mfpu=auto") +set(CMAKE_CXX_FLAGS_INIT "-mcpu=cortex-m3 -mthumb -mfpu=auto -fno-rtti -fno-exceptions") +set(CMAKE_ASM_FLAGS_INIT "-mcpu=cortex-m3 -mthumb -mfpu=auto -x assembler-with-cpp") + +# Suppress ARM assembler warnings - be more aggressive +set(CMAKE_C_FLAGS_INIT "${CMAKE_C_FLAGS_INIT} -Wa,--no-warn -Wno-error -Wno-error=all -Wno-unused-command-line-argument -Wno-implicit-fallthrough -Wno-format") +set(CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT} -Wa,--no-warn -Wno-error -Wno-error=all -Wno-unused-command-line-argument -Wno-implicit-fallthrough -Wno-format") +set(CMAKE_ASM_FLAGS_INIT "${CMAKE_ASM_FLAGS_INIT} -Wa,--no-warn -Wno-error -Wno-error=all -Wno-unused-command-line-argument -Wno-implicit-fallthrough -Wno-format") + +set(CMAKE_EXE_LINKER_FLAGS_INIT "-specs=nosys.specs -specs=nano.specs -Wl,--gc-sections -Wl,-Map=${PROJECT_NAME}.map") + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) \ No newline at end of file diff --git a/Devices/MatrixESP32/Config.cmake b/Devices/MatrixESP32/Config.cmake new file mode 100644 index 00000000..812c3fac --- /dev/null +++ b/Devices/MatrixESP32/Config.cmake @@ -0,0 +1,5 @@ +# Device feature configuration for MatrixESP32 family +# These values must match the #define values in MatrixOSConfig.h + +set(DEVICE_STORAGE 1) +set(DEVICE_BATTERY 0) diff --git a/Devices/MatrixESP32/MatrixOSConfig.h b/Devices/MatrixESP32/MatrixOSConfig.h index 1967a271..b067d376 100644 --- a/Devices/MatrixESP32/MatrixOSConfig.h +++ b/Devices/MatrixESP32/MatrixOSConfig.h @@ -1,10 +1,6 @@ #pragma once #include "Framework.h" -// Device feature configuration -#define DEVICE_STORAGE 1 -#define DEVICE_BATTERY 0 - #define FUNCTION_KEY 0 // Keypad Code for main function key #define X_SIZE 8 diff --git a/Library/CMSIS_5 b/Library/CMSIS_5 new file mode 160000 index 00000000..55b19837 --- /dev/null +++ b/Library/CMSIS_5 @@ -0,0 +1 @@ +Subproject commit 55b19837f5703e418ca37894d5745b1dc05e4c91 diff --git a/Library/FreeRTOS-Kernel b/Library/FreeRTOS-Kernel new file mode 160000 index 00000000..23328574 --- /dev/null +++ b/Library/FreeRTOS-Kernel @@ -0,0 +1 @@ +Subproject commit 233285746e7280e91239d64718ef52b32ee91f68 diff --git a/OS/FileSystem/CMakeLists.txt b/OS/FileSystem/CMakeLists.txt index 63092c4b..4161e8f4 100644 --- a/OS/FileSystem/CMakeLists.txt +++ b/OS/FileSystem/CMakeLists.txt @@ -1,21 +1,25 @@ -file(GLOB_RECURSE FILE_HEADERS "*.h") -set(FILE_SOURCES - File.cpp - FileSystem.cpp -) -# Local FatFS sources -set(FATFS_SOURCES - FatFS/ff.c - FatFS/ffunicode.c - FatFS/diskio.cpp - FatFS/ffsystem.c -) +# Only compile FileSystem.cpp if device has storage +if(DEVICE_STORAGE) + file(GLOB_RECURSE FILE_HEADERS "*.h") + + # Local FatFS sources - only needed when storage is available + set(FILE_SOURCES + FileSystem.cpp + File.cpp + FatFS/ff.c + FatFS/ffunicode.c + FatFS/diskio.cpp + FatFS/ffsystem.c + ) +else() + set(FILE_HEADERS "") + set(FILE_SOURCES "") +endif() add_library(MatrixOSFile ${FILE_HEADERS} ${FILE_SOURCES} - ${FATFS_SOURCES} ) target_include_directories(MatrixOSFile PUBLIC diff --git a/OS/Framework/Color/Color.cpp b/OS/Framework/Color/Color.cpp index 4f487f55..02254d89 100644 --- a/OS/Framework/Color/Color.cpp +++ b/OS/Framework/Color/Color.cpp @@ -1,5 +1,6 @@ #include "Color.h" #include +#include float fract(float x) { return x - int(x); } diff --git a/OS/Framework/Storage/SavedVar.h b/OS/Framework/Storage/SavedVar.h index 3e006108..675b3ae4 100644 --- a/OS/Framework/Storage/SavedVar.h +++ b/OS/Framework/Storage/SavedVar.h @@ -11,7 +11,7 @@ namespace MatrixOS::NVS enum SavedVarState { NotInited, Inited, Loaded, Deleted }; #define CreateSavedVar(scope, name, type, default_value) \ - SavedVar name = SavedVar(StaticHash(scope "-" #name), (type)default_value) + SavedVar name = SavedVar(StaticHash(scope "-" #name), (type)default_value) template class SavedVar { diff --git a/OS/System/System.cpp b/OS/System/System.cpp index f3e22677..51098c18 100644 --- a/OS/System/System.cpp +++ b/OS/System/System.cpp @@ -7,7 +7,9 @@ #include "../LED/LED.h" #include "../KeyPad/KeyPad.h" #include "../FileSystem/File.h" +#include "../FileSystem/FileSystem.h" #include "../MIDI/MIDI.h" +#include "task.h" extern std::unordered_map applications; @@ -141,7 +143,9 @@ namespace MatrixOS::SYS { MatrixOS::KeyPad::Init(); MatrixOS::LED::Init(); +#if DEVICE_STORAGE MatrixOS::FileSystem::Init(); +#endif MatrixOS::USB::SetMode(USB_MODE_NORMAL); MatrixOS::MIDI::Init(); MatrixOS::HID::Init(); diff --git a/OS/UI/UIUtilities.h b/OS/UI/UIUtilities.h index 050d7cfa..d1b05bb9 100644 --- a/OS/UI/UIUtilities.h +++ b/OS/UI/UIUtilities.h @@ -1,5 +1,6 @@ #pragma once #include "MatrixOS.h" + #include namespace MatrixOS::UIUtility diff --git a/OS/USB/CMakeLists.txt b/OS/USB/CMakeLists.txt index b0ac2d53..8ce523ad 100644 --- a/OS/USB/CMakeLists.txt +++ b/OS/USB/CMakeLists.txt @@ -1,5 +1,22 @@ file(GLOB_RECURSE USB_HEADERS "*.h") -file(GLOB_RECURSE USB_SOURCES "*.cpp" "*.c") + +# USB source files +set(USB_SOURCES + USB.cpp + HID.cpp + MIDI.cpp + CDC.cpp + TinyUSB/usb_desc_default.cpp + TinyUSB/usb_descriptors.cpp +) + +# Conditionally add MSC sources if device has storage +if(DEVICE_STORAGE) + list(APPEND USB_SOURCES + MSC.cpp + TinyUSB/usb_desc_msc.cpp + ) +endif() set(TINYUSB_DIR ${CMAKE_SOURCE_DIR}/Library/tinyusb/) @@ -15,7 +32,6 @@ set(TINYUSB_SOURCES ${TINYUSB_DIR}/src/class/dfu/dfu_rt_device.c ${TINYUSB_DIR}/src/class/hid/hid_device.c ${TINYUSB_DIR}/src/class/midi/midi_device.c - ${TINYUSB_DIR}/src/class/msc/msc_device.c ${TINYUSB_DIR}/src/class/net/ecm_rndis_device.c ${TINYUSB_DIR}/src/class/net/ncm_device.c ${TINYUSB_DIR}/src/class/usbtmc/usbtmc_device.c @@ -23,8 +39,13 @@ set(TINYUSB_SOURCES ${TINYUSB_DIR}/src/class/vendor/vendor_device.c ) +# Only include MSC device class if device has storage +if(DEVICE_STORAGE) + list(APPEND TINYUSB_SOURCES ${TINYUSB_DIR}/src/class/msc/msc_device.c) +endif() + # if(TINYUSB_MCU_OPT STREQUAL "ESP32S3" OR TINYUSB_MCU_OPT STREQUAL "ESP32S2") - list(APPEND TINYUSB_SOURCES + list(APPEND TINYUSB_SOURCES "${CMAKE_SOURCE_DIR}/Library/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c" "${CMAKE_SOURCE_DIR}/Library/tinyusb/src/portable/synopsys/dwc2/dwc2_common.c" ) @@ -43,8 +64,8 @@ add_library(MatrixOSUSB ${PRINTF_SOURCES} ) -target_include_directories(MatrixOSUSB PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR} +target_include_directories(MatrixOSUSB PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/TinyUSB ${TINYUSB_DIR}/src ${PRINTF_DIR}/src @@ -52,7 +73,12 @@ target_include_directories(MatrixOSUSB PUBLIC ) # target_compile_options(MatrixOSUSB PUBLIC -# "-DCFG_TUSB_MCU=OPT_MCU_${TINYUSB_MCU_OPT}" +# "-DCFG_TUSB_MCU=OPT_MCU_${TINYUSB_MCU_OPT}" # ) -target_link_libraries(MatrixOSUSB PUBLIC MatrixOSInterface) \ No newline at end of file +target_link_libraries(MatrixOSUSB PUBLIC MatrixOSInterface) + +# Apply device-specific TinyUSB compile options if provided +if(DEFINED DEVICE_TINYUSB_COMPILE_OPTIONS) + target_compile_options(MatrixOSUSB PRIVATE ${DEVICE_TINYUSB_COMPILE_OPTIONS}) +endif() diff --git a/OS/USB/TinyUSB/tusb_config.h b/OS/USB/TinyUSB/tusb_config.h index 5e2d90fb..e7a16119 100644 --- a/OS/USB/TinyUSB/tusb_config.h +++ b/OS/USB/TinyUSB/tusb_config.h @@ -99,7 +99,11 @@ extern "C" { //------------- CLASS -------------// #define CFG_TUD_CDC 1 +#if DEVICE_STORAGE #define CFG_TUD_MSC 1 +#else +#define CFG_TUD_MSC 0 +#endif #define CFG_TUD_HID 1 #define CFG_TUD_MIDI 1 #define CFG_TUD_VENDOR 0 diff --git a/OS/USB/TinyUSB/usb_descriptors.cpp b/OS/USB/TinyUSB/usb_descriptors.cpp index 7b45f240..a0342fcf 100644 --- a/OS/USB/TinyUSB/usb_descriptors.cpp +++ b/OS/USB/TinyUSB/usb_descriptors.cpp @@ -5,7 +5,9 @@ #include "usb_mode_interface.h" #include "usb_desc_default.h" +#if DEVICE_STORAGE #include "usb_desc_msc.h" +#endif //--------------------------------------------------------------------+ // Mode Dispatch Table @@ -18,12 +20,14 @@ const struct usb_mode_interface mode_table[] = { .get_string_descriptor = default_string_descriptor_cb, .get_hid_report_descriptor = default_hid_report_descriptor_cb }, +#if DEVICE_STORAGE [USB_MODE_MSC] = { .get_device_descriptor = msc_device_descriptor_cb, .get_configuration_descriptor = msc_configuration_descriptor_cb, .get_string_descriptor = msc_string_descriptor_cb, .get_hid_report_descriptor = NULL // MSC mode has no HID } +#endif }; //--------------------------------------------------------------------+ diff --git a/OS/USB/USB.h b/OS/USB/USB.h index 9c4035b5..9e677878 100644 --- a/OS/USB/USB.h +++ b/OS/USB/USB.h @@ -10,6 +10,11 @@ enum USB_MODE { USB_MODE_MSC = 1 // MSC only }; +// Undefine STM32 peripheral macros that conflict with C++ namespace names +#ifdef STM32F103xB +#undef USB +#endif + namespace MatrixOS::USB { void Init(USB_MODE mode = USB_MODE_NORMAL); @@ -20,4 +25,4 @@ namespace MatrixOS::USB { void Init(); } -} \ No newline at end of file +} diff --git a/Platform/CMakeLists.txt b/Platform/CMakeLists.txt deleted file mode 100644 index 4e657e18..00000000 --- a/Platform/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -# Core layer - FreeRTOS and basic system components -add_library(MatrixOSCore INTERFACE) - -target_include_directories(MatrixOSCore INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/STM32F1 - ${CMAKE_CURRENT_SOURCE_DIR}/STM32F4 - ${CMAKE_CURRENT_SOURCE_DIR}/ESP32SX -) - -# Add FreeRTOS -add_subdirectory(lib/FreeRTOS-Kernel) - -# Link FreeRTOS to core -target_link_libraries(MatrixOSCore INTERFACE FreeRTOS) - -# Add other core libraries -add_subdirectory(lib/printf) -add_subdirectory(lib/tinyusb) -add_subdirectory(lib/cb0r) - -target_link_libraries(MatrixOSCore INTERFACE - printf - tinyusb - cb0r -) \ No newline at end of file diff --git a/Platform/STM32F1/WS2812/CMakeLists.txt b/Platform/STM32F1/WS2812/CMakeLists.txt new file mode 100644 index 00000000..c3d2f4e0 --- /dev/null +++ b/Platform/STM32F1/WS2812/CMakeLists.txt @@ -0,0 +1,20 @@ +file(GLOB_RECURSE WS2812_SOURCES "*.cpp" "*.c") +file(GLOB_RECURSE WS2812_HEADERS "*.h") + +add_library(WS2812 ${WS2812_SOURCES} ${WS2812_HEADERS}) + +target_include_directories(WS2812 PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/OS +) + +# STM32F1 specific WS2812 configuration +target_compile_definitions(WS2812 PUBLIC + WS2812_USE_TIMER + WS2812_TIMER=TIM8 + WS2812_TIMER_CHANNEL=TIM_CHANNEL_2 +) + +target_link_libraries(WS2812 PUBLIC + MatrixOSFramework +) \ No newline at end of file diff --git a/Platform/STM32F1/WS2812/WS2812.cpp b/Platform/STM32F1/WS2812/WS2812.cpp new file mode 100644 index 00000000..1cc3af61 --- /dev/null +++ b/Platform/STM32F1/WS2812/WS2812.cpp @@ -0,0 +1,148 @@ +#include "WS2812.h" + +namespace WS2812 +{ + static uint16_t numsOfLED; + static uint8_t* led_data; + static uint8_t* dither_error; + static bool transfer_in_progress = false; + + // STM32 specific variables + static TIM_HandleTypeDef* ws2812_timer = nullptr; + static uint32_t ws2812_channel; + static DMA_HandleTypeDef hdma_tim; + + // WS2812 timing constants (for 72MHz system clock) + const uint32_t T0H = 29; // 0.4us at 72MHz (29 cycles) + const uint32_t T1H = 58; // 0.8us at 72MHz (58 cycles) + const uint32_t T0L = 58; // 0.85us at 72MHz (58 cycles) + const uint32_t T1L = 29; // 0.45us at 72MHz (29 cycles) + const uint32_t RESET = 2400; // 50us at 72MHz (2400 cycles) + + void Init(TIM_HandleTypeDef* timer, uint32_t channel, uint16_t led_count) { + ws2812_timer = timer; + ws2812_channel = channel; + numsOfLED = led_count; + + // Allocate memory for LED data (3 bytes per LED) + led_data = (uint8_t*)malloc(numsOfLED * 3); + if (led_data == NULL) { + // Handle memory allocation failure + return; + } + + // Allocate memory for dithering error + dither_error = (uint8_t*)malloc(numsOfLED * 3 * sizeof(uint8_t)); + if (dither_error == NULL) { + free(led_data); + led_data = NULL; + return; + } + + // Initialize dither error with random values + for (uint16_t i = 0; i < numsOfLED * 3; i++) { + dither_error[i] = HAL_GetTick() & 0x7F; // Simple pseudo-random + } + + // Clear LED data + memset(led_data, 0, numsOfLED * 3); + + // Start PWM output + HAL_TIM_PWM_Start(ws2812_timer, ws2812_channel); + } + + void Show(Color* buffer, std::vector& brightness) { + // Safety checks + if (buffer == NULL || led_data == NULL || transfer_in_progress) { + return; + } + + // Process LED data with brightness and dithering + for (uint16_t i = 0; i < numsOfLED; i++) { + uint16_t data_index = i * 3; + + // Apply brightness (assuming single partition for MatrixBlock5) + uint8_t local_brightness = brightness.size() > 0 ? brightness[0] : 255; + + led_data[data_index] = Color::scale8_video(buffer[i].G, local_brightness); + led_data[data_index + 1] = Color::scale8_video(buffer[i].R, local_brightness); + led_data[data_index + 2] = Color::scale8_video(buffer[i].B, local_brightness); + + // Apply dithering if enabled + if (dithering && dither_error != NULL) { + const uint8_t dither_error_threshold = 16; + + // Process all channels + for (int ch = 0; ch < 3; ch++) { + uint16_t channel_index = data_index + ch; + if (led_data[channel_index] >= dithering_threshold) { + uint16_t expected = (uint16_t)buffer[i].components[ch] * local_brightness; + uint16_t actual = (uint16_t)led_data[channel_index] << 8; + + if (expected > actual) { + uint8_t new_dither_error = (expected - actual) >> 8; + if (new_dither_error >= dither_error_threshold) { + dither_error[channel_index] += new_dither_error >> 1; + if (dither_error[channel_index] >= 128) { + if (led_data[channel_index] < 255) { + led_data[channel_index] += 1; + } + dither_error[channel_index] -= 128; + } + } + } + } + } + } + } + + // For STM32F1, we'll use a simple blocking approach for now + // In a real implementation, this would use DMA + + // Convert RGB data to PWM duty cycles and send + // This is a simplified implementation - real implementation would use DMA + + // Set transfer flag + transfer_in_progress = true; + + // Simple blocking transmission (replace with DMA in production) + for (uint16_t i = 0; i < numsOfLED * 3; i++) { + uint8_t byte = led_data[i]; + + // Send each bit + for (int bit = 7; bit >= 0; bit--) { + if (byte & (1 << bit)) { + // Send '1' bit + __HAL_TIM_SET_COMPARE(ws2812_timer, ws2812_channel, T1H); + // Wait for T1H duration + for (volatile int j = 0; j < 10; j++); // Simple delay + __HAL_TIM_SET_COMPARE(ws2812_timer, ws2812_channel, T1L); + } else { + // Send '0' bit + __HAL_TIM_SET_COMPARE(ws2812_timer, ws2812_channel, T0H); + // Wait for T0H duration + for (volatile int j = 0; j < 10; j++); // Simple delay + __HAL_TIM_SET_COMPARE(ws2812_timer, ws2812_channel, T0L); + } + // Wait for bit period + for (volatile int j = 0; j < 10; j++); // Simple delay + } + } + + // Send reset pulse + __HAL_TIM_SET_COMPARE(ws2812_timer, ws2812_channel, 0); + // Wait for reset duration + for (volatile int j = 0; j < 1000; j++); // Simple delay + + transfer_in_progress = false; + } + + // DMA callback functions + void DMA_TransferComplete_Callback(void) { + transfer_in_progress = false; + } + + void DMA_TransferHalfComplete_Callback(void) { + // Handle half transfer if needed + } +} \ No newline at end of file diff --git a/Platform/STM32F1/WS2812/WS2812.h b/Platform/STM32F1/WS2812/WS2812.h new file mode 100644 index 00000000..290fa935 --- /dev/null +++ b/Platform/STM32F1/WS2812/WS2812.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include +#include "Framework.h" +#include "stm32f1xx_hal.h" +#include "FreeRTOS.h" +#include "timers.h" + +namespace WS2812 +{ + inline bool dithering = false; + inline uint8_t dithering_threshold = 4; // Channel value lower than this will not dither + + void Init(TIM_HandleTypeDef* timer, uint32_t channel, uint16_t led_count); + void Show(Color* buffer, std::vector& brightness); + + // STM32 specific functions + void DMA_TransferComplete_Callback(void); + void DMA_TransferHalfComplete_Callback(void); +} \ No newline at end of file diff --git a/Platform/STM32F1/cmsis_device_f1 b/Platform/STM32F1/cmsis_device_f1 new file mode 160000 index 00000000..c8e9a4a4 --- /dev/null +++ b/Platform/STM32F1/cmsis_device_f1 @@ -0,0 +1 @@ +Subproject commit c8e9a4a4f16b6d2cb2a2083cbe5161025280fb22 diff --git a/Platform/STM32F1/stm32f1xx_hal_driver b/Platform/STM32F1/stm32f1xx_hal_driver new file mode 160000 index 00000000..53cf47b9 --- /dev/null +++ b/Platform/STM32F1/stm32f1xx_hal_driver @@ -0,0 +1 @@ +Subproject commit 53cf47b925068ed9c9196fd1842a045ee19bf0fa From 55c9ea380130c142df1e49b1397e98510484af2f Mon Sep 17 00:00:00 2001 From: Nengzhuo Cai Date: Sun, 5 Oct 2025 11:22:16 -0400 Subject: [PATCH 02/17] Update reversi to remove warning --- Applications/Reversi/Reversi.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Applications/Reversi/Reversi.cpp b/Applications/Reversi/Reversi.cpp index b361226f..4ac7f131 100644 --- a/Applications/Reversi/Reversi.cpp +++ b/Applications/Reversi/Reversi.cpp @@ -18,7 +18,7 @@ void Reversi::Loop() uint8_t Reversi::Flip(Point pos, uint8_t currentPlayer, bool update) { - uint8_t opponentPlayer = currentPlayer == 1 ? 2 : 1; + uint8_t opponentPlayer = (1 == currentPlayer) ? 2 : 1; uint8_t flipped = 0; // Check all 8 directions @@ -548,7 +548,7 @@ bool Reversi::ResetGame(bool confirmed) firstPlayer.Load(); // For some reason, the firstPlayer is not auto loaded correctly - uint8_t secondPlayer = (firstPlayer == 1) ? 2 : 1; + uint8_t secondPlayer = (1 == firstPlayer) ? 2 : 1; board[3][3].player = firstPlayer; board[3][3].wasPlayer = firstPlayer; @@ -637,14 +637,14 @@ void Reversi::Settings() { UIButton player1FirstHand; player1FirstHand.SetName("Player 1 First Hand"); - player1FirstHand.SetColorFunc([&]() -> Color { return Color::White.DimIfNot(firstPlayer == 1); }); - player1FirstHand.OnPress([&]() -> void { if(firstPlayer == 1) {return;} if (gameState == Ended || !started || ConfirmMenu()) { firstPlayer = 1; ResetGame(true);} }); + player1FirstHand.SetColorFunc([&]() -> Color { return Color::White.DimIfNot(1 == firstPlayer); }); + player1FirstHand.OnPress([&]() -> void { if(1 == firstPlayer) {return;} if (gameState == Ended || !started || ConfirmMenu()) { firstPlayer = 1; ResetGame(true);} }); settingsUI.AddUIComponent(player1FirstHand, Point(7, 6)); UIButton player2FirstHand; player2FirstHand.SetName("Player 2 First Hand"); - player2FirstHand.SetColorFunc([&]() -> Color { return Color::White.DimIfNot(firstPlayer == 2); }); - player2FirstHand.OnPress([&]() -> void { if(firstPlayer == 2) {return;} if (gameState == Ended || !started || ConfirmMenu()) { firstPlayer = 2; ResetGame(true);} }); + player2FirstHand.SetColorFunc([&]() -> Color { return Color::White.DimIfNot(2 == firstPlayer); }); + player2FirstHand.OnPress([&]() -> void { if(2 == firstPlayer) {return;} if (gameState == Ended || !started || ConfirmMenu()) { firstPlayer = 2; ResetGame(true);} }); settingsUI.AddUIComponent(player2FirstHand, Point(0, 1)); UIToggle hintToggle; From 378e02159f97c8e9255147c456a1aa7454e3dcd3 Mon Sep 17 00:00:00 2001 From: Nengzhuo Cai Date: Sun, 5 Oct 2025 11:25:58 -0400 Subject: [PATCH 03/17] Fix usb driver stub --- Devices/MatrixBlock5/CMakeLists.txt | 2 +- Devices/MatrixBlock5/Drivers/dcd_stm32f1.c | 123 --------------------- 2 files changed, 1 insertion(+), 124 deletions(-) delete mode 100644 Devices/MatrixBlock5/Drivers/dcd_stm32f1.c diff --git a/Devices/MatrixBlock5/CMakeLists.txt b/Devices/MatrixBlock5/CMakeLists.txt index 44806bc4..7bff2af5 100644 --- a/Devices/MatrixBlock5/CMakeLists.txt +++ b/Devices/MatrixBlock5/CMakeLists.txt @@ -90,7 +90,7 @@ add_library(MatrixOSDevice ${DEVICE_SOURCES} ${STM32_HAL_SOURCES} ${DEVICE_HEADERS} - ${CMAKE_CURRENT_SOURCE_DIR}/Drivers/dcd_stm32f1.c + ${CMAKE_SOURCE_DIR}/Library/tinyusb/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ${CMAKE_CURRENT_SOURCE_DIR}/startup_stm32f103xe.s ) diff --git a/Devices/MatrixBlock5/Drivers/dcd_stm32f1.c b/Devices/MatrixBlock5/Drivers/dcd_stm32f1.c deleted file mode 100644 index bc15850b..00000000 --- a/Devices/MatrixBlock5/Drivers/dcd_stm32f1.c +++ /dev/null @@ -1,123 +0,0 @@ -/** - * @file dcd_stm32f1.c - * @brief TinyUSB device controller driver stub for STM32F1 - * - * This is a stub implementation to allow linking. The actual implementation - * will need to configure the STM32F1 USB peripheral for device mode. - */ - -#include "tusb.h" - -// Initialize device controller -void dcd_init(uint8_t rhport) { - (void)rhport; - // TODO: Initialize STM32F1 USB device controller -} - -// Enable device interrupt -void dcd_int_enable(uint8_t rhport) { - (void)rhport; - // TODO: Enable USB interrupts -} - -// Disable device interrupt -void dcd_int_disable(uint8_t rhport) { - (void)rhport; - // TODO: Disable USB interrupts -} - -// Set device address -void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { - (void)rhport; - (void)dev_addr; - // TODO: Set USB device address -} - -// Wake up host -void dcd_remote_wakeup(uint8_t rhport) { - (void)rhport; - // TODO: Implement remote wakeup -} - -// Connect/disconnect by enabling/disabling internal pull-up resistor -void dcd_connect(uint8_t rhport) { - (void)rhport; - // TODO: Connect device (enable pull-up) -} - -void dcd_disconnect(uint8_t rhport) { - (void)rhport; - // TODO: Disconnect device (disable pull-up) -} - -// Enable/disable SOF interrupt -void dcd_sof_enable(uint8_t rhport, bool en) { - (void)rhport; - (void)en; - // TODO: Enable/disable SOF interrupt -} - -//--------------------------------------------------------------------+ -// Endpoint API -//--------------------------------------------------------------------+ - -// Open an endpoint -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { - (void)rhport; - (void)desc_ep; - // TODO: Open endpoint - return true; -} - -// Close all non-control endpoints -void dcd_edpt_close_all(uint8_t rhport) { - (void)rhport; - // TODO: Close all endpoints -} - -// Submit a transfer -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { - (void)rhport; - (void)ep_addr; - (void)buffer; - (void)total_bytes; - // TODO: Submit transfer - return true; -} - -// Stall endpoint -void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { - (void)rhport; - (void)ep_addr; - // TODO: Stall endpoint -} - -// Clear stall -void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { - (void)rhport; - (void)ep_addr; - // TODO: Clear endpoint stall -} - -// Interrupt handler -void dcd_int_handler(uint8_t rhport) { - (void)rhport; - // TODO: Handle USB interrupts and call appropriate dcd_event_* functions -} - -// ISO endpoint allocation (optional, for isochronous transfers) -bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { - (void)rhport; - (void)ep_addr; - (void)largest_packet_size; - // TODO: Allocate ISO endpoint - return false; -} - -// ISO endpoint activation (optional, for isochronous transfers) -bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { - (void)rhport; - (void)desc_ep; - // TODO: Activate ISO endpoint - return false; -} From a1245de0ccef5cb02eae8e714425063482741818 Mon Sep 17 00:00:00 2001 From: Nengzhuo Cai Date: Sun, 5 Oct 2025 11:30:03 -0400 Subject: [PATCH 04/17] Remove keypad calibration --- Devices/MatrixBlock5/Family.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Devices/MatrixBlock5/Family.cpp b/Devices/MatrixBlock5/Family.cpp index a0aee272..84943215 100644 --- a/Devices/MatrixBlock5/Family.cpp +++ b/Devices/MatrixBlock5/Family.cpp @@ -81,13 +81,6 @@ namespace Device touchbarToggle.OnPress([&]() -> void { touchbar_enable.Save(); }); deviceSettings.AddUIComponent(touchbarToggle, Point(0, 0)); - UIButton keypadCalibrationBtn; - keypadCalibrationBtn.SetName("Keypad Calibration"); - keypadCalibrationBtn.SetColor(Color::White); - keypadCalibrationBtn.OnPress([]() -> void { MatrixOS::SYS::ExecuteAPP("203 Systems", "Force Calibration"); }); - keypadCalibrationBtn.SetEnabled(KeyPad::velocity_sensitivity); - deviceSettings.AddUIComponent(keypadCalibrationBtn, Point(7, 0)); - deviceSettings.Start(); } From e57e80cb369bfe30e1ee3f5cc2d81928d6bf0bea Mon Sep 17 00:00:00 2001 From: Nengzhuo Cai Date: Sun, 5 Oct 2025 11:30:12 -0400 Subject: [PATCH 05/17] FE bootloader func --- Devices/MatrixBlock5/Drivers/BKP.cpp | 34 ---------------------------- Devices/MatrixBlock5/Family.cpp | 9 ++++++-- 2 files changed, 7 insertions(+), 36 deletions(-) delete mode 100644 Devices/MatrixBlock5/Drivers/BKP.cpp diff --git a/Devices/MatrixBlock5/Drivers/BKP.cpp b/Devices/MatrixBlock5/Drivers/BKP.cpp deleted file mode 100644 index 762638c4..00000000 --- a/Devices/MatrixBlock5/Drivers/BKP.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "Device.h" - -// Undefine the BKP macro from STM32 HAL to avoid namespace conflict -#ifdef BKP -#define STM32_BKP_BASE BKP -#undef BKP -#endif - -namespace Device::BackupReg -{ - uint16_t size = 20; - - uint32_t Read(uint32_t address) { - RTC_HandleTypeDef RtcHandle; - RtcHandle.Instance = RTC; - return HAL_RTCEx_BKUPRead(&RtcHandle, address); - } - - int8_t Write(uint32_t address, uint32_t data) { - if (address >= size) - return -1; - RTC_HandleTypeDef RtcHandle; - RtcHandle.Instance = RTC; - HAL_PWR_EnableBkUpAccess(); - HAL_RTCEx_BKUPWrite(&RtcHandle, address, data); - HAL_PWR_DisableBkUpAccess(); - return 0; - } -} - -// Restore the BKP macro for STM32 HAL -#ifdef STM32_BKP_BASE -#define BKP STM32_BKP_BASE -#endif \ No newline at end of file diff --git a/Devices/MatrixBlock5/Family.cpp b/Devices/MatrixBlock5/Family.cpp index 84943215..09f191eb 100644 --- a/Devices/MatrixBlock5/Family.cpp +++ b/Devices/MatrixBlock5/Family.cpp @@ -85,8 +85,13 @@ namespace Device } void Bootloader() { - // TODO: Implement bootloader entry mechanism for STM32F103 - // For now, just reboot + // Write bootloader magic to RTC backup register + RTC_HandleTypeDef RtcHandle; + RtcHandle.Instance = RTC; + HAL_PWR_EnableBkUpAccess(); + HAL_RTCEx_BKUPWrite(&RtcHandle, 10, 0x424C); + HAL_PWR_DisableBkUpAccess(); + Reboot(); } From 0e75e62099a2ffcaeb6382b79d82037c8078b5d9 Mon Sep 17 00:00:00 2001 From: Nengzhuo Cai Date: Sun, 5 Oct 2025 11:30:20 -0400 Subject: [PATCH 06/17] Remove existing NVS --- Devices/MatrixBlock5/Drivers/NVS.cpp | 46 ++++++----------------- Devices/MatrixBlock5/Drivers/NVS.h | 56 ---------------------------- 2 files changed, 11 insertions(+), 91 deletions(-) delete mode 100644 Devices/MatrixBlock5/Drivers/NVS.h diff --git a/Devices/MatrixBlock5/Drivers/NVS.cpp b/Devices/MatrixBlock5/Drivers/NVS.cpp index 47f7dd40..32587934 100644 --- a/Devices/MatrixBlock5/Drivers/NVS.cpp +++ b/Devices/MatrixBlock5/Drivers/NVS.cpp @@ -1,56 +1,32 @@ -#include "NVS.h" +#include "Device.h" namespace Device::NVS { - string tag = "NVS Driver"; - void Init() { - // TODO: Implement NVS driver for STM32F103 - // For now, this is stubbed out + // Stub: NVS not implemented for STM32F103 } void Clear() { - // TODO: Implement NVS clear + // Stub: NVS not implemented for STM32F103 } - bool Get(string name_space, string key, void* pointer, uint16_t length) { - // TODO: Implement NVS get - return false; - } - - bool Set(string name_space, string key, void* pointer, uint16_t length) { - // TODO: Implement NVS set - return false; - } - - bool GetString(string name_space, string key, string* string_p) { - // TODO: Implement NVS get string - return false; - } - - bool SetString(string name_space, string key, string* string_p) { - // TODO: Implement NVS set string - return false; + size_t Size(uint32_t hash) { + // Stub: NVS not implemented for STM32F103 + return 0; } - // Additional NVS functions required by MatrixOS::NVS - std::vector Read(uint32_t hash) { - // TODO: Implement NVS read by hash - return std::vector(); + vector Read(uint32_t hash) { + // Stub: NVS not implemented for STM32F103 + return vector(); } bool Write(uint32_t hash, void* pointer, uint16_t length) { - // TODO: Implement NVS write by hash + // Stub: NVS not implemented for STM32F103 return false; } - size_t Size(uint32_t hash) { - // TODO: Implement NVS size by hash - return 0; - } - bool Delete(uint32_t hash) { - // TODO: Implement NVS delete by hash + // Stub: NVS not implemented for STM32F103 return false; } } diff --git a/Devices/MatrixBlock5/Drivers/NVS.h b/Devices/MatrixBlock5/Drivers/NVS.h deleted file mode 100644 index 24007aa8..00000000 --- a/Devices/MatrixBlock5/Drivers/NVS.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include "Device.h" -#include - -namespace Device::NVS -{ - - struct HashKey { - uint32_t hash; - uint16_t length; - uint16_t new_address = 0xFFFF; // This is what limiting the max size. If more than 64 KB is needed, maybe change - // this to uint32_t along with other changes - - HashKey() { - this->hash = 0; - this->length = 0; - } - - HashKey(uint32_t hash, uint16_t length) { - this->hash = hash; - this->length = length; - } - - bool Used() { return hash != 0xFFFFFFFF; } - bool Latest() { return new_address == 0xFFFF; } - }; - - const uint32_t direction_indicator = 0x28dc67e2; - - void Init(); - void UpdateBytesUsed(); - - uint16_t FindKey(uint32_t hash); - - HashKey* GetKey(uint16_t virtual_address); - HashKey* GetKey(uint8_t page, uint16_t local_address); - uint16_t GetVirtualAddress(HashKey* hashKey); - uint32_t GetPage(uint8_t index); - uint16_t GetFreeSpace(uint8_t page); - int8_t CheckSpace(uint16_t length); - - void CleanUpTable(uint32_t hash_to_ignore = 0); - - bool WriteKey(uint32_t hash, void* pointer, uint16_t length); - - void WriteToFlash(uint32_t pointer, uint16_t length, uint16_t* address); - void ErasePage(uint32_t address, uint32_t pages = 1); - - // Public API functions - size_t Size(uint32_t hash); - std::vector Read(uint32_t hash); - bool Write(uint32_t hash, void* pointer, uint16_t length); - bool Delete(uint32_t hash); - void Clear(); -} \ No newline at end of file From 36b13ea402a83f23eda19a8893e3bccadd5e2c7a Mon Sep 17 00:00:00 2001 From: Nengzhuo Cai Date: Sun, 5 Oct 2025 12:11:32 -0400 Subject: [PATCH 07/17] Clean up --- .../Variants/MatrixFounderEdition/note.txt | 1 - Devices/MatrixBlock5/family.mk | 25 +++---------------- Devices/MatrixBlock5/note.txt | 1 - .../MatrixBlock5/toolchain-stm32f103.cmake | 24 +++++------------- 4 files changed, 10 insertions(+), 41 deletions(-) delete mode 100644 Devices/MatrixBlock5/Variants/MatrixFounderEdition/note.txt delete mode 100644 Devices/MatrixBlock5/note.txt diff --git a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/note.txt b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/note.txt deleted file mode 100644 index 17bb8a8a..00000000 --- a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/note.txt +++ /dev/null @@ -1 +0,0 @@ -This is the hardware specific code for Matrix Block 6 variants \ No newline at end of file diff --git a/Devices/MatrixBlock5/family.mk b/Devices/MatrixBlock5/family.mk index d31e2bbe..06f81b57 100644 --- a/Devices/MatrixBlock5/family.mk +++ b/Devices/MatrixBlock5/family.mk @@ -46,29 +46,12 @@ INC += \ # For freeRTOS port source FREERTOS_PORT = ARM_CM3 -.PHONY: build flash bootloader-flash app-flash erase monitor dfu-flash dfu +.PHONY: build flash upload -build: - cmake -B $(BUILD) -Wno-dev . -DCMAKE_TOOLCHAIN_FILE=$(FAMILY_PATH)/toolchain-stm32f103.cmake -DFAMILY=$(FAMILY) -DDEVICE=$(DEVICE) -DMODE=$(MODE) -DSTM32_TOOLCHAIN_PATH="C:/Program Files/Raspberry Pi/Pico SDK v1.5.1/gcc-arm-none-eabi" -G"Unix Makefiles" +$(BUILD)/$(PROJECT)-$(DEVICE).bin build: + cmake -B $(BUILD) -Wno-dev . -DCMAKE_TOOLCHAIN_FILE=$(FAMILY_PATH)/toolchain-stm32f103.cmake -DFAMILY=$(FAMILY) -DDEVICE=$(DEVICE) -DMODE=$(MODE) -G"Unix Makefiles" cmake --build $(BUILD) -- -j8 -$(BUILD)/$(PROJECT)-$(DEVICE).bin: - cmake -B $(BUILD) -Wno-dev . -DCMAKE_TOOLCHAIN_FILE=$(FAMILY_PATH)/toolchain-stm32f103.cmake -DFAMILY=$(FAMILY) -DDEVICE=$(DEVICE) -DMODE=$(MODE) -DSTM32_TOOLCHAIN_PATH="C:/Program Files/Raspberry Pi/Pico SDK v1.5.1/gcc-arm-none-eabi" -G"Unix Makefiles" - cmake --build $(BUILD) -- -j8 - -flash bootloader-flash app-flash erase monitor dfu-flash dfu: +flash upload: @echo "Flash commands not implemented for STM32 yet" -uf2: $(BUILD)/$(PROJECT)-$(DEVICE).uf2 - -$(BUILD)/$(PROJECT)-$(DEVICE).uf2: $(BUILD)/$(PROJECT)-$(DEVICE).bin - @echo CREATE $@ - python Tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -b 0x0 -c -o $@ $^ - -upload: - python Tools/uf2/utils/uf2upload.py -f $(BUILD)/$(PROJECT)-$(DEVICE).uf2 -d "$(UF2_MODEL)" -l - -uf2-upload: $(BUILD)/$(PROJECT)-$(DEVICE).uf2 upload - -menuconfig: - @echo "Menuconfig not available for STM32" diff --git a/Devices/MatrixBlock5/note.txt b/Devices/MatrixBlock5/note.txt deleted file mode 100644 index c04096d0..00000000 --- a/Devices/MatrixBlock5/note.txt +++ /dev/null @@ -1 +0,0 @@ -This is the hardware specific code for Matrix Block 5 variants (Matrix Prototype 1.2, Matrix Prototype 1.5, Matrix Prototype 2.1, and Matrix Founder Edition) \ No newline at end of file diff --git a/Devices/MatrixBlock5/toolchain-stm32f103.cmake b/Devices/MatrixBlock5/toolchain-stm32f103.cmake index 568cda24..4e8eadbc 100644 --- a/Devices/MatrixBlock5/toolchain-stm32f103.cmake +++ b/Devices/MatrixBlock5/toolchain-stm32f103.cmake @@ -3,24 +3,12 @@ set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_PROCESSOR ARM) -# Use Raspberry Pi Pico SDK toolchain -set(STM32_TOOLCHAIN_PATH "C:/Program Files/Raspberry Pi/Pico SDK v1.5.1/gcc-arm-none-eabi") - -if(WIN32) - set(TOOLCHAIN_PREFIX "${STM32_TOOLCHAIN_PATH}/bin/arm-none-eabi-") - set(CMAKE_C_COMPILER "${TOOLCHAIN_PREFIX}gcc.exe") - set(CMAKE_CXX_COMPILER "${TOOLCHAIN_PREFIX}g++.exe") - set(CMAKE_ASM_COMPILER "${TOOLCHAIN_PREFIX}gcc.exe") - set(CMAKE_OBJCOPY "${TOOLCHAIN_PREFIX}objcopy.exe") - set(CMAKE_SIZE "${TOOLCHAIN_PREFIX}size.exe") -else() - set(TOOLCHAIN_PREFIX "${STM32_TOOLCHAIN_PATH}/bin/arm-none-eabi-") - set(CMAKE_C_COMPILER "${TOOLCHAIN_PREFIX}gcc") - set(CMAKE_CXX_COMPILER "${TOOLCHAIN_PREFIX}g++") - set(CMAKE_ASM_COMPILER "${TOOLCHAIN_PREFIX}gcc") - set(CMAKE_OBJCOPY "${TOOLCHAIN_PREFIX}objcopy") - set(CMAKE_SIZE "${TOOLCHAIN_PREFIX}size") -endif() +# Assume toolchain is in PATH like MatrixOS-2.6.0 +set(CMAKE_C_COMPILER arm-none-eabi-gcc) +set(CMAKE_CXX_COMPILER arm-none-eabi-g++) +set(CMAKE_ASM_COMPILER arm-none-eabi-gcc) +set(CMAKE_OBJCOPY arm-none-eabi-objcopy) +set(CMAKE_SIZE arm-none-eabi-size) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) From 9ca2a090d4e9e6c2e0d61fff8048fda081369407 Mon Sep 17 00:00:00 2001 From: Nengzhuo Cai Date: Sun, 5 Oct 2025 12:32:56 -0400 Subject: [PATCH 08/17] flash --- Devices/MatrixBlock5/family.mk | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Devices/MatrixBlock5/family.mk b/Devices/MatrixBlock5/family.mk index 06f81b57..4d38e42d 100644 --- a/Devices/MatrixBlock5/family.mk +++ b/Devices/MatrixBlock5/family.mk @@ -2,6 +2,20 @@ UF2_FAMILY_ID = 0x5ee21072 ST_FAMILY = f1 DEPS_SUBMODULES += lib/CMSIS_5 core/stm32$(ST_FAMILY)/cmsis_device_$(ST_FAMILY) core/stm32$(ST_FAMILY)/stm32$(ST_FAMILY)xx_hal_driver +# Detect whether shell style is windows or not +# https://stackoverflow.com/questions/714100/os-detecting-makefile/52062069#52062069 +ifeq '$(findstring ;,$(PATH))' ';' +CMDEXE := 1 +endif + +ifeq ($(CMDEXE),1) + CP = copy >nul + RM = del +else + CP = cp + RM = rm +endif + ST_CMSIS = core/stm32$(ST_FAMILY)/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = core/stm32$(ST_FAMILY)/stm32$(ST_FAMILY)xx_hal_driver @@ -51,7 +65,9 @@ FREERTOS_PORT = ARM_CM3 $(BUILD)/$(PROJECT)-$(DEVICE).bin build: cmake -B $(BUILD) -Wno-dev . -DCMAKE_TOOLCHAIN_FILE=$(FAMILY_PATH)/toolchain-stm32f103.cmake -DFAMILY=$(FAMILY) -DDEVICE=$(DEVICE) -DMODE=$(MODE) -G"Unix Makefiles" cmake --build $(BUILD) -- -j8 + @$(CP) "$(subst /,\,$(BUILD)/Devices/MatrixBlock5/$(PROJECT)-$(DEVICE).bin)" "$(subst /,\,$(BUILD)/)" + $(if $(wildcard $(BUILD)/Devices/MatrixBlock5/$(PROJECT)-$(DEVICE).map),@$(CP) "$(subst /,\,$(BUILD)/Devices/MatrixBlock5/$(PROJECT)-$(DEVICE).map)" "$(subst /,\,$(BUILD)/)",) -flash upload: - @echo "Flash commands not implemented for STM32 yet" +flash upload: $(BUILD)/$(PROJECT)-$(DEVICE).bin + dfu-util "-a 0" "-d 0203:0003" -D"$<" -R From b38843159dfa422e3b5492601d670cd5b989e616 Mon Sep 17 00:00:00 2001 From: Nengzhuo Cai Date: Sun, 5 Oct 2025 13:14:03 -0400 Subject: [PATCH 09/17] Remove unneeded build stuffs --- Devices/MatrixBlock5/CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Devices/MatrixBlock5/CMakeLists.txt b/Devices/MatrixBlock5/CMakeLists.txt index 7bff2af5..1cf0e1b2 100644 --- a/Devices/MatrixBlock5/CMakeLists.txt +++ b/Devices/MatrixBlock5/CMakeLists.txt @@ -1,11 +1,6 @@ # MatrixBlock5 uses STM32F103 set(DEVICE_TARGET "STM32F103") -# Set up STM32CubeIDE toolchain if available -if(NOT DEFINED STM32_TOOLCHAIN_PATH) - message(FATAL_ERROR "STM32 toolchain not defined. Please set STM32_TOOLCHAIN_PATH environment variable.") -endif() - # Include the STM32 toolchain file include(${CMAKE_CURRENT_SOURCE_DIR}/toolchain-stm32f103.cmake) From 2c8a3f7a7bcf305f9af59b024ad0b306cecc04d4 Mon Sep 17 00:00:00 2001 From: Nengzhuo Cai Date: Sun, 5 Oct 2025 15:55:44 -0400 Subject: [PATCH 10/17] flash correctly now --- Devices/MatrixBlock5/CMakeLists.txt | 8 +- Devices/MatrixBlock5/Drivers/USB.cpp | 43 ++ Devices/MatrixBlock5/Family.cpp | 87 ++-- Devices/MatrixBlock5/Family.h | 63 +-- Devices/MatrixBlock5/FreeRTOSConfig.h | 4 +- .../MatrixFounderEdition/FounderEdition.cpp | 23 +- Devices/MatrixBlock5/family.mk | 53 +- Devices/MatrixBlock5/startup_stm32f103xe.s | 470 ------------------ OS/UI/UI.h | 1 + OS/USB/USB.h | 2 +- Platform/STM32F1/WS2812/WS2812.cpp | 6 +- 11 files changed, 106 insertions(+), 654 deletions(-) create mode 100644 Devices/MatrixBlock5/Drivers/USB.cpp delete mode 100644 Devices/MatrixBlock5/startup_stm32f103xe.s diff --git a/Devices/MatrixBlock5/CMakeLists.txt b/Devices/MatrixBlock5/CMakeLists.txt index 1cf0e1b2..6689d649 100644 --- a/Devices/MatrixBlock5/CMakeLists.txt +++ b/Devices/MatrixBlock5/CMakeLists.txt @@ -1,6 +1,8 @@ # MatrixBlock5 uses STM32F103 set(DEVICE_TARGET "STM32F103") +enable_language(ASM) + # Include the STM32 toolchain file include(${CMAKE_CURRENT_SOURCE_DIR}/toolchain-stm32f103.cmake) @@ -55,6 +57,7 @@ file(GLOB_RECURSE DEVICE_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Family.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Drivers/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Variants/MatrixFounderEdition/*.cpp" + "${CMAKE_SOURCE_DIR}/Platform/STM32F1/WS2812/*.cpp" ) # STM32 HAL source files @@ -86,7 +89,7 @@ add_library(MatrixOSDevice ${STM32_HAL_SOURCES} ${DEVICE_HEADERS} ${CMAKE_SOURCE_DIR}/Library/tinyusb/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - ${CMAKE_CURRENT_SOURCE_DIR}/startup_stm32f103xe.s + ${CMAKE_SOURCE_DIR}/Platform/STM32F1/cmsis_device_f1/Source/Templates/gcc/startup_stm32f103xe.s ) target_include_directories(MatrixOSDevice PUBLIC @@ -145,10 +148,11 @@ target_compile_definitions(FreeRTOS PUBLIC # STM32F103 specific definitions # Note: VDD_VALUE, PREFETCH_ENABLE, HSE/LSE/HSI/LSI values are defined in stm32f1xx_hal_conf.h target_compile_definitions(MatrixOSDevice PUBLIC - STM32F103xB + STM32F103xE USE_HAL_DRIVER CFG_TUSB_MCU=OPT_MCU_STM32F1 __thumb2__=1 + VECT_TAB_OFFSET=0x2000 ) # Set C++ standard for MatrixOSDevice target diff --git a/Devices/MatrixBlock5/Drivers/USB.cpp b/Devices/MatrixBlock5/Drivers/USB.cpp new file mode 100644 index 00000000..f812d8e5 --- /dev/null +++ b/Devices/MatrixBlock5/Drivers/USB.cpp @@ -0,0 +1,43 @@ +#include "Family.h" +#include "tusb.h" + +namespace Device::USB +{ + void Init() + { + NVIC_SetPriority(USB_HP_CAN1_TX_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + NVIC_SetPriority(USBWakeUp_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + + // Enable GPIO clocks + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + + // Configure USB DM and DP pins (PA11, PA12) + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + // USB Clock enable + __HAL_RCC_USB_CLK_ENABLE(); + } +} + +extern "C" { +void USB_HP_IRQHandler(void) { + dcd_int_handler(0); +} + +void USB_LP_IRQHandler(void) { + dcd_int_handler(0); +} + +void USBWakeUp_IRQHandler(void) { + dcd_int_handler(0); +} +} \ No newline at end of file diff --git a/Devices/MatrixBlock5/Family.cpp b/Devices/MatrixBlock5/Family.cpp index 09f191eb..e5945973 100644 --- a/Devices/MatrixBlock5/Family.cpp +++ b/Devices/MatrixBlock5/Family.cpp @@ -11,19 +11,17 @@ extern "C" void dcd_int_handler(uint8_t rhport); // Variant loader function void LoadFounderEdition(); + namespace Device { - namespace KeyPad - { - void Scan(); - } - void DeviceInit() { - LoadDeviceInfo(); - USBController::Init(); - NVS::Init(); + HAL_Init(); + SystemClock_Config(); + + USB::Init(); LED::Init(); KeyPad::Init(); + // NVS::Init(); //Not working TODO FIX } void DeviceStart() { @@ -140,38 +138,32 @@ namespace Device * @retval None */ void SystemClock_Config(void) { - RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - - /** Initializes the RCC Oscillators according to the specified parameters - * in the RCC_OscInitTypeDef structure. - */ - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; - RCC_OscInitStruct.HSEState = RCC_HSE_ON; - RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; - RCC_OscInitStruct.HSIState = RCC_HSI_ON; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; - RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) - { ErrorHandler(); } - /** Initializes the CPU, AHB and APB buses clocks - */ - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; - - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) - { ErrorHandler(); } - PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB; - PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5; - if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) - { ErrorHandler(); } + RCC_ClkInitTypeDef clkinitstruct = {0}; + RCC_OscInitTypeDef oscinitstruct = {0}; + RCC_PeriphCLKInitTypeDef rccperiphclkinit = {0}; + + /* Enable HSE Oscillator and activate PLL with HSE as source */ + oscinitstruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + oscinitstruct.HSEState = RCC_HSE_ON; + oscinitstruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; + oscinitstruct.PLL.PLLMUL = RCC_PLL_MUL9; + oscinitstruct.PLL.PLLState = RCC_PLL_ON; + oscinitstruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + HAL_RCC_OscConfig(&oscinitstruct); + + /* USB clock selection */ + rccperiphclkinit.PeriphClockSelection = RCC_PERIPHCLK_USB; + rccperiphclkinit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5; + HAL_RCCEx_PeriphCLKConfig(&rccperiphclkinit); + + /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */ + clkinitstruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + clkinitstruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + clkinitstruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + clkinitstruct.APB1CLKDivider = RCC_HCLK_DIV2; + clkinitstruct.APB2CLKDivider = RCC_HCLK_DIV1; + HAL_RCC_ClockConfig(&clkinitstruct, FLASH_LATENCY_2); } - } namespace MatrixOS::SYS @@ -180,23 +172,6 @@ namespace MatrixOS::SYS } extern "C" { -void USB_HP_CAN1_TX_IRQHandler(void) { - dcd_int_handler(0); -} - -void USB_LP_CAN1_RX0_IRQHandler(void) { - dcd_int_handler(0); -} - -void USBWakeUp_IRQHandler(void) { - dcd_int_handler(0); -} - -// void SysTick_Handler(void) -// { -// HAL_IncTick(); -// } - void _init(void) { ; } diff --git a/Devices/MatrixBlock5/Family.h b/Devices/MatrixBlock5/Family.h index 69870e7d..f57aa6b5 100644 --- a/Devices/MatrixBlock5/Family.h +++ b/Devices/MatrixBlock5/Family.h @@ -7,7 +7,7 @@ #include "stm32f1xx_hal.h" #include "WS2812/WS2812.h" -#define STM32_PLATFORM 1 +#undef USB // CMSIS defined the USB, undef so we can use USB as MatrixOS namespace // Family-specific defines #define GRID_TYPE_8x8 @@ -29,32 +29,22 @@ namespace Device // Device Variable inline CreateSavedVar(DEVICE_SAVED_VAR_SCOPE, touchbar_enable, bool, true); - inline CreateSavedVar(DEVICE_SAVED_VAR_SCOPE, bluetooth, bool, false); - - namespace HWMidi - { - inline GPIO_TypeDef* tx_port = nullptr; - inline uint16_t tx_pin = 0; - inline GPIO_TypeDef* rx_port = nullptr; - inline uint16_t rx_pin = 0; - } - - namespace LED - { - inline GPIO_TypeDef* led_port = nullptr; - inline uint16_t led_pin = 0; - inline bool underglow = false; - } void LoadDeviceInfo(); void LoadVariantInfo(); + + void SystemClock_Config(); - namespace USBController + namespace USB { void Init(); } + namespace LED { + inline GPIO_TypeDef* led_port = nullptr; + inline uint16_t led_pin = 0; + void Init(); void Start(); } @@ -118,20 +108,6 @@ namespace Device inline KeyInfo keypadState[X_SIZE][Y_SIZE]; inline KeyInfo touchbarState[touchbar_size]; - namespace Binary - { - void Init(); - void Start(); - bool Scan(); - } - - namespace FSR - { - void Init(); - void Start(); - bool Scan(); - } - bool NotifyOS(uint16_t keyID, KeyInfo* keyInfo); // Passthrough MatrixOS::KeyPad::NewEvent() result } @@ -139,25 +115,4 @@ namespace Device { void Init(); } - - namespace WIFI - { - void Init(); - } - - namespace BLEMIDI - { - extern bool started; - void Init(string name); - void Start(); - void Stop(); - } - - namespace HWMidi - { - void Init(); - } - -} - -#undef USB // CMSIS defined the USB, undef so we can use USB as MatrixOS namespace \ No newline at end of file +} \ No newline at end of file diff --git a/Devices/MatrixBlock5/FreeRTOSConfig.h b/Devices/MatrixBlock5/FreeRTOSConfig.h index 46e9a81a..9ded84f7 100644 --- a/Devices/MatrixBlock5/FreeRTOSConfig.h +++ b/Devices/MatrixBlock5/FreeRTOSConfig.h @@ -42,8 +42,8 @@ *----------------------------------------------------------*/ // STM32 device definition - must be defined before including HAL headers -#ifndef STM32F103xB -#define STM32F103xB +#ifndef STM32F103xE +#define STM32F103xE #endif // Include MCU header diff --git a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp index f0b23e44..cc442982 100644 --- a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp +++ b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp @@ -5,26 +5,7 @@ void LoadFounderEdition() { // TODO: Implement Founder Edition variant initialization // This includes: // - GPIO configuration for keypad matrix - // - WS2812 LED driver initialization using TIM1 (not TIM8 - STM32F103xB doesn't have TIM8) + // - WS2812 LED driver initialization using TIM1 (not TIM8 - STM32F103xE doesn't have TIM8) // - Hardware DMA setup for LED PWM (DMA1, not DMA2) // For now, this is stubbed out to allow compilation -} - -namespace WS2812 { - void Show(Color* frameBuffer, std::vector& brightnessMap) { - // TODO: Implement WS2812 LED update using TIM1 PWM + DMA1 for STM32F103 - // For now, this is stubbed out to allow linking - } -} - -namespace Device::USBController { - void Init() { - // TODO: Implement USB controller initialization for STM32F103 - } -} - -namespace Device::BLEMIDI { - void Start() { - // TODO: Implement BLE MIDI start (STM32F103 doesn't have BLE, stub only) - } -} +} \ No newline at end of file diff --git a/Devices/MatrixBlock5/family.mk b/Devices/MatrixBlock5/family.mk index 4d38e42d..180f9206 100644 --- a/Devices/MatrixBlock5/family.mk +++ b/Devices/MatrixBlock5/family.mk @@ -16,57 +16,16 @@ else RM = rm endif -ST_CMSIS = core/stm32$(ST_FAMILY)/cmsis_device_$(ST_FAMILY) -ST_HAL_DRIVER = core/stm32$(ST_FAMILY)/stm32$(ST_FAMILY)xx_hal_driver - -# include $(DEVICE_PATH)/device.mk - -CFLAGS += \ - -mthumb \ - -mabi=aapcs \ - -mcpu=cortex-m3 \ - -mfloat-abi=soft \ - -DCFG_TUSB_MCU=OPT_MCU_STM32F1\ - -nostartfiles - -SRC_C += \ - lib\tinyusb\src\portable\st\stm32_fsdev\dcd_stm32_fsdev.c \ - $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_dma.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_tim.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_tim_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr.c\ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rtc.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rtc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_flash.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_flash_ex.c - -SRC_CPP += \ - Platform\STM32F1\WS2812\WS2812.cpp \ - -INC += \ - $(DEVICE_PATH) \ - $(FAMILY_PATH)/Drivers \ - lib/CMSIS_5/CMSIS/Core/Include \ - Platform/stm32$(ST_FAMILY) \ - $(ST_CMSIS)/Include \ - $(ST_HAL_DRIVER)/Inc - -# For freeRTOS port source -FREERTOS_PORT = ARM_CM3 - .PHONY: build flash upload -$(BUILD)/$(PROJECT)-$(DEVICE).bin build: +build: $(BUILD)/$(PROJECT)-$(DEVICE).bin + +$(BUILD)/$(PROJECT)-$(DEVICE).elf: cmake -B $(BUILD) -Wno-dev . -DCMAKE_TOOLCHAIN_FILE=$(FAMILY_PATH)/toolchain-stm32f103.cmake -DFAMILY=$(FAMILY) -DDEVICE=$(DEVICE) -DMODE=$(MODE) -G"Unix Makefiles" cmake --build $(BUILD) -- -j8 - @$(CP) "$(subst /,\,$(BUILD)/Devices/MatrixBlock5/$(PROJECT)-$(DEVICE).bin)" "$(subst /,\,$(BUILD)/)" - $(if $(wildcard $(BUILD)/Devices/MatrixBlock5/$(PROJECT)-$(DEVICE).map),@$(CP) "$(subst /,\,$(BUILD)/Devices/MatrixBlock5/$(PROJECT)-$(DEVICE).map)" "$(subst /,\,$(BUILD)/)",) + +$(BUILD)/$(PROJECT)-$(DEVICE).bin: $(BUILD)/$(PROJECT)-$(DEVICE).elf + arm-none-eabi-objcopy -O binary "$<" "$@" flash upload: $(BUILD)/$(PROJECT)-$(DEVICE).bin dfu-util "-a 0" "-d 0203:0003" -D"$<" -R diff --git a/Devices/MatrixBlock5/startup_stm32f103xe.s b/Devices/MatrixBlock5/startup_stm32f103xe.s deleted file mode 100644 index 771aa8a5..00000000 --- a/Devices/MatrixBlock5/startup_stm32f103xe.s +++ /dev/null @@ -1,470 +0,0 @@ -/** - *************** (C) COPYRIGHT 2017 STMicroelectronics ************************ - * @file startup_stm32f103xe.s - * @author MCD Application Team - * @brief STM32F103xE Devices vector table for Atollic toolchain. - * This module performs: - * - Set the initial SP - * - Set the initial PC == Reset_Handler, - * - Set the vector table entries with the exceptions ISR address - * - Configure the clock system - * - Configure external SRAM mounted on STM3210E-EVAL board - * to be used as data memory (optional, to be enabled by user) - * - Branches to main in the C library (which eventually - * calls main()). - * After Reset the Cortex-M3 processor is in Thread mode, - * priority is Privileged, and the Stack is set to Main. - ****************************************************************************** - * @attention - * - * Copyright (c) 2017-2021 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m3 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss - -.equ BootRAM, 0xF1E0F85F -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval : None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - -/* Call the clock system initialization function.*/ - bl SystemInit - -/* Copy the data segment initializers from flash to SRAM */ - ldr r0, =_sdata - ldr r1, =_edata - ldr r2, =_sidata - movs r3, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r4, [r2, r3] - str r4, [r0, r3] - adds r3, r3, #4 - -LoopCopyDataInit: - adds r4, r0, r3 - cmp r4, r1 - bcc CopyDataInit - -/* Zero fill the bss segment. */ - ldr r2, =_sbss - ldr r4, =_ebss - movs r3, #0 - b LoopFillZerobss - -FillZerobss: - str r3, [r2] - adds r2, r2, #4 - -LoopFillZerobss: - cmp r2, r4 - bcc FillZerobss - -/* Call static constructors */ - bl __libc_init_array -/* Call the application's entry point.*/ - bl main - bx lr -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * - * @param None - * @retval : None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex M3. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - .word WWDG_IRQHandler - .word PVD_IRQHandler - .word TAMPER_IRQHandler - .word RTC_IRQHandler - .word FLASH_IRQHandler - .word RCC_IRQHandler - .word EXTI0_IRQHandler - .word EXTI1_IRQHandler - .word EXTI2_IRQHandler - .word EXTI3_IRQHandler - .word EXTI4_IRQHandler - .word DMA1_Channel1_IRQHandler - .word DMA1_Channel2_IRQHandler - .word DMA1_Channel3_IRQHandler - .word DMA1_Channel4_IRQHandler - .word DMA1_Channel5_IRQHandler - .word DMA1_Channel6_IRQHandler - .word DMA1_Channel7_IRQHandler - .word ADC1_2_IRQHandler - .word USB_HP_CAN1_TX_IRQHandler - .word USB_LP_CAN1_RX0_IRQHandler - .word CAN1_RX1_IRQHandler - .word CAN1_SCE_IRQHandler - .word EXTI9_5_IRQHandler - .word TIM1_BRK_IRQHandler - .word TIM1_UP_IRQHandler - .word TIM1_TRG_COM_IRQHandler - .word TIM1_CC_IRQHandler - .word TIM2_IRQHandler - .word TIM3_IRQHandler - .word TIM4_IRQHandler - .word I2C1_EV_IRQHandler - .word I2C1_ER_IRQHandler - .word I2C2_EV_IRQHandler - .word I2C2_ER_IRQHandler - .word SPI1_IRQHandler - .word SPI2_IRQHandler - .word USART1_IRQHandler - .word USART2_IRQHandler - .word USART3_IRQHandler - .word EXTI15_10_IRQHandler - .word RTC_Alarm_IRQHandler - .word USBWakeUp_IRQHandler - .word TIM8_BRK_IRQHandler - .word TIM8_UP_IRQHandler - .word TIM8_TRG_COM_IRQHandler - .word TIM8_CC_IRQHandler - .word ADC3_IRQHandler - .word FSMC_IRQHandler - .word SDIO_IRQHandler - .word TIM5_IRQHandler - .word SPI3_IRQHandler - .word UART4_IRQHandler - .word UART5_IRQHandler - .word TIM6_IRQHandler - .word TIM7_IRQHandler - .word DMA2_Channel1_IRQHandler - .word DMA2_Channel2_IRQHandler - .word DMA2_Channel3_IRQHandler - .word DMA2_Channel4_5_IRQHandler - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word BootRAM /* @0x1E0. This is for boot in RAM mode for - STM32F10x High Density devices. */ - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDG_IRQHandler - .thumb_set WWDG_IRQHandler,Default_Handler - - .weak PVD_IRQHandler - .thumb_set PVD_IRQHandler,Default_Handler - - .weak TAMPER_IRQHandler - .thumb_set TAMPER_IRQHandler,Default_Handler - - .weak RTC_IRQHandler - .thumb_set RTC_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak RCC_IRQHandler - .thumb_set RCC_IRQHandler,Default_Handler - - .weak EXTI0_IRQHandler - .thumb_set EXTI0_IRQHandler,Default_Handler - - .weak EXTI1_IRQHandler - .thumb_set EXTI1_IRQHandler,Default_Handler - - .weak EXTI2_IRQHandler - .thumb_set EXTI2_IRQHandler,Default_Handler - - .weak EXTI3_IRQHandler - .thumb_set EXTI3_IRQHandler,Default_Handler - - .weak EXTI4_IRQHandler - .thumb_set EXTI4_IRQHandler,Default_Handler - - .weak DMA1_Channel1_IRQHandler - .thumb_set DMA1_Channel1_IRQHandler,Default_Handler - - .weak DMA1_Channel2_IRQHandler - .thumb_set DMA1_Channel2_IRQHandler,Default_Handler - - .weak DMA1_Channel3_IRQHandler - .thumb_set DMA1_Channel3_IRQHandler,Default_Handler - - .weak DMA1_Channel4_IRQHandler - .thumb_set DMA1_Channel4_IRQHandler,Default_Handler - - .weak DMA1_Channel5_IRQHandler - .thumb_set DMA1_Channel5_IRQHandler,Default_Handler - - .weak DMA1_Channel6_IRQHandler - .thumb_set DMA1_Channel6_IRQHandler,Default_Handler - - .weak DMA1_Channel7_IRQHandler - .thumb_set DMA1_Channel7_IRQHandler,Default_Handler - - .weak ADC1_2_IRQHandler - .thumb_set ADC1_2_IRQHandler,Default_Handler - - .weak USB_HP_CAN1_TX_IRQHandler - .thumb_set USB_HP_CAN1_TX_IRQHandler,Default_Handler - - .weak USB_LP_CAN1_RX0_IRQHandler - .thumb_set USB_LP_CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SCE_IRQHandler - .thumb_set CAN1_SCE_IRQHandler,Default_Handler - - .weak EXTI9_5_IRQHandler - .thumb_set EXTI9_5_IRQHandler,Default_Handler - - .weak TIM1_BRK_IRQHandler - .thumb_set TIM1_BRK_IRQHandler,Default_Handler - - .weak TIM1_UP_IRQHandler - .thumb_set TIM1_UP_IRQHandler,Default_Handler - - .weak TIM1_TRG_COM_IRQHandler - .thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler - - .weak TIM1_CC_IRQHandler - .thumb_set TIM1_CC_IRQHandler,Default_Handler - - .weak TIM2_IRQHandler - .thumb_set TIM2_IRQHandler,Default_Handler - - .weak TIM3_IRQHandler - .thumb_set TIM3_IRQHandler,Default_Handler - - .weak TIM4_IRQHandler - .thumb_set TIM4_IRQHandler,Default_Handler - - .weak I2C1_EV_IRQHandler - .thumb_set I2C1_EV_IRQHandler,Default_Handler - - .weak I2C1_ER_IRQHandler - .thumb_set I2C1_ER_IRQHandler,Default_Handler - - .weak I2C2_EV_IRQHandler - .thumb_set I2C2_EV_IRQHandler,Default_Handler - - .weak I2C2_ER_IRQHandler - .thumb_set I2C2_ER_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXTI15_10_IRQHandler - .thumb_set EXTI15_10_IRQHandler,Default_Handler - - .weak RTC_Alarm_IRQHandler - .thumb_set RTC_Alarm_IRQHandler,Default_Handler - - .weak USBWakeUp_IRQHandler - .thumb_set USBWakeUp_IRQHandler,Default_Handler - - .weak TIM8_BRK_IRQHandler - .thumb_set TIM8_BRK_IRQHandler,Default_Handler - - .weak TIM8_UP_IRQHandler - .thumb_set TIM8_UP_IRQHandler,Default_Handler - - .weak TIM8_TRG_COM_IRQHandler - .thumb_set TIM8_TRG_COM_IRQHandler,Default_Handler - - .weak TIM8_CC_IRQHandler - .thumb_set TIM8_CC_IRQHandler,Default_Handler - - .weak ADC3_IRQHandler - .thumb_set ADC3_IRQHandler,Default_Handler - - .weak FSMC_IRQHandler - .thumb_set FSMC_IRQHandler,Default_Handler - - .weak SDIO_IRQHandler - .thumb_set SDIO_IRQHandler,Default_Handler - - .weak TIM5_IRQHandler - .thumb_set TIM5_IRQHandler,Default_Handler - - .weak SPI3_IRQHandler - .thumb_set SPI3_IRQHandler,Default_Handler - - .weak UART4_IRQHandler - .thumb_set UART4_IRQHandler,Default_Handler - - .weak UART5_IRQHandler - .thumb_set UART5_IRQHandler,Default_Handler - - .weak TIM6_IRQHandler - .thumb_set TIM6_IRQHandler,Default_Handler - - .weak TIM7_IRQHandler - .thumb_set TIM7_IRQHandler,Default_Handler - - .weak DMA2_Channel1_IRQHandler - .thumb_set DMA2_Channel1_IRQHandler,Default_Handler - - .weak DMA2_Channel2_IRQHandler - .thumb_set DMA2_Channel2_IRQHandler,Default_Handler - - .weak DMA2_Channel3_IRQHandler - .thumb_set DMA2_Channel3_IRQHandler,Default_Handler - - .weak DMA2_Channel4_5_IRQHandler - .thumb_set DMA2_Channel4_5_IRQHandler,Default_Handler - diff --git a/OS/UI/UI.h b/OS/UI/UI.h index 4bd63a24..0ebc310b 100644 --- a/OS/UI/UI.h +++ b/OS/UI/UI.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "UIComponents.h" #include "UIUtilities.h" diff --git a/OS/USB/USB.h b/OS/USB/USB.h index 9e677878..2029ac83 100644 --- a/OS/USB/USB.h +++ b/OS/USB/USB.h @@ -11,7 +11,7 @@ enum USB_MODE { }; // Undefine STM32 peripheral macros that conflict with C++ namespace names -#ifdef STM32F103xB +#ifdef USB #undef USB #endif diff --git a/Platform/STM32F1/WS2812/WS2812.cpp b/Platform/STM32F1/WS2812/WS2812.cpp index 1cc3af61..8e8c8f5e 100644 --- a/Platform/STM32F1/WS2812/WS2812.cpp +++ b/Platform/STM32F1/WS2812/WS2812.cpp @@ -76,7 +76,11 @@ namespace WS2812 for (int ch = 0; ch < 3; ch++) { uint16_t channel_index = data_index + ch; if (led_data[channel_index] >= dithering_threshold) { - uint16_t expected = (uint16_t)buffer[i].components[ch] * local_brightness; + uint16_t expected; + // Get the appropriate color component based on channel + if (ch == 0) expected = (uint16_t)buffer[i].G * local_brightness; // Green + else if (ch == 1) expected = (uint16_t)buffer[i].R * local_brightness; // Red + else expected = (uint16_t)buffer[i].B * local_brightness; // Blue uint16_t actual = (uint16_t)led_data[channel_index] << 8; if (expected > actual) { From 6acdc9a05c02e1681ea41b835eccc3a639837f59 Mon Sep 17 00:00:00 2001 From: Nengzhuo Cai Date: Sun, 5 Oct 2025 16:54:49 -0400 Subject: [PATCH 11/17] progress --- Applications/Application.h | 18 ++- Applications/Shell/Shell.cpp | 2 + Devices/MatrixBlock5/CMakeLists.txt | 2 +- Devices/MatrixBlock5/FreeRTOSConfig.h | 191 +++++++++++--------------- Devices/MatrixBlock5/main.cpp | 98 ------------- OS/System/System.cpp | 6 +- OS/main.cpp | 11 +- 7 files changed, 106 insertions(+), 222 deletions(-) delete mode 100644 Devices/MatrixBlock5/main.cpp diff --git a/Applications/Application.h b/Applications/Application.h index ed80d384..004ec5d2 100644 --- a/Applications/Application.h +++ b/Applications/Application.h @@ -47,13 +47,20 @@ class Application { #define APPLICATION_HELPER_CLASS(CLASS) APPLICATION_HELPER_CLASS_IMPL(CLASS) // Stores all the applications - Optimal for ID lookup -inline std::unordered_map applications; +// Using function-local static to ensure proper initialization order +inline std::unordered_map& GetApplications() { + static std::unordered_map applications; + return applications; +} // Store all the application id in order of registration - Preserves order and is optimal for iteration -inline std::map application_ids; +inline std::map& GetApplicationIDs() { + static std::map application_ids; + return application_ids; +} template -static inline void register_application(Application_Info info, uint32_t order, bool is_system) { +static inline void register_application(uint32_t order, bool is_system) { APPLICATION_CLASS::info.is_system = is_system; // Set system flag APPLICATION_CLASS::info.factory = []() -> Application* { \ return new APPLICATION_CLASS(); \ @@ -63,15 +70,16 @@ static inline void register_application(Application_Info info, uint32_t order, b }; \ MLOGI("Application", "Registering application: %s%s", APPLICATION_CLASS::info.name.c_str(), is_system ? " (system)" : ""); \ uint32_t app_id = StringHash(APPLICATION_CLASS::info.author + '-' + APPLICATION_CLASS::info.name); \ + auto& applications = GetApplications(); \ if (applications.find(app_id) != applications.end()) { \ return; \ } \ applications.insert({app_id, &APPLICATION_CLASS::info}); \ - application_ids[order] = app_id; \ + GetApplicationIDs()[order] = app_id; \ } #define REGISTER_APPLICATION(APPLICATION_CLASS, IS_SYSTEM) \ __attribute__((__constructor__)) inline void APPLICATION_HELPER_CLASS(APPLICATION_CLASS)(void) { \ - register_application(APPLICATION_CLASS::info, __COUNTER__, IS_SYSTEM); \ + register_application(__COUNTER__, IS_SYSTEM); \ } diff --git a/Applications/Shell/Shell.cpp b/Applications/Shell/Shell.cpp index 35409384..27a4dfad 100644 --- a/Applications/Shell/Shell.cpp +++ b/Applications/Shell/Shell.cpp @@ -61,6 +61,7 @@ void Shell::InitializeFolderSystem() { } // First, add all native apps to all_applications + auto& applications = GetApplications(); for (const auto& [app_id, app_info] : applications) { all_applications.emplace(app_id, ApplicationEntry(app_info)); } @@ -96,6 +97,7 @@ void Shell::InitializeFolderSystem() { bool missing_apps_found = false; // First, check native apps in registration order + auto& application_ids = GetApplicationIDs(); for (const auto& [order_id, app_id] : application_ids) { // If app is not in any folder, add it if (apps_in_folders.find(app_id) == apps_in_folders.end()) { diff --git a/Devices/MatrixBlock5/CMakeLists.txt b/Devices/MatrixBlock5/CMakeLists.txt index 6689d649..dcf015a0 100644 --- a/Devices/MatrixBlock5/CMakeLists.txt +++ b/Devices/MatrixBlock5/CMakeLists.txt @@ -168,7 +168,7 @@ target_link_libraries(MatrixOSDevice PUBLIC # Create executable set(elf_file ${CMAKE_PROJECT_NAME}.elf) -add_executable(${elf_file} main.cpp) +add_executable(${elf_file} ${CMAKE_SOURCE_DIR}/OS/main.cpp) target_compile_features(${elf_file} PUBLIC cxx_std_17) target_link_libraries(${elf_file} diff --git a/Devices/MatrixBlock5/FreeRTOSConfig.h b/Devices/MatrixBlock5/FreeRTOSConfig.h index 9ded84f7..1ae3693d 100644 --- a/Devices/MatrixBlock5/FreeRTOSConfig.h +++ b/Devices/MatrixBlock5/FreeRTOSConfig.h @@ -26,9 +26,15 @@ * 1 tab == 4 spaces! */ + #ifndef FREERTOS_CONFIG_H #define FREERTOS_CONFIG_H +// STM32 device definition - must be defined before including HAL headers +#ifndef STM32F103xE +#define STM32F103xE +#endif + /*----------------------------------------------------------- * Application specific definitions. * @@ -41,153 +47,110 @@ * See http://www.freertos.org/a00110.html. *----------------------------------------------------------*/ -// STM32 device definition - must be defined before including HAL headers -#ifndef STM32F103xE -#define STM32F103xE +// skip if included from IAR assembler +#ifndef __IASMARM__ + #include "stm32f1xx.h" #endif -// Include MCU header -#include "stm32f1xx_hal.h" - -extern uint32_t SystemCoreClock; - -/* Cortex M23/M33 port configuration. */ -#define configENABLE_MPU 0 -#define configENABLE_FPU 1 -#define configENABLE_TRUSTZONE 0 -#define configMINIMAL_SECURE_STACK_SIZE (1024) +/* Cortex M3 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 0 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) -#define configUSE_PREEMPTION 1 +#define configUSE_PREEMPTION 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 -#define configCPU_CLOCK_HZ SystemCoreClock -#define configTICK_RATE_HZ (100) -#define configMAX_PRIORITIES (5) -#define configMINIMAL_STACK_SIZE (128) -#define configTOTAL_HEAP_SIZE (1024) -#define configMAX_TASK_NAME_LEN 16 -#define configUSE_16_BIT_TICKS 0 -#define configIDLE_SHOULD_YIELD 1 -#define configUSE_MUTEXES 1 -#define configUSE_RECURSIVE_MUTEXES 1 -#define configUSE_COUNTING_SEMAPHORES 1 -#define configQUEUE_REGISTRY_SIZE 2 -#define configUSE_QUEUE_SETS 0 -#define configUSE_TIME_SLICING 0 -#define configUSE_NEWLIB_REENTRANT 0 -#define configENABLE_BACKWARD_COMPATIBILITY 1 -#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 - -#define configSUPPORT_STATIC_ALLOCATION 1 -#define configSUPPORT_DYNAMIC_ALLOCATION 1 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 /* Hook function related definitions. */ -#define configUSE_IDLE_HOOK 0 -#define configUSE_TICK_HOOK 0 -#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning -#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 /* Run time and task stats gathering related definitions. */ -#define configGENERATE_RUN_TIME_STATS 0 -#define configUSE_TRACE_FACILITY 1 // legacy trace -#define configUSE_STATS_FORMATTING_FUNCTIONS 0 +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 /* Co-routine definitions. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES 2 +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 /* Software timer related definitions. */ -#define configUSE_TIMERS 1 -#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 2) -#define configTIMER_QUEUE_LENGTH 32 -#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE /* Optional functions - most linkers will remove unused functions anyway. */ -#define INCLUDE_vTaskPrioritySet 0 -#define INCLUDE_uxTaskPriorityGet 0 -#define INCLUDE_vTaskDelete 1 -#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY -#define INCLUDE_xResumeFromISR 0 -#define INCLUDE_vTaskDelayUntil 1 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTaskGetSchedulerState 0 -#define INCLUDE_uxTaskGetStackHighWaterMark 0 -#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 #define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 -#define INCLUDE_pcTaskGetTaskName 0 -#define INCLUDE_eTaskGetState 0 -#define INCLUDE_xEventGroupSetBitFromISR 0 -#define INCLUDE_xTimerPendFunctionCall 0 - -/* Thread Local Storage */ -#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 4 -#define INCLUDE_xTaskGetCurrentTaskHandle 1 - -/* Define to trap errors during development. */ -// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 -#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) -#define configASSERT(_exp) \ - do \ - { \ - if (!(_exp)) \ - { \ - volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*)0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ - if ((*ARM_CM_DHCSR) & 1UL) \ - { /* Only halt mcu if debugger is attached */ \ - taskDISABLE_INTERRUPTS(); \ - __asm("BKPT #0\n"); \ - } \ - } \ - } while (0) -#else -#define configASSERT(x) -#endif - -#ifdef __RX__ -/* Renesas RX series */ -#define vSoftwareInterruptISR INT_Excep_ICU_SWINT -#define vTickISR INT_Excep_CMT0_CMI0 -#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ / 2) -#define configKERNEL_INTERRUPT_PRIORITY 1 -#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4 - -#else +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 /* FreeRTOS hooks to NVIC vectors */ -#define xPortPendSVHandler PendSV_Handler -#define xPortSysTickHandler SysTick_Handler -#define vPortSVCHandler SVC_Handler +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler //--------------------------------------------------------------------+ // Interrupt nesting behavior configuration. //--------------------------------------------------------------------+ -#if defined(__NVIC_PRIO_BITS) -// For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h -#define configPRIO_BITS __NVIC_PRIO_BITS -#elif defined(__ECLIC_INTCTLBITS) -// RISC-V Bumblebee core from nuclei -#define configPRIO_BITS __ECLIC_INTCTLBITS -#else -// Fallback for Cortex-M3 (STM32F103) - 4 priority bits -#define configPRIO_BITS 4 -#endif + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +#define configPRIO_BITS 4 /* The lowest interrupt priority that can be used in a call to a "set priority" function. */ -#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1 << configPRIO_BITS) - 1) +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< Date: Sun, 5 Oct 2025 17:24:32 -0400 Subject: [PATCH 12/17] Might be working --- CMakeLists.txt | 7 +++ Devices/MatrixBlock5/CMakeLists.txt | 9 ++-- Devices/MatrixBlock5/Family.cpp | 3 ++ Devices/MatrixBlock5/FreeRTOSConfig.h | 2 +- .../MatrixFounderEdition/FounderEdition.cpp | 44 ++++++++++++++++--- OS/LED/LED.cpp | 5 ++- OS/MIDI/MIDI.cpp | 7 +-- OS/System/System.cpp | 3 ++ 8 files changed, 64 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e2167acb..79c8b84f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,6 +105,13 @@ add_compile_definitions( DEVICE_BATTERY=${DEVICE_BATTERY} ) +# Set debug flags globally for all targets before adding subdirectories +if(MODE STREQUAL "DEVELOPMENT" OR MODE STREQUAL "UNDEFINED") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3 -Og") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3 -Og") + message(STATUS "Building with debug symbols: -g3 -Og") +endif() + add_subdirectory(${FAMILY_PATH}) add_subdirectory(Devices) add_subdirectory(OS) diff --git a/Devices/MatrixBlock5/CMakeLists.txt b/Devices/MatrixBlock5/CMakeLists.txt index dcf015a0..6bf57165 100644 --- a/Devices/MatrixBlock5/CMakeLists.txt +++ b/Devices/MatrixBlock5/CMakeLists.txt @@ -42,16 +42,15 @@ set(DEVICE_TINYUSB_COMPILE_OPTIONS # Debug flags if(MODE STREQUAL "DEVELOPMENT" OR MODE STREQUAL "UNDEFINED") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Og") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Og") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3 -Og") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3 -Og") + set(CMAKE_EXE_LINKER_FLAGS "${COMMON_FLAGS} -g3 -specs=nosys.specs -specs=nano.specs -Wl,--gc-sections -Wl,-Map=${PROJECT_NAME}.map -T${CMAKE_CURRENT_SOURCE_DIR}/Variants/MatrixFounderEdition/STM32F103RETx_FLASH.ld") else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Os") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Os") + set(CMAKE_EXE_LINKER_FLAGS "${COMMON_FLAGS} -specs=nosys.specs -specs=nano.specs -Wl,--gc-sections -Wl,-Map=${PROJECT_NAME}.map -T${CMAKE_CURRENT_SOURCE_DIR}/Variants/MatrixFounderEdition/STM32F103RETx_FLASH.ld") endif() -# Linker flags -set(CMAKE_EXE_LINKER_FLAGS "${COMMON_FLAGS} -specs=nosys.specs -specs=nano.specs -Wl,--gc-sections -Wl,-Map=${PROJECT_NAME}.map -T${CMAKE_CURRENT_SOURCE_DIR}/Variants/MatrixFounderEdition/STM32F103RETx_FLASH.ld") - # Collect all device source files file(GLOB_RECURSE DEVICE_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/Family.cpp" diff --git a/Devices/MatrixBlock5/Family.cpp b/Devices/MatrixBlock5/Family.cpp index e5945973..ac7ba60c 100644 --- a/Devices/MatrixBlock5/Family.cpp +++ b/Devices/MatrixBlock5/Family.cpp @@ -18,6 +18,9 @@ namespace Device HAL_Init(); SystemClock_Config(); + // Load device variant info - MUST be called before subsystem Init() + LoadDeviceInfo(); + USB::Init(); LED::Init(); KeyPad::Init(); diff --git a/Devices/MatrixBlock5/FreeRTOSConfig.h b/Devices/MatrixBlock5/FreeRTOSConfig.h index 1ae3693d..5c7f2de8 100644 --- a/Devices/MatrixBlock5/FreeRTOSConfig.h +++ b/Devices/MatrixBlock5/FreeRTOSConfig.h @@ -64,7 +64,7 @@ #define configTICK_RATE_HZ ( 1000 ) #define configMAX_PRIORITIES ( 5 ) #define configMINIMAL_STACK_SIZE ( 128 ) -#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*16*1024 ) #define configMAX_TASK_NAME_LEN 16 #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 diff --git a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp index cc442982..13eeeb00 100644 --- a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp +++ b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp @@ -2,10 +2,42 @@ #include "Device.h" void LoadFounderEdition() { - // TODO: Implement Founder Edition variant initialization - // This includes: - // - GPIO configuration for keypad matrix - // - WS2812 LED driver initialization using TIM1 (not TIM8 - STM32F103xE doesn't have TIM8) - // - Hardware DMA setup for LED PWM (DMA1, not DMA2) - // For now, this is stubbed out to allow compilation + // Configure LED + Device::LED::led_port = GPIOC; + Device::LED::led_pin = GPIO_PIN_7; + + // Configure FN key + Device::KeyPad::fn_port = GPIOA; + Device::KeyPad::fn_pin = GPIO_PIN_8; + + // Configure keypad write pins (columns) + Device::KeyPad::keypad_write_ports[0] = GPIOB; Device::KeyPad::keypad_write_pins[0] = GPIO_PIN_12; // Key1 + Device::KeyPad::keypad_write_ports[1] = GPIOB; Device::KeyPad::keypad_write_pins[1] = GPIO_PIN_13; // Key2 + Device::KeyPad::keypad_write_ports[2] = GPIOB; Device::KeyPad::keypad_write_pins[2] = GPIO_PIN_14; // Key3 + Device::KeyPad::keypad_write_ports[3] = GPIOB; Device::KeyPad::keypad_write_pins[3] = GPIO_PIN_15; // Key4 + Device::KeyPad::keypad_write_ports[4] = GPIOC; Device::KeyPad::keypad_write_pins[4] = GPIO_PIN_6; // Key5 + Device::KeyPad::keypad_write_ports[5] = GPIOC; Device::KeyPad::keypad_write_pins[5] = GPIO_PIN_7; // Key6 + Device::KeyPad::keypad_write_ports[6] = GPIOC; Device::KeyPad::keypad_write_pins[6] = GPIO_PIN_8; // Key7 + Device::KeyPad::keypad_write_ports[7] = GPIOC; Device::KeyPad::keypad_write_pins[7] = GPIO_PIN_9; // Key8 + + // Configure keypad read pins (rows) + Device::KeyPad::keypad_read_ports[0] = GPIOB; Device::KeyPad::keypad_read_pins[0] = GPIO_PIN_0; // KeyRead1 + Device::KeyPad::keypad_read_ports[1] = GPIOB; Device::KeyPad::keypad_read_pins[1] = GPIO_PIN_1; // KeyRead2 + Device::KeyPad::keypad_read_ports[2] = GPIOA; Device::KeyPad::keypad_read_pins[2] = GPIO_PIN_11; // KeyRead3 + Device::KeyPad::keypad_read_ports[3] = GPIOA; Device::KeyPad::keypad_read_pins[3] = GPIO_PIN_12; // KeyRead4 + Device::KeyPad::keypad_read_ports[4] = GPIOC; Device::KeyPad::keypad_read_pins[4] = GPIO_PIN_4; // KeyRead5 + Device::KeyPad::keypad_read_ports[5] = GPIOA; Device::KeyPad::keypad_read_pins[5] = GPIO_PIN_15; // KeyRead6 + Device::KeyPad::keypad_read_ports[6] = GPIOC; Device::KeyPad::keypad_read_pins[6] = GPIO_PIN_5; // KeyRead7 + Device::KeyPad::keypad_read_ports[7] = GPIOC; Device::KeyPad::keypad_read_pins[7] = GPIO_PIN_3; // KeyRead8 + + // Configure touchbar + Device::KeyPad::touchData_Port = GPIOA; + Device::KeyPad::touchData_Pin = GPIO_PIN_0; + Device::KeyPad::touchClock_Port = GPIOA; + Device::KeyPad::touchClock_Pin = GPIO_PIN_1; + + // Set device name and model + Device::name = "MatrixBlock5"; + Device::model = "MB5F"; + Device::product_name = "MatrixBlock5"; } \ No newline at end of file diff --git a/OS/LED/LED.cpp b/OS/LED/LED.cpp index 22f37ec1..fd0aeb1c 100644 --- a/OS/LED/LED.cpp +++ b/OS/LED/LED.cpp @@ -89,7 +89,10 @@ namespace MatrixOS::LED } UpdateBrightness(); + } + if (activeBufferSemaphore == nullptr) + { activeBufferSemaphore = xSemaphoreCreateMutex(); } @@ -102,7 +105,7 @@ namespace MatrixOS::LED } frameBuffers.clear(); - + CreateLayer(0); //Create Layer 0 - The active layer CreateLayer(0); //Create Layer 1 - The base layer diff --git a/OS/MIDI/MIDI.cpp b/OS/MIDI/MIDI.cpp index f0b8f380..62cb97be 100644 --- a/OS/MIDI/MIDI.cpp +++ b/OS/MIDI/MIDI.cpp @@ -11,14 +11,15 @@ namespace MatrixOS::MIDI if (!osPort) { osPort = new MidiPort("MatrixOS", MIDI_PORT_OS, MIDI_QUEUE_SIZE); } - + // Create the application queue if it doesn't exist if (!appQueue) { appQueue = xQueueCreate(MIDI_QUEUE_SIZE, sizeof(MidiPacket)); } - + // Create the receive task if it doesn't exist - if (!receiveTask) { + // Only create task if scheduler is already running (ESP32) or will be started later + if (!receiveTask && xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { xTaskCreate(ReceiveTask, "MIDI_Receive", 2048, NULL, tskIDLE_PRIORITY + 2, &receiveTask); } } diff --git a/OS/System/System.cpp b/OS/System/System.cpp index 31e2e91d..2eae4daa 100644 --- a/OS/System/System.cpp +++ b/OS/System/System.cpp @@ -115,6 +115,9 @@ namespace MatrixOS::SYS void Begin(void) { Device::DeviceInit(); + // Initialize MIDI system before USB to ensure osPort exists + MatrixOS::MIDI::Init(); + MatrixOS::USB::Init(); InitSysModules(); From cb79ee06011071ea01d9a63df9bbff20d159aa2c Mon Sep 17 00:00:00 2001 From: Nengzhuo Cai Date: Mon, 6 Oct 2025 07:58:06 -0400 Subject: [PATCH 13/17] more progress --- Devices/MatrixBlock5/ApplicationList.txt | 2 +- .../Applications/MystrixBoot/CMakeLists.txt | 18 ++ .../Applications/MystrixBoot/MystrixBoot.cpp | 241 ++++++++++++++++++ .../Applications/MystrixBoot/MystrixBoot.h | 42 +++ Devices/MatrixBlock5/Drivers/LED.cpp | 12 +- Devices/MatrixBlock5/Family.cpp | 2 +- Devices/MatrixBlock5/FreeRTOSConfig.h | 2 +- .../MatrixFounderEdition/FounderEdition.cpp | 103 ++++++++ OS/System/Parameters.h | 2 +- OS/System/System.cpp | 9 + OS/USB/MIDI.cpp | 28 +- OS/USB/TinyUSB/tusb_config.h | 4 +- Platform/STM32F1/WS2812/WS2812.cpp | 198 ++++++-------- Platform/STM32F1/WS2812/WS2812.h | 21 +- 14 files changed, 541 insertions(+), 143 deletions(-) create mode 100644 Devices/MatrixBlock5/Applications/MystrixBoot/CMakeLists.txt create mode 100644 Devices/MatrixBlock5/Applications/MystrixBoot/MystrixBoot.cpp create mode 100644 Devices/MatrixBlock5/Applications/MystrixBoot/MystrixBoot.h diff --git a/Devices/MatrixBlock5/ApplicationList.txt b/Devices/MatrixBlock5/ApplicationList.txt index 868e98f9..f77f125d 100644 --- a/Devices/MatrixBlock5/ApplicationList.txt +++ b/Devices/MatrixBlock5/ApplicationList.txt @@ -35,7 +35,7 @@ Performance #[System]Python # Boot animation -{FAMILY_PATH}/Applications/BootAnimation +{FAMILY_PATH}/Applications/MystrixBoot # Device-specific applications (if any) # {FAMILY_PATH}/Applications/FactoryMenu diff --git a/Devices/MatrixBlock5/Applications/MystrixBoot/CMakeLists.txt b/Devices/MatrixBlock5/Applications/MystrixBoot/CMakeLists.txt new file mode 100644 index 00000000..67ed049a --- /dev/null +++ b/Devices/MatrixBlock5/Applications/MystrixBoot/CMakeLists.txt @@ -0,0 +1,18 @@ +# MystrixBoot Application +file(GLOB_RECURSE MYSTRIXBOOT_SOURCES "*.cpp" "*.c") +file(GLOB_RECURSE MYSTRIXBOOT_HEADERS "*.h") + +add_library(MystrixBootAPP ${MYSTRIXBOOT_SOURCES} ${MYSTRIXBOOT_HEADERS}) + +target_include_directories(MystrixBootAPP PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_link_libraries(MystrixBootAPP PUBLIC + MatrixOSInterface + MatrixOSAPPInterface + BootAnimationTemplate +) + +# Register the application class +RegisterApplicationClass(MystrixBoot) \ No newline at end of file diff --git a/Devices/MatrixBlock5/Applications/MystrixBoot/MystrixBoot.cpp b/Devices/MatrixBlock5/Applications/MystrixBoot/MystrixBoot.cpp new file mode 100644 index 00000000..04f32805 --- /dev/null +++ b/Devices/MatrixBlock5/Applications/MystrixBoot/MystrixBoot.cpp @@ -0,0 +1,241 @@ +#include "MystrixBoot.h" + +#define min(a, b) ((a) < (b) ? (a) : (b)) +#define max(a, b) ((a) > (b) ? (a) : (b)) + +void MystrixBoot::Setup(const vector& args) { + for (uint8_t i = 0; i < 100; i++) // Add small delay for USB to be connected (So no idle animation would be shown) + { + MatrixOS::SYS::DelayMs(5); + if (MatrixOS::USB::Connected()) + break; + } +} + +bool MystrixBoot::Idle(bool ready) { + uint8_t step = counter % 12; + if (timer.Tick(80)) + { + MatrixOS::LED::Fill(0); + const Color local_color = Color::White.Scale(MATRIX_BOOT_IDLE * 255); + if (step <= 3) + { + Point line_origin = origin + Point(-1, -1) + Point(0, step); + for (uint8_t i = 0; i < step + 1; i++) + { MatrixOS::LED::SetColor(line_origin + Point(1, -1) * i, local_color); } + } + else if (step <= 6) + { + Point line_origin = origin + Point(0, 2) + Point(step - 4, 0); + for (uint8_t i = 0; i < 3 - (step - 4); i++) + { MatrixOS::LED::SetColor(line_origin + Point(1, -1) * i, local_color); } + } + MatrixOS::LED::Update(); + counter++; + } + return step > 6 && ready; +} + +void MystrixBoot::Boot() { + switch (boot_phase) + { + + case 0: + MatrixOS::LED::Fill(0); + counter = 0; + boot_phase++; + [[fallthrough]]; + case 1: + BootPhase1(); + break; + case 2: + BootPhase2(); + break; + } +} + +void MystrixBoot::BootPhase1() { + if (boot_phase_1_tick_time == 0) + boot_phase_1_tick_time = MatrixOS::SYS::Millis(); + + const uint16_t section_time = 80; + if (timer.Tick(1000 / Device::LED::fps)) + { + uint32_t delta_time = MatrixOS::SYS::Millis() - boot_phase_1_tick_time; + uint8_t local_brightness = min(255 * ((float)delta_time / section_time), 255); + Color local_color = Color(local_brightness, local_brightness, local_brightness); + + if (counter <= 3) + { + Point line_origin = origin + Point(-1, -1) + Point(0, counter); + for (uint8_t i = 0; i < counter + 1; i++) + { MatrixOS::LED::SetColor(line_origin + Point(1, -1) * i, local_color); } + } + else if (counter <= 6) + { + Point line_origin = origin + Point(0, 2) + Point(counter - 4, 0); + for (uint8_t i = 0; i < 3 - (counter - 4); i++) + { MatrixOS::LED::SetColor(line_origin + Point(1, -1) * i, local_color); } + } + MatrixOS::LED::Update(); + if (delta_time >= section_time) + { + if (counter == 6) + { + boot_phase++; + counter = 0; + // MatrixOS::SYS::DelayMs(20); + return; + } + boot_phase_1_tick_time = MatrixOS::SYS::Millis(); + counter++; + } + } +} + +Color MystrixBoot::BootPhase2Color(int16_t time, float hue) { + float saturation; + float brightness; + + // Saturation Function + if (time < 0) + { saturation = 0; } + else if (time < 400) + { saturation = (float)(time - 0) / 400.0; } + else + { saturation = 1.0; } + + // Brightness Function + if (time < -100) + { brightness = 0; } + else if (time < 0) + { brightness = ((float)(time + 100) / 100 * MATRIX_BOOT_BRIGHTNESS); } + else if (time < 300) + { brightness = MATRIX_BOOT_BRIGHTNESS; } + else if (time < 500) + { brightness = ((1.0 - (float)(time - 300) / 200.0) * MATRIX_BOOT_BRIGHTNESS); } + else + { brightness = 0; } + + return Color::HsvToRgb(hue, saturation, brightness); + + // // HSV to RGB + // Color color; + // uint8_t region, remainder, p, q, t; + + // if (saturation == 0) + // { + // color.R = brightness; + // color.G = brightness; + // color.B = brightness; + // return color; + // } + + // region = hue / 43; + // remainder = (hue - (region * 43)) * 6; + + // p = (brightness * (255 - saturation)) >> 8; + // q = (brightness * (255 - ((saturation * remainder) >> 8))) >> 8; + // t = (brightness * (255 - ((saturation * (255 - remainder)) >> 8))) >> 8; + + // switch (region) + // { + // case 0: + // color.R = brightness; + // color.G = t; + // color.B = p; + // break; + // case 1: + // color.R = q; + // color.G = brightness; + // color.B = p; + // break; + // case 2: + // color.R = p; + // color.G = brightness; + // color.B = t; + // break; + // case 3: + // color.R = p; + // color.G = q; + // color.B = brightness; + // break; + // case 4: + // color.R = t; + // color.G = p; + // color.B = brightness; + // break; + // default: + // color.R = brightness; + // color.G = p; + // color.B = q; + // break; + // } + + // return color; +} + +void MystrixBoot::BootPhase2QuadSetColor(uint8_t x_offset, uint8_t y_offset, Color color1, Color color2) { + Point point_q1 = origin + Point(1, 1) + Point(x_offset, y_offset); + MatrixOS::LED::SetColor(point_q1, color2); + + Point point_q2 = origin + Point(0, 1) + Point(-x_offset, y_offset); + MatrixOS::LED::SetColor(point_q2, color1); + + Point point_q3 = origin + Point(0, 0) + Point(-x_offset, -y_offset); + MatrixOS::LED::SetColor(point_q3, color2); + + Point point_q4 = origin + Point(1, 0) + Point(x_offset, -y_offset); + MatrixOS::LED::SetColor(point_q4, color1); +} + +void MystrixBoot::BootPhase2() { + float hue[2]; + + memcpy(hue, hueList[0], sizeof(hue)); + + const uint16_t start_offset = 150; + if (timer.Tick(1000 / Device::LED::fps)) + { + + if (boot_phase_2_start_time == 0) + boot_phase_2_start_time = MatrixOS::SYS::Millis(); + + uint32_t delta_time = MatrixOS::SYS::Millis() - boot_phase_2_start_time; + uint8_t quad_size = max(X_SIZE, Y_SIZE) / 2 + 1; + if (delta_time > (quad_size - 2) * start_offset + 700 + 100) + { Exit(); } + + for (uint8_t r = 0; r < quad_size; r++) // radius + { + uint16_t local_deltatime = delta_time - (r - 1) * start_offset; + Color color1 = BootPhase2Color(local_deltatime, hue[0]); + Color color2 = BootPhase2Color(local_deltatime, hue[1]); + BootPhase2QuadSetColor(r, r, color1, color2); + if (r > 0) + { + uint16_t local_deltatime_half = local_deltatime + start_offset / 2; + Color half_color1 = BootPhase2Color(local_deltatime_half, hue[0]); + Color half_color2 = BootPhase2Color(local_deltatime_half, hue[1]); + BootPhase2QuadSetColor(r - 1, r, half_color1, half_color2); + BootPhase2QuadSetColor(r, r - 1, half_color1, half_color2); + } + #ifdef FAMILY_MYSTRIX + if(r > 3) + { + uint16_t local_deltatime_half = local_deltatime + start_offset * 3 / 2; + Color half_color1 = BootPhase2Color(local_deltatime_half, hue[0]); + Color half_color2 = BootPhase2Color(local_deltatime_half, hue[1]); + BootPhase2QuadSetColor(r - 2, r, half_color1, half_color2); + BootPhase2QuadSetColor(r, r - 2, half_color1, half_color2); + } + #endif + } + MatrixOS::LED::Update(); + } +} + +void MystrixBoot::End() { + MatrixOS::LED::Fill(0); + MatrixOS::LED::Update(); +} \ No newline at end of file diff --git a/Devices/MatrixBlock5/Applications/MystrixBoot/MystrixBoot.h b/Devices/MatrixBlock5/Applications/MystrixBoot/MystrixBoot.h new file mode 100644 index 00000000..416e4b3f --- /dev/null +++ b/Devices/MatrixBlock5/Applications/MystrixBoot/MystrixBoot.h @@ -0,0 +1,42 @@ +#pragma once + +#include "BootAnimation/BootAnimation.h" // TODO Need to be fixed + +#define MATRIX_BOOT_BRIGHTNESS 1.0 // On Top of system brightness +#define MATRIX_BOOT_IDLE 0.25 // On Top of system brightness + +class MystrixBoot : public BootAnimation { + public: + inline static Application_Info info = { + .name = "Mystrix Boot", + .author = "203 Systems", + .color = Color(0xFFFFFFFF), + .version = 1, + .visibility = false, + }; + + // CreateSavedVar(bool, notFirstBoot, false); + Timer timer; + + Point origin = Point((X_SIZE - 1) / 2, (Y_SIZE - 1) / 2); + uint8_t counter; + + uint8_t boot_phase; + uint32_t boot_phase_1_tick_time = 0; + uint32_t boot_phase_2_start_time = 0; + float hueList[1][2] = { + {0.5f, 0.167f} // Standard - Yellow Cyan + }; + + void Setup(const vector& args) override; + bool Idle(bool ready) override; + void Boot() override; + void BootPhase1(); + void BootPhase2(); + Color BootPhase2Color(int16_t time, float hue); + void BootPhase2QuadSetColor(uint8_t x_offset, uint8_t y_offset, Color color1, Color color2); + + void End(); +}; + + diff --git a/Devices/MatrixBlock5/Drivers/LED.cpp b/Devices/MatrixBlock5/Drivers/LED.cpp index 6243939a..ed64de41 100644 --- a/Devices/MatrixBlock5/Drivers/LED.cpp +++ b/Devices/MatrixBlock5/Drivers/LED.cpp @@ -2,13 +2,21 @@ #include "MatrixOSConfig.h" #include "WS2812/WS2812.h" +// TIM8 handle for WS2812 LED driver +extern TIM_HandleTypeDef htim8; + +// Forward declarations +extern void MX_DMA_Init(void); +extern void MX_TIM8_Init(void); + namespace Device { namespace LED { void Init() { - // LED initialization is handled in Family.cpp's LED_Init() - // This function is kept for API compatibility + MX_DMA_Init(); + MX_TIM8_Init(); + WS2812::Init(&htim8, TIM_CHANNEL_2, Device::LED::count); } void Start() { diff --git a/Devices/MatrixBlock5/Family.cpp b/Devices/MatrixBlock5/Family.cpp index ac7ba60c..b63fea09 100644 --- a/Devices/MatrixBlock5/Family.cpp +++ b/Devices/MatrixBlock5/Family.cpp @@ -185,7 +185,7 @@ void NMI_Handler(void) { } void HardFault_Handler(void) { - MatrixOS::SYS::ErrorHandler("Hard Fault"); + //MatrixOS::SYS::ErrorHandler("Hard Fault"); while (true) {} } diff --git a/Devices/MatrixBlock5/FreeRTOSConfig.h b/Devices/MatrixBlock5/FreeRTOSConfig.h index 5c7f2de8..21b9f19f 100644 --- a/Devices/MatrixBlock5/FreeRTOSConfig.h +++ b/Devices/MatrixBlock5/FreeRTOSConfig.h @@ -64,7 +64,7 @@ #define configTICK_RATE_HZ ( 1000 ) #define configMAX_PRIORITIES ( 5 ) #define configMINIMAL_STACK_SIZE ( 128 ) -#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*16*1024 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*24*1024 ) #define configMAX_TASK_NAME_LEN 16 #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 diff --git a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp index 13eeeb00..41969a01 100644 --- a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp +++ b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp @@ -1,5 +1,108 @@ // Matrix Founder Edition Variant Configuration #include "Device.h" +#include "WS2812/WS2812.h" + +// TIM8 handle for WS2812 LED driver +TIM_HandleTypeDef htim8; +DMA_HandleTypeDef hdma_tim8_ch2; + +// Forward declarations +extern "C" void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim); + +// Timer and DMA initialization functions (called from LED.cpp) +void MX_DMA_Init(void) { + /* DMA controller clock enable */ + __HAL_RCC_DMA2_CLK_ENABLE(); + + /* DMA interrupt init */ + /* DMA2_Channel4_5_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA2_Channel4_5_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn); +} + +void MX_TIM8_Init(void) { + TIM_MasterConfigTypeDef sMasterConfig = {0}; + TIM_OC_InitTypeDef sConfigOC = {0}; + TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; + + htim8.Instance = TIM8; + htim8.Init.Prescaler = 0; + htim8.Init.CounterMode = TIM_COUNTERMODE_UP; + htim8.Init.Period = WS2812::GetTimerPeriod(); + htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim8.Init.RepetitionCounter = 0; + htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + if (HAL_TIM_PWM_Init(&htim8) != HAL_OK) + { Device::ErrorHandler(); } + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK) + { Device::ErrorHandler(); } + sConfigOC.OCMode = TIM_OCMODE_PWM1; + sConfigOC.Pulse = 0; + sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; + sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; + sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; + sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; + if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) + { Device::ErrorHandler(); } + sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; + sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; + sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; + sBreakDeadTimeConfig.DeadTime = 0; + sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; + sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; + sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; + if (HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig) != HAL_OK) + { Device::ErrorHandler(); } + + HAL_TIM_MspPostInit(&htim8); +} + +// HAL MSP callbacks for TIM8 +void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if (htim->Instance == TIM8) + { + __HAL_RCC_GPIOC_CLK_ENABLE(); + /**TIM8 GPIO Configuration + PC7 ------> TIM8_CH2 + */ + GPIO_InitStruct.Pin = GPIO_PIN_7; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + } +} + +extern "C" { +void DMA2_Channel4_5_IRQHandler(void) { + HAL_DMA_IRQHandler(&hdma_tim8_ch2); +} +} + +void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm) { + if (htim_pwm->Instance == TIM8) + { + /* Peripheral clock enable */ + __HAL_RCC_TIM8_CLK_ENABLE(); + + /* TIM8 DMA Init */ + hdma_tim8_ch2.Instance = DMA2_Channel5; + hdma_tim8_ch2.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_tim8_ch2.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_tim8_ch2.Init.MemInc = DMA_MINC_ENABLE; + hdma_tim8_ch2.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; // WORD for TIM CCR register + hdma_tim8_ch2.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; // BYTE for pwmBuffer + hdma_tim8_ch2.Init.Mode = DMA_NORMAL; + hdma_tim8_ch2.Init.Priority = DMA_PRIORITY_LOW; + if (HAL_DMA_Init(&hdma_tim8_ch2) != HAL_OK) + { Device::ErrorHandler(); } + + __HAL_LINKDMA(htim_pwm, hdma[TIM_DMA_ID_CC2], hdma_tim8_ch2); + } +} void LoadFounderEdition() { // Configure LED diff --git a/OS/System/Parameters.h b/OS/System/Parameters.h index bfda49d9..4b3162c7 100644 --- a/OS/System/Parameters.h +++ b/OS/System/Parameters.h @@ -31,7 +31,7 @@ #define MATRIXOS_LOG_USBCDC #define MATRIXOS_LOG_COLOR -#define APPLICATION_STACK_SIZE (configMINIMAL_STACK_SIZE * 64) +#define APPLICATION_STACK_SIZE (configMINIMAL_STACK_SIZE * 32) #define KEYEVENT_QUEUE_SIZE 16 #define MIDI_QUEUE_SIZE 128 diff --git a/OS/System/System.cpp b/OS/System/System.cpp index 2eae4daa..180b34f0 100644 --- a/OS/System/System.cpp +++ b/OS/System/System.cpp @@ -39,6 +39,10 @@ namespace MatrixOS::SYS application->second->name.c_str()); active_app_id = next_app_id; active_app = application->second->factory(); + if (active_app == NULL) { + MLOGE("Application Factory", "Factory returned NULL - allocation failed!"); + ErrorHandler("App allocation failed"); + } active_app_info = application->second; } } @@ -50,6 +54,7 @@ namespace MatrixOS::SYS MLOGD("Application Factory", "Can't find target app."); } MLOGD("Application Factory", "Launching Shell"); + MLOGD("Application Factory", "Free heap before Shell factory: %d bytes", xPortGetFreeHeapSize()); next_app_id = OS_SHELL; auto& applications = GetApplications(); auto application = applications.find(next_app_id); @@ -58,6 +63,10 @@ namespace MatrixOS::SYS MLOGD("Application Factory", "Launching %s-%s", application->second->author.c_str(), application->second->name.c_str()); active_app = application->second->factory(); + if (active_app == NULL) { + MLOGE("Application Factory", "Shell factory returned NULL - allocation failed!"); + ErrorHandler("Shell allocation failed"); + } active_app_id = next_app_id; active_app_info = application->second; } diff --git a/OS/USB/MIDI.cpp b/OS/USB/MIDI.cpp index d1888761..534021f4 100644 --- a/OS/USB/MIDI.cpp +++ b/OS/USB/MIDI.cpp @@ -9,41 +9,43 @@ namespace MatrixOS::MIDI namespace MatrixOS::USB::MIDI { - std::vector ports; + std::vector ports; std::vector portTasks; std::vector portTaskNames; - + std::vector sysex_buffer; void portTask(void* param) { - uint8_t itf = ports.size(); - string portname = "USB MIDI " + std::to_string(itf + 1); - MidiPort port = MidiPort(portname, MIDI_PORT_USB + itf); - ports.push_back(&port); + uint8_t itf = (uint8_t)(uintptr_t)param; MidiPacket packet; while (true) { - if (port.Get(&packet, portMAX_DELAY)) - { tud_midi_stream_write(port.id % 0x100, packet.data, packet.Length()); } + if (ports[itf].Get(&packet, portMAX_DELAY)) + { tud_midi_stream_write(ports[itf].id % 0x100, packet.data, packet.Length()); } } } void Init() { - ports.clear(); - for (TaskHandle_t portTask : portTasks) { vTaskDelete(portTask); } + portTasks.clear(); + portTaskNames.clear(); + ports.clear(); + // Create ports and tasks ports.reserve(USB_MIDI_COUNT); portTasks.reserve(USB_MIDI_COUNT); - + for (uint8_t i = 0; i < USB_MIDI_COUNT; i++) { + string portname = "USB MIDI " + std::to_string(i + 1); + ports.emplace_back(portname, MIDI_PORT_USB + i); + portTasks.push_back(NULL); - portTaskNames.push_back("USB MIDI " + std::to_string(i + 1)); - xTaskCreate(portTask, portTaskNames.back().c_str(), configMINIMAL_STACK_SIZE * 2, NULL, configMAX_PRIORITIES - 2, + portTaskNames.push_back(portname); + xTaskCreate(portTask, portTaskNames.back().c_str(), configMINIMAL_STACK_SIZE * 2, (void*)(uintptr_t)i, configMAX_PRIORITIES - 2, &portTasks.back()); } } diff --git a/OS/USB/TinyUSB/tusb_config.h b/OS/USB/TinyUSB/tusb_config.h index e7a16119..cbf1d964 100644 --- a/OS/USB/TinyUSB/tusb_config.h +++ b/OS/USB/TinyUSB/tusb_config.h @@ -121,8 +121,10 @@ extern "C" { #define CFG_TUD_HID_EP_BUFSIZE 64 -// MSC Buffer size of Device Mass storage +// MSC Buffer size of Device Mass storage (only if enabled) +#if DEVICE_STORAGE #define CFG_TUD_MSC_EP_BUFSIZE 512 +#endif enum { diff --git a/Platform/STM32F1/WS2812/WS2812.cpp b/Platform/STM32F1/WS2812/WS2812.cpp index 8e8c8f5e..230a5c42 100644 --- a/Platform/STM32F1/WS2812/WS2812.cpp +++ b/Platform/STM32F1/WS2812/WS2812.cpp @@ -1,152 +1,110 @@ #include "WS2812.h" +namespace Device +{ + void ErrorHandler(void); +} + namespace WS2812 { - static uint16_t numsOfLED; - static uint8_t* led_data; - static uint8_t* dither_error; - static bool transfer_in_progress = false; - - // STM32 specific variables - static TIM_HandleTypeDef* ws2812_timer = nullptr; - static uint32_t ws2812_channel; - static DMA_HandleTypeDef hdma_tim; - - // WS2812 timing constants (for 72MHz system clock) - const uint32_t T0H = 29; // 0.4us at 72MHz (29 cycles) - const uint32_t T1H = 58; // 0.8us at 72MHz (58 cycles) - const uint32_t T0L = 58; // 0.85us at 72MHz (58 cycles) - const uint32_t T1L = 29; // 0.45us at 72MHz (29 cycles) - const uint32_t RESET = 2400; // 50us at 72MHz (2400 cycles) + uint16_t numsOfLED; + uint8_t TH_DutyCycle; + uint8_t TL_DutyCycle; + TIM_HandleTypeDef* ws2812_timer = nullptr; + uint32_t ws2812_channel; + Color* frameBuffer = nullptr; + uint8_t* pwmBuffer = nullptr; + uint16_t bufferSize; + int32_t progress = -1; // -1 means signal end has been sent and ready for new job void Init(TIM_HandleTypeDef* timer, uint32_t channel, uint16_t led_count) { ws2812_timer = timer; ws2812_channel = channel; numsOfLED = led_count; - // Allocate memory for LED data (3 bytes per LED) - led_data = (uint8_t*)malloc(numsOfLED * 3); - if (led_data == NULL) { - // Handle memory allocation failure + // Calculate buffer size and allocate PWM buffer + bufferSize = numsOfLED * 24 + LED_DMA_END_LENGTH * 2; + pwmBuffer = (uint8_t*)calloc(bufferSize, 1); + if (pwmBuffer == NULL) { + Device::ErrorHandler(); return; } - // Allocate memory for dithering error - dither_error = (uint8_t*)malloc(numsOfLED * 3 * sizeof(uint8_t)); - if (dither_error == NULL) { - free(led_data); - led_data = NULL; - return; + // Register TIM callback for DMA completion + if (HAL_TIM_RegisterCallback(ws2812_timer, HAL_TIM_PWM_PULSE_FINISHED_CB_ID, DMAHandler) != HAL_OK) { + Device::ErrorHandler(); } + } - // Initialize dither error with random values - for (uint16_t i = 0; i < numsOfLED * 3; i++) { - dither_error[i] = HAL_GetTick() & 0x7F; // Simple pseudo-random + uint32_t GetTimerPeriod() { + uint32_t timerPeriod; + if (HAL_RCC_GetHCLKFreq() % 800000 == 0) { + timerPeriod = (HAL_RCC_GetHCLKFreq() / 800000) - 1; + } + else { + return -1; // Error: clock frequency not compatible } - // Clear LED data - memset(led_data, 0, numsOfLED * 3); + // Calculate duty cycles for WS2812 timing + // TH (high time for '1'): ~0.8us = 173/256 of period + // TL (high time for '0'): ~0.4us = 82/256 of period + TH_DutyCycle = (timerPeriod * 173) >> 8; + TL_DutyCycle = (timerPeriod * 82) >> 8; - // Start PWM output - HAL_TIM_PWM_Start(ws2812_timer, ws2812_channel); + return timerPeriod; } void Show(Color* buffer, std::vector& brightness) { // Safety checks - if (buffer == NULL || led_data == NULL || transfer_in_progress) { + if (buffer == NULL || pwmBuffer == NULL || progress != -1) { return; } - // Process LED data with brightness and dithering - for (uint16_t i = 0; i < numsOfLED; i++) { - uint16_t data_index = i * 3; - - // Apply brightness (assuming single partition for MatrixBlock5) - uint8_t local_brightness = brightness.size() > 0 ? brightness[0] : 255; - - led_data[data_index] = Color::scale8_video(buffer[i].G, local_brightness); - led_data[data_index + 1] = Color::scale8_video(buffer[i].R, local_brightness); - led_data[data_index + 2] = Color::scale8_video(buffer[i].B, local_brightness); - - // Apply dithering if enabled - if (dithering && dither_error != NULL) { - const uint8_t dither_error_threshold = 16; - - // Process all channels - for (int ch = 0; ch < 3; ch++) { - uint16_t channel_index = data_index + ch; - if (led_data[channel_index] >= dithering_threshold) { - uint16_t expected; - // Get the appropriate color component based on channel - if (ch == 0) expected = (uint16_t)buffer[i].G * local_brightness; // Green - else if (ch == 1) expected = (uint16_t)buffer[i].R * local_brightness; // Red - else expected = (uint16_t)buffer[i].B * local_brightness; // Blue - uint16_t actual = (uint16_t)led_data[channel_index] << 8; - - if (expected > actual) { - uint8_t new_dither_error = (expected - actual) >> 8; - if (new_dither_error >= dither_error_threshold) { - dither_error[channel_index] += new_dither_error >> 1; - if (dither_error[channel_index] >= 128) { - if (led_data[channel_index] < 255) { - led_data[channel_index] += 1; - } - dither_error[channel_index] -= 128; - } - } - } - } - } - } - } - - // For STM32F1, we'll use a simple blocking approach for now - // In a real implementation, this would use DMA - - // Convert RGB data to PWM duty cycles and send - // This is a simplified implementation - real implementation would use DMA - - // Set transfer flag - transfer_in_progress = true; - - // Simple blocking transmission (replace with DMA in production) - for (uint16_t i = 0; i < numsOfLED * 3; i++) { - uint8_t byte = led_data[i]; - - // Send each bit - for (int bit = 7; bit >= 0; bit--) { - if (byte & (1 << bit)) { - // Send '1' bit - __HAL_TIM_SET_COMPARE(ws2812_timer, ws2812_channel, T1H); - // Wait for T1H duration - for (volatile int j = 0; j < 10; j++); // Simple delay - __HAL_TIM_SET_COMPARE(ws2812_timer, ws2812_channel, T1L); - } else { - // Send '0' bit - __HAL_TIM_SET_COMPARE(ws2812_timer, ws2812_channel, T0H); - // Wait for T0H duration - for (volatile int j = 0; j < 10; j++); // Simple delay - __HAL_TIM_SET_COMPARE(ws2812_timer, ws2812_channel, T0L); - } - // Wait for bit period - for (volatile int j = 0; j < 10; j++); // Simple delay - } - } + // Get brightness value (assume single partition for MatrixBlock5) + uint8_t local_brightness = brightness.size() > 0 ? brightness[0] : 255; - // Send reset pulse - __HAL_TIM_SET_COMPARE(ws2812_timer, ws2812_channel, 0); - // Wait for reset duration - for (volatile int j = 0; j < 1000; j++); // Simple delay + // Set up for DMA transfer + progress = 0; + frameBuffer = buffer; + PrepLEDBuffer(local_brightness); + SendData(); + } - transfer_in_progress = false; + void DMAHandler(TIM_HandleTypeDef* htim) { + HAL_TIM_PWM_Stop_DMA(htim, ws2812_channel); + progress = -1; } - // DMA callback functions - void DMA_TransferComplete_Callback(void) { - transfer_in_progress = false; + void SendData() { + HAL_TIM_PWM_Start_DMA(ws2812_timer, ws2812_channel, (uint32_t*)pwmBuffer, bufferSize); } - void DMA_TransferHalfComplete_Callback(void) { - // Handle half transfer if needed + void PrepLEDBuffer(uint8_t brightness) { + uint16_t index = 0; + + // Add start padding + for (uint8_t i = 0; i < LED_DMA_END_LENGTH; i++) { + pwmBuffer[index] = 0; + index++; + } + + // Fill PWM buffer with LED data + while (index <= (bufferSize - 24) && progress < numsOfLED) { + // Get GRB value with brightness applied + uint32_t GRB = frameBuffer[progress].GRB(brightness); + + // Convert each bit to PWM duty cycle + for (int8_t i = 23; i >= 0; i--) { + pwmBuffer[index] = (GRB & (1 << i)) ? TH_DutyCycle : TL_DutyCycle; + index++; + } + progress++; + } + + // Add end padding + for (uint8_t i = 0; i < LED_DMA_END_LENGTH; i++) { + pwmBuffer[index] = 0; + index++; + } } -} \ No newline at end of file +} diff --git a/Platform/STM32F1/WS2812/WS2812.h b/Platform/STM32F1/WS2812/WS2812.h index 290fa935..d6e3e3ca 100644 --- a/Platform/STM32F1/WS2812/WS2812.h +++ b/Platform/STM32F1/WS2812/WS2812.h @@ -3,11 +3,14 @@ #include #include #include +#include #include "Framework.h" #include "stm32f1xx_hal.h" #include "FreeRTOS.h" #include "timers.h" +#define LED_DMA_END_LENGTH 80 + namespace WS2812 { inline bool dithering = false; @@ -15,8 +18,20 @@ namespace WS2812 void Init(TIM_HandleTypeDef* timer, uint32_t channel, uint16_t led_count); void Show(Color* buffer, std::vector& brightness); + uint32_t GetTimerPeriod(); + + // DMA-based WS2812 functions + void DMAHandler(TIM_HandleTypeDef* htim); + void SendData(); + void PrepLEDBuffer(uint8_t brightness); - // STM32 specific functions - void DMA_TransferComplete_Callback(void); - void DMA_TransferHalfComplete_Callback(void); + extern uint16_t numsOfLED; + extern uint8_t TH_DutyCycle; + extern uint8_t TL_DutyCycle; + extern TIM_HandleTypeDef* ws2812_timer; + extern uint32_t ws2812_channel; + extern Color* frameBuffer; + extern uint8_t* pwmBuffer; + extern uint16_t bufferSize; + extern int32_t progress; } \ No newline at end of file From 9b194092185393a3b6dcf21c346ec06b22783a36 Mon Sep 17 00:00:00 2001 From: Nengzhuo Cai Date: Mon, 6 Oct 2025 08:30:15 -0400 Subject: [PATCH 14/17] App allocate using freertos api --- Applications/Application.h | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/Applications/Application.h b/Applications/Application.h index 004ec5d2..943767b6 100644 --- a/Applications/Application.h +++ b/Applications/Application.h @@ -62,20 +62,27 @@ inline std::map& GetApplicationIDs() { template static inline void register_application(uint32_t order, bool is_system) { APPLICATION_CLASS::info.is_system = is_system; // Set system flag - APPLICATION_CLASS::info.factory = []() -> Application* { \ - return new APPLICATION_CLASS(); \ - }; \ - APPLICATION_CLASS::info.destructor = [](Application* app) { \ - delete (APPLICATION_CLASS*)app; \ - }; \ - MLOGI("Application", "Registering application: %s%s", APPLICATION_CLASS::info.name.c_str(), is_system ? " (system)" : ""); \ - uint32_t app_id = StringHash(APPLICATION_CLASS::info.author + '-' + APPLICATION_CLASS::info.name); \ - auto& applications = GetApplications(); \ - if (applications.find(app_id) != applications.end()) { \ - return; \ - } \ - applications.insert({app_id, &APPLICATION_CLASS::info}); \ - GetApplicationIDs()[order] = app_id; \ + APPLICATION_CLASS::info.factory = []() -> Application* { + void* mem = pvPortMalloc(sizeof(APPLICATION_CLASS)); + if (mem == nullptr) { + return nullptr; + } + return new(mem) APPLICATION_CLASS(); // Placement new + }; + APPLICATION_CLASS::info.destructor = [](Application* app) { + if (app != nullptr) { + app->~Application(); // Call destructor + vPortFree(app); // Free memory + } + }; + MLOGI("Application", "Registering application: %s%s", APPLICATION_CLASS::info.name.c_str(), is_system ? " (system)" : ""); + uint32_t app_id = StringHash(APPLICATION_CLASS::info.author + '-' + APPLICATION_CLASS::info.name); + auto& applications = GetApplications(); + if (applications.find(app_id) != applications.end()) { + return; + } + applications.insert({app_id, &APPLICATION_CLASS::info}); + GetApplicationIDs()[order] = app_id; } From e5cce5789b34048e02d4e7c3238d172d8be4603d Mon Sep 17 00:00:00 2001 From: Nengzhuo Cai Date: Mon, 6 Oct 2025 09:02:37 -0400 Subject: [PATCH 15/17] No reinterper cast for keypad timer (Mystrix) --- Devices/MatrixESP32/Drivers/Keypad.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Devices/MatrixESP32/Drivers/Keypad.cpp b/Devices/MatrixESP32/Drivers/Keypad.cpp index 79141c7c..8530fa00 100644 --- a/Devices/MatrixESP32/Drivers/Keypad.cpp +++ b/Devices/MatrixESP32/Drivers/Keypad.cpp @@ -42,6 +42,12 @@ namespace Device::KeyPad { FSR::Init(); } } + // Timer callback wrapper with correct signature + static void KeypadTimerCallback(TimerHandle_t xTimer) { + (void)xTimer; + Scan(); + } + void StartKeyPad() { if (!velocity_sensitivity) { @@ -52,8 +58,7 @@ namespace Device::KeyPad FSR::Start(); } - keypad_timer = xTimerCreateStatic(NULL, configTICK_RATE_HZ / keypad_scanrate, true, NULL, reinterpret_cast(Scan), &keypad_timer_def); - + keypad_timer = xTimerCreateStatic(NULL, configTICK_RATE_HZ / keypad_scanrate, true, NULL, KeypadTimerCallback, &keypad_timer_def); xTimerStart(keypad_timer, 0); } From a65a73be28d6e1015629bd6d86dd23c9a05821af Mon Sep 17 00:00:00 2001 From: Nengzhuo Cai Date: Mon, 6 Oct 2025 09:02:49 -0400 Subject: [PATCH 16/17] No cast for FE --- Devices/MatrixBlock5/Drivers/Keypad.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Devices/MatrixBlock5/Drivers/Keypad.cpp b/Devices/MatrixBlock5/Drivers/Keypad.cpp index b0eb3486..6c51d285 100644 --- a/Devices/MatrixBlock5/Drivers/Keypad.cpp +++ b/Devices/MatrixBlock5/Drivers/Keypad.cpp @@ -28,9 +28,15 @@ namespace Device::KeyPad // TODO: Initialize touch bar for STM32F103 } + // Timer callback wrapper with correct signature + static void KeypadTimerCallback(TimerHandle_t xTimer) { + (void)xTimer; + Scan(); + } + void StartKeyPad() { // Create FreeRTOS timer for keypad scanning - keypad_timer = xTimerCreateStatic(NULL, configTICK_RATE_HZ / keypad_scanrate, true, NULL, reinterpret_cast(Scan), &keypad_timer_def); + keypad_timer = xTimerCreateStatic(NULL, configTICK_RATE_HZ / keypad_scanrate, true, NULL, KeypadTimerCallback, &keypad_timer_def); xTimerStart(keypad_timer, 0); } From 358eb4c42edb4a582e59c7e3d6e787fba7b15a8d Mon Sep 17 00:00:00 2001 From: Nengzhuo Cai Date: Tue, 21 Oct 2025 18:06:24 -0400 Subject: [PATCH 17/17] FE progress --- Devices/MatrixBlock5/Drivers/Keypad.cpp | 3 +- Devices/MatrixBlock5/Family.cpp | 3 +- Devices/MatrixBlock5/Family.h | 10 +- .../Variants/MatrixFounderEdition/Config.h | 179 ++++++------------ .../MatrixFounderEdition/FounderEdition.cpp | 160 ++++++++-------- OS/USB/TinyUSB/usb_desc_default.cpp | 2 +- 6 files changed, 144 insertions(+), 213 deletions(-) diff --git a/Devices/MatrixBlock5/Drivers/Keypad.cpp b/Devices/MatrixBlock5/Drivers/Keypad.cpp index 6c51d285..e6daf3af 100644 --- a/Devices/MatrixBlock5/Drivers/Keypad.cpp +++ b/Devices/MatrixBlock5/Drivers/Keypad.cpp @@ -64,7 +64,6 @@ namespace Device::KeyPad for (uint8_t y = 0; y < Y_SIZE; y++) { // Read row - Fract16 read = HAL_GPIO_ReadPin(keypad_read_ports[y], keypad_read_pins[y]) * UINT16_MAX; if (keypadState[x][y].Update(keypad_config, read)) { uint16_t keyID = (1 << 12) + (x << 6) + y; @@ -91,7 +90,7 @@ namespace Device::KeyPad Fract16 read = HAL_GPIO_ReadPin(fn_port, fn_pin) * UINT16_MAX; if (fn_active_low) { read = UINT16_MAX - (uint16_t)read; } - if (fnState.Update(binary_config, read)) + if (fnState.Update(keypad_config, read)) { if (NotifyOS(0, &fnState)) { return true; } diff --git a/Devices/MatrixBlock5/Family.cpp b/Devices/MatrixBlock5/Family.cpp index b63fea09..b22c385c 100644 --- a/Devices/MatrixBlock5/Family.cpp +++ b/Devices/MatrixBlock5/Family.cpp @@ -2,14 +2,13 @@ #include "MatrixOS.h" #include "UI/UI.h" #include "MatrixOSConfig.h" +#include "Variants/MatrixFounderEdition/Config.h" #include "timers.h" // Forward declare TinyUSB interrupt handler extern "C" void dcd_int_handler(uint8_t rhport); -// Variant loader function -void LoadFounderEdition(); namespace Device diff --git a/Devices/MatrixBlock5/Family.h b/Devices/MatrixBlock5/Family.h index f57aa6b5..9ff0b33f 100644 --- a/Devices/MatrixBlock5/Family.h +++ b/Devices/MatrixBlock5/Family.h @@ -71,7 +71,7 @@ namespace Device inline bool fn_active_low = true; inline bool velocity_sensitivity = false; - inline KeyConfig binary_config = { + inline KeyConfig keypad_config = { .apply_curve = false, .low_threshold = 0, .high_threshold = 65535, @@ -79,14 +79,6 @@ namespace Device .debounce = 3, }; - inline KeyConfig keypad_config = { - .apply_curve = true, - .low_threshold = 1536, - .high_threshold = 32767, - .activation_offset = 256, - .debounce = 10, - }; - inline GPIO_TypeDef* keypad_write_ports[X_SIZE]; inline uint16_t keypad_write_pins[X_SIZE]; inline GPIO_TypeDef* keypad_read_ports[Y_SIZE]; diff --git a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/Config.h b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/Config.h index ab5ffe80..d425f87f 100644 --- a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/Config.h +++ b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/Config.h @@ -1,137 +1,78 @@ -// Define Device Specific Macro, Value and private function #pragma once -#include "Family.h" +#include "../../MatrixOSConfig.h" +#include "stm32f1xx_hal.h" -#define GRID_8x8 -#define MODEL MXFE1 -#define MULTIPRESS 10 // Key Press will be process at once +#include +#include -extern TIM_HandleTypeDef htim8; -extern DMA_HandleTypeDef hdma_tim8_ch2; - -namespace Device -{ - const string name = "Matrix Founder Edition"; - const string model = "MXFE1"; +namespace MatrixBlock5 { +namespace FounderEdition { - const string manufacturer_name = "203 Systems"; - const string product_name = "Matrix"; - const uint16_t usb_vid = 0x0203; - const uint16_t usb_pid = 0x1040; //(Device Class)0001 (Device Code)000001 (Reserved for Device ID (0~63))000000 - - const uint16_t led_count = 64; - const uint8_t x_size = 8; - const uint8_t y_size = 8; +struct GpioPin { + GPIO_TypeDef* port; + uint16_t pin; +}; -#define MAX_LED_LAYERS 5 - inline uint16_t keypad_scanrate = 60; - inline uint16_t fps = 120; // Depends on the FreeRTOS tick speed +inline constexpr const char* kDeviceName = "MatrixBlock5"; +inline constexpr const char* kDeviceModel = "MB5F"; +inline constexpr const char* kManufacturerName = "203 Systems"; +inline constexpr const char* kProductName = "MatrixBlock5"; +inline constexpr uint16_t kUsbVid = 0x0203; +inline constexpr uint16_t kUsbPid = 0x1041; + +inline constexpr uint16_t kKeypadScanRateHz = 60; + +inline constexpr size_t kGridColumns = X_SIZE; +inline constexpr size_t kGridRows = Y_SIZE; +inline constexpr size_t kBrightnessSteps = 8; +inline constexpr size_t kTouchbarEntries = 16; + +inline const uint8_t kBrightnessLevels[kBrightnessSteps] = {8, 12, 24, 40, 64, 90, 128, 168}; + +inline const GpioPin kLedPin{GPIOC, GPIO_PIN_7}; +inline const GpioPin kFnPin{GPIOA, GPIO_PIN_8}; + +inline const GpioPin kKeypadColumns[kGridColumns] = { + {GPIOB, GPIO_PIN_12}, + {GPIOB, GPIO_PIN_13}, + {GPIOB, GPIO_PIN_14}, + {GPIOB, GPIO_PIN_15}, + {GPIOC, GPIO_PIN_6}, + {GPIOC, GPIO_PIN_7}, + {GPIOC, GPIO_PIN_8}, + {GPIOC, GPIO_PIN_9}, +}; - inline uint8_t brightness_level[8] = {8, 12, 24, 40, 64, 90, 128, 168}; +inline const GpioPin kKeypadRows[kGridRows] = { + {GPIOB, GPIO_PIN_0}, + {GPIOB, GPIO_PIN_1}, + {GPIOA, GPIO_PIN_11}, + {GPIOA, GPIO_PIN_12}, + {GPIOC, GPIO_PIN_4}, + {GPIOA, GPIO_PIN_15}, + {GPIOC, GPIO_PIN_5}, + {GPIOC, GPIO_PIN_3}, +}; - const uint8_t touchbar_size = 8; // Not required by the API, private use. 16 Physical but 8 virtualized key. +inline const GpioPin kTouchDataPin{GPIOA, GPIO_PIN_0}; +inline const GpioPin kTouchClockPin{GPIOA, GPIO_PIN_1}; - const uint16_t page_size = 2048; - const uint8_t nums_of_page = 32; // Total size has to smaller than 64kb because address constrain - const uint32_t nvs_address = 0x8070000; +inline const uint8_t kTouchbarMap[kTouchbarEntries] = {4, 5, 6, 7, 15, 14, 13, 12, 11, 10, 9, 8, 0, 1, 2, 3}; - namespace KeyPad - { - inline KeyInfo fnState; - inline KeyInfo keypadState[x_size][y_size]; - inline KeyInfo touchbarState[x_size]; +} // namespace FounderEdition +} // namespace MatrixBlock5 - void FNScan(); - void KeyPadScan(); - void TouchBarScan(); +extern TIM_HandleTypeDef htim8; +extern DMA_HandleTypeDef hdma_tim8_ch2; - bool addToList(uint16_t keyID); // Return true when list is full. - void clearList(); - bool isListFull(); - } +namespace Device { +void LoadFounderEdition(); } extern "C" { +void MX_DMA_Init(void); +void MX_TIM8_Init(void); void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim); -void NMI_Handler(void); -void HardFault_Handler(void); -void MemManage_Handler(void); -void BusFault_Handler(void); -void UsageFault_Handler(void); -void SVC_Handler(void); -void DebugMon_Handler(void); -void PendSV_Handler(void); -void SysTick_Handler(void); void DMA2_Channel4_5_IRQHandler(void); } - -struct GPIO { - GPIO_TypeDef* port; - uint16_t pin; - - GPIO(GPIO_TypeDef* port, uint16_t pin) { - this->port = port; - this->pin = pin; - } -}; - -#define FN_Pin GPIO_PIN_0 -#define FN_GPIO_Port GPIOA - -#define Key1_Pin GPIO_PIN_15 -#define Key1_GPIO_Port GPIOB -#define Key2_Pin GPIO_PIN_14 -#define Key2_GPIO_Port GPIOB -#define Key3_Pin GPIO_PIN_13 -#define Key3_GPIO_Port GPIOB -#define Key4_Pin GPIO_PIN_12 -#define Key4_GPIO_Port GPIOB -#define Key5_Pin GPIO_PIN_6 -#define Key5_GPIO_Port GPIOC -#define Key6_Pin GPIO_PIN_15 -#define Key6_GPIO_Port GPIOC -#define Key7_Pin GPIO_PIN_14 -#define Key7_GPIO_Port GPIOC -#define Key8_Pin GPIO_PIN_13 -#define Key8_GPIO_Port GPIOC - -#define KeyRead1_Pin GPIO_PIN_1 -#define KeyRead1_GPIO_Port GPIOB -#define KeyRead2_Pin GPIO_PIN_0 -#define KeyRead2_GPIO_Port GPIOB -#define KeyRead3_Pin GPIO_PIN_2 -#define KeyRead3_GPIO_Port GPIOA -#define KeyRead4_Pin GPIO_PIN_1 -#define KeyRead4_GPIO_Port GPIOA -#define KeyRead5_Pin GPIO_PIN_3 -#define KeyRead5_GPIO_Port GPIOC -#define KeyRead6_Pin GPIO_PIN_3 -#define KeyRead6_GPIO_Port GPIOA -#define KeyRead7_Pin GPIO_PIN_5 -#define KeyRead7_GPIO_Port GPIOC -#define KeyRead8_Pin GPIO_PIN_4 -#define KeyRead8_GPIO_Port GPIOC - -#define TouchData_Pin GPIO_PIN_6 -#define TouchData_GPIO_Port GPIOA -#define TouchClock_Pin GPIO_PIN_7 -#define TouchClock_GPIO_Port GPIOA - -inline GPIO keypad_write_pins[] = { - GPIO(Key1_GPIO_Port, Key1_Pin), GPIO(Key2_GPIO_Port, Key2_Pin), GPIO(Key3_GPIO_Port, Key3_Pin), - GPIO(Key4_GPIO_Port, Key4_Pin), GPIO(Key5_GPIO_Port, Key5_Pin), GPIO(Key6_GPIO_Port, Key6_Pin), - GPIO(Key7_GPIO_Port, Key7_Pin), GPIO(Key8_GPIO_Port, Key8_Pin), -}; - -inline GPIO keypad_read_pins[] = { - GPIO(KeyRead1_GPIO_Port, KeyRead1_Pin), GPIO(KeyRead2_GPIO_Port, KeyRead2_Pin), - GPIO(KeyRead3_GPIO_Port, KeyRead3_Pin), GPIO(KeyRead4_GPIO_Port, KeyRead4_Pin), - GPIO(KeyRead5_GPIO_Port, KeyRead5_Pin), GPIO(KeyRead6_GPIO_Port, KeyRead6_Pin), - GPIO(KeyRead7_GPIO_Port, KeyRead7_Pin), GPIO(KeyRead8_GPIO_Port, KeyRead8_Pin), -}; - -inline GPIO fn_pin = GPIO(FN_GPIO_Port, FN_Pin); - -inline GPIO touch_clock_pin = GPIO(TouchClock_GPIO_Port, TouchClock_Pin); -inline GPIO touch_data_pin = GPIO(TouchData_GPIO_Port, TouchData_Pin); \ No newline at end of file diff --git a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp index 41969a01..ffa7aa7a 100644 --- a/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp +++ b/Devices/MatrixBlock5/Variants/MatrixFounderEdition/FounderEdition.cpp @@ -1,15 +1,13 @@ // Matrix Founder Edition Variant Configuration #include "Device.h" #include "WS2812/WS2812.h" +#include "Config.h" -// TIM8 handle for WS2812 LED driver TIM_HandleTypeDef htim8; DMA_HandleTypeDef hdma_tim8_ch2; -// Forward declarations extern "C" void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim); -// Timer and DMA initialization functions (called from LED.cpp) void MX_DMA_Init(void) { /* DMA controller clock enable */ __HAL_RCC_DMA2_CLK_ENABLE(); @@ -21,46 +19,45 @@ void MX_DMA_Init(void) { } void MX_TIM8_Init(void) { - TIM_MasterConfigTypeDef sMasterConfig = {0}; - TIM_OC_InitTypeDef sConfigOC = {0}; - TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; - - htim8.Instance = TIM8; - htim8.Init.Prescaler = 0; - htim8.Init.CounterMode = TIM_COUNTERMODE_UP; - htim8.Init.Period = WS2812::GetTimerPeriod(); - htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; - htim8.Init.RepetitionCounter = 0; - htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; - if (HAL_TIM_PWM_Init(&htim8) != HAL_OK) - { Device::ErrorHandler(); } - sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; - sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; - if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK) - { Device::ErrorHandler(); } - sConfigOC.OCMode = TIM_OCMODE_PWM1; - sConfigOC.Pulse = 0; - sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; - sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; - sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; - sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; - sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; - if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) - { Device::ErrorHandler(); } - sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; - sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; - sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; - sBreakDeadTimeConfig.DeadTime = 0; - sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; - sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; - sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; - if (HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig) != HAL_OK) - { Device::ErrorHandler(); } - - HAL_TIM_MspPostInit(&htim8); + TIM_MasterConfigTypeDef sMasterConfig = {0}; + TIM_OC_InitTypeDef sConfigOC = {0}; + TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; + + htim8.Instance = TIM8; + htim8.Init.Prescaler = 0; + htim8.Init.CounterMode = TIM_COUNTERMODE_UP; + htim8.Init.Period = WS2812::GetTimerPeriod(); + htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim8.Init.RepetitionCounter = 0; + htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + if (HAL_TIM_PWM_Init(&htim8) != HAL_OK) + { Device::ErrorHandler(); } + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK) + { Device::ErrorHandler(); } + sConfigOC.OCMode = TIM_OCMODE_PWM1; + sConfigOC.Pulse = 0; + sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; + sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; + sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; + sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; + if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) + { Device::ErrorHandler(); } + sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; + sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; + sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; + sBreakDeadTimeConfig.DeadTime = 0; + sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; + sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; + sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; + if (HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig) != HAL_OK) + { Device::ErrorHandler(); } + + HAL_TIM_MspPostInit(&htim8); } -// HAL MSP callbacks for TIM8 void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if (htim->Instance == TIM8) @@ -105,42 +102,45 @@ void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm) { } void LoadFounderEdition() { - // Configure LED - Device::LED::led_port = GPIOC; - Device::LED::led_pin = GPIO_PIN_7; - - // Configure FN key - Device::KeyPad::fn_port = GPIOA; - Device::KeyPad::fn_pin = GPIO_PIN_8; - - // Configure keypad write pins (columns) - Device::KeyPad::keypad_write_ports[0] = GPIOB; Device::KeyPad::keypad_write_pins[0] = GPIO_PIN_12; // Key1 - Device::KeyPad::keypad_write_ports[1] = GPIOB; Device::KeyPad::keypad_write_pins[1] = GPIO_PIN_13; // Key2 - Device::KeyPad::keypad_write_ports[2] = GPIOB; Device::KeyPad::keypad_write_pins[2] = GPIO_PIN_14; // Key3 - Device::KeyPad::keypad_write_ports[3] = GPIOB; Device::KeyPad::keypad_write_pins[3] = GPIO_PIN_15; // Key4 - Device::KeyPad::keypad_write_ports[4] = GPIOC; Device::KeyPad::keypad_write_pins[4] = GPIO_PIN_6; // Key5 - Device::KeyPad::keypad_write_ports[5] = GPIOC; Device::KeyPad::keypad_write_pins[5] = GPIO_PIN_7; // Key6 - Device::KeyPad::keypad_write_ports[6] = GPIOC; Device::KeyPad::keypad_write_pins[6] = GPIO_PIN_8; // Key7 - Device::KeyPad::keypad_write_ports[7] = GPIOC; Device::KeyPad::keypad_write_pins[7] = GPIO_PIN_9; // Key8 - - // Configure keypad read pins (rows) - Device::KeyPad::keypad_read_ports[0] = GPIOB; Device::KeyPad::keypad_read_pins[0] = GPIO_PIN_0; // KeyRead1 - Device::KeyPad::keypad_read_ports[1] = GPIOB; Device::KeyPad::keypad_read_pins[1] = GPIO_PIN_1; // KeyRead2 - Device::KeyPad::keypad_read_ports[2] = GPIOA; Device::KeyPad::keypad_read_pins[2] = GPIO_PIN_11; // KeyRead3 - Device::KeyPad::keypad_read_ports[3] = GPIOA; Device::KeyPad::keypad_read_pins[3] = GPIO_PIN_12; // KeyRead4 - Device::KeyPad::keypad_read_ports[4] = GPIOC; Device::KeyPad::keypad_read_pins[4] = GPIO_PIN_4; // KeyRead5 - Device::KeyPad::keypad_read_ports[5] = GPIOA; Device::KeyPad::keypad_read_pins[5] = GPIO_PIN_15; // KeyRead6 - Device::KeyPad::keypad_read_ports[6] = GPIOC; Device::KeyPad::keypad_read_pins[6] = GPIO_PIN_5; // KeyRead7 - Device::KeyPad::keypad_read_ports[7] = GPIOC; Device::KeyPad::keypad_read_pins[7] = GPIO_PIN_3; // KeyRead8 - - // Configure touchbar - Device::KeyPad::touchData_Port = GPIOA; - Device::KeyPad::touchData_Pin = GPIO_PIN_0; - Device::KeyPad::touchClock_Port = GPIOA; - Device::KeyPad::touchClock_Pin = GPIO_PIN_1; - - // Set device name and model - Device::name = "MatrixBlock5"; - Device::model = "MB5F"; - Device::product_name = "MatrixBlock5"; -} \ No newline at end of file + using namespace MatrixBlock5::FounderEdition; + + static_assert(kGridColumns == X_SIZE, "FounderEdition grid width mismatch"); + static_assert(kGridRows == Y_SIZE, "FounderEdition grid height mismatch"); + static_assert(kTouchbarEntries == Device::KeyPad::touchbar_size, "FounderEdition touchbar size mismatch"); + + Device::LED::led_port = kLedPin.port; + Device::LED::led_pin = kLedPin.pin; + for (size_t i = 0; i < kBrightnessSteps; ++i) + { Device::LED::brightness_level[i] = kBrightnessLevels[i]; } + + Device::KeyPad::keypad_scanrate = kKeypadScanRateHz; + Device::KeyPad::fn_port = kFnPin.port; + Device::KeyPad::fn_pin = kFnPin.pin; + + for (size_t i = 0; i < kGridColumns; ++i) + { + Device::KeyPad::keypad_write_ports[i] = kKeypadColumns[i].port; + Device::KeyPad::keypad_write_pins[i] = kKeypadColumns[i].pin; + } + + for (size_t i = 0; i < kGridRows; ++i) + { + Device::KeyPad::keypad_read_ports[i] = kKeypadRows[i].port; + Device::KeyPad::keypad_read_pins[i] = kKeypadRows[i].pin; + } + + Device::KeyPad::touchData_Port = kTouchDataPin.port; + Device::KeyPad::touchData_Pin = kTouchDataPin.pin; + Device::KeyPad::touchClock_Port = kTouchClockPin.port; + Device::KeyPad::touchClock_Pin = kTouchClockPin.pin; + + for (size_t i = 0; i < kTouchbarEntries; ++i) + { Device::KeyPad::touchbar_map[i] = kTouchbarMap[i]; } + + Device::name = kDeviceName; + Device::model = kDeviceModel; + Device::manufacturer_name = kManufacturerName; + Device::product_name = kProductName; + Device::usb_vid = kUsbVid; + Device::usb_pid = kUsbPid; +} diff --git a/OS/USB/TinyUSB/usb_desc_default.cpp b/OS/USB/TinyUSB/usb_desc_default.cpp index dc5ae5f8..758b23a0 100644 --- a/OS/USB/TinyUSB/usb_desc_default.cpp +++ b/OS/USB/TinyUSB/usb_desc_default.cpp @@ -152,7 +152,7 @@ uint8_t const desc_default_configuration[] = { TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_DEFAULT_CDC_NOTIF, 8, EPNUM_DEFAULT_CDC_OUT, EPNUM_DEFAULT_CDC_IN, CFG_TUD_CDC_RX_BUFSIZE), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval - TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_DEFAULT_HID_OUT, EPNUM_DEFAULT_HID_IN, 64, 5) + TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_DEFAULT_HID_OUT, EPNUM_DEFAULT_HID_IN, CFG_TUD_HID_EP_BUFSIZE, 5) }; //--------------------------------------------------------------------+