Road to FCC, Part II – HID shenanigans, A tale of a Hat (switch)

Continuing the Quest for a working FCC controller.

In this post I’ll go over on how the hat switch decided to be the thorn in my ass.

In the previous post, I’ve talked about reading the grip and sorting out the bits. I’ve opted for a 3 byte struct with first 19 bits as buttons, then on spare bit, and then 4 bits for the hat switch, as it is a different structure not related to the buttons.

Briefly, the hat switch is made out of 4 buttons, each a different direction, any combination indicates some direction up to a total of 8.

0x1 0x2 0x4 0x8
Trim Forward Trim Right Trim Aft Trim Left

So far so good.  initially I just copied things over from the example I found online this is a 8 way hat config

        0x09, 0x39,                     // Usage (Hat switch)
        0x15, 0x00,                     // Logical Minimum (0)
        0x25, 0x07,                     // Logical Maximum (7)
        0x35, 0x00,                     // Physical Minimum (0)
        0x46, 0x3B, 0x01,               // Physical Maximum (315)
        0x65, 0x14,                     // Unit (20)
        0x75, 0x04,                     // Report Size (4)
        0x95, 0x01,                     // Report Count (1)
        0x81, 0x42,                     // Input (variable,absolute,null_state)

However then started my adventure.  The device will not show it has a HAT switch in windows. Looking at the USB HID documentation I got the rough sense on what I should be declaring. but It would just wont work, It took me a while to figure out what went wrong. I’ve added the HID chunk after the buttons were already in place. and only after going the PDF a few times I noticed that Buttons are on “usage page 8” while the hat switch is with the axis on “usage page 1”.

I moved things over, and the Hat switch finally showed up on windows.

But my troubles didn’t end there. the arrow was never pointing the right way. and I couldn’t figure it out. So I left it and went to do something else. When I got back, I looked some more, and it seems that I have found me issue.

I was using a 4 bit so if we start from the top going clockwise at 45 degrees the values looks like this (integer) – in the bottom row however, lies the “secret” nobody talks about.. the values the descriptor expects to get.

Blank 0 45 90 135 180 225 270 315
0 1 3 2 6 4 12 8 9
8 0 1 2 3 4 5 6 7

So some conversion function was in order to get it to work as intended (which I samelessly borrowed online.. maybe from here):

uint8_t MapHat(uint8_t HatSwitch) {
uint8_t RetVal = 8;
switch (HatSwitch) {
//case 0: RetVal = 8; break; // uldr : center : hatButtons = B00000000
case 1: RetVal = 0; break; // Uldr : 0 : hatButtons = B0001
case 3: RetVal = 1; break; // ULdr : 45 : hatButtons = B0011
case 2: RetVal = 2; break; // uLdr : 90 : hatButtons = B0010
case 6: RetVal = 3; break; // uLDr : 135 : hatButtons = B0110
case 4: RetVal = 4; break; // ulDr : 180 : hatButtons = B0100
case 12: RetVal = 5; break; // ulDR : 225 : hatButtons = B1100
case 8: RetVal = 6; break; // uldR : 270 : hatButtons = B1000
case 9: RetVal = 7; break; // UldR : 315 : hatButtons = B1001
}
return RetVal;
}

And Now Hat switch works too… Yey!

FCC Controller Demo in Windows
FCC Controller Demo in Windows

 

Now All I need to do is wait for the postal service to move it’s lazy ass and get me my FCC so I can actually mount the thing (and tune sensitivities)….

Leave a Reply