Add UsbRadio output, which switches to radio if not connected to usb-hid capable host
This commit is contained in:
parent
7cf833e59f
commit
1e78ac7fdc
|
@ -13,7 +13,7 @@
|
||||||
# supported values:
|
# supported values:
|
||||||
# $board: micro, esp32
|
# $board: micro, esp32
|
||||||
# $input: radio, snes, debug
|
# $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
|
# please note not all boards are compatible with all inputs/outputs
|
||||||
# for example esp32 can only do bt
|
# for example esp32 can only do bt
|
||||||
# micro can only do radio or usb
|
# micro can only do radio or usb
|
||||||
|
@ -57,6 +57,11 @@ platform = atmelavr
|
||||||
build_flags = -DGAMEPAD_OUTPUT=3
|
build_flags = -DGAMEPAD_OUTPUT=3
|
||||||
src_filter = +<gamepad/ESP32-BLE-Gamepad>
|
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
|
# radio input
|
||||||
|
|
||||||
[in-radio]
|
[in-radio]
|
||||||
|
@ -118,6 +123,11 @@ extends = micro, in-snes, out-radio
|
||||||
src_filter = ${in-snes.src_filter} ${out-radio.src_filter}
|
src_filter = ${in-snes.src_filter} ${out-radio.src_filter}
|
||||||
build_flags = ${in-snes.build_flags} ${out-radio.build_flags}
|
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
|
# debug input
|
||||||
|
|
||||||
[in-debug]
|
[in-debug]
|
||||||
|
@ -149,3 +159,8 @@ extends = micro, in-debug, out-radio
|
||||||
src_filter = ${in-debug.src_filter} ${out-radio.src_filter}
|
src_filter = ${in-debug.src_filter} ${out-radio.src_filter}
|
||||||
build_flags = ${in-debug.build_flags} ${out-radio.build_flags}
|
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}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
|
|
||||||
#include "gamepad/Gamepad.h"
|
#include "gamepad/Gamepad.h"
|
||||||
|
|
||||||
Gamepad gamepad;
|
GAMEPAD_CLASS gamepad;
|
||||||
|
|
||||||
|
uint8_t c = 0;
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
@ -14,7 +16,6 @@ void setup() {
|
||||||
void loop() {
|
void loop() {
|
||||||
if (gamepad.isConnected()) {
|
if (gamepad.isConnected()) {
|
||||||
// test code to automate sending to test RadioReceiver (or any gamepad impl)
|
// 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.");
|
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_1);
|
||||||
gamepad.press(c, BUTTON_32);
|
gamepad.press(c, BUTTON_32);
|
||||||
|
|
|
@ -13,7 +13,7 @@ RF24 radio(7, 8); // CE, CSN
|
||||||
|
|
||||||
const byte address[13] = "OpenRetroPad";
|
const byte address[13] = "OpenRetroPad";
|
||||||
|
|
||||||
Gamepad gamepad;
|
GAMEPAD_CLASS gamepad;
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
gamepad.begin();
|
gamepad.begin();
|
||||||
|
|
|
@ -146,7 +146,7 @@ static const int translateToHid[12] = {
|
||||||
|
|
||||||
GameControllers controllers;
|
GameControllers controllers;
|
||||||
|
|
||||||
Gamepad gamepad;
|
GAMEPAD_CLASS gamepad;
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
gamepad.begin();
|
gamepad.begin();
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
|
|
||||||
#include <WString.h>
|
#include <WString.h>
|
||||||
|
|
||||||
|
#ifndef GAMEPAD_CLASS
|
||||||
|
#define GAMEPAD_CLASS DebugGamepad
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
|
||||||
class DebugGamepad : public AbstractGamepad {
|
class DebugGamepad : public AbstractGamepad {
|
||||||
|
@ -10,22 +14,20 @@ class DebugGamepad : public AbstractGamepad {
|
||||||
DebugGamepad() : AbstractGamepad() {
|
DebugGamepad() : AbstractGamepad() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void begin(void) {
|
virtual void begin(void) {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
Serial.println("DebugGamepad.begin");
|
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");
|
Serial.println("DebugGamepad.setAxes");
|
||||||
AbstractGamepad::setAxes(cIdx, x, y, z, rZ, rX, rY, hat);
|
AbstractGamepad::setAxes(cIdx, x, y, z, rZ, rX, rY, hat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sync(const uint8_t cIdx) {
|
virtual void sendHidReport(const uint8_t cIdx, const void* d, int len) {
|
||||||
Serial.print("DebugGamepad.sync: ");
|
Serial.print("DebugGamepad.sendHidReport: ");
|
||||||
Serial.println(cIdx);
|
Serial.println(cIdx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef DebugGamepad Gamepad;
|
|
||||||
|
|
||||||
#endif // USB_GAMEPAD_H
|
#endif // USB_GAMEPAD_H
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#ifndef GAMEPAD_CLASS
|
||||||
|
#define GAMEPAD_CLASS BleGamepad
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
|
||||||
#include "BLE2902.h"
|
#include "BLE2902.h"
|
||||||
|
@ -84,22 +88,22 @@ class BleGamepad : public AbstractGamepad {
|
||||||
this->connectionStatus = new BleConnectionStatus();
|
this->connectionStatus = new BleConnectionStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void begin(void) {
|
virtual void begin(void) {
|
||||||
xTaskCreate(this->taskServer, "server", 20000, (void *)this, 5, NULL);
|
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()) {
|
if (this->isConnected()) {
|
||||||
this->inputGamepad[cIdx]->setValue(gamepadReport, GAMEPAD_REPORT_LEN);
|
this->inputGamepad[cIdx]->setValue((uint8_t *)d, len);
|
||||||
this->inputGamepad[cIdx]->notify();
|
this->inputGamepad[cIdx]->notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isConnected(void) {
|
virtual bool isConnected(void) {
|
||||||
return this->connectionStatus->connected;
|
return this->connectionStatus->connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBatteryLevel(uint8_t level) {
|
virtual void setBatteryLevel(uint8_t level) {
|
||||||
this->batteryLevel = level;
|
this->batteryLevel = level;
|
||||||
if (hid != 0)
|
if (hid != 0)
|
||||||
this->hid->setBatteryLevel(this->batteryLevel);
|
this->hid->setBatteryLevel(this->batteryLevel);
|
||||||
|
@ -109,7 +113,5 @@ class BleGamepad : public AbstractGamepad {
|
||||||
virtual void onStarted(BLEServer *pServer){};
|
virtual void onStarted(BLEServer *pServer){};
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef BleGamepad Gamepad;
|
|
||||||
|
|
||||||
#endif // CONFIG_BT_ENABLED
|
#endif // CONFIG_BT_ENABLED
|
||||||
#endif // ESP32_BLE_GAMEPAD_H
|
#endif // ESP32_BLE_GAMEPAD_H
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
|
|
||||||
#include "ESP32-BLE-Gamepad/BleGamepad.h"
|
#include "ESP32-BLE-Gamepad/BleGamepad.h"
|
||||||
|
|
||||||
|
#elif GAMEPAD_OUTPUT == 4
|
||||||
|
|
||||||
|
#include "UsbRadio-Gamepad/UsbRadioGamepad.h"
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#error Unsupported value for GAMEPAD_OUTPUT, must be 0-3
|
#error Unsupported value for GAMEPAD_OUTPUT, must be 0-3
|
||||||
|
|
|
@ -7,6 +7,10 @@
|
||||||
|
|
||||||
#define GAMEPAD_REPORT_ARRAY_ADD 1
|
#define GAMEPAD_REPORT_ARRAY_ADD 1
|
||||||
|
|
||||||
|
#ifndef GAMEPAD_CLASS
|
||||||
|
#define GAMEPAD_CLASS RadioGamepad
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
|
||||||
RF24 radio(7, 8); // CE, CSN
|
RF24 radio(7, 8); // CE, CSN
|
||||||
|
@ -17,7 +21,7 @@ class RadioGamepad : public AbstractGamepad {
|
||||||
RadioGamepad() : AbstractGamepad() {
|
RadioGamepad() : AbstractGamepad() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void begin(void) {
|
virtual void begin(void) {
|
||||||
Serial.println("RadioGamepad.begin");
|
Serial.println("RadioGamepad.begin");
|
||||||
radio.begin();
|
radio.begin();
|
||||||
radio.openWritingPipe(address);
|
radio.openWritingPipe(address);
|
||||||
|
@ -25,13 +29,11 @@ class RadioGamepad : public AbstractGamepad {
|
||||||
radio.stopListening();
|
radio.stopListening();
|
||||||
}
|
}
|
||||||
|
|
||||||
void sync(const uint8_t cIdx) {
|
virtual void sendHidReport(const uint8_t cIdx, const void* d, int len) {
|
||||||
Serial.println("RadioGamepad.sync");
|
Serial.println("RadioGamepad.sync");
|
||||||
gamepadReport[15] = cIdx;
|
gamepadReport[15] = cIdx;
|
||||||
radio.write(&gamepadReport, 16);
|
radio.write(d, 16);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef RadioGamepad Gamepad;
|
|
||||||
|
|
||||||
#endif // RADIO_GAMEPAD_H
|
#endif // RADIO_GAMEPAD_H
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
|
|
||||||
#include <WString.h>
|
#include <WString.h>
|
||||||
|
|
||||||
|
#ifndef GAMEPAD_CLASS
|
||||||
|
#define GAMEPAD_CLASS UsbGamepad
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
|
||||||
#include "HID.h"
|
#include "HID.h"
|
||||||
|
@ -53,6 +57,8 @@ class Gamepad_ : public PluggableUSBModule {
|
||||||
// due to the USB specs, but Windows and Linux just assumes its in report mode.
|
// due to the USB specs, but Windows and Linux just assumes its in report mode.
|
||||||
protocol = HID_REPORT_PROTOCOL;
|
protocol = HID_REPORT_PROTOCOL;
|
||||||
|
|
||||||
|
this->sentHidReportDescriptor = true;
|
||||||
|
|
||||||
return USB_SendControl(TRANSFER_PGM, _hidReportDescriptor, sizeof(_hidReportDescriptor));
|
return USB_SendControl(TRANSFER_PGM, _hidReportDescriptor, sizeof(_hidReportDescriptor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +106,7 @@ class Gamepad_ : public PluggableUSBModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
boolean sentHidReportDescriptor = false;
|
||||||
Gamepad_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) {
|
Gamepad_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) {
|
||||||
epType[0] = EP_TYPE_INTERRUPT_IN;
|
epType[0] = EP_TYPE_INTERRUPT_IN;
|
||||||
PluggableUSB().plug(this);
|
PluggableUSB().plug(this);
|
||||||
|
@ -121,11 +128,14 @@ class UsbGamepad : public AbstractGamepad {
|
||||||
this->deviceManufacturer = deviceManufacturer;
|
this->deviceManufacturer = deviceManufacturer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sync(const uint8_t cIdx) {
|
virtual bool isConnected(void) {
|
||||||
gamepad[cIdx].send(&gamepadReport, GAMEPAD_REPORT_LEN);
|
// if the first one is connected, we assume they all are
|
||||||
|
return gamepad[0].sentHidReportDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void sendHidReport(const uint8_t cIdx, const void* d, int len) {
|
||||||
|
gamepad[cIdx].send(d, len);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef UsbGamepad Gamepad;
|
|
||||||
|
|
||||||
#endif // USB_GAMEPAD_H
|
#endif // USB_GAMEPAD_H
|
||||||
|
|
|
@ -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
|
|
@ -1,4 +1,7 @@
|
||||||
|
|
||||||
|
#ifndef GAMEPAD_COMMON_H
|
||||||
|
#define GAMEPAD_COMMON_H
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
#define ARDUINO_ARCH_ESP32 1
|
#define ARDUINO_ARCH_ESP32 1
|
||||||
|
@ -241,5 +244,14 @@ class AbstractGamepad {
|
||||||
return ((b & _buttons[cIdx]) > 0);
|
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…
Reference in New Issue