how divide hex values / USBHidJoystick HEX<-->DEC Problem

hi guys,

i have the problem that i get hex values from the usb-hid-joystick, which is connected to the usb host of a MEGA ADK. Im using the USBHost2 Library.

i get the hex values from the Joystick but the Joystick has in some axes a resolution of 1024 steps. the hex values will be sended in pairs; and here is the problem that until a resolution of 255 the hex value is a pair, but above its a tripple.

Is there a possibility to devide a HEX value? Or a possibility to send bigger values (over DEC 255) in HEX?

HID.ino

#include <avr/pgmspace.h>
#include <avrpins.h>
#include <max3421e.h>
#include <usbhost.h>
#include <usb_ch9.h>
#include <Usb.h>
#include <usbhub.h>
#include <avr/pgmspace.h>
#include <address.h>
#include <hid.h>
#include <hiduniversal.h>

#include "hidjoystickrptparser.h"

#include <printhex.h>
#include <message.h>
#include <hexdump.h>
#include <parsetools.h>

USB                                             Usb;
USBHub                                          Hub(&Usb);
HIDUniversal                                    Hid(&Usb);
JoystickEvents                                  JoyEvents;
JoystickReportParser                            Joy(&JoyEvents);

int DI_Val[12];                  // total digital input vars, USB only

// ********************************************************************* Setup ************************************************************************

void setup()
{
  Serial.begin( 115200 );
  Serial.println("Start");

  if (Usb.Init() == -1)
      Serial.println("OSC did not start.");
      
  delay( 200 );

  if (!Hid.SetReportParser(0, &Joy))
      ErrorMessage<uint8_t>(PSTR("SetReportParser"), 1  ); 
}


// ******************************************************************** Main Loop ********************************************************************
void loop()
{
    Usb.Task();
    ReadDigital();
    delay(50);
}

InputOutput.ino

void ReadDigital() 
{
  extern int JoyVarBtn;
  extern int JoyVarX;
  extern int JoyVarY;
  extern int JoyVarZ;
  extern int JoyVarBtnBase;
  extern int JoyVarHAT;

// ++++++++++++++++++++++++++++++++++++++++ Buttons Top of Stick ++++++++++++++++++++++++++++++++++
  
    if (JoyVarBtn == 8) {}            //not pressed
    if (JoyVarBtn == 24) { Serial.println("front"); }           //front
    if (JoyVarBtn == 40) { }           //top left
    if (JoyVarBtn == 72) { }           //top re oben
    if (JoyVarBtn == 136) { }          //top re unten
    if (JoyVarBtn == 0) { }            //top circle up
    if (JoyVarBtn == 1) { }            //top circle re oben
    if (JoyVarBtn == 2) { }            //top circle re   
    if (JoyVarBtn == 3) { }            //top circle re unten
    if (JoyVarBtn == 4) { }            //top circle unten
    if (JoyVarBtn == 5) { }            //top circle unten li
    if (JoyVarBtn == 6) { }            //top circle li
    if (JoyVarBtn == 7) { }            //top circle li oben

// ++++++++++++++++++++++++++++++++++++++++ Achsen Stick +++++++++++++++++++++++++++++++++++++++++++
    
    if (JoyVarX == ) { }    // left - right
    
    if (JoyVarY == ) { }    // forward - backwards
    
    if (JoyVarZ == ) { }    // twist

// ++++++++++++++++++++++++++++++++++++++++ Buttons Base +++++++++++++++++++++++++++++++++++++++++++
    
    if (JoyVarBtnBase == 16 ) { }
    if (JoyVarBtnBase == 8) { }
    if (JoyVarBtnBase == 32) { }
    if (JoyVarBtnBase == 4) { }
    if (JoyVarBtnBase == 67) { }
    
    if (JoyVarHAT == ) { }    
    
     
}

hidrtparser.cpp

void ReadDigital() 
{
  extern int JoyVarBtn;
  extern int JoyVarX;
  extern int JoyVarY;
  extern int JoyVarZ;
  extern int JoyVarBtnBase;
  extern int JoyVarHAT;

// ++++++++++++++++++++++++++++++++++++++++ Buttons Top of Stick ++++++++++++++++++++++++++++++++++
  
    if (JoyVarBtn == 8) {}            //not pressed
    if (JoyVarBtn == 24) { Serial.println("front"); }           //front
    if (JoyVarBtn == 40) { }           //top left
    if (JoyVarBtn == 72) { }           //top re oben
    if (JoyVarBtn == 136) { }          //top re unten
    if (JoyVarBtn == 0) { }            //top circle up
    if (JoyVarBtn == 1) { }            //top circle re oben
    if (JoyVarBtn == 2) { }            //top circle re   
    if (JoyVarBtn == 3) { }            //top circle re unten
    if (JoyVarBtn == 4) { }            //top circle unten
    if (JoyVarBtn == 5) { }            //top circle unten li
    if (JoyVarBtn == 6) { }            //top circle li
    if (JoyVarBtn == 7) { }            //top circle li oben

// ++++++++++++++++++++++++++++++++++++++++ Achsen Stick +++++++++++++++++++++++++++++++++++++++++++
    
    if (JoyVarX == ) { }    // left - right
    
    if (JoyVarY == ) { }    // forward - backwards
    
    if (JoyVarZ == ) { }    // twist

// ++++++++++++++++++++++++++++++++++++++++ Buttons Base +++++++++++++++++++++++++++++++++++++++++++
    
    if (JoyVarBtnBase == 16 ) { }
    if (JoyVarBtnBase == 8) { }
    if (JoyVarBtnBase == 32) { }
    if (JoyVarBtnBase == 4) { }
    if (JoyVarBtnBase == 67) { }
    
    if (JoyVarHAT == ) { }    
    
     
}

hidrptparser.h

#if !defined(__HIDJOYSTICKRPTPARSER_H__)
#define __HIDJOYSTICKRPTPARSER_H__

#include <inttypes.h>
#include <avr/pgmspace.h>
#include "avrpins.h"
#include "max3421e.h"
#include "usbhost.h"
#include "usb_ch9.h"
#include "Usb.h"

#if defined(ARDUINO) && ARDUINO >=100
#include "Arduino.h"
#else
#include <WProgram.h>
#endif

#include "printhex.h"
#include "hexdump.h"
#include "message.h"
#include "confdescparser.h"
#include "hid.h"

struct GamePadEventData
{
	uint8_t X, Y, Z1, Z2, Rz;
};

class JoystickEvents
{
public:
	virtual void OnGamePadChanged(const GamePadEventData *evt);
	virtual void OnHatSwitch(uint8_t hat);
	virtual void OnButtonUp(uint8_t but_id);
	virtual void OnButtonDn(uint8_t but_id);
};

#define RPT_GEMEPAD_LEN		5

class JoystickReportParser : public HIDReportParser
{
	JoystickEvents		*joyEvents;

	uint8_t				oldPad[RPT_GEMEPAD_LEN];
	uint8_t				oldHat;
	uint16_t			oldButtons;

public:
	JoystickReportParser(JoystickEvents *evt);

	virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
};

#endif // __HIDJOYSTICKRPTPARSER_H__

Sounds like you can expect to get some sort of marker byte plus one or two data bytes, so once you know what value the marker byte contains and the order of the three bytes in each message you will be in a position to identify the one or two bytes that contain the input value. (My guess would be that the marker byte contains zero.) If the value consists of one data byte, you can just cast that to an unsigned int to get a 16-bit value. If it's in two bytes then you will need to combine the two eight-bit values into one sixteen-bit value.

That sounds like what i found out. I got a modyfied version of the USBHost2 library from www.circuitsathome.com, When i compare these to different parts from the "old" and the "modyfied" library

modiyfied:

struct GamePadEventData
{
  union { //axes and hut switch
    uint32_t axes;
    struct {
      uint32_t x : 10;
      uint32_t y : 10;
      uint32_t hat : 4;
      uint32_t twist : 8;      
    };
  };
  uint8_t buttons_a;
  uint8_t slider;
  uint8_t buttons_b;
};

old:

struct GamePadEventData
{
	uint8_t X, Y, Z1, Z2, Rz;
};

At the "old" i get every function of my Joystick but the X and Y axes has 4 times the value 255 cause of the override of the HEX and the HAT Button has 8 times 0 to 15...only god knows why. The "modyfied" is recognising back and forward right. in the x axes only left and only the half of the buttons.
Unfortunately i dont know where to find the USB data protokol from the Microsoft Sidewinder Precision Pro. And i didnt find a free USB protocol monitor...

How could i find out the byte/values for my joystick?

If you are looking to convert a 10 bit number (0-1023) to 8 bit (0-255), then shift right works for me. Use PeterH's suggestion to convert the two bytes to an integer, then shift the integer right 2 bits. Something like this.

byte joystickXLow = 255;
byte joystickXHigh = 3;

int joystickX = joystickXHigh;
// shift high byte into position
joystickX = joystickX << 8;
// OR with low byte
joystickX = joystickX | joystickXLow;
// shift the integer right 2 bits to divide by 4
joystickX = joystickX >> 2;

Oh thanks!...but i dont get it...thats too big kung fu for me :wink: it looks easy but i dont get what these lines are doing.

No kung fu. This is the easy part. This constructs an integer from two bytes, then divides by 4.

// These are the two bytes from the joystick.
// These values will equal 1023
byte joystickXLow = 255;
byte joystickXHigh = 3;

// Construct the integer
// Put the high byte into the integer
int joystickX = joystickXHigh;
// shift high byte into position
joystickX = joystickX << 8;
// OR with low byte
joystickX = joystickX | joystickXLow;

// shift the integer right 2 bits to divide by 4
joystickX = joystickX >> 2;

// Display the result to insure it is correct
Serial.println(joystickX);

SurferTim's bit shifting is based on the fact that the bits of a data item are binary, or base 2, numbering system. With a base 10 numbering system, shifting one bit to the left increases the value from 1 to 10. Shifting one more position turns the 10 into 100. Therefore, each leftward shift multiplies by 10, hence a Base 10 numbering system we all know and love. Bit shifting in binary is similar, but uses a Base 2 numbering system. Therefore, shifting the binary value for 1:

00000001

left one bit yields:

00000010

which is the value 2 in binary. Shift it one more place to the left:

00000100

and the value is 4. Therefore, bit shifting left for a binary number has the effect of doubling the value for each shift, while shifting right one bit has the effect of dividing by 2. It then follows that each bit position is the value of 2 raised to the power of its respective bit position. Think about it...

Hey Tim and econjack,

im thankful and sorry but im a bit confused and a newbie in this arduino buisness.

Okay so i read about arithmetic and logical shift.It is like i thought.I understand the technic and believe the mathematic....but i should think about it to get the mathematic :wink: but i finally got it!

But unfotunately i have some more questions...hopefully im coming closer and find my total understanding to it.

Where did you get the values? are these only example values or are these values for devision? if its the second case....why 3 for the high value?

byte joystickXLow = 255;
byte joystickXHigh = 3;

and what does this means?

// OR with low byte
joystickX = joystickX | joystickXLow;

I get the feeling that i hvae the wrong way of logical thinking:

So in my case, i think, im getting something like this "FC F1 87 83 00 02 00". But one double --> FC F1 87 83 00 02 00, is getting overridden.

and that is what im getting here in my code

struct GamePadEventData
{
	uint8_t X, Y, Z1, Z2, Rz;
};

But isnt here the first problem. The uint_8t can only get 8bit but the EventData which will be put into it has 10bit?! That means i have to shift before the uint8_t will be "filled" with the values of the Event.

The 3 is the high bits (bits 8 and 9). The 255 is the low bits (bits 0 to 7).
(3 * 256) + 255 = 1023

The OR combines the low byte with the high byte already shifted into place.

edit Here it is in binary. I split the integer with a space so you can see the bytes.

3 = 0000011
255 = 11111111

(int) 00000000 00000011 << 8 = 00000011 00000000
(int) OR with 11111111 = 00000011 11111111

(int) 00000011 11111111 >> 2 = 00000000 11111111

okay, technic structure: check!

A big sorry! i thought i wrote it in the first thread but i forgot it (i wrote it in another thread)!

In the "old" patch i get as value in the x and y axes a few times 0-255;means as little sketch:

0
.
.
252
+
0....255/0....255 +Jostick Stick+ 0.....255/0.......255
+
0
.
.
252

in the "modyfied" patch:

x-axe is only regognised to the left side/value from around 300 to 0
y-axe is great recognised 0-1024

So both are not really working for me and i have to modify them. So i think:

  1. I should know the USB protocol and the values of the Joystick.But how can i get them?
  2. I have to get the right structure for the values.

This is too short

struct GamePadEventData
{
	uint8_t X, Y, Z1, Z2, Rz;
};

and that doesnt fit for my sidewinder joystick/but is big enough for the values.

struct GamePadEventData
{
union { //axes and hut switch
uint32_t axes;
struct {
uint32_t x : 10;
uint32_t y : 10;
uint32_t hat : 4;
uint32_t twist : 8;
};
};
uint8_t buttons_a;
uint8_t slider;
uint8_t buttons_b;
};

So is it possible to change the first code as simple as possible to...okay its not possible :wink: i tried it

struct GamePadEventData
{
	uint10_t X, Y, Z1, Z2, Rz;
};

gnom

You made my day!

i have this joystick:IP Desktop USB

With:

struct GamePadEventData
{
  uint16_t X, Y, Z1, Z2, Rz; 
};

And

void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt) {
 
  Serial.print(" X:");
  Serial.print(evt->X, DEC);
  Serial.print("  Y:");
  Serial.print(evt->Y, DEC);
  Serial.print("  Z:");
  Serial.print(evt->Z1);
  Serial.print("  Button:");
  Serial.print(evt->Z2);
  Serial.println("");
  
  
}

I get all the correct values and buttons mapped!

Thanks!

Daniel