Interfacing Uno to Logitech Attack3 Joystick

I bought a Logitech Attack3 joystick at a garage sale for a couple of bucks and now I want to use it for something useful, like controlling a car or my small robotic arm. This joystick has 11 buttons and three sliders. I plugged it into a Sparkfun USB shield on top of an Arduino UNO and found some code online to get it up and running. It outputs hex values that tell me the slider values and the states of all the buttons. Where I am having difficulty is that I don't know C++ at all and the event handler and serial output commands are coming from the cpp file. I think that if I can get the output from the cpp file into the main loop in the ino file, I'll be able to do what I want with the data more easily. I plan to use a radio like XBee or Bluetooth to send commands based on the joystick output.

I cut down the code as much as I thought I could get away with. I'm hoping that someone can show me how to organize the code to allow me to do all my logic in the ino file.

Here is the INO file.

#include <usbhid.h>
#include <hiduniversal.h>
#include <usbhub.h>
#include <SPI.h>
#include "hidjoystickrptparser.h"

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

void setup() {
  Serial.begin(115200);
  pinMode(7, OUTPUT);
  digitalWrite(7, HIGH);
  if (Usb.Init() == -1)
    Serial.println("OSC did not start.");
  delay(200);
  if (!Hid.SetReportParser(0, &Joy))
    ErrorMessage<uint8_t > (PSTR("SetReportParser"), 1);
}

void loop() {
  Usb.Task();
  delay(10);
}

and the cpp file

#include "hidjoystickrptparser.h"

JoystickReportParser::JoystickReportParser(JoystickEvents *evt) :
joyEvents(evt),
oldButtons(0) {
        for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++)
                oldPad[i] = 0xD;
}

void JoystickReportParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
        bool match = true;

        // Checking if there are changes in report since the method was last called  
        for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++)
                if (buf[i] != oldPad[i]) {
                        match = false;
                        break;
                }

        // Calling Game Pad event handler
        if (!match && joyEvents) {
                joyEvents->OnGamePadChanged((const GamePadEventData*)buf);
                for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++) oldPad[i] = buf[i];
        }

        uint16_t buttons = (0x0000 | buf[6]);
        buttons <<= 4;
        buttons |= (buf[5] >> 4);
        uint16_t changes = (buttons ^ oldButtons);

}

void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt) {
        Serial.print("Joystick X: ");
        PrintHex<uint8_t > (evt->X, 0x80);
        Serial.print("\tJoystick Y: ");
        PrintHex<uint8_t > (evt->Y, 0x80);
        Serial.print("\tTrim: ");
        PrintHex<uint8_t > (evt->Z1, 0x80);
        Serial.print("\tSW1-8: ");
        PrintHex<uint8_t > (evt->Z2, 0x80);
        Serial.print("  SW9-11: ");
        PrintHex<uint8_t > (evt->Rz, 0x80);
        Serial.println("\t");

and the header file

#if !defined(__HIDJOYSTICKRPTPARSER_H__)
#define __HIDJOYSTICKRPTPARSER_H__

#include <usbhid.h>

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

class JoystickEvents {
public:
        virtual void OnGamePadChanged(const GamePadEventData *evt);
};

#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(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
};

#endif

Here is what the output looks like in the serial monitor

Joystick X: 80  Joystick Y: 82  Trim: 7A    SW1-8: 00  SW9-11: 00   
Joystick X: 7B  Joystick Y: 80  Trim: 7A    SW1-8: 00  SW9-11: 00   
Joystick X: 7B  Joystick Y: 7F  Trim: 7A    SW1-8: 00  SW9-11: 00   
Joystick X: 7B  Joystick Y: 7F  Trim: 7A    SW1-8: 00  SW9-11: 01   
Joystick X: 7B  Joystick Y: 7F  Trim: 7A    SW1-8: 00  SW9-11: 00

attack3.png

You create an instance of the JoystickReportParser class, telling it where to put data for events that happen, called Joy.

The rest of your code never uses that instance. It really should.

There was clearly more to the cpp file than you posted.

Hi Paul,

With the help of a much more experienced programmer at work, it has been solved. After I clean up the code, I will post the complete solution here.