Pages: [1]   Go Down
Author Topic: FAST HID Joystick converter for 2 digital joysticks  (Read 3539 times)
0 Members and 1 Guest are viewing this topic.
Germany
Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
if you want to connect some oldshool digital joysticks like the competition pro to your pc, ps3, raspberry pi or whatever here's a simple and fast solution. It's also perfect to build your retro commodore amiga/c64/atari/sega...

This code transforms the arduino leonardo board into a HID joystick converter for two digital joysticks.


put this into your HID.cpp to create 2 HID Gamepads:
Code:
//   Commodore /  Atari Joystick 1

   0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
   0x09, 0x05,                    // USAGE (Game Pad)
   0xa1, 0x01,                    // COLLECTION (Application)
   0x85, 0x03,                    //   REPORT_ID (3)
   0x09, 0x01,                    //   USAGE (Pointer)
   0xa1, 0x00,                    //   COLLECTION (Physical)
   0x09, 0x30,                    //     USAGE (X)
   0x09, 0x31,                    //     USAGE (Y)
   0x15, 0xff,                    //     LOGICAL_MINIMUM (-1)
   0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
   0x95, 0x02,                    //     REPORT_COUNT (2)
   0x75, 0x02,                    //     REPORT_SIZE (2) ; two bits to represent each axis
   0x81, 0x02,                    //     INPUT (Data,Var,Abs)
   0xc0,                          //   END_COLLECTION
   0x05, 0x09,                    //   USAGE_PAGE (Button)
   0x19, 0x01,                    //   USAGE_MINIMUM (Button 1)
   0x29, 0x01,                    //   USAGE_MAXIMUM (Button 1)
   0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
   0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
   0x95, 0x01,                    //   REPORT_COUNT (1) ; 1 button
   0x75, 0x01,                    //   REPORT_SIZE (1)
   0x81, 0x02,                    //   INPUT (Data,Var,Abs)
   0x95, 0x02,                    //   REPORT_COUNT (2) ; to pad out the bits into a number divisible by 8
   0x81, 0x03,                    //   INPUT (Const,Var,Abs)
    0x05, 0x09,                    //   USAGE_PAGE (Button)
   0x19, 0x02,                    //   USAGE_MINIMUM (Button 2)
   0x29, 0x02,                    //   USAGE_MAXIMUM (Button 2)
   0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
   0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
   0x95, 0x01,                    //   REPORT_COUNT (1) ; 1 button
   0x75, 0x01,                    //   REPORT_SIZE (1)
   0x81, 0x02,                    //   INPUT (Data,Var,Abs)
   0xc0,                          // END_COLLECTION
 
//   Commodore /  Atari Joystick 2

   0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
   0x09, 0x05,                    // USAGE (Game Pad)
   0xa1, 0x01,                    // COLLECTION (Application)
   0x85, 0x04,                    //   REPORT_ID (4)
    0xa1, 0x00,                    //   COLLECTION (Physical)  
   0x05, 0x09,                    //   USAGE_PAGE (Button)
   0x19, 0x01,                    //   USAGE_MINIMUM (Button 1)
   0x29, 0x02,                    //   USAGE_MAXIMUM (Button 2)
   0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
   0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
   0x95, 0x02,                    //   REPORT_COUNT (2) ; 2 buttons
   0x75, 0x01,                    //   REPORT_SIZE (1)
   0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x95, 0x02,                    //   REPORT_COUNT (2) ; to pad out the bits into a number divisible by 8
   0x81, 0x03,                    //   INPUT (Const,Var,Abs)
    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
   0x09, 0x30,                    //     USAGE (X)
   0x09, 0x31,                    //     USAGE (Y)
   0x15, 0xff,                    //     LOGICAL_MINIMUM (-1)
   0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
   0x95, 0x02,                    //     REPORT_COUNT (2)
   0x75, 0x02,                    //     REPORT_SIZE (2) ; two bits to represent each axis
   0x81, 0x02,                    //     INPUT (Data,Var,Abs)
   0xc0,                          //   END_COLLECTION
   0xc0                           // END_COLLECTION    


merge this into your existing sketch or use it as a standalone solution:

Code:

    uint8_t Joy;
    uint8_t MemoJoy1 ;
    uint8_t MemoJoy2 ;

    void setup() {

      // Joystick 1
      pinMode(0, INPUT_PULLUP);                  // configure as DigIn  with pull up
      pinMode(1, INPUT_PULLUP);
      pinMode(2, INPUT_PULLUP);
      pinMode(3, INPUT_PULLUP);
      pinMode(4, INPUT_PULLUP);
      pinMode(5, INPUT_PULLUP);
    
      // Joystick 2
      pinMode(A0, INPUT_PULLUP);
      pinMode(A1, INPUT_PULLUP);
      pinMode(A2, INPUT_PULLUP);
      pinMode(A3, INPUT_PULLUP);
      pinMode(A4, INPUT_PULLUP);
      pinMode(A5, INPUT_PULLUP);

    }

    void loop()
    {         // Joystick 1
          Joy = ~PIND & 0b10011111;     // read Port D, invert logic, mask relevant bits
          if (Joy != MemoJoy1) {        // state changed?
            HID_SendReport(3, &Joy, 1); // send HID report
            MemoJoy1 = Joy;             // save last state
          }
         // Joystick 2
          Joy = ~PINF & 0b11110011;
          if (Joy != MemoJoy2) {
            HID_SendReport(4, &Joy, 1);
            MemoJoy2 = Joy;
          }
       }

Joystick 1 must be hooked up to digital inputs 0...5, joystck 2 to analog inputs A0...A5.
This is the pin assignment:

Code:
   Joystick 1

    IO DB9  Function

    1   1   Forward
    0   2   Back
    2   3   Left
    3   4   Right
        5   not connected
    4   6   Button1
    5V  7   +5V  ( only needed if the joystick contains circuits like autofire,.. )
    GND 8   Ground
    6   9   Button2 (optional)

    Joystick 2

    IO DB9  Function

    A0  1   Forward
    A1  2   Back
    A2  3   Left
    A3  4   Right
        5   not connected
    A5  6   Button1
    5V  7   +5V
    GND 8   Ground
    A4  9   Button2 (optional)

Together with the arduino keyboard interface http://forum.arduino.cc/index.php?topic=139358.0
you have the complete keyrah functionality for an Amiga 500/1000/2000.

Olaf





* IMG_2753.jpg (66.45 KB, 648x484 - viewed 70 times.)

* IMG_2763.jpg (82.7 KB, 648x484 - viewed 107 times.)
« Last Edit: December 04, 2013, 06:40:11 am by olaf » Logged

Dipl. Ing. (FH) Olaf Berthold
Hardware- und Softwareentwicklung

Germany
Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

update: 2nd button added
Logged

Dipl. Ing. (FH) Olaf Berthold
Hardware- und Softwareentwicklung

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

interesting but i ask now,i know can do but how (im newbie)
leonardo or uno who have better thats ?
i need 32 button interface hid interface
8 analog inbut and 16 encoder inbut.
how make hid interface to have all thats ?
ino to in arduino, what more need ?
i understand leonardo have hid ready board no need change bootloader, and uno no have hid compatiple need bootloader new write.

and hid device can adding 32 button, 16 encoder,8 analog inbut.
but how smiley-sad
i need only buttons and encoders my computer.
analog can take old joystick.mean usb board if need,
Logged

Pages: [1]   Go Up
Jump to: