Browse Source

Add UsbRadio output, which switches to radio if not connected to usb-hid capable host

master
Travis Burtrum 2 years ago
parent
commit
1e78ac7fdc
  1. 17
      platformio.ini
  2. 5
      src/Debug.cpp
  3. 2
      src/RadioReceiver.cpp
  4. 2
      src/SnesNes.cpp
  5. 14
      src/gamepad/Debug-Gamepad/DebugGamepad.h
  6. 16
      src/gamepad/ESP32-BLE-Gamepad/BleGamepad.h
  7. 4
      src/gamepad/Gamepad.h
  8. 12
      src/gamepad/Radio-Gamepad/RadioGamepad.h
  9. 18
      src/gamepad/USB-Gamepad/UsbGamepad.h
  10. 58
      src/gamepad/UsbRadio-Gamepad/UsbRadioGamepad.h
  11. 14
      src/gamepad/common.h

17
platformio.ini

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
# supported values:
# $board: micro, esp32
# $input: radio, snes, debug
# $output: radio, usb, bt, debug
# $output: radio, usb, usbradio, bt, debug
# please note not all boards are compatible with all inputs/outputs
# for example esp32 can only do bt
# micro can only do radio or usb
@ -57,6 +57,11 @@ platform = atmelavr @@ -57,6 +57,11 @@ platform = atmelavr
build_flags = -DGAMEPAD_OUTPUT=3
src_filter = +<gamepad/ESP32-BLE-Gamepad>
[out-usbradio]
extends = out-usb, out-radio
build_flags = -DGAMEPAD_OUTPUT=4
src_filter = ${out-usb.src_filter} ${out-radio.src_filter}
# radio input
[in-radio]
@ -118,6 +123,11 @@ extends = micro, in-snes, out-radio @@ -118,6 +123,11 @@ extends = micro, in-snes, out-radio
src_filter = ${in-snes.src_filter} ${out-radio.src_filter}
build_flags = ${in-snes.build_flags} ${out-radio.build_flags}
[env:micro-snes-usbradio]
extends = micro, in-snes, out-usbradio
src_filter = ${in-snes.src_filter} ${out-usbradio.src_filter}
build_flags = ${in-snes.build_flags} ${out-usbradio.build_flags}
# debug input
[in-debug]
@ -149,3 +159,8 @@ extends = micro, in-debug, out-radio @@ -149,3 +159,8 @@ extends = micro, in-debug, out-radio
src_filter = ${in-debug.src_filter} ${out-radio.src_filter}
build_flags = ${in-debug.build_flags} ${out-radio.build_flags}
[env:micro-debug-usbradio]
extends = micro, in-debug, out-usbradio
src_filter = ${in-debug.src_filter} ${out-usbradio.src_filter}
build_flags = ${in-debug.build_flags} ${out-usbradio.build_flags}

5
src/Debug.cpp

@ -3,7 +3,9 @@ @@ -3,7 +3,9 @@
#include "gamepad/Gamepad.h"
Gamepad gamepad;
GAMEPAD_CLASS gamepad;
uint8_t c = 0;
void setup() {
Serial.begin(115200);
@ -14,7 +16,6 @@ void setup() { @@ -14,7 +16,6 @@ void setup() {
void loop() {
if (gamepad.isConnected()) {
// test code to automate sending to test RadioReceiver (or any gamepad impl)
uint8_t c = 0;
Serial.println("Press buttons 1 and 32. Move all axes to center. Set DPAD to down right.");
gamepad.press(c, BUTTON_1);
gamepad.press(c, BUTTON_32);

2
src/RadioReceiver.cpp

@ -13,7 +13,7 @@ RF24 radio(7, 8); // CE, CSN @@ -13,7 +13,7 @@ RF24 radio(7, 8); // CE, CSN
const byte address[13] = "OpenRetroPad";
Gamepad gamepad;
GAMEPAD_CLASS gamepad;
void setup() {
gamepad.begin();

2
src/SnesNes.cpp

@ -146,7 +146,7 @@ static const int translateToHid[12] = { @@ -146,7 +146,7 @@ static const int translateToHid[12] = {
GameControllers controllers;
Gamepad gamepad;
GAMEPAD_CLASS gamepad;
void setup() {
gamepad.begin();

14
src/gamepad/Debug-Gamepad/DebugGamepad.h

@ -3,6 +3,10 @@ @@ -3,6 +3,10 @@
#include <WString.h>
#ifndef GAMEPAD_CLASS
#define GAMEPAD_CLASS DebugGamepad
#endif
#include "../common.h"
class DebugGamepad : public AbstractGamepad {
@ -10,22 +14,20 @@ class DebugGamepad : public AbstractGamepad { @@ -10,22 +14,20 @@ class DebugGamepad : public AbstractGamepad {
DebugGamepad() : AbstractGamepad() {
}
void begin(void) {
virtual void begin(void) {
Serial.begin(115200);
Serial.println("DebugGamepad.begin");
}
void setAxes(const uint8_t cIdx, int16_t x, int16_t y, int16_t z, int16_t rZ, char rX, char rY, signed char hat) {
virtual void setAxes(const uint8_t cIdx, int16_t x, int16_t y, int16_t z, int16_t rZ, char rX, char rY, signed char hat) {
Serial.println("DebugGamepad.setAxes");
AbstractGamepad::setAxes(cIdx, x, y, z, rZ, rX, rY, hat);
}
void sync(const uint8_t cIdx) {
Serial.print("DebugGamepad.sync: ");
virtual void sendHidReport(const uint8_t cIdx, const void* d, int len) {
Serial.print("DebugGamepad.sendHidReport: ");
Serial.println(cIdx);
}
};
typedef DebugGamepad Gamepad;
#endif // USB_GAMEPAD_H

16
src/gamepad/ESP32-BLE-Gamepad/BleGamepad.h

@ -3,6 +3,10 @@ @@ -3,6 +3,10 @@
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#ifndef GAMEPAD_CLASS
#define GAMEPAD_CLASS BleGamepad
#endif
#include "../common.h"
#include "BLE2902.h"
@ -84,22 +88,22 @@ class BleGamepad : public AbstractGamepad { @@ -84,22 +88,22 @@ class BleGamepad : public AbstractGamepad {
this->connectionStatus = new BleConnectionStatus();
}
void begin(void) {
virtual void begin(void) {
xTaskCreate(this->taskServer, "server", 20000, (void *)this, 5, NULL);
}
void sync(const uint8_t cIdx) {
virtual void sendHidReport(const uint8_t cIdx, const void *d, int len) {
if (this->isConnected()) {
this->inputGamepad[cIdx]->setValue(gamepadReport, GAMEPAD_REPORT_LEN);
this->inputGamepad[cIdx]->setValue((uint8_t *)d, len);
this->inputGamepad[cIdx]->notify();
}
}
bool isConnected(void) {
virtual bool isConnected(void) {
return this->connectionStatus->connected;
}
void setBatteryLevel(uint8_t level) {
virtual void setBatteryLevel(uint8_t level) {
this->batteryLevel = level;
if (hid != 0)
this->hid->setBatteryLevel(this->batteryLevel);
@ -109,7 +113,5 @@ class BleGamepad : public AbstractGamepad { @@ -109,7 +113,5 @@ class BleGamepad : public AbstractGamepad {
virtual void onStarted(BLEServer *pServer){};
};
typedef BleGamepad Gamepad;
#endif // CONFIG_BT_ENABLED
#endif // ESP32_BLE_GAMEPAD_H

4
src/gamepad/Gamepad.h

@ -19,6 +19,10 @@ @@ -19,6 +19,10 @@
#include "ESP32-BLE-Gamepad/BleGamepad.h"
#elif GAMEPAD_OUTPUT == 4
#include "UsbRadio-Gamepad/UsbRadioGamepad.h"
#else
#error Unsupported value for GAMEPAD_OUTPUT, must be 0-3

12
src/gamepad/Radio-Gamepad/RadioGamepad.h

@ -7,6 +7,10 @@ @@ -7,6 +7,10 @@
#define GAMEPAD_REPORT_ARRAY_ADD 1
#ifndef GAMEPAD_CLASS
#define GAMEPAD_CLASS RadioGamepad
#endif
#include "../common.h"
RF24 radio(7, 8); // CE, CSN
@ -17,7 +21,7 @@ class RadioGamepad : public AbstractGamepad { @@ -17,7 +21,7 @@ class RadioGamepad : public AbstractGamepad {
RadioGamepad() : AbstractGamepad() {
}
void begin(void) {
virtual void begin(void) {
Serial.println("RadioGamepad.begin");
radio.begin();
radio.openWritingPipe(address);
@ -25,13 +29,11 @@ class RadioGamepad : public AbstractGamepad { @@ -25,13 +29,11 @@ class RadioGamepad : public AbstractGamepad {
radio.stopListening();
}
void sync(const uint8_t cIdx) {
virtual void sendHidReport(const uint8_t cIdx, const void* d, int len) {
Serial.println("RadioGamepad.sync");
gamepadReport[15] = cIdx;
radio.write(&gamepadReport, 16);
radio.write(d, 16);
}
};
typedef RadioGamepad Gamepad;
#endif // RADIO_GAMEPAD_H

18
src/gamepad/USB-Gamepad/UsbGamepad.h

@ -3,6 +3,10 @@ @@ -3,6 +3,10 @@
#include <WString.h>
#ifndef GAMEPAD_CLASS
#define GAMEPAD_CLASS UsbGamepad
#endif
#include "../common.h"
#include "HID.h"
@ -53,6 +57,8 @@ class Gamepad_ : public PluggableUSBModule { @@ -53,6 +57,8 @@ class Gamepad_ : public PluggableUSBModule {
// due to the USB specs, but Windows and Linux just assumes its in report mode.
protocol = HID_REPORT_PROTOCOL;
this->sentHidReportDescriptor = true;
return USB_SendControl(TRANSFER_PGM, _hidReportDescriptor, sizeof(_hidReportDescriptor));
}
@ -100,6 +106,7 @@ class Gamepad_ : public PluggableUSBModule { @@ -100,6 +106,7 @@ class Gamepad_ : public PluggableUSBModule {
}
public:
boolean sentHidReportDescriptor = false;
Gamepad_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) {
epType[0] = EP_TYPE_INTERRUPT_IN;
PluggableUSB().plug(this);
@ -121,11 +128,14 @@ class UsbGamepad : public AbstractGamepad { @@ -121,11 +128,14 @@ class UsbGamepad : public AbstractGamepad {
this->deviceManufacturer = deviceManufacturer;
}
void sync(const uint8_t cIdx) {
gamepad[cIdx].send(&gamepadReport, GAMEPAD_REPORT_LEN);
virtual bool isConnected(void) {
// if the first one is connected, we assume they all are
return gamepad[0].sentHidReportDescriptor;
}
};
typedef UsbGamepad Gamepad;
virtual void sendHidReport(const uint8_t cIdx, const void* d, int len) {
gamepad[cIdx].send(d, len);
}
};
#endif // USB_GAMEPAD_H

58
src/gamepad/UsbRadio-Gamepad/UsbRadioGamepad.h

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
#ifndef RADIO_USB_GAMEPAD_H
#define RADIO_USB_GAMEPAD_H
// number of button presses we wait for USB-HID to connect
// works within 1 for me but who knows...
#ifndef GAMEPAD_USBRADIO_DETECT_BUTTONS
#define GAMEPAD_USBRADIO_DETECT_BUTTONS 1
#endif
#ifndef GAMEPAD_CLASS
#define GAMEPAD_CLASS UsbRadioGamepad
#endif
#include "../Radio-Gamepad/RadioGamepad.h"
#include "../USB-Gamepad/UsbGamepad.h"
class UsbRadioGamepad : public AbstractGamepad {
public:
uint8_t checkCount = 0;
AbstractGamepad* gamepad = new UsbGamepad();
void (UsbRadioGamepad::*syncFunc)(const uint8_t cIdx, const void* d, int len) = &UsbRadioGamepad::syncDetectUsb;
UsbRadioGamepad() : AbstractGamepad() {
}
virtual void begin(void) {
gamepad->begin();
}
void syncDetectUsb(const uint8_t cIdx, const void* d, int len) {
if (++checkCount <= GAMEPAD_USBRADIO_DETECT_BUTTONS) {
if (gamepad->isConnected()) {
// we are connected to PC/phone/usb-hid-capable-device, stop checking
syncFunc = &UsbRadioGamepad::syncNoDetect;
} else if (checkCount == GAMEPAD_USBRADIO_DETECT_BUTTONS) {
// we assume we are connected to a power brick or power supply, and switch to radio
delete gamepad;
gamepad = new RadioGamepad();
gamepad->begin();
// stop trying to detect, it is what it is...
syncFunc = &UsbRadioGamepad::syncNoDetect;
}
}
gamepad->sendHidReport(cIdx, &gamepadReport, GAMEPAD_REPORT_LEN);
}
void syncNoDetect(const uint8_t cIdx, const void* d, int len) {
gamepad->sendHidReport(cIdx, &gamepadReport, GAMEPAD_REPORT_LEN);
}
virtual void sendHidReport(const uint8_t cIdx, const void* d, int len) {
(*this.*syncFunc)(cIdx, &gamepadReport, GAMEPAD_REPORT_LEN);
}
};
#endif // RADIO_GAMEPAD_H

14
src/gamepad/common.h

@ -1,4 +1,7 @@ @@ -1,4 +1,7 @@
#ifndef GAMEPAD_COMMON_H
#define GAMEPAD_COMMON_H
#include <Arduino.h>
#define ARDUINO_ARCH_ESP32 1
@ -241,5 +244,14 @@ class AbstractGamepad { @@ -241,5 +244,14 @@ class AbstractGamepad {
return ((b & _buttons[cIdx]) > 0);
}
virtual void sync(const uint8_t cIdx); // actually sends report
virtual void sync(const uint8_t cIdx) {
sendHidReport(cIdx, &gamepadReport, GAMEPAD_REPORT_LEN);
}
virtual void sendHidReport(const uint8_t cIdx, const void* d, int len); // actually sends report
virtual ~AbstractGamepad() {
}
};
#endif // GAMEPAD_COMMON_H

Loading…
Cancel
Save