diff --git a/.project b/.project
new file mode 100644
index 00000000..3fd72c24
--- /dev/null
+++ b/.project
@@ -0,0 +1,11 @@
+
+
+ OpenFFBoard
+
+
+
+
+
+
+
+
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
new file mode 100644
index 00000000..bd126997
--- /dev/null
+++ b/.vscode/c_cpp_properties.json
@@ -0,0 +1,18 @@
+{
+ "configurations": [
+ {
+ "name": "windows-gcc-x64",
+ "includePath": [
+ "${workspaceFolder}/**"
+ ],
+ "compilerPath": "C:/msys64/mingw64/bin/gcc.exe",
+ "cStandard": "${default}",
+ "cppStandard": "${default}",
+ "intelliSenseMode": "windows-gcc-x64",
+ "compilerArgs": [
+ ""
+ ]
+ }
+ ],
+ "version": 4
+}
\ No newline at end of file
diff --git a/.vscode/cmake-kits.json b/.vscode/cmake-kits.json
new file mode 100644
index 00000000..a2353c93
--- /dev/null
+++ b/.vscode/cmake-kits.json
@@ -0,0 +1,11 @@
+[
+ {
+ "name": "GCC for ARM Embedded",
+ "compilers": {
+ "C": "C:/Program Files (x86)/Arm/GNU Toolchain mingw-w64-i686-arm-none-eabi/bin/arm-none-eabi-gcc.exe",
+ "CXX": "C:/Program Files (x86)/Arm/GNU Toolchain mingw-w64-i686-arm-none-eabi/bin/arm-none-eabi-g++.exe"
+ },
+ "isTrusted": true,
+ "keep": true
+ }
+]
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 00000000..6a67e84f
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,24 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "C/C++ Runner: Debug Session",
+ "type": "cppdbg",
+ "request": "launch",
+ "args": [],
+ "stopAtEntry": false,
+ "externalConsole": true,
+ "cwd": "c:/Users/gorkem/OpenFFBoard/Firmware/FFBoard/Src",
+ "program": "c:/Users/gorkem/OpenFFBoard/Firmware/FFBoard/Src/build/Debug/outDebug",
+ "MIMode": "gdb",
+ "miDebuggerPath": "gdb",
+ "setupCommands": [
+ {
+ "description": "Enable pretty-printing for gdb",
+ "text": "-enable-pretty-printing",
+ "ignoreFailures": true
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 00000000..b4bbaabb
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,68 @@
+{
+ "cmake.additionalKits": [
+ "${workspaceFolder}/.vscode/cmake-kits.json"
+ ],
+ "cmake.configureOnOpen": true,
+ "files.associations": {
+ "*.h": "c",
+ "*.c": "c",
+ "*.cpp": "cpp"
+ },
+ "C_Cpp_Runner.cCompilerPath": "gcc",
+ "C_Cpp_Runner.cppCompilerPath": "g++",
+ "C_Cpp_Runner.debuggerPath": "gdb",
+ "C_Cpp_Runner.cStandard": "",
+ "C_Cpp_Runner.cppStandard": "",
+ "C_Cpp_Runner.msvcBatchPath": "C:/Program Files/Microsoft Visual Studio/VR_NR/Community/VC/Auxiliary/Build/vcvarsall.bat",
+ "C_Cpp_Runner.useMsvc": false,
+ "C_Cpp_Runner.warnings": [
+ "-Wall",
+ "-Wextra",
+ "-Wpedantic",
+ "-Wshadow",
+ "-Wformat=2",
+ "-Wcast-align",
+ "-Wconversion",
+ "-Wsign-conversion",
+ "-Wnull-dereference"
+ ],
+ "C_Cpp_Runner.msvcWarnings": [
+ "/W4",
+ "/permissive-",
+ "/w14242",
+ "/w14287",
+ "/w14296",
+ "/w14311",
+ "/w14826",
+ "/w44062",
+ "/w44242",
+ "/w14905",
+ "/w14906",
+ "/w14263",
+ "/w44265",
+ "/w14928"
+ ],
+ "C_Cpp_Runner.enableWarnings": true,
+ "C_Cpp_Runner.warningsAsError": false,
+ "C_Cpp_Runner.compilerArgs": [],
+ "C_Cpp_Runner.linkerArgs": [],
+ "C_Cpp_Runner.includePaths": [],
+ "C_Cpp_Runner.includeSearch": [
+ "*",
+ "**/*"
+ ],
+ "C_Cpp_Runner.excludeSearch": [
+ "**/build",
+ "**/build/**",
+ "**/.*",
+ "**/.*/**",
+ "**/.vscode",
+ "**/.vscode/**"
+ ],
+ "C_Cpp_Runner.useAddressSanitizer": false,
+ "C_Cpp_Runner.useUndefinedSanitizer": false,
+ "C_Cpp_Runner.useLeakSanitizer": false,
+ "C_Cpp_Runner.showCompilationTime": false,
+ "C_Cpp_Runner.useLinkTimeOptimization": false,
+ "C_Cpp_Runner.msvcSecureNoWarnings": false
+}
\ No newline at end of file
diff --git a/Firmware/FFBoard/Inc/EffectsCalculator.h b/Firmware/FFBoard/Inc/EffectsCalculator.h
index e065c033..7b03b734 100644
--- a/Firmware/FFBoard/Inc/EffectsCalculator.h
+++ b/Firmware/FFBoard/Inc/EffectsCalculator.h
@@ -60,6 +60,7 @@ enum class EffectsCalculator_commands : uint32_t {
damper_f, damper_q, friction_f, friction_q, inertia_f, inertia_q, filterProfileId,
frictionPctSpeedToRampup,
monitorEffect, effectsDetails, effectsForces,
+ safetyLimit, safetyDamping,
};
class EffectsCalculator: public PersistentStorage,
@@ -115,7 +116,9 @@ class EffectsCalculator: public PersistentStorage,
uint8_t global_gain = 0xff;
effect_gain_t gain;
effect_scaler_t scaler;
- uint8_t frictionPctSpeedToRampup = 25; // define the max value of the range (0..5% of maxspeed) where torque is rampup on friction
+ uint8_t frictionPctSpeedToRampup = 25;
+ uint16_t safetySpeedLimit = 20000; // default limit 2
+ uint8_t safetyDamping = 5; // default damping
// FFB status
bool effects_active = false; // If FFB is on
diff --git a/Firmware/FFBoard/Src/EffectsCalculator.cpp b/Firmware/FFBoard/Src/EffectsCalculator.cpp
index 688afb25..8c44ad18 100644
--- a/Firmware/FFBoard/Src/EffectsCalculator.cpp
+++ b/Firmware/FFBoard/Src/EffectsCalculator.cpp
@@ -49,6 +49,8 @@ EffectsCalculator::EffectsCalculator() : CommandHandler("fx", CLSID_EFFECTSCALC)
registerCommand("filterProfile_id", EffectsCalculator_commands::filterProfileId, "Conditional effects filter profile: 0 default; 1 custom", CMDFLAG_GET | CMDFLAG_SET);
registerCommand("frictionPctSpeedToRampup", EffectsCalculator_commands::frictionPctSpeedToRampup, "% of max speed for gradual increase", CMDFLAG_GET | CMDFLAG_SET);
+ registerCommand("safetyLimit", EffectsCalculator_commands::safetyLimit, "Safety Cutoff Speed (0=Off)", CMDFLAG_GET | CMDFLAG_SET);
+ registerCommand("safetyDamping", EffectsCalculator_commands::safetyDamping, "Safety Damping Factor", CMDFLAG_GET | CMDFLAG_SET);
//this->Start(); // Enable if we want to periodically monitor
}
@@ -150,8 +152,35 @@ void EffectsCalculator::calculateEffects(std::vector> &axe
// Apply summed force to axes
for(uint8_t i=0 ; i < axisCount ; i++)
{
- int32_t force = clip(forces[i], -0x7fff, 0x7fff); // Clip
- axes[i]->setEffectTorque(force);
+ int32_t finalForce = forces[i];
+
+ // --- meadhours CONFIGURABLE HAND SAFETY PATCH START ---
+
+ // if limit value 0, off
+ if (this->safetySpeedLimit > 0) {
+
+ float currentVel = 0.0f;
+ metric_t *metrics = axes[i]->getMetrics();
+
+ if (metrics != nullptr) {
+ currentVel = metrics->speed;
+ }
+
+ // speed control
+ if (abs(currentVel) > this->safetySpeedLimit) {
+
+ // killswitch
+ finalForce = 0;
+
+ // active damping
+ float dampingFactor = (float)this->safetyDamping / 10.0f;
+ float dampingForce = -1.0f * currentVel * dampingFactor;
+ finalForce = (int32_t)dampingForce;
+ }
+ }
+
+ int32_t clippedForce = clip(finalForce, -0x7fff, 0x7fff);
+ axes[i]->setEffectTorque(clippedForce);
}
effects_statslast = effects_stats;
@@ -934,6 +963,22 @@ CommandStatus EffectsCalculator::command(const ParsedCommand& cmd,std::vectorsafetySpeedLimit);
+ } else if (cmd.type == CMDtype::set) {
+ this->safetySpeedLimit = cmd.val;
+ }
+ break;
+
+ case EffectsCalculator_commands::safetyDamping:
+ if (cmd.type == CMDtype::get) {
+ replies.emplace_back(this->safetyDamping);
+ } else if (cmd.type == CMDtype::set) {
+ this->safetyDamping = clip(cmd.val, 0, 100);
+ }
+ break;
+
default:
return CommandStatus::NOT_FOUND;
}