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