Skip to content

Commit c4c1d08

Browse files
committed
fix: fix the denormalisation issue in calculateFFBTorque. Optimize the struct from 64 to 32b to reduce load.
1 parent ae2d1e4 commit c4c1d08

3 files changed

Lines changed: 38 additions & 40 deletions

File tree

Firmware/FFBoard/Inc/Axis.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ class Axis : public PersistentStorage, public CommandHandler, public ErrorHandle
349349
* @brief Calculates the FFB torque exponential torque, from the input torque and apply expo and scaler
350350
* @return The calculated exponential torque.
351351
*/
352-
int64_t calculateFFBTorque();
352+
int32_t calculateFFBTorque();
353353

354354
/**
355355
* @brief Starts a force fade-in.
@@ -364,7 +364,7 @@ class Axis : public PersistentStorage, public CommandHandler, public ErrorHandle
364364
* @brief Sets the FFB effect torque.
365365
* @param torque The new FFB effect torque from the EffectsCalculator.
366366
*/
367-
void setFfbEffectTorque(int64_t torque);
367+
void setFfbEffectTorque(int32_t torque);
368368

369369
/**
370370
* @brief Updates the total torque.
@@ -431,12 +431,12 @@ class Axis : public PersistentStorage, public CommandHandler, public ErrorHandle
431431
* @param torque A reference to the torque value to be modified.
432432
* @return torque update to apply to reduced de speed.
433433
*/
434-
int64_t applySpeedLimiterTorque(int64_t& torque);
434+
int32_t applySpeedLimiterTorque(int32_t& torque);
435435
/**
436436
* @brief Applies the torque slew rate limiter to the torque.
437437
* @param torque A reference to the torque value to be modified.
438438
*/
439-
void applyTorqueSlewRateLimiter(int64_t& torque);
439+
void applyTorqueSlewRateLimiter(int32_t& torque);
440440
/**
441441
* @brief Decodes the axis configuration from a 16-bit integer stored in flash.
442442
* @param val The 16-bit encoded configuration value.
@@ -495,7 +495,7 @@ class Axis : public PersistentStorage, public CommandHandler, public ErrorHandle
495495
float previousFrameSpeed = 0; //!< Instantaneous speed from the last cycle, used for acceleration calculation.
496496

497497
// Torque components
498-
int64_t ffbEffectTorque = 0; //!< Torque from HID FFB effects.
498+
int32_t ffbEffectTorque = 0; //!< Torque from HID FFB effects.
499499
int32_t mechanicalEffectTorque = 0; //!< Torque from mechanical effects (damper, friction, inertia).
500500

501501
// Power and scaling

Firmware/FFBoard/Src/Axis.cpp

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -780,36 +780,34 @@ uint16_t Axis::getPower(){
780780
/**
781781
* Calculates an exponential torque correction curve and scale for FFBEffect
782782
*/
783-
int64_t Axis::calculateFFBTorque(){
783+
int32_t Axis::calculateFFBTorque(){
784784

785-
// Apply equalizer
786-
float filtered_torque = this->ffbEffectTorque;
785+
// 1. Initial conversion and normalization
786+
// Convert to float and move to [-1.0, 1.0] range immediately.
787+
float torque = (float)this->ffbEffectTorque * (1.0f / 32767.0f);
787788

789+
// 2. Game Clipping detection
790+
// Performed on normalized value for consistency.
791+
if(fabsf(torque) >= 1.0f){
792+
pulseClipLed(); // Visual alert: game signal is clipping
793+
}
794+
795+
// 3. Apply equalizer
796+
// Standardized DSP processing on [-1.0, 1.0] range.
788797
if(equalizerEnabled){
789798
for (uint8_t i = 0; i < num_eq_bands; ++i) {
790-
filtered_torque = eqFilters[i].process(filtered_torque);
799+
torque = eqFilters[i].process(torque);
791800
}
792801
}
793802

794-
// Game effects. Down and up-scaling may introduce float artifacts. Do this before scaling down.
795-
float torque = (float)filtered_torque / (float)0x7fff;
796-
797-
// 1. Game Clipping detection
798-
// If the game sends more than the theoretical maximum (+/- 32767), the signal is clipped at the source.
799-
if(abs(torque) >= 0x7fff){
800-
pulseClipLed(); // Visual alert: game signal is clipping
801-
}
802-
803-
// 2. Apply Expo (Linearization or sensation curve)
804-
if(expo != 1){
803+
// 4. Apply Expo (Linearization or sensation curve)
804+
if(expo != 1.0f){
805805
torque = calculateExpoTorque(torque);
806806
}
807807

808-
// 3. Game specific gain (effectRatioScaler)
809-
// Scale the FFB from game only (allows lowering game effects without lowering endstops)
810-
torque = (int64_t)((float)torque * effectRatioScaler);
811-
812-
return torque;
808+
// 5. Final scaling and single conversion back to integer
809+
// Apply both the FFB range and the effect ratio in one final step.
810+
return (int32_t)(torque * 32767.0f * effectRatioScaler);
813811
}
814812

815813
int32_t Axis::getTorque() { return metric.current.torque; } // Fix: move from previous to current
@@ -834,7 +832,7 @@ int32_t Axis::calculateEndstopTorque(){
834832
return clip<int32_t,int32_t>(endstopTorque,-0x7fff,0x7fff);
835833
}
836834

837-
void Axis::setFfbEffectTorque(int64_t torque) {
835+
void Axis::setFfbEffectTorque(int32_t torque) {
838836
this->ffbEffectTorque = torque;
839837
}
840838

@@ -846,7 +844,7 @@ bool Axis::updateTorque(int32_t* totalTorque) {
846844

847845
// STEP 1: Process FFB torque from the game (via helper function)
848846
// (Reconstructed by CMSIS Spline, Expo applied, and scaled by FFB ratio)
849-
int64_t torque = calculateFFBTorque();
847+
int32_t torque = calculateFFBTorque();
850848

851849
// STEP 2: Mix in local mechanical effects
852850
// (Damper, Friction, Inertia generated locally at high frequency)
@@ -859,7 +857,7 @@ bool Axis::updateTorque(int32_t* totalTorque) {
859857

860858
// STEP 4: Master Volume Scaling
861859
// Map the virtual signal (+/- 32767) to the physical power limit ("power")
862-
torque = (int64_t)((float)torque * torqueScaler);
860+
torque = (int32_t)((float)torque * torqueScaler);
863861

864862
// STEP 5: Safety limits (Fade-in, Out of bounds)
865863
// Applied BEFORE dynamic limiters so that abrupt cuts are smoothed by the Slew Rate.
@@ -870,7 +868,7 @@ bool Axis::updateTorque(int32_t* totalTorque) {
870868
// Apply a fade-in effect for a smooth force ramp-up on startup or recovery.
871869
// Increases forceFadeMultiplier progressively based on forceFadeDuration and sample rate.
872870
if(forceFadeMultiplier < 1.0f){
873-
torque = (int64_t)((float)torque * forceFadeMultiplier);
871+
torque = (int32_t)((float)torque * forceFadeMultiplier);
874872
forceFadeMultiplier += forceFadeDuration / this->filter_f;
875873
}
876874

@@ -904,7 +902,7 @@ bool Axis::updateTorque(int32_t* totalTorque) {
904902
}
905903

906904

907-
void Axis::applyTorqueSlewRateLimiter(int64_t& torque)
905+
void Axis::applyTorqueSlewRateLimiter(int32_t& torque)
908906
{
909907
// Limits the rate of change of the torque (slew rate), to smooths out sudden changes in torque.
910908
// Essential for a natural feel and to prevent "clanking" noises.
@@ -913,14 +911,14 @@ void Axis::applyTorqueSlewRateLimiter(int64_t& torque)
913911
}
914912

915913
// This prevents sudden torque jumps, resulting in a smoother feel.
916-
const int64_t previousTorque = metric.previous.torque;
917-
const int64_t maxTorqueChange = maxTorqueRateMS;
914+
const int32_t previousTorque = metric.previous.torque;
915+
const int32_t maxTorqueChange = maxTorqueRateMS;
918916

919917
// The torque is clipped to be within the range of [previous torque - limit, previous torque + limit].
920-
torque = clip<int64_t>(torque, previousTorque - maxTorqueChange, previousTorque + maxTorqueChange);
918+
torque = clip<int32_t>(torque, previousTorque - maxTorqueChange, previousTorque + maxTorqueChange);
921919
}
922920

923-
int64_t Axis::applySpeedLimiterTorque(int64_t& torque){
921+
int32_t Axis::applySpeedLimiterTorque(int32_t& torque){
924922
// Speed Limiter: A PI controller to reduce torque when speed exceeds maxSpeedDegS.
925923
// The limiter only acts when torque is applied in the direction of movement.
926924

@@ -929,7 +927,7 @@ int64_t Axis::applySpeedLimiterTorque(int64_t& torque){
929927
return 0;
930928
}
931929

932-
int64_t resultTorque = 0;
930+
int32_t resultTorque = 0;
933931

934932
#ifdef USE_DSP_FUNCTIONS
935933
float effectiveSpeed = metric.current.speed * (torque > 0 ? 1.0f : -1.0f);
@@ -946,9 +944,9 @@ int64_t Axis::applySpeedLimiterTorque(int64_t& torque){
946944
// We must only reduce the magnitude of the torque, not invert it.
947945
reductionAmount = clip(reductionAmount, 0.0f, fabsf((float)torque));
948946
if(torque > 0) {
949-
resultTorque = reductionAmount;
947+
resultTorque = (int32_t)reductionAmount;
950948
} else {
951-
resultTorque = -reductionAmount;
949+
resultTorque = (int32_t)-reductionAmount;
952950
}
953951
} else {
954952
arm_pid_reset_f32(&speedLimiterPID); // Reset PID if not active
@@ -963,9 +961,9 @@ int64_t Axis::applySpeedLimiterTorque(int64_t& torque){
963961
// Only reduce torque. Don't invert it to prevent oscillation
964962
float torqueReduction = speedreducer * speedLimiterP + speedLimitReducerI;// accreducer * 0.025 + acclimitreducerI
965963
if(torque > 0){
966-
resultTorque = clip<float,int64_t>(torqueReduction,0,torque);
964+
resultTorque = (int32_t)clip<float,int32_t>(torqueReduction,0,torque);
967965
}else{
968-
resultTorque = clip<float,int64_t>(-torqueReduction,torque,0);
966+
resultTorque = (int32_t)clip<float,int32_t>(-torqueReduction,torque,0);
969967
}
970968
#endif
971969

Firmware/FFBoard/Src/EffectsCalculator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ An inertia condition uses axis acceleration as the metric.
108108
void EffectsCalculator::calculateEffects(std::vector<std::unique_ptr<Axis>> &axes)
109109
{
110110
int axisCount = axes.size();
111-
int64_t forces[MAX_AXIS] = {0};
111+
int32_t forces[MAX_AXIS] = {0};
112112

113113
if(isActive()){
114114
int32_t force = 0;

0 commit comments

Comments
 (0)