Hello all,
I'm trying to write an Arduino program to control a small go-cart with hoverboard motors and a usb steering wheel and pedals to control it.
I have connected the steering wheel to the arduino using a 'usb host module' and using the USB Host Library 2.0 I have a proof of principle working. On each event (button press or steering angle change), I get an update of all the angle and button states.
When I need to know now is how to implement this into my main code. The library example has 3 files. A .ino, a .cpp and a .h. Unlike I'm used to, I found that my steering wheel data was being read in the .cpp file. There is a variable called 'evt' there, that has all the states. And I can get specific values with 'evt->Z2' (for steering angle), or for example 'evt-<X' for some button states.
The question: How do I access this 'evt' variable from the main .ino sketch? I have a feeling I should not be doing my modifications in the .cpp file, but strictly in the .ino file. But I don't know how the access the data from there.
Thanks in advance! Here is the code:
The .ino file:
#include <usbhid.h>
#include <hiduniversal.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>
#include "hidjoystickrptparser.h"
USB Usb;
USBHub Hub(&Usb);
HIDUniversal Hid(&Usb);
JoystickEvents JoyEvents;
JoystickReportParser Joy(&JoyEvents);
void setup() {
Serial.begin(115200);
#if !defined(__MIPSEL__)
while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
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);
}
void loop() {
Usb.Task();
}
The .cpp file:
#include "hidjoystickrptparser.h"
JoystickReportParser::JoystickReportParser(JoystickEvents *evt) :
joyEvents(evt),
oldHat(0xDE),
oldButtons(0) {
for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++)
oldPad[i] = 0xD;
}
// Variabels.
int angletje = 0;
int Xval = 0;
int Yval = 0;
int DPADval = 0;
int Z2val = 0;
int Rzval = 0;
// Buttons //
// X-Channel
const int btn_X_base = 0; // base value (no buttons pressed)
const int btn_X_ids[] = {1, 2, 4, 8, 16, 32, 64, 128};
bool btn_X_states[] = {0, 0, 0, 0, 0, 0, 0, 0};
// Y-Channel
const int btn_Y_base = 224; // base value (no buttons pressed)
const int btn_Y_ids[] = {225, 226, 228, 232, 240};
bool btn_Y_states[] = {0, 0, 0, 0, 0};
// D-PAD Channel
const int btn_DPAD_base = 255; // base value
const int btn_DPAD_ids[] = {0, 1, 2, 3, 4, 5, 6, 7};
bool btn_DPAD_states[] = {0, 0, 0, 0, 0, 0, 0, 0};
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];
}
uint8_t hat = (buf[5] & 0xF);
// Calling Hat Switch event handler
if (hat != oldHat && joyEvents) {
joyEvents->OnHatSwitch(hat);
oldHat = hat;
}
uint16_t buttons = (0x0000 | buf[6]);
buttons <<= 4;
buttons |= (buf[5] >> 4);
uint16_t changes = (buttons ^ oldButtons);
// Calling Button Event Handler for every button changed
if (changes) {
for (uint8_t i = 0; i < 0x0C; i++) {
uint16_t mask = (0x0001 << i);
if (((mask & changes) > 0) && joyEvents) {
if ((buttons & mask) > 0)
joyEvents->OnButtonDn(i + 1);
else
joyEvents->OnButtonUp(i + 1);
}
}
oldButtons = buttons;
}
}
void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt) {
// Save raw values to variables.
Xval = evt->X;
Yval = evt->Y;
DPADval = evt->Z1;
Z2val = evt->Z2;
Rzval = evt->Rz;
// Check steering angle.
angletje = map(evt->Z2, 0, 255, -90, 90);
Serial.println("ANGLE:" + (String)angletje);
}
void JoystickEvents::OnHatSwitch(uint8_t hat) {
Serial.print("Hat Switch: ");
Serial.print(hat);
Serial.println("");
}
void JoystickEvents::OnButtonUp(uint8_t but_id) {
Serial.print("Up: ");
Serial.println(but_id, DEC);
}
void JoystickEvents::OnButtonDn(uint8_t but_id) {
Serial.print("Dn: ");
Serial.println(but_id, DEC);
}
The .h 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);
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(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
};
#endif // __HIDJOYSTICKRPTPARSER_H__