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:
|
||||
# $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
|
|||
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
|
|||
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
|
|||
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}
|
||||
|
||||
|
|
|
@ -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() {
|
|||
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);
|
||||
|
|
|
@ -13,7 +13,7 @@ RF24 radio(7, 8); // CE, CSN
|
|||
|
||||
const byte address[13] = "OpenRetroPad";
|
||||
|
||||
Gamepad gamepad;
|
||||
GAMEPAD_CLASS gamepad;
|
||||
|
||||
void setup() {
|
||||
gamepad.begin();
|
||||
|
|
|
@ -146,7 +146,7 @@ static const int translateToHid[12] = {
|
|||
|
||||
GameControllers controllers;
|
||||
|
||||
Gamepad gamepad;
|
||||
GAMEPAD_CLASS gamepad;
|
||||
|
||||
void setup() {
|
||||
gamepad.begin();
|
||||
|
|
|
@ -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 {
|
|||
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
|
||||
|
|
|
@ -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 {
|
|||
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 {
|
|||
virtual void onStarted(BLEServer *pServer){};
|
||||
};
|
||||
|
||||
typedef BleGamepad Gamepad;
|
||||
|
||||
#endif // CONFIG_BT_ENABLED
|
||||
#endif // ESP32_BLE_GAMEPAD_H
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
|||
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 {
|
|||
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
|
||||
|
|
|
@ -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 {
|
|||
// 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 {
|
|||
}
|
||||
|
||||
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 {
|
|||
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;
|
||||
}
|
||||
|
||||
virtual void sendHidReport(const uint8_t cIdx, const void* d, int len) {
|
||||
gamepad[cIdx].send(d, len);
|
||||
}
|
||||
};
|
||||
|
||||
typedef UsbGamepad Gamepad;
|
||||
|
||||
#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>
|
||||
|
||||
#define ARDUINO_ARCH_ESP32 1
|
||||
|
@ -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…
Reference in New Issue