Custom Joystick with Teensy 2.0 ++

Status
Not open for further replies.

Whiplash

Member
Hey, I apologize in advance if my lingo is not up to par, I am very new to programming and my level of understand drivers or even how my mouse works after I plug it in is very limited so please bear with me.

I am working on my first teensy project. My goal is to make a switch panel for a flight simulator that works just like a joystick with a lot of buttons. The joystick feature that comes with the Teensyduino that I am currently using has 32 buttons, 6 axes, and 1 hat switch. This seems like a lot but I need more buttons. My question is this: Is there a way to customize the joystick so it has the maximum possible buttons and six separate axes? I don't need the hat switch at all. So far I have tried to work around this issue by treating the hat as eight different buttons but this has been causing some issues. By the way if it is possible to make a custom joystick driver or whatever for the teensy++ 2.0, does anyone know how many buttons I can make it have if I just want buttons and six separate axes?

Thank you for any help.





I don't think this is pertinent, but this is why I am not interested in using the hat feature. I'm using the simple button example that came with Teensyduino which uses the bounce function with rising and falling edge. The problem with the hat switch is I'm using mostly toggle and rotary switches so I want the teensy board to treat it like a pulse (instead of a constant on) by using the fallowing example:

// For a 5 position rotary switch that is using the 0°,45,90°,135,180° hat angles


Joystick.hat(0);
delay(200)
Joystick.hat(-1);

Joystick.hat(45);
delay(200)
Joystick.hat(-1);

Joystick.hat(90);
delay(200)
Joystick.hat(-1);

etc...


The problem is when my rotary switch goes to the button that is used for the 90° position it send a pulse to the 0° position first (I don't know why). I think the error has something to do with using -1 to reset the toggle but I am not sure. This is why I would like to remove the hat switch feature all together and just use joystick buttons.
 
My question is this: Is there a way to customize the joystick so it has the maximum possible buttons and six separate axes?

Yes, but this involves some pretty significant hacking on the USB code.

In theory, hundreds of buttons ought to be possible. Certainly the HID protocol and standard usage tables allow for pretty much any number. There's an entire HID usage page dedicated to buttons, so theoretically 65535 ought to be possible. Well, the USB code limits the HID report to a single packet, which has a maximum of 64 bytes, which means only 512 buttons can be crammed into the biggest HID report you'll be able to send, less the bits needed to send the 6 axes. Still, in theory, you can define a HID joystick with a *lot* of buttons.

In practice, the drivers on the USB host will probably impose some lower limit than the HID protocol. I have no idea what those limits will be. This is the sort of thing where often Linux has some insanely high limit and Windows has some disappointingly low limit. I'll confess, the only reason there are 32 in the code today is because the Windows joystick control panel shows 32 buttons. Windows might support many more, or 32 might actually be the upper limit. I have absolutely no idea. Maybe someone more knowledgeable about Windows could chime in? Or a really good sign would be if anyone knows of a commercial product that offers more than 32 buttons and claims to work with Windows?

So, if you're ready to dive into the code, knowing Windows might not support more than 32 even if you do everything absolutely right, the first place to start is in usb_desc.h (this is all going to be for Teensy 3.1, which is easier than Teensy 2.0, because when I made the new USB stack I designed it to be more easily edited based on lessons learned from the less-easily editable code I wrote years earlier).

Look for this:

Code:
#ifdef JOYSTICK_INTERFACE
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, 0x20,                     // Report Count (32)
        0x05, 0x09,                     // Usage Page (Button)
        0x19, 0x01,                     // Usage Minimum (Button #1)
        0x29, 0x20,                     // Usage Maximum (Button #32)
        0x81, 0x02,                     // Input (variable,absolute)
        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, 0x01,                     // Report Count (1)
        0x65, 0x14,                     // Unit (20)
        0x05, 0x01,                     // Usage Page (Generic Desktop)
        0x09, 0x39,                     // Usage (Hat switch)
        0x81, 0x42,                     // Input (variable,absolute,null_state)
        0x05, 0x01,                     // Usage Page (Generic Desktop)
        0x09, 0x01,                     // Usage (Pointer)
        0xA1, 0x00,                     // Collection ()
        0x15, 0x00,                     //   Logical Minimum (0)
        0x26, 0xFF, 0x03,               //   Logical Maximum (1023)
        0x75, 0x0A,                     //   Report Size (10)
        0x95, 0x04,                     //   Report Count (4)
        0x09, 0x30,                     //   Usage (X)
        0x09, 0x31,                     //   Usage (Y)
        0x09, 0x32,                     //   Usage (Z)
        0x09, 0x35,                     //   Usage (Rz)
        0x81, 0x02,                     //   Input (variable,absolute)
        0xC0,                           // End Collection
        0x15, 0x00,                     // Logical Minimum (0)
        0x26, 0xFF, 0x03,               // Logical Maximum (1023)
        0x75, 0x0A,                     // Report Size (10)
        0x95, 0x02,                     // Report Count (2)
        0x09, 0x36,                     // Usage (Slider)
        0x09, 0x36,                     // Usage (Slider)
        0x81, 0x02,                     // Input (variable,absolute)
        0xC0                            // End Collection
};
#endif

This defines all the data Teensy will send as the Joystick. It's how the computer "knows" what stuff your joystick has.

I believe all you'll need to do here is edit the report count and usage maximum in the first section about the buttons. Maybe just double it, to 64?

Next, look for this in usb_desc.h. It's in 2 places. Edit both.

Code:
#define JOYSTICK_SIZE         16

This is actually a maximum size. If you go over 16, you'll have to increase it.

Next, look in joystick.c. Find this part:

Code:
        }
        transmit_previous_timeout = 0;
        memcpy(tx_packet->buf, usb_joystick_data, 12);
        tx_packet->len = 12;
        usb_tx(JOYSTICK_ENDPOINT, tx_packet);
        //serial_print("ok\n");
        return 0;
}

Here is the actual size. It's 12 bytes. For every 8 buttons you add, the size will grow by 1 byte. So increase this. It MUST EXACTLY MATCH the report spec you edited. If you transmit a different number of bytes than the sum of all the stuff you defined, the PC will ignore you.

Edit: if you add stuff that isn't a multiple of 8 bits, there's extra hoops you have to jump through to specify unused bits so it pads out to an exact number of bytes. I wouldn't bother trying to add buttons in groups smaller than 8 or 32 (you'll see why 32 below....)

The last part will be the most challenging. It's also the part you can get not-quite-right and thing might sort-of work. It's all in usb_joystick.h.

First, find this. Actually, it's in both usb_joystick.h and usb_joystick.h.c

Code:
extern uint32_t usb_joystick_data[3];

The data was 12 bytes long. This is the actual data. It's only 3 because it's uint32_t, which is 4 bytes each. You need to increase this. It's ok to make it bigger than you need.

The rest of usb_joystick.h is just functions that change the bits within those 12 bytes when you call the functions. Since the buttons are at the beginning, when you add more buttons, you'll have to edit ALL the other stuff. If you get things wrong here, the joystick will still work (that is, if you don't hit some stupid limit in the operating system's drivers) but moving the axes will change the wrong bits, so you'll see other controls move in strange ways.

How exactly to edit this code involves C programming with shifts and logical and / or, which are a bit tricky to get right, but again, you can test these 1 by 1 until you get them all working. If you add buttons in increments of 32, most of this can be left as-is and just edit the array index numbers., since each 32 buttons will move everything after them to the next uint32_t in the array.


If you try all this, I hope you'll share your experience and coding here, especially if it actually works.

If none of this made any sense and sounds like horribly complex programming, then you probably be best off to design within the 32 button limitation. Or perhaps use 2 or more Teensy boards (32 buttons each), maybe linked by Serial1 or I2C to coordinate their efforts, if necessary?
 
Last edited:
I did a guide for creating a custom joystick with the Teesny++ 2.0 here. It doesn't go into great detail about the HID descriptors but I do give some external links to help.

If you are still stuck I would be happy with the code/descriptors.

As for the maximum buttons, there seems to be reports that windows/directx will support 128 buttons, but it seems common in games to have the 32 button limit. I would test with you game and find the limit, if you need more just send keystrokes for the rest.

Regards,

Les
 
On my long-term todo list is an expanded joystick, with many more axes and buttons. The main obstacle, aside from just finding the time with so many other projects like the audio lib, is testing.

If anyone can recommend a way I could test such a crazy joystick, like a utility or a specific game with a joystick test that shows all those buttons and axes, that would enable me to do such an expanded joystick in a future version of Teensyduino.
 
Thanks you for all the info! I think the real limit will be the number of I/O pins I have on my Teensy ++ 2.0 board. then again I guess I could set up some logic such as if button 1 and 2 are low (or some some arbitrary combination) flash button 3... and so on. Dange, I hope I can follow your guys instructions! I was thinking I might have to use two or more teensy ++ boards. The simulator I am going to be using this project for primarily will be DCS: P-51. I am aware that there is some kind of maximum number of buttons that either windows or the simulator have but I seem to think it was somewhere around 128 as well.

Here is a incomplete render of the panel I am trying to make. It doesn't look like I need a lot of button but most of the toggle switches have 3 positions (each one requires a separate button) and some of the rotary switches have up to 5 positions. If the maximum upper limit of buttons is really around 128 and I could use the logic I mentioned up earlier I might expand my panel to include even more functions.



P.S. I work for a manufacturing company which has several laser cutting tables as well as sheet metal forming tools and spot welders. Eventually, I will be making the panel out of stainless sheet metal but for now I am just using poster board. I have done a little more then what this next picture shows but it will give you an idea of what I am doing, in case you are interested.



I'll keep this tread updated as I make progress, which might be slow some times since we just added another addition to our family and my time is a little strapped at the moment.

Again thank you both for getting me off on the right foot. I read through Pointy's link too and I believe that will be very helpful as well!
 
If anyone can recommend a way I could test such a crazy joystick, like a utility or a specific game with a joystick test that shows all those buttons and axes, that would enable me to do such an expanded joystick in a future version of Teensyduino.

I could easy write a simple test app for windows using directx, I already have a directx joystick class I wrote for my Keybinder app.

I think the real limit will be the number of I/O pins I have on my Teensy ++ 2.0 board.

You could always do some key of matrix, I think an 8 x 8 matrix would give you 64 buttons but only use 16 pins.

Regards,

Les
 
A fellow member on the DCS simulator page confirmed that it can take a maximum of a 128 buttons. Any idea if the number of axis might affect this number as well? I asked the same question on the DCS form and still waiting to hear back. Right now I am thinking I would like to reconfigure the generic joystick to have six slider axes, and 128 buttons by making a 11x11 matrix plus another 7 which means I will use a total of 29 pins on my Teensy++ 2.0 board.
 
Ok I get my answer: DCS supports 128 buttons, 4 POV hats and 8 axes.

Any idea if they make a button matrix board with diode built in to eliminate ghosting. It seems like something that would be common enough you could buy it off the shelf.
 
so here is a part of the code I am trying to edit

Code:
static const uint8_t PROGMEM gamepad_hid_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, 0x20,                     // Report Count (64)
        0x05, 0x09,                     // Usage Page (Button)
        0x19, 0x01,                     // Usage Minimum (Button #1)
        0x29, 0x20,                     // Usage Maximum (Button #64)
        0x81, 0x02,                     // Input (variable,absolute)
        0x05, 0x01,                     // Usage Page (Generic Desktop)
        0x09, 0x01,                     // Usage (Pointer)
        0xA1, 0x00,                     // Collection ()
        0x15, 0x00,                     //   Logical Minimum (0)
        0x26, 0xFF, 0x03,               //   Logical Maximum (1023)
        0x75, 0x0A,                     //   Report Size (10)
        0x95, 0x04,                     //   Report Count (4)
        0x09, 0x30,                     //   Usage (X)
        0x09, 0x31,                     //   Usage (Y)
        0x09, 0x32,                     //   Usage (Z)
        0x09, 0x35,                     //   Usage (Rz)
        0x81, 0x02,                     //   Input (variable,absolute)
        0xC0,                           // End Collection
        0x15, 0x00,                     // Logical Minimum (0)
        0x26, 0xFF, 0x03,               // Logical Maximum (1023)
        0x75, 0x0A,                     // Report Size (10)
        0x95, 0x02,                     // Report Count (2)
        0x09, 0x36,                     // Usage (Slider)
        0x09, 0x36,                     // Usage (Slider)
        0x81, 0x02,                     // Input (variable,absolute)
        0xC0                            // End Collection
};

I tried deleting the part that included the hat switch and changing the button value from 32 to 64 from the report count and usage maximum. My question is what do I change the value on the left to? I don't get where 0x20 defines 32 buttons. Does that make sense? in Pointy's example I believe he used 0x0D where he defined 13 buttons. It's probably something stupid basic that I am missing but like I said I'm not really familiar with any USB hacking.

Thanks,
 
ha ha you guys are probably laughing at me. I understand now but to play it safe I think I will just use a hexadecimal converter. Thanks... I'll be back with more stupid questions.
 
Last edited:
It's alright, I'm happy to help if you're trying. Projects like this can be a great learning experience if you persevere.

You can actually put either hex or decimal into that table. Just take off the 0x and any leading zeros and the compiler will know it's base 10. Each individual number can be any format.
 
I didnt mention is earlier but I am following the steps that Pointy outlined because his example uses the teensy ++ 2.0. I see the similarities between both of your methods. Does your method also work for the teensy ++ 2.0?

So here is what I got. This should define a joystick with 64 buttons and 6 axis for a total of 64x1 + 6x10 or 124 bit.

I added a 4 bit padding right after I defined the buttons to round the number to 128. Does this all seem correct to you?

Code:
static const uint8_t PROGMEM gamepad_hid_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, 0x40,                     // Report Count (64)
        0x05, 0x09,                     // Usage Page (Button)
        0x19, 0x01,                     // Usage Minimum (Button #1)
        0x29, 0x40,                     // Usage Maximum (Button #64)
        0x81, 0x02,                     // Input (variable,absolute
	0x75, 0x01,             	// 	REPORT_SIZE (1)
	0x95, 0x04,            		// 	REPORT_COUNT (4)
	0x81, 0x02,             	//	INPUT (variable,absolute)
        0x05, 0x01,                     // Usage Page (Generic Desktop)
        0x09, 0x01,                     // Usage (Pointer)
        0xA1, 0x00,                     // Collection ()
        0x15, 0x00,                     //   Logical Minimum (0)
        0x26, 0xFF, 0x03,               //   Logical Maximum (1023)
        0x75, 0x0A,                     //   Report Size (10)
        0x95, 0x04,                     //   Report Count (4)
        0x09, 0x30,                     //   Usage (X)
        0x09, 0x31,                     //   Usage (Y)
        0x09, 0x32,                     //   Usage (Z)
        0x09, 0x35,                     //   Usage (Rz)
        0x81, 0x02,                     //   Input (variable,absolute)
        0xC0,                           // End Collection
        0x15, 0x00,                     // Logical Minimum (0)
        0x26, 0xFF, 0x03,               // Logical Maximum (1023)
        0x75, 0x0A,                     // Report Size (10)
        0x95, 0x02,                     // Report Count (2)
        0x09, 0x36,                     // Usage (Slider)
        0x09, 0x36,                     // Usage (Slider)
        0x81, 0x02,                     // Input (variable,absolute)
        0xC0                            // End Collection
};
 
It's alright, I'm happy to help if you're trying. Projects like this can be a great learning experience if you persevere.

You can actually put either hex or decimal into that table. Just take off the 0x and any leading zeros and the compiler will know it's base 10. Each individual number can be any format.

Oops I didn't see this post as I was typing my last reply. I totally know what you mean. I know this project is simple enough anyone with experience could probably knock it out of the park. I'm just a mechanical engineer who took c++ back in college almost ten years ago. I know how basic things work but I lack proficiency. I think half the fun of this project is going to be figuring all this code out. As for the sketch I think I have it handled. I'm not exactly sure how I am going to construct a button matrix but I have a general idea. I'll keep updating as I go though.
 
here is an example of the sketch I plan on using. I know it is not the most efficient way to code what I want to do but it's simple enough for me to understand and it will be easy to program one switch at a time. So for the first 4 buttons are momentary off/(on) switches and buttons 5 through 7 are part of a three position toggle on/off/on. I added a pulse delay for buttons 5 and 6 since the toggle will be always on and all I want is for it to pulse on momentarily then on the fallingedge side when ever I switch button 5 or 6 to off I want button 7 to pulse once. That is as far as I have got on the sketch. Really basic and simple but it works just the way I need it to. When I run out of pins on the teensy board I plan on just wiring combinations up so like when button 8 and 9 go low flash button 45 (or something like that). The tricky thing has been keeping track of the teensy pin buttons which start with 0 and the gamepad buttons which start with 1.

Code:
/* Buttons to USB Gamepad Example

   You must select Gamepad from the "Tools > USB Type" menu

   This example code is in the public domain.
*/

#include <Bounce.h>

// Create Bounce objects for each button.  The Bounce object
// automatically deals with contact chatter or "bounce", and
// it makes detecting changes very simple.
Bounce button0 = Bounce(0, 10);
Bounce button1 = Bounce(1, 10);  // 10 = 10 ms debounce time
Bounce button2 = Bounce(2, 10);  // which is appropriate for
Bounce button3 = Bounce(3, 10);  // most mechanical pushbuttons
Bounce button4 = Bounce(4, 10);
Bounce button5 = Bounce(5, 10);
Bounce button6 = Bounce(6, 10);
Bounce button7 = Bounce(7, 10);
Bounce button8 = Bounce(8, 10);
Bounce button9 = Bounce(9, 10);
Bounce button10 = Bounce(10, 10);
Bounce button11 = Bounce(11, 10);
Bounce button12 = Bounce(12, 10);
Bounce button13 = Bounce(13, 10);
Bounce button14 = Bounce(14, 10);
Bounce button15 = Bounce(15, 10);
Bounce button16 = Bounce(16, 10);
Bounce button17 = Bounce(17, 10);


void setup() {
  // Configure the pins for input mode with pullup resistors.
  // The pushbuttons connect from each pin to ground.  When
  // the button is pressed, the pin reads LOW because the button
  // shorts it to ground.  When released, the pin reads HIGH
  // because the pullup resistor connects to +5 volts inside
  // the chip.  LOW for "on", and HIGH for "off" may seem
  // backwards, but using the on-chip pullup resistors is very
  // convenient.  The scheme is called "active low", and it's
  // very commonly used in electronics... so much that the chip
  // has built-in pullup resistors!
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);  // Teensy++ LED, may need 1k resistor pullup
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(13, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
  pinMode(15, INPUT_PULLUP);
  pinMode(16, INPUT_PULLUP);
  pinMode(17, INPUT_PULLUP);
}

void loop() {
  
  //Gamepad.Z(analogRead(2));
  //Gamepad.Zrotate(analogRead(3));
  // Update all the buttons.  There should not be any long
  // delays in loop(), so this runs repetitively at a rate
  // faster than the buttons could be pressed and released.
  button0.update();
  button1.update();
  button2.update();
  button3.update();
  button4.update();
  button5.update();
  button6.update();
  button7.update();
  button8.update();
  button9.update();
  button10.update();
  button11.update();
  button12.update();
  button13.update();
  button14.update();
  button15.update();
  button16.update();
  button17.update();

  // Check each button for "falling" edge.
  // Update the Gamepad buttons only upon changes.
  // falling = high (not pressed - voltage from pullup resistor)
  //           to low (pressed - button connects pin to ground)
  if (button0.fallingEdge()) {
    Gamepad.button(1, 1);
  }
  if (button1.fallingEdge()) {
    Gamepad.button(2, 1);
  }
  if (button2.fallingEdge()) {
    Gamepad.button(3, 1);
  }
  if (button3.fallingEdge()) {
    Gamepad.button(4, 1);
  }
  if (button4.fallingEdge()) {
    Gamepad.button(5, 1);
    delay(200);
    Gamepad.button(5, 0);
  }
  if (button5.fallingEdge()) {
    Gamepad.button(6, 1);
    delay(200);
    Gamepad.button(6, 0);
  }
  if (button6.fallingEdge()) {
    Gamepad.button(7, 1);
  }
  if (button7.fallingEdge()) {
    Gamepad.button(8, 1);
  }
  if (button8.fallingEdge()) {
    Gamepad.button(9, 1);
  }
  if (button9.fallingEdge()) {
    Gamepad.button(10, 1);
  }
  if (button11.fallingEdge()) {
    Gamepad.button(12, 1);
  }
  if (button12.fallingEdge()) {
    Gamepad.button(13, 1);
  }
  if (button13.fallingEdge()) {
    Gamepad.button(14, 1);
  }
  if (button14.fallingEdge()) {
    Gamepad.button(15, 1);
  }
  if (button15.fallingEdge()) {
    Gamepad.button(16, 1);
  }
  if (button16.fallingEdge()) {
    Gamepad.button(17, 1);
  }
  if (button17.fallingEdge()) {
    Gamepad.button(18, 1);
  }
  // Check each button for "rising" edge
  // Update the Gamepad buttons only upon changes.
  // rising = low (pressed - button connects pin to ground)
  //          to high (not pressed - voltage from pullup resistor)
  if (button0.risingEdge()) {
    Gamepad.button(1, 0);
  }
  if (button1.risingEdge()) {
    Gamepad.button(2, 0);
  }
  if (button2.risingEdge()) {
    Gamepad.button(3, 0);
  }
  if (button3.risingEdge()) {
    Gamepad.button(4, 0);
  }
  if (button4.risingEdge() || button5.risingEdge()) {
    Gamepad.button(7, 1);
    delay(200);
    Gamepad.button(7, 0);
  }
  if (button6.risingEdge()) {
    
  }
  if (button7.risingEdge()) {
    
  }
  if (button8.risingEdge()) {
    
  }
  if (button9.risingEdge()) {
    
  }
  if (button10.risingEdge()) {
    
  }
  if (button11.risingEdge()) {
    Gamepad.button(12, 0);
  }
  if (button12.risingEdge()) {
    Gamepad.button(13, 0);
  }
  if (button13.risingEdge()) {
    Gamepad.button(14, 0);
  }
  if (button14.risingEdge()) {
    Gamepad.button(15, 0);
  }
  if (button15.risingEdge()) {
    Gamepad.button(16, 0);
  }
  if (button16.risingEdge()) {
    Gamepad.button(17, 0);
  }
  if (button17.risingEdge()) {
    Gamepad.button(18, 0);
  }
}
 
ha ha you guys are probably laughing at me. I understand now but to play it safe I think I will just use a hexadecimal converter. Thanks... I'll be back with more stupid questions.

If you want a really good laugh, how about this...

I was changing the button count in the USB descriptor one night, and couldn't work out why it wasn't changing in the game controller settings. I even tried it on my laptop. Anyway I eventually figured out why....

I was changing the numbers in the comments but NOT in the actual table! :eek: DOH!

So lessen number one... it's probably not a good idea to code after drinking 3/4 bottle of red wine.

Regards,

Les
 
I have made the quick and dirty Joystick Test app, you can download it here.

I have added support for 128 buttons (tedious work), 6 axis, 2 sliders and 4 POV, but it's not fully tested. It should work on XP up with Net Framework 3 and DirectX 9.

Let me know of any issues.

Regards,

Les
 
Does directx allow you to read the POV with finer granularity than 45 degrees?

According to msdn....

"The position is indicated in hundredths of a degree clockwise from north (away from the user). For indicators that have only five positions, the value for a controller is -1, 0, 9,000, 18,000, or 27,000."

I have not seen the first case used, only the later, using the former would be like an extra 4 axes I suppose.

Regards,

Les
 
A question is how to allocate 64 bytes for the most features.

I can't find any evidence anyone has ever made a mass-market joystick with POV hat switches using more than 9 positions. On the numerous requests I've heard from people wanting more joystick functions, I do not recall even 1 request for anything involving hat switches. Still, I'm leaning towards including 4 of them, but with only 4 bits each.

The most common request has been more 8 or 12 or more axes + sliders. More buttons is the other common request, and high res on the axes and sliders has also been requested.

Here's how I'm leaning towards using the 64 bytes:

128 buttons, 1 bit each
4 POV, 4 bits each
6 axes, 16 bits each
12 sliders, 12 bits each

Can directx read so many sliders?
 
Status
Not open for further replies.
Back
Top