I'm interested in building a force feedback joystick controller around Teensy 4.0. I've purchased some salvaged old control loading servos that communicate via CANOpen, and have established communications using a python canopen library on my desktop. The servos report position as a 16-bit signed integer and accept drive torque as a 16-bit signed integer. I tried implementing a desktop application with the latest vjoy, which supports force feedback, but I want tighter control over cycle times than a multi-threaded desktop app can give me, thanks to the limits of sleep precision on Windows. I'm looking at Teensy 4.0 to do the soft real-time force calculation loop and CAN IO. I want to extend Teensy's HID joystick endpoint to add Physical Input Device support, and also maintain a virtual serial port for debugging/configuration.
Firmware for such a device that's close to what I want already exists (ref: jmriego's Fino project, among others), but in the Arduino ecosystem, using their PluggableUSB code. While both are USB HID endpoints, the PluggableUSB API is quite different from Teensy's usb.c / usb_desc.h. I'm ignorant enough about the implementation details of USB HID that porting this feels pretty daunting. I've already read the canonical "Adding a new USB type" PJRC forum thread, but that discusses creating an endpoint that includes a different mix of the builtin Teensyduino device types, not something entirely new. Also relevant: the Fino project includes a PDF of a USB Implementers' Forum document describing the Physical Input Device USB spec.
As best as I can tell, the force feedback device type is implemented as an extension of the HID standard, and involves implementing an extra interrupt out endpoint on top of the regular USB HID joystick profile. The Fino project includes an implementation of the descriptor. So I think I need to create a new USB device type that defines that descriptor, in addition to the joystick descriptor, and write an extension of usb_joystick.cpp that parses those datastructures out of the report described by the descriptor, populates the relevant structs, and makes them available so that I can employ the effect code from Fino to generate the output torques (and then use CANOpen to send the forces to the actuators, and update the position/velocity/acceleration).
[edit]I just had a look in the comments in usb_desc.h and usb_desc.c, which are much nicer since I was last in there several years ago. Thank you for the improved comments, Paul! That also led me to the canonical description of the stack.
So it looks like I need to add the FFB descriptor to usb_desc.c, and wire up usb_desc.h such that I have a device with a Serial, and a FFBJoystick, which is just a Joystick except I'm re-using the endpoint to receive as well. I feel like I should be able to use the Serial receive code to figure out getting data from the usb_packet_t into the structs I plan to borrow from Fino...[/edit]
Any pointers on how to put together the various disconnected bits here into an approach to modifying Teensyduino to get where I need to be?
Firmware for such a device that's close to what I want already exists (ref: jmriego's Fino project, among others), but in the Arduino ecosystem, using their PluggableUSB code. While both are USB HID endpoints, the PluggableUSB API is quite different from Teensy's usb.c / usb_desc.h. I'm ignorant enough about the implementation details of USB HID that porting this feels pretty daunting. I've already read the canonical "Adding a new USB type" PJRC forum thread, but that discusses creating an endpoint that includes a different mix of the builtin Teensyduino device types, not something entirely new. Also relevant: the Fino project includes a PDF of a USB Implementers' Forum document describing the Physical Input Device USB spec.
As best as I can tell, the force feedback device type is implemented as an extension of the HID standard, and involves implementing an extra interrupt out endpoint on top of the regular USB HID joystick profile. The Fino project includes an implementation of the descriptor. So I think I need to create a new USB device type that defines that descriptor, in addition to the joystick descriptor, and write an extension of usb_joystick.cpp that parses those datastructures out of the report described by the descriptor, populates the relevant structs, and makes them available so that I can employ the effect code from Fino to generate the output torques (and then use CANOpen to send the forces to the actuators, and update the position/velocity/acceleration).
[edit]I just had a look in the comments in usb_desc.h and usb_desc.c, which are much nicer since I was last in there several years ago. Thank you for the improved comments, Paul! That also led me to the canonical description of the stack.
So it looks like I need to add the FFB descriptor to usb_desc.c, and wire up usb_desc.h such that I have a device with a Serial, and a FFBJoystick, which is just a Joystick except I'm re-using the endpoint to receive as well. I feel like I should be able to use the Serial receive code to figure out getting data from the usb_packet_t into the structs I plan to borrow from Fino...[/edit]
Any pointers on how to put together the various disconnected bits here into an approach to modifying Teensyduino to get where I need to be?
Last edited: