Many axis joystick

Hi, I'm trying to create a custom class so to use a custom device (pretty similar to JOYSTICK_INTERFACE, but with different bit resolution, for few axes, and few more buttons).
The first step I did was modifying the JOYSTICK_INTERFACE (in usb_desc.c), and usb_joystick.c and usb_joystick.h, and everything is working as expected (axis and buttons are recognized).

So I created my custom usb_cougar.c, and usb_cougar.h, which mirrors usb_joystick.c and usb_joystick.h, and modified :
* usb_desc.c
* usb_desc.h
* boards.txt
* usb_inst.cpp
* WProgram.h

The Arduino app shows the new entry "Cougar", under Tools--> USB Type ... But when I compile and upload, it something gets broken (fails to connect to the usb device and returns the error below).

No Teensy boards were found on any USB ports of your computer.
Please press the PROGRAM MODE BUTTON on your Teensy to upload your sketch.

So: question time:
* Am I missing some file that needs to be modified?
* Is it possible to have an USB_TYPE which is only a plain JOYSTICK and not a sort of hub/group of (Serial)+Keyboard+Mouse+Joystick?
* Is it possible to change the names of the axis which are shown in Windows, (e.g. to something more appealing than Rx Ry Rz)?


BTW thanks for the very interesting info in this post!
 
OK So I have been reading over this thread again since it has been a while since changing my descriptors to use the Extreme Joystick but I have only been using the 128 buttons and nothing else at the moment..

However I have a couple of questions as I wasn't to move into using the axis and possibly sliders (not sure if those will work on the primary programs I use) but in any case my question has to do with the relation of the hardware to the Profiles.

I am currently using the Teensy LC for my system but I was trying to figure out how the Hardware input to the Joystick actually relates as from what I understand the ADC's only put out a value of 1024 (-512 / +512) but the joystick will of course output 16bit.. So my understanding is essentially even though the the joystick is reporting 16bit because the ADC is only at 10 bits the DC is the bottle neck..

Im trying to figure out by what method I might get a true 16 bit signal or if it is even possible..

Thank you
 
As far as I understand, considering that you are using the Teensy LC, according to tech specs, you are limited to 12bit max (its ADC has an usable resolution of 12bit).

You may change the resolution of the analogRead, with analogReadResolution(desired bit), so analogReadResolution(12) at most for Teensy LC. That's the raw data, as far as what you pass to the Joystick class, it really depends on how your code is implemented.

So I would say that with the Teensy LC there is a limitation to 12bit raw signal, while, then you may map it / modify it, smooth it within Arduino.

Ultimately, on the OS side, it expects a sequence of data, formatted according to the contents of usb_desc.c (JOYSTICK_INTERFACE or the interface you are using), so if it expect 16bit data, it will read (at most) 16bit data for the axis.

Just my 0.02$.
 
As far as I understand, considering that you are using the Teensy LC, according to tech specs, you are limited to 12bit max (its ADC has an usable resolution of 12bit).

You may change the resolution of the analogRead, with analogReadResolution(desired bit), so analogReadResolution(12) at most for Teensy LC. That's the raw data, as far as what you pass to the Joystick class, it really depends on how your code is implemented.

So I would say that with the Teensy LC there is a limitation to 12bit raw signal, while, then you may map it / modify it, smooth it within Arduino.

Ultimately, on the OS side, it expects a sequence of data, formatted according to the contents of usb_desc.c (JOYSTICK_INTERFACE or the interface you are using), so if it expect 16bit data, it will read (at most) 16bit data for the axis.

Just my 0.02$.

That was sort of what I was thinking is that re-mapping would give me the 16bit to the computer but in REALITY it would only be 10bit with maybe some interpolation algorithm (which I will need to look into as that will be new for me) as the actual RAW would only be 10 bit (using default).. Thank you for the tip on the 12bit though as I didn't realize that as that will give me a bit more raw resolution.. So that is a hel, Thank you..


ANOTHER QUESTION: (though you sort of asked the same question above.. so for someone else :) )

What might be done to the USB header file if I wanted to remove the Keyboard and Mouse functionality so that ONLY Joystick and Serial are used.. I really kind hate that my device in the end shows up as a Keyboard in windows, but, I can't just use Joystick as I need Serial for some other communication and as well I found that having the Serial as well is the ONLY way to get Windows to recognize a custom device name.
 
Ok, I managed to find the error of my implementation, as it was related to one of the question I arose, I thought of reporting it here, as if you are going to implement your own joystick it may be of use.

All the additions/modifications were fine, but since I took as reference the "Serial/Keyboard/Mouse/Joystick" interface, it had a lot of stuff (I'm not really interested in having), among them:

KEYMEDIA_INTERFACE

The problem is that its KEYMEDIA_INTERFACE_DESC_POS is defined taking into account MTP_INTERFACE_DESC_POS, which in turn is defined taking into account JOYSTICK_INTERFACE_DESC_POS+JOYSTICK_INTERFACE_DESC_SIZE, so I simply had to add my interface size to the MTP_INTERFACE_DESC_POS definition.

#define COUGAR_INTERFACE_DESC_POS SEREMU_INTERFACE_DESC_POS+SEREMU_INTERFACE_DESC_SIZE
#ifdef COUGAR_INTERFACE
#define COUGAR_INTERFACE_DESC_SIZE 9+9+7
#define COUGAR_HID_DESC_OFFSET COUGAR_INTERFACE_DESC_POS+9
#else
#define COUGAR_INTERFACE_DESC_SIZE 0
#endif


#define MTP_INTERFACE_DESC_POS JOYSTICK_INTERFACE_DESC_POS+JOYSTICK_INTERFACE_DESC_SIZE+COUGAR_INTERFACE_DESC_SIZE
#ifdef MTP_INTERFACE
#define MTP_INTERFACE_DESC_SIZE 9+7+7+7
#else
#define MTP_INTERFACE_DESC_SIZE 0
#endif

So I have a question: is it possible to have a simple USB_JOYSTICK_INTERFACE, with only the joystick? Or how can I drop keyboard, keymedia and mouse (I can live with Serial or SerialEmulation, as it is very handy)?

Thanks
 
I have a Teensy 4.1 controller. Is there a version of the "extreme_joystick_test3.zip" that supports the 4.1? I tried coping the following files (usb_desc.h, usb_joystick.c, usb_joystick.h and usb_desc.c) into the Teensy 4 folder but this caused compile errors. When I compare the v3 to v4 there are significant changes to the files. Any support would be appreciated...
 
Did you try simply editing the one file/line I mentioned in the other thread? I believe that all of this stuff has been included in the main USB stuff when you set the JOYSTICK_SIZE to 64...

And I would expect these files to be reasonably different between T3.x and T4.x... Also the one in the zip file is a lot behind the one that currently installs for T3.x.
 
Hi everyone, newguy here.

It's been about a week since I started this lil project of mine on Teensy 4.0: a small panel that goes on top of my throttle with a total of about 42 inputs, 4 of which sliders.
Problem is I can't seem to go over that 32 inputs max that windows can detect with the controller properties.
I was looking into how to edit the .ino files to increase the max number of inputs, but (my bad move) I just copied over what was posted previously for the Teensy 3.6.
So now I'm getting those compile errors that someone else also got.

My question here is:
Where can I get the original .ino files to go back to normal and start editing them manually one by one?
Can I just reinstall the Teensyduino addon?

Cheers

Barg
 
Hi,

I would love to get some help setting this up on Platform IO.
I don't understand what is the process to get the Mouse+keyboard+gamepad+joystick option like you choose in the arduino ? (are those the build flags? or are they a library?)
once this is installed, where can i find the files to change?
* usb_desc.c
* usb_desc.h
* boards.txt
* usb_inst.cpp

I would really like to use Teensy with PlatformIO but if i won't have a choice i'll revert to the arduino IDE...

Thanks.
P.S.
Would the many joystick axis work on the 3.5 teensy?
 
I've updated the JOYSTICK SIZE from 12 to 64 but the arduino compiler yells this:

Code:
Complete:41: error: 'class usb_joystick_class' has no member named 'sliderLeft'
   Joystick.sliderLeft(analogRead(4));

This is the example code... how's that possible?

any explanation for the reason?
 
Tried to edited the Previous post But couldn't do it...

Pual - i'm trying different Vendor ID and Product ID, but i can't get the Joystick to show 128 buttons.

Do you have any suggestion about what's going on?
Could windows/Microsoft blocked the option?
 
i'm trying different Vendor ID and Product ID, but i can't get the Joystick to show 128 buttons.

Do you have any suggestion about what's going on?

USB descriptors and HID report descriptors and report data size are tricky to get correct.

Maybe try running the USB-IF command verifier program, which will read & check all your descriptor data. It's a free download from www.usb.org. But beware, it temporarily replaces the Windows USB host controller driver. If you have an extra "clean" Window system, best to run it there rather than on a "well used" Windows machine. If testing at 12 Mbit, it requires a real USB hub between your PC and the device you're testing. That fact is mentioned in the documentation but easy to overlook.



Tried to edited the Previous post But couldn't do it...

This forum allows 2 hours to edit your message. It's mostly an anti-spam policy. Some spammers (or their bots) will post short context-free messages which look like ordinary but somewhat confused conversation, then weeks or months later edit them to become spam. We've also had a couple cases years ago where a person got frustrated and edited all their messages after engaging in a conversation, leaving the whole thing a big mess. Spam is the much larger ongoing problem, but for both these reasons we set the policy at 2 hours years ago. If it's been longer than 2 hours, just post another message.
 
USB descriptors and HID report descriptors and report data size are tricky to get correct.

Maybe try running the USB-IF command verifier program, which will read & check all your descriptor data. It's a free download from www.usb.org. But beware, it temporarily replaces the Windows USB host controller driver. If you have an extra "clean" Window system, best to run it there rather than on a "well used" Windows machine. If testing at 12 Mbit, it requires a real USB hub between your PC and the device you're testing. That fact is mentioned in the documentation but easy to overlook.

Hi Paul,

Thanks for the answer.
I've tested it with pointy software, which shows 128 buttons, 7 sliders and 4 hats.
So what's wrong with windows? why cant it show the correct joystick?

I've went from the 128 button to 32 button and pointy software showed the correct settings.

Is it something in windows that needs to be configured?

If testing at 12 Mbit, it requires a real USB hub between your PC and the device you're testing.

I'm not sure i fully understand...

i do have a virtual system to run it on... i'll try.

I also tried to run it on my wife windows laptop, but i didn't see it either there.

Do you think games will show the correct joystick configuration?
 
So what's wrong with windows? why cant it show the correct joystick?

Oh I can't even begin to tell you how many times I've asked this exact question. I'll create a USB thing and it works great in Linux and Macintosh, but Windows won't touch it.

These problems usually come in 2 varieties.

1: Something is wrong with your descriptors which Linux accepts, but Windows does not. The USB-IF verifier software really helps for this case.

2: Your device fully complies with USB standards, but Microsoft simply does not use it with built-in drivers.
 
I'll try with the USB-IF program (i didn't see any download on the link you shared)

and i'll try on the Mac. What is the Mac's "Game controller"?

Ashamed to say i've never used it and i own a Mac for 10 years.

OK. I've downloaded a software called "Controller Lite" and it identifies the joystick as expected.

F#$#$%#$% you Windows... Almost sleepless night
 
Last edited:
I'm trying in every way to create a joystick with 8 axes and 8 buttons working, based on on the excellent Extreme Joystick (size 64).
I use a 16 channels SBUS receiver connected to the Teensy, I can make everything work but one of the two declared sliders it doesn't work, I correctly see two sliders in the Windows panel but it only interacts with channel 7 of the rx (mapped on analog 6), the second slider on channel 8 (analog 7) does not work.
All the other 15 of the 16 SBUS channels work, only that damn slider on rx channel 8 stays at half scale.

Portion of the .ino code:

Code:
{
    sbus_data_t* c = &controllerState;
    for(int i = 0; i < 8; i++)
    Joystick.slider(i+1,millis());
    Joystick.X(mapAnalog(c->analog[0]));
    Joystick.Y(mapAnalog(c->analog[1]));
    Joystick.Z(mapAnalog(c->analog[2]));
    Joystick.Xrotate(mapAnalog(c->analog[3]));
    Joystick.Yrotate(mapAnalog(c->analog[4]));
    Joystick.Zrotate(mapAnalog(c->analog[5]));
    Joystick.sliderLeft(mapAnalog(c->analog[6]));
    Joystick.sliderRight(mapAnalog(c->analog[7]));
    
    Joystick.button(1, c->analog[8] < 0);
    Joystick.button(2, c->analog[9] < 0);
    Joystick.button(3, c->analog[10] < 0);
    Joystick.button(4, c->analog[11] < 0);
    Joystick.button(5, c->analog[12] < 0);
    Joystick.button(6, c->analog[13] < 0);
    Joystick.button(7, c->analog[14] < 0);
    Joystick.button(8, c->analog[15] < 0);
    Joystick.send_now();
}

usb_joystick.h:

Code:
	void X(unsigned int position) { analog16(0, position); }
	void Y(unsigned int position) { analog16(1, position); }
	void Z(unsigned int position) { analog16(2, position); }
	void Xrotate(unsigned int position) { analog16(3, position); }
	void Yrotate(unsigned int position) { analog16(4, position); }
	void Zrotate(unsigned int position) { analog16(5, position); }
	void sliderLeft(unsigned int position) { analog16(6, position); }
	void sliderRight(unsigned int position) { analog16(7, position); }
	void slider(unsigned int num, unsigned int position) {
		if (--num >= 17) return;
		analog16(num + 8, position);

usb_desc.c:

Code:
#elif JOYSTICK_SIZE == 64
// extreme joystick  (to use this, edit JOYSTICK_SIZE to 64 in usb_desc.h)
//  128 buttons   16
//    6 axes      12
//   17 sliders   34
//    4 pov        2
static uint8_t joystick_report_desc[] = {
        0x05, 0x01,                     // Usage Page (Generic Desktop)
        0x09, 0x04,                     // Usage (Joystick)
        0xA1, 0x01,                     // Collection (Application)
        0x15, 0x00,                     // Logical Minimum (0)
        0x25, 0x01,                     // Logical Maximum (1)
        0x75, 0x01,                     // Report Size (1)
        0x95, 0x80,                     // Report Count (128)
        0x05, 0x09,                     // Usage Page (Button)
        0x19, 0x01,                     // Usage Minimum (Button #1)
        0x29, 0x20,                     // Usage Maximum (Button #32)
        0x81, 0x02,                     // Input (variable,absolute)
        0x05, 0x01,                     // Usage Page (Generic Desktop)
        0x09, 0x01,                     // Usage (Pointer)
        0xA1, 0x00,                     // Collection ()
        0x15, 0x00,                     // Logical Minimum (0)
        0x27, 0xFF, 0xFF, 0, 0,         // Logical Maximum (65535)
        0x75, 0x10,                     // Report Size (16)
        0x95, 23,                       // Report Count (23)
        0x09, 0x30,                     // Usage (X)
        0x09, 0x31,                     // Usage (Y)
        0x09, 0x32,                     // Usage (Z)
        0x09, 0x33,                     // Usage (Rx)
        0x09, 0x34,                     // Usage (Ry)
        0x09, 0x35,                     // Usage (Rz)
        0x09, 0x36,                     // Usage (Slider)
        0x09, 0x36,                     // Usage (Slider)
        0x81, 0x02,                     // Input (variable,absolute)
        0xC0,                           // End Collection
        0x15, 0x00,                     // Logical Minimum (0)
        0x25, 0x07,                     // Logical Maximum (7)
        0x35, 0x00,                     // Physical Minimum (0)
        0x46, 0x3B, 0x01,               // Physical Maximum (315)
        0x75, 0x04,                     // Report Size (4)
        0x95, 0x04,                     // Report Count (4)
        0x65, 0x14,                     // Unit (20)
        0x05, 0x01,                     // Usage Page (Generic Desktop)
        0x09, 0x39,                     // Usage (Hat switch)
        0x81, 0x42,                     // Input (variable,absolute,null_state)
        0xC0                            // End Collection

Where am I doing wrong?

Marco
 
Last edited:
I'm trying to use 2 hat switches and i'm not sure i'm using the command correctly.

Should it be:

Joystick.hat (1,angle) for hat #1
Joystick.hat (2,angle) for hat #2

Am i doing it right?

in the usb_joystick the hat function is as follows:

Code:
inline void hat(unsigned int num, int angle) {
		uint32_t val=15;
		if (angle > 0 && angle < 23) val = 0;
		else if (angle < 68) val = 1;
		else if (angle < 113) val = 2;
		else if (angle < 158) val = 3;
		else if (angle < 203) val = 4;
		else if (angle < 245) val = 5;
		else if (angle < 293) val = 6;
		else if (angle < 338) val = 7;
		else if (angle < 360) val = 0;
		uint32_t *p = usb_joystick_data;
		switch(num) {
		  case 1:
			p[15] = (p[15] & 0xFFF0FFFF) | (val << 16); break;
		  case 2:
			p[15] = (p[15] & 0xFF0FFFFF) | (val << 20); break;
		  case 3:
			p[15] = (p[15] & 0xF0FFFFFF) | (val << 24); break;
		  case 4:
			p[15] = (p[15] & 0x0FFFFFFF) | (val << 28); break;
		  default:
			return;
		}
 
Hello, I have gone through this thread trying to figure out how to increase the resolution of the axis from the default 10 bits on a Teensy LC in the latest Arduino IDE version. Some sensors other than the built in ADC can outputs much more than 10 bits.
It seems people have provided several code changes to be able to support much more buttons, and I got lost in the code changes trying to figure out how to just change the resolution of the axis. BEfore I dig too much into this, has anybody just done this? And would it be possible for you to share the code?

If not, would it be possible for somebody to point me to the files to be modified? I am guessing the usb_desc.c definition would need to change, though I only see a copy of this file for the teensy3 and 4. Which one would cover the Teensy LC?
I have tried in the past changing the descriptor and this led to much trouble debugging on Windows. Would anybody be willing to point what they though would be the changes required in the decriptor?
Once this is done I am guessing the joystick packet format sent to the host would need to be modified to include more than 10 bits per sample.

Thank you in advance for any help you may be able to provide.

Regards,
JS
 
Back
Top