*
This commit is contained in:
-21
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Sergey Serb
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
-1
@@ -1 +0,0 @@
|
||||
# LFramework.CMake
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
find_program(nuget "nuget" REQUIRED)
|
||||
|
||||
|
||||
function(nugetRestore)
|
||||
execute_process(
|
||||
COMMAND "${nuget}" "restore" "-PackagesDirectory" "${CMAKE_SOURCE_DIR}/packages"
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
#nuget restore -PackagesDirectory ./packages
|
||||
endfunction()
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
|
||||
|
||||
|
||||
set(MCU_ARCH cortex-m7)
|
||||
set(MCU_FLOAT_ABI softfp)
|
||||
set(MCU_FPU fpv4-sp-d16)
|
||||
|
||||
|
||||
set(COMMON_COMPILE_FLAGS -mcpu=${MCU_ARCH} -mthumb -mfloat-abi=${MCU_FLOAT_ABI} -mfpu=${MCU_FPU})
|
||||
set(C_CXX_COMPILE_FLAGS -ffunction-sections -fdata-sections -fsigned-char -g -fmessage-length=0)
|
||||
|
||||
if(NOT (TARGET STM32::F7))
|
||||
add_library(STM32::F7 INTERFACE IMPORTED)
|
||||
|
||||
target_compile_options(STM32::F7 INTERFACE
|
||||
--sysroot="${TOOLCHAIN_SYSROOT}"
|
||||
${COMMON_COMPILE_FLAGS}
|
||||
)
|
||||
|
||||
#target_compile_options(STM32::F7 INTERFACE $<$<COMPILE_LANGUAGE:ASM>:-x assembler-with-cpp>)
|
||||
target_compile_options(STM32::F7 INTERFACE $<$<COMPILE_LANGUAGE:C>:${C_CXX_COMPILE_FLAGS}>)
|
||||
target_compile_options(STM32::F7 INTERFACE $<$<COMPILE_LANGUAGE:CXX>:${C_CXX_COMPILE_FLAGS}>)
|
||||
target_compile_options(STM32::F7 INTERFACE $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions -fno-rtti -fno-use-cxa-atexit -fno-threadsafe-statics>)
|
||||
|
||||
target_link_options(STM32::F7 INTERFACE
|
||||
--sysroot="${TOOLCHAIN_SYSROOT}"
|
||||
${COMMON_COMPILE_FLAGS}
|
||||
${C_CXX_COMPILE_FLAGS}
|
||||
LINKER:-gc-sections
|
||||
)
|
||||
|
||||
|
||||
target_link_options(STM32::F7 INTERFACE $<$<CONFIG:RELEASE>:LINKER:--undefined=vTaskSwitchContext,--undefined=HardFault_HandlerC,-undefined=_realloc_r>)
|
||||
|
||||
target_compile_definitions(STM32::F7 INTERFACE
|
||||
STM32F7
|
||||
"__weak=__attribute__((weak))"
|
||||
"__packed=__attribute__((__packed__))"
|
||||
)
|
||||
endif()
|
||||
@@ -1,25 +0,0 @@
|
||||
add_library(Stm32CmsisCore INTERFACE)
|
||||
|
||||
target_include_directories(Stm32CmsisCore
|
||||
INTERFACE
|
||||
${STM32_CMSIS_CORE_SOURCE_DIR}/Core/Include
|
||||
${STM32_CMSIS_CORE_SOURCE_DIR}/RTOS2/Include
|
||||
)
|
||||
|
||||
|
||||
file(GLOB_RECURSE Stm32CmsisCore_HEADERS "${STM32_CMSIS_CORE_SOURCE_DIR}/Core/Include/*.h" "${STM32_CMSIS_CORE_SOURCE_DIR}/RTOS2/Include/*.h")
|
||||
#file(GLOB_RECURSE cmsis_device_f7_SOURCES1 "${cmsis_device_f7_SOURCE_DIR}/Src/**/*.c")
|
||||
|
||||
target_sources(Stm32CmsisCore
|
||||
INTERFACE
|
||||
${Stm32CmsisCore_HEADERS1}
|
||||
)
|
||||
|
||||
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Stm32CmsisCore
|
||||
REQUIRED_VARS
|
||||
Stm32CmsisCore_HEADERS
|
||||
#Stm32CmsisCore_SOURCES
|
||||
)
|
||||
@@ -1,33 +0,0 @@
|
||||
add_library(Stm32CmsisDevice INTERFACE)
|
||||
|
||||
target_include_directories(Stm32CmsisDevice
|
||||
INTERFACE
|
||||
${STM32_CMSIS_DEVICE_SOURCE_DIR}/Include
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE Stm32CmsisDevice_HEADERS "${STM32_CMSIS_DEVICE_SOURCE_DIR}/Include/*.h")
|
||||
|
||||
set(Stm32CmsisDevice_SOURCES
|
||||
${STM32_CMSIS_DEVICE_SOURCE_DIR}/Source/Templates/system_stm32f7xx.c
|
||||
${STM32_CMSIS_DEVICE_SOURCE_DIR}/Source/Templates/gcc/startup_stm32f746xx.s
|
||||
)
|
||||
|
||||
target_compile_definitions(Stm32CmsisDevice
|
||||
INTERFACE
|
||||
STM32${MCU_FAMILY}${MCU_CORE}${MCU_LINE}xx
|
||||
)
|
||||
|
||||
|
||||
target_sources(Stm32CmsisDevice
|
||||
INTERFACE
|
||||
${Stm32CmsisDevice_HEADERS}
|
||||
${Stm32CmsisDevice_SOURCES}
|
||||
)
|
||||
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Stm32CmsisDevice
|
||||
REQUIRED_VARS
|
||||
Stm32CmsisDevice_HEADERS
|
||||
Stm32CmsisDevice_SOURCES
|
||||
)
|
||||
@@ -1,37 +0,0 @@
|
||||
add_library(Stm32FreeRtos INTERFACE)
|
||||
|
||||
target_include_directories(Stm32FreeRtos
|
||||
INTERFACE
|
||||
${STM32_FREERTOS_SOURCE_DIR}/Source
|
||||
${STM32_FREERTOS_SOURCE_DIR}/Source/include
|
||||
#${STM32_FREERTOS_SOURCE_DIR}/Source/CMSIS_RTOS_V2
|
||||
${STM32_FREERTOS_SOURCE_DIR}/Source/portable/GCC/ARM_CM7/r0p1
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE Stm32FreeRtos_HEADERS
|
||||
#"${STM32_FREERTOS_SOURCE_DIR}/Source/CMSIS_RTOS_V2/*.h"
|
||||
"${STM32_FREERTOS_SOURCE_DIR}/Source/include/**/*.h"
|
||||
"${STM32_FREERTOS_SOURCE_DIR}/Source/portable/GCC/ARM_CM7/*.h"
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE Stm32FreeRtos_SOURCES
|
||||
#"${STM32_FREERTOS_SOURCE_DIR}/Source/CMSIS_RTOS_V2/*.c"
|
||||
"${STM32_FREERTOS_SOURCE_DIR}/Source/portable/GCC/ARM_CM7/*.c"
|
||||
)
|
||||
|
||||
file(GLOB Stm32FreeRtos_SOURCES2 "${STM32_FREERTOS_SOURCE_DIR}/Source/*.c")
|
||||
list(APPEND Stm32FreeRtos_SOURCES ${Stm32FreeRtos_SOURCES2} ${STM32_FREERTOS_SOURCE_DIR}/Source/portable/MemMang/heap_4.c)
|
||||
|
||||
target_sources(Stm32FreeRtos
|
||||
INTERFACE
|
||||
${Stm32FreeRtos_HEADERS}
|
||||
${Stm32FreeRtos_SOURCES}
|
||||
)
|
||||
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Stm32FreeRtos
|
||||
REQUIRED_VARS
|
||||
Stm32FreeRtos_HEADERS
|
||||
Stm32FreeRtos_SOURCES
|
||||
)
|
||||
@@ -1,25 +0,0 @@
|
||||
add_library(Stm32Hal INTERFACE)
|
||||
|
||||
target_include_directories(Stm32Hal
|
||||
INTERFACE
|
||||
${STM32_HAL_SOURCE_DIR}/Inc
|
||||
${STM32_HAL_SOURCE_DIR}/Inc/Legacy
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE Stm32Hal_HEADERS "${STM32_HAL_SOURCE_DIR}/Inc/*.h")
|
||||
file(GLOB_RECURSE Stm32Hal_SOURCES "${STM32_HAL_SOURCE_DIR}/Src/*.c")
|
||||
list(FILTER Stm32Hal_SOURCES EXCLUDE REGEX ".*_template.c$")
|
||||
|
||||
target_sources(Stm32Hal
|
||||
INTERFACE
|
||||
${Stm32Hal_HEADERS}
|
||||
${Stm32Hal_SOURCES}
|
||||
)
|
||||
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Stm32Hal
|
||||
REQUIRED_VARS
|
||||
Stm32Hal_HEADERS
|
||||
Stm32Hal_SOURCES
|
||||
)
|
||||
@@ -1,25 +0,0 @@
|
||||
add_library(Stm32UsbDevice INTERFACE)
|
||||
|
||||
target_include_directories(Stm32UsbDevice
|
||||
INTERFACE
|
||||
${STM32_USB_DEVICE_SOURCE_DIR}/Core/Inc
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE Stm32UsbDevice_HEADERS "${STM32_USB_DEVICE_SOURCE_DIR}/Core/Inc/*.h")
|
||||
file(GLOB_RECURSE Stm32UsbDevice_SOURCES "${STM32_USB_DEVICE_SOURCE_DIR}/Core/Src/*.c")
|
||||
list(FILTER Stm32UsbDevice_SOURCES EXCLUDE REGEX ".*_template.c$")
|
||||
list(FILTER Stm32UsbDevice_HEADERS EXCLUDE REGEX ".*_template.h$")
|
||||
|
||||
target_sources(Stm32UsbDevice
|
||||
INTERFACE
|
||||
${Stm32UsbDevice_HEADERS}
|
||||
${Stm32UsbDevice_SOURCES}
|
||||
)
|
||||
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Stm32UsbDevice
|
||||
REQUIRED_VARS
|
||||
Stm32UsbDevice_HEADERS
|
||||
Stm32UsbDevice_SOURCES
|
||||
)
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
|
||||
set(MCU_ARCH cortex-m7)
|
||||
set(MCU_FLOAT_ABI hard)
|
||||
set(MCU_FPU fpv5-d16)
|
||||
|
||||
|
||||
set(COMMON_COMPILE_FLAGS -mcpu=${MCU_ARCH} -mthumb -mfloat-abi=${MCU_FLOAT_ABI} -mfpu=${MCU_FPU})
|
||||
set(C_CXX_COMPILE_FLAGS -ffunction-sections -fdata-sections -fsigned-char -g -fmessage-length=0)
|
||||
|
||||
if(NOT (TARGET STM32::H7))
|
||||
add_library(STM32::H7 INTERFACE IMPORTED)
|
||||
|
||||
target_compile_options(STM32::H7 INTERFACE
|
||||
--sysroot="${TOOLCHAIN_SYSROOT}"
|
||||
${COMMON_COMPILE_FLAGS}
|
||||
)
|
||||
|
||||
#target_compile_options(STM32::H7 INTERFACE $<$<COMPILE_LANGUAGE:ASM>:-x assembler-with-cpp>)
|
||||
target_compile_options(STM32::H7 INTERFACE $<$<COMPILE_LANGUAGE:C>:${C_CXX_COMPILE_FLAGS}>)
|
||||
target_compile_options(STM32::H7 INTERFACE $<$<COMPILE_LANGUAGE:CXX>:${C_CXX_COMPILE_FLAGS}>)
|
||||
target_compile_options(STM32::H7 INTERFACE $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions -fno-rtti -fno-use-cxa-atexit -fno-threadsafe-statics>)
|
||||
|
||||
target_link_options(STM32::H7 INTERFACE
|
||||
--sysroot="${TOOLCHAIN_SYSROOT}"
|
||||
${COMMON_COMPILE_FLAGS}
|
||||
${C_CXX_COMPILE_FLAGS}
|
||||
LINKER:-gc-sections
|
||||
)
|
||||
|
||||
|
||||
target_link_options(STM32::H7 INTERFACE $<$<CONFIG:RELEASE>:LINKER:--undefined=vTaskSwitchContext,--undefined=HardFault_HandlerC,-undefined=_realloc_r>)
|
||||
|
||||
target_compile_definitions(STM32::H7 INTERFACE
|
||||
STM32H7
|
||||
"__weak=__attribute__((weak))"
|
||||
"__packed=__attribute__((__packed__))"
|
||||
)
|
||||
endif()
|
||||
-152
@@ -1,152 +0,0 @@
|
||||
if (DEFINED STM32_DEVICE AND NOT STM32_DEVICE STREQUAL "")
|
||||
string(REGEX MATCH "STM(32|8)(F|L|H|W|U)([0-9])([^A-Z]+)([A-Z])(.)" STM32_DEVICE_ ${STM32_DEVICE}])
|
||||
set(MCU_FAMILY ${CMAKE_MATCH_2})
|
||||
set(MCU_CORE ${CMAKE_MATCH_3})
|
||||
set(MCU_LINE ${CMAKE_MATCH_4})
|
||||
|
||||
message("MCU_FAMILY: ${MCU_FAMILY}")
|
||||
message("MCU_CORE: ${MCU_CORE}")
|
||||
message("MCU_LINE: ${MCU_LINE}")
|
||||
|
||||
set(STM32_FAMILY_EX "${MCU_FAMILY}${MCU_CORE}" )
|
||||
|
||||
message("STM32_FAMILY_EX: ${STM32_FAMILY_EX}")
|
||||
else()
|
||||
message("STM32_DEVICE not defined")
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
set(STM32_FAMILIES F7 )
|
||||
set(STM32_HAL_DEFAULT_VERSION v1.3.0 )
|
||||
set(STM32_FREERTOS_DEFAULT_VERSION v10.5.1 )
|
||||
set(STM32_CMSIS_DEVICE_DEFAULT_VERSION v1.2.8 )
|
||||
|
||||
set(STM32_CMSIS_CORE_DEFAULT_VERSION v5.6.0 )
|
||||
|
||||
set(STM32_USB_DEVICE_DEFAULT_VERSION v2.11.2 )
|
||||
set(STM32_USB_HOST_DEFAULT_VERSION v3.5.1 )
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(stm32_usb_host
|
||||
GIT_REPOSITORY https://github.com/STMicroelectronics/stm32_mw_usb_host.git
|
||||
GIT_TAG ${STM32_USB_HOST_DEFAULT_VERSION}
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
|
||||
FetchContent_Declare(stm32_usb_device
|
||||
GIT_REPOSITORY https://github.com/STMicroelectronics/stm32_mw_usb_device.git
|
||||
GIT_TAG ${STM32_USB_DEVICE_DEFAULT_VERSION}
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
|
||||
function(FetchStm32UsbDevice)
|
||||
string(TOLOWER ${STM32_FAMILY_EX} STM32_FAMILY_EX_LOWER_CASE)
|
||||
FetchContent_MakeAvailable(stm32_usb_device)
|
||||
set(STM32_USB_DEVICE_SOURCE_DIR ${stm32_usb_device_SOURCE_DIR} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(FetchStm32UsbHost)
|
||||
string(TOLOWER ${STM32_FAMILY_EX} STM32_FAMILY_EX_LOWER_CASE)
|
||||
FetchContent_MakeAvailable(stm32_usb_host)
|
||||
set(STM32_USB_HOST_SOURCE_DIR ${stm32_usb_host_SOURCE_DIR} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
||||
|
||||
FetchContent_Declare(stm32_cmsis_core
|
||||
GIT_REPOSITORY https://github.com/STMicroelectronics/cmsis_core.git
|
||||
GIT_TAG ${STM32_CMSIS_CORE_DEFAULT_VERSION}
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
|
||||
|
||||
set(ARRAY_INDEX 0)
|
||||
foreach(FAMILY ${STM32_FAMILIES})
|
||||
string(TOLOWER ${FAMILY} STM_FAMILY_LOWER_CASE)
|
||||
|
||||
if (DEFINED STM32_HAL_VERSION AND NOT STM32_HAL_VERSION STREQUAL "")
|
||||
|
||||
else()
|
||||
list(GET STM32_HAL_DEFAULT_VERSION ${ARRAY_INDEX} STM32_HAL_VERSION)
|
||||
endif()
|
||||
message("STM32_HAL_VERSION: ${STM32_HAL_VERSION}")
|
||||
|
||||
if (DEFINED STM32_FREERTOS_VERSION AND NOT STM32_FREERTOS_VERSION STREQUAL "")
|
||||
|
||||
else()
|
||||
list(GET STM32_FREERTOS_DEFAULT_VERSION ${ARRAY_INDEX} STM32_FREERTOS_VERSION)
|
||||
endif()
|
||||
message("STM32_FREERTOS_VERSION: ${STM32_FREERTOS_VERSION}")
|
||||
|
||||
|
||||
if (DEFINED STM32_CMSIS_DEVICE_VERSION AND NOT STM32_CMSIS_DEVICE_VERSION STREQUAL "")
|
||||
|
||||
else()
|
||||
list(GET STM32_CMSIS_DEVICE_DEFAULT_VERSION ${ARRAY_INDEX} STM32_CMSIS_DEVICE_VERSION)
|
||||
endif()
|
||||
message("STM32_CMSIS_DEVICE_VERSION: ${STM32_CMSIS_DEVICE_VERSION}")
|
||||
|
||||
#CMSIS Device
|
||||
FetchContent_Declare(stm32_cmsis_device_${STM_FAMILY_LOWER_CASE}
|
||||
GIT_REPOSITORY https://github.com/STMicroelectronics/cmsis_device_${STM_FAMILY_LOWER_CASE}.git
|
||||
GIT_TAG ${STM32_CMSIS_DEVICE_VERSION}
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
|
||||
#Hal
|
||||
FetchContent_Declare(stm32_hal_${STM_FAMILY_LOWER_CASE}
|
||||
GIT_REPOSITORY https://github.com/STMicroelectronics/stm32${STM_FAMILY_LOWER_CASE}xx_hal_driver.git
|
||||
GIT_TAG ${STM32_HAL_VERSION}
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
|
||||
#FreeRTOS
|
||||
FetchContent_Declare(stm32_freertos
|
||||
GIT_REPOSITORY https://github.com/STMicroelectronics/stm32_mw_freertos.git
|
||||
GIT_TAG ${STM32_FREERTOS_VERSION}
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
|
||||
math(EXPR ARRAY_INDEX "${ARRAY_INDEX} + 1")
|
||||
endforeach()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function(FetchStm32Hal)
|
||||
string(TOLOWER ${STM32_FAMILY_EX} STM32_FAMILY_EX_LOWER_CASE)
|
||||
FetchContent_MakeAvailable(stm32_hal_${STM32_FAMILY_EX_LOWER_CASE} )
|
||||
set(STM32_HAL_SOURCE_DIR ${stm32_hal_${STM32_FAMILY_EX_LOWER_CASE}_SOURCE_DIR} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(FetchStm32FreeRtos)
|
||||
FetchContent_MakeAvailable(stm32_freertos)
|
||||
set(STM32_FREERTOS_SOURCE_DIR ${stm32_freertos_SOURCE_DIR} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(FetchStm32CmsisDevice)
|
||||
string(TOLOWER ${STM32_FAMILY_EX} STM32_FAMILY_EX_LOWER_CASE)
|
||||
FetchContent_MakeAvailable(stm32_cmsis_device_${STM32_FAMILY_EX})
|
||||
set(STM32_CMSIS_DEVICE_SOURCE_DIR ${stm32_cmsis_device_${STM32_FAMILY_EX_LOWER_CASE}_SOURCE_DIR} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(FetchStm32CmsisCore)
|
||||
FetchContent_MakeAvailable(STM32_CMSIS_CORE)
|
||||
set(STM32_CMSIS_CORE_SOURCE_DIR ${stm32_cmsis_core_SOURCE_DIR} PARENT_SCOPE)
|
||||
endfunction()
|
||||
-110
@@ -1,110 +0,0 @@
|
||||
if(NOT DEFINED TOOLCHAIN_DIR)
|
||||
if(CMAKE_HOST_UNIX)
|
||||
file(GLOB TOOLCHAIN_DIRS "/usr/local/gcc-arm-none-eabi-*")
|
||||
else()
|
||||
file(GLOB TOOLCHAIN_DIRS "C:/Program Files (x86)/GNU Arm Embedded Toolchain/*" "C:/Program Files (x86)/Arm GNU Toolchain arm-none-eabi/*")
|
||||
endif()
|
||||
|
||||
if(TOOLCHAIN_DIRS)
|
||||
list(GET TOOLCHAIN_DIRS 0 TOOLCHAIN_DIR)
|
||||
message("FOUND ARM GCC Toolchain Directory: ${TOOLCHAIN_DIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
GET_FILENAME_COMPONENT(STM32_CMAKE_DIR ${CMAKE_CURRENT_LIST_FILE} DIRECTORY)
|
||||
list(APPEND CMAKE_MODULE_PATH ${STM32_CMAKE_DIR})
|
||||
|
||||
set(EXE_SUFFIX "")
|
||||
|
||||
set(CMAKE_LIBRARY_ARCHITECTURE arm-none-eabi)
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||
set(CMAKE_SYSTEM_VERSION 1)
|
||||
|
||||
|
||||
set(TOOLCHAIN_PREFIX "${CMAKE_LIBRARY_ARCHITECTURE}-")
|
||||
set(TOOLCHAIN_BIN_PATH "${TOOLCHAIN_DIR}/bin")
|
||||
set(TOOLCHAIN_INC_PATH "${TOOLCHAIN_DIR}/${CMAKE_LIBRARY_ARCHITECTURE}/include")
|
||||
set(TOOLCHAIN_LIB_PATH "${TOOLCHAIN_DIR}/${CMAKE_LIBRARY_ARCHITECTURE}/lib")
|
||||
set(TOOLCHAIN_SYSROOT "${TOOLCHAIN_DIR}/${CMAKE_LIBRARY_ARCHITECTURE}")
|
||||
|
||||
|
||||
|
||||
|
||||
find_program(CMAKE_C_COMPILER NAMES ${TOOLCHAIN_PREFIX}gcc HINTS ${TOOLCHAIN_BIN_PATH})
|
||||
find_program(CMAKE_CXX_COMPILER NAMES ${TOOLCHAIN_PREFIX}g++ HINTS ${TOOLCHAIN_BIN_PATH})
|
||||
find_program(CMAKE_ASM_COMPILER NAMES ${TOOLCHAIN_PREFIX}gcc HINTS ${TOOLCHAIN_BIN_PATH})
|
||||
find_program(CMAKE_CPPFILT NAMES ${TOOLCHAIN_PREFIX}c++filt HINTS ${TOOLCHAIN_BIN_PATH})
|
||||
find_program(CMAKE_DEBUGGER NAMES ${TOOLCHAIN_PREFIX}gdb HINTS ${TOOLCHAIN_BIN_PATH})
|
||||
find_program(CMAKE_OBJCOPY NAMES ${TOOLCHAIN_PREFIX}objcopy HINTS ${TOOLCHAIN_BIN_PATH})
|
||||
find_program(CMAKE_OBJDUMP NAMES ${TOOLCHAIN_PREFIX}objdump HINTS ${TOOLCHAIN_BIN_PATH})
|
||||
find_program(CMAKE_SIZE NAMES ${TOOLCHAIN_PREFIX}size HINTS ${TOOLCHAIN_BIN_PATH})
|
||||
find_program(CMAKE_AS NAMES ${TOOLCHAIN_PREFIX}as HINTS ${TOOLCHAIN_BIN_PATH})
|
||||
find_program(CMAKE_AR NAMES ${TOOLCHAIN_PREFIX}ar HINTS ${TOOLCHAIN_BIN_PATH})
|
||||
|
||||
|
||||
set(CMAKE_EXECUTABLE_SUFFIX_C .elf)
|
||||
set(CMAKE_EXECUTABLE_SUFFIX_CXX .elf)
|
||||
set(CMAKE_EXECUTABLE_SUFFIX_ASM .elf)
|
||||
|
||||
|
||||
|
||||
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
|
||||
|
||||
|
||||
#set(COMMON_FLAGS "-mcpu=${MCU_ARCH} -mthumb -mfloat-abi=${MCU_FLOAT_ABI} -mfpu=${MCU_FPU} -ffunction-sections -fdata-sections -fsigned-char -g -fmessage-length=0 -D__weak=__attribute__((weak)) -D__packed=__attribute__((__packed__))")
|
||||
#
|
||||
#set(CMAKE_CXX_FLAGS "${COMMON_FLAGS} -std=c++17 -fno-exceptions -fno-rtti -fno-use-cxa-atexit -fno-threadsafe-statics" CACHE INTERNAL "cxx compiler flags")
|
||||
#set(CMAKE_C_FLAGS "${COMMON_FLAGS} -std=c11" CACHE INTERNAL "c compiler flags")
|
||||
#
|
||||
#set(CMAKE_EXE_LINKER_FLAGS "-Wl,-gc-sections -specs=nosys.specs -specs=nano.specs" CACHE INTERNAL "exe compiler flags")
|
||||
#SET(CMAKE_ASM_FLAGS "-mthumb -mcpu=${MCU_ARCH} -mfpu=${MCU_FPU} -mfloat-abi=${MCU_FLOAT_ABI} -x assembler-with-cpp" CACHE INTERNAL "asm compiler flags")
|
||||
#
|
||||
#
|
||||
#include(fetch_utils)
|
||||
|
||||
|
||||
|
||||
if(NOT (TARGET GCC::Specs::NoSys))
|
||||
add_library(GCC::Specs::NoSys INTERFACE IMPORTED)
|
||||
target_link_options(GCC::Specs::NoSys INTERFACE
|
||||
-specs=nosys.specs
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT (TARGET GCC::Specs::Nano))
|
||||
add_library(GCC::Specs::Nano INTERFACE IMPORTED)
|
||||
target_link_options(GCC::Specs::Nano INTERFACE
|
||||
-specs=nano.specs
|
||||
)
|
||||
endif()
|
||||
|
||||
function(gcc_add_linker_script TARGET VISIBILITY SCRIPT_PATH)
|
||||
get_filename_component(SCRIPT_PATH "${SCRIPT_PATH}" ABSOLUTE)
|
||||
target_link_options(${TARGET} ${VISIBILITY} -T "${SCRIPT_PATH}")
|
||||
endfunction()
|
||||
|
||||
function(gcc_generate_bin_file TargetName)
|
||||
add_custom_command(
|
||||
TARGET ${TargetName}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Generating flash image ${TargetName}.bin"
|
||||
COMMAND ${CMAKE_OBJCOPY} -O binary ${TargetName}${CMAKE_EXECUTABLE_SUFFIX_C} ${TargetName}.bin
|
||||
BYPRODUCTS ${TargetName}.bin
|
||||
)
|
||||
endfunction()
|
||||
|
||||
|
||||
|
||||
function(gcc_print_target_size TargetName)
|
||||
add_custom_command(
|
||||
TARGET ${TargetName}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Invoking: GCC Print Size"
|
||||
COMMAND ${CMAKE_SIZE} ${TargetName}${CMAKE_EXECUTABLE_SUFFIX_C}
|
||||
)
|
||||
endfunction()
|
||||
@@ -1,32 +0,0 @@
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
add_library(LFramework INTERFACE)
|
||||
target_include_directories(LFramework INTERFACE "Src")
|
||||
add_subdirectory(Src/LFramework)
|
||||
Vendored
-21
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Sergey Serb
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
Vendored
-2
@@ -1,2 +0,0 @@
|
||||
# LFramework
|
||||
C++ general purpose library for my projects
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Debug.h"
|
||||
#include "IO/Terminal/Terminal.h"
|
||||
|
||||
namespace LFramework::Debug {
|
||||
class Assert : public LogWriter {
|
||||
public:
|
||||
Assert():LogWriter(LogLevel::Fatal){}
|
||||
~Assert(){
|
||||
for(;;);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#define lfAssert(expression) \
|
||||
do { \
|
||||
if(!(expression)) { \
|
||||
LFramework::Debug::Assert() \
|
||||
<< "Assert: " << #expression << LFramework::Terminal::NewLine \
|
||||
<< "File: " << __FILE__ << LFramework::Terminal::NewLine; \
|
||||
} \
|
||||
}while(false)
|
||||
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* BitField.h
|
||||
*
|
||||
* Created on: 14 sept. 2017 ã.
|
||||
* Author: l-pro
|
||||
*/
|
||||
|
||||
#ifndef LFRAMEWORK_BITFIELD_H_
|
||||
#define LFRAMEWORK_BITFIELD_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
|
||||
namespace LFramework {
|
||||
|
||||
template<typename TBase, typename T>
|
||||
struct BitFieldValueConverter {
|
||||
static TBase toBase(T value) {
|
||||
return static_cast<TBase>(value);
|
||||
}
|
||||
static T fromBase(TBase value) {
|
||||
return static_cast<T>(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename TBase, size_t BitOffset, size_t BitCount = 1, typename T = TBase, typename Converter = BitFieldValueConverter<TBase, T>>
|
||||
struct BitFieldMember {
|
||||
static constexpr size_t FieldBitsCount = BitCount;
|
||||
static constexpr size_t TBitsCount = std::numeric_limits<unsigned char>::digits * sizeof(T);
|
||||
static_assert(std::numeric_limits<unsigned char>::digits == 8, "Only systems with 8 bit chars are supported for now");
|
||||
static_assert(std::is_standard_layout_v<TBase>, "Only standard layout types supported in unions (and so in BitFieldMember) without UB");
|
||||
static_assert(BitOffset + BitCount <= TBitsCount, "Base type bits overflow");
|
||||
|
||||
TBase baseValue;
|
||||
|
||||
static constexpr TBase LowMask = (static_cast<TBase>((~(TBase{ 0 }))) >> (TBitsCount - BitCount));
|
||||
static constexpr TBase HiMask = TBase(LowMask << BitOffset);
|
||||
|
||||
template<typename TR = T, typename = std::enable_if_t<!std::is_same_v<TR, TBase>>>
|
||||
volatile BitFieldMember& operator =(TR value) volatile {
|
||||
baseValue = assign(baseValue, Converter::toBase(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename TR = TBase>
|
||||
constexpr BitFieldMember& operator =(TR value) {
|
||||
if constexpr(std::is_same_v<TR, TBase>){
|
||||
baseValue = assign(baseValue, value);
|
||||
}else{
|
||||
baseValue = assign(baseValue, Converter::toBase(value));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr operator T() const {
|
||||
return Converter::fromBase((baseValue >> BitOffset) & LowMask);
|
||||
}
|
||||
static constexpr inline TBase assign(TBase left, TBase right) {
|
||||
return (left & ~(HiMask)) | ((right & LowMask) << BitOffset);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static_assert(std::is_standard_layout_v<BitFieldMember<uint32_t, 0, 1>>, "Only standard layout types supported in unions (and so in BitFieldMember) without UB");
|
||||
|
||||
}
|
||||
|
||||
#endif /* LFRAMEWORK_BITFIELD_H_ */
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* BitFieldTest.cpp
|
||||
*
|
||||
* Created on: 14 ñåíò. 2017 ã.
|
||||
* Author: l-pro
|
||||
*/
|
||||
|
||||
#include "UnitTest/UnitTest.h"
|
||||
#include "BitField.h"
|
||||
|
||||
using namespace LFramework;
|
||||
|
||||
union Test8BitField {
|
||||
constexpr Test8BitField():value(0){}
|
||||
uint8_t value;
|
||||
BitFieldMember<uint8_t, 0, 1> bit_0_1;
|
||||
BitFieldMember<uint8_t, 1, 3> bit_1_3;
|
||||
BitFieldMember<uint8_t, 4, 4> bit_4_4;
|
||||
};
|
||||
|
||||
TEST(BitField_8bit){
|
||||
Test8BitField bitfield;
|
||||
TEST_TRUE(bitfield.value == 0);
|
||||
|
||||
bitfield.bit_0_1 = 1;
|
||||
TEST_TRUE(bitfield.value == 1);
|
||||
TEST_TRUE(bitfield.bit_0_1 == 1);
|
||||
|
||||
bitfield.bit_1_3 = 4;
|
||||
TEST_TRUE(bitfield.bit_1_3 == 4);
|
||||
TEST_TRUE(bitfield.value == 9);
|
||||
bitfield.bit_1_3 = 0;
|
||||
TEST_TRUE(bitfield.value == 1);
|
||||
|
||||
bitfield.bit_4_4 = 1;
|
||||
TEST_TRUE(bitfield.value == 17);
|
||||
|
||||
bitfield.bit_4_4 = 15;
|
||||
TEST_TRUE(bitfield.value == 241);
|
||||
|
||||
bitfield.bit_1_3 = 7;
|
||||
TEST_TRUE(bitfield.value == 0xff);
|
||||
|
||||
bitfield.bit_0_1 = 0;
|
||||
TEST_TRUE(bitfield.value == 0xfe);
|
||||
|
||||
bitfield.bit_4_4 = 0;
|
||||
TEST_TRUE(bitfield.value == 0x0e);
|
||||
|
||||
bitfield.bit_1_3 = 0;
|
||||
TEST_TRUE(bitfield.value == 0x00);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
target_sources(LFramework
|
||||
INTERFACE
|
||||
Assert.h
|
||||
BitField.h
|
||||
CMakeLists.txt
|
||||
Debug.h
|
||||
Guid.h
|
||||
GuidUtils.h
|
||||
GuidUtils.cpp
|
||||
System.h
|
||||
SystemArmCortexM.h
|
||||
SystemWindows.h
|
||||
TupleUtils.h
|
||||
#BitFieldTest.cpp
|
||||
Syscalls.cpp
|
||||
Text/Encoding.h
|
||||
|
||||
TypeTraits/FunctionTraits.h
|
||||
TypeTraits/Integral.h
|
||||
|
||||
Reflection/Reflection.h
|
||||
)
|
||||
|
||||
add_subdirectory(USB)
|
||||
add_subdirectory(UnitTest)
|
||||
add_subdirectory(Threading)
|
||||
add_subdirectory(IO)
|
||||
add_subdirectory(Input)
|
||||
#add_subdirectory(Time)
|
||||
|
||||
#add_subdirectory(MCU)
|
||||
#add_subdirectory(Macro)
|
||||
#add_subdirectory(IO)
|
||||
#add_subdirectory(Input)
|
||||
#add_subdirectory(Detect)
|
||||
#add_subdirectory(Containers)
|
||||
#add_subdirectory(COM)
|
||||
@@ -1,4 +0,0 @@
|
||||
target_sources(${PROJECT_NAME}
|
||||
INTERFACE
|
||||
ComObject.h
|
||||
)
|
||||
@@ -1,30 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ComObject.h"
|
||||
|
||||
#if defined(__CYGWIN32__)
|
||||
#define LFRAMEWORK_COM_LIBRARY_CALL __stdcall
|
||||
#define LFRAMEWORK_COM_LIBRARY_EXPORT __declspec(dllexport)
|
||||
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(WINAPI_FAMILY)
|
||||
#define LFRAMEWORK_COM_LIBRARY_CALL __stdcall
|
||||
#define LFRAMEWORK_COM_LIBRARY_EXPORT __declspec(dllexport)
|
||||
#elif defined(__MACH__)
|
||||
#define LFRAMEWORK_COM_LIBRARY_CALL
|
||||
#define LFRAMEWORK_COM_LIBRARY_EXPORT
|
||||
#elif defined(__linux__) || defined(__ANDROID__)
|
||||
#define LFRAMEWORK_COM_LIBRARY_CALL
|
||||
#define LFRAMEWORK_COM_LIBRARY_EXPORT __attribute__ ((visibility ("default")))
|
||||
#else
|
||||
#define LFRAMEWORK_COM_LIBRARY_CALL
|
||||
#define LFRAMEWORK_COM_LIBRARY_EXPORT
|
||||
#endif
|
||||
|
||||
namespace LFramework {
|
||||
|
||||
#define LFRAMEWORK_COM_LIBRARY_EXPORT_ENTRY_FUNCTION() \
|
||||
extern "C" LFRAMEWORK_COM_LIBRARY_EXPORT void LFRAMEWORK_COM_LIBRARY_CALL getInterface(LFramework::ComPtr<LFramework::IUnknown>& result){ \
|
||||
result = LFramework::ComPtr<ILibrary>::create<Library>(); \
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,602 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <LFramework/Detect/DetectOS.h>
|
||||
#include <LFramework/Guid.h>
|
||||
#include <LFramework/TypeTraits/FunctionTraits.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
|
||||
#if (LF_TARGET_OS == LF_OS_WINDOWS) || (LF_TARGET_OS == LF_OS_CYGWIN)
|
||||
#define LFRAMEWORK_COM_CALL __stdcall
|
||||
#else
|
||||
#define LFRAMEWORK_COM_CALL
|
||||
#endif
|
||||
|
||||
namespace LFramework {
|
||||
|
||||
using InterfaceID = Guid;
|
||||
|
||||
//IUnknown
|
||||
class IUnknown;
|
||||
|
||||
template<class TInterface, class TImplementer>
|
||||
struct InterfaceRemap {};
|
||||
|
||||
template<typename Remap>
|
||||
struct RemapTraits {
|
||||
|
||||
};
|
||||
|
||||
template<class TInterface, class TImplementer>
|
||||
struct RemapTraits<InterfaceRemap<TInterface, TImplementer>> {
|
||||
using InterfaceType = TInterface;
|
||||
using ImplementerType = TImplementer;
|
||||
};
|
||||
|
||||
template<class Interface>
|
||||
struct InterfaceAbi {};
|
||||
|
||||
|
||||
|
||||
|
||||
template<class InterfaceAbi>
|
||||
bool InterfaceAbiInterfaceSupported(const InterfaceID& id) {
|
||||
if (InterfaceAbi::ID() == id) {
|
||||
return true;
|
||||
}
|
||||
if constexpr (!std::is_same_v<typename InterfaceAbi::Base, void>) {
|
||||
return InterfaceAbiInterfaceSupported<typename InterfaceAbi::Base>(id);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
struct RemapChainItemBase {
|
||||
using InterfaceAbiInterfaceSupportedPtr = bool(*)(const InterfaceID&);
|
||||
RemapChainItemBase* next = nullptr;
|
||||
InterfaceAbiInterfaceSupportedPtr isSupported = nullptr;
|
||||
void* getRemapPtr() {
|
||||
return reinterpret_cast<std::uint8_t*>(&isSupported) + sizeof(isSupported);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename TRemap>
|
||||
struct RemapChainItem : RemapChainItemBase {
|
||||
RemapChainItem(typename RemapTraits<TRemap>::ImplementerType* implementer) {
|
||||
remap._implementer = implementer;
|
||||
this->isSupported = &InterfaceAbiInterfaceSupported<InterfaceAbi<typename RemapTraits<TRemap>::InterfaceType>>;
|
||||
implementer->registerRemap(this);
|
||||
}
|
||||
TRemap remap;
|
||||
};
|
||||
|
||||
template<class Implementer, class FirstInterface, class ... Interfaces>
|
||||
struct ComRemapList : ComRemapList<Implementer, Interfaces...> {
|
||||
using Base = ComRemapList<Implementer, Interfaces...>;
|
||||
ComRemapList(Implementer* _this) : Base(_this), remapContainer{ _this } {}
|
||||
RemapChainItem<InterfaceRemap<FirstInterface, Implementer>> remapContainer;
|
||||
};
|
||||
|
||||
template<class Implementer, class FirstInterface>
|
||||
struct ComRemapList<Implementer, FirstInterface> {
|
||||
ComRemapList(Implementer* _this) : remapContainer{ _this } {}
|
||||
RemapChainItem<InterfaceRemap<FirstInterface, Implementer>> remapContainer;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct IsInterface : std::conditional_t<std::is_base_of_v<InterfaceAbi<IUnknown>, InterfaceAbi<T>>, std::true_type, std::false_type> {};
|
||||
|
||||
template<class...T>
|
||||
struct IsAllInterfaces : std::conjunction<IsInterface<T>...> {};
|
||||
|
||||
template<class TImplementer, class TBase, class ... TInterfaceList>
|
||||
struct ComImplement : public TBase {
|
||||
using ComImplement_BaseType = TBase;
|
||||
using ComImplement_SelfType = ComImplement;
|
||||
using Implementer = TImplementer;
|
||||
ComRemapList<TImplementer, TInterfaceList...> _remaps = { reinterpret_cast<TImplementer*>(this) };
|
||||
};
|
||||
|
||||
|
||||
template<class T, class = void>
|
||||
struct IsComImplement : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct IsComImplement<T, std::void_t<typename T::ComImplement_SelfType>> : std::true_type {};
|
||||
|
||||
template<class...T>
|
||||
struct IsAllComImplement : std::conjunction<IsComImplement<T>...> {};
|
||||
|
||||
template<class TInterface, class ... TInterfaceList>
|
||||
struct HasInterface : std::disjunction<std::is_base_of<InterfaceAbi<TInterface>, InterfaceAbi<TInterfaceList>>...> {};
|
||||
|
||||
template<class TImplementer, class TInterface>
|
||||
class ComDelegate;
|
||||
|
||||
|
||||
template<class T>
|
||||
struct IsComDelegate : std::false_type {};
|
||||
|
||||
template<class TImplementer, class TInterface>
|
||||
struct IsComDelegate<ComDelegate<TImplementer, TInterface>> : std::true_type {};
|
||||
|
||||
|
||||
enum class Result : uint32_t {
|
||||
Ok = 0,
|
||||
NotImplemented = 0x80004001L,
|
||||
NoInterface = 0x80004002L,
|
||||
ErrorPointer = 0x80004003L,
|
||||
UnknownFailure = 0x80004005L,
|
||||
OutOfMemory = 0x8007000EL,
|
||||
InvalidArg = 0x80070057L,
|
||||
Pending = 0x8000000AL,
|
||||
AsyncOperationNotStarted = 0x80000019L,
|
||||
RpcTimeout = 0x8001011FL,
|
||||
RpcDisconnected = 0x80010108L
|
||||
};
|
||||
|
||||
struct ComException : std::exception {
|
||||
ComException(Result code) : _errorCode(code) {
|
||||
|
||||
}
|
||||
ComException() : ComException(Result::UnknownFailure) {
|
||||
|
||||
}
|
||||
ComException(Result code, std::string message) :_errorCode(code), _message(std::move(message)) {
|
||||
|
||||
}
|
||||
ComException(std::string message) : ComException(Result::UnknownFailure, std::move(message)) {
|
||||
|
||||
}
|
||||
Result code() const {
|
||||
return _errorCode;
|
||||
}
|
||||
char const* what() const noexcept override {
|
||||
return _message.c_str();
|
||||
}
|
||||
const std::string& message() const {
|
||||
return _message;
|
||||
}
|
||||
private:
|
||||
Result _errorCode;
|
||||
std::string _message;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct InterfaceAbi<IUnknown> {
|
||||
public:
|
||||
using Base = void;
|
||||
static constexpr InterfaceID ID() { return { 0x00000000, 0x0000000, 0x000000C0, 0x46000000 }; }
|
||||
template<class TInterface>
|
||||
friend class ComPtr;
|
||||
friend class ComObject;
|
||||
virtual Result LFRAMEWORK_COM_CALL queryInterface(const InterfaceID& riid, void** ppvObject) = 0;
|
||||
virtual std::uint32_t LFRAMEWORK_COM_CALL addRef() = 0;
|
||||
virtual std::uint32_t LFRAMEWORK_COM_CALL release() = 0;
|
||||
~InterfaceAbi() = delete;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename TInterface>
|
||||
static constexpr InterfaceID getInterfaceId() {
|
||||
return InterfaceAbi<TInterface>::ID();
|
||||
}
|
||||
|
||||
|
||||
template<class TImplementer>
|
||||
struct InterfaceRemap<IUnknown, TImplementer> {
|
||||
virtual Result LFRAMEWORK_COM_CALL queryInterface(const InterfaceID& riid, void** ppvObject) { return _implementer->queryInterface(riid, ppvObject); }
|
||||
virtual std::uint32_t LFRAMEWORK_COM_CALL addRef() { return _implementer->addRef(); }
|
||||
virtual std::uint32_t LFRAMEWORK_COM_CALL release() { return _implementer->release(); }
|
||||
inline auto implementer() {
|
||||
if constexpr (IsComDelegate<TImplementer>::value) {
|
||||
return _implementer->getImplementer();
|
||||
} else {
|
||||
return _implementer;
|
||||
}
|
||||
}
|
||||
TImplementer* _implementer;
|
||||
~InterfaceRemap() = default;
|
||||
};
|
||||
|
||||
template <class TInterface, class TComImplement>
|
||||
struct IsComImplementSupportsInterface : std::false_type {};
|
||||
|
||||
template <class TInterface, class TImplementer, class TBase, class ... TInterfaceList>
|
||||
struct IsComImplementSupportsInterface<TInterface, ComImplement<TImplementer, TBase, TInterfaceList...>> : HasInterface<TInterface, TInterfaceList...> {};
|
||||
|
||||
class RefCountedObject {
|
||||
public:
|
||||
virtual ~RefCountedObject() = default;
|
||||
std::uint32_t addRef() {
|
||||
return _refCount.fetch_add(1) + 1;
|
||||
}
|
||||
std::uint32_t release() {
|
||||
auto result = _refCount.fetch_sub(1);
|
||||
if (result == 1) {
|
||||
delete this;
|
||||
}
|
||||
return result - 1;
|
||||
}
|
||||
private:
|
||||
std::atomic<unsigned long> _refCount{};
|
||||
};
|
||||
|
||||
template<class TInterface>
|
||||
class ComPtr;
|
||||
|
||||
|
||||
class ComObject : public RefCountedObject {
|
||||
public:
|
||||
template<typename TRemap>
|
||||
friend struct RemapChainItem;
|
||||
|
||||
ComObject() {
|
||||
_headRemap.next = &_headRemap;
|
||||
}
|
||||
|
||||
template<typename TInterface>
|
||||
ComPtr<TInterface> queryInterface() {
|
||||
void* result = nullptr;
|
||||
if(queryInterface(InterfaceAbi<TInterface>::ID(), &result) == Result::Ok){
|
||||
auto abiPtr = reinterpret_cast<InterfaceAbi<TInterface>*>(result);
|
||||
ComPtr<TInterface> result;
|
||||
result.attach(abiPtr);
|
||||
return result;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Result queryInterface(const InterfaceID& riid, void** ppvObject) {
|
||||
if (ppvObject == nullptr) {
|
||||
return Result::ErrorPointer;
|
||||
}
|
||||
|
||||
findInterface(riid, ppvObject);
|
||||
|
||||
if (*ppvObject == nullptr) {
|
||||
return Result::NoInterface;
|
||||
} else {
|
||||
auto obj = (reinterpret_cast<InterfaceAbi<IUnknown>*>(*ppvObject));
|
||||
obj->addRef();
|
||||
return Result::Ok;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void findInterface(const InterfaceID& id, void** result) {
|
||||
RemapChainItemBase* current = &_headRemap;
|
||||
do {
|
||||
if (current->isSupported(id)) {
|
||||
*result = current->getRemapPtr();
|
||||
return;
|
||||
}
|
||||
current = current->next;
|
||||
} while (current != &_headRemap);
|
||||
|
||||
*result = nullptr;
|
||||
}
|
||||
void registerRemap(RemapChainItemBase* remap) {
|
||||
remap->next = _headRemap.next;
|
||||
_headRemap.next = remap;
|
||||
}
|
||||
|
||||
RemapChainItem<InterfaceRemap<IUnknown, ComObject>> _headRemap{ this };
|
||||
};
|
||||
|
||||
|
||||
template<class TImplementer, class TInterface>
|
||||
constexpr bool IsInterfaceSupported() {
|
||||
if constexpr(!LFramework::IsInterface<TInterface>::value || !IsComImplement<TImplementer>::value){
|
||||
return false;
|
||||
}else{
|
||||
if constexpr(std::is_same_v<TImplementer, ComObject> && std::is_same_v<TInterface, LFramework::IUnknown>){
|
||||
return true;
|
||||
}else{
|
||||
if constexpr (LFramework::IsComImplementSupportsInterface<TInterface, typename TImplementer::ComImplement_SelfType>::value){
|
||||
return true;
|
||||
}else{
|
||||
return IsInterfaceSupported<typename TImplementer::ComImplement_BaseType, TInterface>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class TInterface>
|
||||
class InterfaceWrapper {
|
||||
public:
|
||||
using NotSpecialized = bool;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<class TInterface, class = void>
|
||||
class HasInterfaceWrapper : public std::true_type {};
|
||||
|
||||
template<class TInterface>
|
||||
class HasInterfaceWrapper<TInterface, std::void_t<typename LFramework::InterfaceWrapper<TInterface>::NotSpecialized>> : public std::false_type {};
|
||||
|
||||
template<class TInterface>
|
||||
class ComPtr {
|
||||
public:
|
||||
using InterfacePtr = InterfaceAbi<TInterface>*;
|
||||
|
||||
using PublicInterfacePtr = std::conditional_t<HasInterfaceWrapper<TInterface>::value, InterfaceWrapper<TInterface>*, InterfacePtr>;
|
||||
|
||||
ComPtr() = default;
|
||||
|
||||
ComPtr(InterfacePtr ptr) : _interface(ptr){
|
||||
if(_interface != nullptr){
|
||||
_interface->addRef();
|
||||
}
|
||||
}
|
||||
|
||||
template<class U, class = std::enable_if_t<std::is_base_of_v<InterfaceAbi<TInterface>, InterfaceAbi<U>>>>
|
||||
ComPtr(ComPtr<U> ptr) : _interface(ptr.get()) {
|
||||
_interface->addRef();
|
||||
}
|
||||
|
||||
ComPtr(const ComPtr& ptr) : _interface(ptr.get()) {
|
||||
if(_interface != nullptr){
|
||||
_interface->addRef();
|
||||
}
|
||||
}
|
||||
|
||||
template<class U>
|
||||
ComPtr<U> queryInterface(){
|
||||
ComPtr<U> result;
|
||||
if(_interface->queryInterface(InterfaceAbi<U>::ID(), result.put()) == Result::Ok){
|
||||
return result;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
~ComPtr() {
|
||||
reset();
|
||||
}
|
||||
|
||||
PublicInterfacePtr operator ->() {
|
||||
if constexpr(HasInterfaceWrapper<TInterface>::value){
|
||||
return reinterpret_cast<PublicInterfacePtr>(&_interface);
|
||||
}else{
|
||||
return reinterpret_cast<InterfacePtr>(_interface);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<class U, class = std::enable_if_t<std::is_base_of_v<InterfaceAbi<TInterface>, InterfaceAbi<U>>>>
|
||||
operator ComPtr<U>(){
|
||||
return ComPtr<U>(_interface);
|
||||
}
|
||||
|
||||
ComPtr operator = (std::nullptr_t) {
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
ComPtr operator = (const ComPtr& other) {
|
||||
reset();
|
||||
auto ptr = other._interface;
|
||||
if (ptr != nullptr) {
|
||||
ptr->addRef();
|
||||
}
|
||||
_interface = ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool operator == (const ComPtr& other) const {
|
||||
return _interface == other._interface;
|
||||
}
|
||||
|
||||
bool operator != (const ComPtr& other) const {
|
||||
return _interface != other._interface;
|
||||
}
|
||||
bool operator == (std::nullptr_t) const {
|
||||
return _interface == nullptr;
|
||||
}
|
||||
|
||||
bool operator != (std::nullptr_t) const {
|
||||
return _interface != nullptr;
|
||||
}
|
||||
|
||||
InterfacePtr operator*() {
|
||||
return _interface;
|
||||
}
|
||||
|
||||
const InterfacePtr operator*() const {
|
||||
return _interface;
|
||||
}
|
||||
|
||||
operator bool() const {
|
||||
return (_interface != nullptr);
|
||||
}
|
||||
|
||||
InterfacePtr get() const {
|
||||
return _interface;
|
||||
}
|
||||
|
||||
void** put() {
|
||||
return reinterpret_cast<void**>(&_interface);
|
||||
}
|
||||
|
||||
InterfacePtr detach() {
|
||||
auto result = _interface;
|
||||
_interface = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
void attach(InterfacePtr ptr) {
|
||||
reset();
|
||||
_interface = ptr;
|
||||
}
|
||||
void reset() {
|
||||
auto ptr = _interface;
|
||||
if (ptr != nullptr) {
|
||||
_interface = nullptr;
|
||||
ptr->release();
|
||||
}
|
||||
}
|
||||
|
||||
template<class TImplementer, class ... TArgs>
|
||||
static ComPtr create(TArgs&& ... args) {
|
||||
if constexpr(IsInterfaceSupported<TImplementer, TInterface>()){
|
||||
auto obj = new TImplementer(std::forward<TArgs>(args)...);
|
||||
return obj->template queryInterface<TInterface>();
|
||||
}else{
|
||||
static_assert(IsInterfaceSupported<TImplementer, TInterface>(), "Interface not supported");
|
||||
}
|
||||
}
|
||||
private:
|
||||
InterfacePtr _interface = nullptr;
|
||||
};
|
||||
|
||||
|
||||
template<class TImplementer, class TInterface>
|
||||
class ComDelegate : public ComImplement<ComDelegate<TImplementer, TInterface>, ComObject, TInterface> {
|
||||
public:
|
||||
using DelegatedImplementer = TImplementer;
|
||||
typedef void (TImplementer::*DelegateDestroyCallback)();
|
||||
|
||||
ComDelegate(TImplementer* implementer, DelegateDestroyCallback destroyCallback)
|
||||
: _implementer(implementer), _destroyCallback(destroyCallback) {
|
||||
if constexpr (std::is_base_of_v<RefCountedObject, TImplementer>) {
|
||||
_implementer->addRef();
|
||||
}
|
||||
}
|
||||
~ComDelegate() {
|
||||
if (_destroyCallback != nullptr) {
|
||||
((_implementer)->*(_destroyCallback))();
|
||||
}
|
||||
if constexpr (std::is_base_of_v<RefCountedObject, TImplementer>) {
|
||||
_implementer->release();
|
||||
}
|
||||
}
|
||||
TImplementer* getImplementer() {
|
||||
return _implementer;
|
||||
}
|
||||
private:
|
||||
DelegateDestroyCallback _destroyCallback;
|
||||
TImplementer* _implementer;
|
||||
};
|
||||
|
||||
|
||||
template<class TInterface, class TImplementer>
|
||||
ComPtr<TInterface> makeComDelegate(TImplementer* implementer, typename ComDelegate<TImplementer, TInterface>::DelegateDestroyCallback delegateDestroyCallback = nullptr) {
|
||||
return ComPtr<TInterface>::template create<ComDelegate<TImplementer, TInterface>>(implementer, delegateDestroyCallback);
|
||||
}
|
||||
|
||||
|
||||
class ArrayOutMarshaler {
|
||||
public:
|
||||
using SizeType = std::uint32_t;
|
||||
typedef void* ContextPtr;
|
||||
typedef void* (LFRAMEWORK_COM_CALL *ContainerResizeCallback)(ContextPtr context, SizeType size);
|
||||
|
||||
ContextPtr context;
|
||||
ContainerResizeCallback callback;
|
||||
|
||||
template<typename T>
|
||||
ArrayOutMarshaler(std::vector<T>& buffer) {
|
||||
context = &buffer;
|
||||
callback = &ArrayOutMarshaler::resizeCallback<T>;
|
||||
}
|
||||
|
||||
ArrayOutMarshaler(std::string& buffer) {
|
||||
context = &buffer;
|
||||
callback = &ArrayOutMarshaler::resizeCallback;
|
||||
}
|
||||
template<typename T>
|
||||
void operator = (const std::vector<T>& source) {
|
||||
void* data = callback(context, static_cast<SizeType>(source.size()));
|
||||
if (data != nullptr && !source.empty()) {
|
||||
memcpy(data, source.data(), sizeof(T) * source.size());
|
||||
}
|
||||
}
|
||||
void operator = (const std::string& source) {
|
||||
void* data = callback(context, static_cast<SizeType>(source.size()));
|
||||
if (data != nullptr && !source.empty()) {
|
||||
memcpy(data, source.data(), source.size());
|
||||
}
|
||||
}
|
||||
private:
|
||||
template<typename T>
|
||||
static void* LFRAMEWORK_COM_CALL resizeCallback(ContextPtr context, SizeType size) {
|
||||
auto container = reinterpret_cast<std::vector<T>*>(context);
|
||||
container->resize(size);
|
||||
return size == 0 ? nullptr : container->data();
|
||||
}
|
||||
static void* LFRAMEWORK_COM_CALL resizeCallback(ContextPtr context, SizeType size) {
|
||||
auto container = reinterpret_cast<std::string*>(context);
|
||||
container->resize(size);
|
||||
return size == 0 ? nullptr : container->data();
|
||||
}
|
||||
ArrayOutMarshaler() = delete;
|
||||
};
|
||||
|
||||
class ArrayInMarshaler {
|
||||
public:
|
||||
using SizeType = std::uint32_t;
|
||||
const void* data;
|
||||
SizeType itemsCount;
|
||||
|
||||
ArrayInMarshaler(const std::string& source) {
|
||||
data = source.data();
|
||||
itemsCount = static_cast<SizeType>(source.size());
|
||||
}
|
||||
template<typename T>
|
||||
ArrayInMarshaler(const std::vector<T>& source) {
|
||||
data = source.data();
|
||||
itemsCount = static_cast<SizeType>(source.size());
|
||||
}
|
||||
operator std::string() const {
|
||||
return std::string(reinterpret_cast<const char*>(data), itemsCount);
|
||||
}
|
||||
template<typename T>
|
||||
operator std::vector<T>() const {
|
||||
std::vector<T> result;
|
||||
if (itemsCount != 0) {
|
||||
result.resize(itemsCount);
|
||||
memcpy(result.data(), data, sizeof(T) * itemsCount);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
ArrayInMarshaler() = delete;
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
class InterfaceWrapper<IUnknown> {
|
||||
public:
|
||||
template<typename TInterface, typename = typename std::enable_if<std::is_base_of<InterfaceAbi<IUnknown>, InterfaceAbi<TInterface>>::value>::type>
|
||||
ComPtr<TInterface> queryInterface() {
|
||||
if (_abi == nullptr) {
|
||||
return {};
|
||||
}
|
||||
ComPtr<TInterface> result{};
|
||||
reinterpret_cast<InterfaceAbi<IUnknown>*>(_abi)->queryInterface(InterfaceAbi<TInterface>::ID(), reinterpret_cast<void**>(&result));
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t addRef() {
|
||||
return reinterpret_cast<InterfaceAbi<IUnknown>*>(_abi)->addRef();
|
||||
}
|
||||
uint32_t release() {
|
||||
return reinterpret_cast<InterfaceAbi<IUnknown>*>(_abi)->release();
|
||||
}
|
||||
protected:
|
||||
void* _abi = nullptr;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
template<std::size_t _Capacity>
|
||||
class ByteFifo {
|
||||
public:
|
||||
static constexpr std::size_t Capacity = _Capacity;
|
||||
|
||||
bool write(const void* data, std::size_t size){
|
||||
std::size_t availableSize = getAvailableSize();
|
||||
if(availableSize >= size){
|
||||
auto writeOffset = (_begin + _size) % Capacity;
|
||||
auto distanceToEnd = Capacity - writeOffset;
|
||||
if(distanceToEnd >= size){
|
||||
memcpy(_buffer.data() + writeOffset, data, size);
|
||||
}else{
|
||||
memcpy(_buffer.data() + writeOffset, data, distanceToEnd);
|
||||
memcpy(_buffer.data(), reinterpret_cast<const std::uint8_t*>(data) + distanceToEnd, size - distanceToEnd);
|
||||
}
|
||||
_size += size;
|
||||
if(_size >= 100000){
|
||||
for(;;);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool write(std::uint8_t value){
|
||||
return write(&value, 1);
|
||||
}
|
||||
|
||||
bool read(void* data, std::uint8_t size) {
|
||||
if(_size >= 100000){
|
||||
for(;;);
|
||||
}
|
||||
if(_size < size){
|
||||
return false;
|
||||
}
|
||||
|
||||
auto distanceToEnd = Capacity - _begin;
|
||||
|
||||
if(distanceToEnd >= size){
|
||||
memcpy(data, _buffer.data() + _begin, size);
|
||||
_begin = (_begin + size) % Capacity;
|
||||
}else{
|
||||
memcpy(data, _buffer.data() + _begin, distanceToEnd);
|
||||
memcpy(reinterpret_cast<std::uint8_t*>(data) + distanceToEnd, _buffer.data(), size - distanceToEnd);
|
||||
_begin = size - distanceToEnd;
|
||||
}
|
||||
if(_size >= 100000){
|
||||
for(;;);
|
||||
}
|
||||
_size -= size;
|
||||
if(_size >= 100000){
|
||||
for(;;);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::size_t discard(std::size_t count){
|
||||
if(count > _size){
|
||||
count = _size;
|
||||
}
|
||||
|
||||
_begin = (_begin + count) % Capacity;
|
||||
_size -= count;
|
||||
if(_size >= 100000){
|
||||
for(;;);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool peek(void* data, std::size_t size) {
|
||||
if(_size < size){
|
||||
return false;
|
||||
}
|
||||
|
||||
auto distanceToEnd = Capacity - _begin;
|
||||
|
||||
if(distanceToEnd >= size){
|
||||
memcpy(data, _buffer.data() + _begin, size);
|
||||
}else{
|
||||
memcpy(data, _buffer.data() + _begin, distanceToEnd);
|
||||
memcpy(reinterpret_cast<std::uint8_t*>(data) + distanceToEnd, _buffer.data(), size - distanceToEnd);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool read(std::uint8_t* value) {
|
||||
return read(value, 1);
|
||||
}
|
||||
|
||||
std::size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
std::size_t sizeAvailable() const {
|
||||
return Capacity - _size;
|
||||
}
|
||||
bool empty() const {
|
||||
return _size == 0;
|
||||
}
|
||||
void clear() {
|
||||
_begin = 0;
|
||||
_size = 0;
|
||||
}
|
||||
private:
|
||||
std::size_t getAvailableSize() const {
|
||||
return Capacity - _size;
|
||||
}
|
||||
std::size_t _size = 0;
|
||||
std::size_t _begin = 0;
|
||||
std::array<std::uint8_t, Capacity> _buffer;
|
||||
};
|
||||
@@ -1,6 +0,0 @@
|
||||
target_sources(${PROJECT_NAME}
|
||||
INTERFACE
|
||||
ByteFifo.h
|
||||
LinkedList.h
|
||||
StaticVector.h
|
||||
)
|
||||
@@ -1,78 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
class LinkedList;
|
||||
|
||||
class LinkedListItem {
|
||||
public:
|
||||
LinkedListItem* next = nullptr;
|
||||
LinkedListItem* previous = nullptr;
|
||||
LinkedList* owner = nullptr;
|
||||
};
|
||||
|
||||
|
||||
class LinkedList {
|
||||
public:
|
||||
|
||||
LinkedList():_size(0){
|
||||
_head.next = &_head;
|
||||
_head.previous = &_head;
|
||||
_head.owner = this;
|
||||
}
|
||||
|
||||
bool pushFront(LinkedListItem* newItem){
|
||||
if (newItem->owner == nullptr) {
|
||||
newItem->owner = this;
|
||||
newItem->next = _head.next;
|
||||
newItem->previous = &_head;
|
||||
_head.next->previous = newItem;
|
||||
_head.next = newItem;
|
||||
++_size;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pushBack(LinkedListItem* newItem) {
|
||||
if (newItem->owner == nullptr) {
|
||||
newItem->owner = _head.owner;
|
||||
newItem->previous = _head.previous;
|
||||
newItem->next = &_head;
|
||||
_head.previous->next = newItem;
|
||||
_head.previous = newItem;
|
||||
++_size;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
void remove(LinkedListItem* item) {
|
||||
if (item->owner == this) {
|
||||
item->next->previous = item->previous;
|
||||
item->previous->next = item->next;
|
||||
--_size;
|
||||
item->next = nullptr;
|
||||
item->previous = nullptr;
|
||||
item->owner = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void foreach(T functor) {
|
||||
auto current = _head.next;
|
||||
while (current != &_head) {
|
||||
functor(current);
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
private:
|
||||
size_t _size;
|
||||
LinkedListItem _head;
|
||||
};
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <new>
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
|
||||
namespace LFramework {
|
||||
|
||||
template<class ValueType, size_t Capacity>
|
||||
class StaticVector {
|
||||
public:
|
||||
typedef ValueType& ValueReference;
|
||||
typedef const ValueReference& ConstValueReference;
|
||||
|
||||
StaticVector() = default;
|
||||
|
||||
~StaticVector() {
|
||||
clear();
|
||||
}
|
||||
|
||||
constexpr std::size_t capacity() const {
|
||||
return Capacity;
|
||||
}
|
||||
|
||||
std::size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return _size == 0;
|
||||
}
|
||||
|
||||
bool full() const {
|
||||
return _size == Capacity;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
for(auto it = begin(); it != end(); ++it) {
|
||||
it->~value_type();
|
||||
}
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
ValueType* begin() {
|
||||
return reinterpret_cast<ValueType*>(&_buffer[0]);
|
||||
}
|
||||
|
||||
const ValueType* begin() const {
|
||||
return reinterpret_cast<const ValueType*>(&_buffer[0]);
|
||||
}
|
||||
|
||||
ValueType* end() {
|
||||
return reinterpret_cast<ValueType*>(&_buffer[_size]);
|
||||
}
|
||||
|
||||
const ValueType* end() const {
|
||||
return reinterpret_cast<const ValueType*>(&_buffer[_size]);
|
||||
}
|
||||
|
||||
ValueReference back() {
|
||||
return *reinterpret_cast<ValueType*>(&_buffer[_size - 1]);
|
||||
}
|
||||
|
||||
ConstValueReference back() const {
|
||||
return *reinterpret_cast<const ValueType*>(&_buffer[_size - 1]);
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
bool emplace_back(Args&&... args) {
|
||||
if(!full()) {
|
||||
::new(&_buffer[_size++]) ValueType(std::forward<Args>(args)...);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool push_back(ConstValueReference value) {
|
||||
if (!full()) {
|
||||
::new((void*)&_buffer[_size++]) ValueType(value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void erase(const std::size_t first, const std::size_t count) {
|
||||
std::size_t last = first + count;
|
||||
if ((last <= first) || (last > _size)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//move items
|
||||
auto writePtr = reinterpret_cast<ValueType*>(&_buffer[first]);
|
||||
for(std::size_t i = last; i < _size; ++i){
|
||||
*writePtr = std::move(*reinterpret_cast<ValueType*>(&_buffer[i]));
|
||||
++writePtr;
|
||||
}
|
||||
|
||||
//destroy tail
|
||||
for(std::size_t i = first; i < last; ++i){
|
||||
writePtr->~value_type();
|
||||
++writePtr;
|
||||
}
|
||||
|
||||
_size -= (last - first);
|
||||
}
|
||||
|
||||
void erase(const ValueType& value) {
|
||||
for (std::size_t i = 0; i < _size; ++i) {
|
||||
if (_buffer[i] == value) {
|
||||
erase(i, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void erase(const ValueType* itemPtr) {
|
||||
if(itemPtr < begin()){
|
||||
return;
|
||||
}
|
||||
std::size_t id = itemPtr - begin();
|
||||
erase(id, 1);
|
||||
}
|
||||
|
||||
void pop_back() {
|
||||
if (!empty()) {
|
||||
reinterpret_cast<ValueType*>(&_buffer[--_size])->~value_type();
|
||||
}
|
||||
}
|
||||
|
||||
ValueReference operator[](std::size_t i) {
|
||||
return *reinterpret_cast<ValueType*>(&_buffer[i]);
|
||||
}
|
||||
|
||||
ConstValueReference operator[](std::size_t i) const {
|
||||
return *reinterpret_cast<const ValueType*>(&_buffer[i]);
|
||||
}
|
||||
|
||||
bool contains(ConstValueReference value) {
|
||||
for (std::size_t i = 0; i < _size; ++i) {
|
||||
if (_buffer[i] == value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t resize(std::size_t newSize) {
|
||||
if (newSize > Capacity) {
|
||||
newSize = Capacity;
|
||||
}
|
||||
|
||||
for(std::size_t i = _size; i < newSize; ++i){
|
||||
::new(reinterpret_cast<ValueType*>(&_buffer[i])) ValueType;
|
||||
}
|
||||
|
||||
for(std::size_t i = newSize; i < _size; ++i){
|
||||
reinterpret_cast<ValueType*>(&_buffer[i])->~value_type();
|
||||
}
|
||||
|
||||
_size = newSize;
|
||||
return newSize;
|
||||
}
|
||||
|
||||
private:
|
||||
typename std::aligned_storage<sizeof(ValueType), alignof(ValueType)>::type _buffer[Capacity];
|
||||
std::size_t _size = 0;
|
||||
};
|
||||
|
||||
}
|
||||
-59
@@ -1,59 +0,0 @@
|
||||
#pragma once
|
||||
#include "IO/Terminal/Terminal.h"
|
||||
|
||||
namespace LFramework::Debug {
|
||||
|
||||
enum class LogLevel {
|
||||
Debug,
|
||||
Info,
|
||||
Warning,
|
||||
Critical,
|
||||
Fatal
|
||||
};
|
||||
|
||||
inline const char* toString(LogLevel category) {
|
||||
switch (category) {
|
||||
case LogLevel::Debug:
|
||||
return "Debug";
|
||||
case LogLevel::Info:
|
||||
return "Info";
|
||||
case LogLevel::Warning:
|
||||
return "Warning";
|
||||
case LogLevel::Critical:
|
||||
return "Critical";
|
||||
case LogLevel::Fatal:
|
||||
return "Fatal";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
class LogWriter {
|
||||
public:
|
||||
LogWriter(LogLevel level){
|
||||
|
||||
}
|
||||
template<typename T>
|
||||
LogWriter& operator << (const T& value) {
|
||||
Terminal::out << value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~LogWriter() {
|
||||
Terminal::out << Terminal::NewLine;
|
||||
}
|
||||
};
|
||||
|
||||
inline LogWriter Log() { return LogWriter(LogLevel::Debug); }
|
||||
inline LogWriter Info() { return LogWriter(LogLevel::Info); }
|
||||
inline LogWriter Warning() { return LogWriter(LogLevel::Warning); }
|
||||
inline LogWriter Critical() { return LogWriter(LogLevel::Critical); }
|
||||
inline LogWriter Fatal() { return LogWriter(LogLevel::Fatal); }
|
||||
|
||||
|
||||
#define lfDebug() LFramework::Debug::Log()
|
||||
#define lfInfo() LFramework::Debug::Info()
|
||||
#define lfWarning() LFramework::Debug::Warning()
|
||||
#define lfCritical() LFramework::Debug::Critical()
|
||||
#define lfFatal() LFramework::Debug::Fatal()
|
||||
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
target_sources(${PROJECT_NAME}
|
||||
INTERFACE
|
||||
DetectCPU.h
|
||||
DetectEndianness.h
|
||||
DetectOS.h
|
||||
)
|
||||
@@ -1,87 +0,0 @@
|
||||
#ifndef DetectCPU_h__
|
||||
#define DetectCPU_h__
|
||||
|
||||
#define LF_CPU_ARCH_ALPHA 0
|
||||
#define LF_CPU_ARCH_AMD64 1
|
||||
#define LF_CPU_ARCH_ARM 2
|
||||
#define LF_CPU_ARCH_ARM64 3
|
||||
#define LF_CPU_ARCH_BLACKFIN 4
|
||||
#define LF_CPU_ARCH_CONVEX 5
|
||||
#define LF_CPU_ARCH_IX86 6
|
||||
#define LF_CPU_ARCH_IA64 7
|
||||
#define LF_CPU_ARCH_MOTOROLA68K 8
|
||||
#define LF_CPU_ARCH_MIPS 9
|
||||
#define LF_CPU_ARCH_POWERPC 10
|
||||
#define LF_CPU_ARCH_SPARC 11
|
||||
|
||||
|
||||
#ifndef LF_CPU_ARCH
|
||||
|
||||
#if defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)
|
||||
#define LF_CPU_ARCH LF_CPU_ARCH_ALPHA
|
||||
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
|
||||
#define LF_CPU_ARCH LF_CPU_ARCH_AMD64
|
||||
#elif defined(__arm__) || defined(__thumb__) || defined(__TARGET_ARCH_ARM) || defined(__TARGET_ARCH_THUMB) || defined(_ARM) || defined(_M_ARM)|| defined(_M_ARMT) || defined(__arm)
|
||||
#define LF_CPU_ARCH LF_CPU_ARCH_ARM
|
||||
#elif defined(__aarch64__)
|
||||
#define LF_CPU_ARCH LF_CPU_ARCH_ARM64
|
||||
#elif defined(__bfin) || defined(__BFIN__)
|
||||
#define LF_CPU_ARCH LF_CPU_ARCH_BLACKFIN
|
||||
#elif defined(__convex__)
|
||||
#define LF_CPU_ARCH LF_CPU_ARCH_CONVEX
|
||||
|
||||
#elif defined(i386) || defined(__i386) || defined(__i386__) || defined(__IA32__) \
|
||||
|| defined(_M_I86) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) \
|
||||
|| defined(__THW_INTEL__) || defined(__I86__) || defined(__INTEL__) || defined(__386)
|
||||
#define LF_CPU_ARCH LF_CPU_ARCH_IX86
|
||||
|
||||
#elif defined(__ia64__) || defined(_IA64) || defined(__IA64__) || defined(__ia64) \
|
||||
|| defined(_M_IA64) || defined(_M_IA64) || defined(__itanium__)
|
||||
#define LF_CPU_ARCH LF_CPU_ARCH_IA64
|
||||
|
||||
#elif defined(__m68k__) || defined(M68000) || defined(__MC68K__)
|
||||
#define LF_CPU_ARCH LF_CPU_ARCH_MOTOROLA68K
|
||||
|
||||
#elif defined(__mips__) || defined(mips) || defined(__mips) || defined(__MIPS__)
|
||||
#define LF_CPU_ARCH LF_CPU_ARCH_MIPS
|
||||
|
||||
#elif defined(__powerpc) || defined(__powerpc__) || defined(__powerpc64__) || defined(__POWERPC__) \
|
||||
|| defined(__ppc__) || defined(__ppc64__) || defined(__PPC__) || defined(__PPC64__) \
|
||||
|| defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_M_PPC) || defined(__ppc)
|
||||
#define LF_CPU_ARCH LF_CPU_ARCH_POWERPC
|
||||
|
||||
#elif defined(__sparc__) || defined(__sparc)
|
||||
#define LF_CPU_ARCH LF_CPU_ARCH_MIPS
|
||||
|
||||
#else
|
||||
#error "Unknown CPU arch"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
namespace LFramework {
|
||||
|
||||
enum class CpuArchitecture {
|
||||
Alpha = LF_CPU_ARCH_ALPHA,
|
||||
AMD64 = LF_CPU_ARCH_AMD64,
|
||||
ARM = LF_CPU_ARCH_ARM,
|
||||
ARM64 = LF_CPU_ARCH_ARM64,
|
||||
Blackfin = LF_CPU_ARCH_BLACKFIN,
|
||||
Convex = LF_CPU_ARCH_CONVEX,
|
||||
IX86 = LF_CPU_ARCH_IX86,
|
||||
IA64 = LF_CPU_ARCH_IA64,
|
||||
Motorola68K = LF_CPU_ARCH_MOTOROLA68K,
|
||||
MIPS = LF_CPU_ARCH_MIPS,
|
||||
PowerPC = LF_CPU_ARCH_POWERPC,
|
||||
SPARC = LF_CPU_ARCH_SPARC
|
||||
};
|
||||
|
||||
namespace Detect {
|
||||
static constexpr CpuArchitecture cpuArchitecture() {
|
||||
return static_cast<CpuArchitecture>(LF_CPU_ARCH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DetectCPU_h__
|
||||
@@ -1,63 +0,0 @@
|
||||
#ifndef DetectEndianness_h__
|
||||
#define DetectEndianness_h__
|
||||
|
||||
#define LF_ENDIANNESS_UNKNOWN 0
|
||||
#define LF_ENDIANNESS_LITTLE 1
|
||||
#define LF_ENDIANNESS_BIG 2
|
||||
|
||||
#ifndef LF_ENDIANNESS
|
||||
|
||||
#if defined(__BIG_ENDIAN__) || defined(__ARMEB__) || defined(__THUMBEB__) \
|
||||
|| defined(__AARCH64EB__) || defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) \
|
||||
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) \
|
||||
|| (defined(__FLOAT_WORD_ORDER__) && (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||
#define LF_ENDIANNESS LF_ENDIANNESS_BIG
|
||||
|
||||
#elif defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__THUMBEL__) \
|
||||
|| defined(__AARCH64EL__) || defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) \
|
||||
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) \
|
||||
|| (defined(__FLOAT_WORD_ORDER__) && (__FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||
#define LF_ENDIANNESS LF_ENDIANNESS_LITTLE
|
||||
|
||||
#else
|
||||
#define LF_ENDIANNESS LF_ENDIANNESS_UNKNOWN
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
namespace LFramework {
|
||||
|
||||
enum class Endianness {
|
||||
Unknown = LF_ENDIANNESS_UNKNOWN,
|
||||
Little = LF_ENDIANNESS_LITTLE,
|
||||
Big = LF_ENDIANNESS_BIG
|
||||
};
|
||||
|
||||
namespace Detect {
|
||||
|
||||
static constexpr Endianness endianness() {
|
||||
return static_cast<Endianness>(LF_ENDIANNESS);
|
||||
}
|
||||
|
||||
static Endianness endiannessRuntime() {
|
||||
union {
|
||||
uint32_t value;
|
||||
uint8_t data[sizeof(uint32_t)];
|
||||
} number;
|
||||
|
||||
number.data[0] = 0x00;
|
||||
number.data[1] = 0x01;
|
||||
number.data[2] = 0x02;
|
||||
number.data[3] = 0x03;
|
||||
|
||||
switch (number.value){
|
||||
case 0x00010203U: return Endianness::Big;
|
||||
case 0x03020100U: return Endianness::Little;
|
||||
default: return Endianness::Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // DetectEndianness_h__
|
||||
@@ -1,121 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
//OS Types
|
||||
#define LF_OS_NONE 0
|
||||
#define LF_OS_WINDOWS 1
|
||||
#define LF_OS_LINUX 2
|
||||
#define LF_OS_ANDROID 3
|
||||
#define LF_OS_FREERTOS 4
|
||||
|
||||
//BSD family
|
||||
#define LF_OS_BSD_DRAGONFLY 5
|
||||
#define LF_OS_BSD_FREE 6
|
||||
#define LF_OS_BSD_NET 7
|
||||
#define LF_OS_BSD_OPEN 8
|
||||
#define LF_OS_BSD_BSDI 9
|
||||
|
||||
//Apple
|
||||
#define LF_OS_IPHONE 10
|
||||
#define LF_OS_MAC 11
|
||||
|
||||
#define LF_OS_CYGWIN 12
|
||||
#define LF_OS_LYNX 13
|
||||
#define LF_OS_MSDOS 14
|
||||
#define LF_OS_NUCLEUS_RTOS 15
|
||||
#define LF_OS_OS2 16
|
||||
#define LF_OS_PALMOS 17
|
||||
#define LF_OS_SOLARIS 18
|
||||
|
||||
|
||||
//OS Detect
|
||||
#if !defined(LF_TARGET_OS)
|
||||
#if defined(_WIN32) || defined(_WIN16) || defined(_WIN64) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__)
|
||||
#define LF_TARGET_OS LF_OS_WINDOWS
|
||||
#elif defined(__linux__)
|
||||
#define LF_TARGET_OS LF_OS_LINUX
|
||||
#elif defined(__ANDROID__)
|
||||
#define LF_TARGET_OS LF_OS_ANDROID
|
||||
|
||||
//Detect BDS
|
||||
#elif defined(__DragonFly__)
|
||||
#define LF_TARGET_OS LF_OS_BSD_DRAGONFLY
|
||||
#elif defined(__FreeBSD__)
|
||||
#define LF_TARGET_OS LF_OS_BSD_FREE
|
||||
#elif defined(__NetBSD__)
|
||||
#define LF_TARGET_OS LF_OS_BSD_NET
|
||||
#elif defined(__OpenBSD__)
|
||||
#define LF_TARGET_OS LF_OS_BSD_OPEN
|
||||
#elif defined(__bsdi__)
|
||||
#define LF_TARGET_OS LF_OS_BSD_BSDI
|
||||
|
||||
//Detect Apple
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
#include <TargetConditionals.h>
|
||||
#if (TARGET_IPHONE_SIMULATOR == 1) || (TARGET_OS_IPHONE == 1)
|
||||
#define LF_TARGET_OS LF_OS_IPHONE
|
||||
#elif TARGET_OS_MAC == 1
|
||||
#define LF_TARGET_OS LF_OS_MAC
|
||||
#else
|
||||
#error "Unknown Apple OS"
|
||||
#endif
|
||||
|
||||
#elif defined(__CYGWIN__)
|
||||
#define LF_TARGET_OS LF_OS_CYGWIN
|
||||
#elif defined(__Lynx__)
|
||||
#define LF_TARGET_OS LF_OS_LYNX
|
||||
|
||||
|
||||
//detect MS-DOS
|
||||
#elif defined(MSDOS) || defined(__MSDOS__) || defined(_MSDOS) || defined(__DOS__)
|
||||
#define LF_TARGET_OS LF_OS_MSDOS
|
||||
|
||||
#elif defined(__nucleus__)
|
||||
#define LF_TARGET_OS LF_OS_NUCLEUS_RTOS
|
||||
|
||||
#elif defined(OS2) || defined(_OS2) || defined(__OS2__) || defined(__TOS_OS2__)
|
||||
#define LF_TARGET_OS LF_OS_OS2
|
||||
|
||||
#elif defined(__palmos__)
|
||||
#define LF_TARGET_OS LF_OS_PALMOS
|
||||
|
||||
#elif defined(sun) || defined(__sun)
|
||||
#define LF_TARGET_OS LF_OS_SOLARIS
|
||||
|
||||
#else
|
||||
#error "OS auto detect fail!"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace LFramework {
|
||||
|
||||
enum class OSType {
|
||||
None = LF_OS_NONE,
|
||||
Windows = LF_OS_WINDOWS,
|
||||
Linux = LF_OS_LINUX,
|
||||
Android = LF_OS_ANDROID,
|
||||
FreeRTOS = LF_OS_FREERTOS,
|
||||
|
||||
BSDDragonfly = LF_OS_BSD_DRAGONFLY,
|
||||
BSDFree = LF_OS_BSD_FREE,
|
||||
BSDNet = LF_OS_BSD_NET,
|
||||
BSDOpen = LF_OS_BSD_OPEN,
|
||||
BSDI = LF_OS_BSD_BSDI,
|
||||
|
||||
AppleIPhone = LF_OS_IPHONE,
|
||||
AppleMacOSX = LF_OS_MAC,
|
||||
|
||||
Cygwin = LF_OS_CYGWIN,
|
||||
Lynx = LF_OS_LYNX,
|
||||
MSDOS = LF_OS_MSDOS,
|
||||
NucleusRTOS = LF_OS_NUCLEUS_RTOS,
|
||||
OS2 = LF_OS_OS2,
|
||||
PlamOS = LF_OS_PALMOS,
|
||||
Solaris = LF_OS_SOLARIS
|
||||
};
|
||||
|
||||
namespace Detect {
|
||||
static constexpr inline OSType operatingSystem() {
|
||||
return static_cast<OSType>(LF_TARGET_OS);
|
||||
}
|
||||
}
|
||||
}
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
namespace LFramework {
|
||||
|
||||
struct Guid {
|
||||
std::uint32_t data1;
|
||||
std::uint32_t data2_3;
|
||||
std::uint32_t data4_0;
|
||||
std::uint32_t data4_1;
|
||||
|
||||
//std::uint16_t data2;
|
||||
//std::uint16_t data3;
|
||||
//std::uint8_t data4[8];
|
||||
|
||||
Guid() = default;
|
||||
|
||||
constexpr Guid(std::uint32_t data1, std::uint32_t data2_3, std::uint32_t data4_0, std::uint32_t data4_1) : data1(data1), data2_3(data2_3), data4_0(data4_0), data4_1(data4_1) {}
|
||||
|
||||
constexpr bool operator ==(const Guid& rhs) const {
|
||||
return
|
||||
(data1 == rhs.data1) &&
|
||||
(data2_3 == rhs.data2_3) &&
|
||||
(data4_0 == rhs.data4_0) &&
|
||||
(data4_1 == rhs.data4_1);
|
||||
}
|
||||
|
||||
constexpr bool operator !=(const Guid& rhs) const {
|
||||
return !(this->operator ==(rhs));
|
||||
}
|
||||
|
||||
bool isZero() const {
|
||||
return (data1 == 0) && (data2_3 == 0) && (data4_0 == 0) && (data4_1 == 0);
|
||||
}
|
||||
|
||||
Guid& operator =(const Guid& right) {
|
||||
data1 = right.data1;
|
||||
data2_3 = right.data2_3;
|
||||
data4_0 = right.data4_0;
|
||||
data4_1 = right.data4_1;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#ifdef WIN32
|
||||
#include <LFramework/GuidUtils.h>
|
||||
#include <LFramework/Text/Encoding.h>
|
||||
#include <Windows.h>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace LFramework::GuidUtils {
|
||||
LFramework::Guid newGuid() {
|
||||
LFramework::Guid result;
|
||||
if (CoCreateGuid((GUID*)&result) != S_OK) {
|
||||
throw std::runtime_error("Failed to create GUID");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
LFramework::Guid fromString(const char* str) {
|
||||
LFramework::Guid iid;
|
||||
if (IIDFromString(LFramework::Text::Encoding::u8StringToWString(str).c_str(), (GUID*)&iid) != S_OK) {
|
||||
throw std::runtime_error("Failed to parse GUID");
|
||||
}
|
||||
return iid;
|
||||
}
|
||||
|
||||
std::string toString(const LFramework::Guid& guid) {
|
||||
LPOLESTR guid_str = nullptr;
|
||||
if (StringFromIID(*((const GUID*)&guid), &guid_str) != S_OK) {
|
||||
throw std::runtime_error("Failed to convert GUID to string");
|
||||
}
|
||||
std::wstring result(guid_str);
|
||||
CoTaskMemFree(guid_str);
|
||||
return LFramework::Text::Encoding::wStringToU8String(result);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <LFramework/Guid.h>
|
||||
|
||||
namespace LFramework::GuidUtils {
|
||||
LFramework::Guid newGuid();
|
||||
LFramework::Guid fromString(const char* str);
|
||||
std::string toString(const LFramework::Guid& guid);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
add_library(LFrameworkIo INTERFACE )
|
||||
add_library(LFramework::IO ALIAS LFrameworkIo )
|
||||
|
||||
|
||||
target_sources(LFrameworkIo
|
||||
INTERFACE
|
||||
Stream.h
|
||||
StreamWriter.h
|
||||
|
||||
StreamWriter.cpp
|
||||
)
|
||||
add_subdirectory(Terminal)
|
||||
@@ -1,39 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
namespace LFramework {
|
||||
|
||||
|
||||
template<typename T>
|
||||
class OutputStream {
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
enum class AdjustField {
|
||||
Left,
|
||||
Right,
|
||||
Internal
|
||||
};
|
||||
|
||||
template<typename TChar>
|
||||
class OutputStreamFormat {
|
||||
public:
|
||||
size_t fillWidth = 0;
|
||||
TChar fillChar{};
|
||||
AdjustField adjust = AdjustField::Right;
|
||||
};
|
||||
|
||||
template<>
|
||||
class OutputStream<char> {
|
||||
public:
|
||||
OutputStreamFormat<char> format;
|
||||
|
||||
virtual ~OutputStream() = default;
|
||||
virtual int write(const char* data, int length) = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#include "StreamWriter.h"
|
||||
|
||||
namespace LFramework {
|
||||
|
||||
OutputStream<char>& operator <<(OutputStream<char>& stream, const char* value){
|
||||
auto len = strlen(value);
|
||||
OutputStreamFormatter::fieldBegin(stream, len);
|
||||
stream.write(value, static_cast<int>(len));
|
||||
OutputStreamFormatter::fieldEnd(stream, len);
|
||||
return stream;
|
||||
}
|
||||
|
||||
OutputStream<char>& operator <<(OutputStream<char>& stream, char value){
|
||||
OutputStreamFormatter::fieldBegin(stream, 1);
|
||||
stream.write(&value, 1);
|
||||
OutputStreamFormatter::fieldEnd(stream, 1);
|
||||
return stream;
|
||||
}
|
||||
|
||||
OutputStream<char>& operator <<(OutputStream<char>& stream, bool value){
|
||||
return stream << (value ? "true" : "false");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Stream.h"
|
||||
|
||||
#include "../TypeTraits/Integral.h"
|
||||
|
||||
namespace LFramework {
|
||||
|
||||
|
||||
template<typename T, typename = ::std::enable_if_t<::std::is_integral_v<T>>>
|
||||
struct DecimalFormat {
|
||||
DecimalFormat(T value) :value(value) {}
|
||||
T value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename T, bool UpperCase = false, size_t MinWidth = 0, typename = ::std::enable_if_t<::std::is_integral_v<T>>>
|
||||
struct HexFormat {
|
||||
HexFormat(T value) :value(value) {}
|
||||
T value;
|
||||
};
|
||||
|
||||
template<bool UpperCase = false, size_t MinWidth = 0, typename T>
|
||||
HexFormat<T, UpperCase, MinWidth> hex(T value) {
|
||||
return HexFormat<T, UpperCase, MinWidth>(value);
|
||||
}
|
||||
|
||||
|
||||
class OutputStreamFormatter {
|
||||
public:
|
||||
|
||||
static void writeFiller(OutputStream<char>& stream, size_t itemSize){
|
||||
auto fillSize = stream.format.fillWidth - itemSize;
|
||||
for(size_t i = 0; i < fillSize; ++i){
|
||||
stream.write(&stream.format.fillChar, 1);
|
||||
}
|
||||
stream.format.fillWidth = 0;
|
||||
}
|
||||
|
||||
static void fieldBegin(OutputStream<char>& stream, size_t itemSize){
|
||||
|
||||
if(stream.format.adjust == AdjustField::Right || stream.format.adjust == AdjustField::Internal){
|
||||
if(itemSize < stream.format.fillWidth){
|
||||
writeFiller(stream, itemSize);
|
||||
}
|
||||
stream.format.fillWidth = 0;
|
||||
}
|
||||
}
|
||||
static void fieldEnd(OutputStream<char>& stream, size_t itemSize){
|
||||
if(stream.format.adjust == AdjustField::Left){
|
||||
if(itemSize < stream.format.fillWidth){
|
||||
writeFiller(stream, itemSize);
|
||||
}
|
||||
stream.format.fillWidth = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
size_t outputStreamWriteInteger (OutputStream<char>& stream, DecimalFormat<T> formatter){
|
||||
auto v = formatter.value;
|
||||
|
||||
static constexpr size_t BufferSize = TypeTraits::Integral::maxDigitsCount<T>() + (::std::is_signed_v<T> ? 1 : 0); //Add space for sign
|
||||
char result[BufferSize];
|
||||
|
||||
size_t writePos = BufferSize - 1;
|
||||
|
||||
if constexpr(::std::is_signed_v<T>) {
|
||||
//print negative numbers
|
||||
if (v < 0) {
|
||||
do {
|
||||
auto next = v / 10;
|
||||
result[writePos--] = static_cast<char>('0' - (v - (next * 10)));
|
||||
v = next;
|
||||
} while (v != 0);
|
||||
result[writePos] = '-';
|
||||
|
||||
auto fieldSize = BufferSize - writePos;
|
||||
|
||||
if(fieldSize < stream.format.fillWidth){
|
||||
|
||||
if(stream.format.adjust == AdjustField::Internal){
|
||||
stream.write(&result[writePos], 1);
|
||||
OutputStreamFormatter::writeFiller(stream, fieldSize);
|
||||
stream.write(&result[writePos + 1], fieldSize - 1);
|
||||
}else {
|
||||
OutputStreamFormatter::fieldBegin(stream, fieldSize);
|
||||
stream.write(&result[writePos], fieldSize);
|
||||
OutputStreamFormatter::fieldEnd(stream, fieldSize);
|
||||
}
|
||||
|
||||
}else{
|
||||
stream.write(&result[writePos], fieldSize);
|
||||
}
|
||||
|
||||
return fieldSize;
|
||||
}
|
||||
}
|
||||
|
||||
//print positive numbers
|
||||
do {
|
||||
result[writePos--] = static_cast<char>('0' + (v % 10));
|
||||
v /= 10;
|
||||
} while (v != 0);
|
||||
|
||||
auto fieldSize = BufferSize - writePos - 1;
|
||||
|
||||
OutputStreamFormatter::fieldBegin(stream, fieldSize);
|
||||
stream.write(&result[writePos + 1], fieldSize);
|
||||
OutputStreamFormatter::fieldEnd(stream, fieldSize);
|
||||
|
||||
return fieldSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename T, bool UpperCase, size_t MinWidth>
|
||||
OutputStream<char>& operator <<(OutputStream<char>& stream, const HexFormat<T, UpperCase, MinWidth>& formatter){
|
||||
auto v = static_cast<typename std::make_unsigned<T>::type>(formatter.value);
|
||||
|
||||
const auto bufferSize = sizeof(T) * 2;
|
||||
char buffer[bufferSize];
|
||||
size_t end = bufferSize;
|
||||
|
||||
char a = 'a';
|
||||
if constexpr(UpperCase) {
|
||||
a = 'A';
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < bufferSize; ++i) {
|
||||
auto digit = v & 0xf;
|
||||
if (digit < 10) {
|
||||
buffer[end - 1] = static_cast<char>('0' + digit);
|
||||
}
|
||||
else {
|
||||
buffer[end - 1] = static_cast<char>(a + (digit - 10));
|
||||
}
|
||||
v >>= 4;
|
||||
--end;
|
||||
if(v == 0 && (i + 1) >= MinWidth) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const auto dataSize = bufferSize - end;
|
||||
|
||||
OutputStreamFormatter::fieldBegin(stream, dataSize);
|
||||
stream.write(&buffer[end], dataSize);
|
||||
OutputStreamFormatter::fieldEnd(stream, dataSize);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
|
||||
OutputStream<char>& operator <<(OutputStream<char>& stream, const char* value);
|
||||
OutputStream<char>& operator <<(OutputStream<char>& stream, char value);
|
||||
OutputStream<char>& operator <<(OutputStream<char>& stream, bool value);
|
||||
|
||||
template<typename T>
|
||||
OutputStream<char>& operator <<(OutputStream<char>& stream, DecimalFormat<T> formatter){
|
||||
outputStreamWriteInteger(stream, formatter);
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
template<typename T, typename = std::enable_if_t<
|
||||
std::is_integral_v<T> &&
|
||||
std::is_arithmetic_v<T> &&
|
||||
!std::is_same_v<T, bool> &&
|
||||
!std::is_same_v<T, char>
|
||||
>>
|
||||
OutputStream<char>& operator <<(OutputStream<char>& stream, T value){
|
||||
return stream << DecimalFormat<T>(value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
add_library(LFrameworkIoTerminal INTERFACE )
|
||||
add_library(LFramework::IO::Terminal ALIAS LFrameworkIoTerminal )
|
||||
|
||||
target_sources(LFrameworkIoTerminal
|
||||
INTERFACE
|
||||
Terminal.h
|
||||
TerminalAnsi.h
|
||||
TerminalStream.h
|
||||
|
||||
Terminal.cpp
|
||||
TerminalStreamCout.cpp
|
||||
TerminalStreamUartStm32.cpp
|
||||
)
|
||||
@@ -1,5 +0,0 @@
|
||||
#include "Terminal.h"
|
||||
|
||||
namespace LFramework::Terminal {
|
||||
Stream out;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "TerminalStream.h"
|
||||
|
||||
namespace LFramework::Terminal {
|
||||
static const char* NewLine = "\r\n";
|
||||
extern Stream out;
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#define LF_TERMINAL_ANSI_ESC "\033"
|
||||
|
||||
#define LF_TERMINAL_ANSI_SS2 LF_TERMINAL_ANSI_ESC"N"
|
||||
#define LF_TERMINAL_ANSI_SS3 LF_TERMINAL_ANSI_ESC"O"
|
||||
#define LF_TERMINAL_ANSI_DCS LF_TERMINAL_ANSI_ESC"P"
|
||||
#define LF_TERMINAL_ANSI_CSI LF_TERMINAL_ANSI_ESC"["
|
||||
#define LF_TERMINAL_ANSI_ST LF_TERMINAL_ANSI_ESC"\\"
|
||||
#define LF_TERMINAL_ANSI_OSC LF_TERMINAL_ANSI_ESC"]"
|
||||
#define LF_TERMINAL_ANSI_SOS LF_TERMINAL_ANSI_ESC"X"
|
||||
#define LF_TERMINAL_ANSI_PM LF_TERMINAL_ANSI_ESC"^"
|
||||
#define LF_TERMINAL_ANSI_APC LF_TERMINAL_ANSI_ESC"_"
|
||||
#define LF_TERMINAL_ANSI_RIS LF_TERMINAL_ANSI_ESC"c"
|
||||
|
||||
#if defined(LF__TERMINAL_ANSI_CODES_ENABLE)
|
||||
#define LF_TERMINAL_ANSI_CODE(__id, __suffix) LF_TERMINAL_ANSI_CSI #__id #__suffix
|
||||
#else
|
||||
#define LF_TERMINAL_ANSI_CODE(__id, __suffix) ""
|
||||
#endif
|
||||
|
||||
#define LF_TERMINAL_ANSI_GRAPHICS_CODE(__id) LF_TERMINAL_ANSI_CODE(__id, m)
|
||||
#define LF_TERMINAL_ANSI_CODE_DEFINE(__codeName, __id) inline const char (& __codeName ())[std::extent<std::remove_reference_t<decltype(LF_TERMINAL_ANSI_GRAPHICS_CODE(__id))>>::value] { return LF_TERMINAL_ANSI_GRAPHICS_CODE(__id); }
|
||||
|
||||
|
||||
namespace LFramework::Terminal::Ansi {
|
||||
namespace Color {
|
||||
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Black, 30)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Red, 31)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Green, 32)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Yellow, 33)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Blue, 34)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Magenta, 35)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Cyan, 36)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(LightGray, 37)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(DarkGray, 90)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(LightRed, 91)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(LightGreen, 92)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(LightYellow, 93)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(LightBlue, 94)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(LightMagenta, 95)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(LightCyan, 96)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(White, 97)
|
||||
|
||||
//Background
|
||||
namespace BG {
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Black, 40)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Red, 41)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Green, 42)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Yellow, 43)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Blue, 44)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Magenta, 45)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Cyan, 46)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(LightGray, 47)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(DarkGray, 100)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(LightRed, 101)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(LightGreen, 102)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(LightYellow, 103)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(LightBlue, 104)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(LightMagenta, 105)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(LightCyan, 106)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(White, 107)
|
||||
}
|
||||
}
|
||||
|
||||
namespace Format {
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(BoldSet, 1)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(BoldReset, 21)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(UnderlinedSet, 4)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(UnderlinedReset, 24)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(BlinkSet, 5)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(BlinkReset, 25)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(ReverseSet, 7)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(ReverseReset, 27)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(ResetAll, 0)
|
||||
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Framed, 51)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Encircled, 52)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(Overlined, 53)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(ClearFramedEncircled, 54)
|
||||
LF_TERMINAL_ANSI_CODE_DEFINE(ClearOverlined, 55)
|
||||
}
|
||||
|
||||
|
||||
namespace Cursor {
|
||||
inline const char (& EnableBlinking ())[std::extent<std::remove_reference_t<decltype(LF_TERMINAL_ANSI_CSI"?12h")>>::value] {
|
||||
return LF_TERMINAL_ANSI_CSI"?12h";
|
||||
}
|
||||
inline const char (& DisableBlinking ())[std::extent<std::remove_reference_t<decltype(LF_TERMINAL_ANSI_CSI"?12l")>>::value] {
|
||||
return LF_TERMINAL_ANSI_CSI"?12l";
|
||||
}
|
||||
inline const char (& Show ())[std::extent<std::remove_reference_t<decltype(LF_TERMINAL_ANSI_CSI"?25h")>>::value] {
|
||||
return LF_TERMINAL_ANSI_CSI"?25h";
|
||||
}
|
||||
inline const char (& Hide ())[std::extent<std::remove_reference_t<decltype(LF_TERMINAL_ANSI_CSI"?25l")>>::value] {
|
||||
return LF_TERMINAL_ANSI_CSI"?25l";
|
||||
}
|
||||
|
||||
|
||||
inline const char (& MoveHome ())[std::extent<std::remove_reference_t<decltype(LF_TERMINAL_ANSI_CSI"H")>>::value] {
|
||||
return LF_TERMINAL_ANSI_CSI"H";
|
||||
}
|
||||
|
||||
inline const char (& SavePosition ())[std::extent<std::remove_reference_t<decltype(LF_TERMINAL_ANSI_CSI"s")>>::value] {
|
||||
return LF_TERMINAL_ANSI_CSI"s";
|
||||
}
|
||||
|
||||
inline const char (& RestorePosition ())[std::extent<std::remove_reference_t<decltype(LF_TERMINAL_ANSI_CSI"u")>>::value] {
|
||||
return LF_TERMINAL_ANSI_CSI"u";
|
||||
}
|
||||
}
|
||||
|
||||
namespace TextEdit {
|
||||
inline const char (& EraseLineCurToBeg ())[std::extent<std::remove_reference_t<decltype(LF_TERMINAL_ANSI_CSI"K")>>::value] {
|
||||
return LF_TERMINAL_ANSI_CSI"K";
|
||||
}
|
||||
inline const char (& EraseLineBegToCur ())[std::extent<std::remove_reference_t<decltype(LF_TERMINAL_ANSI_CSI"1K")>>::value] {
|
||||
return LF_TERMINAL_ANSI_CSI"1K";
|
||||
}
|
||||
inline const char (& EraseLine ())[std::extent<std::remove_reference_t<decltype(LF_TERMINAL_ANSI_CSI"2K")>>::value] {
|
||||
return LF_TERMINAL_ANSI_CSI"2K";
|
||||
}
|
||||
}
|
||||
|
||||
namespace Viewport {
|
||||
inline const char (& ClearScreenAfterCursor ())[std::extent<std::remove_reference_t<decltype(LF_TERMINAL_ANSI_CSI"0J")>>::value] {
|
||||
return LF_TERMINAL_ANSI_CSI"0J";
|
||||
}
|
||||
inline const char (& ClearScreenBeforeCursor ())[std::extent<std::remove_reference_t<decltype(LF_TERMINAL_ANSI_CSI"1J")>>::value] {
|
||||
return LF_TERMINAL_ANSI_CSI"1J";
|
||||
}
|
||||
inline const char (& ClearScreen ())[std::extent<std::remove_reference_t<decltype(LF_TERMINAL_ANSI_CSI"2J")>>::value] {
|
||||
return LF_TERMINAL_ANSI_CSI"2J";
|
||||
}
|
||||
inline const char (& ClearScreenAndScrollback ())[std::extent<std::remove_reference_t<decltype(LF_TERMINAL_ANSI_CSI"3J")>>::value] {
|
||||
return LF_TERMINAL_ANSI_CSI"3J";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "../StreamWriter.h"
|
||||
|
||||
namespace LFramework::Terminal {
|
||||
class Stream : public OutputStream<char>{
|
||||
public:
|
||||
int write(const char* data, int length) override final;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#include "TerminalStream.h"
|
||||
|
||||
|
||||
#ifdef LF_TERMINAL_STREAM_COUT
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace LFramework::Terminal {
|
||||
int LFramework::Terminal::Stream::write(const char* data, int length) {
|
||||
std::cout.write(data, length);
|
||||
std::cout.flush();
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
#include "TerminalStream.h"
|
||||
|
||||
#ifdef LF_TERMINAL_STREAM_USART_STM32
|
||||
|
||||
|
||||
#ifdef STM32F7
|
||||
#include <stm32f7xx_hal.h>
|
||||
#include <stm32f7xx_ll_usart.h>
|
||||
#elif STM32H7
|
||||
#include <stm32h7xx_hal.h>
|
||||
#include <stm32h7xx_ll_usart.h>
|
||||
#endif
|
||||
|
||||
namespace LFramework::Terminal {
|
||||
|
||||
|
||||
int LFramework::Terminal::Stream::write(const char* data, int length) {
|
||||
for(int i = 0; i < length; ++i){
|
||||
while (!LL_USART_IsActiveFlag_TXE(LF_TERMINAL_STREAM_USART)) {}
|
||||
LL_USART_TransmitData8(LF_TERMINAL_STREAM_USART, *data);
|
||||
++data;
|
||||
}
|
||||
|
||||
//if(HAL_OK == HAL_UART_Transmit(&huart1, reinterpret_cast<uint8_t*>(const_cast<char*>(data)), length, HAL_MAX_DELAY)){
|
||||
// return length;
|
||||
//}
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,14 +0,0 @@
|
||||
add_library(LFrameworkInput INTERFACE )
|
||||
add_library(LFramework::Input ALIAS LFrameworkInput )
|
||||
|
||||
target_sources(LFrameworkInput
|
||||
INTERFACE
|
||||
Input.h
|
||||
Keyboard.h
|
||||
KeysStateManager.h
|
||||
Mouse.h
|
||||
|
||||
Input.cpp
|
||||
Keyboard.cpp
|
||||
Mouse.cpp
|
||||
)
|
||||
@@ -1,150 +0,0 @@
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "Input.h"
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
Input::Input() {
|
||||
auto hInst = GetModuleHandle(NULL);
|
||||
register_input_window_class(hInst);
|
||||
|
||||
_input_window = CreateWindow(_class_name, TEXT("RawInputWindow"), WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInst, NULL);
|
||||
|
||||
if (_input_window == NULL) {
|
||||
std::cout << "Failed to create input window!" << std::endl;
|
||||
}
|
||||
SetWindowLongPtr(_input_window, GWLP_USERDATA, (LONG_PTR)this);
|
||||
ShowWindow(_input_window, SW_HIDE);
|
||||
UpdateWindow(_input_window);
|
||||
|
||||
enumerate_devices();
|
||||
|
||||
RAWINPUTDEVICE Rid[2];
|
||||
|
||||
Rid[0].usUsagePage = 0x01; //HID mouse
|
||||
Rid[0].usUsage = 0x02;
|
||||
Rid[0].dwFlags = RIDEV_INPUTSINK;
|
||||
Rid[0].hwndTarget = _input_window;
|
||||
|
||||
Rid[1].usUsagePage = 0x01; //HID keyboard
|
||||
Rid[1].usUsage = 0x06;
|
||||
Rid[1].dwFlags = RIDEV_INPUTSINK;
|
||||
Rid[1].hwndTarget = _input_window;
|
||||
|
||||
if (RegisterRawInputDevices(Rid, 2, sizeof(Rid[0])) == FALSE) {
|
||||
std::cout << "Failed to register raw input devices!" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Input> Input::Instance() {
|
||||
static std::shared_ptr<Input> instance(new Input());
|
||||
return instance;
|
||||
}
|
||||
|
||||
const std::vector<std::shared_ptr<Mouse>>& Input::mice() const{
|
||||
return _mice;
|
||||
}
|
||||
|
||||
void Input::strobe(){
|
||||
|
||||
MSG msg = { 0 };
|
||||
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
for(auto mouse : _mice){
|
||||
mouse->Strobe();
|
||||
}
|
||||
for(auto kb : _keyboards){
|
||||
kb->Strobe();
|
||||
}
|
||||
}
|
||||
|
||||
void Input::enumerate_devices() {
|
||||
_mice.clear();
|
||||
|
||||
UINT numDevices;
|
||||
GetRawInputDeviceList(NULL, &numDevices, sizeof(RAWINPUTDEVICELIST));
|
||||
if (numDevices == 0) return;
|
||||
|
||||
std::vector<RAWINPUTDEVICELIST> deviceList(numDevices);
|
||||
GetRawInputDeviceList(&deviceList[0], &numDevices, sizeof(RAWINPUTDEVICELIST));
|
||||
|
||||
std::vector<wchar_t> deviceNameData;
|
||||
std::wstring deviceName;
|
||||
for (UINT i = 0; i < numDevices; ++i) {
|
||||
const RAWINPUTDEVICELIST& device = deviceList[i];
|
||||
if (device.dwType == RIM_TYPEMOUSE) {
|
||||
_mice.push_back(std::make_shared<Mouse>(device.hDevice));
|
||||
} else if (device.dwType == RIM_TYPEKEYBOARD) {
|
||||
_keyboards.push_back(std::make_shared<Keyboard>(device.hDevice));
|
||||
} else {
|
||||
std::cout << "HID device" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ATOM Input::register_input_window_class(HINSTANCE hinstance) {
|
||||
|
||||
WNDCLASSEX wcex;
|
||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wcex.lpfnWndProc = &Input::wnd_proc;
|
||||
wcex.cbClsExtra = 0;
|
||||
wcex.cbWndExtra = 0;
|
||||
wcex.hInstance = hinstance;
|
||||
wcex.hIcon = LoadIcon(wcex.hInstance, IDI_APPLICATION);
|
||||
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||||
wcex.lpszMenuName = NULL;
|
||||
wcex.lpszClassName = _class_name;
|
||||
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
|
||||
return RegisterClassEx(&wcex);
|
||||
}
|
||||
|
||||
const std::vector<std::shared_ptr<Keyboard>>& Input::keyboards() const
|
||||
{
|
||||
return _keyboards;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK Input::wnd_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
auto input = (Input*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
|
||||
switch (message) {
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
case WM_INPUT: {
|
||||
UINT dwSize;
|
||||
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
|
||||
LPBYTE lpb = new BYTE[dwSize];
|
||||
|
||||
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) {
|
||||
OutputDebugString(TEXT("GetRawInputData does not return correct size !\n"));
|
||||
}
|
||||
|
||||
RAWINPUT* raw = (RAWINPUT*)lpb;
|
||||
|
||||
if (raw->header.dwType == RIM_TYPEKEYBOARD) {
|
||||
auto device = std::find_if(input->_keyboards.begin(), input->_keyboards.end(), [raw](std::shared_ptr<Keyboard> m) {return m->GetHandle() == raw->header.hDevice; });
|
||||
if (device != input->_keyboards.end()) {
|
||||
(*device)->ApplyInput(*raw);
|
||||
}
|
||||
} else if (raw->header.dwType == RIM_TYPEMOUSE) {
|
||||
auto device = std::find_if(input->_mice.begin(), input->_mice.end(), [raw](std::shared_ptr<Mouse> m) {return m->GetHandle() == raw->header.hDevice; });
|
||||
if(device != input->_mice.end()){
|
||||
(*device)->ApplyInput(*raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <Windows.h>
|
||||
#include <vector>
|
||||
#include "Mouse.h"
|
||||
#include "Keyboard.h"
|
||||
|
||||
class Input {
|
||||
public:
|
||||
Input();
|
||||
static std::shared_ptr<Input> Instance();
|
||||
const std::vector<std::shared_ptr<Mouse>>& mice() const;
|
||||
const std::vector<std::shared_ptr<Keyboard>>& keyboards() const;
|
||||
void strobe();
|
||||
private:
|
||||
void enumerate_devices();
|
||||
ATOM register_input_window_class(HINSTANCE hinstance);
|
||||
static LRESULT CALLBACK wnd_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
HWND _input_window;
|
||||
const TCHAR* _class_name = TEXT("RawInputWindow");
|
||||
std::vector<std::shared_ptr<Mouse>> _mice;
|
||||
std::vector<std::shared_ptr<Keyboard>> _keyboards;
|
||||
};
|
||||
@@ -1,53 +0,0 @@
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "Keyboard.h"
|
||||
#include <iostream>
|
||||
|
||||
Keyboard::Keyboard(HANDLE hdevice) :_hdevice(hdevice) {
|
||||
UINT dataSize;
|
||||
GetRawInputDeviceInfo(hdevice, RIDI_DEVICENAME, nullptr, &dataSize);
|
||||
if (dataSize) {
|
||||
std::wstring name_data;
|
||||
name_data.resize(dataSize);
|
||||
UINT result = GetRawInputDeviceInfo(hdevice, RIDI_DEVICENAME, &name_data[0], &dataSize);
|
||||
if (result != UINT_MAX) {
|
||||
_name = name_data;
|
||||
}
|
||||
}
|
||||
|
||||
RID_DEVICE_INFO deviceInfo;
|
||||
deviceInfo.cbSize = sizeof deviceInfo;
|
||||
dataSize = sizeof deviceInfo;
|
||||
UINT result = GetRawInputDeviceInfo(hdevice, RIDI_DEVICEINFO, &deviceInfo, &dataSize);
|
||||
_function_keys_count = deviceInfo.keyboard.dwNumberOfFunctionKeys;
|
||||
_keys_count = deviceInfo.keyboard.dwNumberOfKeysTotal;
|
||||
_indicators_count = deviceInfo.keyboard.dwNumberOfIndicators;
|
||||
}
|
||||
|
||||
void Keyboard::Strobe() {
|
||||
_keys_manager.strobe();
|
||||
}
|
||||
|
||||
HANDLE Keyboard::GetHandle() const {
|
||||
return _hdevice;
|
||||
}
|
||||
|
||||
bool Keyboard::GetKeyState(uint32_t key_index) const {
|
||||
return _keys_manager._key_states[key_index];
|
||||
}
|
||||
|
||||
bool Keyboard::GetKeyPressed(uint32_t key_index) const {
|
||||
return _keys_manager._key_pressed[key_index];
|
||||
}
|
||||
|
||||
bool Keyboard::GetKeyReleased(uint32_t key_index) const {
|
||||
return _keys_manager._key_released[key_index];
|
||||
}
|
||||
|
||||
void Keyboard::ApplyInput(RAWINPUT input) {
|
||||
if (input.data.keyboard.Flags == RI_KEY_BREAK)
|
||||
_keys_manager._key_states[input.data.keyboard.VKey] = false;
|
||||
else
|
||||
_keys_manager._key_states[input.data.keyboard.VKey] = true;
|
||||
}
|
||||
#endif
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include "KeysStateManager.h"
|
||||
|
||||
class Keyboard {
|
||||
public:
|
||||
friend class Input;
|
||||
Keyboard(HANDLE hdevice);
|
||||
|
||||
HANDLE GetHandle() const;
|
||||
bool GetKeyState(uint32_t key_index) const;
|
||||
bool GetKeyPressed(uint32_t key_index) const;
|
||||
bool GetKeyReleased(uint32_t key_index) const;
|
||||
private:
|
||||
void Strobe();
|
||||
void ApplyInput(RAWINPUT input);
|
||||
HANDLE _hdevice;
|
||||
std::wstring _name;
|
||||
uint32_t _function_keys_count;
|
||||
uint32_t _keys_count;
|
||||
uint32_t _indicators_count;
|
||||
|
||||
KeysStateManager<0xff, Keyboard> _keys_manager;
|
||||
};
|
||||
@@ -1,50 +0,0 @@
|
||||
#ifndef KeysStateManager_h__
|
||||
#define KeysStateManager_h__
|
||||
|
||||
template<uint32_t Count, typename Owner>
|
||||
class KeysStateManager {
|
||||
public:
|
||||
friend Owner;
|
||||
KeysStateManager()
|
||||
{
|
||||
for (uint32_t i = 0; i < Count; ++i) {
|
||||
_key_states[i] = _key_pressed[i] = _key_released[i] = _key_states_previous[i] = false;
|
||||
}
|
||||
}
|
||||
void strobe();
|
||||
private:
|
||||
bool _key_states[Count];
|
||||
bool _key_states_previous[Count];
|
||||
bool _key_pressed[Count];
|
||||
bool _key_released[Count];
|
||||
};
|
||||
|
||||
template <uint32_t Count, typename Owner>
|
||||
void KeysStateManager<Count, Owner>::strobe(){
|
||||
|
||||
|
||||
for (uint32_t i = 0; i < Count; ++i) {
|
||||
if (_key_states[i]) { //if now pressed
|
||||
if (_key_states_previous[i]) {//if was pressed
|
||||
_key_pressed[i] = false;
|
||||
} else {
|
||||
_key_pressed[i] = true;
|
||||
}
|
||||
} else {
|
||||
_key_pressed[i] = false;
|
||||
}
|
||||
if (!_key_states[i]) { //not pressed
|
||||
if (_key_states_previous[i]) {//if was pressed
|
||||
_key_released[i] = true;
|
||||
} else {
|
||||
_key_released[i] = false;
|
||||
}
|
||||
} else {
|
||||
_key_released[i] = false;
|
||||
}
|
||||
_key_states_previous[i] = _key_states[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // KeysStateManager_h__
|
||||
@@ -1,80 +0,0 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "Mouse.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
Mouse::Mouse(HANDLE handle) :_handle(handle){
|
||||
_deltax = _deltay = _deltax_integral = _deltay_integral = 0;
|
||||
|
||||
UINT dataSize;
|
||||
GetRawInputDeviceInfo(_handle, RIDI_DEVICENAME, nullptr, &dataSize);
|
||||
if (dataSize) {
|
||||
_name.resize(dataSize);
|
||||
UINT result = GetRawInputDeviceInfo(_handle, RIDI_DEVICENAME, &_name[0], &dataSize);
|
||||
if (result != UINT_MAX) {
|
||||
_name.assign(_name.begin(), _name.end());
|
||||
}
|
||||
}
|
||||
|
||||
RID_DEVICE_INFO deviceInfo;
|
||||
deviceInfo.cbSize = sizeof deviceInfo;
|
||||
dataSize = sizeof deviceInfo;
|
||||
UINT result = GetRawInputDeviceInfo(_handle, RIDI_DEVICEINFO, &deviceInfo, &dataSize);
|
||||
if (result != UINT_MAX) {
|
||||
_buttons_count = deviceInfo.mouse.dwNumberOfButtons;
|
||||
_has_horizontal_wheel = deviceInfo.mouse.fHasHorizontalWheel == TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE Mouse::GetHandle() const{
|
||||
return _handle;
|
||||
}
|
||||
|
||||
bool Mouse::GetKeyState(uint32_t key_index) const{
|
||||
return _keys_manager._key_states[key_index];
|
||||
}
|
||||
|
||||
bool Mouse::GetKeyPressed(uint32_t key_index) const{
|
||||
return _keys_manager._key_pressed[key_index];
|
||||
}
|
||||
|
||||
bool Mouse::GetKeyReleased(uint32_t key_index) const{
|
||||
return _keys_manager._key_released[key_index];
|
||||
}
|
||||
|
||||
void Mouse::Strobe() {
|
||||
_deltax = _deltax_integral;
|
||||
_deltax_integral = 0;
|
||||
_deltay = _deltay_integral;
|
||||
_deltay_integral = 0;
|
||||
_keys_manager.strobe();
|
||||
}
|
||||
|
||||
int32_t Mouse::GetDx() const{
|
||||
return _deltax;
|
||||
}
|
||||
|
||||
int32_t Mouse::GetDy() const{
|
||||
return _deltay;
|
||||
}
|
||||
|
||||
void Mouse::ApplyInput(RAWINPUT input) {
|
||||
//input.data.mouse.lLastX
|
||||
_deltax_integral += input.data.mouse.lLastX;
|
||||
_deltay_integral += input.data.mouse.lLastY;
|
||||
|
||||
RAWMOUSE data = input.data.mouse;
|
||||
for (uint32_t i = 0; i < maxButtonsCount; ++i){
|
||||
if((data.ulButtons & (1 << (i << 1))) != 0){
|
||||
_keys_manager._key_states[i] = true;
|
||||
}
|
||||
if ((data.ulButtons & (2 << (i << 1))) != 0) {
|
||||
_keys_manager._key_states[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <cstdint>
|
||||
#include "KeysStateManager.h"
|
||||
#include <string>
|
||||
|
||||
class Mouse {
|
||||
public:
|
||||
static constexpr uint32_t maxButtonsCount = 5;
|
||||
friend class Input;
|
||||
Mouse(HANDLE handle);
|
||||
HANDLE GetHandle() const;
|
||||
bool GetKeyState(uint32_t key_index) const;
|
||||
bool GetKeyPressed(uint32_t key_index) const;
|
||||
bool GetKeyReleased(uint32_t key_index) const;
|
||||
int32_t GetDx() const;
|
||||
int32_t GetDy() const;
|
||||
private:
|
||||
void Strobe();
|
||||
void ApplyInput(RAWINPUT input);
|
||||
LONG _deltax_integral;
|
||||
LONG _deltay_integral;
|
||||
LONG _deltax;
|
||||
LONG _deltay;
|
||||
KeysStateManager<maxButtonsCount, Mouse> _keys_manager;
|
||||
HANDLE _handle;
|
||||
std::wstring _name;
|
||||
uint32_t _buttons_count;
|
||||
bool _has_horizontal_wheel;
|
||||
};
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
target_sources(${PROJECT_NAME}
|
||||
INTERFACE
|
||||
Mcu.h
|
||||
)
|
||||
add_subdirectory(DMA)
|
||||
add_subdirectory(stm32)
|
||||
add_subdirectory(USBDevice)
|
||||
@@ -1,4 +0,0 @@
|
||||
target_sources(${PROJECT_NAME}
|
||||
INTERFACE
|
||||
DMA.h
|
||||
)
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* DMA.h
|
||||
*
|
||||
* Created on: 25 ñåíò. 2017 ã.
|
||||
* Author: l-pro
|
||||
*/
|
||||
|
||||
#ifndef LFRAMEWORK_MCU_DMA_DMA_H_
|
||||
#define LFRAMEWORK_MCU_DMA_DMA_H_
|
||||
|
||||
|
||||
namespace EmbeddedFramework {
|
||||
|
||||
class DMA{
|
||||
|
||||
};
|
||||
|
||||
template<int Number, int Channel>
|
||||
class DmaIrqHandler{
|
||||
|
||||
};
|
||||
|
||||
template<int Number, int Channel>
|
||||
class DmaCallback {
|
||||
public:
|
||||
/*static void error();
|
||||
static void complete();
|
||||
static void halfComplete();*/
|
||||
};
|
||||
|
||||
|
||||
#endif /* LFRAMEWORK_MCU_DMA_DMA_H_ */
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Mcu.h
|
||||
*
|
||||
* Created on: 19 July. 2017 ã.
|
||||
* Author: l-pro
|
||||
*/
|
||||
|
||||
#ifndef MCUFRAMEWORK_MCU_H_
|
||||
#define MCUFRAMEWORK_MCU_H_
|
||||
|
||||
#include "LFrameworkConfig.h"
|
||||
#include <cstddef>
|
||||
|
||||
#ifndef CMSIS_DEVICE_FILE
|
||||
#error "CMSIS_DEVICE_FILE path not defined in McuConfig.h"
|
||||
#else
|
||||
#include CMSIS_DEVICE_FILE
|
||||
#endif
|
||||
|
||||
namespace LFramework {
|
||||
namespace Mcu {
|
||||
inline size_t getCurrentInterruptHandlerIndex(){
|
||||
return __get_IPSR();
|
||||
}
|
||||
|
||||
inline bool isHandlingInterrupt() {
|
||||
return getCurrentInterruptHandlerIndex() != 0;
|
||||
}
|
||||
|
||||
inline bool isDebuggerAttached() {
|
||||
return (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) != 0;
|
||||
}
|
||||
|
||||
inline void setBreakpoint() {
|
||||
if(isDebuggerAttached){
|
||||
__BKPT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MCUFRAMEWORK_MCU_H_ */
|
||||
@@ -1 +0,0 @@
|
||||
add_subdirectory(PHY)
|
||||
@@ -1,9 +0,0 @@
|
||||
target_sources(${PROJECT_NAME}
|
||||
INTERFACE
|
||||
Stm32FsPhy.h
|
||||
UsbDeviceSoftPhy.h
|
||||
UsbInternalFsDeviceDriver.h
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
#ifndef Stm32FsPhy_h__
|
||||
#define Stm32FsPhy_h__
|
||||
|
||||
namespace LFramework {
|
||||
|
||||
template<typename Child>
|
||||
class Stm32FsPhy {
|
||||
public:
|
||||
/*void UsbDevice::start() {
|
||||
HAL_PCD_Start(_pcd);
|
||||
}*/
|
||||
|
||||
//UsbDevice(PCD_HandleTypeDef* pcd);
|
||||
|
||||
/*void initPHY() {
|
||||
|
||||
_pcd->Instance = USB_OTG_FS;
|
||||
_pcd->Init.dev_endpoints = 1;
|
||||
_pcd->Init.speed = PCD_SPEED_FULL;
|
||||
_pcd->Init.dma_enable = DISABLE;
|
||||
_pcd->Init.Sof_enable = DISABLE;
|
||||
_pcd->Init.ep0_mps = 64;
|
||||
_pcd->Init.phy_itface = PCD_PHY_EMBEDDED;
|
||||
_pcd->Init.low_power_enable = DISABLE;
|
||||
_pcd->Init.lpm_enable = DISABLE;
|
||||
_pcd->Init.vbus_sensing_enable = DISABLE;
|
||||
_pcd->Init.use_dedicated_ep1 = DISABLE;
|
||||
//_pcd->Init.battery_charging_enable = DISABLE;
|
||||
HAL_PCD_Init(_pcd);
|
||||
|
||||
//HAL_PCD_SetRxFiFo(&USBD_PCD, 0x80);
|
||||
//HAL_PCD_SetTxFiFo(&USBD_PCD, 0, 0x20);
|
||||
//HAL_PCD_SetTxFiFo(&USBD_PCD, 1, 0x40);
|
||||
|
||||
HAL_PCD_SetRxFiFo(_pcd, 0x80);
|
||||
HAL_PCD_SetTxFiFo(_pcd, 0, 0x40);
|
||||
HAL_PCD_SetTxFiFo(_pcd, 1, 0x80);
|
||||
}*/
|
||||
|
||||
void connect() {
|
||||
//HAL_PCD_DevConnect(_pcd);
|
||||
}
|
||||
|
||||
void disconnect() {
|
||||
//HAL_PCD_DevDisconnect(_pcd);
|
||||
}
|
||||
|
||||
//PCD_HandleTypeDef* _pcd;
|
||||
};
|
||||
}
|
||||
#endif // Stm32FsPhy_h__
|
||||
@@ -1,211 +0,0 @@
|
||||
#ifndef UsbDeviceSoftPhy_h__
|
||||
#define UsbDeviceSoftPhy_h__
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
namespace LFramework {
|
||||
namespace USB {
|
||||
|
||||
static const char* StageStrings[] = { "WaitForConnection", "Reset1", "GetDeviceDescriptor", "Reset2" };
|
||||
|
||||
class SoftEndpoint {
|
||||
public:
|
||||
bool isIn = false;
|
||||
bool isOpen = false;
|
||||
uint8_t maxPacketSize = 0;
|
||||
bool receiving = false;
|
||||
std::queue<std::vector<uint8_t>> packets;
|
||||
};
|
||||
|
||||
template<typename Device>
|
||||
class UsbDeviceSoftPhy {
|
||||
public:
|
||||
static constexpr uint8_t MaxEndpointsCount = 16;
|
||||
static constexpr uint8_t MaxPacketSize = 64;
|
||||
|
||||
|
||||
void connect() {
|
||||
_connected = true;
|
||||
}
|
||||
|
||||
void start() {
|
||||
if (_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
_running = true;
|
||||
setStage(Stage::WaitForConnection);
|
||||
_usbThread = std::thread(std::bind(&UsbDeviceSoftPhy::threadHandler, this));
|
||||
}
|
||||
|
||||
void stop() {
|
||||
|
||||
if (_running) {
|
||||
_running = false;
|
||||
_usbThread.join;
|
||||
}
|
||||
}
|
||||
|
||||
enum class Stage {
|
||||
WaitForConnection,
|
||||
Reset1,
|
||||
GetDeviceDescriptor,
|
||||
Reset2,
|
||||
StageCount
|
||||
};
|
||||
|
||||
|
||||
|
||||
UsbDeviceSoftPhy() {
|
||||
_stageHandlers[static_cast<int>(Stage::WaitForConnection)] = &UsbDeviceSoftPhy::stageWaitForConnection;
|
||||
_stageHandlers[static_cast<int>(Stage::Reset1)] = &UsbDeviceSoftPhy::stageReset1;
|
||||
_stageHandlers[static_cast<int>(Stage::GetDeviceDescriptor)] = &UsbDeviceSoftPhy::stageGetDeviceDescriptor;
|
||||
_stageHandlers[static_cast<int>(Stage::Reset2)] = &UsbDeviceSoftPhy::stageReset2;
|
||||
}
|
||||
|
||||
Device* asDevice() {
|
||||
return static_cast<Device*>(this);
|
||||
}
|
||||
|
||||
static bool isValidPacketSize(uint8_t maxPacketSize, EndpointAddress endpointAddress) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool openEndpoint(EndpointAddress address, uint8_t maxPacketSize, EndpointType type) {
|
||||
if(!isValidPacketSize(maxPacketSize, address)) {
|
||||
std::cout << "Failed to open endpoint with address " << address.value << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
SoftEndpoint& endpoint = address.isIn() ? _inEndpoints[address.index()] : _outEndpoints[address.index()];
|
||||
endpoint.maxPacketSize = maxPacketSize;
|
||||
endpoint.isOpen = true;
|
||||
std::cout << "Open endpoint with address " << (int)address.value << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
void closeEndpoint(EndpointAddress address) {
|
||||
SoftEndpoint& endpoint = address.isIn() ? _inEndpoints[address.index()] : _outEndpoints[address.index()];
|
||||
endpoint.isOpen = false;
|
||||
endpoint.packets.clear();
|
||||
}
|
||||
|
||||
void beginReceive(EndpointAddress address, void* buffer, uint8_t size) {
|
||||
auto& ep = _outEndpoints[address.index()];
|
||||
ep.receiving = true;
|
||||
}
|
||||
|
||||
void beginTransmit(EndpointAddress address, void* buffer, uint8_t size) {
|
||||
auto& ep = _inEndpoints[address.index()];
|
||||
size = (std::min)(size, ep.maxPacketSize);
|
||||
std::vector<uint8_t> packet;
|
||||
if(size != 0) {
|
||||
packet.insert(packet.end(), (uint8_t*)buffer, (uint8_t*)buffer + size);
|
||||
}
|
||||
ep.packets.push(packet);
|
||||
}
|
||||
private:
|
||||
|
||||
void setStage(Stage stage) {
|
||||
std::cout << "Change stage from " << StageStrings[(int)_currentStage] << " to " << StageStrings[(int)stage] << std::endl;
|
||||
_currentStage = stage;
|
||||
|
||||
if(_currentStage == Stage::WaitForConnection) {
|
||||
for(auto& ep : _inEndpoints) {
|
||||
ep.isOpen = false;
|
||||
ep.receiving = false;
|
||||
ep.packets = {};
|
||||
}
|
||||
for (auto& ep : _outEndpoints) {
|
||||
ep.isOpen = false;
|
||||
ep.receiving = false;
|
||||
ep.packets = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SoftEndpoint _inEndpoints[MaxEndpointsCount];
|
||||
SoftEndpoint _outEndpoints[MaxEndpointsCount];
|
||||
|
||||
Stage _currentStage = Stage::WaitForConnection;
|
||||
|
||||
void stageWaitForConnection() {
|
||||
if (_connected) {
|
||||
std::cout << "Device connected" << std::endl;
|
||||
setStage(Stage::Reset1);
|
||||
|
||||
}
|
||||
}
|
||||
void stageReset1() {
|
||||
std::cout << "Device reset1 begin" << std::endl;
|
||||
asDevice()->onReset();
|
||||
std::cout << "Device reset1 end" << std::endl;
|
||||
setStage(Stage::GetDeviceDescriptor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<uint8_t> controlIn(SetupPacket setup) {
|
||||
/*SetupPacket setup;
|
||||
setup.bmRequestType.Direction = RequestDirection::DeviceToHost;
|
||||
setup.bmRequestType.Recipient = RequestRecipient::Device;
|
||||
setup.bmRequestType.Type = RequestType::Standard;*/
|
||||
|
||||
asDevice()->onSetup(&setup);
|
||||
|
||||
|
||||
std::vector<uint8_t> rxBuffer;
|
||||
auto& ep = _inEndpoints[0];
|
||||
for (;;) {
|
||||
if(ep.isOpen) {
|
||||
if(!ep.packets.empty()) {
|
||||
auto packet = ep.packets.front();
|
||||
ep.packets.pop();
|
||||
if(packet.empty()) {
|
||||
return rxBuffer;
|
||||
}else {
|
||||
rxBuffer.insert(rxBuffer.end(), packet.begin(), packet.end());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Sleep(1);
|
||||
}
|
||||
}
|
||||
void stageGetDeviceDescriptor() {
|
||||
SetupPacket setup;
|
||||
setup.bmRequestType.Direction = RequestDirection::DeviceToHost;
|
||||
setup.bmRequestType.Recipient = RequestRecipient::Device;
|
||||
setup.bmRequestType.Type = RequestType::Standard;
|
||||
setup.bRequest = SetupRequest::GetDescriptor;
|
||||
setup.wIndex = 0;
|
||||
setup.wValue = ((uint8_t)DescriptorType::DeviceDescriptor << 8) | 0;
|
||||
setup.wLength = sizeof(DeviceDescriptor);
|
||||
|
||||
auto descriptorData = controlIn(setup);
|
||||
|
||||
for (;;);
|
||||
}
|
||||
void stageReset2() {
|
||||
|
||||
}
|
||||
void threadHandler() {
|
||||
while (_running) {
|
||||
(this->*_stageHandlers[static_cast<int>(_currentStage)])();
|
||||
Sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
std::array<void(UsbDeviceSoftPhy::*)(), static_cast<int>(Stage::StageCount)> _stageHandlers;
|
||||
|
||||
std::thread _usbThread;
|
||||
bool _connected = false;
|
||||
bool _running = false;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UsbDeviceSoftPhy_h__
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* UsbInternalFsDeviceDriver.h
|
||||
*
|
||||
* Created on: 1 îêò. 2017 ã.
|
||||
* Author: l-pro
|
||||
*/
|
||||
|
||||
#ifndef LFRAMEWORK_MCU_USBDEVICE_USBINTERNALFSDEVICEDRIVER_H_
|
||||
#define LFRAMEWORK_MCU_USBDEVICE_USBINTERNALFSDEVICEDRIVER_H_
|
||||
|
||||
namespace LFramework {
|
||||
namespace USB {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* LFRAMEWORK_MCU_USBDEVICE_USBINTERNALFSDEVICEDRIVER_H_ */
|
||||
@@ -1,8 +0,0 @@
|
||||
target_sources(${PROJECT_NAME}
|
||||
INTERFACE
|
||||
HalLibrary.h
|
||||
HardFaultHandler.h
|
||||
|
||||
HardFaultHandler.cpp
|
||||
)
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* HalLibrary.h
|
||||
*
|
||||
* Created on: 17 ñåíò. 2017 ã.
|
||||
* Author: l-pro
|
||||
*/
|
||||
|
||||
#ifndef LFRAMEWORK_MCU_STM32_HALLIBRARY_H_
|
||||
#define LFRAMEWORK_MCU_STM32_HALLIBRARY_H_
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* LFRAMEWORK_MCU_STM32_HALLIBRARY_H_ */
|
||||
@@ -1,41 +0,0 @@
|
||||
#ifndef _WIN32
|
||||
|
||||
|
||||
#include <LFramework/Debug.h>
|
||||
#include <LFramework/IO/StreamWriter.h>
|
||||
|
||||
extern "C" {
|
||||
void HardFaultHandlerExtended(unsigned int * hardfault_args){
|
||||
unsigned int stacked_r0;
|
||||
unsigned int stacked_r1;
|
||||
unsigned int stacked_r2;
|
||||
unsigned int stacked_r3;
|
||||
unsigned int stacked_r12;
|
||||
unsigned int stacked_lr;
|
||||
unsigned int stacked_pc;
|
||||
unsigned int stacked_psr;
|
||||
|
||||
stacked_r0 = ((unsigned int)hardfault_args[0]);
|
||||
stacked_r1 = ((unsigned int)hardfault_args[1]);
|
||||
stacked_r2 = ((unsigned int)hardfault_args[2]);
|
||||
stacked_r3 = ((unsigned int)hardfault_args[3]);
|
||||
|
||||
stacked_r12 = ((unsigned int)hardfault_args[4]);
|
||||
stacked_lr = ((unsigned int)hardfault_args[5]);
|
||||
stacked_pc = ((unsigned int)hardfault_args[6]);
|
||||
stacked_psr = ((unsigned int)hardfault_args[7]);
|
||||
|
||||
lfFatal() << "----------";
|
||||
lfFatal() << "Hard fault";
|
||||
lfFatal() << "----------";
|
||||
|
||||
lfFatal() << "stacked_lr: 0x" << LFramework::HexFormat(stacked_lr) ;
|
||||
lfFatal() << "stacked_pc: 0x" << LFramework::HexFormat(stacked_pc) ;
|
||||
|
||||
while(true){
|
||||
asm("nop");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define HARD_FAULT_HANDLER \
|
||||
__asm( ".syntax unified\n" \
|
||||
"MOVS R0, #4 \n" \
|
||||
"MOV R1, LR \n" \
|
||||
"TST R0, R1 \n" \
|
||||
"BEQ _MSP \n" \
|
||||
"MRS R0, PSP \n" \
|
||||
"B HardFaultHandlerExtended \n" \
|
||||
"_MSP: \n" \
|
||||
"MRS R0, MSP \n" \
|
||||
"B HardFaultHandlerExtended \n" \
|
||||
".syntax divided\n") ;
|
||||
@@ -1,4 +0,0 @@
|
||||
target_sources(${PROJECT_NAME}
|
||||
INTERFACE
|
||||
ForEach.h
|
||||
)
|
||||
@@ -1,76 +0,0 @@
|
||||
#ifndef ForEach_h__
|
||||
#define ForEach_h__
|
||||
|
||||
#define UNPACK(...) __VA_ARGS__
|
||||
|
||||
//Count of commas == max args count (32)
|
||||
#define CNT_PREFIX__CNT_POSTFIX ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0
|
||||
|
||||
#define COUNTER_SEQUENCE 32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
|
||||
|
||||
#define ARGS_CNT2(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31, N, ...) N
|
||||
#define ARGS_CNT1(__ARGS) ARGS_CNT2 __ARGS
|
||||
#define ARGS_CNT(...) UNPACK(ARGS_CNT1((CNT_PREFIX_ ## __VA_ARGS__ ## _CNT_POSTFIX, COUNTER_SEQUENCE)))
|
||||
|
||||
#define CONCAT(arg1, arg2) CONCAT1(arg1, arg2)
|
||||
#define CONCAT1(arg1, arg2) CONCAT2(arg1, arg2)
|
||||
#define CONCAT2(arg1, arg2) arg1##arg2
|
||||
|
||||
#define FOR_EACH_0(macro, runner, ...)
|
||||
#define FOR_EACH_1(macro, runner, x) runner(macro, 0, LAST, x)
|
||||
#define FOR_EACH_2(macro, runner, x, ...) runner(macro, 1, NOT_LAST, x) UNPACK(FOR_EACH_1(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_3(macro, runner, x, ...) runner(macro, 2, NOT_LAST, x) UNPACK(FOR_EACH_2(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_4(macro, runner, x, ...) runner(macro, 3, NOT_LAST, x) UNPACK(FOR_EACH_3(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_5(macro, runner, x, ...) runner(macro, 4, NOT_LAST, x) UNPACK(FOR_EACH_4(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_6(macro, runner, x, ...) runner(macro, 5, NOT_LAST, x) UNPACK(FOR_EACH_5(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_7(macro, runner, x, ...) runner(macro, 6, NOT_LAST, x) UNPACK(FOR_EACH_6(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_8(macro, runner, x, ...) runner(macro, 7, NOT_LAST, x) UNPACK(FOR_EACH_7(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_9(macro, runner, x, ...) runner(macro, 8, NOT_LAST, x) UNPACK(FOR_EACH_8(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_10(macro, runner, x, ...) runner(macro, 9, NOT_LAST, x) UNPACK(FOR_EACH_9(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_11(macro, runner, x, ...) runner(macro, 10, NOT_LAST, x) UNPACK(FOR_EACH_10(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_12(macro, runner, x, ...) runner(macro, 11, NOT_LAST, x) UNPACK(FOR_EACH_11(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_13(macro, runner, x, ...) runner(macro, 12, NOT_LAST, x) UNPACK(FOR_EACH_12(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_14(macro, runner, x, ...) runner(macro, 13, NOT_LAST, x) UNPACK(FOR_EACH_13(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_15(macro, runner, x, ...) runner(macro, 14, NOT_LAST, x) UNPACK(FOR_EACH_14(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_16(macro, runner, x, ...) runner(macro, 15, NOT_LAST, x) UNPACK(FOR_EACH_15(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_17(macro, runner, x, ...) runner(macro, 16, NOT_LAST, x) UNPACK(FOR_EACH_16(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_18(macro, runner, x, ...) runner(macro, 17, NOT_LAST, x) UNPACK(FOR_EACH_17(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_19(macro, runner, x, ...) runner(macro, 18, NOT_LAST, x) UNPACK(FOR_EACH_18(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_20(macro, runner, x, ...) runner(macro, 19, NOT_LAST, x) UNPACK(FOR_EACH_19(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_21(macro, runner, x, ...) runner(macro, 20, NOT_LAST, x) UNPACK(FOR_EACH_20(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_22(macro, runner, x, ...) runner(macro, 21, NOT_LAST, x) UNPACK(FOR_EACH_21(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_23(macro, runner, x, ...) runner(macro, 22, NOT_LAST, x) UNPACK(FOR_EACH_22(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_24(macro, runner, x, ...) runner(macro, 23, NOT_LAST, x) UNPACK(FOR_EACH_23(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_25(macro, runner, x, ...) runner(macro, 24, NOT_LAST, x) UNPACK(FOR_EACH_24(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_26(macro, runner, x, ...) runner(macro, 25, NOT_LAST, x) UNPACK(FOR_EACH_25(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_27(macro, runner, x, ...) runner(macro, 26, NOT_LAST, x) UNPACK(FOR_EACH_26(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_28(macro, runner, x, ...) runner(macro, 27, NOT_LAST, x) UNPACK(FOR_EACH_27(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_29(macro, runner, x, ...) runner(macro, 28, NOT_LAST, x) UNPACK(FOR_EACH_28(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_30(macro, runner, x, ...) runner(macro, 29, NOT_LAST, x) UNPACK(FOR_EACH_29(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_31(macro, runner, x, ...) runner(macro, 30, NOT_LAST, x) UNPACK(FOR_EACH_30(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_32(macro, runner, x, ...) runner(macro, 31, NOT_LAST, x) UNPACK(FOR_EACH_31(macro, runner, __VA_ARGS__))
|
||||
|
||||
|
||||
#define FOREACH_SIMPLE_RUNNER(macro, id, isLast, x) macro(x)
|
||||
#define FOREACH_INDEXED_RUNNER(macro, id, isLast, x) macro(id, x)
|
||||
|
||||
#define FOREACH_SIMPLE_RUNNER_ISLAST(macro, id, isLast, x) macro(isLast, x)
|
||||
|
||||
#define FOR_EACH1_R(macro, runner, N, ...) UNPACK(CONCAT(FOR_EACH_, N)(macro, runner, __VA_ARGS__))
|
||||
#define FOR_EACH_R(macro, runner, ...) UNPACK(FOR_EACH1_R(macro, runner, ARGS_CNT(__VA_ARGS__), __VA_ARGS__))
|
||||
|
||||
#define FOR_EACH(macro, ...) FOR_EACH_R(macro, FOREACH_SIMPLE_RUNNER, __VA_ARGS__)
|
||||
|
||||
#define FOR_EACH_N(macro, ...) FOR_EACH_R(macro, FOREACH_INDEXED_RUNNER, __VA_ARGS__)
|
||||
#define FOR_EACH_L(macro, ...) FOR_EACH_R(macro, FOREACH_SIMPLE_RUNNER_ISLAST, __VA_ARGS__)
|
||||
|
||||
static_assert(ARGS_CNT() == 0, "ARGS_CNT test fail");
|
||||
static_assert(ARGS_CNT(a) == 1, "ARGS_CNT test fail");
|
||||
static_assert(ARGS_CNT(a, a) == 2, "ARGS_CNT test fail");
|
||||
static_assert(ARGS_CNT(a, a, a, a) == 4, "ARGS_CNT test fail");
|
||||
static_assert(ARGS_CNT(a, a, a, a, a, a, a, a) == 8, "ARGS_CNT test fail");
|
||||
static_assert(ARGS_CNT(a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a) == 16, "ARGS_CNT test fail");
|
||||
static_assert(ARGS_CNT(a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a) == 32, "ARGS_CNT test fail");
|
||||
|
||||
|
||||
#endif // ForEach_h__
|
||||
@@ -1,71 +0,0 @@
|
||||
#include "../Macro/ForEach.h"
|
||||
|
||||
#define COMMA_LAST(x) x
|
||||
#define COMMA_NOT_LAST(x) x ,
|
||||
|
||||
#define JOIN_IMPL(last, x) COMMA_##last(x)
|
||||
|
||||
#define JOIN2(...) UNPACK(FOR_EACH_L(JOIN_IMPL, __VA_ARGS__))
|
||||
#define JOIN(...) UNPACK( JOIN2 (__VA_ARGS__) )
|
||||
|
||||
template<typename T>
|
||||
struct Reflect {
|
||||
|
||||
};
|
||||
|
||||
|
||||
#define GEN_FIELD2(type_, name_) type_ name_;
|
||||
#define GEN_FIELD(field_) GEN_FIELD2 field_
|
||||
|
||||
#define GEN_FIELD_GETTER2(id_, type_, name_) if constexpr(ID == FieldsCount - 1 - id_) return object. name_;
|
||||
#define GEN_FIELD_GETTER1(id_, ...) UNPACK(GEN_FIELD_GETTER2(id_, __VA_ARGS__))
|
||||
#define GEN_FIELD_GETTER(id_, ...) GEN_FIELD_GETTER1(id_, UNPACK __VA_ARGS__ )
|
||||
|
||||
|
||||
#define DEFINE_STRUCT_RTTI(structName_, publicFields_) \
|
||||
template<> struct Reflect<structName_> { \
|
||||
static const char* Name() {return #structName_; } \
|
||||
static constexpr size_t FieldsCount = ARGS_CNT(UNPACK publicFields_) ; \
|
||||
template<size_t ID> static auto& getField(structName_& object){ \
|
||||
FOR_EACH_N(GEN_FIELD_GETTER, UNPACK publicFields_) ; \
|
||||
} \
|
||||
};
|
||||
#define DEFINE_STRUCT_TYPE(structName_, publicFields_) struct structName_ { FOR_EACH(GEN_FIELD, UNPACK publicFields_) };
|
||||
|
||||
|
||||
#define DEFINE_STRUCT(structName_, publicFields_) \
|
||||
DEFINE_STRUCT_TYPE(structName_, publicFields_) \
|
||||
DEFINE_STRUCT_RTTI(structName_, publicFields_)
|
||||
|
||||
|
||||
|
||||
#define UNPACK_TEMPLATE_PARAMS1(last_, type_, name_) COMMA_##last_(type_ name_)
|
||||
#define UNPACK_TEMPLATE_PARAM1(last, ...) UNPACK( UNPACK_TEMPLATE_PARAMS1(last, __VA_ARGS__ ))
|
||||
#define UNPACK_TEMPLATE_PARAM(last, x) UNPACK_TEMPLATE_PARAM1(last, UNPACK x)
|
||||
|
||||
|
||||
#define UNPACK_TEMPLATE_ARGS1(last_, type_, name_) COMMA_##last_(name_)
|
||||
#define UNPACK_TEMPLATE_ARG1(last, ...) UNPACK( UNPACK_TEMPLATE_ARGS1(last, __VA_ARGS__ ))
|
||||
#define UNPACK_TEMPLATE_ARG(last, x) UNPACK_TEMPLATE_ARG1(last, UNPACK x)
|
||||
|
||||
#define UNPACK_TEMPLATE_PARAMS(...) UNPACK (FOR_EACH_L(UNPACK_TEMPLATE_PARAM, __VA_ARGS__) )
|
||||
|
||||
|
||||
|
||||
#define UNPACK_TEMPLATE_ARGS(...) UNPACK (FOR_EACH_L(UNPACK_TEMPLATE_ARG, __VA_ARGS__) )
|
||||
|
||||
|
||||
#define DEFINE_TEMPLATE_STRUCT_RTTI(templateParams_, structName_, publicFields_) \
|
||||
template< UNPACK_TEMPLATE_PARAMS templateParams_ > struct Reflect<structName_< UNPACK_TEMPLATE_ARGS templateParams_ > > { \
|
||||
static const char* Name() {return #structName_; } \
|
||||
static constexpr size_t FieldsCount = ARGS_CNT(UNPACK publicFields_) ; \
|
||||
template<size_t ID> static auto& getField(structName_ < UNPACK_TEMPLATE_ARGS templateParams_ > & object){ \
|
||||
FOR_EACH_N(GEN_FIELD_GETTER, UNPACK publicFields_) ; \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DEFINE_TEMPLATE_STRUCT_TYPE(templateParams_, structName_, publicFields_) template< UNPACK_TEMPLATE_PARAMS templateParams_ > struct structName_ { FOR_EACH(GEN_FIELD, UNPACK publicFields_) };
|
||||
|
||||
#define DEFINE_TEMPLATE_STRUCT(templateParams_, structName_, publicFields_) \
|
||||
DEFINE_TEMPLATE_STRUCT_TYPE(templateParams_, structName_, publicFields_) \
|
||||
DEFINE_TEMPLATE_STRUCT_RTTI(templateParams_, structName_, publicFields_)
|
||||
-167
@@ -1,167 +0,0 @@
|
||||
#include "Detect/DetectOS.h"
|
||||
#include "Assert.h"
|
||||
|
||||
#if defined(LF_NEWLIB_TO_RTOS_MALLOC)
|
||||
#include "FreeRTOS.h"
|
||||
#endif
|
||||
|
||||
#if defined(LF_SYSCALLS_STUBS) || defined(LF_NEWLIB_TO_RTOS_MALLOC)
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include "Debug.h"
|
||||
#include "System.h"
|
||||
#include <malloc.h>
|
||||
#endif//Todo check right files for different configuration
|
||||
|
||||
extern "C" {
|
||||
|
||||
#if defined(LF_SYSCALLS_STUBS)
|
||||
|
||||
//extern int errno;
|
||||
//register char * stack_ptr asm("sp");
|
||||
|
||||
#ifndef __errno_r
|
||||
#include <sys/reent.h>
|
||||
#define __errno_r(reent) reent->_errno
|
||||
#endif
|
||||
|
||||
caddr_t _sbrk(int incr) {
|
||||
static_cast<void>(incr);
|
||||
//std::terminate(); //Do not use newlib memory management
|
||||
for(;;);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int _write_r(struct _reent* r, int file, char* ptr, int len){
|
||||
static_cast<void>(r);
|
||||
static_cast<void>(ptr);
|
||||
|
||||
if(stdout->_file != file && stderr->_file != file){
|
||||
for(;;);//Assert: unknown file descriptor
|
||||
}
|
||||
|
||||
#if defined(AF_TERMINAL_STDIO)
|
||||
Terminal::write(ptr, len);
|
||||
#endif
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int _read_r(struct _reent *r, int file, char * ptr, int len)
|
||||
{
|
||||
(void)r;
|
||||
(void)file;
|
||||
(void)ptr;
|
||||
(void)len;
|
||||
__errno_r(r) = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _lseek_r(struct _reent *r, int file, int ptr, int dir){
|
||||
(void)r;
|
||||
(void)file;
|
||||
(void)ptr;
|
||||
(void)dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _close_r(struct _reent *r, int file){
|
||||
(void)r;
|
||||
(void)file;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _open_r ( struct _reent *ptr, const char *file, int flags, int mode ){
|
||||
static_cast<void>(ptr);
|
||||
static_cast<void>(file);
|
||||
static_cast<void>(flags);
|
||||
static_cast<void>(mode);
|
||||
int fd = -1;
|
||||
return fd;
|
||||
}
|
||||
|
||||
int _fstat_r(struct _reent *r, int file, struct stat * st){
|
||||
(void)r;
|
||||
(void)file;
|
||||
memset(st, 0, sizeof(*st));
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _isatty_r(struct _reent *r, int fd){
|
||||
(void)r;
|
||||
(void)fd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _kill (int a, int b){
|
||||
(void)a;
|
||||
(void)b;
|
||||
return 0;
|
||||
}
|
||||
int _getpid(int a){
|
||||
(void)a;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
//memory management
|
||||
|
||||
#if LF_TARGET_OS == LF_OS_FREERTOS || defined(LF_SYSCALLS_STUBS)
|
||||
|
||||
void __assert_func(const char * file, int line, const char * func, const char * error){
|
||||
lfDebug() << "libc assert";
|
||||
lfDebug() << "File: " << file;
|
||||
//lfDebug() << "Line: " << line;
|
||||
lfDebug() << "Function: " << func;
|
||||
lfDebug() << "Expression: " << error;
|
||||
for(;;);
|
||||
}
|
||||
void _exit(int status){
|
||||
lfDebug() << "_exit called";
|
||||
for(;;);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(LF_NEWLIB_TO_RTOS_MALLOC)
|
||||
|
||||
|
||||
void* _realloc_r(struct _reent *re, void* oldAddr, size_t newSize) {
|
||||
static_cast<void>(re);
|
||||
static_cast<void>(oldAddr);
|
||||
static_cast<void>(newSize);
|
||||
lfAssert(false); //No mechanism is currently available to correctly reallocate memory, so just don't allow it for now
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* _calloc_r(struct _reent *re, size_t num, size_t size) {
|
||||
static_cast<void>(re);
|
||||
void* result = pvPortMalloc(num*size);
|
||||
if(result){
|
||||
//calloc should zero-initialize allocated memory
|
||||
uint8_t* bytes = (uint8_t*)result;
|
||||
for(size_t i = 0; i < (num * size); ++i){
|
||||
bytes[i] = 0;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void* _malloc_r(struct _reent *re, size_t size) {
|
||||
static_cast<void>(re);
|
||||
return pvPortMalloc(size);
|
||||
}
|
||||
|
||||
void _free_r(struct _reent *re, void* ptr) {
|
||||
static_cast<void>(re);
|
||||
vPortFree(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
} //extern "C"
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
#ifndef System_h__
|
||||
#define System_h__
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "Detect/DetectOS.h"
|
||||
|
||||
|
||||
#if LF_TARGET_OS == LF_OS_FREERTOS
|
||||
#include "SystemArmCortexM.h"
|
||||
#elif LF_TARGET_OS == LF_OS_WINDOWS
|
||||
#include "SystemWindows.h"
|
||||
#endif
|
||||
|
||||
|
||||
#endif // System_h__
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
#ifndef CMSIS_DEVICE_FILE
|
||||
#error "CMSIS_DEVICE_FILE path not defined in McuConfig.h"
|
||||
#else
|
||||
#include CMSIS_DEVICE_FILE
|
||||
#endif
|
||||
|
||||
namespace LFramework {
|
||||
namespace System {
|
||||
inline size_t getCurrentInterruptHandlerIndex() {
|
||||
return __get_IPSR();
|
||||
}
|
||||
|
||||
inline bool isHandlingInterrupt() {
|
||||
return getCurrentInterruptHandlerIndex() != 0;
|
||||
}
|
||||
|
||||
inline bool isDebuggerAttached() {
|
||||
return (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) != 0;
|
||||
}
|
||||
|
||||
inline void setBreakpoint() {
|
||||
if (isDebuggerAttached) {
|
||||
__BKPT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
#ifndef SystemWindows_h__
|
||||
#define SystemWindows_h__
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace LFramework {
|
||||
namespace System {
|
||||
inline size_t getCurrentInterruptHandlerIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool isHandlingInterrupt() {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isDebuggerAttached() {
|
||||
return IsDebuggerPresent() == TRUE;
|
||||
}
|
||||
|
||||
inline void setBreakpoint() {
|
||||
if (isDebuggerAttached()) {
|
||||
DebugBreak();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SystemWindows_h__
|
||||
@@ -1,87 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <codecvt>
|
||||
#include <string>
|
||||
|
||||
namespace LFramework::Text {
|
||||
class Encoding {
|
||||
public:
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1900
|
||||
// https://social.msdn.microsoft.com/Forums/en-US/8f40dcd8-c67f-4eba-9134-a19b9178e481/vs-2015-rc-linker-stdcodecvt-error?forum=vcgeneral
|
||||
#define _MSVC_CONVERT_WORKAROUND
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSVC_CONVERT_WORKAROUND)
|
||||
static inline std::wstring_convert<std::codecvt_utf8<int32_t>, int32_t> s_u32Converter;
|
||||
static inline std::wstring_convert<std::codecvt_utf8_utf16<int16_t>, int16_t> s_u16Converter;
|
||||
#else
|
||||
static inline std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> s_u32Converter;
|
||||
static inline std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> s_u16Converter;
|
||||
#endif
|
||||
|
||||
static std::wstring u8StringToWString(const std::string& src) {
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
|
||||
return converter.from_bytes(src);
|
||||
}
|
||||
|
||||
static std::string wStringToU8String(const std::wstring& src) {
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> convert;
|
||||
return convert.to_bytes(src);
|
||||
}
|
||||
|
||||
static std::u32string u16StringToU32String(const std::u16string& u16String)
|
||||
{
|
||||
std::string temp{ u16StringToU8String(u16String) };
|
||||
|
||||
return u8StringToU32String(temp);
|
||||
}
|
||||
|
||||
static std::string u16StringToU8String(const std::u16string& u16String)
|
||||
{
|
||||
#if defined(_MSVC_CONVERT_WORKAROUND)
|
||||
using workaround_str = std::basic_string<int16_t, std::char_traits<int16_t>, std::allocator<int16_t> >;
|
||||
workaround_str workaround(reinterpret_cast<const int16_t*>(u16String.c_str()));
|
||||
return s_u16Converter.to_bytes(workaround);
|
||||
#else
|
||||
return s_u16Converter.to_bytes(u16String);
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::string u32StringToU8String(const std::u32string& u32String)
|
||||
{
|
||||
#if defined(_MSVC_CONVERT_WORKAROUND)
|
||||
using workaround_str = std::basic_string<int32_t, std::char_traits<int32_t>, std::allocator<int32_t> >;
|
||||
workaround_str workaround(reinterpret_cast<const int32_t*>(u32String.c_str()));
|
||||
return s_u32Converter.to_bytes(workaround);
|
||||
#else
|
||||
return s_u32Converter.to_bytes(u32String);
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::u16string u8StringToU16String(const std::string& u8String)
|
||||
{
|
||||
#if defined(_MSVC_CONVERT_WORKAROUND)
|
||||
auto&& workaround = s_u16Converter.from_bytes(u8String);
|
||||
return std::u16string(reinterpret_cast<const char16_t*>(workaround.c_str()));
|
||||
#else
|
||||
return s_u16Converter.from_bytes(u8String);
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::u32string u8StringToU32String(const std::string& u8String)
|
||||
{
|
||||
#if defined(_MSVC_CONVERT_WORKAROUND)
|
||||
auto&& workaround = s_u32Converter.from_bytes(u8String);
|
||||
return std::u32string(reinterpret_cast<const char32_t*>(workaround.c_str()));
|
||||
#else
|
||||
return s_u32Converter.from_bytes(u8String);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#ifdef _MSVC_CONVERT_WORKAROUND
|
||||
#undef _MSVC_CONVERT_WORKAROUND
|
||||
#endif
|
||||
@@ -1,21 +0,0 @@
|
||||
add_library(LFrameworkThreading INTERFACE )
|
||||
add_library(LFramework::Threading ALIAS LFrameworkThreading )
|
||||
|
||||
target_sources(LFrameworkThreading
|
||||
INTERFACE
|
||||
CriticalSection.h
|
||||
CriticalSectionFreeRTOS.h
|
||||
CriticalSectionStd.h
|
||||
Semaphore.h
|
||||
SemaphoreFreeRTOS.h
|
||||
SemaphoreStd.h
|
||||
Thread.h
|
||||
ThreadFreeRTOS.h
|
||||
ThreadPlatform.h
|
||||
ThreadStd.h
|
||||
|
||||
CriticalSectionStd.cpp
|
||||
SemaphoreStdTest.cpp
|
||||
Thread.cpp
|
||||
ThreadTest.cpp
|
||||
)
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <LFramework/Detect/DetectOS.h>
|
||||
|
||||
#if LF_TARGET_OS == LF_OS_FREERTOS
|
||||
#include "CriticalSectionFreeRTOS.h"
|
||||
#elif (LF_TARGET_OS == LF_OS_WINDOWS) || (LF_TARGET_OS == LF_OS_LINUX)
|
||||
#include "CriticalSectionStd.h"
|
||||
#endif
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "stm32f746xx.h"
|
||||
|
||||
namespace LFramework::Threading {
|
||||
|
||||
class CriticalSection {
|
||||
public:
|
||||
CriticalSection() {
|
||||
_status = lock();
|
||||
}
|
||||
|
||||
~CriticalSection() {
|
||||
unlock();
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
unlock(_status);
|
||||
}
|
||||
|
||||
static size_t getCurrentInterruptNumber() {
|
||||
return __get_IPSR();
|
||||
}
|
||||
|
||||
static bool isInterruptHandling() {
|
||||
return getCurrentInterruptNumber() != 0;
|
||||
}
|
||||
|
||||
static uint32_t lock() {
|
||||
if (isInterruptHandling()) {
|
||||
return taskENTER_CRITICAL_FROM_ISR();
|
||||
}
|
||||
else {
|
||||
taskENTER_CRITICAL();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void unlock(uint32_t irqStatus) {
|
||||
if (isInterruptHandling()) {
|
||||
taskEXIT_CRITICAL_FROM_ISR(irqStatus);
|
||||
}
|
||||
else {
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t _status = 0;
|
||||
};
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#include <LFramework/Detect/DetectOS.h>
|
||||
|
||||
#if (LF_TARGET_OS == LF_OS_WINDOWS) || (LF_TARGET_OS == LF_OS_LINUX)
|
||||
#include <LFramework/Threading/CriticalSectionStd.h>
|
||||
|
||||
std::recursive_mutex LFramework::Threading::CriticalSection::_lock;
|
||||
#endif
|
||||
@@ -1,31 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
|
||||
namespace LFramework::Threading {
|
||||
|
||||
class CriticalSection {
|
||||
public:
|
||||
CriticalSection() {
|
||||
lock();
|
||||
}
|
||||
|
||||
~CriticalSection() {
|
||||
unlock(0);
|
||||
}
|
||||
|
||||
static uint32_t lock() {
|
||||
_lock.lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void unlock(int ) {
|
||||
_lock.unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
static std::recursive_mutex _lock;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <LFramework/Detect/DetectOS.h>
|
||||
|
||||
#if LF_TARGET_OS == LF_OS_FREERTOS
|
||||
#include "SemaphoreFreeRTOS.h"
|
||||
#elif (LF_TARGET_OS == LF_OS_WINDOWS) || (LF_TARGET_OS == LF_OS_LINUX)
|
||||
#include "SemaphoreStd.h"
|
||||
#endif
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "../MCU/Mcu.h"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "portable.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
|
||||
|
||||
namespace LFramework::Threading {
|
||||
|
||||
class Semaphore {
|
||||
public:
|
||||
~Semaphore(){
|
||||
vSemaphoreDelete(_handle);
|
||||
}
|
||||
|
||||
size_t messagesWaiting() const {
|
||||
return (size_t)uxQueueMessagesWaiting(_handle);
|
||||
}
|
||||
|
||||
bool take(TickType_t wait = portMAX_DELAY) {
|
||||
if (LFramework::Mcu::isHandlingInterrupt()) {
|
||||
portBASE_TYPE taskWoken = pdFALSE;
|
||||
if (xSemaphoreTakeFromISR(_handle, &taskWoken) != pdTRUE) {
|
||||
return false;
|
||||
}
|
||||
portEND_SWITCHING_ISR(taskWoken);
|
||||
return true;
|
||||
} else {
|
||||
return xSemaphoreTake(_handle, wait) == pdTRUE;
|
||||
}
|
||||
}
|
||||
|
||||
bool give() {
|
||||
if (LFramework::Mcu::isHandlingInterrupt()) {
|
||||
portBASE_TYPE taskWoken = pdFALSE;
|
||||
if (xSemaphoreGiveFromISR(_handle, &taskWoken) != pdTRUE) {
|
||||
return false;
|
||||
}
|
||||
portEND_SWITCHING_ISR(taskWoken);
|
||||
return true;
|
||||
} else {
|
||||
return xSemaphoreGive(_handle) == pdTRUE;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
SemaphoreHandle_t _handle;
|
||||
};
|
||||
|
||||
class BinarySemaphore : public Semaphore{
|
||||
public:
|
||||
BinarySemaphore(){
|
||||
_handle = xSemaphoreCreateBinary();
|
||||
assert(_handle != nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
class CountingSemaphore : public Semaphore{
|
||||
public:
|
||||
CountingSemaphore(UBaseType_t maxCount, UBaseType_t initialCount){
|
||||
_handle = xSemaphoreCreateCounting(maxCount, initialCount);
|
||||
assert(_handle != nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <atomic>
|
||||
|
||||
namespace LFramework::Threading {
|
||||
|
||||
class CountingSemaphore {
|
||||
public:
|
||||
static constexpr std::size_t InfiniteTimeout = -1;
|
||||
CountingSemaphore(std::size_t maxCount, std::size_t initialCount) :_maxCount(maxCount), _count(initialCount) {
|
||||
|
||||
}
|
||||
bool take() {
|
||||
std::unique_lock<std::mutex> lk(_mutex);
|
||||
_conditional.wait(lk, [this] { return _count > 0; });
|
||||
--_count;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool take(std::size_t milliseconds) {
|
||||
std::unique_lock<std::mutex> lk(_mutex);
|
||||
if (_conditional.wait_for(lk, ::std::chrono::milliseconds(milliseconds), [this] { return _count > 0; })) {
|
||||
--_count;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool tryTake() {
|
||||
std::lock_guard<::std::mutex> lk(_mutex);
|
||||
if (_count > 0) {
|
||||
--_count;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool give(std::size_t count) {
|
||||
if(count == 0){
|
||||
return true;
|
||||
}
|
||||
std::lock_guard<::std::mutex> lk(_mutex);
|
||||
if ((_count + count) <= _maxCount) {
|
||||
_count += count;
|
||||
if(count > 1){
|
||||
_conditional.notify_all();
|
||||
}else{
|
||||
_conditional.notify_one();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool give() {
|
||||
std::lock_guard<::std::mutex> lk(_mutex);
|
||||
if (_count < _maxCount) {
|
||||
++_count;
|
||||
_conditional.notify_one();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t messagesWaiting() const {
|
||||
return _count.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t _maxCount = -1;
|
||||
std::atomic<std::size_t> _count = 0;
|
||||
std::mutex _mutex;
|
||||
std::condition_variable _conditional;
|
||||
};
|
||||
|
||||
class BinarySemaphore : public CountingSemaphore {
|
||||
public:
|
||||
BinarySemaphore(bool startWithValue = false) : CountingSemaphore(1, startWithValue ? 1 : 0){ }
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
#include "../UnitTest/UnitTest.h"
|
||||
|
||||
#ifdef LF_THREADING
|
||||
|
||||
#include "SemaphoreStd.h"
|
||||
#include "Thread.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace LFramework;
|
||||
|
||||
|
||||
TEST(SemaphoreStd_SyncUsage) {
|
||||
Semaphore s0;
|
||||
|
||||
TEST_TRUE(s0.available() == 0);
|
||||
s0.give();
|
||||
TEST_TRUE(s0.available() == 1);
|
||||
s0.give(9);
|
||||
TEST_TRUE(s0.available() == 10);
|
||||
|
||||
s0.take(0);
|
||||
TEST_TRUE(s0.available() == 10);
|
||||
s0.take();
|
||||
TEST_TRUE(s0.available() == 9);
|
||||
s0.take(9);
|
||||
TEST_TRUE(s0.available() == 0);
|
||||
}
|
||||
|
||||
TEST(SemaphoreStd_AsyncUsage) {
|
||||
static constexpr size_t initialCount = 25;
|
||||
|
||||
Semaphore resources(initialCount);
|
||||
|
||||
Thread consumerThread0 = Thread("", 0, ThreadPriority::Normal, [&resources]() {
|
||||
for(size_t i = 0; i < 100; ++i) {
|
||||
resources.take();
|
||||
ThisThread::sleepForMs(1);
|
||||
}
|
||||
});
|
||||
|
||||
Thread consumerThread1 = Thread("", 0, ThreadPriority::Normal, [&resources]() {
|
||||
for (size_t i = 0; i < 10; ++i) {
|
||||
resources.take(10);
|
||||
ThisThread::sleepForMs(2);
|
||||
}
|
||||
});
|
||||
|
||||
for(size_t i = 0; i < (200 - initialCount); i += 5) {
|
||||
resources.give(5);
|
||||
}
|
||||
|
||||
consumerThread0.join();
|
||||
consumerThread1.join();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,77 +0,0 @@
|
||||
#include <LFramework/Threading/Thread.h>
|
||||
#include <LFramework/Threading/ThreadFreeRTOS.h>
|
||||
#include <LFramework/Threading/ThreadStd.h>
|
||||
|
||||
|
||||
namespace LFramework::Threading {
|
||||
|
||||
Thread::Thread(const char* name, size_t stackSize, ThreadPriority priority, std::function<void()>&& func) {
|
||||
_impl = new Thread::Impl(name, stackSize, priority, std::move(func));
|
||||
}
|
||||
|
||||
|
||||
Thread::Thread() noexcept = default;
|
||||
|
||||
Thread::Thread(Thread&& other) noexcept{
|
||||
moveTask(other);
|
||||
}
|
||||
|
||||
Thread::~Thread() {
|
||||
assert(!joinable());
|
||||
//_impl.reset();
|
||||
}
|
||||
bool Thread::joinable() const noexcept {
|
||||
return _impl != nullptr;
|
||||
}
|
||||
void Thread::join() {
|
||||
assert(joinable());
|
||||
assert(ThisThread::getId() != getId()); //Can't join self
|
||||
_impl->join();
|
||||
delete _impl;
|
||||
_impl = nullptr;
|
||||
}
|
||||
void Thread::swap(Thread& other) {
|
||||
std::swap(_impl, other._impl);
|
||||
}
|
||||
/*Thread::NativeHandleType Thread::nativeHandle() const {
|
||||
assert(joinable());
|
||||
return _impl->getNativeHandle();
|
||||
}*/
|
||||
Thread::ID Thread::getId() const noexcept {
|
||||
if (_impl != nullptr) {
|
||||
return _impl->getId();
|
||||
}
|
||||
return Thread::ID{};
|
||||
}
|
||||
ThreadPriority Thread::getPriority() const {
|
||||
assert(joinable());
|
||||
return _impl->getPriority();
|
||||
}
|
||||
void Thread::setPriority(ThreadPriority priority) const {
|
||||
assert(joinable());
|
||||
_impl->setPriority(priority);
|
||||
}
|
||||
void Thread::suspend() {
|
||||
assert(joinable());
|
||||
_impl->suspend();
|
||||
}
|
||||
void Thread::resume() {
|
||||
assert(joinable());
|
||||
_impl->resume();
|
||||
}
|
||||
Thread& Thread::operator = (Thread&& other) noexcept {
|
||||
return moveTask(other);
|
||||
}
|
||||
const char* Thread::getName() const {
|
||||
assert(joinable());
|
||||
return _impl->getName();
|
||||
}
|
||||
|
||||
Thread& Thread::moveTask(Thread& other) {
|
||||
assert(!joinable());
|
||||
_impl = std::move(other._impl);
|
||||
other._impl = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} //LFramework
|
||||
@@ -1,66 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <LFramework/Threading/ThreadPlatform.h>
|
||||
|
||||
namespace LFramework::Threading {
|
||||
|
||||
enum class ThreadPriority{
|
||||
Idle,
|
||||
Low,
|
||||
BelowNormal,
|
||||
Normal,
|
||||
AboveNormal,
|
||||
High,
|
||||
Realtime,
|
||||
Error
|
||||
};
|
||||
|
||||
class Thread {
|
||||
public:
|
||||
using ID = ThreadID;
|
||||
|
||||
explicit Thread(const char* name, size_t stackSize, ThreadPriority priority, std::function<void()>&& func);
|
||||
|
||||
~Thread();
|
||||
Thread() noexcept;
|
||||
Thread(const Thread&) = delete;
|
||||
Thread(Thread&& other) noexcept;
|
||||
|
||||
Thread& operator = (const Thread&) = delete;
|
||||
Thread& operator = (Thread&& other) noexcept;
|
||||
|
||||
void swap(Thread& other);
|
||||
|
||||
bool joinable() const noexcept;
|
||||
void join();
|
||||
//TODO: detach
|
||||
|
||||
ID getId() const noexcept;
|
||||
//NativeHandleType nativeHandle() const noexcept;
|
||||
|
||||
const char* getName() const;
|
||||
|
||||
ThreadPriority getPriority() const;
|
||||
void setPriority(ThreadPriority priority) const;
|
||||
|
||||
void suspend();
|
||||
void resume();
|
||||
private:
|
||||
class Impl;
|
||||
Thread& moveTask(Thread& other);
|
||||
Impl* _impl = nullptr;
|
||||
};
|
||||
|
||||
namespace ThisThread {
|
||||
Thread::ID getId();
|
||||
ThreadPriority getPriority();
|
||||
void setPriority(ThreadPriority priority);
|
||||
void sleepForMs(size_t milliseconds);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
#pragma once
|
||||
#include <LFramework/Threading/Thread.h>
|
||||
#include "../Detect/DetectOS.h"
|
||||
|
||||
|
||||
#if LF_TARGET_OS == LF_OS_FREERTOS
|
||||
#include <LFramework/Threading/SemaphoreFreeRTOS.h>
|
||||
#include "task.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace LFramework::Threading {
|
||||
|
||||
#if LF_TARGET_OS == LF_OS_FREERTOS
|
||||
static Thread::ID makeThreadId(TaskHandle_t handle) {
|
||||
return reinterpret_cast<Thread::ID>(handle);
|
||||
}
|
||||
|
||||
static ThreadPriority makeThreadPriority(portBASE_TYPE osPriority) {
|
||||
return static_cast<ThreadPriority>(osPriority);
|
||||
}
|
||||
|
||||
static portBASE_TYPE makeOsPriority(ThreadPriority priority) {
|
||||
return static_cast<portBASE_TYPE>(priority);
|
||||
}
|
||||
|
||||
|
||||
class Thread::Impl {
|
||||
public:
|
||||
explicit Impl(const char* name, size_t stackSize, ThreadPriority priority, std::function<void()>&& body) :_body(std::move(body)) {
|
||||
xTaskCreate(&Impl::staticTaskHandler, name, stackSize, this, (UBaseType_t)priority, &_rtosTaskHandle);
|
||||
}
|
||||
|
||||
void join(){
|
||||
_joinSemaphore.take();
|
||||
}
|
||||
|
||||
Thread::ID getId() const {
|
||||
return makeThreadId(_rtosTaskHandle);
|
||||
}
|
||||
|
||||
TaskHandle_t getNativeHandle() const {
|
||||
return _rtosTaskHandle;
|
||||
}
|
||||
|
||||
const char* getName() const {
|
||||
return pcTaskGetTaskName(_rtosTaskHandle);
|
||||
}
|
||||
void suspend() {
|
||||
vTaskSuspend(_rtosTaskHandle);
|
||||
}
|
||||
void resume() {
|
||||
vTaskResume(_rtosTaskHandle);
|
||||
}
|
||||
ThreadPriority getPriority() const {
|
||||
return makeThreadPriority(uxTaskPriorityGet(_rtosTaskHandle));
|
||||
}
|
||||
void setPriority(ThreadPriority priority) const {
|
||||
vTaskPrioritySet(_rtosTaskHandle, makeOsPriority(priority));
|
||||
}
|
||||
private:
|
||||
static void staticTaskHandler(void* param) {
|
||||
Impl* _this = (Impl*)param;
|
||||
_this->taskHandler();
|
||||
}
|
||||
void taskHandler() {
|
||||
_body();
|
||||
assert(_joinSemaphore.give());
|
||||
vTaskDelete(xTaskGetCurrentTaskHandle());
|
||||
}
|
||||
TaskHandle_t _rtosTaskHandle = nullptr;
|
||||
std::function<void()> _body;
|
||||
Threading::BinarySemaphore _joinSemaphore;
|
||||
};
|
||||
|
||||
|
||||
namespace ThisThread {
|
||||
Thread::ID getId() {
|
||||
return makeThreadId(xTaskGetCurrentTaskHandle());
|
||||
}
|
||||
ThreadPriority getPriority() {
|
||||
return makeThreadPriority(uxTaskPriorityGet(xTaskGetCurrentTaskHandle()));
|
||||
}
|
||||
void setPriority(ThreadPriority priority) {
|
||||
vTaskPrioritySet(xTaskGetCurrentTaskHandle(), makeOsPriority(priority));
|
||||
}
|
||||
void sleepForMs(size_t milliseconds){
|
||||
vTaskDelay(milliseconds);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Detect/DetectOS.h"
|
||||
|
||||
#if LF_TARGET_OS == LF_OS_FREERTOS
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
namespace LFramework::Threading {
|
||||
using ThreadID = TaskHandle_t;
|
||||
}
|
||||
#else
|
||||
#include <thread>
|
||||
namespace LFramework::Threading {
|
||||
using ThreadID = std::thread::id;
|
||||
}
|
||||
#endif
|
||||
@@ -1,60 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(LF_THREAD_STD)
|
||||
|
||||
#include <LFramework/Threading/Thread.h>
|
||||
#include <thread>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
|
||||
namespace LFramework::Threading {
|
||||
class Thread::Impl {
|
||||
public:
|
||||
explicit Impl(const char* name, size_t stackSize, ThreadPriority priority, std::function<void()>&& body):_name(name){
|
||||
_thread = std::thread(body);
|
||||
}
|
||||
void join() {
|
||||
_thread.join();
|
||||
}
|
||||
Thread::ID getId() const {
|
||||
return _thread.get_id();
|
||||
}
|
||||
const char* getName() const {
|
||||
return _name.c_str();
|
||||
}
|
||||
void suspend() {
|
||||
|
||||
}
|
||||
void resume() {
|
||||
|
||||
}
|
||||
ThreadPriority getPriority() const {
|
||||
return ThreadPriority::Normal;
|
||||
}
|
||||
void setPriority(ThreadPriority priority) const {
|
||||
|
||||
}
|
||||
private:
|
||||
std::string _name;
|
||||
std::thread _thread;
|
||||
};
|
||||
|
||||
namespace ThisThread {
|
||||
inline Thread::ID getId() {
|
||||
return std::this_thread::get_id();
|
||||
}
|
||||
void sleepForMs(size_t milliseconds) {
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
|
||||
}
|
||||
/*ThreadPriority getPriority() {
|
||||
return Private::makeThreadPriority(uxTaskPriorityGet(xTaskGetCurrentTaskHandle()));
|
||||
}
|
||||
void setPriority(ThreadPriority priority) {
|
||||
vTaskPrioritySet(xTaskGetCurrentTaskHandle(), Private::makeOsPriority(priority));
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#include <LFramework/Threading/Thread.h>
|
||||
#include "../UnitTest/UnitTest.h"
|
||||
|
||||
#ifdef LF_THREADING
|
||||
|
||||
using namespace LFramework::Threading;
|
||||
|
||||
void test(int& counter) {
|
||||
counter = 100500;
|
||||
}
|
||||
|
||||
TEST(Thread_Create) {
|
||||
int counter = 0;
|
||||
Thread t;
|
||||
TEST_TRUE(t.joinable() == false);
|
||||
|
||||
t = Thread("123", 123, ThreadPriority::Normal, [&](){
|
||||
test(counter);
|
||||
});
|
||||
t.join();
|
||||
|
||||
TEST_TRUE(counter == 100500);
|
||||
TEST_TRUE(!t.joinable());
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,6 +0,0 @@
|
||||
target_sources(${PROJECT_NAME}
|
||||
INTERFACE
|
||||
Stopwatch.h
|
||||
)
|
||||
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
#ifndef Stopwatch_h__
|
||||
#define Stopwatch_h__
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
|
||||
namespace LFramework {
|
||||
class Stopwatch {
|
||||
public:
|
||||
Stopwatch() {
|
||||
Reset();
|
||||
}
|
||||
typedef std::chrono::high_resolution_clock clock_t;
|
||||
|
||||
void Reset() {
|
||||
_startTime = clock_t::now();
|
||||
}
|
||||
clock_t::duration Check() {
|
||||
_lastDelta = clock_t::now() - _startTime;
|
||||
return _lastDelta;
|
||||
}
|
||||
std::chrono::milliseconds CheckMs() {
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(Check());
|
||||
}
|
||||
clock_t::duration GetLastDelta() {
|
||||
return _lastDelta;
|
||||
}
|
||||
private:
|
||||
clock_t::time_point _startTime;
|
||||
clock_t::duration _lastDelta;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // Stopwatch_h__
|
||||
-318
@@ -1,318 +0,0 @@
|
||||
#ifndef TUPLEUTILS_H
|
||||
#define TUPLEUTILS_H
|
||||
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
namespace LFramework {
|
||||
|
||||
|
||||
template <class... Ts>
|
||||
struct Tuple;
|
||||
|
||||
template <>
|
||||
struct Tuple<> {};
|
||||
|
||||
template <class T, class... Ts>
|
||||
struct Tuple<T, Ts...>{
|
||||
T first;
|
||||
Tuple<Ts...> rest;
|
||||
constexpr Tuple() = default;
|
||||
template <class U, class...Us, class = typename ::std::enable_if<!::std::is_base_of<Tuple,typename ::std::decay<U>::type>::value>::type>
|
||||
constexpr Tuple(U&& u, Us&&...tail) : first(::std::forward<U>(u)), rest(::std::forward<Us>(tail)...) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Tuple<T>{
|
||||
T first;
|
||||
constexpr Tuple() = default;
|
||||
template <class U, class = typename ::std::enable_if<!::std::is_base_of<Tuple, typename ::std::decay<U>::type>::value>::type>
|
||||
constexpr Tuple(U&& u) : first(::std::forward<U>(u)) {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct IsTuple : std::false_type {};
|
||||
|
||||
template<typename ...T>
|
||||
struct IsTuple<Tuple<T...>> : std::true_type {};
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
template <class... Ts>
|
||||
struct PackedTuple;
|
||||
|
||||
template <>
|
||||
struct PackedTuple<> {};
|
||||
|
||||
template <class T, class... Ts>
|
||||
struct PackedTuple<T, Ts...>{
|
||||
T first;
|
||||
Tuple<Ts...> rest;
|
||||
PackedTuple() = default;
|
||||
template <class U, class...Us, class = typename ::std::enable_if<!::std::is_base_of<PackedTuple,typename ::std::decay<U>::type>::value>::type>
|
||||
PackedTuple(U&& u, Us&&...tail) : first(::std::forward<U>(u)), rest(::std::forward<Us>(tail)...) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct PackedTuple<T>{
|
||||
T first;
|
||||
PackedTuple() = default;
|
||||
template <class U, class = typename ::std::enable_if<!::std::is_base_of<PackedTuple, typename ::std::decay<U>::type>::value>::type>
|
||||
PackedTuple(U&& u) : first(::std::forward<U>(u)) {}
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
template<typename T>
|
||||
struct IsPackedTuple : std::false_type {};
|
||||
|
||||
template<typename ...T>
|
||||
struct IsPackedTuple<PackedTuple<T...>> : std::true_type {};
|
||||
|
||||
|
||||
namespace details {
|
||||
template<size_t Index, size_t CurrentIndex, typename...Types>
|
||||
auto& Get(Tuple<Types...>& t) {
|
||||
if constexpr (Index == CurrentIndex) {
|
||||
return t.first;
|
||||
}
|
||||
else if constexpr (sizeof...(Types) > 1) {
|
||||
return details::Get<Index, CurrentIndex + 1>(t.rest);
|
||||
}
|
||||
else {
|
||||
static_assert(sizeof(t) == 0, "Invalid tuple index");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct tupleSizeHelper {
|
||||
static constexpr size_t size = 0;
|
||||
};
|
||||
|
||||
template<typename... T>
|
||||
struct tupleSizeHelper<Tuple<T...>> {
|
||||
static constexpr size_t size = sizeof...(T);
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
constexpr size_t tupleSize = tupleSizeHelper<T>::size;
|
||||
|
||||
|
||||
template<size_t Index, typename...Types>
|
||||
auto& Get(Tuple<Types...>& t) {
|
||||
return details::Get<Index, 0>(t);
|
||||
}
|
||||
|
||||
|
||||
namespace details {
|
||||
template<size_t Index, size_t CurrentIndex, typename...Types>
|
||||
auto& Get(PackedTuple<Types...>& t) {
|
||||
if constexpr (Index == CurrentIndex) {
|
||||
return t.first;
|
||||
}
|
||||
else if constexpr (sizeof...(Types) > 1) {
|
||||
return details::Get<Index, CurrentIndex + 1>(t.rest);
|
||||
}
|
||||
else {
|
||||
static_assert(sizeof(t) == 0, "Invalid tuple index");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<size_t Index, typename...Types>
|
||||
auto& Get(PackedTuple<Types...>& t) {
|
||||
return details::Get<Index, 0>(t);
|
||||
}
|
||||
|
||||
struct TupleSkipType {};
|
||||
|
||||
struct TupleStepInType {};
|
||||
|
||||
namespace details {
|
||||
template<typename...A, typename...B>
|
||||
auto tupleCatImpl(Tuple<A...> done, Tuple<B...> t) {
|
||||
return Tuple<A..., B...>{};
|
||||
};
|
||||
|
||||
|
||||
template<typename A, typename B>
|
||||
using tupleCat = decltype(tupleCatImpl(std::declval<A>(), std::declval<B>()));
|
||||
|
||||
template<typename F, typename...T, typename...U>
|
||||
auto tupleSelectImpl(F f, const Tuple<T...>& tuple, const Tuple<U...>& intermediate) {
|
||||
if constexpr(sizeof...(T) > 1) {
|
||||
using SelectedType = decltype(f(tuple.first));
|
||||
|
||||
if constexpr (std::is_same_v<SelectedType, TupleStepInType>) {
|
||||
return tupleCat<decltype(tupleSelectImpl(f, tuple.first, Tuple<>())), decltype(tupleSelectImpl(f, tuple.rest, Tuple<U...>()))>{};
|
||||
}else if constexpr (std::is_same_v<SelectedType, TupleSkipType>) {
|
||||
return tupleSelectImpl(f, tuple.rest, Tuple<U...>());
|
||||
}
|
||||
else {
|
||||
return tupleSelectImpl(f, tuple.rest, Tuple<U..., SelectedType>());
|
||||
}
|
||||
}
|
||||
else {
|
||||
using SelectedType = decltype(f(tuple.first));
|
||||
if constexpr (std::is_same_v<SelectedType, TupleStepInType>) {
|
||||
return tupleSelectImpl(f, tuple.first, Tuple<>());
|
||||
}
|
||||
else if constexpr (std::is_same_v<SelectedType, TupleSkipType>) {
|
||||
return Tuple<U...>();
|
||||
}
|
||||
else {
|
||||
return Tuple<U..., SelectedType>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F, typename...T>
|
||||
auto tupleSelectType_(F f, const Tuple<T...>& tuple) {
|
||||
return tupleSelectImpl(f, tuple, Tuple<>{});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename A, typename B>
|
||||
using tupleAppendFront = tupleCat<Tuple<A>, B>;
|
||||
|
||||
template<typename A, typename B>
|
||||
using tupleAppendBack = tupleCat<B, Tuple<A>>;
|
||||
|
||||
|
||||
template<typename ... T>
|
||||
struct tupleFlattenImpl {
|
||||
using type = Tuple<>;
|
||||
};
|
||||
|
||||
template<typename D, typename...T>
|
||||
struct tupleFlattenImpl<D, T...> {
|
||||
using type = tupleAppendFront<D, typename tupleFlattenImpl<T...>::type>;
|
||||
};
|
||||
|
||||
template<typename D>
|
||||
struct tupleFlattenImpl<D> {
|
||||
using type = Tuple<D>;
|
||||
};
|
||||
|
||||
template<typename...D, typename...T>
|
||||
struct tupleFlattenImpl<Tuple<D...>, T...> {
|
||||
using type = tupleCat<typename tupleFlattenImpl<D...>::type, typename tupleFlattenImpl<T...>::type>;
|
||||
};
|
||||
|
||||
template<typename...T>
|
||||
auto tupleFlatten_(const Tuple<T...>& tuple) {
|
||||
return typename tupleFlattenImpl<T...>::type{};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename F, typename T>
|
||||
struct tupleSelectTypeHelp {
|
||||
typedef decltype(details::tupleSelectType_(std::declval<F>(), std::declval<T>())) type;
|
||||
};
|
||||
|
||||
template<typename F, typename T>
|
||||
using tupleSelectType = typename tupleSelectTypeHelp<F, T>::type;
|
||||
|
||||
|
||||
template<typename T>
|
||||
using tupleFlatten = decltype(details::tupleFlatten_(std::declval<T>()));
|
||||
|
||||
template<typename Target, bool Recurse = false>
|
||||
struct TupleTypeSelector {
|
||||
template<typename T>
|
||||
auto operator () (const T& t) {
|
||||
if constexpr (IsTuple<T>::value) {
|
||||
if constexpr (Recurse) {
|
||||
return TupleStepInType{};
|
||||
}
|
||||
else {
|
||||
return TupleSkipType{};
|
||||
}
|
||||
}
|
||||
else {
|
||||
if constexpr (std::is_base_of_v<Target, T>) {
|
||||
return T{};
|
||||
}
|
||||
else {
|
||||
return TupleSkipType{};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
namespace details {
|
||||
template<typename F, typename...T, typename...U>
|
||||
auto tupleSelectImpl(F f, PackedTuple<T...> tuple, PackedTuple<U...> intermediate) {
|
||||
if constexpr(sizeof...(T) > 1) {
|
||||
return tupleSelectImpl(f, tuple.rest, PackedTuple<U..., decltype(f(tuple.first))>());
|
||||
}
|
||||
else {
|
||||
return PackedTuple<U..., decltype(f(tuple.first))>();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F, typename...T>
|
||||
auto tupleSelectType_(F f, PackedTuple<T...> tuple) {
|
||||
return tupleSelectImpl(f, tuple, PackedTuple<>{});
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F, typename T>
|
||||
using packedTupleSelectType = decltype(details::tupleSelectType_(std::declval<F>(), std::declval<T>()));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename T, typename F, int... Is>
|
||||
void forEach(T&& t, F f, std::index_sequence<Is...>) {
|
||||
auto l = { (f(std::get<Is>(t)), 0)... };
|
||||
}
|
||||
|
||||
template<typename T, typename F, int... Is>
|
||||
void forEachIndexed(T&& t, F f, std::index_sequence<Is...>) {
|
||||
auto l = { (f(std::get<Is>(t), Is), 0)... };
|
||||
}
|
||||
|
||||
template<typename... Ts, typename F>
|
||||
void forEachInTuple(std::tuple<Ts...> const& t, F f) {
|
||||
forEach(t, f, std::index_sequence_for<Ts...>());
|
||||
}
|
||||
|
||||
template<typename... Ts, typename F>
|
||||
void forEachInTupleIndexed(std::tuple<Ts...> const& t, F f) {
|
||||
forEachIndexed(t, f, std::index_sequence_for<Ts...>());
|
||||
}
|
||||
|
||||
template<typename Functor, int ID = 0, typename ... Types>
|
||||
bool executeOnIndex(std::tuple<Types...>& t, int id, Functor f) {
|
||||
if constexpr (ID < sizeof...(Types)) {
|
||||
if (id == ID) {
|
||||
f(std::get<ID>(t));
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return executeOnIndex<Functor, ID + 1, Types...>(t, id, f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // TUPLEUTILS_H
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <tuple>
|
||||
|
||||
namespace LFramework {
|
||||
|
||||
template<class F>
|
||||
struct FunctionTraits;
|
||||
|
||||
template<class R, class... Args>
|
||||
struct FunctionTraits<R(Args...)> {
|
||||
using ReturnType = R;
|
||||
|
||||
static constexpr std::size_t Arity = sizeof...(Args);
|
||||
|
||||
template <int N>
|
||||
struct ArgumentHelper {
|
||||
static_assert(N < Arity, "error: invalid parameter index.");
|
||||
using Type = typename std::tuple_element<N, std::tuple<Args...>>::type;
|
||||
};
|
||||
|
||||
template <int N>
|
||||
using Argument = typename ArgumentHelper<N>::Type;
|
||||
};
|
||||
|
||||
// function pointer
|
||||
template<class R, class... Args>
|
||||
struct FunctionTraits<R(*)(Args...)> : public FunctionTraits<R(Args...)> {
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
|
||||
namespace LFramework::TypeTraits::Integral {
|
||||
|
||||
template<typename T, typename = ::std::enable_if_t<::std::is_integral_v<T>>>
|
||||
static constexpr std::size_t digitsCount(T value) {
|
||||
return value == 0 ? 0 : 1 + digitsCount(value / 10);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static constexpr std::size_t digitsCountBase10(T value) {
|
||||
std::size_t result = 0;
|
||||
while (value != 0) {
|
||||
++result;
|
||||
value /= 10;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T, typename = ::std::enable_if_t<::std::is_integral_v<T>>>
|
||||
static constexpr std::size_t maxDigitsCount() {
|
||||
return (::std::max)(digitsCount((::std::numeric_limits<T>::min)()), digitsCount((::std::numeric_limits<T>::max)()));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
|
||||
add_library(LFrameworkUsb INTERFACE )
|
||||
add_library( LFramework::Usb ALIAS LFrameworkUsb )
|
||||
|
||||
target_sources(LFrameworkUsb
|
||||
INTERFACE
|
||||
USBDevice_Deprecated.h
|
||||
usbd_conf.h
|
||||
UsbEndpoint.h
|
||||
UsbException.h
|
||||
UsbInterface.h
|
||||
UsbMicrosoftTypes.h
|
||||
UsbPollingTransfer.h
|
||||
UsbTransfer.h
|
||||
USBTypes.h
|
||||
USBTypesTest.cpp
|
||||
)
|
||||
|
||||
add_subdirectory(Device)
|
||||
add_subdirectory(Host)
|
||||
|
||||
|
||||
target_include_directories(LFrameworkUsb
|
||||
INTERFACE
|
||||
.
|
||||
)
|
||||
@@ -1,27 +0,0 @@
|
||||
add_library(LFrameworkUsbDevice INTERFACE )
|
||||
add_library(LFramework::Usb::Device ALIAS LFrameworkUsbDevice )
|
||||
|
||||
target_sources(LFrameworkUsbDevice
|
||||
INTERFACE
|
||||
UsbDBulkInterface.h
|
||||
UsbDDeviceContext.h
|
||||
UsbDEndpoint.h
|
||||
UsbDDevice.h
|
||||
UsbDInterface.h
|
||||
|
||||
UsbDEndpoint.cpp
|
||||
USBDDevice.cpp
|
||||
UsbDLowLevel.cpp
|
||||
UsbDDeviceCallbacks.cpp
|
||||
)
|
||||
|
||||
|
||||
target_compile_definitions(LFrameworkUsbDevice
|
||||
INTERFACE
|
||||
USBD_SUPPORT_USER_STRING_DESC=1
|
||||
)
|
||||
|
||||
target_include_directories(LFrameworkUsbDevice
|
||||
INTERFACE
|
||||
.
|
||||
)
|
||||
@@ -1,344 +0,0 @@
|
||||
#include <UsbDDevice.h>
|
||||
#include <usbd_conf.h>
|
||||
#include <usbd_def.h>
|
||||
#include <usbd_ioreq.h>
|
||||
#include <usbd_ctlreq.h>
|
||||
|
||||
#include <usbd_core.h>
|
||||
#include <stm32f7xx_hal.h>
|
||||
#include <LFramework/USB/USBTypes.h>
|
||||
#include <LFramework/USB/UsbMicrosoftTypes.h>
|
||||
#include <type_traits>
|
||||
#include <new>
|
||||
|
||||
using namespace LFramework;
|
||||
|
||||
extern "C" {
|
||||
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
|
||||
}
|
||||
|
||||
namespace LFramework::USB {
|
||||
__attribute__((used)) USBD_HandleTypeDef UsbDevice::hUsbDevice{};
|
||||
__attribute__((used)) UsbDDeviceContext* _context = nullptr;
|
||||
|
||||
|
||||
|
||||
|
||||
//For other-speed description
|
||||
__ALIGN_BEGIN volatile USB::DeviceQualifierDescriptor USBD_NDC_DeviceQualifierDesc __ALIGN_END {
|
||||
USB::UsbVersion(2),
|
||||
USB::UsbClass::Device::UseInterfaceClass(),
|
||||
64,
|
||||
1,
|
||||
0
|
||||
};
|
||||
|
||||
#define USB_VENDOR_CODE_WINUSB 'P'
|
||||
|
||||
__ALIGN_BEGIN volatile USB::Microsoft::MicrosoftStringDescriptor NDC_StringDescriptor __ALIGN_END = {
|
||||
(uint8_t)USB_VENDOR_CODE_WINUSB
|
||||
};
|
||||
|
||||
|
||||
extern volatile USB::DeviceQualifierDescriptor USBD_NDC_DeviceQualifierDesc;
|
||||
extern volatile USB::Microsoft::MicrosoftStringDescriptor NDC_StringDescriptor;
|
||||
|
||||
__attribute__((used)) std::aligned_storage_t<USBD_MAX_STR_DESC_SIZ, 4> _descriptorsBuffer;
|
||||
|
||||
|
||||
UsbDDeviceContext* UsbDevice::getContext(){
|
||||
return _context;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void hang(){
|
||||
while(true){
|
||||
asm("nop");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
__attribute__((used)) const USBD_DescriptorsTypeDef UsbDevice::_descriptorsTable = {
|
||||
&UsbDevice::getDeviceDescriptor,
|
||||
&UsbDevice::getLangidStrDescriptor,
|
||||
&UsbDevice::getManufacturerStringDescriptor,
|
||||
&UsbDevice::getProductStringDescriptor,
|
||||
&UsbDevice::getSerialStringDescriptor,
|
||||
&UsbDevice::getConfigStringDescriptor,
|
||||
&UsbDevice::getInterfaceStringDescriptor
|
||||
};
|
||||
|
||||
__attribute__((used)) const USBD_ClassTypeDef UsbDevice::_usbClassBinding = {
|
||||
&UsbDevice::coreInit,
|
||||
&UsbDevice::coreDeinit,
|
||||
&UsbDevice::coreSetup,
|
||||
0, //USBD_NDC_EP0_TxReady,
|
||||
&UsbDevice::coreEp0RxReady,
|
||||
&UsbDevice::coreDataIn,
|
||||
&UsbDevice::coreDataOut,
|
||||
&UsbDevice::coreSof,
|
||||
&UsbDevice::coreIsoInIncomplete,
|
||||
&UsbDevice::coreIsoOutIncomplete,
|
||||
&UsbDevice::coreGetCfgDesc,
|
||||
&UsbDevice::coreGetCfgDesc,
|
||||
&UsbDevice::coreGetCfgDesc,
|
||||
&UsbDevice::coreGetDeviceQualifierDesc,
|
||||
&UsbDevice::coreGetUserStringDesc
|
||||
};
|
||||
|
||||
|
||||
uint8_t UsbDevice::coreInit(USBD_HandleTypeDef* pdev, uint8_t cfgidx){
|
||||
//TODO: use configuration id
|
||||
for(size_t i = 0; i < _context->getInterfaceCount(); ++i){
|
||||
auto interface = _context->getInterface(i);
|
||||
if(interface != nullptr){
|
||||
if(!interface->init(pdev)){
|
||||
return USBD_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
uint8_t UsbDevice::coreDeinit(USBD_HandleTypeDef* pdev, uint8_t cfgidx){
|
||||
//TODO: use configuration id
|
||||
|
||||
for(size_t i = 0; i < _context->getInterfaceCount(); ++i){
|
||||
auto interface = _context->getInterface(i);
|
||||
if(interface != nullptr){
|
||||
if(!interface->deinit(pdev)){
|
||||
//return USBD_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
uint8_t UsbDevice::coreImplSetup(USBD_SetupReqTypedef request, void* data){
|
||||
switch ( request.bmRequest & USB_REQ_RECIPIENT_MASK ){
|
||||
case USB_REQ_RECIPIENT_INTERFACE:{
|
||||
if(_context != nullptr){
|
||||
auto* interface = _context->getInterface(request.wValue);
|
||||
if(interface != nullptr){
|
||||
hang();
|
||||
/*if(interface->control(&hUsbDevice, request.bRequest, (uint8_t*)data, request.wLength)){
|
||||
return USBD_OK;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case USB_REQ_RECIPIENT_ENDPOINT:
|
||||
hang();
|
||||
/*if(_usb_device_context != nullptr){
|
||||
if(request.bRequest == USB_REQ_CLEAR_FEATURE){ //reset pipe is called at host side
|
||||
//do reset pipe
|
||||
if(_clearFeatureCallback != nullptr){
|
||||
_clearFeatureCallback(request.wIndex);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
break;
|
||||
case USB_REQ_RECIPIENT_DEVICE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
uint8_t UsbDevice::coreSetup(USBD_HandleTypeDef* pdev, USBD_SetupReqTypedef *req){
|
||||
hang();
|
||||
/*if (req->wLength){
|
||||
//Request with data stage{
|
||||
if((req->bmRequest & USB_REQ_DATA_PHASE_MASK) == USB_REQ_DATA_PHASE_DEVICE_TO_HOST){
|
||||
//device to host data stage => handler should send data
|
||||
return coreImplSetup(*req, 0);
|
||||
}else{ //host to device data stage! Can't execute now, read data first & execute later in Ep0Receive callback
|
||||
last_request = *req;
|
||||
USBD_CtlPrepareRx (pdev, (uint8_t*)&ep0Buffer[0], req->wLength);
|
||||
}
|
||||
} else {//No data stage => simple request => execute now
|
||||
return coreImplSetup(*req, 0);
|
||||
}*/
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t UsbDevice::coreEp0RxReady(USBD_HandleTypeDef* pdev){
|
||||
hang();
|
||||
//coreImplSetup(last_request, &ep0Buffer[0]); //data in stage complete => execute request
|
||||
//last_request.bRequest = 0xff;
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
UsbDInterface* UsbDevice::findInterfaceByEndpointAddress(uint8_t address){
|
||||
if(_context == nullptr){
|
||||
return nullptr;
|
||||
}
|
||||
auto if_cnt = _context->getInterfaceCount();
|
||||
for(uint32_t i = 0; i < if_cnt; ++i){
|
||||
auto interface = _context->getInterface(i);
|
||||
if(interface != nullptr){
|
||||
auto endpoint = interface->getEndpoint(address);
|
||||
if(endpoint != nullptr){
|
||||
return interface;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t UsbDevice::coreDataIn(USBD_HandleTypeDef* pdev, uint8_t epnum){
|
||||
auto interface = findInterfaceByEndpointAddress(USB::EndpointAddress::makeIn(epnum));//TODO: cleanup
|
||||
if(interface != nullptr){
|
||||
interface->txComplete(epnum | 0x80);
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
uint8_t UsbDevice::coreDataOut(USBD_HandleTypeDef* pdev, uint8_t epnum){
|
||||
|
||||
uint32_t rxLen = USBD_LL_GetRxDataSize (pdev, epnum);
|
||||
auto interface = findInterfaceByEndpointAddress(USB::EndpointAddress::makeOut(epnum));
|
||||
if(interface != nullptr){
|
||||
interface->rxComplete(rxLen, epnum);
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
uint8_t UsbDevice::coreSof(USBD_HandleTypeDef* pdev){
|
||||
hang();
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
uint8_t UsbDevice::coreIsoInIncomplete(USBD_HandleTypeDef* pdev, uint8_t epnum){
|
||||
hang();
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
uint8_t UsbDevice::coreIsoOutIncomplete(USBD_HandleTypeDef* pdev, uint8_t epnum){
|
||||
hang();
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
uint8_t* UsbDevice::coreGetCfgDesc(uint16_t* length){
|
||||
auto* mem = reinterpret_cast<uint8_t*>(&_descriptorsBuffer);
|
||||
auto* buffer = mem;
|
||||
USB::ConfigurationDescriptor* cd = new(buffer) USB::ConfigurationDescriptor();
|
||||
cd->wTotalLength = 0;
|
||||
cd->bNumInterfaces = (uint8_t)_context->getInterfaceCount();
|
||||
cd->bConfigurationValue = 0x01;
|
||||
cd->iConfiguration = USBD_IDX_CONFIG_STR;
|
||||
cd->bmAttributes = USB::UsbAttributes().value;
|
||||
cd->bMaxPower = 500;
|
||||
buffer += sizeof(USB::ConfigurationDescriptor);
|
||||
|
||||
for(uint32_t i = 0; i < _context->getInterfaceCount(); ++i){
|
||||
auto emptySize = (mem + sizeof(_descriptorsBuffer)) - buffer;
|
||||
auto size = _context->getInterface(i)->getDescriptor(buffer, emptySize, i);
|
||||
buffer += size;
|
||||
cd->wTotalLength += size;
|
||||
}
|
||||
cd->wTotalLength += sizeof(USB::ConfigurationDescriptor);
|
||||
|
||||
*length = cd->wTotalLength;
|
||||
return reinterpret_cast<uint8_t*>(&_descriptorsBuffer);
|
||||
}
|
||||
|
||||
|
||||
uint8_t* UsbDevice::getDeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t* length){
|
||||
auto mem = reinterpret_cast<uint8_t*>(&_descriptorsBuffer);
|
||||
auto& desc = *new(mem) USB::DeviceDescriptor();
|
||||
*length = sizeof(USB::DeviceDescriptor);
|
||||
|
||||
desc.bcdUSB = 0x0200;
|
||||
desc.classDescription = USB::UsbClassDescriptor(0,0,0);
|
||||
desc.bMaxPacketSize0 = 64;
|
||||
desc.idVendor = 0x0301;
|
||||
desc.idProduct = 0x1111;
|
||||
desc.bcdDevice = USB::UsbVersion(2);
|
||||
desc.iManufacturer = USBD_IDX_MFC_STR;
|
||||
desc.iProduct = USBD_IDX_PRODUCT_STR;
|
||||
desc.iSerialNumber = USBD_IDX_SERIAL_STR;
|
||||
desc.bNumConfigurations = 1;
|
||||
return reinterpret_cast<uint8_t*>(&desc);
|
||||
}
|
||||
|
||||
struct USBDDummyClassData{
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
|
||||
|
||||
__attribute__((used)) static USBDDummyClassData _classData = {};
|
||||
|
||||
void UsbDevice::start(UsbDDeviceContext* context){
|
||||
_context = context;
|
||||
|
||||
hUsbDevice.pClassData = &_classData; //Otherwise USBD_Reset handler would not disable interfaces ((
|
||||
//hUsbDevice.pClassData = nullptr; //Init?
|
||||
hUsbDevice.dev_speed = USBD_SPEED_FULL;
|
||||
|
||||
USBD_Init(&hUsbDevice, const_cast<USBD_DescriptorsTypeDef*>(&_descriptorsTable), 0);
|
||||
|
||||
USBD_RegisterClass(&hUsbDevice, const_cast<USBD_ClassTypeDef*>(&_usbClassBinding));
|
||||
USBD_Start(&hUsbDevice);
|
||||
|
||||
}
|
||||
uint8_t* UsbDevice::coreGetDeviceQualifierDesc (uint16_t *length){
|
||||
*length = sizeof (USBD_NDC_DeviceQualifierDesc);
|
||||
return (uint8_t*)&USBD_NDC_DeviceQualifierDesc;
|
||||
}
|
||||
|
||||
uint8_t* UsbDevice::coreGetUserStringDesc(USBD_HandleTypeDef* pdev, uint8_t index, uint16_t* length){
|
||||
*length = 0;
|
||||
if ( 0xEE == index ){
|
||||
*length = sizeof (NDC_StringDescriptor);
|
||||
return (uint8_t*)&NDC_StringDescriptor;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t* UsbDevice::getLangidStrDescriptor(USBD_SpeedTypeDef speed, uint16_t* length){
|
||||
auto mem = static_cast<void*>(&_descriptorsBuffer);
|
||||
auto& desc = *new(mem) USB::LanguageIDStringDescriptor<1>();
|
||||
*length = sizeof(USB::LanguageIDStringDescriptor<1>);
|
||||
desc.languages[0] = USB::LanguageID::EnglishUnitedStates;
|
||||
return reinterpret_cast<uint8_t*>(&desc);
|
||||
}
|
||||
uint8_t* UsbDevice::getManufacturerStringDescriptor(USBD_SpeedTypeDef speed, uint16_t* length){
|
||||
return USB::MakeStringDescriptor(_context->manufacturerStringDescriptor, &_descriptorsBuffer, sizeof(_descriptorsBuffer), length);
|
||||
}
|
||||
uint8_t* UsbDevice::getProductStringDescriptor(USBD_SpeedTypeDef speed, uint16_t* length){
|
||||
return USB::MakeStringDescriptor(_context->productStringDescriptor, &_descriptorsBuffer, sizeof(_descriptorsBuffer), length);
|
||||
}
|
||||
|
||||
|
||||
uint8_t* UsbDevice::getSerialStringDescriptor(USBD_SpeedTypeDef speed, uint16_t* length){
|
||||
return USB::MakeStringDescriptor(_context->serialStringDescriptor, &_descriptorsBuffer, sizeof(_descriptorsBuffer), length);
|
||||
}
|
||||
uint8_t* UsbDevice::getConfigStringDescriptor(USBD_SpeedTypeDef speed, uint16_t* length){
|
||||
return USB::MakeStringDescriptor(_context->configurationStringDescriptor, &_descriptorsBuffer, sizeof(_descriptorsBuffer), length);
|
||||
}
|
||||
uint8_t* UsbDevice::getInterfaceStringDescriptor(USBD_SpeedTypeDef speed, uint16_t* length){
|
||||
return USB::MakeStringDescriptor(_context->interfaceStringDescriptor, &_descriptorsBuffer, sizeof(_descriptorsBuffer), length);
|
||||
}
|
||||
|
||||
|
||||
USBD_StatusTypeDef UsbDevice::interfaceRequest(USBD_HandleTypeDef* pdev, USBD_SetupReqTypedef* req){
|
||||
uint8_t interface_id = (uint8_t)req->wValue; //TODO: bug! wIndex == interface id
|
||||
auto interface = _context->getInterface(interface_id);
|
||||
if(interface == nullptr){
|
||||
return USBD_FAIL;
|
||||
}
|
||||
return interface->interfaceRequest(pdev, req);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "UsbDInterface.h"
|
||||
#include <optional>
|
||||
|
||||
namespace LFramework::USB {
|
||||
|
||||
class UsbDBulkInterface : public UsbDInterface {
|
||||
public:
|
||||
UsbDBulkInterface(){
|
||||
_descriptor.bNumEndpoints = 2;
|
||||
_descriptor.classDescription = USB::UsbClass::Interface::VendorSpecific<0,0>();
|
||||
_descriptor.iInterface = USBD_IDX_INTERFACE_STR;
|
||||
|
||||
USB::EndpointDescriptor desc;
|
||||
desc.bEndpointAddress = USB::EndpointAddress::makeIn(1);
|
||||
desc.bmAttributes.setType(EndpointType::Bulk);
|
||||
desc.wMaxPacketSize = 64;
|
||||
_inEp.emplace(desc);
|
||||
|
||||
desc.bEndpointAddress = USB::EndpointAddress::makeOut(1);
|
||||
_outEp.emplace(desc);
|
||||
}
|
||||
bool init(USBD_HandleTypeDef* pdev) override final {
|
||||
auto status = UsbDInterface::init(pdev);
|
||||
|
||||
/*if(status &) {
|
||||
_initListener->onBulkInterfaceInitComplete();
|
||||
}*/
|
||||
|
||||
return status;
|
||||
}
|
||||
bool deinit(USBD_HandleTypeDef* pdev) override final {
|
||||
return UsbDInterface::deinit(pdev);
|
||||
}
|
||||
UsbEndpoint* getEndpoint(bool isInEndpoint, uint8_t id)override final {
|
||||
if(id != 0){
|
||||
return nullptr;
|
||||
}
|
||||
return isInEndpoint ? &_inEp.value() : &_outEp.value();
|
||||
}
|
||||
const UsbEndpoint* getEndpoint(bool isInEndpoint, uint8_t id) const override final {
|
||||
if(id != 0){
|
||||
return nullptr;
|
||||
}
|
||||
return isInEndpoint ? &_inEp.value() : &_outEp.value();
|
||||
}
|
||||
|
||||
const USB::InterfaceDescriptor& getInterfaceDescriptor() const override final {
|
||||
return _descriptor;
|
||||
}
|
||||
|
||||
private:
|
||||
USB::InterfaceDescriptor _descriptor;
|
||||
std::optional<UsbDEndpoint> _inEp;
|
||||
std::optional<UsbDEndpoint> _outEp;
|
||||
};
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user