Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9038483ce | ||
|
|
e57de52cc4 | ||
|
|
ee05f9516a |
212
.clang-format
Normal file
212
.clang-format
Normal file
@@ -0,0 +1,212 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: Google
|
||||
AccessModifierOffset: -1
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveMacros: true
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveBitFields: true
|
||||
AlignConsecutiveDeclarations: true
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: true
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 160
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: true
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^<ext/.*\.h>'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^<.*'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseLabels: true
|
||||
IndentCaseBlocks: true
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentRequires: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertTrailingCommas: None
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
LambdaBodyIndentation: Signature
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Never
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PointerAlignment: Left
|
||||
PPIndentWidth: -1
|
||||
RawStringFormats:
|
||||
- Language: Cpp
|
||||
Delimiters:
|
||||
- cc
|
||||
- CC
|
||||
- cpp
|
||||
- Cpp
|
||||
- CPP
|
||||
- 'c++'
|
||||
- 'C++'
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
- Language: TextProto
|
||||
Delimiters:
|
||||
- pb
|
||||
- PB
|
||||
- proto
|
||||
- PROTO
|
||||
EnclosingFunctions:
|
||||
- EqualsProto
|
||||
- EquivToProto
|
||||
- PARSE_PARTIAL_TEXT_PROTO
|
||||
- PARSE_TEST_PROTO
|
||||
- PARSE_TEXT_PROTO
|
||||
- ParseTextOrDie
|
||||
- ParseTextProtoOrDie
|
||||
- ParseTestProto
|
||||
- ParsePartialTestProto
|
||||
CanonicalDelimiter: pb
|
||||
BasedOnStyle: google
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: true
|
||||
ShortNamespaceLines: 1
|
||||
SortIncludes: CaseSensitive
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: Never
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
BitFieldColonSpacing: Both
|
||||
Standard: Auto
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
WhitespaceSensitiveMacros:
|
||||
- STRINGIZE
|
||||
- PP_STRINGIZE
|
||||
- BOOST_PP_STRINGIZE
|
||||
- NS_SWIFT_NAME
|
||||
- CF_SWIFT_NAME
|
||||
...
|
||||
|
||||
15
.github/FUNDING.yml
vendored
15
.github/FUNDING.yml
vendored
@@ -1,15 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: wiredopposite
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
polar: # Replace with a single Polar username
|
||||
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
|
||||
thanks_dev: # Replace with a single thanks.dev username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
17
.gitignore
vendored
17
.gitignore
vendored
@@ -1,11 +1,6 @@
|
||||
/Firmware/pico/build/
|
||||
/Firmware/pico/debug/
|
||||
/Firmware/pico/.ignore/
|
||||
/Firmware/pico/src/USBDevice/DeviceDriver/XboxOG/tud_xid/tud_xid_xremote_rom.h
|
||||
/Firmware/pico/src/BLEServer/att_delayed_response.h
|
||||
/Firmware/ESP32/main/BLEServer/att_delayed_response.h
|
||||
/Firmware/ESP32/.ignore/
|
||||
/Firmware/ESP32/build/
|
||||
/Firmware/ESP32/components/btstack/
|
||||
/Firmware/ESP32/sdkconfig.old
|
||||
/scripts/xremote/dvd-dongle-rom.bin
|
||||
build
|
||||
.vscode
|
||||
release
|
||||
generated
|
||||
tools
|
||||
.ignore
|
||||
52
.gitmodules
vendored
52
.gitmodules
vendored
@@ -1,42 +1,12 @@
|
||||
[submodule "WebApp"]
|
||||
path = WebApp
|
||||
url = https://github.com/wiredopposite/OGX-Mini-WebApp.git
|
||||
[submodule "Firmware/BlueRetro"]
|
||||
path = Firmware/BlueRetro
|
||||
url = https://github.com/wiredopposite/BlueRetro.git
|
||||
[submodule "scripts/xremote/dump-dvd-kit"]
|
||||
path = scripts/xremote/dump-dvd-kit
|
||||
url = https://github.com/XboxDev/dump-dvd-kit.git
|
||||
[submodule "Firmware/pico/external/pico_usb"]
|
||||
path = Firmware/pico/external/pico_usb
|
||||
url = https://github.com/wiredopposite/pico_usb.git
|
||||
[submodule "Firmware/pico/external/g726/g726"]
|
||||
path = Firmware/pico/external/g726/g726
|
||||
url = https://github.com/fredrikhederstierna/g726.git
|
||||
[submodule "Firmware/pico/external/libxsm3/libxsm3"]
|
||||
path = Firmware/pico/external/libxsm3/libxsm3
|
||||
url = https://github.com/InvoxiPlayGames/libxsm3.git
|
||||
[submodule "Firmware/pico/external/libfixmath"]
|
||||
path = Firmware/pico/external/libfixmath
|
||||
url = https://github.com/PetteriAimonen/libfixmath.git
|
||||
[submodule "Firmware/pico/external/tinyusb"]
|
||||
path = Firmware/pico/external/tinyusb
|
||||
url = https://github.com/hathach/tinyusb.git
|
||||
[submodule "Firmware/pico/external/Pico-PIO-USB"]
|
||||
path = Firmware/pico/external/Pico-PIO-USB
|
||||
[submodule "lib/Pico-PIO-USB"]
|
||||
path = lib/Pico-PIO-USB
|
||||
url = https://github.com/sekigon-gonnoc/Pico-PIO-USB.git
|
||||
[submodule "Firmware/pico/external/bluepad32/bluepad32"]
|
||||
path = Firmware/pico/external/bluepad32/bluepad32
|
||||
url = https://github.com/ricardoquesada/bluepad32.git
|
||||
[submodule "Firmware/pico/external/bluepad32"]
|
||||
path = Firmware/pico/external/bluepad32
|
||||
url = https://github.com/ricardoquesada/bluepad32.git
|
||||
[submodule "Firmware/ESP32/components/bluepad32"]
|
||||
path = Firmware/ESP32/components/bluepad32
|
||||
url = https://github.com/ricardoquesada/bluepad32.git
|
||||
[submodule "Firmware/ESP32/components/libfixmath/libfixmath"]
|
||||
path = Firmware/ESP32/components/libfixmath/libfixmath
|
||||
url = https://github.com/PetteriAimonen/libfixmath.git
|
||||
[submodule "Firmware/pico/external/lwip"]
|
||||
path = Firmware/pico/external/lwip
|
||||
url = https://github.com/lwip-tcpip/lwip.git
|
||||
[submodule "lib/tinyusb"]
|
||||
path = lib/tinyusb
|
||||
url = https://github.com/hathach/tinyusb.git
|
||||
[submodule "lib/tusb_gamepad"]
|
||||
path = lib/tusb_gamepad
|
||||
url = https://github.com/wiredopposite/tusb_gamepad.git
|
||||
[submodule "lib/tusb_xinput"]
|
||||
path = lib/tusb_xinput
|
||||
url = https://github.com/wiredopposite/tusb_xinput.git
|
||||
|
||||
91
CMakeLists.txt
Normal file
91
CMakeLists.txt
Normal file
@@ -0,0 +1,91 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
message("Build type: \"${CMAKE_BUILD_TYPE}\"")
|
||||
|
||||
set(NAME OGX-Mini)
|
||||
|
||||
set(PICO_BOARD none)
|
||||
|
||||
# Fixes that allow some MCH2022 badges with a slowly starting oscillator to boot properly
|
||||
# add_compile_definitions(PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H=1 PICO_XOSC_STARTUP_DELAY_MULTIPLIER=64)
|
||||
|
||||
# add_compile_options(-Wno-unused-parameter -Wno-unused-variable -Wno-missing-field-initializers -Wno-unused-function)
|
||||
add_compile_options(-Wno-missing-field-initializers)
|
||||
|
||||
include($ENV{PICO_SDK_PATH}/pico_sdk_init.cmake)
|
||||
|
||||
project(${NAME} C CXX ASM)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
if (PICO_SDK_VERSION_STRING VERSION_LESS "1.3.0")
|
||||
message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.3.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
|
||||
endif()
|
||||
|
||||
set(ROOT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
set(PICO_PIO_USB_PATH ${ROOT}/lib/Pico-PIO-USB)
|
||||
set(PICO_TINYUSB_PATH ${ROOT}/lib/tinyusb)
|
||||
set(TUSB_GAMEPAD_PATH ${ROOT}/lib/tusb_gamepad)
|
||||
set(XINPUT_HOST_PATH ${ROOT}/lib/tusb_xinput)
|
||||
|
||||
pico_sdk_init()
|
||||
|
||||
# add_subdirectory(${ROOT}/lib)
|
||||
add_subdirectory(${ROOT}/lib/CRC32 CRC32)
|
||||
add_subdirectory(${XINPUT_HOST_PATH} xinput_host)
|
||||
add_subdirectory(${PICO_PIO_USB_PATH})
|
||||
add_subdirectory(${TUSB_GAMEPAD_PATH})
|
||||
target_include_directories(tusb_gamepad PRIVATE ${ROOT}/src) # so tusb_gamepad can see tusb_config.h
|
||||
|
||||
set(SRC_DIR ${ROOT}/src)
|
||||
file(GLOB_RECURSE SOURCES
|
||||
${SRC_DIR}/main.cpp
|
||||
${SRC_DIR}/input_mode.cpp
|
||||
|
||||
${SRC_DIR}/usbh/tusb_host_manager.cpp
|
||||
${SRC_DIR}/usbh/tusb_host.cpp
|
||||
${SRC_DIR}/usbh/n64usb/N64USB.cpp
|
||||
${SRC_DIR}/usbh/ps3/Dualshock3.cpp
|
||||
${SRC_DIR}/usbh/ps3/DInput.cpp
|
||||
${SRC_DIR}/usbh/ps4/Dualshock4.cpp
|
||||
${SRC_DIR}/usbh/ps5/Dualsense.cpp
|
||||
${SRC_DIR}/usbh/psclassic/PSClassic.cpp
|
||||
${SRC_DIR}/usbh/switch/SwitchPro.cpp
|
||||
${SRC_DIR}/usbh/switch/SwitchWired.cpp
|
||||
${SRC_DIR}/usbh/xinput/XInput.cpp
|
||||
${SRC_DIR}/usbh/shared/hid_class_driver.c
|
||||
${SRC_DIR}/usbh/shared/scaling.cpp
|
||||
)
|
||||
|
||||
# Firmware
|
||||
add_executable(${NAME} ${SOURCES})
|
||||
|
||||
target_include_directories(${NAME} PUBLIC
|
||||
${ROOT}/src
|
||||
${ROOT}/lib)
|
||||
|
||||
target_link_libraries(${NAME}
|
||||
pico_stdlib
|
||||
pico_unique_id
|
||||
pico_multicore
|
||||
hardware_watchdog
|
||||
hardware_flash
|
||||
hardware_sync
|
||||
hardware_uart
|
||||
hardware_pio
|
||||
hardware_pwm
|
||||
hardware_adc
|
||||
hardware_i2c
|
||||
tinyusb_device
|
||||
tinyusb_board
|
||||
tinyusb_host
|
||||
tinyusb_pico_pio_usb
|
||||
CRC32
|
||||
cmsis_core
|
||||
xinput_host
|
||||
tusb_gamepad
|
||||
)
|
||||
|
||||
pico_add_extra_outputs(${NAME})
|
||||
Submodule Firmware/BlueRetro deleted from bb98a87da7
25
Firmware/ESP32/.vscode/c_cpp_properties.json
vendored
25
Firmware/ESP32/.vscode/c_cpp_properties.json
vendored
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "ESP-IDF",
|
||||
"compilerPath": "${default}",
|
||||
"compileCommands": "${config:idf.buildPath}/compile_commands.json",
|
||||
"includePath": [
|
||||
"${config:idf.espIdfPath}/components/**",
|
||||
"${config:idf.espIdfPathWin}/components/**",
|
||||
"${workspaceFolder}/main/**",
|
||||
"${workspaceFolder}/components/**"
|
||||
],
|
||||
"browse": {
|
||||
"path": [
|
||||
"${config:idf.espIdfPath}/components",
|
||||
"${config:idf.espIdfPathWin}/components",
|
||||
"${workspaceFolder}/main",
|
||||
"${workspaceFolder}/components"
|
||||
],
|
||||
"limitSymbolsToIncludedHeaders": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
44
Firmware/ESP32/.vscode/settings.json
vendored
44
Firmware/ESP32/.vscode/settings.json
vendored
@@ -1,44 +0,0 @@
|
||||
{
|
||||
"idf.adapterTargetName": "esp32",
|
||||
"cmake.configureOnOpen": false,
|
||||
"idf.portWin": "COM26",
|
||||
"idf.flashType": "UART",
|
||||
"C_Cpp.intelliSenseEngine": "default",
|
||||
"idf.pythonInstallPath": "/usr/bin/python3",
|
||||
"files.associations": {
|
||||
"wired.h": "c",
|
||||
"stdarg.h": "c",
|
||||
"semphr.h": "c",
|
||||
"spi_slave.h": "c",
|
||||
"regex": "c",
|
||||
"chrono": "c",
|
||||
"variant": "c",
|
||||
"atomic": "cpp",
|
||||
"spi_hal.h": "c",
|
||||
"spi_ll.h": "c",
|
||||
"spi_struct.h": "c",
|
||||
"wired_private.h": "c",
|
||||
"gpio_ll.h": "c",
|
||||
"gpio_sig_map.h": "c",
|
||||
"gpio_hal.h": "c",
|
||||
"spi_master.h": "c",
|
||||
"spi_common.h": "c",
|
||||
"clk_tree_defs.h": "c",
|
||||
"io_mux_reg.h": "c",
|
||||
"pcnt_ll.h": "c",
|
||||
"gpio.h": "c",
|
||||
"freertos.h": "c",
|
||||
"bitset": "c",
|
||||
"string_view": "c",
|
||||
"i2c_ll.h": "c",
|
||||
"i2c_hal.h": "c",
|
||||
"stdbool.h": "c",
|
||||
"i2c_master.h": "c",
|
||||
"cstdint": "cpp",
|
||||
"array": "cpp",
|
||||
"string": "cpp",
|
||||
"span": "cpp"
|
||||
},
|
||||
"idf.port": "/dev/ttyUSB0",
|
||||
"idf.flashBaudRate": "57600"
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/FWDefines.cmake)
|
||||
set(COMPONENTS_PATH ${CMAKE_CURRENT_SOURCE_DIR}/components)
|
||||
set(BLUEPAD32_ROOT ${COMPONENTS_PATH}/bluepad32/src/components/bluepad32)
|
||||
set(BTSTACK_REPO_PATH ${COMPONENTS_PATH}/bluepad32/external/btstack)
|
||||
set(BTSTACK_SCRIPT_PATH ${COMPONENTS_PATH}/integrate_btstack.py)
|
||||
|
||||
execute_process(
|
||||
COMMAND git apply --ignore-whitespace ${COMPONENTS_PATH}/btstack_l2cap.diff
|
||||
WORKING_DIRECTORY ${BTSTACK_REPO_PATH}
|
||||
# RESULT_VARIABLE result
|
||||
# ERROR_VARIABLE error
|
||||
)
|
||||
|
||||
if(NOT EXISTS ${COMPONENTS_PATH}/btstack)
|
||||
find_package(Python3 COMPONENTS Interpreter REQUIRED)
|
||||
|
||||
if(Python3_Interpreter_FOUND)
|
||||
message(STATUS "Python3 found: ${Python3_EXECUTABLE}")
|
||||
message(STATUS "Python3 version: ${Python3_VERSION}")
|
||||
else()
|
||||
message(FATAL_ERROR "Python3 not found! Python is required to integrate BTStack with ESP-IDF")
|
||||
endif()
|
||||
|
||||
message(STATUS "Integrating BTStack with project")
|
||||
execute_process(
|
||||
COMMAND ${Python3_EXECUTABLE} ${BTSTACK_SCRIPT_PATH} ${BTSTACK_REPO_PATH} ${COMPONENTS_PATH}
|
||||
WORKING_DIRECTORY ${COMPONENTS_PATH}
|
||||
RESULT_VARIABLE PYTHON_RESULT
|
||||
OUTPUT_VARIABLE PYTHON_OUTPUT
|
||||
ERROR_VARIABLE PYTHON_ERROR
|
||||
)
|
||||
|
||||
if(PYTHON_RESULT EQUAL 0)
|
||||
message(STATUS "BTStack integration successful:\n${PYTHON_OUTPUT}")
|
||||
else()
|
||||
message(FATAL_ERROR "BTStack integration failed:\n${PYTHON_ERROR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS
|
||||
${BLUEPAD32_ROOT}/..
|
||||
${COMPONENTS_PATH}
|
||||
)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project("${FW_NAME}-${FW_VERSION}-ESP32")
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
set(FW_NAME "OGX-Mini")
|
||||
set(FW_VERSION "1.0.0a4")
|
||||
Submodule Firmware/ESP32/components/bluepad32 deleted from 6efa7123fe
@@ -1,16 +0,0 @@
|
||||
diff --git a/src/l2cap.c b/src/l2cap.c
|
||||
index 9ffa9c102..d78b59a39 100644
|
||||
--- a/src/l2cap.c
|
||||
+++ b/src/l2cap.c
|
||||
@@ -2455,7 +2455,11 @@ static void l2cap_handle_remote_supported_features_received(l2cap_channel_t * ch
|
||||
|
||||
// incoming: assert security requirements
|
||||
channel->state = L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE;
|
||||
+#if 0
|
||||
if (channel->required_security_level <= gap_security_level(channel->con_handle)){
|
||||
+#else
|
||||
+ if (1) {
|
||||
+#endif
|
||||
l2cap_handle_security_level_incoming_sufficient(channel);
|
||||
} else {
|
||||
// send connection pending if not already done
|
||||
@@ -1,77 +0,0 @@
|
||||
# This script copies BTstack ESP32 port files to this project's components folder
|
||||
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
def main(btstack_root, components_dir):
|
||||
PROJECT_COMPONENTS = os.path.abspath(components_dir)
|
||||
BTSTACK_DIR = os.path.abspath(btstack_root)
|
||||
BTSTACK_PORT_DIR = os.path.abspath(os.path.join(BTSTACK_DIR, 'port', 'esp32'))
|
||||
|
||||
if not os.path.exists(PROJECT_COMPONENTS):
|
||||
print(f"Error: No components folder at {PROJECT_COMPONENTS}")
|
||||
sys.exit(10)
|
||||
|
||||
if not os.path.exists(BTSTACK_DIR):
|
||||
print(f"Error: No BTstack folder at {BTSTACK_DIR}")
|
||||
sys.exit(10)
|
||||
|
||||
PROJECT_BTSTACK = os.path.join(PROJECT_COMPONENTS, "btstack")
|
||||
|
||||
if os.path.exists(PROJECT_BTSTACK):
|
||||
print("Deleting old BTstack component %s" % PROJECT_BTSTACK)
|
||||
shutil.rmtree(PROJECT_BTSTACK)
|
||||
|
||||
# create components/btstack
|
||||
print("Creating BTstack component at %s" % PROJECT_COMPONENTS)
|
||||
shutil.copytree(os.path.join(BTSTACK_PORT_DIR, 'components', 'btstack'), PROJECT_BTSTACK)
|
||||
|
||||
dirs_to_copy = [
|
||||
'src',
|
||||
'3rd-party/bluedroid',
|
||||
'3rd-party/hxcmod-player',
|
||||
'3rd-party/lwip/dhcp-server',
|
||||
'3rd-party/lc3-google',
|
||||
'3rd-party/md5',
|
||||
'3rd-party/micro-ecc',
|
||||
'3rd-party/yxml',
|
||||
'platform/freertos',
|
||||
'platform/lwip',
|
||||
'tool'
|
||||
]
|
||||
|
||||
for dir in dirs_to_copy:
|
||||
print('- %s' % dir)
|
||||
shutil.copytree(os.path.join(BTSTACK_PORT_DIR, '..', '..', dir), os.path.join(PROJECT_BTSTACK, dir))
|
||||
|
||||
# manually prepare platform/embedded
|
||||
print('- platform/embedded')
|
||||
platform_embedded_path = PROJECT_BTSTACK + '/platform/embedded'
|
||||
os.makedirs(platform_embedded_path)
|
||||
platform_embedded_files_to_copy = [
|
||||
'hal_time_ms.h',
|
||||
'hal_uart_dma.h',
|
||||
'hci_dump_embedded_stdout.h',
|
||||
'hci_dump_embedded_stdout.c',
|
||||
]
|
||||
for file in platform_embedded_files_to_copy:
|
||||
shutil.copy(os.path.join(BTSTACK_PORT_DIR, '..', '..', 'platform', 'embedded', file), platform_embedded_path)
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 3:
|
||||
print("Usage: script.py <path_to_btstack> <path_to_project_components>")
|
||||
sys.exit(1)
|
||||
|
||||
btstack_root = sys.argv[1]
|
||||
project_components = sys.argv[2]
|
||||
|
||||
if not os.path.exists(btstack_root):
|
||||
print(f"Error: Specified external directory does not exist: {btstack_root}")
|
||||
sys.exit(2)
|
||||
|
||||
if not os.path.exists(project_components):
|
||||
print(f"Error: Specified components directory does not exist: {project_components}")
|
||||
sys.exit(3)
|
||||
|
||||
main(btstack_root, project_components)
|
||||
@@ -1,25 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(LIBFIXMATH_ROOT ${CMAKE_CURRENT_LIST_DIR}/libfixmath)
|
||||
|
||||
if(NOT EXISTS ${LIBFIXMATH_ROOT}/libfixmath)
|
||||
message(FATAL_ERROR "libfixmath directory not found at ${LIBFIXMATH_ROOT}. Please ensure the library is present.")
|
||||
endif()
|
||||
|
||||
file(GLOB SRCS ${LIBFIXMATH_ROOT}/libfixmath/*.c)
|
||||
|
||||
idf_component_register(
|
||||
SRCS
|
||||
${SRCS}
|
||||
INCLUDE_DIRS
|
||||
${LIBFIXMATH_ROOT}
|
||||
${LIBFIXMATH_ROOT}/libfixmath
|
||||
)
|
||||
|
||||
target_compile_definitions(${COMPONENT_LIB} PRIVATE
|
||||
FIXMATH_FAST_SIN
|
||||
FIXMATH_NO_64BIT
|
||||
FIXMATH_NO_CACHE
|
||||
FIXMATH_NO_HARD_DIVISION
|
||||
FIXMATH_NO_OVERFLOW
|
||||
)
|
||||
Submodule Firmware/ESP32/components/libfixmath/libfixmath deleted from d308e466e1
@@ -1,10 +0,0 @@
|
||||
dependencies:
|
||||
idf:
|
||||
source:
|
||||
type: idf
|
||||
version: 5.4.1
|
||||
direct_dependencies:
|
||||
- idf
|
||||
manifest_hash: ed38c883314ee552977d073f5c9d0e2ab9acc3248eefbeb203f3439de3e31b6e
|
||||
target: esp32
|
||||
version: 2.0.0
|
||||
@@ -1,28 +0,0 @@
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../FWDefines.cmake)
|
||||
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"main.c"
|
||||
"log/log.c"
|
||||
"wired/wired_i2c.c"
|
||||
"wired/wired_spi.c"
|
||||
"led/led.c"
|
||||
"settings/nvs.c"
|
||||
"settings/settings.cpp"
|
||||
"settings/button_combo.c"
|
||||
"bluetooth/bluetooth.c"
|
||||
"periph/i2c_master.c"
|
||||
INCLUDE_DIRS
|
||||
"."
|
||||
REQUIRES
|
||||
bluepad32
|
||||
btstack
|
||||
nvs_flash
|
||||
libfixmath
|
||||
)
|
||||
|
||||
target_compile_definitions(${COMPONENT_LIB}
|
||||
PRIVATE
|
||||
FIRMWARE_NAME=\"${FW_NAME}\"
|
||||
FIRMWARE_VERSION=\"${FW_VERSION}\"
|
||||
)
|
||||
@@ -1,104 +0,0 @@
|
||||
menu "OGXMini Options"
|
||||
|
||||
config LOG_ENABLED
|
||||
bool "Enable logging"
|
||||
default n
|
||||
help
|
||||
Enable logging to the console. This is useful for debugging and monitoring the system.
|
||||
|
||||
config LOG_LEVEL
|
||||
int "Set log level"
|
||||
default 2
|
||||
range 0 3
|
||||
depends on LOG_ENABLED
|
||||
|
||||
choice
|
||||
prompt "Communication Interface"
|
||||
default I2C_ENABLED
|
||||
|
||||
config I2C_ENABLED
|
||||
bool "Enable I2C support"
|
||||
|
||||
config SPI_ENABLED
|
||||
bool "Enable SPI support"
|
||||
endchoice
|
||||
|
||||
config I2C_PORT
|
||||
int "Set I2C port"
|
||||
default 0
|
||||
depends on I2C_ENABLED
|
||||
|
||||
config I2C_SDA_PIN
|
||||
int "Set I2C SDA pin"
|
||||
default 21
|
||||
depends on I2C_ENABLED
|
||||
|
||||
config I2C_SCL_PIN
|
||||
int "Set I2C SCL pin"
|
||||
default 22
|
||||
depends on I2C_ENABLED
|
||||
|
||||
config I2C_IRQ_PIN
|
||||
int "Set I2C IRQ pin"
|
||||
default 9
|
||||
depends on I2C_ENABLED
|
||||
|
||||
config I2C_BAUDRATE
|
||||
int "Set I2C baudrate"
|
||||
default 1000000
|
||||
depends on I2C_ENABLED
|
||||
|
||||
config I2C_MULTI_SLAVE_MODE
|
||||
bool "Enable multiple slave devices"
|
||||
default n
|
||||
depends on I2C_ENABLED
|
||||
|
||||
config WIRED_HEADSET_ENABLED
|
||||
bool "Enable wired headset support"
|
||||
default n
|
||||
depends on SPI_ENABLED
|
||||
|
||||
# config RESET_PIN
|
||||
# int "Set reset pin"
|
||||
# default 9
|
||||
|
||||
config ENABLE_LED_1
|
||||
bool "Enable LED 1"
|
||||
default y
|
||||
|
||||
config LED_PIN_1
|
||||
int "Set LED 1 pin"
|
||||
default 15
|
||||
depends on ENABLE_LED_1
|
||||
|
||||
config ENABLE_LED_2
|
||||
bool "Enable LED 2"
|
||||
default n
|
||||
depends on ENABLE_LED_1
|
||||
|
||||
config LED_PIN_2
|
||||
int "Set LED 2 pin"
|
||||
default 15
|
||||
depends on ENABLE_LED_2
|
||||
|
||||
config ENABLE_LED_3
|
||||
bool "Enable LED 3"
|
||||
default n
|
||||
depends on ENABLE_LED_2
|
||||
|
||||
config LED_PIN_3
|
||||
int "Set LED 3 pin"
|
||||
default 15
|
||||
depends on ENABLE_LED_3
|
||||
|
||||
config ENABLE_LED_4
|
||||
bool "Enable LED 4"
|
||||
default n
|
||||
depends on ENABLE_LED_3
|
||||
|
||||
config LED_PIN_4
|
||||
int "Set LED 4 pin"
|
||||
default 15
|
||||
depends on ENABLE_LED_4
|
||||
|
||||
endmenu
|
||||
@@ -1,330 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include "btstack_port_esp32.h"
|
||||
#include "btstack_run_loop.h"
|
||||
#include "btstack_stdio_esp32.h"
|
||||
#include "uni.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "bluetooth/bluetooth.h"
|
||||
#include "bluetooth/ring_rumble.h"
|
||||
#include "led/led.h"
|
||||
#include "log/log.h"
|
||||
#include "gamepad/range.h"
|
||||
#include "settings/settings.h"
|
||||
|
||||
#define LED_INTERVAL_MS 500U
|
||||
#define JOY_DIF_THRESHOLD 0x50
|
||||
#define TRIGGER_DIF_THRESHOLD 0x50
|
||||
|
||||
typedef struct {
|
||||
volatile bool connected;
|
||||
gamepad_pad_t report;
|
||||
uni_gamepad_t prev_uni;
|
||||
struct {
|
||||
bool joy_l;
|
||||
bool joy_r;
|
||||
bool trigger_l;
|
||||
bool trigger_r;
|
||||
} map;
|
||||
} gp_context_t;
|
||||
|
||||
typedef struct {
|
||||
bool led_state;
|
||||
bool led_timer_running;
|
||||
btstack_timer_source_t led_timer;
|
||||
gp_context_t gp_ctx[GAMEPADS_MAX];
|
||||
bt_connect_cb_t connect_cb;
|
||||
bt_gamepad_cb_t gamepad_cb;
|
||||
ring_rumble_t rumble_ring;
|
||||
btstack_context_callback_registration_t rumble_cb_reg;
|
||||
} bt_context_t;
|
||||
|
||||
static bt_context_t bt_context = {0};
|
||||
|
||||
static inline bool any_connected(void) {
|
||||
for (int i = 0; i < GAMEPADS_MAX; i++) {
|
||||
if (bt_context.gp_ctx[i].connected) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void led_blink_cb(btstack_timer_source_t *ts) {
|
||||
bt_context.led_state = !bt_context.led_state;
|
||||
led_set(0, bt_context.led_state);
|
||||
btstack_run_loop_set_timer(ts, LED_INTERVAL_MS);
|
||||
btstack_run_loop_add_timer(ts);
|
||||
}
|
||||
|
||||
static void led_blink_set_enabled(bool enable) {
|
||||
if (enable && !bt_context.led_timer_running) {
|
||||
bt_context.led_timer_running = true;
|
||||
bt_context.led_timer.process = led_blink_cb;
|
||||
btstack_run_loop_set_timer(&bt_context.led_timer, LED_INTERVAL_MS);
|
||||
btstack_run_loop_add_timer(&bt_context.led_timer);
|
||||
} else if (!enable && bt_context.led_timer_running) {
|
||||
bt_context.led_timer_running = false;
|
||||
btstack_run_loop_remove_timer(&bt_context.led_timer);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_rumble_cb(void* ctx) {
|
||||
uint8_t index = 0;
|
||||
gamepad_rumble_t rumble = {0};
|
||||
if (!ring_rumble_pop(&bt_context.rumble_ring, &index, &rumble)) {
|
||||
return;
|
||||
}
|
||||
uni_hid_device_t* bp_dev = uni_hid_device_get_instance_for_idx(index);
|
||||
if ((bp_dev == NULL) || !bt_context.gp_ctx[index].connected ||
|
||||
(bp_dev->report_parser.play_dual_rumble == NULL)) {
|
||||
return;
|
||||
}
|
||||
uint8_t duration = 100;
|
||||
if ((rumble.l_duration > 0) || (rumble.r_duration > 0)) {
|
||||
duration = MAX(rumble.l_duration, rumble.r_duration);
|
||||
}
|
||||
else if (bp_dev->controller_type == CONTROLLER_TYPE_XBoxOneController) {
|
||||
duration += 10;
|
||||
}
|
||||
bp_dev->report_parser.play_dual_rumble(bp_dev, 0, duration, rumble.l, rumble.r);
|
||||
|
||||
if (!ring_rumble_empty(&bt_context.rumble_ring)) {
|
||||
bt_context.rumble_cb_reg.callback = set_rumble_cb;
|
||||
bt_context.rumble_cb_reg.context = NULL;
|
||||
btstack_run_loop_execute_on_main_thread(&bt_context.rumble_cb_reg);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- Bluepad32 driver ---- */
|
||||
|
||||
static void bp32_init_cb(int argc, const char** arg_V) {
|
||||
(void)argc;
|
||||
(void)arg_V;
|
||||
}
|
||||
|
||||
static void bp32_init_complete_cb(void) {
|
||||
// uni_bt_enable_new_connections_unsafe(true);
|
||||
uni_bt_start_scanning_and_autoconnect_unsafe();
|
||||
// uni_bt_del_keys_unsafe();
|
||||
uni_property_dump_all();
|
||||
}
|
||||
|
||||
static uni_error_t bp32_device_discovered_cb(bd_addr_t addr, const char* name,
|
||||
uint16_t cod, uint8_t rssi) {
|
||||
(void)rssi;
|
||||
(void)name;
|
||||
(void)addr;
|
||||
|
||||
if (((cod & UNI_BT_COD_MINOR_MASK) & UNI_BT_COD_MINOR_GAMEPAD) == 0) {
|
||||
return UNI_ERROR_IGNORE_DEVICE;
|
||||
}
|
||||
return UNI_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static void bp32_device_connected_cb(uni_hid_device_t* device) {
|
||||
(void)device;
|
||||
}
|
||||
|
||||
static uni_error_t bp32_device_ready_cb(uni_hid_device_t* device) {
|
||||
int index = uni_hid_device_get_idx_for_instance(device);
|
||||
if (index < 0 || index >= GAMEPADS_MAX) {
|
||||
return UNI_ERROR_INVALID_CONTROLLER;
|
||||
}
|
||||
bt_context.gp_ctx[index].connected = true;
|
||||
led_blink_set_enabled(false);
|
||||
led_set(index, true);
|
||||
if (bt_context.connect_cb) {
|
||||
bt_context.connect_cb(index, true);
|
||||
}
|
||||
return UNI_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static void bp32_device_disconnect_cb(uni_hid_device_t* device) {
|
||||
int index = uni_hid_device_get_idx_for_instance(device);
|
||||
if (index < 0 || index >= GAMEPADS_MAX) {
|
||||
return;
|
||||
}
|
||||
bt_context.gp_ctx[index].connected = false;
|
||||
if (!any_connected()) {
|
||||
led_blink_set_enabled(true);
|
||||
}
|
||||
if (bt_context.connect_cb) {
|
||||
bt_context.connect_cb(index, false);
|
||||
}
|
||||
}
|
||||
|
||||
static void bp32_oob_event_cb(uni_platform_oob_event_t event, void* data) {
|
||||
(void)data;
|
||||
(void)event;
|
||||
}
|
||||
|
||||
// Prevent I2C/SPI bus flooding
|
||||
static inline bool gp_state_change(const uni_gamepad_t* uni_a, const uni_gamepad_t* uni_b) {
|
||||
if (memcmp(uni_a, uni_b, sizeof(uni_gamepad_t)) == 0) {
|
||||
return false;
|
||||
}
|
||||
if ((uni_a->dpad != uni_b->dpad) ||
|
||||
(uni_a->buttons != uni_b->buttons) ||
|
||||
(uni_a->misc_buttons != uni_b->misc_buttons)) {
|
||||
return true;
|
||||
}
|
||||
if ((abs(uni_a->brake - uni_b->brake) > TRIGGER_DIF_THRESHOLD) ||
|
||||
(uni_a->brake <= 0) || (uni_a->brake >= R_UINT10_MAX)) {
|
||||
return true;
|
||||
}
|
||||
if ((abs(uni_a->throttle - uni_b->throttle) > TRIGGER_DIF_THRESHOLD) ||
|
||||
(uni_a->throttle <= 0) || (uni_a->throttle >= R_UINT10_MAX)) {
|
||||
return true;
|
||||
}
|
||||
if ((abs(uni_a->axis_x - uni_b->axis_x) > JOY_DIF_THRESHOLD) ||
|
||||
(uni_a->axis_x <= R_INT10_MIN) || (uni_a->axis_x >= R_INT10_MAX)) {
|
||||
return true;
|
||||
}
|
||||
if ((abs(uni_a->axis_y - uni_b->axis_y) > JOY_DIF_THRESHOLD) ||
|
||||
(uni_a->axis_y <= R_INT10_MIN) || (uni_a->axis_y >= R_INT10_MAX)) {
|
||||
return true;
|
||||
}
|
||||
if ((abs(uni_a->axis_rx - uni_b->axis_rx) > JOY_DIF_THRESHOLD) ||
|
||||
(uni_a->axis_rx <= R_INT10_MIN) || (uni_a->axis_rx >= R_INT10_MAX)) {
|
||||
return true;
|
||||
}
|
||||
if ((abs(uni_a->axis_ry - uni_b->axis_ry) > JOY_DIF_THRESHOLD) ||
|
||||
(uni_a->axis_ry <= R_INT10_MIN) || (uni_a->axis_ry >= R_INT10_MAX)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void bp32_controller_data_cb(uni_hid_device_t* device, uni_controller_t* controller) {
|
||||
if (controller->klass != UNI_CONTROLLER_CLASS_GAMEPAD){
|
||||
return;
|
||||
}
|
||||
|
||||
const uni_gamepad_t* uni = &controller->gamepad;
|
||||
int index = uni_hid_device_get_idx_for_instance(device);
|
||||
|
||||
if ((index < 0) || (index >= GAMEPADS_MAX) ||
|
||||
!gp_state_change(uni, &bt_context.gp_ctx[index].prev_uni)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gamepad_pad_t* pad = &bt_context.gp_ctx[index].report;
|
||||
memset(pad, 0, sizeof(gamepad_pad_t));
|
||||
|
||||
switch (uni->dpad) {
|
||||
case DPAD_UP:
|
||||
pad->dpad |= GAMEPAD_D_UP;
|
||||
break;
|
||||
case DPAD_DOWN:
|
||||
pad->dpad |= GAMEPAD_D_DOWN;
|
||||
break;
|
||||
case DPAD_LEFT:
|
||||
pad->dpad |= GAMEPAD_D_LEFT;
|
||||
break;
|
||||
case DPAD_RIGHT:
|
||||
pad->dpad |= GAMEPAD_D_RIGHT;
|
||||
break;
|
||||
case DPAD_UP | DPAD_RIGHT:
|
||||
pad->dpad |= (GAMEPAD_D_UP | GAMEPAD_D_RIGHT);
|
||||
break;
|
||||
case DPAD_DOWN | DPAD_RIGHT:
|
||||
pad->dpad |= (GAMEPAD_D_DOWN | GAMEPAD_D_RIGHT);
|
||||
break;
|
||||
case DPAD_DOWN | DPAD_LEFT:
|
||||
pad->dpad |= (GAMEPAD_D_DOWN | GAMEPAD_D_LEFT);
|
||||
break;
|
||||
case DPAD_UP | DPAD_LEFT:
|
||||
pad->dpad |= (GAMEPAD_D_UP | GAMEPAD_D_LEFT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (uni->buttons & BUTTON_A) { pad->buttons |= GAMEPAD_BTN_A; }
|
||||
if (uni->buttons & BUTTON_B) { pad->buttons |= GAMEPAD_BTN_B; }
|
||||
if (uni->buttons & BUTTON_X) { pad->buttons |= GAMEPAD_BTN_X; }
|
||||
if (uni->buttons & BUTTON_Y) { pad->buttons |= GAMEPAD_BTN_Y; }
|
||||
if (uni->buttons & BUTTON_SHOULDER_L) { pad->buttons |= GAMEPAD_BTN_LB; }
|
||||
if (uni->buttons & BUTTON_SHOULDER_R) { pad->buttons |= GAMEPAD_BTN_RB; }
|
||||
if (uni->buttons & BUTTON_THUMB_L) { pad->buttons |= GAMEPAD_BTN_L3; }
|
||||
if (uni->buttons & BUTTON_THUMB_R) { pad->buttons |= GAMEPAD_BTN_R3; }
|
||||
if (uni->misc_buttons & MISC_BUTTON_BACK) { pad->buttons |= GAMEPAD_BTN_BACK; }
|
||||
if (uni->misc_buttons & MISC_BUTTON_START) { pad->buttons |= GAMEPAD_BTN_START; }
|
||||
if (uni->misc_buttons & MISC_BUTTON_SYSTEM) { pad->buttons |= GAMEPAD_BTN_SYS; }
|
||||
|
||||
pad->trigger_l = range_uint10_to_uint8(uni->brake);
|
||||
pad->trigger_r = range_uint10_to_uint8(uni->throttle);
|
||||
|
||||
pad->joystick_lx = range_int10_to_int16(uni->axis_x);
|
||||
pad->joystick_ly = range_invert_int16(range_int10_to_int16(uni->axis_y));
|
||||
pad->joystick_rx = range_int10_to_int16(uni->axis_rx);
|
||||
pad->joystick_ry = range_invert_int16(range_int10_to_int16(uni->axis_ry));
|
||||
|
||||
if (bt_context.gamepad_cb != NULL) {
|
||||
bt_context.gamepad_cb(index, pad, GAMEPAD_FLAG_IN_PAD);
|
||||
}
|
||||
memcpy(&bt_context.gp_ctx[index].prev_uni, uni, sizeof(uni_gamepad_t));
|
||||
}
|
||||
|
||||
static const uni_property_t* bp32_get_property_cb(uni_property_idx_t idx) {
|
||||
(void)idx;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct uni_platform BP32_DRIVER = {
|
||||
.name = "OGX-Mini",
|
||||
.init = bp32_init_cb,
|
||||
.on_init_complete = bp32_init_complete_cb,
|
||||
.on_device_discovered = bp32_device_discovered_cb,
|
||||
.on_device_connected = bp32_device_connected_cb,
|
||||
.on_device_disconnected = bp32_device_disconnect_cb,
|
||||
.on_device_ready = bp32_device_ready_cb,
|
||||
.on_controller_data = bp32_controller_data_cb,
|
||||
.get_property = bp32_get_property_cb,
|
||||
.on_oob_event = bp32_oob_event_cb,
|
||||
};
|
||||
|
||||
/* ---- Public ---- */
|
||||
|
||||
void bluetooth_set_rumble(uint8_t index, const gamepad_rumble_t* rumble) {
|
||||
if ((index >= GAMEPADS_MAX) ||
|
||||
!bt_context.gp_ctx[index].connected ||
|
||||
(rumble == NULL)) {
|
||||
return;
|
||||
}
|
||||
ring_rumble_push(&bt_context.rumble_ring, index, rumble);
|
||||
bt_context.rumble_cb_reg.callback = set_rumble_cb;
|
||||
bt_context.rumble_cb_reg.context = NULL;
|
||||
btstack_run_loop_execute_on_main_thread(&bt_context.rumble_cb_reg);
|
||||
}
|
||||
|
||||
void bluetooth_set_audio(uint8_t index, const gamepad_pcm_in_t* pcm) {
|
||||
(void)index;
|
||||
(void)pcm;
|
||||
// Bluetooth audio handling is not implemented in this version
|
||||
}
|
||||
|
||||
void bluetooth_config(bt_connect_cb_t connect_cb, bt_gamepad_cb_t gamepad_cb, bt_audio_cb_t audio_cb) {
|
||||
(void)audio_cb;
|
||||
memset(&bt_context, 0, sizeof(bt_context_t));
|
||||
bt_context.connect_cb = connect_cb;
|
||||
bt_context.gamepad_cb = gamepad_cb;
|
||||
}
|
||||
|
||||
void bluetooth_task(void* args) {
|
||||
(void)args;
|
||||
|
||||
btstack_init();
|
||||
|
||||
// ble_server_init();
|
||||
|
||||
uni_platform_set_custom(&BP32_DRIVER);
|
||||
uni_init(0, NULL);
|
||||
|
||||
led_init();
|
||||
led_blink_set_enabled(true);
|
||||
|
||||
btstack_run_loop_execute();
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "gamepad/gamepad.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*bt_connect_cb_t)(uint8_t index, bool connected);
|
||||
typedef void (*bt_gamepad_cb_t)(uint8_t index, const gamepad_pad_t* pad, uint32_t flags);
|
||||
typedef void (*bt_audio_cb_t)(uint8_t index, const gamepad_pcm_out_t* pcm);
|
||||
|
||||
void bluetooth_config(bt_connect_cb_t connect_cb, bt_gamepad_cb_t gamepad_cb, bt_audio_cb_t audio_cb);
|
||||
void bluetooth_task(void* args);
|
||||
void bluetooth_set_rumble(uint8_t index, const gamepad_rumble_t* rumble);
|
||||
void bluetooth_set_audio(uint8_t index, const gamepad_pcm_in_t* pcm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,55 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdatomic.h>
|
||||
#include "gamepad/gamepad.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RUBMLE_RING_SIZE 8U
|
||||
|
||||
typedef struct {
|
||||
gamepad_rumble_t buf[RUBMLE_RING_SIZE] __attribute__((aligned(4)));
|
||||
uint8_t index[RUBMLE_RING_SIZE];
|
||||
atomic_uint head;
|
||||
atomic_uint tail;
|
||||
} ring_rumble_t;
|
||||
|
||||
static inline bool ring_rumble_push(ring_rumble_t* ring, uint8_t index, const gamepad_rumble_t* rumble) {
|
||||
uint32_t head = atomic_load_explicit(&ring->head, memory_order_relaxed);
|
||||
uint32_t next_head = (head + 1) % RUBMLE_RING_SIZE;
|
||||
uint32_t tail = atomic_load_explicit(&ring->tail, memory_order_acquire);
|
||||
|
||||
if (next_head == tail) {
|
||||
atomic_store_explicit(&ring->tail, (tail + 1) % RUBMLE_RING_SIZE, memory_order_release);
|
||||
}
|
||||
ring->index[head] = index;
|
||||
memcpy(&ring->buf[head], rumble, sizeof(gamepad_rumble_t));
|
||||
atomic_store_explicit(&ring->head, next_head, memory_order_release);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool ring_rumble_pop(ring_rumble_t* ring, uint8_t* index, gamepad_rumble_t* rumble) {
|
||||
uint32_t tail = atomic_load_explicit(&ring->tail, memory_order_relaxed);
|
||||
uint32_t head = atomic_load_explicit(&ring->head, memory_order_acquire);
|
||||
if (tail == head) {
|
||||
return false;
|
||||
}
|
||||
*index = ring->index[tail];
|
||||
memcpy(rumble, &ring->buf[tail], sizeof(gamepad_rumble_t));
|
||||
atomic_store_explicit(&ring->tail, (tail + 1) % RUBMLE_RING_SIZE, memory_order_release);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool ring_rumble_empty(const ring_rumble_t* ring) {
|
||||
return (atomic_load_explicit(&ring->head, memory_order_relaxed) ==
|
||||
atomic_load_explicit(&ring->tail, memory_order_acquire));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,82 +0,0 @@
|
||||
#ifndef _ESP_BTSTACK_CONFIG_H
|
||||
#define _ESP_BTSTACK_CONFIG_H
|
||||
|
||||
// BTstack features that can be enabled
|
||||
// #define ENABLE_LE_PERIPHERAL
|
||||
// #define ENABLE_LE_CENTRAL
|
||||
// #define ENABLE_L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE
|
||||
// #define ENABLE_LOG_INFO
|
||||
// #define ENABLE_LOG_ERROR
|
||||
// #define ENABLE_PRINTF_HEXDUMP
|
||||
#define ENABLE_SCO_OVER_HCI
|
||||
|
||||
// BTstack configuration. buffers, sizes, ...
|
||||
#define HCI_OUTGOING_PRE_BUFFER_SIZE 4
|
||||
#define HCI_ACL_PAYLOAD_SIZE (1691 + 4)
|
||||
#define HCI_ACL_CHUNK_SIZE_ALIGNMENT 4
|
||||
// #define MAX_NR_AVDTP_CONNECTIONS 1
|
||||
// #define MAX_NR_AVDTP_STREAM_ENDPOINTS 1
|
||||
// #define MAX_NR_AVRCP_CONNECTIONS 2
|
||||
// #define MAX_NR_BNEP_CHANNELS 1
|
||||
// #define MAX_NR_BNEP_SERVICES 1
|
||||
// #define MAX_NR_BTSTACK_LINK_KEY_DB_MEMORY_ENTRIES 2
|
||||
// #define MAX_NR_GATT_CLIENTS 4
|
||||
// #define MAX_NR_HCI_CONNECTIONS 4
|
||||
// #define MAX_NR_HID_HOST_CONNECTIONS 4
|
||||
// #define MAX_NR_HIDS_CLIENTS 4
|
||||
// #define MAX_NR_HFP_CONNECTIONS 1
|
||||
// #define MAX_NR_L2CAP_CHANNELS 6
|
||||
// #define MAX_NR_L2CAP_SERVICES 5
|
||||
// #define MAX_NR_RFCOMM_CHANNELS 1
|
||||
// #define MAX_NR_RFCOMM_MULTIPLEXERS 1
|
||||
// #define MAX_NR_RFCOMM_SERVICES 1
|
||||
// #define MAX_NR_SERVICE_RECORD_ITEMS 4
|
||||
// #define MAX_NR_SM_LOOKUP_ENTRIES 3
|
||||
// #define MAX_NR_WHITELIST_ENTRIES 16
|
||||
// #define MAX_NR_LE_DEVICE_DB_ENTRIES 16
|
||||
|
||||
// Limit number of ACL/SCO Buffer to use by stack to avoid cyw43 shared bus overrun
|
||||
#define MAX_NR_CONTROLLER_ACL_BUFFERS 6
|
||||
#define MAX_NR_CONTROLLER_SCO_PACKETS 6
|
||||
|
||||
// Enable and configure HCI Controller to Host Flow Control to avoid cyw43 shared bus overrun
|
||||
#define ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
|
||||
#define HCI_HOST_ACL_PACKET_LEN 1024
|
||||
#define HCI_HOST_ACL_PACKET_NUM 6
|
||||
#define HCI_HOST_SCO_PACKET_LEN 120
|
||||
#define HCI_HOST_SCO_PACKET_NUM 6
|
||||
|
||||
#ifndef HCI_INCOMING_PRE_BUFFER_SIZE
|
||||
#define HCI_INCOMING_PRE_BUFFER_SIZE 6
|
||||
#endif
|
||||
|
||||
// Link Key DB and LE Device DB using TLV on top of Flash Sector interface
|
||||
// #define NVM_NUM_DEVICE_DB_ENTRIES 16
|
||||
// #define NVM_NUM_LINK_KEYS 16
|
||||
|
||||
// We don't give btstack a malloc, so use a fixed-size ATT DB.
|
||||
#define MAX_ATT_DB_SIZE 512
|
||||
// #define HAVE_MALLOC
|
||||
|
||||
// BTstack HAL configuration
|
||||
// #define HAVE_EMBEDDED_TIME_MS
|
||||
|
||||
// // map btstack_assert onto Pico SDK assert()
|
||||
// #define HAVE_ASSERT
|
||||
|
||||
// // Some USB dongles take longer to respond to HCI reset (e.g. BCM20702A).
|
||||
#define HCI_RESET_RESEND_TIMEOUT_MS 1000
|
||||
|
||||
// #define ENABLE_SOFTWARE_AES128
|
||||
// #define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
|
||||
|
||||
// #define HAVE_BTSTACK_STDIN
|
||||
|
||||
// To get the audio demos working even with HCI dump at 115200, this truncates long ACL packetws
|
||||
#define HCI_DUMP_STDOUT_MAX_SIZE_ACL 100
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
#define ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE
|
||||
#endif
|
||||
|
||||
#endif // _ESP_BTSTACK_CONFIG_H
|
||||
@@ -1,125 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef GAMEPADS_MAX
|
||||
#define GAMEPADS_MAX CONFIG_BLUEPAD32_MAX_DEVICES
|
||||
#endif
|
||||
|
||||
#define GAMPAD_PCM_FRAME_SIZE 16U
|
||||
|
||||
typedef enum {
|
||||
GAMEPAD_DPAD_BIT_UP = 0,
|
||||
GAMEPAD_DPAD_BIT_DOWN,
|
||||
GAMEPAD_DPAD_BIT_LEFT,
|
||||
GAMEPAD_DPAD_BIT_RIGHT,
|
||||
GAMEPAD_DPAD_BIT_COUNT,
|
||||
GAMEPAD_DPAD_BIT_NONE = GAMEPAD_DPAD_BIT_COUNT,
|
||||
} gamepad_dpad_bit_t;
|
||||
|
||||
typedef enum {
|
||||
GAMEPAD_BTN_BIT_A = 0,
|
||||
GAMEPAD_BTN_BIT_B,
|
||||
GAMEPAD_BTN_BIT_X,
|
||||
GAMEPAD_BTN_BIT_Y,
|
||||
GAMEPAD_BTN_BIT_L3,
|
||||
GAMEPAD_BTN_BIT_R3,
|
||||
GAMEPAD_BTN_BIT_LB,
|
||||
GAMEPAD_BTN_BIT_RB,
|
||||
GAMEPAD_BTN_BIT_LT,
|
||||
GAMEPAD_BTN_BIT_RT,
|
||||
GAMEPAD_BTN_BIT_BACK,
|
||||
GAMEPAD_BTN_BIT_START,
|
||||
GAMEPAD_BTN_BIT_SYS,
|
||||
GAMEPAD_BTN_BIT_MISC,
|
||||
GAMEPAD_BTN_BIT_COUNT,
|
||||
GAMEPAD_BTN_BIT_NONE = GAMEPAD_BTN_BIT_COUNT,
|
||||
} gamepad_btn_bit_t;
|
||||
|
||||
typedef enum {
|
||||
GAMEPAD_ANALOG_UP = 0,
|
||||
GAMEPAD_ANALOG_DOWN,
|
||||
GAMEPAD_ANALOG_LEFT,
|
||||
GAMEPAD_ANALOG_RIGHT,
|
||||
GAMEPAD_ANALOG_A,
|
||||
GAMEPAD_ANALOG_B,
|
||||
GAMEPAD_ANALOG_X,
|
||||
GAMEPAD_ANALOG_Y,
|
||||
GAMEPAD_ANALOG_LB,
|
||||
GAMEPAD_ANALOG_RB,
|
||||
GAMEPAD_ANALOG_COUNT
|
||||
} gampead_analog_t;
|
||||
|
||||
#define GP_BIT8(bit) ((uint8_t)1U << (bit))
|
||||
#define GP_BIT16(bit) ((uint16_t)1U << (bit))
|
||||
|
||||
#define GAMEPAD_D_UP GP_BIT8(GAMEPAD_DPAD_BIT_UP)
|
||||
#define GAMEPAD_D_DOWN GP_BIT8(GAMEPAD_DPAD_BIT_DOWN)
|
||||
#define GAMEPAD_D_LEFT GP_BIT8(GAMEPAD_DPAD_BIT_LEFT)
|
||||
#define GAMEPAD_D_RIGHT GP_BIT8(GAMEPAD_DPAD_BIT_RIGHT)
|
||||
|
||||
#define GAMEPAD_BTN_A GP_BIT16(GAMEPAD_BTN_BIT_A)
|
||||
#define GAMEPAD_BTN_B GP_BIT16(GAMEPAD_BTN_BIT_B)
|
||||
#define GAMEPAD_BTN_X GP_BIT16(GAMEPAD_BTN_BIT_X)
|
||||
#define GAMEPAD_BTN_Y GP_BIT16(GAMEPAD_BTN_BIT_Y)
|
||||
#define GAMEPAD_BTN_L3 GP_BIT16(GAMEPAD_BTN_BIT_L3)
|
||||
#define GAMEPAD_BTN_R3 GP_BIT16(GAMEPAD_BTN_BIT_R3)
|
||||
#define GAMEPAD_BTN_LB GP_BIT16(GAMEPAD_BTN_BIT_LB)
|
||||
#define GAMEPAD_BTN_RB GP_BIT16(GAMEPAD_BTN_BIT_RB)
|
||||
#define GAMEPAD_BTN_LT GP_BIT16(GAMEPAD_BTN_BIT_LT)
|
||||
#define GAMEPAD_BTN_RT GP_BIT16(GAMEPAD_BTN_BIT_RT)
|
||||
#define GAMEPAD_BTN_BACK GP_BIT16(GAMEPAD_BTN_BIT_BACK)
|
||||
#define GAMEPAD_BTN_START GP_BIT16(GAMEPAD_BTN_BIT_START)
|
||||
#define GAMEPAD_BTN_SYS GP_BIT16(GAMEPAD_BTN_BIT_SYS)
|
||||
#define GAMEPAD_BTN_MISC GP_BIT16(GAMEPAD_BTN_BIT_MISC)
|
||||
|
||||
typedef struct __attribute__((packed, aligned(4))) {
|
||||
uint8_t dpad;
|
||||
uint8_t reserved0;
|
||||
uint16_t buttons;
|
||||
uint8_t trigger_l;
|
||||
uint8_t trigger_r;
|
||||
int16_t joystick_lx;
|
||||
int16_t joystick_ly;
|
||||
int16_t joystick_rx;
|
||||
int16_t joystick_ry;
|
||||
uint8_t analog[GAMEPAD_ANALOG_COUNT];
|
||||
// uint8_t chatpad[3];
|
||||
// uint8_t reserved1;
|
||||
} gamepad_pad_t;
|
||||
_Static_assert(sizeof(gamepad_pad_t) == 24, "Gamepad pad size mismatch");
|
||||
|
||||
typedef struct __attribute__((packed, aligned(4))) {
|
||||
uint8_t l;
|
||||
uint8_t r;
|
||||
uint8_t l_duration;
|
||||
uint8_t r_duration;
|
||||
} gamepad_rumble_t;
|
||||
_Static_assert(sizeof(gamepad_rumble_t) == 4, "Gamepad rumble size mismatch");
|
||||
|
||||
typedef struct __attribute__((packed, aligned(4))) {
|
||||
int16_t data[GAMPAD_PCM_FRAME_SIZE];
|
||||
uint16_t samples;
|
||||
uint16_t reserved;
|
||||
} gamepad_pcm_t, gamepad_pcm_in_t, gamepad_pcm_out_t;
|
||||
_Static_assert(sizeof(gamepad_pcm_t) == 36, "Gamepad PCM size mismatch");
|
||||
|
||||
/* ---- IN/OUT Data Flags ---- */
|
||||
|
||||
#define GAMEPAD_FLAG_IN_PAD ((uint32_t)1 << 0) /* New Device->Host pad data */
|
||||
#define GAMEPAD_FLAG_IN_PAD_ANALOG ((uint32_t)1 << 1) /* New Device->Host pad data has analog data */
|
||||
#define GAMEPAD_FLAG_IN_CHATPAD ((uint32_t)1 << 2) /* New Device->Host chatpad data */
|
||||
#define GAMEPAD_FLAG_IN_PCM ((uint32_t)1 << 3) /* New Device->Host PCM data */
|
||||
#define GAMEPAD_FLAG_OUT_PCM ((uint32_t)1 << 4) /* New Host->Device PCM data */
|
||||
#define GAMEPAD_FLAG_OUT_RUMBLE ((uint32_t)1 << 5) /* New Host->Device rumble data */
|
||||
#define GAMEPAD_FLAG_OUT_RUMBLE_DUR ((uint32_t)1 << 6) /* New Host->Device rumble has duration info */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,98 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define R_INT16_MAX ((int16_t)32767)
|
||||
#define R_INT16_MID ((int16_t)0)
|
||||
#define R_INT16_MIN ((int16_t)-32768)
|
||||
|
||||
#define R_UINT8_MAX ((uint8_t)255)
|
||||
#define R_UINT8_MID ((uint8_t)128)
|
||||
#define R_UINT8_MIN ((uint8_t)0)
|
||||
|
||||
#define R_UINT16_MAX ((uint16_t)65535)
|
||||
#define R_UINT16_MID ((uint16_t)32768)
|
||||
#define R_UINT16_MIN ((uint16_t)0)
|
||||
|
||||
#define R_UINT10_MAX ((uint16_t)1023)
|
||||
#define R_UINT10_MID ((uint16_t)512)
|
||||
#define R_UINT10_MIN ((uint16_t)0)
|
||||
|
||||
#define R_INT10_MAX ((int16_t)511)
|
||||
#define R_INT10_MID ((int16_t)0)
|
||||
#define R_INT10_MIN ((int16_t)-512)
|
||||
|
||||
static inline int16_t range_uint8_to_int16(uint8_t value) {
|
||||
return (int16_t)(((int32_t)value << 8) - R_UINT16_MID);
|
||||
}
|
||||
|
||||
static inline uint16_t range_uint8_to_uint16(uint8_t value) {
|
||||
return (uint16_t)value << 8;
|
||||
}
|
||||
|
||||
static inline uint8_t range_int16_to_uint8(int16_t value) {
|
||||
return (uint8_t)(((int32_t)value + R_UINT16_MID) >> 8);
|
||||
}
|
||||
|
||||
static inline uint8_t range_uint16_to_uint8(uint16_t value) {
|
||||
return (uint8_t)(value >> 8);
|
||||
}
|
||||
|
||||
static inline int16_t range_uint10_to_int16(uint16_t value) {
|
||||
return (int16_t)(((int32_t)MIN(value, R_UINT10_MAX) << 6) - R_UINT16_MID);
|
||||
}
|
||||
|
||||
static inline uint8_t range_uint10_to_uint8(uint16_t value) {
|
||||
return (uint8_t)(MIN(value, R_UINT10_MAX) >> 2);
|
||||
}
|
||||
|
||||
static inline int16_t range_int10_to_int16(int16_t value) {
|
||||
if (value > R_INT10_MAX) {
|
||||
value = R_INT10_MAX;
|
||||
} else if (value < R_INT10_MIN) {
|
||||
value = R_INT10_MIN;
|
||||
}
|
||||
return value << 6;
|
||||
}
|
||||
|
||||
static inline int16_t range_invert_int16(int16_t value) {
|
||||
return (int16_t)(-((int32_t)value) - 1);
|
||||
}
|
||||
|
||||
static inline int16_t range_free_scale_int16(int32_t value, int32_t min, int32_t max) {
|
||||
if (max <= min) {
|
||||
return 0;
|
||||
} else if (value < min) {
|
||||
return R_INT16_MIN;
|
||||
} else if (value > max) {
|
||||
return R_INT16_MAX;
|
||||
}
|
||||
return (int16_t)(((value - min) * (int64_t)(R_INT16_MAX - R_INT16_MIN)) / (max - min) + R_INT16_MIN);
|
||||
}
|
||||
|
||||
static inline uint8_t range_free_scale_uint8(int32_t value, int32_t min, int32_t max) {
|
||||
if (max <= min) {
|
||||
return 0;
|
||||
} else if (value < min) {
|
||||
return R_UINT8_MIN;
|
||||
} else if (value > max) {
|
||||
return R_UINT8_MAX;
|
||||
}
|
||||
return (uint8_t)(((value - min) * (int64_t)(R_UINT8_MAX - R_UINT8_MIN)) / (max - min) + R_UINT8_MIN);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,42 +0,0 @@
|
||||
#include <hal/gpio_ll.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "led/led.h"
|
||||
#include "gamepad/gamepad.h"
|
||||
|
||||
static const int LED_PINS[] = {
|
||||
#if defined(CONFIG_ENABLE_LED_1) && (GAMEPADS_MAX > 0)
|
||||
CONFIG_LED_PIN_1,
|
||||
|
||||
#if defined(CONFIG_ENABLE_LED_2) && (GAMEPADS_MAX > 1)
|
||||
CONFIG_LED_PIN_2,
|
||||
|
||||
#if defined(CONFIG_ENABLE_LED_3) && (GAMEPADS_MAX > 2)
|
||||
CONFIG_LED_PIN_3,
|
||||
|
||||
#if defined(CONFIG_ENABLE_LED_4) && (GAMEPADS_MAX > 3)
|
||||
CONFIG_LED_PIN_4,
|
||||
|
||||
#endif // CONFIG_ENABLE_LED_4
|
||||
#endif // CONFIG_ENABLE_LED_3
|
||||
#endif // CONFIG_ENABLE_LED_2
|
||||
#endif // CONFIG_ENABLE_LED_1
|
||||
};
|
||||
|
||||
#define NUM_LEDS (sizeof(LED_PINS) / sizeof(LED_PINS[0]))
|
||||
|
||||
void led_init(void) {
|
||||
for (uint8_t i = 0; i < NUM_LEDS; ++i) {
|
||||
gpio_ll_output_enable(&GPIO, LED_PINS[i]);
|
||||
gpio_ll_set_level(&GPIO, LED_PINS[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
void led_set(uint8_t index, bool state) {
|
||||
if (NUM_LEDS == 0) {
|
||||
return;
|
||||
}
|
||||
if (index >= NUM_LEDS) {
|
||||
index = NUM_LEDS - 1;
|
||||
}
|
||||
gpio_ll_set_level(&GPIO, LED_PINS[index], state ? 1 : 0);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void led_init(void);
|
||||
void led_set(uint8_t index, bool state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,100 +0,0 @@
|
||||
#include "log/log.h"
|
||||
#if CONFIG_LOG_ENABLED
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
|
||||
static SemaphoreHandle_t log_mutex;
|
||||
static bool multithread = false;
|
||||
|
||||
void ogxm_log_init(bool multithreaded) {
|
||||
multithread = multithreaded;
|
||||
if (multithread) {
|
||||
log_mutex = xSemaphoreCreateMutex();
|
||||
}
|
||||
}
|
||||
|
||||
void ogxm_log_level(uint8_t level, const char* fmt, ...) {
|
||||
if (level > CONFIG_LOG_LEVEL) {
|
||||
return;
|
||||
}
|
||||
if (multithread) {
|
||||
xSemaphoreTake(log_mutex, portMAX_DELAY);
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
switch (level) {
|
||||
case 0: // Error
|
||||
fprintf(stderr, "OGXM ERROR: ");
|
||||
vfprintf(stderr, fmt, args);
|
||||
break;
|
||||
case 1: // Info
|
||||
printf("OGXM INFO: ");
|
||||
vprintf(fmt, args);
|
||||
break;
|
||||
case 2: // Debug
|
||||
printf("OGXM DEBUG: ");
|
||||
vprintf(fmt, args);
|
||||
break;
|
||||
case 3: // Verbose
|
||||
printf("OGXM VERBOSE: ");
|
||||
vprintf(fmt, args);
|
||||
break;
|
||||
}
|
||||
va_end(args);
|
||||
if (multithread) {
|
||||
xSemaphoreGive(log_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void ogxm_log_hex_level(uint8_t level, const void* data, uint16_t len, const char* fmt, ...) {
|
||||
if (level > CONFIG_LOG_LEVEL) {
|
||||
return;
|
||||
}
|
||||
if (multithread) {
|
||||
xSemaphoreTake(log_mutex, portMAX_DELAY);
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
switch (level) {
|
||||
case 0: // Error
|
||||
fprintf(stderr, "OGXM ERROR: ");
|
||||
vfprintf(stderr, fmt, args);
|
||||
break;
|
||||
case 1: // Info
|
||||
printf("OGXM INFO: ");
|
||||
vprintf(fmt, args);
|
||||
break;
|
||||
case 2: // Debug
|
||||
printf("OGXM DEBUG: ");
|
||||
vprintf(fmt, args);
|
||||
break;
|
||||
case 3: // Verbose
|
||||
printf("OGXM VERBOSE: ");
|
||||
vprintf(fmt, args);
|
||||
break;
|
||||
}
|
||||
va_end(args);
|
||||
printf("\n");
|
||||
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
if (i % 8 == 0 && i != 0) {
|
||||
printf("\n");
|
||||
}
|
||||
printf(" %02X", ((uint8_t*)data)[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (multithread) {
|
||||
xSemaphoreGive(log_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CONFIG_LOG_ENABLED
|
||||
@@ -1,42 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_LOG_ENABLED
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ogxm_log_init(bool multithreaded);
|
||||
void ogxm_log_level(uint8_t level, const char* fmt, ...);
|
||||
void ogxm_log_hex_level(uint8_t level, const void* data, uint16_t len, const char* fmt, ...);
|
||||
|
||||
#define ogxm_loge(fmt, ...) ogxm_log_level(0, fmt, ##__VA_ARGS__)
|
||||
#define ogxm_logi(fmt, ...) ogxm_log_level(1, fmt, ##__VA_ARGS__)
|
||||
#define ogxm_logd(fmt, ...) ogxm_log_level(2, fmt, ##__VA_ARGS__)
|
||||
#define ogxm_logv(fmt, ...) ogxm_log_level(3, fmt, ##__VA_ARGS__)
|
||||
#define ogxm_loge_hex(data, len, fmt, ...) ogxm_log_hex_level(0, data, len, fmt, ##__VA_ARGS__)
|
||||
#define ogxm_logi_hex(data, len, fmt, ...) ogxm_log_hex_level(1, data, len, fmt, ##__VA_ARGS__)
|
||||
#define ogxm_logd_hex(data, len, fmt, ...) ogxm_log_hex_level(2, data, len, fmt, ##__VA_ARGS__)
|
||||
#define ogxm_logv_hex(data, len, fmt, ...) ogxm_log_hex_level(3, data, len, fmt, ##__VA_ARGS__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define ogxm_log_init(...) ((void)0)
|
||||
#define ogxm_loge(fmt, ...) ((void)0)
|
||||
#define ogxm_logi(fmt, ...) ((void)0)
|
||||
#define ogxm_logd(fmt, ...) ((void)0)
|
||||
#define ogxm_logv(fmt, ...) ((void)0)
|
||||
#define ogxm_loge_hex(fmt, ...) ((void)0)
|
||||
#define ogxm_logi_hex(fmt, ...) ((void)0)
|
||||
#define ogxm_logd_hex(fmt, ...) ((void)0)
|
||||
#define ogxm_logv_hex(fmt, ...) ((void)0)
|
||||
|
||||
#endif // CONFIG_LOG_ENABLED
|
||||
@@ -1,32 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include "log/log.h"
|
||||
#include "bluetooth/bluetooth.h"
|
||||
#include "wired/wired.h"
|
||||
|
||||
void app_main(void) {
|
||||
ogxm_log_init(true);
|
||||
bluetooth_config(wired_set_connected, wired_set_pad, wired_set_audio);
|
||||
wired_config(bluetooth_set_rumble, bluetooth_set_audio);
|
||||
|
||||
xTaskCreatePinnedToCore(
|
||||
wired_task,
|
||||
"wired",
|
||||
2048U * 2U,
|
||||
NULL,
|
||||
configMAX_PRIORITIES - 6,
|
||||
NULL,
|
||||
1
|
||||
);
|
||||
|
||||
xTaskCreatePinnedToCore(
|
||||
bluetooth_task,
|
||||
"bluetooth",
|
||||
2048U * 4U,
|
||||
NULL,
|
||||
configMAX_PRIORITIES - 4,
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
}
|
||||
@@ -1,463 +0,0 @@
|
||||
#include <string.h>
|
||||
#include <esp_private/periph_ctrl.h>
|
||||
#include <esp_rom_gpio.h>
|
||||
#include <esp_clk_tree.h>
|
||||
#include <esp_intr_alloc.h>
|
||||
#include <soc/clk_tree_defs.h>
|
||||
#include <rom/lldesc.h>
|
||||
#include <hal/gpio_ll.h>
|
||||
#include <hal/i2c_ll.h>
|
||||
#include <hal/i2c_hal.h>
|
||||
#include <esp_rom_sys.h>
|
||||
#include <esp_timer.h>
|
||||
|
||||
#include "log/log.h"
|
||||
#include "periph/i2c_master.h"
|
||||
|
||||
typedef struct i2c_master_handle_ {
|
||||
bool alloc;
|
||||
int port;
|
||||
int freq_hz;
|
||||
int pin_sda;
|
||||
int pin_scl;
|
||||
bool lsb_first;
|
||||
bool pullup_en;
|
||||
int glitch_ignore_cnt;
|
||||
i2c_dev_t* dev;
|
||||
uint32_t clk_src_hz;
|
||||
volatile bool xfer_done;
|
||||
i2c_intr_event_t xfer_result;
|
||||
} i2c_master_handle_t;
|
||||
|
||||
static const uint32_t IO_MUX_REGS[40] = {
|
||||
IO_MUX_GPIO0_REG, IO_MUX_GPIO1_REG, IO_MUX_GPIO2_REG, IO_MUX_GPIO3_REG,
|
||||
IO_MUX_GPIO4_REG, IO_MUX_GPIO5_REG, IO_MUX_GPIO6_REG, IO_MUX_GPIO7_REG,
|
||||
IO_MUX_GPIO8_REG, IO_MUX_GPIO9_REG, IO_MUX_GPIO10_REG, IO_MUX_GPIO11_REG,
|
||||
IO_MUX_GPIO12_REG, IO_MUX_GPIO13_REG, IO_MUX_GPIO14_REG, IO_MUX_GPIO15_REG,
|
||||
IO_MUX_GPIO16_REG, IO_MUX_GPIO17_REG, IO_MUX_GPIO18_REG, IO_MUX_GPIO19_REG,
|
||||
IO_MUX_GPIO20_REG, IO_MUX_GPIO21_REG, IO_MUX_GPIO22_REG, IO_MUX_GPIO23_REG,
|
||||
IO_MUX_GPIO24_REG, IO_MUX_GPIO25_REG, IO_MUX_GPIO26_REG, IO_MUX_GPIO27_REG,
|
||||
0, 0, 0, 0,
|
||||
IO_MUX_GPIO32_REG, IO_MUX_GPIO33_REG, IO_MUX_GPIO34_REG, IO_MUX_GPIO35_REG,
|
||||
IO_MUX_GPIO36_REG, IO_MUX_GPIO37_REG, IO_MUX_GPIO38_REG, IO_MUX_GPIO39_REG,
|
||||
};
|
||||
|
||||
static i2c_master_handle_t i2c_handles[2] = {0};
|
||||
|
||||
static void i2c_master_config_gpio(i2c_master_handle_t* handle);
|
||||
static void i2c_master_config_bus(i2c_master_handle_t* handle);
|
||||
static void i2c_master_isr_init(i2c_master_handle_t* handle);
|
||||
void i2c_master_isr_enable(i2c_dev_t* dev, bool enable);
|
||||
void i2c_master_isr_handler(void* arg);
|
||||
static void i2c_master_clear_bus(i2c_master_handle_t* handle);
|
||||
static inline void i2c_master_cmd_start(i2c_dev_t* dev, int* cmd_idx);
|
||||
static inline void i2c_master_cmd_stop(i2c_dev_t* dev, int* cmd_idx);
|
||||
static inline void i2c_master_cmd_end(i2c_dev_t* dev, int* cmd_idx);
|
||||
static inline void i2c_master_cmd_write(i2c_dev_t* dev, int* cmd_idx, uint8_t* data, uint8_t len);
|
||||
static inline void i2c_master_cmd_read(i2c_dev_t* dev, int* cmd_idx, uint8_t len, bool last);
|
||||
static inline i2c_intr_event_t i2c_master_xfer_blocking(i2c_master_handle_t* handle, int cmd_idx, uint32_t timeout_us);
|
||||
static inline bool i2c_master_err_check(i2c_master_handle_t* handle, i2c_intr_event_t event);
|
||||
|
||||
i2c_master_handle_t* i2c_master_init(const i2c_master_cfg* cfg) {
|
||||
if (cfg == NULL) {
|
||||
ogxm_loge("I2C: Invalid config\n");
|
||||
return NULL;
|
||||
}
|
||||
if (cfg->port_num >= 2) {
|
||||
ogxm_loge("I2C: Invalid port number %d\n",
|
||||
cfg->port_num);
|
||||
return NULL;
|
||||
}
|
||||
if (i2c_handles[cfg->port_num].alloc) {
|
||||
ogxm_loge("I2C: Port %d already initialized\n",
|
||||
cfg->port_num);
|
||||
return NULL;
|
||||
}
|
||||
if ((cfg->pin_sda >= 40) ||
|
||||
(cfg->pin_scl >= 40) ||
|
||||
(IO_MUX_REGS[cfg->pin_sda] == 0) ||
|
||||
(IO_MUX_REGS[cfg->pin_scl] == 0)) {
|
||||
ogxm_loge("I2C: Invalid pin number sda=%d scl=%d\n",
|
||||
cfg->pin_sda, cfg->pin_scl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
i2c_master_handle_t* handle = &i2c_handles[cfg->port_num];
|
||||
memset(handle, 0, sizeof(i2c_master_handle_t));
|
||||
handle->alloc = true;
|
||||
handle->port = cfg->port_num;
|
||||
handle->dev = I2C_LL_GET_HW(handle->port);
|
||||
handle->freq_hz = cfg->freq_hz;
|
||||
handle->pin_sda = cfg->pin_sda;
|
||||
handle->pin_scl = cfg->pin_scl;
|
||||
handle->lsb_first = cfg->lsb_first;
|
||||
handle->pullup_en = cfg->pullup_en;
|
||||
handle->glitch_ignore_cnt = cfg->glitch_ignore_cnt;
|
||||
|
||||
i2c_master_config_gpio(handle);
|
||||
i2c_master_config_bus(handle);
|
||||
i2c_master_isr_init(handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
bool i2c_master_write_blocking(i2c_master_handle_t* handle, uint8_t addr,
|
||||
uint8_t* data, size_t len, uint32_t timeout_us) {
|
||||
if ((handle == NULL) || ((data == NULL) && (len > 0)) || !handle->alloc) {
|
||||
ogxm_loge("I2C: Invalid write params\n");
|
||||
return false;
|
||||
}
|
||||
i2c_ll_txfifo_rst(handle->dev);
|
||||
|
||||
uint8_t addr7 = (addr << 1) | 0;
|
||||
int cmd_idx = 0;
|
||||
i2c_master_cmd_start(handle->dev, &cmd_idx);
|
||||
i2c_master_cmd_write(handle->dev, &cmd_idx, &addr7, 1);
|
||||
|
||||
uint32_t offset = 0;
|
||||
uint32_t txfifo_free = 0;
|
||||
i2c_ll_get_txfifo_len(handle->dev, &txfifo_free);
|
||||
|
||||
while (len > txfifo_free) {
|
||||
i2c_master_cmd_write(handle->dev, &cmd_idx,
|
||||
data + offset, txfifo_free);
|
||||
i2c_master_cmd_end(handle->dev, &cmd_idx);
|
||||
i2c_intr_event_t result = i2c_master_xfer_blocking(handle, cmd_idx, timeout_us);
|
||||
if (!i2c_master_err_check(handle, result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
offset += txfifo_free;
|
||||
len -= txfifo_free;
|
||||
|
||||
i2c_ll_txfifo_rst(handle->dev);
|
||||
i2c_ll_get_txfifo_len(handle->dev, &txfifo_free);
|
||||
}
|
||||
|
||||
if (len) {
|
||||
i2c_master_cmd_write(handle->dev, &cmd_idx, data + offset, len);
|
||||
}
|
||||
i2c_master_cmd_stop(handle->dev, &cmd_idx);
|
||||
i2c_intr_event_t result = i2c_master_xfer_blocking(handle, cmd_idx, timeout_us);
|
||||
return i2c_master_err_check(handle, result);
|
||||
}
|
||||
|
||||
bool i2c_master_read_blocking(i2c_master_handle_t* handle, uint8_t addr,
|
||||
uint8_t* data, size_t len, uint32_t timeout_us) {
|
||||
if ((handle == NULL) || ((data == NULL) && (len > 0)) || !handle->alloc) {
|
||||
ogxm_loge("I2C: Invalid read params\n");
|
||||
return false;
|
||||
}
|
||||
i2c_ll_txfifo_rst(handle->dev);
|
||||
i2c_ll_rxfifo_rst(handle->dev);
|
||||
|
||||
uint8_t addr7 = (addr << 1) | 1;
|
||||
int cmd_idx = 0;
|
||||
|
||||
i2c_master_cmd_start(handle->dev, &cmd_idx);
|
||||
i2c_master_cmd_write(handle->dev, &cmd_idx, &addr7, 1);
|
||||
|
||||
uint32_t offset = 0;
|
||||
|
||||
while (len > SOC_I2C_FIFO_LEN) {
|
||||
i2c_master_cmd_read(handle->dev, &cmd_idx,
|
||||
SOC_I2C_FIFO_LEN, false);
|
||||
i2c_master_cmd_end(handle->dev, &cmd_idx);
|
||||
i2c_intr_event_t result = i2c_master_xfer_blocking(handle, cmd_idx, timeout_us);
|
||||
if (!i2c_master_err_check(handle, result)) {
|
||||
return false;
|
||||
}
|
||||
i2c_ll_read_rxfifo(handle->dev, data + offset, len);
|
||||
i2c_ll_rxfifo_rst(handle->dev);
|
||||
|
||||
offset += SOC_I2C_FIFO_LEN;
|
||||
len -= SOC_I2C_FIFO_LEN;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
i2c_master_cmd_read(handle->dev, &cmd_idx, len, true);
|
||||
}
|
||||
|
||||
i2c_master_cmd_stop(handle->dev, &cmd_idx);
|
||||
i2c_intr_event_t result = i2c_master_xfer_blocking(handle, cmd_idx, timeout_us);
|
||||
if (!i2c_master_err_check(handle, result)) {
|
||||
return false;
|
||||
}
|
||||
i2c_ll_read_rxfifo(handle->dev, data + offset, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
void i2c_master_deinit(i2c_master_handle_t* handle) {
|
||||
if ((handle == NULL) || !handle->alloc) {
|
||||
ogxm_loge("I2C: Invalid handle\n");
|
||||
return;
|
||||
}
|
||||
i2c_master_isr_enable(handle->dev, false);
|
||||
i2c_ll_enable_controller_clock(handle->dev, false);
|
||||
|
||||
PERIPH_RCC_ATOMIC() {
|
||||
i2c_ll_reset_register(handle->port);
|
||||
i2c_ll_enable_bus_clock(handle->port, false);
|
||||
}
|
||||
i2c_master_clear_bus(handle);
|
||||
memset(handle, 0, sizeof(i2c_master_handle_t));
|
||||
}
|
||||
|
||||
static void i2c_master_config_gpio(i2c_master_handle_t* handle) {
|
||||
gpio_ll_input_enable(&GPIO, handle->pin_sda);
|
||||
gpio_ll_input_enable(&GPIO, handle->pin_scl);
|
||||
gpio_ll_od_enable(&GPIO, handle->pin_sda);
|
||||
gpio_ll_od_enable(&GPIO, handle->pin_scl);
|
||||
|
||||
if (handle->pullup_en) {
|
||||
gpio_ll_pullup_en(&GPIO, handle->pin_sda);
|
||||
gpio_ll_pullup_en(&GPIO, handle->pin_scl);
|
||||
} else {
|
||||
gpio_ll_pullup_dis(&GPIO, handle->pin_sda);
|
||||
gpio_ll_pullup_dis(&GPIO, handle->pin_scl);
|
||||
}
|
||||
|
||||
gpio_ll_iomux_func_sel(IO_MUX_REGS[handle->pin_scl], PIN_FUNC_GPIO);
|
||||
gpio_ll_iomux_func_sel(IO_MUX_REGS[handle->pin_sda], PIN_FUNC_GPIO);
|
||||
|
||||
int ext_scl_out_idx = (handle->port == 0) ? I2CEXT0_SCL_OUT_IDX
|
||||
: I2CEXT1_SCL_OUT_IDX;
|
||||
int ext_sda_out_idx = (handle->port == 0) ? I2CEXT0_SDA_OUT_IDX
|
||||
: I2CEXT1_SDA_OUT_IDX;
|
||||
int ext_scl_in_idx = (handle->port == 0) ? I2CEXT0_SCL_IN_IDX
|
||||
: I2CEXT1_SCL_IN_IDX;
|
||||
int ext_sda_in_idx = (handle->port == 0) ? I2CEXT0_SDA_IN_IDX
|
||||
: I2CEXT1_SDA_IN_IDX;
|
||||
|
||||
esp_rom_gpio_connect_out_signal(handle->pin_scl, ext_scl_out_idx, false, false);
|
||||
esp_rom_gpio_connect_in_signal(handle->pin_scl, ext_scl_in_idx, false);
|
||||
esp_rom_gpio_connect_out_signal(handle->pin_sda, ext_sda_out_idx, false, false);
|
||||
esp_rom_gpio_connect_in_signal(handle->pin_sda, ext_sda_in_idx, false);
|
||||
}
|
||||
|
||||
static void i2c_master_config_bus(i2c_master_handle_t* handle) {
|
||||
i2c_ll_enable_controller_clock(handle->dev, true);
|
||||
|
||||
PERIPH_RCC_ATOMIC() {
|
||||
i2c_ll_enable_bus_clock(handle->port, true);
|
||||
i2c_ll_reset_register(handle->port);
|
||||
}
|
||||
|
||||
i2c_ll_master_init(handle->dev);
|
||||
i2c_ll_set_data_mode(handle->dev,
|
||||
handle->lsb_first
|
||||
? I2C_DATA_MODE_LSB_FIRST
|
||||
: I2C_DATA_MODE_MSB_FIRST,
|
||||
handle->lsb_first
|
||||
? I2C_DATA_MODE_LSB_FIRST
|
||||
: I2C_DATA_MODE_MSB_FIRST);
|
||||
i2c_ll_txfifo_rst(handle->dev);
|
||||
i2c_ll_rxfifo_rst(handle->dev);
|
||||
|
||||
soc_module_clk_t clk_src = (soc_module_clk_t)I2C_CLK_SRC_DEFAULT;
|
||||
esp_clk_tree_src_get_freq_hz(clk_src,
|
||||
ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX,
|
||||
&handle->clk_src_hz);
|
||||
|
||||
i2c_hal_clk_config_t clk_cfg;
|
||||
i2c_ll_master_cal_bus_clk(handle->clk_src_hz, handle->freq_hz, &clk_cfg);
|
||||
i2c_ll_master_set_bus_timing(handle->dev, &clk_cfg);
|
||||
i2c_ll_master_set_filter(handle->dev, handle->glitch_ignore_cnt);
|
||||
i2c_ll_set_source_clk(handle->dev, (soc_periph_i2c_clk_src_t)clk_src);
|
||||
i2c_ll_update(handle->dev);
|
||||
i2c_ll_clear_intr_mask(handle->dev, I2C_LL_MASTER_EVENT_INTR);
|
||||
}
|
||||
|
||||
static void i2c_master_isr_init(i2c_master_handle_t* handle) {
|
||||
i2c_master_isr_enable(handle->dev, false);
|
||||
i2c_ll_clear_intr_mask(handle->dev, I2C_LL_MASTER_EVENT_INTR);
|
||||
esp_intr_alloc(ETS_I2C_EXT0_INTR_SOURCE,
|
||||
ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1,
|
||||
i2c_master_isr_handler, (void*)handle, NULL);
|
||||
}
|
||||
|
||||
void IRAM_ATTR i2c_master_isr_enable(i2c_dev_t* dev, bool enable) {
|
||||
if (enable) {
|
||||
i2c_ll_enable_intr_mask(dev, I2C_LL_MASTER_EVENT_INTR);
|
||||
} else {
|
||||
i2c_ll_disable_intr_mask(dev, I2C_LL_MASTER_EVENT_INTR);
|
||||
}
|
||||
}
|
||||
|
||||
void IRAM_ATTR i2c_master_isr_handler(void* arg) {
|
||||
i2c_master_handle_t* handle = (i2c_master_handle_t*)arg;
|
||||
i2c_intr_event_t event;
|
||||
i2c_ll_master_get_event(handle->dev, &event);
|
||||
i2c_ll_clear_intr_mask(handle->dev, I2C_LL_MASTER_EVENT_INTR);
|
||||
if (!handle->xfer_done && (event != I2C_INTR_EVENT_ERR)) {
|
||||
i2c_master_isr_enable(handle->dev, false);
|
||||
handle->xfer_result = event;
|
||||
handle->xfer_done = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void i2c_master_clear_bus(i2c_master_handle_t* handle) {
|
||||
i2c_ll_master_fsm_rst(handle->dev);
|
||||
i2c_ll_txfifo_rst(handle->dev);
|
||||
i2c_ll_rxfifo_rst(handle->dev);
|
||||
i2c_ll_update(handle->dev);
|
||||
|
||||
gpio_ll_iomux_func_sel(IO_MUX_REGS[handle->pin_sda], PIN_FUNC_GPIO);
|
||||
gpio_ll_iomux_func_sel(IO_MUX_REGS[handle->pin_scl], PIN_FUNC_GPIO);
|
||||
gpio_ll_od_enable(&GPIO, handle->pin_sda);
|
||||
gpio_ll_od_enable(&GPIO, handle->pin_scl);
|
||||
gpio_ll_pullup_en(&GPIO, handle->pin_sda);
|
||||
gpio_ll_pullup_en(&GPIO, handle->pin_scl);
|
||||
|
||||
/*
|
||||
* If SDA is low it is driven by the slave, wait until SDA goes high, at
|
||||
* maximum 9 clock cycles in standard mode at 100 kHz including the ACK bit.
|
||||
*/
|
||||
uint32_t half_cycle = 5;
|
||||
int count = 9;
|
||||
|
||||
while (!gpio_ll_get_level(&GPIO, handle->pin_sda) && count--) {
|
||||
// Drive SCL low
|
||||
gpio_ll_output_enable(&GPIO, handle->pin_scl);
|
||||
gpio_ll_set_level(&GPIO, handle->pin_scl, 0);
|
||||
esp_rom_delay_us(half_cycle);
|
||||
// Drive SCL high
|
||||
gpio_ll_set_level(&GPIO, handle->pin_scl, 1);
|
||||
esp_rom_delay_us(half_cycle);
|
||||
}
|
||||
|
||||
// Generate STOP condition
|
||||
// SCL low, SDA low
|
||||
gpio_ll_set_level(&GPIO, handle->pin_scl, 0);
|
||||
esp_rom_delay_us(half_cycle);
|
||||
gpio_ll_set_level(&GPIO, handle->pin_sda, 0);
|
||||
esp_rom_delay_us(half_cycle);
|
||||
// SCL high
|
||||
gpio_ll_set_level(&GPIO, handle->pin_scl, 1);
|
||||
esp_rom_delay_us(half_cycle);
|
||||
// SDA high (STOP)
|
||||
gpio_ll_set_level(&GPIO, handle->pin_sda, 1);
|
||||
esp_rom_delay_us(half_cycle);
|
||||
}
|
||||
|
||||
static inline const char* i2c_master_evt_to_str(i2c_intr_event_t event) {
|
||||
switch (event) {
|
||||
case I2C_INTR_EVENT_ERR:
|
||||
return "I2C_INTR_EVENT_ERR";
|
||||
case I2C_INTR_EVENT_ARBIT_LOST:
|
||||
return "I2C_INTR_EVENT_ARBIT_LOST";
|
||||
case I2C_INTR_EVENT_NACK:
|
||||
return "I2C_INTR_EVENT_NACK";
|
||||
case I2C_INTR_EVENT_TOUT:
|
||||
return "I2C_INTR_EVENT_TOUT";
|
||||
case I2C_INTR_EVENT_END_DET:
|
||||
return "I2C_INTR_EVENT_END_DET";
|
||||
case I2C_INTR_EVENT_TRANS_DONE:
|
||||
return "I2C_INTR_EVENT_TRANS_DONE";
|
||||
case I2C_INTR_EVENT_RXFIFO_FULL:
|
||||
return "I2C_INTR_EVENT_RXFIFO_FULL";
|
||||
case I2C_INTR_EVENT_TXFIFO_EMPTY:
|
||||
return "I2C_INTR_EVENT_TXFIFO_EMPTY";
|
||||
default:
|
||||
return "Unknown event";
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool i2c_master_err_check(i2c_master_handle_t* handle,
|
||||
i2c_intr_event_t event) {
|
||||
if ((event != I2C_INTR_EVENT_TRANS_DONE) &&
|
||||
(event != I2C_INTR_EVENT_END_DET)) {
|
||||
ogxm_loge("I2C: Xfer failed: %s\n",
|
||||
i2c_master_evt_to_str(event));
|
||||
i2c_master_clear_bus(handle);
|
||||
i2c_master_config_gpio(handle);
|
||||
i2c_master_config_bus(handle);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void i2c_master_cmd_start(i2c_dev_t* dev, int* cmd_idx) {
|
||||
i2c_ll_hw_cmd_t cmd = {0};
|
||||
cmd.op_code = I2C_LL_CMD_RESTART;
|
||||
i2c_ll_master_write_cmd_reg(dev, cmd, *cmd_idx);
|
||||
(*cmd_idx)++;
|
||||
}
|
||||
|
||||
static inline void i2c_master_cmd_stop(i2c_dev_t* dev, int* cmd_idx) {
|
||||
i2c_ll_hw_cmd_t cmd = {0};
|
||||
cmd.op_code = I2C_LL_CMD_STOP;
|
||||
i2c_ll_master_write_cmd_reg(dev, cmd, *cmd_idx);
|
||||
(*cmd_idx)++;
|
||||
}
|
||||
|
||||
static inline void i2c_master_cmd_end(i2c_dev_t* dev, int* cmd_idx) {
|
||||
i2c_ll_hw_cmd_t cmd = {0};
|
||||
cmd.op_code = I2C_LL_CMD_END;
|
||||
i2c_ll_master_write_cmd_reg(dev, cmd, *cmd_idx);
|
||||
(*cmd_idx)++;
|
||||
}
|
||||
|
||||
static inline void i2c_master_cmd_write(i2c_dev_t* dev, int* cmd_idx,
|
||||
uint8_t* data, uint8_t len) {
|
||||
i2c_ll_write_txfifo(dev, data, len);
|
||||
i2c_ll_hw_cmd_t cmd = {
|
||||
.op_code = I2C_LL_CMD_WRITE,
|
||||
.byte_num = len,
|
||||
.ack_en = 1,
|
||||
.ack_exp = 0,
|
||||
.ack_val = 0
|
||||
};
|
||||
i2c_ll_master_write_cmd_reg(dev, cmd, *cmd_idx);
|
||||
(*cmd_idx)++;
|
||||
}
|
||||
|
||||
static inline void i2c_master_cmd_read(i2c_dev_t* dev, int* cmd_idx, uint8_t len, bool last) {
|
||||
if ((len == 0) || (len > SOC_I2C_FIFO_LEN)) {
|
||||
ogxm_loge("I2C: Invalid read length: %d\n", len);
|
||||
return;
|
||||
}
|
||||
if (len > 1) {
|
||||
i2c_ll_hw_cmd_t cmd = {
|
||||
.op_code = I2C_LL_CMD_READ,
|
||||
.byte_num = len - 1,
|
||||
.ack_en = 0,
|
||||
.ack_exp = 0,
|
||||
.ack_val = 0
|
||||
};
|
||||
i2c_ll_master_write_cmd_reg(dev, cmd, *cmd_idx);
|
||||
(*cmd_idx)++;
|
||||
}
|
||||
i2c_ll_hw_cmd_t cmd = {
|
||||
.op_code = I2C_LL_CMD_READ,
|
||||
.byte_num = 1,
|
||||
.ack_en = 1,
|
||||
.ack_exp = 0,
|
||||
.ack_val = last ? 1 : 0
|
||||
};
|
||||
i2c_ll_master_write_cmd_reg(dev, cmd, *cmd_idx);
|
||||
(*cmd_idx)++;
|
||||
}
|
||||
|
||||
static inline i2c_intr_event_t i2c_master_xfer_blocking(i2c_master_handle_t* handle,
|
||||
int cmd_idx, uint32_t timeout_us) {
|
||||
uint32_t reg_val =
|
||||
i2c_ll_calculate_timeout_us_to_reg_val(handle->clk_src_hz,
|
||||
timeout_us);
|
||||
i2c_ll_set_tout(handle->dev, reg_val);
|
||||
i2c_ll_update(handle->dev);
|
||||
handle->xfer_done = false;
|
||||
i2c_master_isr_enable(handle->dev, true);
|
||||
i2c_ll_start_trans(handle->dev);
|
||||
|
||||
uint32_t start = esp_timer_get_time();
|
||||
while (!handle->xfer_done) {
|
||||
// A timeout is written to the register, but this can get stuck anyway
|
||||
if ((esp_timer_get_time() - start) > (timeout_us + 100)) {
|
||||
i2c_master_isr_enable(handle->dev, false);
|
||||
handle->xfer_result = I2C_INTR_EVENT_TOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ogxm_logv("I2C: xfer done: %s\n", i2c_master_evt_to_str(handle->xfer_result));
|
||||
return handle->xfer_result;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct i2c_master_handle_ i2c_master_handle_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t port_num;
|
||||
uint32_t freq_hz;
|
||||
uint8_t pin_sda;
|
||||
uint8_t pin_scl;
|
||||
bool lsb_first;
|
||||
bool pullup_en;
|
||||
int glitch_ignore_cnt;
|
||||
} i2c_master_cfg;
|
||||
|
||||
i2c_master_handle_t* i2c_master_init(const i2c_master_cfg* cfg);
|
||||
bool i2c_master_write_blocking(i2c_master_handle_t* handle, uint8_t addr, uint8_t* data, size_t len, uint32_t timeout_us);
|
||||
bool i2c_master_read_blocking(i2c_master_handle_t* handle, uint8_t addr, uint8_t* data, size_t len, uint32_t timeout_us);
|
||||
void i2c_master_deinit(i2c_master_handle_t* handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,42 +0,0 @@
|
||||
#include <stddef.h>
|
||||
#include "esp_timer.h"
|
||||
#include "settings/button_combo.h"
|
||||
|
||||
#define BUTTON_COMBO(dpad, buttons) (((uint32_t)(dpad) << 16) | (buttons))
|
||||
#define BUTTON_COMBO_NONE ((uint32_t)0xFFFFFFFFU)
|
||||
|
||||
static const uint32_t BUTTON_COMBOS[USBD_TYPE_COUNT] = {
|
||||
[USBD_TYPE_XBOXOG_GP] = BUTTON_COMBO(GAMEPAD_D_RIGHT, GAMEPAD_BTN_START),
|
||||
[USBD_TYPE_XBOXOG_SB] = BUTTON_COMBO(GAMEPAD_D_RIGHT, GAMEPAD_BTN_START | GAMEPAD_BTN_RB),
|
||||
[USBD_TYPE_XBOXOG_XR] = BUTTON_COMBO(GAMEPAD_D_RIGHT, GAMEPAD_BTN_START | GAMEPAD_BTN_LB),
|
||||
[USBD_TYPE_XINPUT] = BUTTON_COMBO(GAMEPAD_D_UP, GAMEPAD_BTN_START),
|
||||
[USBD_TYPE_PS3] = BUTTON_COMBO(GAMEPAD_D_LEFT, GAMEPAD_BTN_START),
|
||||
[USBD_TYPE_PSCLASSIC] = BUTTON_COMBO(0, GAMEPAD_BTN_START | GAMEPAD_BTN_A),
|
||||
[USBD_TYPE_SWITCH] = BUTTON_COMBO(GAMEPAD_D_DOWN, GAMEPAD_BTN_START),
|
||||
// [USBD_TYPE_WEBAPP] = BUTTON_COMBO(0, GAMEPAD_BTN_START | GAMEPAD_BTN_LB | GAMEPAD_BTN_RB),
|
||||
// [USBD_TYPE_UART_BRIDGE] = BUTTON_COMBO_NONE,
|
||||
};
|
||||
|
||||
static uint32_t check_time[GAMEPADS_MAX] = { 0 };
|
||||
static uint32_t last_combo[GAMEPADS_MAX] = { BUTTON_COMBO_NONE };
|
||||
|
||||
usbd_type_t check_button_combo(uint8_t index, const gamepad_pad_t* pad) {
|
||||
if ((index >= GAMEPADS_MAX) || (pad == NULL)) {
|
||||
return USBD_TYPE_COUNT;
|
||||
}
|
||||
const uint32_t now = (uint32_t)esp_timer_get_time();
|
||||
if (BUTTON_COMBO(pad->dpad, pad->buttons) != last_combo[index]) {
|
||||
check_time[index] = now;
|
||||
last_combo[index] = BUTTON_COMBO(pad->dpad, pad->buttons);
|
||||
return USBD_TYPE_COUNT;
|
||||
}
|
||||
if ((now - check_time[index]) >= COMBO_HOLD_TIME_US) {
|
||||
check_time[index] = now;
|
||||
for (uint8_t type = 0; type < USBD_TYPE_COUNT; type++) {
|
||||
if ((BUTTON_COMBOS[type] == last_combo[index])) {
|
||||
return (usbd_type_t)type;
|
||||
}
|
||||
}
|
||||
}
|
||||
return USBD_TYPE_COUNT;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "gamepad/gamepad.h"
|
||||
#include "settings/device_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define COMBO_CHECK_INTERVAL_MS ((uint32_t)600U)
|
||||
#define COMBO_CHECK_INTERVAL_US (COMBO_CHECK_INTERVAL_MS * 1000U)
|
||||
#define COMBO_HOLD_TIME_US ((uint32_t)(3U * 1000U * 1000U))
|
||||
|
||||
usbd_type_t check_button_combo(uint8_t index, const gamepad_pad_t* pad);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
USBD_TYPE_XBOXOG_GP = 0,
|
||||
USBD_TYPE_XBOXOG_SB,
|
||||
USBD_TYPE_XBOXOG_XR,
|
||||
USBD_TYPE_XINPUT,
|
||||
USBD_TYPE_PS3,
|
||||
USBD_TYPE_PSCLASSIC,
|
||||
USBD_TYPE_SWITCH,
|
||||
// USBD_TYPE_WEBAPP,
|
||||
// USBD_TYPE_UART_BRIDGE,
|
||||
USBD_TYPE_COUNT
|
||||
} usbd_type_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,86 +0,0 @@
|
||||
#include <string.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include <nvs_flash.h>
|
||||
#include <nvs.h>
|
||||
#include <esp_err.h>
|
||||
#include "log/log.h"
|
||||
#include "settings/nvs.h"
|
||||
|
||||
static const char NVS_NAMESPACE[] = "user_data";
|
||||
static SemaphoreHandle_t nvs_mutex;
|
||||
static volatile bool nvs_inited = false;
|
||||
|
||||
void nvs_init(void) {
|
||||
nvs_mutex = xSemaphoreCreateMutex();
|
||||
xSemaphoreTake(nvs_mutex, portMAX_DELAY);
|
||||
|
||||
if (nvs_flash_init() != ESP_OK) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
}
|
||||
nvs_inited = true;
|
||||
xSemaphoreGive(nvs_mutex);
|
||||
}
|
||||
|
||||
void nvs_erase(void) {
|
||||
if (!nvs_inited) {
|
||||
return;
|
||||
}
|
||||
nvs_handle_t handle;
|
||||
xSemaphoreTake(nvs_mutex, portMAX_DELAY);
|
||||
|
||||
if (nvs_open(NVS_NAMESPACE, NVS_READWRITE, &handle) != ESP_OK) {
|
||||
xSemaphoreGive(nvs_mutex);
|
||||
return;
|
||||
}
|
||||
nvs_erase_all(handle);
|
||||
nvs_close(handle);
|
||||
xSemaphoreGive(nvs_mutex);
|
||||
}
|
||||
|
||||
bool nvs_read(const char* key, void* value, size_t len) {
|
||||
if (!nvs_inited) {
|
||||
return false;
|
||||
}
|
||||
esp_err_t err;
|
||||
nvs_handle_t handle;
|
||||
|
||||
xSemaphoreTake(nvs_mutex, portMAX_DELAY);
|
||||
|
||||
if ((err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &handle)) != ESP_OK) {
|
||||
xSemaphoreGive(nvs_mutex);
|
||||
return (err == ESP_OK);
|
||||
}
|
||||
|
||||
err = nvs_get_blob(handle, key, value, &len);
|
||||
nvs_close(handle);
|
||||
|
||||
xSemaphoreGive(nvs_mutex);
|
||||
return (err == ESP_OK);
|
||||
}
|
||||
|
||||
bool nvs_write(const char* key, const void* value, size_t len) {
|
||||
if (!nvs_inited) {
|
||||
return false;
|
||||
}
|
||||
esp_err_t err;
|
||||
nvs_handle_t handle;
|
||||
|
||||
xSemaphoreTake(nvs_mutex, portMAX_DELAY);
|
||||
|
||||
if ((err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &handle)) != ESP_OK) {
|
||||
xSemaphoreGive(nvs_mutex);
|
||||
return (err == ESP_OK);
|
||||
}
|
||||
if ((err = nvs_set_blob(handle, key, value, len)) != ESP_OK) {
|
||||
nvs_close(handle);
|
||||
xSemaphoreGive(nvs_mutex);
|
||||
return (err == ESP_OK);
|
||||
}
|
||||
err = nvs_commit(handle);
|
||||
nvs_close(handle);
|
||||
|
||||
xSemaphoreGive(nvs_mutex);
|
||||
return (err == ESP_OK);
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void nvs_init(void);
|
||||
bool nvs_read(const char* key, void* value, size_t len);
|
||||
bool nvs_write(const char* key, const void* value, size_t len);
|
||||
void nvs_erase(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,181 +0,0 @@
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include "log/log.h"
|
||||
#include "gamepad/gamepad.h"
|
||||
#include "settings/nvs.h"
|
||||
#include "settings/settings.h"
|
||||
|
||||
#define INIT_FLAG ((uint16_t)0xFFA3)
|
||||
|
||||
typedef struct __attribute__((aligned(4))) {
|
||||
volatile uint16_t init_flag;
|
||||
volatile usbd_type_t device_type;
|
||||
volatile uint32_t addons;
|
||||
volatile uint8_t active_profile_id[GAMEPADS_MAX];
|
||||
} settings_t;
|
||||
|
||||
static settings_t settings = {};
|
||||
|
||||
static inline const std::string SETTINGS_KEY() {
|
||||
return std::string("settings");
|
||||
}
|
||||
|
||||
static inline const std::string PROFILE_KEY(uint8_t id) {
|
||||
return std::string("profile_") + std::to_string(id);
|
||||
}
|
||||
|
||||
void settings_init(void) {
|
||||
if (settings.init_flag == INIT_FLAG) {
|
||||
ogxm_logd("Settings already initialized\n");
|
||||
return;
|
||||
}
|
||||
ogxm_logd("Initializing settings\n");
|
||||
|
||||
nvs_init();
|
||||
nvs_read(SETTINGS_KEY().c_str(), &settings, sizeof(settings));
|
||||
if (settings.init_flag == INIT_FLAG) {
|
||||
ogxm_logd("Settings already initialized with flag: %04X\n", settings.init_flag);
|
||||
return;
|
||||
}
|
||||
|
||||
ogxm_logd("Settings not initialized, setting default values\n");
|
||||
|
||||
settings.init_flag = INIT_FLAG;
|
||||
settings.device_type = USBD_TYPE_XBOXOG_GP;
|
||||
settings.addons = 0;
|
||||
for (uint8_t i = 0; i < GAMEPADS_MAX; i++) {
|
||||
settings.active_profile_id[i] = 1;
|
||||
}
|
||||
nvs_erase();
|
||||
|
||||
user_profile_t profile = {};
|
||||
settings_get_default_profile(&profile);
|
||||
|
||||
for (uint8_t i = 0; i < USER_PROFILES_MAX; i++) {
|
||||
profile.id = i + 1;
|
||||
nvs_write(PROFILE_KEY(i + 1).c_str(), &profile, sizeof(profile));
|
||||
}
|
||||
|
||||
nvs_write(SETTINGS_KEY().c_str(), &settings, sizeof(settings));
|
||||
|
||||
ogxm_logd("Settings initialized successfully\n");
|
||||
}
|
||||
|
||||
usbd_type_t settings_get_device_type(void) {
|
||||
return settings.device_type;
|
||||
}
|
||||
|
||||
void settings_get_profile_by_index(uint8_t index, user_profile_t* profile) {
|
||||
if ((settings.init_flag != INIT_FLAG) || (index > GAMEPADS_MAX)) {
|
||||
ogxm_logd("returning default profile\n");
|
||||
settings_get_default_profile(profile);
|
||||
return;
|
||||
}
|
||||
ogxm_logd("Getting profile by index: %d\n", index);
|
||||
nvs_read(PROFILE_KEY(settings.active_profile_id[index]).c_str(),
|
||||
profile, sizeof(user_profile_t));
|
||||
}
|
||||
|
||||
void settings_get_profile_by_id(uint8_t id, user_profile_t* profile) {
|
||||
if ((settings.init_flag != INIT_FLAG) ||
|
||||
(id > USER_PROFILES_MAX) || (id == 0)) {
|
||||
settings_get_default_profile(profile);
|
||||
return;
|
||||
}
|
||||
ogxm_logd("Getting profile by ID: %d\n", id);
|
||||
nvs_read(PROFILE_KEY(id).c_str(), profile, sizeof(user_profile_t));
|
||||
}
|
||||
|
||||
uint8_t settings_get_active_profile_id(uint8_t index) {
|
||||
if ((settings.init_flag != INIT_FLAG) || (index > GAMEPADS_MAX)) {
|
||||
return 1;
|
||||
}
|
||||
return settings.active_profile_id[index];
|
||||
}
|
||||
|
||||
void settings_store_device_type(usbd_type_t type) {
|
||||
if ((settings.init_flag != INIT_FLAG) ||
|
||||
(type >= USBD_TYPE_COUNT)) {
|
||||
return;
|
||||
}
|
||||
settings.device_type = type;
|
||||
ogxm_logd("Storing device type: %d\n", type);
|
||||
nvs_write(SETTINGS_KEY().c_str(), &settings, sizeof(settings));
|
||||
}
|
||||
|
||||
void settings_store_profile(uint8_t index, const user_profile_t* profile) {
|
||||
if ((settings.init_flag != INIT_FLAG) || (index > USER_PROFILES_MAX)) {
|
||||
return;
|
||||
}
|
||||
ogxm_logd("Storing profile, index: %d", index);
|
||||
nvs_write(PROFILE_KEY(settings.active_profile_id[index]).c_str(),
|
||||
profile, sizeof(user_profile_t));
|
||||
}
|
||||
|
||||
void settings_get_default_joystick(joystick_settings_t* joy_set) {
|
||||
joy_set->dz_inner = fix16_from_int(0);
|
||||
joy_set->dz_outer = fix16_from_int(1);
|
||||
joy_set->anti_dz_circle = fix16_from_int(0);
|
||||
joy_set->anti_dz_circle_y_scale = fix16_from_int(0);
|
||||
joy_set->anti_dz_square = fix16_from_int(0);
|
||||
joy_set->anti_dz_square_y_scale = fix16_from_int(0);
|
||||
joy_set->anti_dz_angular = fix16_from_int(0);
|
||||
joy_set->anti_dz_outer = fix16_from_int(1);
|
||||
joy_set->axis_restrict = fix16_from_int(0);
|
||||
joy_set->angle_restrict = fix16_from_int(0);
|
||||
joy_set->diag_scale_min = fix16_from_int(1);
|
||||
joy_set->diag_scale_max = fix16_from_int(1);
|
||||
joy_set->curve = fix16_from_int(1);
|
||||
joy_set->uncap_radius = 1;
|
||||
joy_set->invert_y = 0;
|
||||
joy_set->invert_x = 0;
|
||||
}
|
||||
|
||||
void settings_get_default_trigger(trigger_settings_t* trig_set) {
|
||||
trig_set->dz_inner = fix16_from_int(0);
|
||||
trig_set->dz_outer = fix16_from_int(1);
|
||||
trig_set->anti_dz_inner = fix16_from_int(0);
|
||||
trig_set->anti_dz_outer = fix16_from_int(1);
|
||||
trig_set->curve = fix16_from_int(1);
|
||||
}
|
||||
|
||||
void settings_get_default_profile(user_profile_t* profile) {
|
||||
if (profile == NULL) {
|
||||
return;
|
||||
}
|
||||
memset(profile, 0, sizeof(user_profile_t));
|
||||
settings_get_default_joystick(&profile->joystick_l);
|
||||
memcpy(&profile->joystick_r, &profile->joystick_l, sizeof(joystick_settings_t));
|
||||
settings_get_default_trigger(&profile->trigger_l);
|
||||
memcpy(&profile->trigger_r, &profile->trigger_l, sizeof(trigger_settings_t));
|
||||
|
||||
for (uint8_t i = 0; i < GAMEPAD_BTN_BIT_COUNT; i++) {
|
||||
profile->btns[i] = i;
|
||||
}
|
||||
for (uint8_t i = 0; i < GAMEPAD_DPAD_BIT_COUNT; i++) {
|
||||
profile->dpad[i] = i;
|
||||
}
|
||||
for (uint8_t i = 0; i < GAMEPAD_ANALOG_COUNT; i++) {
|
||||
profile->analog[i] = i;
|
||||
}
|
||||
profile->analog_en = 1;
|
||||
profile->id = 1;
|
||||
}
|
||||
|
||||
bool settings_is_default_joystick(const joystick_settings_t* joy_set) {
|
||||
if (joy_set == NULL) {
|
||||
return false;
|
||||
}
|
||||
joystick_settings_t default_joy = {};
|
||||
settings_get_default_joystick(&default_joy);
|
||||
return (memcmp(joy_set, &default_joy, sizeof(joystick_settings_t)) == 0);
|
||||
}
|
||||
|
||||
bool settings_is_default_trigger(const trigger_settings_t* trig_set) {
|
||||
if (trig_set == NULL) {
|
||||
return false;
|
||||
}
|
||||
trigger_settings_t default_trig = {};
|
||||
settings_get_default_trigger(&default_trig);
|
||||
return (memcmp(trig_set, &default_trig, sizeof(trigger_settings_t)) == 0);
|
||||
}
|
||||
@@ -1,388 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "libfixmath/fix16.h"
|
||||
#include "settings/device_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define USER_PROFILES_MAX 8U
|
||||
|
||||
typedef struct __attribute__((packed, aligned(4))) {
|
||||
fix16_t dz_inner;
|
||||
fix16_t dz_outer;
|
||||
|
||||
fix16_t anti_dz_inner;
|
||||
fix16_t anti_dz_outer;
|
||||
|
||||
fix16_t curve;
|
||||
} trigger_settings_t;
|
||||
_Static_assert(sizeof(trigger_settings_t) == 20, "Trigger settings size mismatch");
|
||||
_Static_assert((sizeof(trigger_settings_t) % 4) == 0, "Trigger settings size mismatch");
|
||||
|
||||
typedef struct __attribute__((packed, aligned(4))) {
|
||||
fix16_t dz_inner;
|
||||
fix16_t dz_outer;
|
||||
|
||||
fix16_t anti_dz_circle;
|
||||
fix16_t anti_dz_circle_y_scale;
|
||||
fix16_t anti_dz_square;
|
||||
fix16_t anti_dz_square_y_scale;
|
||||
fix16_t anti_dz_angular;
|
||||
fix16_t anti_dz_outer;
|
||||
|
||||
fix16_t axis_restrict;
|
||||
fix16_t angle_restrict;
|
||||
|
||||
fix16_t diag_scale_min;
|
||||
fix16_t diag_scale_max;
|
||||
|
||||
fix16_t curve;
|
||||
|
||||
uint8_t uncap_radius;
|
||||
uint8_t invert_y;
|
||||
uint8_t invert_x;
|
||||
|
||||
uint8_t reserved;
|
||||
} joystick_settings_t;
|
||||
_Static_assert(sizeof(joystick_settings_t) == 56, "Joystick settings size mismatch");
|
||||
_Static_assert((sizeof(joystick_settings_t) % 4) == 0, "Joystick settings size mismatch");
|
||||
|
||||
typedef struct __attribute__((packed, aligned(4))) {
|
||||
uint8_t id; /* Profile ID */
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint8_t d_up; /* Uint8 bit offset */
|
||||
uint8_t d_down; /* Uint8 bit offset */
|
||||
uint8_t d_left; /* Uint8 bit offset */
|
||||
uint8_t d_right; /* Uint8 bit offset */
|
||||
};
|
||||
uint8_t dpad[GAMEPAD_DPAD_BIT_COUNT]; /* Raw array of uint8 bit offsets */
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint8_t btn_a; /* Uint16 bit offset */
|
||||
uint8_t btn_b; /* Uint16 bit offset */
|
||||
uint8_t btn_x; /* Uint16 bit offset */
|
||||
uint8_t btn_y; /* Uint16 bit offset */
|
||||
uint8_t btn_l3; /* Uint16 bit offset */
|
||||
uint8_t btn_r3; /* Uint16 bit offset */
|
||||
uint8_t btn_lb; /* Uint16 bit offset */
|
||||
uint8_t btn_rb; /* Uint16 bit offset */
|
||||
uint8_t btn_lt; /* Uint16 bit offset */
|
||||
uint8_t btn_rt; /* Uint16 bit offset */
|
||||
uint8_t btn_back; /* Uint16 bit offset */
|
||||
uint8_t btn_start; /* Uint16 bit offset */
|
||||
uint8_t btn_sys; /* Uint16 bit offset */
|
||||
uint8_t btn_misc; /* Uint16 bit offset */
|
||||
};
|
||||
uint8_t btns[GAMEPAD_BTN_BIT_COUNT]; /* Raw array of uint16 bit offsets */
|
||||
};
|
||||
|
||||
uint8_t analog_en; /* Analog buttons enabled */
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint8_t a_up; /* Analog button array byte offset */
|
||||
uint8_t a_down; /* Analog button array byte offset */
|
||||
uint8_t a_left; /* Analog button array byte offset */
|
||||
uint8_t a_right; /* Analog button array byte offset */
|
||||
uint8_t a_a; /* Analog button array byte offset */
|
||||
uint8_t a_b; /* Analog button array byte offset */
|
||||
uint8_t a_x; /* Analog button array byte offset */
|
||||
uint8_t a_y; /* Analog button array byte offset */
|
||||
uint8_t a_lb; /* Analog button array byte offset */
|
||||
uint8_t a_rb; /* Analog button array byte offset */
|
||||
};
|
||||
uint8_t analog[GAMEPAD_ANALOG_COUNT]; /* Raw array of analog button array byte offsets */
|
||||
};
|
||||
|
||||
uint8_t reserved[2];
|
||||
|
||||
joystick_settings_t joystick_l;
|
||||
joystick_settings_t joystick_r;
|
||||
trigger_settings_t trigger_l;
|
||||
trigger_settings_t trigger_r;
|
||||
} user_profile_t;
|
||||
_Static_assert(sizeof(user_profile_t) == 184, "User profile size mismatch");
|
||||
_Static_assert((sizeof(user_profile_t) % 4) == 0, "User profile size mismatch");
|
||||
|
||||
typedef struct __attribute__((packed, aligned(4))) {
|
||||
float dz_inner;
|
||||
float dz_outer;
|
||||
|
||||
float anti_dz_inner;
|
||||
float anti_dz_outer;
|
||||
|
||||
float curve;
|
||||
} trigger_settings_f_t;
|
||||
// _Static_assert(sizeof(trigger_settings_t) == 20, "Trigger settings size mismatch");
|
||||
// _Static_assert((sizeof(trigger_settings_t) % 4) == 0, "Trigger settings size mismatch");
|
||||
|
||||
typedef struct __attribute__((packed, aligned(4))) {
|
||||
float dz_inner;
|
||||
float dz_outer;
|
||||
|
||||
float anti_dz_circle;
|
||||
float anti_dz_circle_y_scale;
|
||||
float anti_dz_square;
|
||||
float anti_dz_square_y_scale;
|
||||
float anti_dz_angular;
|
||||
float anti_dz_outer;
|
||||
|
||||
float axis_restrict;
|
||||
float angle_restrict;
|
||||
|
||||
float diag_scale_min;
|
||||
float diag_scale_max;
|
||||
|
||||
float curve;
|
||||
|
||||
uint8_t uncap_radius;
|
||||
uint8_t invert_y;
|
||||
uint8_t invert_x;
|
||||
|
||||
uint8_t reserved;
|
||||
} joystick_settings_f_t;
|
||||
// _Static_assert(sizeof(joystick_settings_t) == 56, "Joystick settings size mismatch");
|
||||
// _Static_assert((sizeof(joystick_settings_t) % 4) == 0, "Joystick settings size mismatch");
|
||||
|
||||
typedef struct __attribute__((packed, aligned(4))) {
|
||||
uint8_t id; /* Profile ID */
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint8_t d_up; /* Uint8 bit offset */
|
||||
uint8_t d_down; /* Uint8 bit offset */
|
||||
uint8_t d_left; /* Uint8 bit offset */
|
||||
uint8_t d_right; /* Uint8 bit offset */
|
||||
};
|
||||
uint8_t dpad[GAMEPAD_DPAD_BIT_COUNT]; /* Raw array of uint8 bit offsets */
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint8_t btn_a; /* Uint16 bit offset */
|
||||
uint8_t btn_b; /* Uint16 bit offset */
|
||||
uint8_t btn_x; /* Uint16 bit offset */
|
||||
uint8_t btn_y; /* Uint16 bit offset */
|
||||
uint8_t btn_l3; /* Uint16 bit offset */
|
||||
uint8_t btn_r3; /* Uint16 bit offset */
|
||||
uint8_t btn_lb; /* Uint16 bit offset */
|
||||
uint8_t btn_rb; /* Uint16 bit offset */
|
||||
uint8_t btn_lt; /* Uint16 bit offset */
|
||||
uint8_t btn_rt; /* Uint16 bit offset */
|
||||
uint8_t btn_back; /* Uint16 bit offset */
|
||||
uint8_t btn_start; /* Uint16 bit offset */
|
||||
uint8_t btn_sys; /* Uint16 bit offset */
|
||||
uint8_t btn_misc; /* Uint16 bit offset */
|
||||
};
|
||||
uint8_t btns[GAMEPAD_BTN_BIT_COUNT]; /* Raw array of uint16 bit offsets */
|
||||
};
|
||||
|
||||
uint8_t analog_en; /* Analog buttons enabled */
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint8_t a_up; /* Analog button array byte offset */
|
||||
uint8_t a_down; /* Analog button array byte offset */
|
||||
uint8_t a_left; /* Analog button array byte offset */
|
||||
uint8_t a_right; /* Analog button array byte offset */
|
||||
uint8_t a_a; /* Analog button array byte offset */
|
||||
uint8_t a_b; /* Analog button array byte offset */
|
||||
uint8_t a_x; /* Analog button array byte offset */
|
||||
uint8_t a_y; /* Analog button array byte offset */
|
||||
uint8_t a_lb; /* Analog button array byte offset */
|
||||
uint8_t a_rb; /* Analog button array byte offset */
|
||||
};
|
||||
uint8_t analog[GAMEPAD_ANALOG_COUNT]; /* Raw array of analog button array byte offsets */
|
||||
};
|
||||
|
||||
uint8_t reserved[2];
|
||||
|
||||
joystick_settings_f_t joystick_l;
|
||||
joystick_settings_f_t joystick_r;
|
||||
trigger_settings_f_t trigger_l;
|
||||
trigger_settings_f_t trigger_r;
|
||||
} user_profile_f_t;
|
||||
// _Static_assert(sizeof(user_profile_f_t) == 184, "User profile size mismatch");
|
||||
// _Static_assert((sizeof(user_profile_f_t) % 4) == 0, "User profile size mismatch");
|
||||
|
||||
void settings_init(void);
|
||||
usbd_type_t settings_get_device_type(void);
|
||||
void settings_get_profile_by_index(uint8_t index, user_profile_t* profile);
|
||||
void settings_get_profile_by_id(uint8_t id, user_profile_t* profile);
|
||||
uint8_t settings_get_active_profile_id(uint8_t index);
|
||||
void settings_store_device_type(usbd_type_t type);
|
||||
void settings_store_profile(uint8_t index, const user_profile_t* profile);
|
||||
|
||||
void settings_get_default_profile(user_profile_t* profile);
|
||||
bool settings_is_default_joystick(const joystick_settings_t* joy_set);
|
||||
bool settings_is_default_trigger(const trigger_settings_t* trig_set);
|
||||
|
||||
static inline void settings_scale_trigger(const trigger_settings_t* set, uint8_t* trigger) {
|
||||
|
||||
}
|
||||
|
||||
static inline void settings_scale_joysticks(const joystick_settings_t* set, int16_t* joy_x, int16_t* joy_y) {
|
||||
// #define fix16_i(x) fix16_from_int(x)
|
||||
// #define fix16_f(x) fix16_from_float(x)
|
||||
|
||||
// #define FIX_90 fix16_f(90.0f)
|
||||
// #define FIX_100 fix16_f(100.0f)
|
||||
// #define FIX_180 fix16_f(180.0f)
|
||||
// #define FIX_EPSILON fix16_f(0.0001f)
|
||||
// #define FIX_EPSILON2 fix16_f(0.001f)
|
||||
// #define FIX_ELLIPSE_DEF fix16_f(1.570796f)
|
||||
// #define FIX_DIAG_DIVISOR fix16_f(0.29289f)
|
||||
|
||||
// fix16_t x = fix16_div( set->invert_x
|
||||
// ? fix16_i(range_invert_int16(*joy_x))
|
||||
// : fix16_i(*joy_x),
|
||||
// fix16_i(R_INT16_MAX));
|
||||
// fix16_t y = fix16_div( (set->invert_y ^ invert_y)
|
||||
// ? fix16_i(range_invert_int16(*joy_y))
|
||||
// : fix16_i(*joy_y),
|
||||
// fix16_i(R_INT16_MAX));
|
||||
|
||||
// const fix16_t abs_x = fix16_abs(x);
|
||||
// const fix16_t abs_y = fix16_abs(y);
|
||||
// const fix16_t inv_axis_restrict = fix16_f(1.0f) / (fix16_f(1.0f) - set->axis_restrict);
|
||||
|
||||
// fix16_t rAngle = (abs_x < FIX_EPSILON)
|
||||
// ? FIX_90
|
||||
// : fix16_rad2deg(fix16_abs(fix16_atan(fix16_div(y, x))));
|
||||
|
||||
// fix16_t axial_x = ((abs_x <= set->axis_restrict) && (rAngle > fix16_f(45.0f)))
|
||||
// ? fix16_f(0.0f)
|
||||
// : fix16_mul((abs_x - set->axis_restrict), inv_axis_restrict);
|
||||
|
||||
// fix16_t axial_y = ((abs_y <= set->axis_restrict) && (rAngle <= fix16_f(45.0f)))
|
||||
// ? fix16_f(0.0f)
|
||||
// : fix16_mul((abs_y - set->axis_restrict), inv_axis_restrict);
|
||||
|
||||
// fix16_t in_magnitude = fix16_sqrt(fix16_sq(axial_x) + fix16_sq(axial_y));
|
||||
|
||||
// if (in_magnitude < set->dz_inner) {
|
||||
// *joy_x = 0;
|
||||
// *joy_y = 0;
|
||||
// return;
|
||||
// }
|
||||
|
||||
// fix16_t angle =
|
||||
// fix16_abs(axial_x) < FIX_EPSILON
|
||||
// ? FIX_90
|
||||
// : fix16_rad2deg(fix16_abs(fix16_atan(axial_y / axial_x)));
|
||||
|
||||
// fix16_t anti_r_scale = (set->anti_dz_square_y_scale == fix16_f(0.0f))
|
||||
// ? set->anti_dz_square : set->anti_dz_square_y_scale;
|
||||
// fix16_t anti_dz_c = set->anti_dz_circle;
|
||||
|
||||
// if ((anti_r_scale > fix16_f(0.0f)) && (anti_dz_c > fix16_f(0.0f))) {
|
||||
// fix16_t anti_ellip_scale = fix16_div(anti_ellip_scale, anti_dz_c);
|
||||
// fix16_t ellipse_angle = fix16_atan(fix16_mul(fix16_div(fix16_f(1.0f), anti_ellip_scale), fix16_tan(fix16_rad2deg(rAngle))));
|
||||
// ellipse_angle = (ellipse_angle < fix16_f(0.0f)) ? FIX_ELLIPSE_DEF : ellipse_angle;
|
||||
|
||||
// fix16_t ellipse_x = fix16_cos(ellipse_angle);
|
||||
// fix16_t ellipse_y = fix16_sqrt(fix16_mul(fix16_sq(anti_ellip_scale), (fix16_f(1.0f) - fix16_sq(ellipse_x))));
|
||||
// anti_dz_c = fix16_mul(fix16_sqrt(fix16_sq(ellipse_x) + fix16_sq(ellipse_y)), anti_dz_c);
|
||||
// }
|
||||
|
||||
// if (anti_dz_c > fix16_f(0.0f)) {
|
||||
// fix16_t a = fix16_mul(anti_dz_c, (fix16_f(1.0f) - fix16_div(set->anti_dz_circle, set->dz_outer)));
|
||||
// fix16_t b = fix16_mul(anti_dz_c, (fix16_f(1.0f) - set->anti_dz_square));
|
||||
// anti_dz_c = fix16_div(anti_dz_c, fix16_div(a, b));
|
||||
// // anti_dz_c = anti_dz_c / ((anti_dz_c * (fix16_f(1.0f) - set->anti_dz_circle / set->dz_outer)) / (anti_dz_c * (fix16_f(1.0f) - set->anti_dz_square)));
|
||||
// }
|
||||
|
||||
// if ((abs_x > set->axis_restrict) && (abs_y > set->axis_restrict)) {
|
||||
// const fix16_t FIX_ANGLE_MAX = fix16_div(set->angle_restrict, fix16_f(2.0f));
|
||||
|
||||
// if ((angle > fix16_f(0.0f)) && (angle < FIX_ANGLE_MAX)) {
|
||||
// angle = fix16_f(0.0f);
|
||||
// }
|
||||
// if (angle > (FIX_90 - FIX_ANGLE_MAX)) {
|
||||
// angle = FIX_90;
|
||||
// }
|
||||
// if (angle > FIX_ANGLE_MAX && angle < (FIX_90 - FIX_ANGLE_MAX)) {
|
||||
// angle = fix16_div(fix16_mul((angle - FIX_ANGLE_MAX), FIX_90), ((FIX_90 - FIX_ANGLE_MAX) - FIX_ANGLE_MAX));
|
||||
// }
|
||||
// }
|
||||
|
||||
// fix16_t ref_angle = (angle < FIX_EPSILON2) ? fix16_f(0.0f) : angle;
|
||||
// fix16_t diagonal = (angle > fix16_f(45.0f))
|
||||
// ? fix16_div(fix16_mul(angle - fix16_f(45.0f), (-fix16_f(45.0f))), fix16_f(45.0f)) + fix16_f(45.0f)
|
||||
// : angle;
|
||||
|
||||
// const fix16_t angle_comp = set->angle_restrict / fix16_f(2.0f);
|
||||
|
||||
// if (angle < FIX_90 && angle > fix16_f(0.0f)) {
|
||||
// angle = ((angle * ((FIX_90 - angle_comp) - angle_comp)) / FIX_90) + angle_comp;
|
||||
// }
|
||||
|
||||
// if ((axial_x < fix16_f(0.0f)) && (axial_y > fix16_f(0.0f))) {
|
||||
// angle = -angle;
|
||||
// }
|
||||
// if ((axial_x > fix16_f(0.0f)) && (axial_y < fix16_f(0.0f))) {
|
||||
// angle = angle - FIX_180;
|
||||
// }
|
||||
// if ((axial_x < fix16_f(0.0f)) && (axial_y < fix16_f(0.0f))) {
|
||||
// angle = angle + FIX_180;
|
||||
// }
|
||||
|
||||
// //Deadzone Warp
|
||||
// fix16_t out_magnitude = (in_magnitude - set->dz_inner) / (set->anti_dz_outer - set->dz_inner);
|
||||
// out_magnitude = fix16_pow(out_magnitude, (fix16_f(1.0f) / set->curve)) * (set->dz_outer - anti_dz_c) + anti_dz_c;
|
||||
// out_magnitude = (out_magnitude > set->dz_outer && !set->uncap_radius) ? set->dz_outer : out_magnitude;
|
||||
|
||||
// fix16_t d_scale = (((out_magnitude - anti_dz_c) * (set->diag_scale_max - set->diag_scale_min)) / (set->dz_outer - anti_dz_c)) + set->diag_scale_min;
|
||||
// fix16_t c_scale = (diagonal * (fix16_f(1.0f) / fix16_sqrt(fix16_f(2.0f)))) / fix16_f(45.0f); //Both these lines scale the intensity of the warping
|
||||
// c_scale = fix16_f(1.0f) - fix16_sqrt(fix16_f(1.0f) - c_scale * c_scale); //based on a circular curve to the perfect diagonal
|
||||
// d_scale = (c_scale * (d_scale - fix16_f(1.0f))) / FIX_DIAG_DIVISOR + fix16_f(1.0f);
|
||||
|
||||
// out_magnitude = out_magnitude * d_scale;
|
||||
|
||||
// //Scaling values for square antideadzone
|
||||
// fix16_t new_x = fix16_cos(fix16_deg2rad(angle)) * out_magnitude;
|
||||
// fix16_t new_y = fix16_sin(fix16_deg2rad(angle)) * out_magnitude;
|
||||
|
||||
// //Magic angle wobble fix by user ME.
|
||||
// // if (angle > 45.0 && angle < 225.0) {
|
||||
// // newX = inv(Math.sin(deg2rad(angle - 90.0)))*outputMagnitude;
|
||||
// // newY = inv(Math.cos(deg2rad(angle - 270.0)))*outputMagnitude;
|
||||
// // }
|
||||
|
||||
// //Square antideadzone scaling
|
||||
// fix16_t output_x = fix16_abs(new_x) * (fix16_f(1.0f) - fix16_div(set->anti_dz_square, set->dz_outer)) + set->anti_dz_square;
|
||||
// if (x < fix16_f(0.0f)) {
|
||||
// output_x = -output_x;
|
||||
// }
|
||||
// if (ref_angle == FIX_90) {
|
||||
// output_x = fix16_f(0.0f);
|
||||
// }
|
||||
|
||||
// fix16_t output_y = fix16_abs(new_y) * (fix16_f(1.0f) - anti_r_scale / set->dz_outer) + anti_r_scale;
|
||||
// if (y < fix16_f(0.0f)) {
|
||||
// output_y = -output_y;
|
||||
// }
|
||||
// if (ref_angle == fix16_f(0.0f)) {
|
||||
// output_y = fix16_f(0.0f);
|
||||
// }
|
||||
|
||||
// output_x = fix16_clamp(output_x, -fix16_f(1.0f), fix16_f(1.0f)) * fix16_i(R_INT16_MAX);
|
||||
// output_y = fix16_clamp(output_y, -fix16_f(1.0f), fix16_f(1.0f)) * fix16_i(R_INT16_MAX);
|
||||
|
||||
// *joy_x = (int16_t)fix16_to_int(output_x);
|
||||
// *joy_y = (int16_t)fix16_to_int(output_y);
|
||||
|
||||
// // return { static_cast<int16_t>(fix16_to_int(output_x)), static_cast<int16_t>(fix16_to_int(output_y)) };
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "gamepad/gamepad.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*wired_begin_cb_t)(void);
|
||||
typedef void (*wired_rumble_cb_t)(uint8_t index, const gamepad_rumble_t* rumble);
|
||||
typedef void (*wired_audio_cb_t)(uint8_t index, const gamepad_pcm_out_t* pcm);
|
||||
|
||||
void wired_config(wired_rumble_cb_t rumble_cb, wired_audio_cb_t audio_cb);
|
||||
void wired_task(void* args);
|
||||
void wired_set_connected(uint8_t index, bool connected);
|
||||
void wired_set_pad(uint8_t index, const gamepad_pad_t* pad, uint32_t flags);
|
||||
void wired_set_audio(uint8_t index, const gamepad_pcm_in_t* pcm) __attribute__((weak));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,144 +0,0 @@
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_I2C_ENABLED)
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <esp_private/periph_ctrl.h>
|
||||
#include <esp_rom_gpio.h>
|
||||
#include <esp_clk_tree.h>
|
||||
#include <soc/clk_tree_defs.h>
|
||||
#include <rom/lldesc.h>
|
||||
#include <hal/gpio_ll.h>
|
||||
#include <hal/i2c_ll.h>
|
||||
#include <hal/i2c_hal.h>
|
||||
#include <esp_timer.h>
|
||||
|
||||
#include "log/log.h"
|
||||
#include "periph/i2c_master.h"
|
||||
#include "wired/wired.h"
|
||||
#include "wired/wired_ring.h"
|
||||
|
||||
#define I2C_PORT 0
|
||||
#define I2C_HW I2C_LL_GET_HW(I2C_PORT)
|
||||
#define I2C_PIN_SDA 21
|
||||
#define I2C_PIN_SCL 22
|
||||
#define I2C_PIN_IRQ 3
|
||||
#define I2C_BAUD (1*1000*1000)
|
||||
#define I2C_TIMEOUT_US (10U*1000)
|
||||
#define I2C_GLITCH_IGNORE_CNT 7
|
||||
|
||||
#define SLAVE_ADDR ((uint8_t)0x40)
|
||||
|
||||
typedef struct {
|
||||
i2c_master_handle_t* handle;
|
||||
ring_wired_t ring_i2c;
|
||||
uint8_t bt_buf_tx[WIRED_MAX_SIZE] __attribute__((aligned(4))); /* Belongs to bt thread */
|
||||
uint8_t i2c_buf_tx[WIRED_MAX_SIZE] __attribute__((aligned(4))); /* Belongs to i2c thread */
|
||||
uint8_t i2c_buf_rx[WIRED_MAX_SIZE] __attribute__((aligned(4))); /* Belongs to i2c thread */
|
||||
wired_rumble_cb_t rumble_cb;
|
||||
} i2c_state_t;
|
||||
|
||||
static i2c_state_t i2c_state = {0};
|
||||
|
||||
static void parse_rx(void) {
|
||||
const wired_packet_t* packet =
|
||||
(const wired_packet_t*)i2c_state.i2c_buf_rx;
|
||||
switch (packet->report_id) {
|
||||
case WIRED_REPORT_ID_RUMBLE:
|
||||
if (i2c_state.rumble_cb != NULL) {
|
||||
i2c_state.rumble_cb(packet->index,
|
||||
(gamepad_rumble_t*)packet->payload);
|
||||
}
|
||||
ogxm_logd("I2C: Gamepad %d rumble set\n", packet->index);
|
||||
break;
|
||||
default:
|
||||
ogxm_logd_hex(packet, WIRED_MAX_SIZE,
|
||||
"I2C: Received unknown report %02X:",
|
||||
packet->report_id);
|
||||
break;
|
||||
}
|
||||
memset(i2c_state.i2c_buf_rx, 0, WIRED_MAX_SIZE);
|
||||
}
|
||||
|
||||
void wired_task(void* args) {
|
||||
(void)args;
|
||||
|
||||
i2c_master_cfg cfg = {
|
||||
.port_num = I2C_PORT,
|
||||
.freq_hz = I2C_BAUD,
|
||||
.pin_sda = I2C_PIN_SDA,
|
||||
.pin_scl = I2C_PIN_SCL,
|
||||
.lsb_first = false,
|
||||
.pullup_en = true,
|
||||
.glitch_ignore_cnt = I2C_GLITCH_IGNORE_CNT,
|
||||
};
|
||||
|
||||
i2c_master_handle_t* handle = i2c_master_init(&cfg);
|
||||
if (handle == NULL) {
|
||||
ogxm_loge("I2C: Failed to initialize I2C\n");
|
||||
while (1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
}
|
||||
|
||||
gpio_ll_func_sel(&GPIO, I2C_PIN_IRQ, FUNC_GPIO5_GPIO5);
|
||||
gpio_ll_input_enable(&GPIO, I2C_PIN_IRQ);
|
||||
gpio_ll_pullup_en(&GPIO, I2C_PIN_IRQ);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
|
||||
while (true) {
|
||||
if ((gpio_ll_get_level(&GPIO, I2C_PIN_IRQ) == 0)) {
|
||||
if (i2c_master_read_blocking(handle, SLAVE_ADDR, i2c_state.i2c_buf_rx,
|
||||
WIRED_MAX_SIZE, I2C_TIMEOUT_US)) {
|
||||
parse_rx();
|
||||
} else {
|
||||
ogxm_loge("I2C: Failed to read from slave\n");
|
||||
}
|
||||
}
|
||||
if (ring_wired_pop(&i2c_state.ring_i2c, i2c_state.i2c_buf_tx)) {
|
||||
wired_packet_t* packet = (wired_packet_t*)i2c_state.i2c_buf_tx;
|
||||
if (packet->report_id == WIRED_REPORT_ID_CONNECTED) {
|
||||
ogxm_logd("I2C: Gamepad %d connect event, connected=%d\n",
|
||||
packet->index, packet->payload[0]);
|
||||
}
|
||||
i2c_master_write_blocking(handle, SLAVE_ADDR, i2c_state.i2c_buf_tx,
|
||||
WIRED_MAX_SIZE, I2C_TIMEOUT_US);
|
||||
}
|
||||
vTaskDelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void wired_config(wired_rumble_cb_t rumble_cb, wired_audio_cb_t audio_cb) {
|
||||
(void)audio_cb;
|
||||
memset(&i2c_state, 0, sizeof(i2c_state_t));
|
||||
i2c_state.rumble_cb = rumble_cb;
|
||||
}
|
||||
|
||||
void wired_set_connected(uint8_t index, bool connected) {
|
||||
ogxm_logd("I2C: Set gamepad %d connected=%d\n", index, connected);
|
||||
wired_packet_t* packet = (wired_packet_t*)i2c_state.bt_buf_tx;
|
||||
packet->report_id = WIRED_REPORT_ID_CONNECTED;
|
||||
packet->index = index;
|
||||
packet->reserved = 0U;
|
||||
packet->payload_len = 2U;
|
||||
packet->payload[0] = connected ? 1U : 0U;
|
||||
packet->payload[1] = 0U; // Reserved
|
||||
ring_wired_push(&i2c_state.ring_i2c, i2c_state.bt_buf_tx, true);
|
||||
}
|
||||
|
||||
void wired_set_pad(uint8_t index, const gamepad_pad_t* pad, uint32_t flags) {
|
||||
wired_packet_t* packet = (wired_packet_t*)i2c_state.bt_buf_tx;
|
||||
packet->report_id = WIRED_REPORT_ID_PAD;
|
||||
packet->index = index;
|
||||
packet->reserved = 0U;
|
||||
packet->payload_len = sizeof(gamepad_pad_t);
|
||||
memcpy(packet->payload, pad, sizeof(gamepad_pad_t));
|
||||
ring_wired_push(&i2c_state.ring_i2c, i2c_state.bt_buf_tx, false);
|
||||
}
|
||||
|
||||
void wired_set_audio(uint8_t index, const gamepad_pcm_in_t* pcm) {
|
||||
(void)index;
|
||||
(void)pcm;
|
||||
}
|
||||
|
||||
#endif // CONFIG_I2C_ENABLED
|
||||
@@ -1,84 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdatomic.h>
|
||||
#include "gamepad/gamepad.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define WIRED_RING_SIZE 16U
|
||||
#if defined(CONFIG_I2C_ENABLED)
|
||||
#define WIRED_MAX_SIZE (sizeof(gamepad_pad_t) + sizeof(wired_packet_t))
|
||||
#else
|
||||
#define WIRED_MAX_SIZE (MAX(sizeof(gamepad_pad_t), sizeof(gamepad_pcm_in_t)) + sizeof(wired_packet_t))
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
WIRED_REPORT_ID_NONE = 0,
|
||||
WIRED_REPORT_ID_CONNECTED,
|
||||
WIRED_REPORT_ID_PAD,
|
||||
WIRED_REPORT_ID_RUMBLE,
|
||||
WIRED_REPORT_ID_PCM,
|
||||
} wired_report_id_t;
|
||||
|
||||
typedef struct __attribute__((packed, aligned(4))) {
|
||||
uint8_t report_id;
|
||||
uint8_t index;
|
||||
uint8_t reserved;
|
||||
uint8_t payload_len;
|
||||
uint8_t payload[];
|
||||
} wired_packet_t;
|
||||
_Static_assert(sizeof(wired_packet_t) == 4, "Wired packet size mismatch");
|
||||
|
||||
typedef struct {
|
||||
uint8_t buf[WIRED_RING_SIZE][WIRED_MAX_SIZE] __attribute__((aligned(4)));
|
||||
bool no_overwrite[WIRED_RING_SIZE];
|
||||
atomic_uint head;
|
||||
atomic_uint tail;
|
||||
} ring_wired_t;
|
||||
|
||||
static inline bool ring_wired_push(ring_wired_t* ring, const uint8_t* data, bool no_overwrite) {
|
||||
uint32_t head = atomic_load_explicit(&ring->head, memory_order_relaxed);
|
||||
uint32_t next_head = (head + 1) % WIRED_RING_SIZE;
|
||||
uint32_t tail = atomic_load_explicit(&ring->tail, memory_order_acquire);
|
||||
|
||||
if (next_head == tail) {
|
||||
if (ring->no_overwrite[tail]) {
|
||||
ogxm_loge("SPI ring buffer full, cannot push data\n");
|
||||
return false;
|
||||
}
|
||||
atomic_store_explicit(&ring->tail, (tail + 1) % WIRED_RING_SIZE, memory_order_release);
|
||||
}
|
||||
memcpy(ring->buf[head], data, WIRED_MAX_SIZE);
|
||||
ring->no_overwrite[head] = no_overwrite;
|
||||
atomic_store_explicit(&ring->head, next_head, memory_order_release);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool ring_wired_pop(ring_wired_t* ring, uint8_t* data) {
|
||||
uint32_t tail = atomic_load_explicit(&ring->tail, memory_order_relaxed);
|
||||
uint32_t head = atomic_load_explicit(&ring->head, memory_order_acquire);
|
||||
if (tail == head) {
|
||||
return false;
|
||||
}
|
||||
memcpy(data, ring->buf[tail], WIRED_MAX_SIZE);
|
||||
atomic_store_explicit(&ring->tail, (tail + 1) % WIRED_RING_SIZE, memory_order_release);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool ring_wired_empty(const ring_wired_t* ring) {
|
||||
return (atomic_load_explicit(&ring->head, memory_order_relaxed) ==
|
||||
atomic_load_explicit(&ring->tail, memory_order_acquire));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,258 +0,0 @@
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_SPI_ENABLED)
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <esp_private/periph_ctrl.h>
|
||||
#include <rom/lldesc.h>
|
||||
#include <hal/gpio_ll.h>
|
||||
#include <hal/spi_ll.h>
|
||||
#include <hal/spi_hal.h>
|
||||
|
||||
#include "log/log.h"
|
||||
#include "wired/wired.h"
|
||||
#include "wired/wired_ring.h"
|
||||
|
||||
#define SPI_DEVICE SPI2_HOST
|
||||
#define SPI_PIN_CS 15
|
||||
#define SPI_PIN_SCK 14
|
||||
#define SPI_PIN_MOSI 13
|
||||
#define SPI_PIN_MISO 12
|
||||
#define SPI_PIN_IRQ 5
|
||||
|
||||
typedef struct {
|
||||
spi_hal_context_t hal;
|
||||
spi_hal_dev_config_t hal_dev_cfg;
|
||||
int dma_channel;
|
||||
ring_wired_t ring_spi;
|
||||
uint8_t bt_buf_tx[WIRED_MAX_SIZE] __attribute__((aligned(4))); /* Belongs to bt thread */
|
||||
uint8_t* dma_buf_tx; /* Belongs to spi thread */
|
||||
uint8_t* dma_buf_rx; /* Belongs to spi thread */
|
||||
lldesc_t* dma_desc_tx;
|
||||
lldesc_t* dma_desc_rx;
|
||||
wired_rumble_cb_t rumble_cb;
|
||||
wired_audio_cb_t audio_cb;
|
||||
} spi_state_t;
|
||||
|
||||
static spi_state_t spi_state = {0};
|
||||
// static const size_t spi_state_size = sizeof(spi_state_t);
|
||||
|
||||
static void spi_init(void) {
|
||||
spi_state.dma_channel = 1;
|
||||
PERIPH_RCC_ATOMIC() {
|
||||
spi_ll_enable_bus_clock(SPI_DEVICE, true);
|
||||
spi_ll_reset_register(SPI_DEVICE);
|
||||
spi_dma_ll_enable_bus_clock(spi_state.dma_channel, true);
|
||||
spi_dma_ll_reset_register(spi_state.dma_channel);
|
||||
/* Link DMA */
|
||||
DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, spi_state.dma_channel, (SPI_DEVICE * 2));
|
||||
}
|
||||
|
||||
gpio_ll_iomux_func_sel(IO_MUX_GPIO14_REG, FUNC_MTMS_HSPICLK);
|
||||
gpio_ll_iomux_func_sel(IO_MUX_GPIO13_REG, FUNC_MTCK_HSPID);
|
||||
gpio_ll_iomux_func_sel(IO_MUX_GPIO12_REG, FUNC_MTDI_HSPIQ);
|
||||
gpio_ll_iomux_func_sel(IO_MUX_GPIO15_REG, FUNC_MTDO_HSPICS0);
|
||||
|
||||
gpio_ll_output_enable(&GPIO, SPI_PIN_SCK);
|
||||
gpio_ll_output_enable(&GPIO, SPI_PIN_MOSI);
|
||||
gpio_ll_input_enable(&GPIO, SPI_PIN_MISO);
|
||||
gpio_ll_output_enable(&GPIO, SPI_PIN_CS);
|
||||
|
||||
spi_hal_timing_param_t timing = {
|
||||
.clk_src_hz = APB_CLK_FREQ,
|
||||
.half_duplex = false,
|
||||
.no_compensate = false,
|
||||
.expected_freq = 1*1000*1000,
|
||||
.duty_cycle = 128,
|
||||
.input_delay_ns = 0,
|
||||
.use_gpio = true,
|
||||
};
|
||||
|
||||
spi_state.hal_dev_cfg.mode = 3;
|
||||
spi_state.hal_dev_cfg.cs_setup = 1;
|
||||
spi_state.hal_dev_cfg.cs_hold = 1;
|
||||
spi_state.hal_dev_cfg.cs_pin_id = -1;
|
||||
ESP_ERROR_CHECK(spi_hal_cal_clock_conf(&timing, &spi_state.hal_dev_cfg.timing_conf));
|
||||
spi_state.hal_dev_cfg.sio = 0;
|
||||
spi_state.hal_dev_cfg.half_duplex = 0;
|
||||
spi_state.hal_dev_cfg.tx_lsbfirst = 0;
|
||||
spi_state.hal_dev_cfg.rx_lsbfirst = 0;
|
||||
spi_state.hal_dev_cfg.no_compensate = 0;
|
||||
spi_state.hal_dev_cfg.as_cs = 0;
|
||||
spi_state.hal_dev_cfg.positive_cs = 0;
|
||||
|
||||
spi_hal_init(&spi_state.hal, SPI_DEVICE);
|
||||
spi_hal_setup_device(&spi_state.hal, &spi_state.hal_dev_cfg);
|
||||
spi_hal_enable_data_line(spi_state.hal.hw, true, true);
|
||||
|
||||
gpio_ll_output_enable(&GPIO, SPI_PIN_CS);
|
||||
gpio_ll_set_level(&GPIO, SPI_PIN_CS, 1);
|
||||
|
||||
gpio_ll_input_enable(&GPIO, SPI_PIN_IRQ);
|
||||
gpio_ll_pullup_en(&GPIO, SPI_PIN_IRQ);
|
||||
|
||||
spi_state.dma_buf_tx = heap_caps_malloc(WIRED_MAX_SIZE, MALLOC_CAP_DMA);
|
||||
spi_state.dma_buf_rx = heap_caps_malloc(WIRED_MAX_SIZE, MALLOC_CAP_DMA);
|
||||
spi_state.dma_desc_tx = heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA);
|
||||
spi_state.dma_desc_rx = heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA);
|
||||
if ((spi_state.dma_buf_tx == NULL) ||
|
||||
(spi_state.dma_buf_rx == NULL) ||
|
||||
(spi_state.dma_desc_rx == NULL) ||
|
||||
(spi_state.dma_desc_tx == NULL)) {
|
||||
ogxm_loge("SPI: Failed to allocate DMA buffers\n");
|
||||
abort();
|
||||
}
|
||||
memset(spi_state.dma_buf_tx, 0, WIRED_MAX_SIZE);
|
||||
memset(spi_state.dma_buf_rx, 0, WIRED_MAX_SIZE);
|
||||
memset(spi_state.dma_desc_tx, 0, sizeof(lldesc_t));
|
||||
memset(spi_state.dma_desc_rx, 0, sizeof(lldesc_t));
|
||||
|
||||
spi_state.dma_desc_rx->size = WIRED_MAX_SIZE;
|
||||
spi_state.dma_desc_rx->length = WIRED_MAX_SIZE;
|
||||
spi_state.dma_desc_rx->eof = 1;
|
||||
spi_state.dma_desc_rx->owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
spi_state.dma_desc_rx->buf = spi_state.dma_buf_rx;
|
||||
spi_state.dma_desc_rx->empty = 0;
|
||||
|
||||
spi_state.dma_desc_tx->size = WIRED_MAX_SIZE;
|
||||
spi_state.dma_desc_tx->length = WIRED_MAX_SIZE;
|
||||
spi_state.dma_desc_tx->eof = 1;
|
||||
spi_state.dma_desc_tx->owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
spi_state.dma_desc_tx->buf = spi_state.dma_buf_tx;
|
||||
spi_state.dma_desc_tx->empty = 0;
|
||||
}
|
||||
|
||||
static bool sync_slave(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void transmit_blocking(void) {
|
||||
spi_hal_trans_config_t xfer_cfg = {
|
||||
.cmd = 0,
|
||||
.cmd_bits = 0,
|
||||
.addr = 0,
|
||||
.addr_bits = 0,
|
||||
.dummy_bits = 0,
|
||||
.tx_bitlen = WIRED_MAX_SIZE * 8U,
|
||||
.rx_bitlen = WIRED_MAX_SIZE * 8U,
|
||||
.send_buffer = spi_state.dma_buf_tx,
|
||||
.rcv_buffer = spi_state.dma_buf_rx,
|
||||
.line_mode = {1,1,1},
|
||||
.cs_keep_active = false,
|
||||
};
|
||||
|
||||
ogxm_logd_hex(spi_state.dma_buf_tx, WIRED_MAX_SIZE, "SPI TX Buffer before:");
|
||||
|
||||
gpio_ll_set_level(&GPIO, SPI_PIN_CS, 0);
|
||||
|
||||
spi_hal_setup_trans(&spi_state.hal, &spi_state.hal_dev_cfg, &xfer_cfg);
|
||||
spi_hal_hw_prepare_tx(spi_state.hal.hw);
|
||||
spi_hal_hw_prepare_rx(spi_state.hal.hw);
|
||||
spi_dma_ll_rx_start(spi_state.hal.hw, spi_state.dma_channel, spi_state.dma_desc_rx);
|
||||
spi_dma_ll_tx_start(spi_state.hal.hw, spi_state.dma_channel, spi_state.dma_desc_tx);
|
||||
|
||||
spi_ll_user_start(spi_state.hal.hw);
|
||||
while (!spi_ll_usr_is_done(spi_state.hal.hw)) {
|
||||
// Wait
|
||||
}
|
||||
|
||||
gpio_ll_set_level(&GPIO, SPI_PIN_CS, 1);
|
||||
|
||||
ogxm_logd_hex(spi_state.dma_buf_tx, WIRED_MAX_SIZE, "SPI TX Buffer after:");
|
||||
}
|
||||
|
||||
static void parse_rx(void) {
|
||||
const wired_packet_t* packet =
|
||||
(const wired_packet_t*)spi_state.dma_buf_rx;
|
||||
switch (packet->report_id) {
|
||||
case WIRED_REPORT_ID_PCM:
|
||||
if (spi_state.audio_cb != NULL) {
|
||||
spi_state.audio_cb(packet->index,
|
||||
(gamepad_pcm_out_t*)packet->payload);
|
||||
}
|
||||
ogxm_logd("SPI: Gamepad %d PCM data received\n", packet->index);
|
||||
break;
|
||||
case WIRED_REPORT_ID_RUMBLE:
|
||||
if (spi_state.rumble_cb != NULL) {
|
||||
spi_state.rumble_cb(packet->index,
|
||||
(gamepad_rumble_t*)packet->payload);
|
||||
}
|
||||
ogxm_logd("SPI: Gamepad %d rumble set\n", packet->index);
|
||||
break;
|
||||
default:
|
||||
ogxm_logd_hex(packet, WIRED_MAX_SIZE,
|
||||
"SPI: Received unknown report %02X:",
|
||||
packet->report_id);
|
||||
break;
|
||||
}
|
||||
memset(spi_state.dma_buf_rx, 0, WIRED_MAX_SIZE);
|
||||
}
|
||||
|
||||
void wired_task(void* args) {
|
||||
(void)args;
|
||||
|
||||
spi_init();
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
transmit_blocking();
|
||||
|
||||
while (true) {
|
||||
if (gpio_ll_get_level(&GPIO, SPI_PIN_IRQ) == 1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
continue;
|
||||
}
|
||||
if (ring_wired_pop(&spi_state.ring_spi, spi_state.dma_buf_tx)) {
|
||||
wired_packet_t* packet = (wired_packet_t*)spi_state.dma_buf_tx;
|
||||
if (packet->report_id == WIRED_REPORT_ID_CONNECTED) {
|
||||
ogxm_logd("SPI: Gamepad %d connect event, connected=%d\n",
|
||||
packet->index, packet->payload[0]);
|
||||
}
|
||||
transmit_blocking();
|
||||
parse_rx();
|
||||
}
|
||||
else {
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
continue;
|
||||
}
|
||||
// spi_transmit_blocking();
|
||||
vTaskDelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void wired_config(wired_rumble_cb_t rumble_cb, wired_audio_cb_t audio_cb) {
|
||||
memset(&spi_state, 0, sizeof(spi_state_t));
|
||||
spi_state.rumble_cb = rumble_cb;
|
||||
spi_state.audio_cb = audio_cb;
|
||||
}
|
||||
|
||||
void wired_set_connected(uint8_t index, bool connected) {
|
||||
ogxm_logd("SPI: Set gamepad %d connected=%d\n", index, connected);
|
||||
wired_packet_t* packet = (wired_packet_t*)spi_state.bt_buf_tx;
|
||||
packet->report_id = WIRED_REPORT_ID_CONNECTED;
|
||||
packet->index = index;
|
||||
packet->reserved = 0U;
|
||||
packet->payload_len = 2U;
|
||||
packet->payload[0] = connected ? 1U : 0U;
|
||||
packet->payload[1] = 0U; // Reserved
|
||||
ring_wired_push(&spi_state.ring_spi, spi_state.bt_buf_tx, true);
|
||||
}
|
||||
|
||||
void wired_set_pad(uint8_t index, const gamepad_pad_t* pad, uint32_t flags) {
|
||||
wired_packet_t* packet = (wired_packet_t*)spi_state.bt_buf_tx;
|
||||
packet->report_id = WIRED_REPORT_ID_PAD;
|
||||
packet->index = index;
|
||||
packet->reserved = 0U;
|
||||
packet->payload_len = sizeof(gamepad_pad_t);
|
||||
memcpy(packet->payload, pad, sizeof(gamepad_pad_t));
|
||||
ring_wired_push(&spi_state.ring_spi, spi_state.bt_buf_tx, false);
|
||||
}
|
||||
|
||||
void wired_set_audio(uint8_t index, const gamepad_pcm_in_t* pcm) {
|
||||
wired_packet_t* packet = (wired_packet_t*)spi_state.bt_buf_tx;
|
||||
packet->report_id = WIRED_REPORT_ID_PCM;
|
||||
packet->index = index;
|
||||
packet->reserved = 0U;
|
||||
packet->payload_len = sizeof(gamepad_pcm_in_t);
|
||||
memcpy(packet->payload, pcm, sizeof(gamepad_pcm_in_t));
|
||||
ring_wired_push(&spi_state.ring_spi, spi_state.bt_buf_tx, false);
|
||||
}
|
||||
|
||||
#endif // CONFIG_SPI_ENABLED
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,42 +0,0 @@
|
||||
#
|
||||
# ESP32 options
|
||||
#
|
||||
CONFIG_COMPILER_OPTIMIZATION_PERF=y
|
||||
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
|
||||
CONFIG_ESP32_XTAL_FREQ_AUTO=y
|
||||
CONFIG_XTAL_FREQ_AUTO=y
|
||||
|
||||
# Bluetooh related
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BT_CONTROLLER_ONLY=y
|
||||
# Enable Dualmode (BLE and BR/EDR)
|
||||
CONFIG_BTDM_CTRL_MODE_BTDM=y
|
||||
#CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y
|
||||
# Should be, at least, one more than CONFIG_BLUEPAD32_MAX_DEVICES
|
||||
# See: https://gitlab.com/ricardoquesada/bluepad32/-/issues/11
|
||||
CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN=5
|
||||
CONFIG_BTDM_CTRL_BLE_MAX_CONN=5
|
||||
CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN=0
|
||||
CONFIG_BTDM_CTRL_AUTO_LATENCY=y
|
||||
CONFIG_BTDM_CTRL_MODEM_SLEEP=n
|
||||
|
||||
CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=y
|
||||
|
||||
#
|
||||
# FreeRTOS
|
||||
#
|
||||
# Enable FreeRTOS stats formatting functions, needed for 'tasks' console command
|
||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||
CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y
|
||||
|
||||
#
|
||||
# Bluepad32 options
|
||||
#
|
||||
CONFIG_BLUEPAD32_MAX_DEVICES=4
|
||||
CONFIG_BLUEPAD32_PLATFORM_CUSTOM=y
|
||||
|
||||
#
|
||||
# Add here other options
|
||||
#
|
||||
21
Firmware/pico/.vscode/c_cpp_properties.json
vendored
21
Firmware/pico/.vscode/c_cpp_properties.json
vendored
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Pico",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"${workspaceFolder}/build/generated/pico_base/pico/**"
|
||||
],
|
||||
"forcedInclude": [
|
||||
"${workspaceFolder}/build/generated/pico_base/pico/config_autogen.h"
|
||||
],
|
||||
"defines": [],
|
||||
"compileCommands": "${workspaceFolder}/build/compile_commands.json",
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "gnu++17",
|
||||
"intelliSenseMode": "linux-gcc-arm64",
|
||||
"configurationProvider": "ms-vscode.cmake-tools"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
9
Firmware/pico/.vscode/extensions.json
vendored
9
Firmware/pico/.vscode/extensions.json
vendored
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"ms-vscode.cpptools",
|
||||
"ms-vscode.cortex-debug",
|
||||
"ms-vscode.cmake-tools",
|
||||
"ms-vscode.python",
|
||||
"ms-vscode.vscode-serial-monitor"
|
||||
]
|
||||
}
|
||||
63
Firmware/pico/.vscode/launch.json
vendored
63
Firmware/pico/.vscode/launch.json
vendored
@@ -1,63 +0,0 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debug RP2040",
|
||||
"type": "cortex-debug",
|
||||
"request": "launch",
|
||||
"servertype": "openocd",
|
||||
"cwd": "${workspaceFolder}/build",
|
||||
"executable": "${workspaceFolder}/build/OGX-Mini.elf",
|
||||
"device": "RP2040",
|
||||
"configFiles": [
|
||||
"/usr/local/share/openocd/scripts/interface/cmsis-dap.cfg",
|
||||
"/usr/local/share/openocd/scripts/target/rp2040.cfg"
|
||||
],
|
||||
"runToEntryPoint": "main",
|
||||
"preLaunchTask": "CMake Build",
|
||||
"svdFile": "",
|
||||
"openOCDLaunchCommands": [
|
||||
// "set USE_CORE 1",
|
||||
"adapter speed 1000"
|
||||
],
|
||||
"openOCDPreConfigLaunchCommands": [],
|
||||
"postRestartCommands": [],
|
||||
"postLaunchCommands": [
|
||||
// "handle SIGINT nostop noprint pass",
|
||||
// "handle SIGTRAP nostop noprint pass"
|
||||
],
|
||||
"searchDir": [
|
||||
"/usr/local/share/openocd/scripts/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Debug RP2350",
|
||||
"type": "cortex-debug",
|
||||
"request": "launch",
|
||||
"servertype": "openocd",
|
||||
"cwd": "${workspaceFolder}/build",
|
||||
"executable": "${workspaceFolder}/build/OGX-Mini.elf",
|
||||
"device": "RP2350",
|
||||
"configFiles": [
|
||||
"/usr/local/share/openocd/scripts/interface/cmsis-dap.cfg",
|
||||
"/usr/local/share/openocd/scripts/target/rp2350.cfg"
|
||||
],
|
||||
"runToEntryPoint": "main",
|
||||
"preLaunchTask": "CMake Build",
|
||||
"svdFile": "",
|
||||
"openOCDLaunchCommands": [
|
||||
// "set USE_CORE 1",
|
||||
"adapter speed 1000"
|
||||
],
|
||||
"openOCDPreConfigLaunchCommands": [],
|
||||
"postRestartCommands": [],
|
||||
"postLaunchCommands": [
|
||||
// "handle SIGINT nostop noprint pass",
|
||||
// "handle SIGTRAP nostop noprint pass"
|
||||
],
|
||||
"searchDir": [
|
||||
"/usr/local/share/openocd/scripts/"
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
112
Firmware/pico/.vscode/settings.json
vendored
112
Firmware/pico/.vscode/settings.json
vendored
@@ -1,112 +0,0 @@
|
||||
{
|
||||
"cmake.sourceDirectory": "${workspaceFolder}",
|
||||
"cmake.buildDirectory": "${workspaceFolder}/build",
|
||||
"extensions.ignoreRecommendations": true,
|
||||
"cortex-debug.gdbPath": "/usr/bin/gdb-multiarch",
|
||||
"cortex-debug.objdumpPath": "/usr/bin/arm-none-eabi-objdump",
|
||||
"cortex-debug.nmPath": "/usr/bin/arm-none-eabi-nm",
|
||||
"cmake.configureArgs": [
|
||||
"-DOGXMINI_BOARD=DEVKIT",
|
||||
],
|
||||
"files.associations": {
|
||||
"device_private.h": "c",
|
||||
"sdkconfig.h": "c",
|
||||
"any": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"bitset": "cpp",
|
||||
"cctype": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"compare": "cpp",
|
||||
"concepts": "cpp",
|
||||
"csignal": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cuchar": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"string": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"forward_list": "cpp",
|
||||
"fstream": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"map": "cpp",
|
||||
"new": "cpp",
|
||||
"numbers": "cpp",
|
||||
"ostream": "cpp",
|
||||
"ranges": "cpp",
|
||||
"ratio": "cpp",
|
||||
"regex": "cpp",
|
||||
"set": "cpp",
|
||||
"span": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"valarray": "cpp",
|
||||
"variant": "cpp",
|
||||
"stdlib.h": "c",
|
||||
"stdio_uart.h": "c",
|
||||
"tuh_xaudio.h": "c",
|
||||
"gamepad.h": "c",
|
||||
"usbd.h": "c",
|
||||
"log.h": "c",
|
||||
"button_combo.h": "c",
|
||||
"timer.h": "c",
|
||||
"*.in": "cpp",
|
||||
"bluetooth.h": "c",
|
||||
"i2c.h": "c",
|
||||
"ring.h": "c",
|
||||
"stdint.h": "c",
|
||||
"device.h": "c",
|
||||
"string.h": "c",
|
||||
"watchdog.h": "c",
|
||||
"settings.h": "c",
|
||||
"master.h": "c",
|
||||
"i2c_slave.h": "c",
|
||||
"callbacks.h": "c",
|
||||
"gpio.h": "c",
|
||||
"sync.h": "c",
|
||||
"lwip_nosys.h": "c",
|
||||
"lwip_freertos.h": "c",
|
||||
"dhserver.h": "c",
|
||||
"debug.h": "c",
|
||||
"httpd.h": "c",
|
||||
"etharp.h": "c",
|
||||
"unique_id.h": "c",
|
||||
"net_device.h": "c",
|
||||
"ethernet.h": "c",
|
||||
"rndis_def.h": "c"
|
||||
},
|
||||
"idf.port": "/dev/ttyUSB0",
|
||||
}
|
||||
15
Firmware/pico/.vscode/tasks.json
vendored
15
Firmware/pico/.vscode/tasks.json
vendored
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "CMake Conifgure",
|
||||
"type": "process",
|
||||
"command": "${command:cmake.configure}",
|
||||
},
|
||||
{
|
||||
"label": "CMake Build",
|
||||
"type": "shell",
|
||||
"command": "${command:cmake.build}",
|
||||
},
|
||||
]
|
||||
}
|
||||
55
Firmware/pico/.vscode/win_launch.json
vendored
55
Firmware/pico/.vscode/win_launch.json
vendored
@@ -1,55 +0,0 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Pico RP2040 Debug",
|
||||
"cwd": "${workspaceFolder}/debug_win/scripts",
|
||||
"executable": "${command:cmake.launchTargetPath}",
|
||||
"request": "launch",
|
||||
"type": "cortex-debug",
|
||||
"servertype": "openocd",
|
||||
"serverpath": "${workspaceFolder}/debug_win/openocd.exe",
|
||||
"gdbPath": "arm-none-eabi-gdb",
|
||||
"device": "RP2040",
|
||||
"configFiles": [
|
||||
"${workspaceFolder}/debug_win/scripts/interface/cmsis-dap.cfg",
|
||||
"${workspaceFolder}/debug_win/scripts/target/rp2040.cfg"
|
||||
],
|
||||
"svdFile": "${workspaceFolder}/external/pico-sdk/src/rp2040/hardware_regs/RP2040.svd",
|
||||
"runToEntryPoint": "main",
|
||||
"preLaunchTask": "Compile Project",
|
||||
"overrideLaunchCommands": [
|
||||
"monitor reset init",
|
||||
"load ../../build/ogx-mini.elf"
|
||||
],
|
||||
"openOCDLaunchCommands": [
|
||||
"adapter speed 5000"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Pico RP2350 Debug",
|
||||
"cwd": "${workspaceFolder}/debug_win/scripts",
|
||||
"executable": "${command:cmake.launchTargetPath}",
|
||||
"request": "launch",
|
||||
"type": "cortex-debug",
|
||||
"servertype": "openocd",
|
||||
"serverpath": "${workspaceFolder}/debug_win/openocd.exe",
|
||||
"gdbPath": "arm-none-eabi-gdb",
|
||||
"device": "RP2350",
|
||||
"configFiles": [
|
||||
"${workspaceFolder}/debug_win/scripts/interface/cmsis-dap.cfg",
|
||||
"${workspaceFolder}/debug_win/scripts/target/rp2350.cfg"
|
||||
],
|
||||
"svdFile": "${workspaceFolder}/external/pico-sdk/src/rp2350/hardware_regs/RP2350.svd",
|
||||
"runToEntryPoint": "main",
|
||||
"preLaunchTask": "Compile Project",
|
||||
"overrideLaunchCommands": [
|
||||
"monitor reset init",
|
||||
"load ../../build/ogx-mini.elf"
|
||||
],
|
||||
"openOCDLaunchCommands": [
|
||||
"adapter speed 5000"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
set(FW_NAME "OGX-Mini")
|
||||
set(FW_VERSION "1.0.0a4")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
set(SRC ${CMAKE_CURRENT_LIST_DIR}/src)
|
||||
set(EXTERNAL_DIR ${CMAKE_CURRENT_LIST_DIR}/external)
|
||||
|
||||
if(NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/boards/${OGXMINI_BOARD}.cmake)
|
||||
message(FATAL_ERROR "Board configuration file for '${OGXMINI_BOARD}' not found.")
|
||||
endif()
|
||||
|
||||
string(TIMESTAMP CURRENT_DATETIME "%Y-%m-%d %H:%M:%S")
|
||||
set(BUILD_DATETIME "\"${CURRENT_DATETIME}\"")
|
||||
set(BUILD_VERSION "\"${FW_VERSION}\"")
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/boards/init.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/boards/${OGXMINI_BOARD}.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/pico_sdk_import.cmake)
|
||||
include($ENV{PICO_SDK_PATH}/pico_sdk_init.cmake)
|
||||
|
||||
set(PICO_PIO_USB_PATH ${EXTERNAL_DIR}/Pico-PIO-USB)
|
||||
set(PICO_TINYUSB_PATH ${EXTERNAL_DIR}/tinyusb)
|
||||
set(BLUEPAD32_PATH ${EXTERNAL_DIR}/bluepad32)
|
||||
set(PICO_BTSTACK_PATH ${EXTERNAL_DIR}/bluepad32/external/btstack)
|
||||
set(LWIP_DIR ${EXTERNAL_DIR}/lwip)
|
||||
|
||||
set(LWIP_INCLUDE_DIRS
|
||||
${LWIP_DIR}/src/include
|
||||
${SRC}/webserver/lwip
|
||||
)
|
||||
|
||||
project(${FW_NAME} C CXX ASM)
|
||||
|
||||
pico_sdk_init()
|
||||
|
||||
add_subdirectory(${EXTERNAL_DIR}/pico_usb)
|
||||
add_subdirectory(${EXTERNAL_DIR}/libxsm3)
|
||||
add_subdirectory(${EXTERNAL_DIR}/g726)
|
||||
add_subdirectory(${EXTERNAL_DIR}/libfixmath libfixmath)
|
||||
add_subdirectory(${EXTERNAL_DIR}/fatfs)
|
||||
include(${LWIP_DIR}/src/Filelists.cmake)
|
||||
|
||||
add_executable(${FW_NAME}
|
||||
${SRC}/main_standard.c
|
||||
${SRC}/main_bluetooth.c
|
||||
${SRC}/main_bluetooth_usbh.c
|
||||
${SRC}/main_four_channel.c
|
||||
${SRC}/main_devkit.c
|
||||
${SRC}/main_devkit_esp32.c
|
||||
${SRC}/shared.c
|
||||
|
||||
${SRC}/log/log.c
|
||||
|
||||
${SRC}/settings/nvs.c
|
||||
${SRC}/settings/settings.cpp
|
||||
|
||||
${SRC}/sdcard/sdcard.c
|
||||
${SRC}/sdcard/sd_spi.c
|
||||
${SRC}/sdcard/fatfs_io.c
|
||||
|
||||
${SRC}/led/led.cpp
|
||||
${SRC}/led/neopixel/WS2812.cpp
|
||||
|
||||
${SRC}/usb/device/device.c
|
||||
${SRC}/usb/device/drivers/ps3.c
|
||||
${SRC}/usb/device/drivers/xboxog_hub.c
|
||||
${SRC}/usb/device/drivers/xboxog_gp.c
|
||||
${SRC}/usb/device/drivers/xboxog_sb.c
|
||||
${SRC}/usb/device/drivers/xboxog_xblc.c
|
||||
${SRC}/usb/device/drivers/msc.c
|
||||
${SRC}/usb/device/drivers/xinput.c
|
||||
${SRC}/usb/device/drivers/generic_hub.c
|
||||
${SRC}/usb/device/drivers/dinput.c
|
||||
${SRC}/usb/device/drivers/switch.c
|
||||
${SRC}/usb/device/drivers/psclassic.c
|
||||
${SRC}/usb/device/drivers/uart_bridge.c
|
||||
${SRC}/usb/device/drivers/webapp.c
|
||||
${SRC}/usb/device/drivers/net.c
|
||||
${SRC}/usb/device/drivers/rndis/rndis.c
|
||||
|
||||
${SRC}/usb/host/host.c
|
||||
${SRC}/usb/host/drivers/xboxog_gp.c
|
||||
${SRC}/usb/host/drivers/xinput_wl.c
|
||||
${SRC}/usb/host/drivers/xinput.c
|
||||
${SRC}/usb/host/drivers/xgip_gp.c
|
||||
${SRC}/usb/host/drivers/ps3.c
|
||||
${SRC}/usb/host/drivers/ps4.c
|
||||
${SRC}/usb/host/drivers/ps5.c
|
||||
${SRC}/usb/host/drivers/switch_pro.c
|
||||
${SRC}/usb/host/drivers/hid/hid.c
|
||||
${SRC}/usb/host/drivers/hid/dinput.c
|
||||
${SRC}/usb/host/drivers/hid/psclassic.c
|
||||
${SRC}/usb/host/drivers/hid/switch.c
|
||||
${SRC}/usb/host/drivers/hid/n64.c
|
||||
${SRC}/usb/host/drivers/hid/generic.c
|
||||
${SRC}/usb/host/tusb_host/tuh_hxx.cpp
|
||||
${SRC}/usb/host/tusb_host/tuh_xaudio.c
|
||||
|
||||
${SRC}/bluetooth/picow/picow.c
|
||||
${SRC}/bluetooth/picow/ble_server.c
|
||||
${SRC}/bluetooth/esp32/esp32_i2c.c
|
||||
${SRC}/bluetooth/esp32/esp32_spi.c
|
||||
|
||||
${SRC}/four_channel/master.c
|
||||
${SRC}/four_channel/slave.c
|
||||
|
||||
${SRC}/webserver/webserver.c
|
||||
${SRC}/webserver/lwip/sys.c
|
||||
${SRC}/webserver/networking/dhserver.c
|
||||
${SRC}/webserver/networking/dnserver.c
|
||||
# ${SRC}/webserver/networking/rndis_reports.c
|
||||
)
|
||||
|
||||
target_include_directories(${FW_NAME}
|
||||
PRIVATE
|
||||
${SRC}
|
||||
${SRC}/webserver/networking/
|
||||
${LWIP_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(${FW_NAME}
|
||||
PUBLIC
|
||||
pico_stdlib
|
||||
pico_multicore
|
||||
pico_rand
|
||||
pico_i2c_slave
|
||||
# pico_lwip
|
||||
# pico_lwip_arch
|
||||
hardware_pio
|
||||
hardware_sync
|
||||
hardware_gpio
|
||||
hardware_i2c
|
||||
hardware_spi
|
||||
hardware_flash
|
||||
hardware_dma
|
||||
|
||||
pico_usb
|
||||
libxsm3
|
||||
g726
|
||||
libfixmath
|
||||
fatfs
|
||||
tinyusb_board
|
||||
tinyusb_host
|
||||
tinyusb_pico_pio_usb
|
||||
|
||||
lwipcore
|
||||
lwipallapps
|
||||
)
|
||||
|
||||
target_compile_definitions(${FW_NAME}
|
||||
PUBLIC
|
||||
PICO_DEFAULT_UART=${PICO_DEFAULT_UART}
|
||||
PICO_DEFAULT_UART_TX_PIN=${PICO_DEFAULT_UART_TX_PIN}
|
||||
PICO_DEFAULT_UART_RX_PIN=${PICO_DEFAULT_UART_RX_PIN}
|
||||
PICO_FLASH_SIZE_BYTES=${PICO_FLASH_SIZE_BYTES}
|
||||
# PICO_HEAP_SIZE=4096
|
||||
# PICO_STACK_SIZE=4096
|
||||
)
|
||||
|
||||
target_compile_options(${FW_NAME}
|
||||
PUBLIC
|
||||
$<$<CONFIG:Debug>:-O2 -g3 -Wuninitialized -Wall -Wno-unused -Werror>
|
||||
$<$<CONFIG:Release>:-O3 -g0 -DNDEBUG -mthumb -ffunction-sections -fdata-sections -fomit-frame-pointer -finline-functions>
|
||||
)
|
||||
|
||||
# pico_enable_stdio_uart(${FW_NAME} 0)
|
||||
|
||||
target_link_options(${FW_NAME}
|
||||
PUBLIC
|
||||
$<$<CONFIG:Release>:-Wl,--gc-sections -flto>
|
||||
)
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(OGXM_LOG_ENABLED 1)
|
||||
set(OGXM_LOG_LEVEL 3)
|
||||
endif()
|
||||
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_LIST_DIR}/board_config.h.in
|
||||
${SRC}/board_config.h
|
||||
@ONLY
|
||||
)
|
||||
|
||||
if(PICO_BOARD STREQUAL pico_w OR PICO_BOARD STREQUAL pico2_w)
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
message(FATAL_ERROR "Pico W does not support Debug build type due to CYW43 driver limitations.")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND git apply --ignore-whitespace ${BLUEPAD32_PATH}/../btstack_l2cap.diff
|
||||
WORKING_DIRECTORY ${PICO_BTSTACK_PATH}
|
||||
RESULT_VARIABLE result
|
||||
ERROR_VARIABLE error
|
||||
)
|
||||
|
||||
include_directories(${PICO_BTSTACK_PATH}/3rd-party/bluedroid/encoder/include)
|
||||
include_directories(${PICO_BTSTACK_PATH}/3rd-party/bluedroid/decoder/include)
|
||||
include_directories(${BLUEPAD32_PATH}/src/components/bluepad32/include)
|
||||
include_directories(bluepad32 ${SRC}/bluetooth/picow)
|
||||
target_include_directories(pico_btstack_classic INTERFACE ${SRC}/bluetooth/picow)
|
||||
|
||||
target_link_libraries(${FW_NAME}
|
||||
PUBLIC
|
||||
pico_cyw43_arch_none
|
||||
pico_btstack_classic
|
||||
pico_btstack_cyw43
|
||||
bluepad32
|
||||
)
|
||||
|
||||
add_subdirectory(${BLUEPAD32_PATH}/src/components/bluepad32 libbluepad32)
|
||||
|
||||
target_compile_definitions(bluepad32
|
||||
PUBLIC
|
||||
GAMEPADS_MAX=${GAMEPADS_MAX}
|
||||
)
|
||||
|
||||
target_include_directories(bluepad32
|
||||
PUBLIC
|
||||
${SRC}/bluetooth/picow
|
||||
)
|
||||
endif()
|
||||
|
||||
if(GAMEPADS_MAX LESS 1 OR GAMEPADS_MAX GREATER 4)
|
||||
message(FATAL_ERROR "GAMEPADS_MAX must be 1 to 4")
|
||||
elseif(GAMEPADS_MAX EQUAL 1)
|
||||
target_compile_definitions(pico_usb PUBLIC
|
||||
USBD_DEVICES_MAX=1
|
||||
)
|
||||
else()
|
||||
target_compile_definitions(pico_usb PUBLIC
|
||||
USBD_DEVICES_MAX=${GAMEPADS_MAX}+1
|
||||
)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(libfixmath PRIVATE
|
||||
FIXMATH_FAST_SIN
|
||||
FIXMATH_NO_64BIT
|
||||
FIXMATH_NO_CACHE
|
||||
FIXMATH_NO_HARD_DIVISION
|
||||
FIXMATH_NO_OVERFLOW
|
||||
# FIXMATH_NO_ROUNDING
|
||||
# FIXMATH_OPTIMIZE_8BIT
|
||||
)
|
||||
|
||||
target_include_directories(tinyusb_host
|
||||
INTERFACE
|
||||
${SRC}/usb/host/tusb_host
|
||||
)
|
||||
|
||||
target_compile_definitions(tinyusb_host
|
||||
INTERFACE
|
||||
$<$<CONFIG:Release>:CFG_TUSB_DEBUG=0>
|
||||
# $<$<CONFIG:Debug>:CFG_TUSB_DEBUG=1>
|
||||
# $<$<CONFIG:Debug>:CFG_TUH_LOG_LEVEL=1>
|
||||
)
|
||||
|
||||
# target_compile_definitions(pico_usb
|
||||
# PUBLIC
|
||||
# $<$<CONFIG:Debug>:USB_LOG_ENABLE=1>
|
||||
# $<$<CONFIG:Debug>:USB_LOG_LEVEL=2>
|
||||
# )
|
||||
|
||||
pico_generate_pio_header(${FW_NAME} ${SRC}/led/neopixel/WS2812.pio)
|
||||
|
||||
# set_target_properties(${FW_NAME}
|
||||
# PROPERTIES
|
||||
# OUTPUT_NAME "${FW_NAME}-${FW_VERSION}-${OGXMINI_BOARD}"
|
||||
# )
|
||||
|
||||
pico_add_extra_outputs(${FW_NAME})
|
||||
@@ -1,90 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define BUILD_DATETIME @BUILD_DATETIME@
|
||||
#define BUILD_VERSION @BUILD_VERSION@
|
||||
#define VERIFY_BUILD_VERSION @VERIFY_BUILD_VERSION@
|
||||
#define OGXM_LOG_ENABLED @OGXM_LOG_ENABLED@
|
||||
#define OGXM_LOG_LEVEL @OGXM_LOG_LEVEL@
|
||||
|
||||
#define GAMEPADS_MAX @GAMEPADS_MAX@
|
||||
|
||||
#define LED_ENABLED @LED_ENABLED@
|
||||
#define LED_PIN @LED_PIN@
|
||||
|
||||
#define NEOPIXEL_ENABLED @NEOPIXEL_ENABLED@
|
||||
#define NEOPIXEL_FORMAT_RGB @NEOPIXEL_FORMAT_RGB@
|
||||
#define NEOPIXEL_FORMAT_GRB @NEOPIXEL_FORMAT_GRB@
|
||||
#define NEOPIXEL_FORMAT_WRGB @NEOPIXEL_FORMAT_WRGB@
|
||||
#define NEOPIXEL_FORMAT @NEOPIXEL_FORMAT@
|
||||
#define NEOPIXEL_DATA_PIN @NEOPIXEL_DATA_PIN@
|
||||
#define NEOPIXEL_VCC_ENABLED @NEOPIXEL_VCC_ENABLED@
|
||||
#define NEOPIXEL_VCC_ENABLE_PIN @NEOPIXEL_POWER_PIN@
|
||||
|
||||
#define UART_BRIDGE_ENABLED @UART_BRIDGE_ENABLED@
|
||||
#define UART_BRIDGE_UART_NUM @UART_BRIDGE_UART_NUM@
|
||||
#define UART_BRIDGE_PIN_TX @UART_BRIDGE_PIN_TX@
|
||||
#define UART_BRIDGE_PIN_RX @UART_BRIDGE_PIN_RX@
|
||||
#define UART_BRIDGE_PIN_BOOT @UART_BRIDGE_PIN_BOOT@
|
||||
#define UART_BRIDGE_PIN_RESET @UART_BRIDGE_PIN_RESET@
|
||||
|
||||
#define USBH_ENABLED @USBH_ENABLED@
|
||||
#define USBH_PIO_ENABLED @USBH_PIO_ENABLED@
|
||||
#define USBH_PIO_DP_PIN @USBH_PIO_DP_PIN@
|
||||
#define USBH_VCC_ENABLED @USBH_VCC_ENABLED@
|
||||
#define USBH_VCC_ENABLE_PIN @USBH_VCC_ENABLE_PIN@
|
||||
|
||||
#define USBD_PIO_ENABLED @USBD_PIO_ENABLED@
|
||||
#define USBD_PIO_USB_DP_PIN @USBD_PIO_USB_DP_PIN@
|
||||
|
||||
#define TS3USB221_ENABLED @TS3USB221_ENABLED@
|
||||
#define TS3USB221_PIN_MUX_OE @TS3USB221_PIN_MUX_OE@
|
||||
#define TS3USB221_PIN_MUX_SEL @TS3USB221_PIN_MUX_SEL@
|
||||
|
||||
#define BLUETOOTH_ENABLED @BLUETOOTH_ENABLED@
|
||||
#define BLUETOOTH_HARDWARE_PICOW @BLUETOOTH_HARDWARE_PICOW@
|
||||
#define BLUETOOTH_HARDWARE_ESP32_I2C @BLUETOOTH_HARDWARE_ESP32_I2C@
|
||||
#define BLUETOOTH_HARDWARE_ESP32_SPI @BLUETOOTH_HARDWARE_ESP32_SPI@
|
||||
#define BLUETOOTH_HARDWARE @BLUETOOTH_HARDWARE@
|
||||
|
||||
#define ESP32_I2C_NUM @ESP32_I2C_NUM@
|
||||
#define ESP32_I2C_PIN_SDA @ESP32_I2C_PIN_SDA@
|
||||
#define ESP32_I2C_PIN_SCL @ESP32_I2C_PIN_SCL@
|
||||
#define ESP32_I2C_PIN_IRQ @ESP32_I2C_PIN_IRQ@
|
||||
|
||||
#define ESP32_SPI_NUM @ESP32_SPI_NUM@
|
||||
#define ESP32_SPI_PIN_MOSI @ESP32_SPI_PIN_MOSI@
|
||||
#define ESP32_SPI_PIN_MISO @ESP32_SPI_PIN_MISO@
|
||||
#define ESP32_SPI_PIN_SCK @ESP32_SPI_PIN_SCK@
|
||||
#define ESP32_SPI_PIN_CS @ESP32_SPI_PIN_CS@
|
||||
#define ESP32_SPI_PIN_IRQ @ESP32_SPI_PIN_IRQ@
|
||||
|
||||
#define ESP32_RESET_PIN UART_BRIDGE_PIN_RESET
|
||||
|
||||
#define FOUR_CHANNEL_I2C_NUM @FOUR_CHANNEL_I2C_NUM@
|
||||
#define FOUR_CHANNEL_I2C_PIN_SDA @FOUR_CHANNEL_I2C_PIN_SDA@
|
||||
#define FOUR_CHANNEL_I2C_PIN_SCL @FOUR_CHANNEL_I2C_PIN_SCL@
|
||||
#define FOUR_CHANNEL_I2C_PIN_IRQ_1 @FOUR_CHANNEL_I2C_PIN_IRQ_1@
|
||||
#define FOUR_CHANNEL_I2C_PIN_IRQ_2 @FOUR_CHANNEL_I2C_PIN_IRQ_2@
|
||||
#define FOUR_CHANNEL_I2C_PIN_IRQ_3 @FOUR_CHANNEL_I2C_PIN_IRQ_3@
|
||||
#define FOUR_CHANNEL_PIN_SLAVE_1 @FOUR_CHANNEL_PIN_SLAVE_1@
|
||||
#define FOUR_CHANNEL_PIN_SLAVE_2 @FOUR_CHANNEL_PIN_SLAVE_2@
|
||||
|
||||
#define SD_CARD_ENABLED @SD_CARD_ENABLED@
|
||||
#define SD_CARD_SPI_NUM @SD_CARD_SPI_NUM@
|
||||
#define SD_CARD_SPI_PIN_SCK @SD_CARD_SPI_PIN_SCK@
|
||||
#define SD_CARD_SPI_PIN_MOSI @SD_CARD_SPI_PIN_MOSI@
|
||||
#define SD_CARD_SPI_PIN_MISO @SD_CARD_SPI_PIN_MISO@
|
||||
#define SD_CARD_SPI_PIN_CS @SD_CARD_SPI_PIN_CS@
|
||||
|
||||
#define OGXM_BOARD_STANDARD @OGXM_BOARD_STANDARD@
|
||||
#define OGXM_BOARD_BLUETOOTH @OGXM_BOARD_BLUETOOTH@
|
||||
#define OGXM_BOARD_DEVKIT @OGXM_BOARD_DEVKIT@
|
||||
#define OGXM_BOARD_DEVKIT_ESP32 @OGXM_BOARD_DEVKIT_ESP32@
|
||||
#define OGXM_BOARD_4CHANNEL @OGXM_BOARD_4CHANNEL@
|
||||
#define OGXM_BOARD_BLUETOOTH_USBH @OGXM_BOARD_BLUETOOTH_USBH@
|
||||
#define OGXM_BOARD @OGXM_BOARD@
|
||||
|
||||
#if (((OGXM_BOARD != OGXM_BOARD_DEVKIT) && (OGXM_BOARD != OGXM_BOARD_DEVKIT_ESP32)) \
|
||||
&& USBH_PIO_ENABLED && USBD_PIO_ENABLED)
|
||||
#error "USB Host and Device PIO cannot be enabled at the same time"
|
||||
#endif
|
||||
@@ -1,19 +0,0 @@
|
||||
set(NEOPIXEL_ENABLED 1)
|
||||
set(NEOPIXEL_FORMAT NEOPIXEL_FORMAT_GRB)
|
||||
set(NEOPIXEL_DATA_PIN 21)
|
||||
set(NEOPIXEL_VCC_ENABLED 1)
|
||||
set(NEOPIXEL_VCC_ENABLE_PIN 20)
|
||||
|
||||
set(USBH_ENABLED 1)
|
||||
set(USBH_PIO_ENABLED 1)
|
||||
set(USBH_PIO_DP_PIN 0)
|
||||
set(USBH_VCC_ENABLED 1)
|
||||
set(USBH_VCC_ENABLE_PIN 18)
|
||||
|
||||
set(OGXM_BOARD OGXM_BOARD_STANDARD)
|
||||
|
||||
set(PICO_DEFAULT_UART 1)
|
||||
set(PICO_DEFAULT_UART_TX_PIN 4)
|
||||
set(PICO_DEFAULT_UART_RX_PIN 5)
|
||||
|
||||
set(PICO_BOARD adafruit_feather_rp2040_usb_host)
|
||||
@@ -1,41 +0,0 @@
|
||||
set(LED_ENABLED 1)
|
||||
set(LED_PIN 25)
|
||||
|
||||
set(UART_BRIDGE_ENABLED 1)
|
||||
set(UART_BRIDGE_UART_NUM 1)
|
||||
set(UART_BRIDGE_PIN_TX 8)
|
||||
set(UART_BRIDGE_PIN_RX 9)
|
||||
set(UART_BRIDGE_PIN_BOOT 22)
|
||||
set(UART_BRIDGE_PIN_RESET 6)
|
||||
|
||||
set(USBH_ENABLED 1)
|
||||
set(USBH_PIO_ENABLED 1)
|
||||
set(USBH_PIO_DP_PIN 18)
|
||||
|
||||
set(USBD_PIO_ENABLED 1)
|
||||
set(USBD_PIO_USB_DP_PIN 0)
|
||||
|
||||
set(TS3USB221_ENABLED 1)
|
||||
set(TS3USB221_PIN_MUX_OE 20)
|
||||
set(TS3USB221_PIN_MUX_SEL 21)
|
||||
|
||||
set(ESP32_SPI_NUM 1)
|
||||
set(ESP32_SPI_PIN_SCK 10)
|
||||
set(ESP32_SPI_PIN_MOSI 11)
|
||||
set(ESP32_SPI_PIN_MISO 12)
|
||||
set(ESP32_SPI_PIN_CS 13)
|
||||
set(ESP32_SPI_PIN_IRQ 7)
|
||||
|
||||
set(SD_CARD_ENABLED 1)
|
||||
set(SD_CARD_SPI_NUM 0)
|
||||
set(SD_CARD_SPI_PIN_SCK 2)
|
||||
set(SD_CARD_SPI_PIN_MOSI 3)
|
||||
set(SD_CARD_SPI_PIN_MISO 4)
|
||||
set(SD_CARD_SPI_PIN_CS 5)
|
||||
|
||||
set(OGXM_BOARD OGXM_BOARD_DEVKIT)
|
||||
|
||||
set(PICO_DEFAULT_UART 0)
|
||||
set(PICO_DEFAULT_UART_TX_PIN 16)
|
||||
set(PICO_DEFAULT_UART_RX_PIN 17)
|
||||
set(PICO_BOARD pico)
|
||||
@@ -1,43 +0,0 @@
|
||||
set(LED_ENABLED 1)
|
||||
set(LED_PIN 25)
|
||||
|
||||
set(UART_BRIDGE_ENABLED 1)
|
||||
set(UART_BRIDGE_UART_NUM 1)
|
||||
set(UART_BRIDGE_PIN_TX 8)
|
||||
set(UART_BRIDGE_PIN_RX 9)
|
||||
set(UART_BRIDGE_PIN_BOOT 22)
|
||||
set(UART_BRIDGE_PIN_RESET 6)
|
||||
|
||||
# set(USBH_ENABLED 1)
|
||||
# set(USBH_PIO_ENABLED 1)
|
||||
# set(USBH_PIO_DP_PIN 18)
|
||||
|
||||
set(USBD_PIO_ENABLED 0)
|
||||
set(USBD_PIO_USB_DP_PIN 0)
|
||||
|
||||
set(TS3USB221_ENABLED 1)
|
||||
set(TS3USB221_PIN_MUX_OE 20)
|
||||
set(TS3USB221_PIN_MUX_SEL 21)
|
||||
|
||||
set(BLUETOOTH_ENABLED 1)
|
||||
# set(BLUETOOTH_HARDWARE BLUETOOTH_HARDWARE_ESP32_SPI)
|
||||
set(BLUETOOTH_HARDWARE BLUETOOTH_HARDWARE_ESP32_I2C)
|
||||
|
||||
set(ESP32_SPI_NUM 1)
|
||||
set(ESP32_SPI_PIN_SCK 10)
|
||||
set(ESP32_SPI_PIN_MISO 11)
|
||||
set(ESP32_SPI_PIN_MOSI 12)
|
||||
set(ESP32_SPI_PIN_CS 13)
|
||||
set(ESP32_SPI_PIN_IRQ 7)
|
||||
|
||||
set(ESP32_I2C_NUM 1)
|
||||
set(ESP32_I2C_PIN_SDA 26)
|
||||
set(ESP32_I2C_PIN_SCL 27)
|
||||
set(ESP32_I2C_PIN_IRQ UART_BRIDGE_PIN_TX)
|
||||
|
||||
set(OGXM_BOARD OGXM_BOARD_DEVKIT_ESP32)
|
||||
|
||||
set(PICO_DEFAULT_UART 0)
|
||||
set(PICO_DEFAULT_UART_TX_PIN 16)
|
||||
set(PICO_DEFAULT_UART_RX_PIN 17)
|
||||
set(PICO_BOARD pico)
|
||||
@@ -1,20 +0,0 @@
|
||||
set(UART_BRIDGE_ENABLED 1)
|
||||
set(UART_BRIDGE_UART_NUM 0)
|
||||
set(UART_BRIDGE_PIN_TX 16)
|
||||
set(UART_BRIDGE_PIN_RX 17)
|
||||
set(UART_BRIDGE_PIN_BOOT 20)
|
||||
set(UART_BRIDGE_PIN_RESET 8)
|
||||
|
||||
set(BLUETOOTH_ENABLED 1)
|
||||
set(BLUETOOTH_HARDWARE BLUETOOTH_HARDWARE_ESP32_I2C)
|
||||
|
||||
set(ESP32_I2C_NUM 1)
|
||||
set(ESP32_I2C_PIN_SDA 18)
|
||||
set(ESP32_I2C_PIN_SCL 19)
|
||||
set(ESP32_I2C_PIN_IRQ UART_BRIDGE_PIN_TX)
|
||||
|
||||
set(OGXM_BOARD OGXM_BOARD_BLUETOOTH)
|
||||
|
||||
set(PICO_DEFAULT_UART 1)
|
||||
set(PICO_DEFAULT_UART_TX_PIN 4)
|
||||
set(PICO_DEFAULT_UART_RX_PIN 5)
|
||||
@@ -1,26 +0,0 @@
|
||||
set(UART_BRIDGE_ENABLED 1)
|
||||
set(UART_BRIDGE_UART_NUM 1)
|
||||
set(UART_BRIDGE_PIN_TX 8)
|
||||
set(UART_BRIDGE_PIN_RX 9)
|
||||
set(UART_BRIDGE_PIN_BOOT 22)
|
||||
set(UART_BRIDGE_PIN_RESET 6)
|
||||
|
||||
set(BLUETOOTH_ENABLED 1)
|
||||
set(BLUETOOTH_HARDWARE BLUETOOTH_HARDWARE_ESP32_SPI)
|
||||
|
||||
set(ESP32_SPI_NUM 1)
|
||||
set(ESP32_SPI_PIN_SCK 10)
|
||||
set(ESP32_SPI_PIN_MOSI 11)
|
||||
set(ESP32_SPI_PIN_MISO 12)
|
||||
set(ESP32_SPI_PIN_CS 13)
|
||||
set(ESP32_SPI_PIN_IRQ 7)
|
||||
|
||||
set(GAMEPAD_MAX 1)
|
||||
|
||||
set(OGXM_BOARD OGXM_BOARD_BLUETOOTH)
|
||||
|
||||
set(PICO_DEFAULT_UART 0)
|
||||
set(PICO_DEFAULT_UART_TX_PIN 16)
|
||||
set(PICO_DEFAULT_UART_RX_PIN 17)
|
||||
|
||||
set(VERIFY_BUILD_VERSION 1)
|
||||
@@ -1,31 +0,0 @@
|
||||
set(NEOPIXEL_ENABLED 1)
|
||||
set(NEOPIXEL_FORMAT NEOPIXEL_FORMAT_RGB)
|
||||
set(NEOPIXEL_DATA_PIN 16)
|
||||
|
||||
set(USBH_ENABLED 1)
|
||||
set(USBH_PIO_ENABLED 1)
|
||||
set(USBH_PIO_DP_PIN 12)
|
||||
|
||||
set(FOUR_CHANNEL_I2C_NUM 0)
|
||||
set(FOUR_CHANNEL_I2C_PIN_SDA 4)
|
||||
set(FOUR_CHANNEL_I2C_PIN_SCL 5)
|
||||
set(FOUR_CHANNEL_I2C_PIN_IRQ_1 6)
|
||||
set(FOUR_CHANNEL_I2C_PIN_IRQ_2 7)
|
||||
set(FOUR_CHANNEL_I2C_PIN_IRQ_3 8)
|
||||
set(FOUR_CHANNEL_PIN_SLAVE_1 0)
|
||||
set(FOUR_CHANNEL_PIN_SLAVE_2 1)
|
||||
|
||||
set(GAMEPADS_MAX 4)
|
||||
|
||||
set(OGXM_BOARD OGXM_BOARD_FOUR_CHANNEL)
|
||||
|
||||
set(PICO_DEFAULT_UART 0)
|
||||
set(PICO_DEFAULT_UART_TX_PIN 0)
|
||||
set(PICO_DEFAULT_UART_RX_PIN 1)
|
||||
|
||||
set(PICO_FLASH_SIZE_BYTES 2*1024*1024)
|
||||
set(PICO_PLATFORM rp2350)
|
||||
set(PICO_BOARD none)
|
||||
|
||||
add_compile_definitions(PICO_BOOT_STAGE2_CHOOSE_W25Q016=1)
|
||||
add_compile_definitions(PICO_XOSC_STARTUP_DELAY_MULTIPLIER=128)
|
||||
@@ -1,21 +0,0 @@
|
||||
set(VERIFY_BUILD_VERSION 1)
|
||||
|
||||
set(UART_BRIDGE_ENABLED 1)
|
||||
set(UART_BRIDGE_UART_NUM 0)
|
||||
set(UART_BRIDGE_PIN_TX 16)
|
||||
set(UART_BRIDGE_PIN_RX 17)
|
||||
set(UART_BRIDGE_PIN_BOOT 20)
|
||||
set(UART_BRIDGE_PIN_RESET 8)
|
||||
|
||||
set(BLUETOOTH_ENABLED 1)
|
||||
set(BLUETOOTH_HARDWARE BLUETOOTH_HARDWARE_ESP32_I2C)
|
||||
|
||||
set(ESP32_I2C_NUM 1)
|
||||
set(ESP32_I2C_PIN_SDA 18)
|
||||
set(ESP32_I2C_PIN_SCL 19)
|
||||
|
||||
set(OGXM_BOARD OGXM_BOARD_BLUETOOTH)
|
||||
|
||||
set(PICO_DEFAULT_UART 1)
|
||||
set(PICO_DEFAULT_UART_TX_PIN 4)
|
||||
set(PICO_DEFAULT_UART_RX_PIN 5)
|
||||
@@ -1,13 +0,0 @@
|
||||
set(LED_ENABLED 1)
|
||||
set(LED_PIN 25)
|
||||
|
||||
set(USBH_ENABLED 1)
|
||||
set(USBH_PIO_ENABLED 1)
|
||||
set(USBH_PIO_DP_PIN 0)
|
||||
|
||||
set(OGXM_BOARD OGXM_BOARD_STANDARD)
|
||||
|
||||
set(PICO_DEFAULT_UART 1)
|
||||
set(PICO_DEFAULT_UART_TX_PIN 4)
|
||||
set(PICO_DEFAULT_UART_RX_PIN 5)
|
||||
set(PICO_BOARD pico)
|
||||
@@ -1,15 +0,0 @@
|
||||
set(LED_ENABLED 1)
|
||||
set(LED_PIN 25)
|
||||
|
||||
set(USBH_ENABLED 1)
|
||||
set(USBH_PIO_ENABLED 1)
|
||||
set(USBH_PIO_DP_PIN 0)
|
||||
|
||||
set(OGXM_BOARD OGXM_BOARD_STANDARD)
|
||||
|
||||
set(PICO_DEFAULT_UART 1)
|
||||
set(PICO_DEFAULT_UART_TX_PIN 4)
|
||||
set(PICO_DEFAULT_UART_RX_PIN 5)
|
||||
set(PICO_FLASH_SIZE_BYTES 4*1024*1024)
|
||||
set(PICO_PLATFORM rp2350)
|
||||
set(PICO_BOARD pico2)
|
||||
@@ -1,12 +0,0 @@
|
||||
set(BLUETOOTH_ENABLED 1)
|
||||
set(BLUETOOTH_HARDWARE BLUETOOTH_HARDWARE_PICOW)
|
||||
|
||||
set(PICO_DEFAULT_UART 1)
|
||||
set(PICO_DEFAULT_UART_TX_PIN 4)
|
||||
set(PICO_DEFAULT_UART_RX_PIN 5)
|
||||
|
||||
set(PICO_FLASH_SIZE_BYTES 4*1024*1024)
|
||||
set(PICO_PLATFORM rp2350)
|
||||
set(PICO_BOARD pico2_w)
|
||||
|
||||
set(OGXM_BOARD OGXM_BOARD_BLUETOOTH)
|
||||
@@ -1,16 +0,0 @@
|
||||
set(BLUETOOTH_ENABLED 1)
|
||||
set(BLUETOOTH_HARDWARE BLUETOOTH_HARDWARE_PICOW)
|
||||
|
||||
set(USBH_ENABLED 1)
|
||||
set(USBH_PIO_ENABLED 1)
|
||||
set(USBH_PIO_DP_PIN 0)
|
||||
|
||||
set(PICO_DEFAULT_UART 1)
|
||||
set(PICO_DEFAULT_UART_TX_PIN 4)
|
||||
set(PICO_DEFAULT_UART_RX_PIN 5)
|
||||
|
||||
set(PICO_FLASH_SIZE_BYTES 4*1024*1024)
|
||||
set(PICO_PLATFORM rp2350)
|
||||
set(PICO_BOARD pico2_w)
|
||||
|
||||
set(OGXM_BOARD OGXM_BOARD_BLUETOOTH_USBH)
|
||||
@@ -1,13 +0,0 @@
|
||||
set(BLUETOOTH_ENABLED 1)
|
||||
set(BLUETOOTH_HARDWARE BLUETOOTH_HARDWARE_PICOW)
|
||||
|
||||
set(PICO_DEFAULT_UART 1)
|
||||
set(PICO_DEFAULT_UART_TX_PIN 4)
|
||||
set(PICO_DEFAULT_UART_RX_PIN 5)
|
||||
|
||||
set(PICO_BOARD pico_w)
|
||||
|
||||
set(OGXM_BOARD OGXM_BOARD_BLUETOOTH)
|
||||
|
||||
set(OGXM_LOG_ENABLED 1)
|
||||
set(OGXM_LOG_LEVEL 3)
|
||||
@@ -1,14 +0,0 @@
|
||||
set(BLUETOOTH_ENABLED 1)
|
||||
set(BLUETOOTH_HARDWARE BLUETOOTH_HARDWARE_PICOW)
|
||||
|
||||
set(USBH_ENABLED 1)
|
||||
set(USBH_PIO_ENABLED 1)
|
||||
set(USBH_PIO_DP_PIN 0)
|
||||
|
||||
set(PICO_DEFAULT_UART 1)
|
||||
set(PICO_DEFAULT_UART_TX_PIN 4)
|
||||
set(PICO_DEFAULT_UART_RX_PIN 5)
|
||||
|
||||
set(PICO_BOARD pico_w)
|
||||
|
||||
set(OGXM_BOARD OGXM_BOARD_BLUETOOTH_USBH)
|
||||
@@ -1,14 +0,0 @@
|
||||
set(NEOPIXEL_ENABLED 1)
|
||||
set(NEOPIXEL_FORMAT NEOPIXEL_FORMAT_GRB)
|
||||
set(NEOPIXEL_DATA_PIN 16)
|
||||
|
||||
set(USBH_ENABLED 1)
|
||||
set(USBH_PIO_ENABLED 1)
|
||||
set(USBH_PIO_DP_PIN 10)
|
||||
|
||||
set(OGXM_BOARD OGXM_BOARD_STANDARD)
|
||||
|
||||
set(PICO_DEFAULT_UART 1)
|
||||
set(PICO_DEFAULT_UART_TX_PIN 4)
|
||||
set(PICO_DEFAULT_UART_RX_PIN 5)
|
||||
set(PICO_BOARD waveshare_rp2040_zero)
|
||||
@@ -1,23 +0,0 @@
|
||||
set(NEOPIXEL_ENABLED 1)
|
||||
set(NEOPIXEL_FORMAT NEOPIXEL_FORMAT_RGB)
|
||||
set(NEOPIXEL_DATA_PIN 16)
|
||||
|
||||
set(USBH_ENABLED 1)
|
||||
set(USBH_PIO_ENABLED 1)
|
||||
set(USBH_PIO_DP_PIN 12)
|
||||
|
||||
set(OGXM_BOARD OGXM_BOARD_STANDARD)
|
||||
|
||||
# set(PICO_DEFAULT_UART 1)
|
||||
# set(PICO_DEFAULT_UART_TX_PIN 4)
|
||||
# set(PICO_DEFAULT_UART_RX_PIN 5)
|
||||
set(PICO_DEFAULT_UART 0)
|
||||
set(PICO_DEFAULT_UART_TX_PIN 0)
|
||||
set(PICO_DEFAULT_UART_RX_PIN 1)
|
||||
set(PICO_FLASH_SIZE_BYTES 2*1024*1024)
|
||||
set(PICO_PLATFORM rp2350)
|
||||
set(PICO_BOARD none)
|
||||
# set(PICO_BOARD pico2)
|
||||
|
||||
add_compile_definitions(PICO_BOOT_STAGE2_CHOOSE_W25Q016=1)
|
||||
add_compile_definitions(PICO_XOSC_STARTUP_DELAY_MULTIPLIER=128)
|
||||
@@ -1,46 +0,0 @@
|
||||
set(VERIFY_BUILD_VERSION 0)
|
||||
set(LED_ENABLED 0)
|
||||
set(NEOPIXEL_ENABLED 0)
|
||||
set(NEOPIXEL_VCC_ENABLED 0)
|
||||
set(UART_BRIDGE_ENABLED 0)
|
||||
set(USBH_ENABLED 0)
|
||||
set(USBH_PIO_ENABLED 0)
|
||||
set(USBD_PIO_ENABLED 0)
|
||||
set(TS3USB221_ENABLED 0)
|
||||
set(BLUETOOTH_ENABLED 0)
|
||||
set(USBH_VCC_ENABLED 0)
|
||||
|
||||
set(OGXM_LOG_ENABLED 0)
|
||||
set(OGXM_LOG_LEVEL 2)
|
||||
|
||||
set(SD_CARD_ENABLED 0)
|
||||
set(SD_CARD_SPI_NUM 0)
|
||||
set(SD_CARD_SPI_PIN_SCK 0)
|
||||
set(SD_CARD_SPI_PIN_MOSI 0)
|
||||
set(SD_CARD_SPI_PIN_MISO 0)
|
||||
set(SD_CARD_SPI_PIN_CS 0)
|
||||
|
||||
set(BLUETOOTH_HARDWARE_PICOW 0)
|
||||
set(BLUETOOTH_HARDWARE_ESP32_I2C 1)
|
||||
set(BLUETOOTH_HARDWARE_ESP32_SPI 2)
|
||||
set(BLUETOOTH_HARDWARE 0)
|
||||
|
||||
set(NEOPIXEL_FORMAT_RGB 0)
|
||||
set(NEOPIXEL_FORMAT_GRB 1)
|
||||
set(NEOPIXEL_FORMAT_WRGB 2)
|
||||
|
||||
set(OGXM_BOARD_STANDARD 1)
|
||||
set(OGXM_BOARD_BLUETOOTH 2)
|
||||
set(OGXM_BOARD_DEVKIT 3)
|
||||
set(OGXM_BOARD_DEVKIT_ESP32 4)
|
||||
set(OGXM_BOARD_4CHANNEL 5)
|
||||
set(OGXM_BOARD_BLUETOOTH_USBH 6)
|
||||
|
||||
set(GAMEPADS_MAX 1)
|
||||
|
||||
set(PICO_DEFAULT_UART 1)
|
||||
set(PICO_DEFAULT_UART_TX_PIN 4)
|
||||
set(PICO_DEFAULT_UART_RX_PIN 5)
|
||||
|
||||
set(PICO_FLASH_SIZE_BYTES 2*1024*1024)
|
||||
set(PICO_PLATFORM rp2040)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,61 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#----------------------------------------
|
||||
# Purpose - Create some $BIT variables
|
||||
# Create $K and $M variables
|
||||
# and some bit field extraction variables.
|
||||
# Create helper variables ...
|
||||
# BIT0.. BIT31
|
||||
|
||||
for { set x 0 } { $x < 32 } { set x [expr {$x + 1}]} {
|
||||
set vn [format "BIT%d" $x]
|
||||
global $vn
|
||||
set $vn [expr {1 << $x}]
|
||||
}
|
||||
|
||||
# Create K bytes values
|
||||
# __1K ... to __2048K
|
||||
for { set x 1 } { $x < 2048 } { set x [expr {$x * 2}]} {
|
||||
set vn [format "__%dK" $x]
|
||||
global $vn
|
||||
set $vn [expr {1024 * $x}]
|
||||
}
|
||||
|
||||
# Create M bytes values
|
||||
# __1M ... to __2048K
|
||||
for { set x 1 } { $x < 2048 } { set x [expr {$x * 2}]} {
|
||||
set vn [format "__%dM" $x]
|
||||
global $vn
|
||||
set $vn [expr {1024 * 1024 * $x}]
|
||||
}
|
||||
|
||||
proc create_mask { MSB LSB } {
|
||||
return [expr {((1 << ($MSB - $LSB + 1))-1) << $LSB}]
|
||||
}
|
||||
|
||||
# Cut Bits $MSB to $LSB out of this value.
|
||||
# Example: % format "0x%08x" [extract_bitfield 0x12345678 27 16]
|
||||
# Result: 0x02340000
|
||||
|
||||
proc extract_bitfield { VALUE MSB LSB } {
|
||||
return [expr {[create_mask $MSB $LSB] & $VALUE}]
|
||||
}
|
||||
|
||||
|
||||
# Cut bits $MSB to $LSB out of this value
|
||||
# and shift (normalize) them down to bit 0.
|
||||
#
|
||||
# Example: % format "0x%08x" [normalize_bitfield 0x12345678 27 16]
|
||||
# Result: 0x00000234
|
||||
#
|
||||
proc normalize_bitfield { VALUE MSB LSB } {
|
||||
return [expr {[extract_bitfield $VALUE $MSB $LSB ] >> $LSB}]
|
||||
}
|
||||
|
||||
proc show_normalize_bitfield { VALUE MSB LSB } {
|
||||
set m [create_mask $MSB $LSB]
|
||||
set mr [expr {$VALUE & $m}]
|
||||
set sr [expr {$mr >> $LSB}]
|
||||
echo [format "((0x%08x & 0x%08x) -> 0x%08x) >> %2d => (0x%x) %5d " $VALUE $m $mr $LSB $sr $sr]
|
||||
return $sr
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# Product page:
|
||||
# https://www.8devices.com/products/lima
|
||||
#
|
||||
# Location of JTAG pins:
|
||||
# J2 GPIO0 JTAG TCK
|
||||
# J2 GPIO1 JTAG TDI
|
||||
# J2 GPIO2 JTAG TDO
|
||||
# J2 GPIO3 JTAG TMS
|
||||
# J2 RST directly connected to RESET_L of the SoC and can be used as
|
||||
# JTAG SRST. Note: this pin will also reset the debug engine.
|
||||
# J1 +3,3V Can be use as JTAG Vref
|
||||
# J1 or J2 GND Can be used for JTAG GND
|
||||
#
|
||||
# This board is powered from mini USB connecter which is also used
|
||||
# as USB to UART converted based on FTDI FT230XQ chip
|
||||
|
||||
source [find target/qualcomm_qca4531.cfg]
|
||||
|
||||
proc board_init { } {
|
||||
qca4531_ddr2_550_550_init
|
||||
}
|
||||
|
||||
$_TARGETNAME configure -event reset-init {
|
||||
board_init
|
||||
}
|
||||
|
||||
set ram_boot_address 0xa0000000
|
||||
$_TARGETNAME configure -work-area-phys 0xa1FFE000 -work-area-size 0x1000
|
||||
|
||||
flash bank flash0 ath79 0xbf000000 0 0 0 $_TARGETNAME cs0
|
||||
@@ -1,71 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# board config file for AcTux3/XBA IXP42x board
|
||||
# Date: 2010-12-16
|
||||
# Author: Michael Schwingen <michael@schwingen.org>
|
||||
|
||||
reset_config trst_and_srst separate
|
||||
|
||||
adapter srst delay 100
|
||||
jtag_ntrst_delay 100
|
||||
|
||||
source [find target/ixp42x.cfg]
|
||||
|
||||
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size 0x10000 -work-area-backup 0
|
||||
|
||||
$_TARGETNAME configure -event reset-init { init_actux3 }
|
||||
|
||||
proc init_actux3 { } {
|
||||
##########################################################################
|
||||
# setup expansion bus CS
|
||||
##########################################################################
|
||||
mww 0xc4000000 0xbd113842 ;#CS0 : Flash, write enabled @0x50000000
|
||||
mww 0xc4000004 0x94d10013 ;#CS1
|
||||
mww 0xc4000008 0x95960003 ;#CS2
|
||||
mww 0xc400000c 0x00000000 ;#CS3
|
||||
mww 0xc4000010 0x80900003 ;#CS4
|
||||
mww 0xc4000014 0x9d520003 ;#CS5
|
||||
mww 0xc4000018 0x81860001 ;#CS6
|
||||
mww 0xc400001c 0x80900003 ;#CS7
|
||||
|
||||
ixp42x_init_sdram $::IXP42x_SDRAM_16MB_4Mx16_1BANK 2100 3
|
||||
|
||||
#mww 0xc4000020 0xffffee ;# CFG0: remove expansion bus boot flash mirror at 0x00000000
|
||||
|
||||
ixp42x_set_bigendian
|
||||
|
||||
flash probe 0
|
||||
}
|
||||
|
||||
proc flash_boot { {FILE "/tftpboot/actux3/u-boot.bin"} } {
|
||||
echo "writing bootloader: $FILE"
|
||||
flash write_image erase $FILE 0x50000000 bin
|
||||
}
|
||||
|
||||
set _FLASHNAME $_CHIPNAME.flash
|
||||
flash bank $_FLASHNAME cfi 0x50000000 0x400000 2 2 $_TARGETNAME
|
||||
|
||||
init
|
||||
reset init
|
||||
|
||||
# setup to debug u-boot in flash
|
||||
proc uboot_debug {} {
|
||||
gdb_breakpoint_override hard
|
||||
xscale vector_catch 0xFF
|
||||
|
||||
xscale vector_table low 1 0xe59ff018
|
||||
xscale vector_table low 2 0xe59ff018
|
||||
xscale vector_table low 3 0xe59ff018
|
||||
xscale vector_table low 4 0xe59ff018
|
||||
xscale vector_table low 5 0xe59ff018
|
||||
xscale vector_table low 6 0xe59ff018
|
||||
xscale vector_table low 7 0xe59ff018
|
||||
|
||||
xscale vector_table high 1 0xe59ff018
|
||||
xscale vector_table high 2 0xe59ff018
|
||||
xscale vector_table high 3 0xe59ff018
|
||||
xscale vector_table high 4 0xe59ff018
|
||||
xscale vector_table high 5 0xe59ff018
|
||||
xscale vector_table high 6 0xe59ff018
|
||||
xscale vector_table high 7 0xe59ff018
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#
|
||||
# Adapteva Parallella-I board (via Porcupine-1 adapter board)
|
||||
#
|
||||
|
||||
reset_config srst_only
|
||||
|
||||
source [find target/zynq_7000.cfg]
|
||||
@@ -1,32 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#
|
||||
# Analog Devices ADSP-SC584-EZBRD evaluation board
|
||||
#
|
||||
# Evaluation boards by Analog Devices (and designs derived from them) use a
|
||||
# non-standard 10-pin 0.05" ARM Cortex Debug Connector. In this bastardized
|
||||
# implementation, pin 9 (GND or GNDDetect) has been usurped with JTAG /TRST.
|
||||
#
|
||||
# As a result, a standards-compliant debug pod will force /TRST active,
|
||||
# putting the processor's debug interface into reset and preventing usage.
|
||||
#
|
||||
# A connector adapter must be employed on these boards to isolate or remap
|
||||
# /TRST so that it is only asserted when intended.
|
||||
|
||||
# Analog expects users to use their proprietary ICE-1000 / ICE-2000 with all
|
||||
# ADSP-SC58x designs, but this is an ARM target (and subject to the
|
||||
# qualifications above) many ARM debug pods should be compatible.
|
||||
|
||||
#source [find interface/cmsis-dap.cfg]
|
||||
source [find interface/jlink.cfg]
|
||||
|
||||
# Analog's silicon supports SWD and JTAG, but their proprietary ICE is limited
|
||||
# to JTAG. (This is presumably why their connector pinout was modified.)
|
||||
# SWD is chosen here, as it is more efficient and doesn't require /TRST.
|
||||
|
||||
transport select swd
|
||||
|
||||
# chosen speed is 'safe' choice, but your adapter may be capable of more
|
||||
adapter speed 400
|
||||
|
||||
source [find target/adsp-sc58x.cfg]
|
||||
@@ -1,23 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
# configuration file for Advantech IMX8QM DMSSE20
|
||||
#
|
||||
|
||||
# only JTAG supported
|
||||
transport select jtag
|
||||
|
||||
# set a safe JTAG clock speed, can be overridden
|
||||
adapter speed 1000
|
||||
|
||||
# default JTAG configuration has only SRST and no TRST
|
||||
reset_config srst_only srst_push_pull
|
||||
|
||||
# delay after SRST goes inactive
|
||||
adapter srst delay 70
|
||||
|
||||
# board has an i.MX8QM with 4 Cortex-A53 cores and 2 Cortex-A72
|
||||
set CHIPNAME imx8qm
|
||||
set CHIPCORES 6
|
||||
|
||||
# source SoC configuration
|
||||
source [find tcl/target/imx8qm.cfg]
|
||||
@@ -1,71 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
source [find target/alphascale_asm9260t.cfg]
|
||||
|
||||
reset_config trst_and_srst
|
||||
|
||||
$_TARGETNAME configure -event reset-init {
|
||||
echo "Configure clock"
|
||||
# Enable SRAM clk
|
||||
mww 0x80040024 0x4
|
||||
# Enable IRQ clk
|
||||
mww 0x80040034 0x100
|
||||
# Enable DMA0,1 clk
|
||||
mww 0x80040024 0x600
|
||||
# Make sysre syspll is enabled
|
||||
mww 0x80040238 0x750
|
||||
#CPU = PLLCLK/2
|
||||
mww 0x8004017C 0x2
|
||||
#SYSAHBCLK = CPUCLK/2
|
||||
mww 0x80040180 0x2
|
||||
# Set PLL freq to 480MHz
|
||||
mww 0x80040100 480
|
||||
# normally we shoul waiting here until we get 0x1 (0x80040104)&0x1)==0x0)
|
||||
sleep 100
|
||||
|
||||
# select PLL as main source
|
||||
mww 0x80040120 0x1
|
||||
# disable and enable main clk to update changes?
|
||||
mww 0x80040124 0x0
|
||||
mww 0x80040124 0x1
|
||||
|
||||
echo "Configure memory"
|
||||
#enable EMI CLK
|
||||
mww 0x80040024 0x40
|
||||
|
||||
# configure memory controller for internal SRAM
|
||||
mww 0x80700000 0x1188
|
||||
# change default emi clk delay
|
||||
mww 0x8004034C 0xA0503
|
||||
# make sure chip_select_register2_low has correct value (why?)
|
||||
mww 0x8070001c 0x20000000
|
||||
# set type to sdram and size to 32MB
|
||||
mww 0x8070005c 0xa
|
||||
# configure internal SDRAM timing
|
||||
mww 0x80700004 0x024996d9
|
||||
# configure Static Memory timing
|
||||
mww 0x80700094 0x00542b4f
|
||||
|
||||
echo "Configure uart4"
|
||||
# enable pinctrl clk
|
||||
mww 0x80040024 0x2000000
|
||||
# mux GPIO3_0 and GPIO3_1 to UART4
|
||||
mww 0x80044060 0x2
|
||||
mww 0x80044064 0x2
|
||||
# configure UART4CLKDIV
|
||||
mww 0x800401a8 0x1
|
||||
# enable uart4 clk
|
||||
mww 0x80040024 0x8000
|
||||
# clear softrst and clkgate on uart4
|
||||
mww 0x80010008 0xC0000000
|
||||
# set bandrate 115200 12M
|
||||
mww 0x80010030 0x00062070
|
||||
# enable Rx&Tx
|
||||
mww 0x80010024 0x301
|
||||
# clear hw control
|
||||
mww 0x80010028 0xc000
|
||||
}
|
||||
|
||||
$_TARGETNAME configure -work-area-phys 0x21ffe000 -work-area-virt 0xc1ffe000 -work-area-size 0x1000
|
||||
$_TARGETNAME arm7_9 fast_memory_access enable
|
||||
$_TARGETNAME arm7_9 dcc_downloads enable
|
||||
@@ -1,20 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#
|
||||
# Cyclone V SocKit board
|
||||
# http://www.altera.com/b/arrow-sockit.html
|
||||
#
|
||||
# Software support page:
|
||||
# http://www.rocketboards.org/
|
||||
|
||||
# openocd does not currently support the on-board USB Blaster II.
|
||||
# Install the JTAG header and use a USB Blaster instead.
|
||||
adapter driver usb_blaster
|
||||
|
||||
source [find target/altera_fpgasoc.cfg]
|
||||
|
||||
# If the USB Blaster II were supported, these settings would be needed
|
||||
#usb_blaster vid_pid 0x09fb 0x6810
|
||||
#usb_blaster device_desc "USB-Blaster II"
|
||||
|
||||
adapter speed 100
|
||||
@@ -1,22 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# DANGER!!!! early work in progress for this PCB/target.
|
||||
#
|
||||
# The most basic operations work well enough that it is
|
||||
# useful to have this in the repository for cooperation
|
||||
# alpha testing purposes.
|
||||
#
|
||||
# TI AM3517
|
||||
#
|
||||
# http://focus.ti.com/docs/prod/folders/print/am3517.html
|
||||
# http://processors.wiki.ti.com/index.php/Debug_Access_Port_(DAP)
|
||||
# http://processors.wiki.ti.com/index.php?title=How_to_Find_the_Silicon_Revision_of_your_OMAP35x
|
||||
|
||||
set CHIPTYPE "am35x"
|
||||
source [find target/amdm37x.cfg]
|
||||
|
||||
# The TI-14 JTAG connector does not have srst. CPU reset is handled in
|
||||
# hardware.
|
||||
reset_config trst_only
|
||||
|
||||
# "amdm37x_dbginit am35x.cpu" needs to be run after init.
|
||||
@@ -1,26 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#
|
||||
# OpenOCD Board Configuration for eMAG Development Platform
|
||||
#
|
||||
# Copyright (c) 2019-2021, Ampere Computing LLC
|
||||
#
|
||||
|
||||
#
|
||||
# Configure JTAG speed
|
||||
#
|
||||
|
||||
adapter speed 2000
|
||||
|
||||
#
|
||||
# Configure Resets
|
||||
#
|
||||
|
||||
jtag_ntrst_delay 100
|
||||
reset_config trst_only
|
||||
|
||||
#
|
||||
# Configure Targets
|
||||
#
|
||||
|
||||
source [find target/ampere_emag.cfg]
|
||||
@@ -1,100 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
# OpenOCD Board Configuration for Ampere Altra ("Quicksilver") and
|
||||
# Ampere Altra Max ("Mystique") processors
|
||||
#
|
||||
# Copyright (c) 2019-2021, Ampere Computing LLC
|
||||
|
||||
# Argument Description
|
||||
#
|
||||
# JTAGFREQ
|
||||
# Set the JTAG clock frequency
|
||||
# Syntax: -c "set JTAGFREQ {freq_in_khz}"
|
||||
#
|
||||
# SYSNAME
|
||||
# Set the system name
|
||||
# If not specified, defaults to "qs"
|
||||
# Syntax: -c "set SYSNAME {qs}"
|
||||
#
|
||||
# Life-Cycle State (LCS)
|
||||
# If not specified, defaults to "Secure LCS"
|
||||
# LCS=0, "Secure LCS"
|
||||
# LCS=1, "Chip Manufacturing LCS"
|
||||
# Syntax: -c "set LCS {0}"
|
||||
# Syntax: -c "set LCS {1}"
|
||||
#
|
||||
# CORELIST_S0
|
||||
# Specify available physical cores by number
|
||||
# Example syntax to connect to physical cores 16 and 17 for S0
|
||||
# Syntax: -c "set CORELIST_S0 {16 17}"
|
||||
#
|
||||
# COREMASK_S0_LO
|
||||
# Specify available physical cores 0-63 by mask
|
||||
# Example syntax to connect to physical cores 16 and 17 for S0
|
||||
# Syntax: -c "set COREMASK_S0_LO {0x0000000000030000}"
|
||||
#
|
||||
# COREMASK_S0_HI
|
||||
# Specify available physical cores 64 and above by mask
|
||||
# Example syntax to connect to physical cores 94 and 95 for S0
|
||||
# Syntax: -c "set COREMASK_S0_HI {0x00000000C0000000}"
|
||||
#
|
||||
# PHYS_IDX
|
||||
# Enable OpenOCD ARMv8 core target physical indexing
|
||||
# If not specified, defaults to OpenOCD ARMv8 core target logical indexing
|
||||
# Syntax: -c "set PHYS_IDX {}"
|
||||
|
||||
#
|
||||
# Configure JTAG speed
|
||||
#
|
||||
|
||||
if { [info exists JTAGFREQ] } {
|
||||
adapter speed $JTAGFREQ
|
||||
} else {
|
||||
adapter speed 100
|
||||
}
|
||||
|
||||
#
|
||||
# Set the system name
|
||||
#
|
||||
|
||||
if { [info exists SYSNAME] } {
|
||||
set _SYSNAME $SYSNAME
|
||||
} else {
|
||||
set _SYSNAME qs
|
||||
}
|
||||
|
||||
#
|
||||
# Configure Resets
|
||||
#
|
||||
|
||||
jtag_ntrst_delay 100
|
||||
reset_config trst_only
|
||||
|
||||
#
|
||||
# Configure Targets
|
||||
#
|
||||
|
||||
if { [info exists CORELIST_S0] || [info exists COREMASK_S0_LO] || [info exists COREMASK_S0_HI] } {
|
||||
set CHIPNAME ${_SYSNAME}0
|
||||
if { [info exists CORELIST_S0] } {
|
||||
set CORELIST $CORELIST_S0
|
||||
} else {
|
||||
if { [info exists COREMASK_S0_LO] } {
|
||||
set COREMASK_LO $COREMASK_S0_LO
|
||||
} else {
|
||||
set COREMASK_LO 0x0
|
||||
}
|
||||
|
||||
if { [info exists COREMASK_S0_HI] } {
|
||||
set COREMASK_HI $COREMASK_S0_HI
|
||||
} else {
|
||||
set COREMASK_HI 0x0
|
||||
}
|
||||
}
|
||||
} else {
|
||||
set CHIPNAME ${_SYSNAME}0
|
||||
set COREMASK_LO 0x1
|
||||
set COREMASK_HI 0x0
|
||||
}
|
||||
|
||||
source [find target/ampere_qs_mq.cfg]
|
||||
@@ -1,164 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
# OpenOCD Board Configuration for Ampere Altra ("Quicksilver") and
|
||||
# Ampere Altra Max ("Mystique") processors
|
||||
#
|
||||
# Copyright (c) 2019-2021, Ampere Computing LLC
|
||||
|
||||
# Argument Description
|
||||
#
|
||||
# JTAGFREQ
|
||||
# Set the JTAG clock frequency
|
||||
# Syntax: -c "set JTAGFREQ {freq_in_khz}"
|
||||
#
|
||||
# SYSNAME
|
||||
# Set the system name
|
||||
# If not specified, defaults to "qs"
|
||||
# Syntax: -c "set SYSNAME {qs}"
|
||||
#
|
||||
# Life-Cycle State (LCS)
|
||||
# If not specified, defaults to "Secure LCS"
|
||||
# LCS=0, "Secure LCS"
|
||||
# LCS=1, "Chip Manufacturing LCS"
|
||||
# Syntax: -c "set LCS {0}"
|
||||
# Syntax: -c "set LCS {1}"
|
||||
#
|
||||
# CORELIST_S0, CORELIST_S1
|
||||
# Specify available physical cores by number
|
||||
# Example syntax to connect to physical cores 16 and 17 for S0 and S1
|
||||
# Syntax: -c "set CORELIST_S0 {16 17}"
|
||||
# Syntax: -c "set CORELIST_S1 {16 17}"
|
||||
#
|
||||
# COREMASK_S0_LO, COREMASK_S1_LO
|
||||
# Specify available physical cores 0-63 by mask
|
||||
# Example syntax to connect to physical cores 16 and 17 for S0 and S1
|
||||
# Syntax: -c "set COREMASK_S0_LO {0x0000000000030000}"
|
||||
# Syntax: -c "set COREMASK_S1_LO {0x0000000000030000}"
|
||||
#
|
||||
# COREMASK_S0_HI, COREMASK_S1_HI
|
||||
# Specify available physical cores 64 and above by mask
|
||||
# Example syntax to connect to physical cores 94 and 95 for S0 and S1
|
||||
# Syntax: -c "set COREMASK_S0_HI {0x00000000C0000000}"
|
||||
# Syntax: -c "set COREMASK_S1_HI {0x00000000C0000000}"
|
||||
#
|
||||
# SPLITSMP
|
||||
# Group all ARMv8 cores per socket into individual SMP sessions
|
||||
# If not specified, group ARMv8 cores from both sockets into one SMP session
|
||||
# Syntax: -c "set SPLITSMP {}"
|
||||
#
|
||||
# PHYS_IDX
|
||||
# Enable OpenOCD ARMv8 core target physical indexing
|
||||
# If not specified, defaults to OpenOCD ARMv8 core target logical indexing
|
||||
# Syntax: -c "set PHYS_IDX {}"
|
||||
|
||||
#
|
||||
# Configure JTAG speed
|
||||
#
|
||||
|
||||
if { [info exists JTAGFREQ] } {
|
||||
adapter speed $JTAGFREQ
|
||||
} else {
|
||||
adapter speed 100
|
||||
}
|
||||
|
||||
#
|
||||
# Set the system name
|
||||
#
|
||||
|
||||
if { [info exists SYSNAME] } {
|
||||
set _SYSNAME $SYSNAME
|
||||
} else {
|
||||
set _SYSNAME qs
|
||||
}
|
||||
|
||||
#
|
||||
# Configure Board level SMP configuration if necessary
|
||||
#
|
||||
|
||||
if { ![info exists SPLITSMP] } {
|
||||
# Group dual chip into a single SMP configuration
|
||||
set SMP_STR "target smp"
|
||||
set CORE_INDEX_OFFSET 0
|
||||
set DUAL_SOCKET_SMP_ENABLED ""
|
||||
}
|
||||
|
||||
#
|
||||
# Configure Resets
|
||||
#
|
||||
|
||||
jtag_ntrst_delay 100
|
||||
reset_config trst_only
|
||||
|
||||
#
|
||||
# Configure Targets
|
||||
#
|
||||
|
||||
if { [info exists CORELIST_S0] || [info exists COREMASK_S0_LO] || [info exists COREMASK_S0_HI] || \
|
||||
[info exists CORELIST_S1] || [info exists COREMASK_S1_LO] || [info exists COREMASK_S1_HI] } {
|
||||
set CHIPNAME ${_SYSNAME}1
|
||||
if { [info exists CORELIST_S1] } {
|
||||
set CORELIST $CORELIST_S1
|
||||
} else {
|
||||
if { [info exists COREMASK_S1_LO] } {
|
||||
set COREMASK_LO $COREMASK_S1_LO
|
||||
} else {
|
||||
set COREMASK_LO 0x0
|
||||
}
|
||||
|
||||
if { [info exists COREMASK_S1_HI] } {
|
||||
set COREMASK_HI $COREMASK_S1_HI
|
||||
} else {
|
||||
set COREMASK_HI 0x0
|
||||
}
|
||||
}
|
||||
source [find target/ampere_qs_mq.cfg]
|
||||
|
||||
if { [info exists DUAL_SOCKET_SMP_ENABLED] && [info exists PHYS_IDX]} {
|
||||
if { [info exists MQ_ENABLE] } {
|
||||
set CORE_INDEX_OFFSET 128
|
||||
} else {
|
||||
set CORE_INDEX_OFFSET 80
|
||||
}
|
||||
}
|
||||
|
||||
set CHIPNAME ${_SYSNAME}0
|
||||
if { [info exists CORELIST_S0] } {
|
||||
set CORELIST $CORELIST_S0
|
||||
} else {
|
||||
if { [info exists COREMASK_S0_LO] } {
|
||||
set COREMASK_LO $COREMASK_S0_LO
|
||||
} else {
|
||||
set COREMASK_LO 0x0
|
||||
}
|
||||
|
||||
if { [info exists COREMASK_S0_HI] } {
|
||||
set COREMASK_HI $COREMASK_S0_HI
|
||||
} else {
|
||||
set COREMASK_HI 0x0
|
||||
}
|
||||
}
|
||||
source [find target/ampere_qs_mq.cfg]
|
||||
} else {
|
||||
set CHIPNAME ${_SYSNAME}1
|
||||
set COREMASK_LO 0x0
|
||||
set COREMASK_HI 0x0
|
||||
source [find target/ampere_qs_mq.cfg]
|
||||
|
||||
if { [info exists DUAL_SOCKET_SMP_ENABLED] && [info exists PHYS_IDX]} {
|
||||
if { [info exists MQ_ENABLE] } {
|
||||
set CORE_INDEX_OFFSET 128
|
||||
} else {
|
||||
set CORE_INDEX_OFFSET 80
|
||||
}
|
||||
}
|
||||
|
||||
set CHIPNAME ${_SYSNAME}0
|
||||
set COREMASK_LO 0x1
|
||||
set COREMASK_HI 0x0
|
||||
source [find target/ampere_qs_mq.cfg]
|
||||
}
|
||||
|
||||
if { [info exists DUAL_SOCKET_SMP_ENABLED] } {
|
||||
# For dual socket SMP configuration, evaluate the string
|
||||
eval $SMP_STR
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# This board is from ARM and has an samsung s3c45101x01 chip
|
||||
|
||||
source [find target/samsung_s3c4510.cfg]
|
||||
|
||||
#
|
||||
# FIXME:
|
||||
# Add (A) sdram configuration
|
||||
# Add (B) flash cfi programming configuration
|
||||
#
|
||||
@@ -1,46 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#
|
||||
# Configuration script for ARM Musca-A development board
|
||||
#
|
||||
# For now we do not support Musca A flash programming using OpenOCD. However, a
|
||||
# work area is configured for flash programming speed up.
|
||||
#
|
||||
# GDB considers all memory as RAM unless target supplies a memory map.
|
||||
# OpenOCD will only send memory map if flash banks are configured. Otherwise,
|
||||
# configure GDB after connection by issuing following commands:
|
||||
# (gdb) mem 0x10200000 0x109FFFFF ro
|
||||
# (gdb) mem 0x00200000 0x009FFFFF ro
|
||||
# (gdb) set mem inaccessible-by-default off
|
||||
|
||||
# ARM Musca A board supports both JTAG and SWD transports.
|
||||
source [find target/swj-dp.tcl]
|
||||
|
||||
# set a safe JTAG clock speed, can be overridden
|
||||
adapter speed 1000
|
||||
|
||||
global _CHIPNAME
|
||||
if { [info exists CHIPNAME] } {
|
||||
set _CHIPNAME $CHIPNAME
|
||||
} else {
|
||||
set _CHIPNAME MUSCA_A
|
||||
}
|
||||
|
||||
if { [info exists CPUTAPID] } {
|
||||
set _CPUTAPID $CPUTAPID
|
||||
} else {
|
||||
set _CPUTAPID 0x6ba00477
|
||||
}
|
||||
|
||||
# Enable CPU1 debugging as a separate GDB target
|
||||
set _ENABLE_CPU1 1
|
||||
|
||||
# Musca A1 has 32KB SRAM banks. Override default work-area-size to 8KB per CPU
|
||||
set WORKAREASIZE_CPU0 0x2000
|
||||
set WORKAREASIZE_CPU1 0x2000
|
||||
|
||||
# Set SRAM bank 1 to be used for work area. Override here if needed.
|
||||
set WORKAREAADDR_CPU0 0x30008000
|
||||
set WORKAREAADDR_CPU1 0x3000A000
|
||||
|
||||
source [find target/arm_corelink_sse200.cfg]
|
||||
@@ -1,37 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#
|
||||
# Arty S7: Spartan7 25/50 FPGA Board for Makers and Hobbyists
|
||||
#
|
||||
# https://www.xilinx.com/products/boards-and-kits/1-pnziih.html
|
||||
# https://store.digilentinc.com/arty-s7-spartan-7-fpga-board-for-makers-and-hobbyists/
|
||||
|
||||
source [find interface/ftdi/digilent-hs1.cfg]
|
||||
|
||||
# Xilinx Spartan7-25/50 FPGA (XC7S{25,50}-CSGA324)
|
||||
source [find cpld/xilinx-xc7.cfg]
|
||||
source [find cpld/jtagspi.cfg]
|
||||
|
||||
adapter speed 25000
|
||||
|
||||
# Usage:
|
||||
#
|
||||
# Load Bitstream into FPGA:
|
||||
# openocd -f board/arty_s7.cfg -c "init;\
|
||||
# pld load 0 bitstream.bit;\
|
||||
# shutdown"
|
||||
#
|
||||
# Write Bitstream to Flash:
|
||||
# openocd -f board/arty_s7.cfg -c "init;\
|
||||
# jtagspi_init 0 bscan_spi_xc7s??.bit;\
|
||||
# jtagspi_program bitstream.bin 0;\
|
||||
# xc7_program xc7.tap;\
|
||||
# shutdown"
|
||||
#
|
||||
# jtagspi flash proxies can be found at:
|
||||
# https://github.com/quartiq/bscan_spi_bitstreams
|
||||
#
|
||||
# For the Spartan 50 variant, use
|
||||
# - https://github.com/quartiq/bscan_spi_bitstreams/raw/master/bscan_spi_xc7s50.bit
|
||||
# For the Spartan 25 variant, use
|
||||
# - https://github.com/quartiq/bscan_spi_bitstreams/raw/master/bscan_spi_xc7s25.bit
|
||||
@@ -1,17 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#
|
||||
# http://wikidevi.com/wiki/ASUS_RT-N16
|
||||
#
|
||||
|
||||
set partition_list {
|
||||
CFE { Bootloader 0xbc000000 0x00040000 }
|
||||
firmware { "Kernel+rootfs" 0xbc040000 0x01fa0000 }
|
||||
nvram { "Config space" 0xbdfe0000 0x00020000 }
|
||||
}
|
||||
|
||||
source [find target/bcm4718.cfg]
|
||||
|
||||
# External 32MB NOR Flash (Macronix MX29GL256EHTI2I-90Q)
|
||||
set _FLASHNAME $_CHIPNAME.flash
|
||||
flash bank $_FLASHNAME cfi 0xbc000000 0x02000000 1 1 $_TARGETNAME x16_as_x8
|
||||
@@ -1,21 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#
|
||||
# http://wikidevi.com/wiki/Asus_RT-N66U
|
||||
#
|
||||
|
||||
echo "ATTENTION: you need to solder a 4.7-10k pullup resistor to pin 21 of flash IC"
|
||||
echo "to enable JTAG, see http://wl500g.info/album.php?albumid=28&attachmentid=8991 ,"
|
||||
echo "there is an unpopulated footprint near U8.\n"
|
||||
|
||||
set partition_list {
|
||||
CFE { Bootloader 0xbc000000 0x00040000 }
|
||||
firmware { "Kernel+rootfs" 0xbc040000 0x01fa0000 }
|
||||
nvram { "Config space" 0xbdfe0000 0x00020000 }
|
||||
}
|
||||
|
||||
source [find target/bcm4706.cfg]
|
||||
|
||||
# External 32MB NOR Flash (Spansion S29GL256P10TF101
|
||||
set _FLASHNAME $_CHIPNAME.flash
|
||||
flash bank $_FLASHNAME cfi 0xbc000000 0x02000000 2 2 $_TARGETNAME
|
||||
@@ -1,165 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4394
|
||||
#
|
||||
# use combined on interfaces or targets that can't set TRST/SRST separately
|
||||
reset_config trst_and_srst srst_pulls_trst
|
||||
|
||||
if { [info exists CHIPNAME] } {
|
||||
set _CHIPNAME $CHIPNAME
|
||||
} else {
|
||||
set _CHIPNAME cap7
|
||||
}
|
||||
|
||||
if { [info exists ENDIAN] } {
|
||||
set _ENDIAN $ENDIAN
|
||||
} else {
|
||||
set _ENDIAN little
|
||||
}
|
||||
|
||||
if { [info exists CPUTAPID] } {
|
||||
set _CPUTAPID $CPUTAPID
|
||||
} else {
|
||||
set _CPUTAPID 0x40700f0f
|
||||
}
|
||||
|
||||
jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
|
||||
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME
|
||||
|
||||
$_TARGETNAME configure -event reset-start {
|
||||
# start off real slow when we're running off internal RC oscillator
|
||||
adapter speed 32
|
||||
}
|
||||
|
||||
proc peek32 {address} {
|
||||
return [read_memory $address 32 1]
|
||||
}
|
||||
|
||||
# Wait for an expression to be true with a timeout
|
||||
proc wait_state {expression} {
|
||||
for {set i 0} {$i < 1000} {set i [expr {$i + 1}]} {
|
||||
if {[uplevel 1 $expression] == 0} {
|
||||
return
|
||||
}
|
||||
}
|
||||
return -code 1 "Timed out"
|
||||
}
|
||||
|
||||
# Use a global variable here to be able to tinker interactively with
|
||||
# post reset jtag frequency.
|
||||
global post_reset_khz
|
||||
# Danger!!!! Even 16MHz kinda works with this target, but
|
||||
# it needs to be as low as 2000kHz to be stable.
|
||||
set post_reset_khz 2000
|
||||
|
||||
$_TARGETNAME configure -event reset-init {
|
||||
echo "Configuring master clock"
|
||||
# disable watchdog
|
||||
mww 0xfffffd44 0xff008000
|
||||
# enable user reset
|
||||
mww 0xfffffd08 0xa5000001
|
||||
# Enable main oscillator
|
||||
mww 0xFFFFFc20 0x00000f01
|
||||
wait_state {expr {([peek32 0xFFFFFC68] & 0x1) == 0}}
|
||||
|
||||
# Set PLLA to 96MHz
|
||||
mww 0xFFFFFc28 0x20072801
|
||||
wait_state {expr {([peek32 0xFFFFFC68] & 0x2) == 0}}
|
||||
|
||||
# Select prescaler
|
||||
mww 0xFFFFFC30 0x00000004
|
||||
wait_state {expr {([peek32 0xFFFFFC68] & 0x8) == 0}}
|
||||
|
||||
# Select master clock to 48MHz
|
||||
mww 0xFFFFFC30 0x00000006
|
||||
wait_state {expr {([peek32 0xFFFFFC68] & 0x8) == 0}}
|
||||
|
||||
echo "Master clock ok."
|
||||
|
||||
# Now that we're up and running, crank up speed!
|
||||
global post_reset_khz ; adapter speed $post_reset_khz
|
||||
|
||||
echo "Configuring the SDRAM controller..."
|
||||
|
||||
# Configure EBI Chip select for SDRAM
|
||||
mww 0xFFFFEF30 0x00000102
|
||||
|
||||
# Enable clock on EBI PIOs
|
||||
mww 0xFFFFFC10 0x00000004
|
||||
|
||||
# Configure PIO for SDRAM
|
||||
mww 0xFFFFF470 0xFFFF0000
|
||||
mww 0xFFFFF474 0x00000000
|
||||
mww 0xFFFFF404 0xFFFF0000
|
||||
|
||||
# Configure SDRAMC CR
|
||||
mww 0xFFFFEA08 0xA63392F9
|
||||
|
||||
# NOP command
|
||||
mww 0xFFFFEA00 0x1
|
||||
mww 0x20000000 0
|
||||
|
||||
# Precharge All Banks command
|
||||
mww 0xFFFFEA00 0x2
|
||||
mww 0x20000000 0
|
||||
|
||||
# Set 1st CBR
|
||||
mww 0xFFFFEA00 0x00000004
|
||||
mww 0x20000010 0x00000001
|
||||
|
||||
# Set 2nd CBR
|
||||
mww 0xFFFFEA00 0x00000004
|
||||
mww 0x20000020 0x00000002
|
||||
|
||||
# Set 3rd CBR
|
||||
mww 0xFFFFEA00 0x00000004
|
||||
mww 0x20000030 0x00000003
|
||||
|
||||
# Set 4th CBR
|
||||
mww 0xFFFFEA00 0x00000004
|
||||
mww 0x20000040 0x00000004
|
||||
|
||||
# Set 5th CBR
|
||||
mww 0xFFFFEA00 0x00000004
|
||||
mww 0x20000050 0x00000005
|
||||
|
||||
# Set 6th CBR
|
||||
mww 0xFFFFEA00 0x00000004
|
||||
mww 0x20000060 0x00000006
|
||||
|
||||
# Set 7th CBR
|
||||
mww 0xFFFFEA00 0x00000004
|
||||
mww 0x20000070 0x00000007
|
||||
|
||||
# Set 8th CBR
|
||||
mww 0xFFFFEA00 0x00000004
|
||||
mww 0x20000080 0x00000008
|
||||
|
||||
# Set LMR operation
|
||||
mww 0xFFFFEA00 0x00000003
|
||||
|
||||
# Perform LMR burst=1, lat=2
|
||||
mww 0x20000020 0xCAFEDEDE
|
||||
|
||||
# Set Refresh Timer
|
||||
mww 0xFFFFEA04 0x00000203
|
||||
|
||||
# Set Normal mode
|
||||
mww 0xFFFFEA00 0x00000000
|
||||
mww 0x20000000 0x00000000
|
||||
|
||||
#remap internal memory at address 0x0
|
||||
mww 0xffffef00 0x3
|
||||
|
||||
echo "SDRAM configuration ok."
|
||||
}
|
||||
|
||||
$_TARGETNAME configure -work-area-phys 0x00200000 -work-area-size 0x4000 -work-area-backup 0
|
||||
|
||||
arm7_9 dcc_downloads enable
|
||||
arm7_9 fast_memory_access enable
|
||||
|
||||
#set _FLASHNAME $_CHIPNAME.flash
|
||||
#flash bank $_FLASHNAME at91sam7 0 0 0 0 $_TARGETNAME 0 0 0 0 0 0 0 18432
|
||||
@@ -1,69 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#Script for AT91EB40a
|
||||
|
||||
# FIXME use some standard target config, maybe create one from this
|
||||
#
|
||||
# source [find target/...cfg]
|
||||
|
||||
if { [info exists CHIPNAME] } {
|
||||
set _CHIPNAME $CHIPNAME
|
||||
} else {
|
||||
set _CHIPNAME at91eb40a
|
||||
}
|
||||
|
||||
if { [info exists ENDIAN] } {
|
||||
set _ENDIAN $ENDIAN
|
||||
} else {
|
||||
set _ENDIAN little
|
||||
}
|
||||
|
||||
if { [info exists CPUTAPID] } {
|
||||
set _CPUTAPID $CPUTAPID
|
||||
} else {
|
||||
set _CPUTAPID 0x1f0f0f0f
|
||||
}
|
||||
|
||||
|
||||
#Atmel ties SRST & TRST together, at which point it makes
|
||||
#no sense to use TRST, but use TMS instead.
|
||||
#
|
||||
#The annoying thing with tying SRST & TRST together is that
|
||||
#there is no way to halt the CPU *before and during* the
|
||||
#SRST reset, which means that the CPU will run a number
|
||||
#of cycles before it can be halted(as much as milliseconds).
|
||||
reset_config srst_only srst_pulls_trst
|
||||
|
||||
#jtag scan chain
|
||||
jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
|
||||
|
||||
#target configuration
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME
|
||||
|
||||
# speed up memory downloads
|
||||
arm7_9 fast_memory_access enable
|
||||
arm7_9 dcc_downloads enable
|
||||
|
||||
#flash driver
|
||||
set _FLASHNAME $_CHIPNAME.flash
|
||||
flash bank $_FLASHNAME cfi 0x01000000 0x200000 2 2 $_TARGETNAME
|
||||
|
||||
# required for usable performance. Used for lots of
|
||||
# other things than flash programming.
|
||||
$_TARGETNAME configure -work-area-phys 0x00030000 -work-area-size 0x10000 -work-area-backup 0
|
||||
|
||||
$_TARGETNAME configure -event reset-init {
|
||||
echo "Running reset init script for AT91EB40A"
|
||||
# Reset script for AT91EB40a
|
||||
reg cpsr 0x000000D3
|
||||
mww 0xFFE00020 0x1
|
||||
mww 0xFFE00024 0x00000000
|
||||
mww 0xFFE00000 0x01002539
|
||||
mww 0xFFFFF124 0xFFFFFFFF
|
||||
mww 0xffff0010 0x100
|
||||
mww 0xffff0034 0x100
|
||||
}
|
||||
|
||||
# This target is pretty snappy...
|
||||
adapter speed 16000
|
||||
@@ -1,84 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#
|
||||
# This is for the "at91rm9200-DK" (not the EK) eval board.
|
||||
#
|
||||
# The two are probably very simular.... I have DK...
|
||||
#
|
||||
# It has atmel at91rm9200 chip.
|
||||
source [find target/at91rm9200.cfg]
|
||||
|
||||
reset_config trst_and_srst
|
||||
|
||||
$_TARGETNAME configure -event gdb-attach { reset init }
|
||||
$_TARGETNAME configure -event reset-init { at91rm9200_dk_init }
|
||||
|
||||
#flash bank <name> <driver> <base> <size> <chip_width> <bus_width> <target>
|
||||
set _FLASHNAME $_CHIPNAME.flash
|
||||
flash bank $_FLASHNAME cfi 0x10000000 0x00200000 2 2 $_TARGETNAME
|
||||
|
||||
|
||||
proc at91rm9200_dk_init { } {
|
||||
# Try to run at 1khz... Yea, that slow!
|
||||
# Chip is really running @ 32khz
|
||||
adapter speed 8
|
||||
|
||||
mww 0xfffffc64 0xffffffff
|
||||
## disable all clocks but system clock
|
||||
mww 0xfffffc04 0xfffffffe
|
||||
## disable all clocks to pioa and piob
|
||||
mww 0xfffffc14 0xffffffc3
|
||||
## master clock = slow cpu = slow
|
||||
## (means the CPU is running at 32khz!)
|
||||
mww 0xfffffc30 0
|
||||
## main osc enable
|
||||
mww 0xfffffc20 0x0000ff01
|
||||
## program pllA
|
||||
mww 0xfffffc28 0x20263e04
|
||||
## program pllB
|
||||
mww 0xfffffc2c 0x10483e0e
|
||||
## let pll settle... sleep 100msec
|
||||
sleep 100
|
||||
## switch to fast clock
|
||||
mww 0xfffffc30 0x202
|
||||
## Sleep some - (go read)
|
||||
sleep 100
|
||||
|
||||
#========================================
|
||||
# CPU now runs at 180mhz
|
||||
# SYS runs at 60mhz.
|
||||
adapter speed 40000
|
||||
#========================================
|
||||
|
||||
|
||||
## set memc for all memories
|
||||
mww 0xffffff60 0x02
|
||||
## program smc controller
|
||||
mww 0xffffff70 0x3284
|
||||
## init sdram
|
||||
mww 0xffffff98 0x7fffffd0
|
||||
## all banks precharge
|
||||
mww 0xffffff80 0x02
|
||||
## touch sdram chip to make it work
|
||||
mww 0x20000000 0
|
||||
## sdram controller mode register
|
||||
mww 0xffffff90 0x04
|
||||
mww 0x20000000 0
|
||||
mww 0x20000000 0
|
||||
mww 0x20000000 0
|
||||
mww 0x20000000 0
|
||||
mww 0x20000000 0
|
||||
mww 0x20000000 0
|
||||
mww 0x20000000 0
|
||||
mww 0x20000000 0
|
||||
## sdram controller mode register
|
||||
## Refresh, etc....
|
||||
mww 0xffffff90 0x03
|
||||
mww 0x20000080 0
|
||||
mww 0xffffff94 0x1f4
|
||||
mww 0x20000080 0
|
||||
mww 0xffffff90 0x10
|
||||
mww 0x20000000 0
|
||||
mww 0xffffff00 0x01
|
||||
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#
|
||||
# Copyright 2010 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
|
||||
#
|
||||
# under GPLv2 Only
|
||||
#
|
||||
# This is for the "at91rm9200-ek" eval board.
|
||||
#
|
||||
#
|
||||
# It has atmel at91rm9200 chip.
|
||||
source [find target/at91rm9200.cfg]
|
||||
|
||||
reset_config trst_and_srst
|
||||
|
||||
$_TARGETNAME configure -event gdb-attach { reset init }
|
||||
$_TARGETNAME configure -event reset-init { at91rm9200_ek_init }
|
||||
|
||||
## flash bank <name> <driver> <base> <size> <chip_width> <bus_width> <target>
|
||||
set _FLASHNAME $_CHIPNAME.flash
|
||||
flash bank $_FLASHNAME cfi 0x10000000 0x00800000 2 2 $_TARGETNAME
|
||||
|
||||
# The chip may run @ 32khz, so set a really low JTAG speed
|
||||
adapter speed 8
|
||||
|
||||
proc at91rm9200_ek_init { } {
|
||||
# Try to run at 1khz... Yea, that slow!
|
||||
# Chip is really running @ 32khz
|
||||
adapter speed 8
|
||||
|
||||
mww 0xfffffc64 0xffffffff
|
||||
## disable all clocks but system clock
|
||||
mww 0xfffffc04 0xfffffffe
|
||||
## disable all clocks to pioa and piob
|
||||
mww 0xfffffc14 0xffffffc3
|
||||
## master clock = slow cpu = slow
|
||||
## (means the CPU is running at 32khz!)
|
||||
mww 0xfffffc30 0
|
||||
## main osc enable
|
||||
mww 0xfffffc20 0x0000ff01
|
||||
## MC_PUP
|
||||
mww 0xFFFFFF50 0x00000000
|
||||
## MC_PUER: Memory controller protection unit disable
|
||||
mww 0xFFFFFF54 0x00000000
|
||||
## EBI_CFGR
|
||||
mww 0xFFFFFF64 0x00000000
|
||||
## SMC2_CSR[0]: 16bit, 2 TDF, 4 WS
|
||||
mww 0xFFFFFF70 0x00003284
|
||||
|
||||
## Init Clocks
|
||||
## CKGR_PLLAR
|
||||
mww 0xFFFFFC28 0x2000BF05
|
||||
## PLLAR: 179,712000 MHz for PCK
|
||||
mww 0xFFFFFC28 0x20263E04
|
||||
sleep 100
|
||||
## PMC_MCKR
|
||||
mww 0xFFFFFC30 0x00000100
|
||||
sleep 100
|
||||
## ;MCKR : PCK/3 = MCK Master Clock = 59,904000MHz from PLLA
|
||||
mww 0xFFFFFC30 0x00000202
|
||||
sleep 100
|
||||
|
||||
#========================================
|
||||
# CPU now runs at 180mhz
|
||||
# SYS runs at 60mhz.
|
||||
adapter speed 40000
|
||||
#========================================
|
||||
|
||||
## Init SDRAM
|
||||
## PIOC_ASR: Configure PIOC as peripheral (D16/D31)
|
||||
mww 0xFFFFF870 0xFFFF0000
|
||||
## PIOC_BSR:
|
||||
mww 0xFFFFF874 0x00000000
|
||||
## PIOC_PDR:
|
||||
mww 0xFFFFF804 0xFFFF0000
|
||||
## EBI_CSA : CS1=SDRAM
|
||||
mww 0xFFFFFF60 0x00000002
|
||||
## EBI_CFGR:
|
||||
mww 0xFFFFFF64 0x00000000
|
||||
## SDRC_CR :
|
||||
mww 0xFFFFFF98 0x2188c155
|
||||
## SDRC_MR : Precharge All
|
||||
mww 0xFFFFFF90 0x00000002
|
||||
## access SDRAM
|
||||
mww 0x20000000 0x00000000
|
||||
## SDRC_MR : Refresh
|
||||
mww 0xFFFFFF90 0x00000004
|
||||
## access SDRAM
|
||||
mww 0x20000000 0x00000000
|
||||
## access SDRAM
|
||||
mww 0x20000000 0x00000000
|
||||
## access SDRAM
|
||||
mww 0x20000000 0x00000000
|
||||
## access SDRAM
|
||||
mww 0x20000000 0x00000000
|
||||
## access SDRAM
|
||||
mww 0x20000000 0x00000000
|
||||
## access SDRAM
|
||||
mww 0x20000000 0x00000000
|
||||
## access SDRAM
|
||||
mww 0x20000000 0x00000000
|
||||
## access SDRAM
|
||||
mww 0x20000000 0x00000000
|
||||
## SDRC_MR : Load Mode Register
|
||||
mww 0xFFFFFF90 0x00000003
|
||||
## access SDRAM
|
||||
mww 0x20000080 0x00000000
|
||||
## SDRC_TR : Write refresh rate
|
||||
mww 0xFFFFFF94 0x000002E0
|
||||
## access SDRAM
|
||||
mww 0x20000000 0x00000000
|
||||
## SDRC_MR : Normal Mode
|
||||
mww 0xFFFFFF90 0x00000000
|
||||
## access SDRAM
|
||||
mww 0x20000000 0x00000000
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
################################################################################
|
||||
# Atmel AT91SAM9261-EK eval board
|
||||
################################################################################
|
||||
|
||||
source [find mem_helper.tcl]
|
||||
source [find target/at91sam9261.cfg]
|
||||
uplevel #0 [list source [find chip/atmel/at91/hardware.cfg]]
|
||||
uplevel #0 [list source [find chip/atmel/at91/at91sam9261.cfg]]
|
||||
uplevel #0 [list source [find chip/atmel/at91/at91sam9261_matrix.cfg]]
|
||||
uplevel #0 [list source [find chip/atmel/at91/at91sam9_init.cfg]]
|
||||
|
||||
# By default S1 is open and this means that NTRST is not connected.
|
||||
# The reset_config in target/at91sam9261.cfg is overridden here.
|
||||
# (or S1 must be populated with a 0 Ohm resistor)
|
||||
reset_config srst_only
|
||||
|
||||
scan_chain
|
||||
$_TARGETNAME configure -event gdb-attach { reset init }
|
||||
$_TARGETNAME configure -event reset-init { at91sam9261ek_reset_init }
|
||||
$_TARGETNAME configure -event reset-start { at91sam9_reset_start }
|
||||
|
||||
proc at91sam9261ek_reset_init { } {
|
||||
|
||||
;# for ppla at 199 Mhz
|
||||
set config(master_pll_div) 15
|
||||
set config(master_pll_mul) 162
|
||||
|
||||
;# for ppla at 239 Mhz
|
||||
;# set master_pll_div 1
|
||||
;# set master_pll_mul 13
|
||||
|
||||
set val $::AT91_WDT_WDV ;# Counter Value
|
||||
set val [expr {$val | $::AT91_WDT_WDDIS}] ;# Watchdog Disable
|
||||
set val [expr {$val | $::AT91_WDT_WDD}] ;# Delta Value
|
||||
set val [expr {$val | $::AT91_WDT_WDDBGHLT}] ;# Debug Halt
|
||||
set val [expr {$val | $::AT91_WDT_WDIDLEHLT}] ;# Idle Halt
|
||||
|
||||
set config(wdt_mr_val) $val
|
||||
|
||||
;# EBI_CSA, no pull-ups for D[15:0], CS1 SDRAM, CS3 NAND Flash
|
||||
set config(matrix_ebicsa_addr) $::AT91_MATRIX_EBICSA
|
||||
set config(matrix_ebicsa_val) [expr {$::AT91_MATRIX_DBPUC | $::AT91_MATRIX_CS1A_SDRAMC}]
|
||||
|
||||
;# SDRAMC_CR - Configuration register
|
||||
set val $::AT91_SDRAMC_NC_9
|
||||
set val [expr {$val | $::AT91_SDRAMC_NR_13}]
|
||||
set val [expr {$val | $::AT91_SDRAMC_NB_4}]
|
||||
set val [expr {$val | $::AT91_SDRAMC_CAS_3}]
|
||||
set val [expr {$val | $::AT91_SDRAMC_DBW_32}]
|
||||
set val [expr {$val | (2 << 8)}] ;# Write Recovery Delay
|
||||
set val [expr {$val | (7 << 12)}] ;# Row Cycle Delay
|
||||
set val [expr {$val | (3 << 16)}] ;# Row Precharge Delay
|
||||
set val [expr {$val | (2 << 20)}] ;# Row to Column Delay
|
||||
set val [expr {$val | (5 << 24)}] ;# Active to Precharge Delay
|
||||
set val [expr {$val | (8 << 28)}] ;# Exit Self Refresh to Active Delay
|
||||
|
||||
set config(sdram_cr_val) $val
|
||||
|
||||
set config(sdram_tr_val) 0x13c
|
||||
|
||||
set config(sdram_base) $::AT91_CHIPSELECT_1
|
||||
at91sam9_reset_init $config
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user