Guidance on how to get more joystick resolution

Status
Not open for further replies.
I've just recently dove into the deep end of USB HID devices and, as you might guess, am now a bit lost.

Here's what I'm trying to achieve: the Teensyduino joystick library allows you to send values of 0-1023 for any of the axis or slider usages. That's already a pretty generous spread when it comes to joysticks, but I'm looking to get a bit more.

Here's what I've done so far: I've duped the teensy directory found within the Arduino hardware directory (this is for a Teensy 2.0++), renamed it to something meaningful to me (vrc), and edited that folder's boards.txt file to include my "new" Teensy based device.

I've edited the manufacturer and product strings in vrc/cores/teensy/usb_serial_hid/usb_private.h like so:

Code:
#define STR_MANUFACTURER L"Round4"
#define STR_PRODUCT L"VRCPro"
#define STR_SERIAL L"Serial"

/* */

#define PRODUCT_ID 0x0490

The product name change is mostly so that when I select my board in the Arduino app it's obviously that I'm using the correct code and the product id change is to force my machine to see it as something new, and therefore obviously new. I only needed to do that once.

Now I'm puzzling a bit over the resolution thing.

In vrc/cores/teensy/usb_serial_hid/usb.c I can see where the HID report is put together.

Am I correct in thinking that if I wanted to adjust the minimum to -1023, and the maximum to 1023, I'd want those lines to look like so?

Code:
0x15, 0x01, 0xFC,               //   Logical Minimum (-1023)
0x26, 0xFF, 0x03,               //   Logical Maximum (1023)

Is it safe to assume that adjusting the logical minimum then changes the report size? And why a report size of 10 in the first place? With a report count of 4, wouldn't the report size be 8 instead?

Assuming I worked out the report size, by adjusting the minimum does my joystick_report_data array need to increase in size as well? And of course, I'd need to adjust the hard limit defined in vrc/cores/teensy/usb_serial_hid/usb_api.h to allow for the larger range.

What am I missing?
 
I gave up trying to do this on the Teensy 2.0 code. There's a lot going on in the USB code for Teensy 2.0 and I just couldn't follow it.

The Teensy 3.x code is a lot easier to follow. I ended up giving this tutorial a shot using a Teensy 3.0. Problem is, it's not showing up as a Joystick, or even as an HID device for that matter. The device can be seen by both Windows and OSX, but that's about it.

I'm thinking something in the Teensy code has changed since the tutorial was made and I'm wondering if anyone can do a quick check of the code there and see if anything stands out?

One thing I'm curious about are how these lines of code found in usb_desc.h are derived:

Code:
#define KEYBOARD_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9)
#define MOUSE_DESC_OFFSET    (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9)
#define JOYSTICK_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9)
#define CONFIG_DESC_SIZE     (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9+9+7)

I'm guessing they're the length values for each of a device's interface descriptors, which leads to this question: how are those values derived?
 
I gave up trying to do this on the Teensy 2.0 code. There's a lot going on in the USB code for Teensy 2.0 and I just couldn't follow it.

The Teensy 3.x code is a lot easier to follow. I ended up giving this tutorial a shot using a Teensy 3.0. Problem is, it's not showing up as a Joystick, or even as an HID device for that matter. The device can be seen by both Windows and OSX, but that's about it.

I'm thinking something in the Teensy code has changed since the tutorial was made and I'm wondering if anyone can do a quick check of the code there and see if anything stands out?

One thing I'm curious about are how these lines of code found in usb_desc.h are derived:

Code:
#define KEYBOARD_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9)
#define MOUSE_DESC_OFFSET    (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9)
#define JOYSTICK_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9)
#define CONFIG_DESC_SIZE     (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9+9+7)

I'm guessing they're the length values for each of a device's interface descriptors, which leads to this question: how are those values derived?


I found the offset part confusing also, but did successfully manage to add my own Gamepad USB type, using the guide you posted above. I also found the code much easier to follow using the Teensy 3, rather than the Teesnsy 2++.

I am no expert but this is what I think it all means...

I have the following in my usb_desc.h for my gamepad. (Yours has several #defines, because you have a mouse, keyboard & joystick device, my gamepad type is a single device)

Code:
  #define GAMEPAD_DESC_OFFSET	(9)
  #define CONFIG_DESC_SIZE	(9 + 9+9+7)


Now in the usb_desc.c I have...

Code:
#ifdef GAMEPAD_INTERFACE
        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
        9,                                      // bLength
        4,                                      // bDescriptorType
        GAMEPAD_INTERFACE,                     // bInterfaceNumber
        0,                                      // bAlternateSetting
        1,                                      // bNumEndpoints
        0x03,                                   // bInterfaceClass (0x03 = HID)
        0x00,                                   // bInterfaceSubClass
        0x00,                                   // bInterfaceProtocol
        0,                                      // iInterface
        // HID interface descriptor, HID 1.11 spec, section 6.2.1
        9,                                      // bLength
        0x21,                                   // bDescriptorType
        0x11, 0x01,                             // bcdHID
        0,                                      // bCountryCode
        1,                                      // bNumDescriptors
        0x22,                                   // bDescriptorType
        LSB(sizeof(gamepad_report_desc)),      // wDescriptorLength
        MSB(sizeof(gamepad_report_desc)),
        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
        7,                                      // bLength
        5,                                      // bDescriptorType
        GAMEPAD_ENDPOINT | 0x80,               // bEndpointAddress
        0x03,                                   // bmAttributes (0x03=intr)
        GAMEPAD_SIZE, 0,                       // wMaxPacketSize
        GAMEPAD_INTERVAL,                      // bInterval
#endif

The first 9 comes from the bLength of config_descriptor (usb_desc.c), which I presume must be present for all devices. If you look at the bLengths in the above code they are the 9+9+7, which give the CONFIG_DESC_SIZE part. (Again if you look at yours, all the numbers are the bLength & bFunctionLengths from each interface descriptor, the serial hid uses the config_descriptor(9), CDC_IAD (8), CDC_DATA (9+5+5+4+5+7+9+7+7), Keyboard(9+9+7), Mouse(9+9+7) & Joystick(9+9+7). I am not sure where the last 9 is coming from but hopefully I gives you the picture.)

The above code is only a small part of it, let me know if you want the full code.

Regards,

Les
 
Thanks Les - that certainly helps clear up the mystery of the 9's and 7's.

One thing I've relearned while pursuing this goal of higher resolution is that it's sort of pointless, at least using anything but a Teensy 3.1. The resolution of the ADCs are the bottleneck, even if I could tweak the USB code to report higher resolution. With that in mind, I ordered a Teensy 3.1. It may turn out that my resolution doesn't change all that much, but at the very least I'll have more accurate analog inputs.
 
It may turn out that my resolution doesn't change all that much, but at the very least I'll have more accurate analog inputs.

You should be able to achieve 12-13bits of real resolution using a Teensy 3.1 - but the devil is in the details, so see if using a lower-voltage reference, etc. might improve your accuracy. That all depends on the signals coming out of the joystick, which I am unfamiliar with. Using averaging or decimation should improve the stability of your signals and the ADC is more than fast enough to sample a plethora of channels in this manner.
 
I gave up trying to do this on the Teensy 2.0 code. There's a lot going on in the USB code for Teensy 2.0 and I just couldn't follow it.

I had another look at this today and was successful in adding a new joystick device for the Teensy 2++. It's not actually that bad once you understand the Teensy 3 code, it's maybe a bit harder to find your way around, but a lot of the code is quite similar. Maybe I'll add a guide to my blog if I get a chance.

Regards,

Les
 
Status
Not open for further replies.
Back
Top