Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
f7114aa
Command interface buffer size changes
Ultrawipf Aug 26, 2024
b33edde
SPI allow speed range
Ultrawipf Sep 28, 2023
fd7c1b3
Task delay in i2c eeprom
Ultrawipf Oct 21, 2023
a6aa0e1
Dynamic biss-c speed presets
Ultrawipf Oct 23, 2023
7b99444
Add force erase flag for debugging
Ultrawipf Dec 8, 2023
ca8468f
Set initial spi device config to actual current port config
Ultrawipf Jan 23, 2024
67fb5fd
Add analog encoder cal skip option
Ultrawipf Jan 30, 2024
f940e34
.gitignore added Debug
Ultrawipf Feb 7, 2024
4dd799e
TMC4671 restructured hw conf constants
Ultrawipf Feb 20, 2024
6fbe1a5
TMC allow autotuning I term definition
Ultrawipf Feb 22, 2024
ed65676
Commandhandler split register command template and prepared overriding
Ultrawipf Feb 22, 2024
5febed3
Make FFB capable axes optionally report 32b gamepad values
Ultrawipf Feb 26, 2024
785a4f5
Allow changing FFB update rates
Ultrawipf Mar 4, 2024
c2f784e
Added tasklist
Ultrawipf Mar 6, 2024
862b383
Periodic effect sampling using microsecond counter
Ultrawipf Mar 6, 2024
ffde94f
Corrected tmc hw config defines
Ultrawipf Mar 6, 2024
b4497d5
TMC4671 corrected brake pin settings.
Ultrawipf Mar 12, 2024
b9aeefe
Removed micros timer from canbridge
Ultrawipf Mar 19, 2024
2e368c3
Default ffb rate option
Ultrawipf Mar 19, 2024
8a4683f
Axis always returns a 32b value. mainclass does the scaling in 16b mode.
Ultrawipf Apr 2, 2024
29ddbd3
Prepared usb descriptor splitting.
Ultrawipf Apr 2, 2024
2b47451
Split HID gamepad report buffer into helper class
Ultrawipf Apr 4, 2024
3c02223
Cleanup
Ultrawipf Apr 8, 2024
bca95eb
I2C eeprom using port class.
Ultrawipf Apr 16, 2024
e67f11f
TMC check if motor is set before encoder init
Ultrawipf Apr 23, 2024
9843a8f
FFBWheel supporting variable range in 32b desc mode
Ultrawipf Apr 29, 2024
d396f62
HID command interface using reference in loop
Ultrawipf Apr 29, 2024
da0b439
Fixed first 16b axis being scaled incorrectly
Ultrawipf May 3, 2024
f616395
Axis updates friction and inertia filters on samplerate change
Ultrawipf Jun 14, 2024
1cda177
Allow overriding flash defaults. Requires >CPP20
Ultrawipf Aug 26, 2024
15ae944
Wait at least 1ms if no TIM_FFB defined
Ultrawipf Feb 10, 2025
ce15222
TMC4671 fix ext encoder timer not starting
Ultrawipf Feb 26, 2025
6026b4c
TMC4671 make ext enc timer ARR a define
Ultrawipf Feb 26, 2025
c1dc72c
Fixed timerless FFB updating waiting 1ms too long
Ultrawipf Jan 10, 2026
af7885f
Enabled TIM_FFB for F407VG target
Ultrawipf Jan 10, 2026
8d49485
Enable freertos task formatting for F407VG
Ultrawipf Jan 15, 2026
0d9c851
Write task info directly into string buffer
Ultrawipf Jan 15, 2026
4aaecc5
Fix SPI_Buttons constructor procedure (#164)
dracc Jan 16, 2026
cf7dd4d
Version bump 1.16.7
Ultrawipf Jan 18, 2026
1b07468
MT6835 corrected saved offset shift
Ultrawipf Feb 1, 2026
9f4699d
Funding update
Ultrawipf Feb 17, 2026
9367886
F4 DISCO set encoder timer filter to 5
Ultrawipf Feb 25, 2026
a827c68
F407 general set encoder filter to 5
Ultrawipf Feb 25, 2026
92c327f
Changelog update
Ultrawipf Feb 26, 2026
0767c51
TMC4671 fixed encoder forwarding force inversion logic
Ultrawipf Mar 10, 2026
6405b90
MTenc fixed excessive delays when forwarding/multithread access
Ultrawipf Mar 10, 2026
2f061da
Reduced default TMC forwarding rate to 4khz
Ultrawipf Mar 10, 2026
ab16fd4
Changelog update
Ultrawipf Mar 10, 2026
99171b0
Version bump v1.17.0
Ultrawipf Mar 16, 2026
da99aba
Release update
Ultrawipf Mar 17, 2026
5fc00db
Filled Changelog with past changes
Ultrawipf Mar 18, 2026
48e29f3
Added I2C EEPROM ID/OTP Support
Ultrawipf Apr 1, 2026
7485d65
Configurator update
Ultrawipf Apr 1, 2026
983caa4
Fix changelog path typo
Ultrawipf Apr 1, 2026
cbfe547
Configurator update
Ultrawipf Apr 8, 2026
59a1350
Configurator update
Ultrawipf Apr 10, 2026
cafe50c
Initialize ffb rate dividers always
Ultrawipf Apr 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# These are supported funding model platforms

github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
github: ultrawipf
patreon: Gigawipf
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
Expand All @@ -9,4 +9,4 @@ community_bridge: # Replace with a single Community Bridge project-name e.g., cl
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: "paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=B23BD5FGD5CH8"
custom: "https://www.paypal.com/donate/?hosted_button_id=2SU5VLFRFZACG"
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ jobs:
- name: Make changelog
run: |
echo -e "### Firmware changes\n" > /tmp/CHANGELOG.md
cat ${{ github.workspace }}/CHANGELOG.md >> /tmp/CHANGELOG.md
perl -0777 -ne 'print "$1\n$2" if /^(#+.+)\n((?:[^#\n]+\n)+)/m; exit' ${{ github.workspace }}/CHANGELOG.md >> /tmp/CHANGELOG.md
echo -e "\n### Configurator changes\n" >> /tmp/CHANGELOG.md
cat ${{ github.workspace }}/Configurator/CHANGELOG.md >> /tmp/CHANGELOG.md
perl -0777 -ne 'print "$1\n$2" if /^(#+.+)\n((?:[^#\n]+\n)+)/m; exit' ${{ github.workspace }}/Configurator/CHANGELOG.md >> /tmp/CHANGELOG.md
# Create release
Expand Down
189 changes: 175 additions & 14 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,185 @@
### Changes this version:
### v1.17.0
- Added SPI speed selector to MagnTek encoders
- Added "reg" and "save" commands to MagnTek encoder. Allows programming MT6835 encoders (debug=1 mode required!)
- Set ABN encoder filter to 5 for F407 and F407_DISCO. Should improve encoder stability in noisy environments.
- Fixed Magntek encoder forwarding causing choppy FFB
- Fixed TMC4671 ext encoder having inverted forces if previously inverted by dual enc mode

### Changes in 1.16:
### v1.16.6
- Added SPI speed selector to MagnTek encoders
- Added "reg" and "save" commands to MagnTek encoder. Allows programming MT6835 encoders (debug=1 mode required!)
- Set ABN encoder filter to 5 for F407 and F407_DISCO. Should improve encoder stability in noisy environments.

Internal changes:
- CAN port interfaces rewritten
- HAL updated
- Migrated to CPP20
- Upgraded to tinyusb 0.17
- Improved microsecond counter implementation
### v1.16.5
- Reformatted USB serial string as hex and added command to request UID as hex string
- Added device name to USB Product name
- Added support for F407 OTP section
- Added support for MagnTek MT6835 via SPI (SPI3 port, MagnTek encoder class)

### v1.16.4
- Added exponential torque postprocessing for game effects

### v1.16.3
- Added remote CAN button/analog source mainclass

### v1.16.2
- Inverted Y axis direction vector magnitude
- Fixes 2 axis setups in XPforce and DCS and other flight sims
- Changed 2 axis conditional effects to ignore direction vectors (Fixes DCS)
- Modified HID 2 axis descriptor, added back second direction for compliance
- Fixed chip temp sometimes glitching
- TMC debug mode: Changed openloopspeed command to use torque mode instead of raw PWM. Added new openloopspeedpwm to control raw PWM.
- CAN bus corrected packet length when packet is sent as command
- Corrected CAN speed preset in can bridge GVRET mode (savvycan works again)
- Using interrupt transfer for TMC4671 encoder forwarding (Fixed again)

### v1.16.0
- Added MyActuator RMD CAN support class.
- Temporary implementation until CAN protocol changes. Usable but might be improved in the future
- Fixed issues in CAN analog class for packet 2. Allow shorter frames
- F407: ADC now triggered by timer to reduce interrupt frequency
- Using analog VREF for voltage sensing (better accuracy with unstable 3.3V)
- Added chip temperature readout
- Added remote CAN button/analog source mainclass
- Added exponential torque postprocessing for game effects
- Reformatted USB serial string as hex and added command to request UID as hex string
- Added device name to USB Product name
- Added support for F407 OTP section
- Added support for MagnTek MT6835 via SPI (SPI3 port, MagnTek encoder class)
- CAN port interfaces rewritten
- HAL updated
- Migrated to CPP20
- Upgraded to tinyusb 0.17
- Improved microsecond counter implementation

### v1.15.1
- Fixed BISS-C encoder sometimes overflowing one rotation at startup
- Added BISS-C direction inversion function (Default true). Most BISS-C encoders count CW while most others and TMC count CCW.
- Standardized encoder counting direction counting up in CCW direction as a more common industrial standard
- Fixed idle spring effect not working before first save
- Retuned speed limiter function. Removed averaging. Should be more stable for high resolution encoders if high bandwidth speed filter preset is selected
- Force ramps up slowly on potential sharp position changes such as recentering
- FFB led now shows FFB state. On when FFB actuators enabled. Still blinks on clipping

### v1.15.0
- Added independend friction and inertia effects to axis
- ODrive class can save encoder position offset
- Reverted the forza fix for 2 axis setups.
- TODO: test and report if behaviour works for all games with the angle always being used for 1 axis modes (Games must send 90° on X axis effects instead of 0°).

### v1.14.4
- TMC E-Stop handled even during calibration by pausing and disabling driver
- E-Stop checked correctly after startup. You can now disable force and delay startup by setting E-Stop during startup.
- Digital and Analog sources are disabled by default
- Biss-C 1 rotation offset glitch at first packet fixed
- Reverted CAN retransmission to enabled temporarily. Fixes 2 axis ODrive issues.

### v1.14.3
- Only activate brake resistor if vint and vext are >6.5V. Prevents board from activating resistor if only usb powered and a fault reset loop
- Changed behaviour of direction enable and axis enable bits in set_effect report to always apply direction vector
- Fix for Forza Motorsport

### v1.14.2
- Added local button pulse mode

### v1.14.0
- Save TMC space vector PWM mode in flash. Should be usually on for BLDC motors if the star point is isolated.
- Allow using the motors flux component to dissipate energy with the TMC4671 instead of the brake resistor. May cause noticable braking in the motor but takes stress off the resistor.
- Axis speed limiter usable and saved in flash.
- Removed unused hall direction flash setting.

### v1.13.3
- Added uid command (`sys.uid?` returns first 64 bits as val and second 32 as adr)

### v1.13.2
- Added effect monitoring per axis

### v1.13.1
- Added PWM direction toggle

### v1.13.0
- Added basic iterative TMC PI autotuning
- Fixed issues with CAN transmission with multiple axes
- Added SSI encoder support (AMT232B)
- Fixed SPI buttons not working (SPI2 DMA on F407)
- Dynamic TMC encoder alignment current based on current limit

### v1.12.1
- Added part of unique serial number to usb interface names for easier identification of multiple devices
- Enabled Simplemotion for F407_DISCO build

### v1.12.0
- Added support for Simplemotion V2 (Ioni/Argon motor drivers)

### v1.11.2
- Fixed a possible crash if unparsable/too large numbers are sent in a command
- Removed unused direction field from descriptor in 2 axis desc
- Workarounds for 2 axis conditional effects giving condition blocks priority over direction angles

### v1.11.1
- Added new subproject for third party devkits (F407DISCO target)
- Added serialfx effect manager for a command based FFB mainclass (Instead of PID FFB)
- Added Serial FFB mainclass mode
- Added mosfet BBM time to TMC hardware selection
- TMC enable pin is set when TMC debug mode starts
- Added option to change SPI speed for buttons. Can be helpful if the connection is unreliable
- Added back second VESC instance for 2 axis vesc setups
- Separate motor driver selection lists per axis (No double odrive/vesc/tmc instance options in motor driver lists)

### v1.10.1
- Changed default power from 2000 to 5000 as 2000 is not enough to calibrate many motors
- Internal change moving effects into effectscalculator to simplify managing effects from different sources
- Effect intensity tuning value now only affects game effects. Fixes the effect intensity incorrectly affecting the endstop.

### v1.10.0
- Added local encoder index option to reload a previously stored offset
- Fixed an issue with 2 axis FFB effects on second axis
- Added TMC4671 biquad filter option
- Lowpass, notch and peak modes (fixed Q factor, saved frequency)
- Improved BISS performance when used with TMC
- Fixed an issue with live effects statistics jumping to 0 using double buffers
- Added missing command flags and help messages

### v1.9.7
- Fixed CDC serial port sometimes losing replies on with some USB ports

### v1.9.6:
- Added analog filter option
- Main effect loop runs in higher priority thread than idle
- Added ADS111X analog source
- Added user configurable axis encoder ratios for setups with reductions
- Added effect filter option (Speed/accel filter presets for different encoders)
- Added effects monitoring
- Added some analog autorange margin
- Added min/max commands to analog processing for manual ranges
- Added analog processing functions to ADS111X
- Selecting a "none" encoder will remove the axis value. Allows analog inputs to be used as the primary axis.
- Added constant force rate command
- Highly improved uart command stability (default baud rate 115200)
- Added command to check command flags (cls.cmdinfo?cmdid)
- Added advanced filter mode to switch between custom and default conditional effect output filters ("fx.filterProfile_id")
- Automatic flash erase condition changed from major version change to separate flash version counter

### v1.8.8
- Rescaled endstop to encoder angle (makes strength feel the same at every range)
- Changed SPI button saved count from 0-63 to 1-64 (will invalidate your setting)
- Added CAN next frame length command to send frames with different headers
- Emergency stop can be reset and only disables torque
- Added estop command
- Optimized string based command interfaces
- Effects honor the gain setting (Makes Forza Horizon work)

### v1.8.7
- FFBWheel and FFBJoystick classes split for 1 and 2 axis FFB (Allows to use different HID descriptors)
- Added a single axis HID descriptor (currently not used for compatibility reasons. enable by defining FFBWHEEL_USE_1AXIS_DESC)
- Default SPI button speed increased to 1.3MHz
- Added CAN button source
- Added CAN analog source
- Moved CAN and i2c speed settings to port class
- Fixed CAN bridge RTR frames
- HID interface sends ACKs
- Improved help command formatting and added flags
- Added I2C fast mode 400kHz
- Added BISS-C encoder
- Fixed MT Encoder
- Reworked TMC external encoder system
- Digital and analog source readout command


# Persistent changelog
Append changes at the top.
The first section is used in release comments
5 changes: 2 additions & 3 deletions Firmware/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*Debug/
**/Debug/
**/Release/
**/.settings/
*.launch
Expand All @@ -7,5 +7,4 @@
.mxproject
fixlang
/build/
/OpenFFBoard/
/*Targets/F407VG/*.cfg
/OpenFFBoard/
4 changes: 2 additions & 2 deletions Firmware/FFBoard/Inc/AxesManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ class AxesManager
void emergencyStop(bool reset);
void resetPosZero();

void updateSamplerate(float newSamplerate);

private:
volatile Control_t* control;
volatile bool *p_usb_disabled;
volatile bool *p_emergency;
std::shared_ptr<EffectsCalculator> effects_calc;
uint16_t axis_count = 0;
std::vector<std::unique_ptr<Axis>> axes;
Expand Down
7 changes: 5 additions & 2 deletions Firmware/FFBoard/Inc/Axis.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ struct AxisConfig
struct metric_t {
float accel = 0; // in deg/s²
float speed = 0; // in deg/s
int32_t pos = 0; // scaled position as 16b int -0x7fff to 0x7fff
int32_t pos_scaled_16b = 0; // scaled position as 16b int -0x7fff to 0x7fff matching FFB ranges
float pos_f = 0; // scaled position as float. -1 to 1 range
float posDegrees = 0; // Position in degrees. Not scaled to selected range
int32_t torque = 0; // total of effect + endstop torque
Expand Down Expand Up @@ -171,6 +171,9 @@ class Axis : public PersistentStorage, public CommandHandler, public ErrorHandle
bool updateTorque(int32_t* totalTorque);


void updateSamplerate(float newSamplerate);
void updateFilters(uint8_t profileId);

void setGearRatio(uint8_t numerator,uint8_t denominator);

static const std::vector<class_entry<MotorDriver>> axis1_drivers;
Expand Down Expand Up @@ -259,7 +262,7 @@ class Axis : public PersistentStorage, public CommandHandler, public ErrorHandle
const biquad_constant_t filterFrictionCst = {50, 20};
const biquad_constant_t filterInertiaCst = {20, 20};
uint8_t filterProfileId = 1; // Default medium (1) as this is the most common encoder resolution and users can go lower or higher if required.
const float filter_f = 1000; // 1khz
float filter_f = 1000; // 1khz default. should be set at runtime once the actual rate is known
const int32_t intFxClip = 20000;
uint8_t damperIntensity = 30;

Expand Down
2 changes: 2 additions & 0 deletions Firmware/FFBoard/Inc/CmdParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
#include "CommandHandler.h"
#include "ringbufferwrapper.h"

#ifndef CMDPARSER_MAX_VALID_CAPACITY
#define CMDPARSER_MAX_VALID_CAPACITY 2048
#endif

class CommandHandler;
class CommandInterface;
Expand Down
27 changes: 18 additions & 9 deletions Firmware/FFBoard/Inc/CommandHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include "mutex.hpp"
#include "ClassIDs.h"
#include <vector>

#include <span>

#define CMDFLAG_GET 0x01
#define CMDFLAG_SET 0x02
Expand All @@ -22,6 +22,7 @@
#define CMDFLAG_SETADR 0x20
#define CMDFLAG_HIDDEN 0x40
#define CMDFLAG_DEBUG 0x80
#define CMDFLAG_EXTOVERRIDE 0x80000000

#define CMDFLAG_STR_ONLY 0x100
#define CMDFLAG_HID_ONLY 0x200 // Command not available for string based parsers
Expand Down Expand Up @@ -50,8 +51,8 @@ class CmdHandlerCommanddef
{};
const char* cmd = nullptr;
const char* helpstring = nullptr;
const uint32_t cmdId;
const uint32_t flags;
uint32_t cmdId;
uint32_t flags;
};

struct CmdHandlerInfo
Expand Down Expand Up @@ -260,17 +261,22 @@ class CommandHandler {
*/
template<typename ID>
void registerCommand(const char* cmd,const ID cmdid,const char* help=nullptr,uint32_t flags = 0){
for(CmdHandlerCommanddef& cmdDef : registeredCommands){
if(cmdDef.cmdId == static_cast<uint32_t>(cmdid))
return; //already present
}
registerCommand_INT(cmd, static_cast<uint32_t>(cmdid), help, flags);
}

this->registeredCommands.emplace_back(cmd, help,static_cast<uint32_t>(cmdid),flags);
this->registeredCommands.shrink_to_fit();

virtual void postCmdhandlerInit(){}; // Can implement in external file to override command flags
template<typename ID>
/**
* Can override command flags to make it read only
*/
void overrideCommandFlags(const ID cmdid,uint32_t flagmask = 0){
overrideCommandFlags_INT(static_cast<uint32_t>(cmdid), flagmask);
}




protected:
void setInstance(uint8_t instance);
bool commandsEnabled = true;
Expand All @@ -287,6 +293,9 @@ class CommandHandler {

CmdHandlerInfo cmdHandlerInfo;

void registerCommand_INT(const char* cmd,const uint32_t cmdid,const char* help=nullptr,uint32_t flags = 0);
void overrideCommandFlags_INT(const uint32_t cmdid,uint32_t flagmask = CMDFLAG_GET | CMDFLAG_GETADR);

};

#endif /* COMMANDHANDLER_H_ */
4 changes: 2 additions & 2 deletions Firmware/FFBoard/Inc/CommandInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class StringCommandInterface : public CommandInterface{
CmdParser parser; // String parser
};


#define CDC_CMD_BUFFER_SIZE (TUD_OPT_HIGH_SPEED ? 4096 : 1024)
//receives bytes from mainclass. calls its own parser instance, calls global parser thread, passes replies back to cdc port.
class CDC_CommandInterface : public StringCommandInterface,public cpp_freertos::Thread{
public:
Expand All @@ -83,7 +83,7 @@ class CDC_CommandInterface : public StringCommandInterface,public cpp_freertos::
bool nextFormat = false;
std::string sendBuffer;
uint32_t bufferLength = 0;
const uint32_t maxSendBuffer = 1024; // Max buffered command size before sending immediately
const uint32_t maxSendBuffer = CDC_CMD_BUFFER_SIZE; // Max buffered command size before sending immediately
};


Expand Down
Loading
Loading