mr.Spinner: more natural axis range for paddles, option for single device, support for paddle and spinner at the same time.

This commit is contained in:
sorgelig 2020-02-25 20:01:51 +08:00
parent b75acc4de2
commit f812ceff60
2 changed files with 78 additions and 83 deletions

View File

@ -46,8 +46,8 @@ static const uint8_t _hidReportDescriptor[] PROGMEM = {
0xa1, 0x00, // COLLECTION (Physical) 0xa1, 0x00, // COLLECTION (Physical)
0x09, 0x30, // USAGE (X) 0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y) 0x09, 0x31, // USAGE (Y)
0x15, 0x80, // LOGICAL_MINIMUM (-128) 0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x7f, // LOGICAL_MAXIMUM (127) 0x26, 0xFF, 0x00, // LOGICAL_MAXIMUM (255)
0x95, 0x02, // REPORT_COUNT (2) 0x95, 0x02, // REPORT_COUNT (2)
0x75, 0x08, // REPORT_SIZE (8) 0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x02, // INPUT (Data,Var,Abs) 0x81, 0x02, // INPUT (Data,Var,Abs)

View File

@ -80,6 +80,9 @@
// Optional parameter. Leave it commented out. // Optional parameter. Leave it commented out.
//#define SPINNER_SENSITIVITY 1 //#define SPINNER_SENSITIVITY 1
// Set it to 1 if you want only single input device.
#define DEV_NUM 2
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// pins map // pins map
@ -111,46 +114,16 @@ const char *gp_serial = "MiSTer PD/SP v1";
#include <ResponsiveAnalogRead.h> #include <ResponsiveAnalogRead.h>
#include "Gamepad.h" #include "Gamepad.h"
Gamepad_ Gamepad[2]; Gamepad_ Gamepad[DEV_NUM];
ResponsiveAnalogRead analog[2] = {ResponsiveAnalogRead(pdlpin[0], true),ResponsiveAnalogRead(pdlpin[1], true)}; ResponsiveAnalogRead analog[2] = {ResponsiveAnalogRead(pdlpin[0], true),ResponsiveAnalogRead(pdlpin[1], true)};
int8_t pdlena[2] = {0,0}; int8_t pdlena[2] = {0,0};
uint16_t drvpos[2]; uint16_t drvpos[2];
int16_t drvX[2] = {0,0}; int16_t drvX[2] = {0,0};
void setup() #define SP_MAX ((SPINNER_PPR*4*270UL)/360)
{ const uint16_t sp_max = SP_MAX;
float snap = .01; int32_t sp_clamp[2] = {SP_MAX/2,SP_MAX/2};
float thresh = 8.0;
for(int idx=0; idx<2; idx++)
{
Gamepad[idx].reset();
pinMode(encpin[idx][0], INPUT_PULLUP);
pinMode(encpin[idx][1], INPUT_PULLUP);
pinMode(dbtnpin[idx], INPUT_PULLUP);
drv_proc(idx);
drvpos[idx] = 0;
attachInterrupt(digitalPinToInterrupt(encpin[idx][0]), idx ? drv1_isr : drv0_isr, CHANGE);
attachInterrupt(digitalPinToInterrupt(encpin[idx][1]), idx ? drv1_isr : drv0_isr, CHANGE);
pdlena[idx] = 0;
pinMode(pbtnpin[idx], INPUT_PULLUP);
pinMode(pdlpin[idx], INPUT);
analog[idx].setSnapMultiplier(snap);
analog[idx].setActivityThreshold(thresh);
}
}
void loop()
{
sendState(0);
sendState(1);
}
const uint16_t sp_max = ((SPINNER_PPR*4*270UL)/360);
int32_t sp_clamp[2] = {0,0};
void drv_proc(int8_t idx) void drv_proc(int8_t idx)
{ {
@ -185,35 +158,66 @@ void drv1_isr()
drv_proc(1); drv_proc(1);
} }
const int16_t sp_step = (SPINNER_PPR*10)/(20*SPINNER_SENSITIVITY); void setup()
{
float snap = .01;
float thresh = 8.0;
void sendState(byte idx) for(int idx=0; idx<DEV_NUM; idx++)
{
Gamepad[idx].reset();
pinMode(encpin[idx][0], INPUT_PULLUP);
pinMode(encpin[idx][1], INPUT_PULLUP);
pinMode(dbtnpin[idx], INPUT_PULLUP);
drv_proc(idx);
drvpos[idx] = 0;
attachInterrupt(digitalPinToInterrupt(encpin[idx][0]), idx ? drv1_isr : drv0_isr, CHANGE);
attachInterrupt(digitalPinToInterrupt(encpin[idx][1]), idx ? drv1_isr : drv0_isr, CHANGE);
pdlena[idx] = 0;
pinMode(pbtnpin[idx], INPUT_PULLUP);
pinMode(pdlpin[idx], INPUT);
analog[idx].setSnapMultiplier(snap);
analog[idx].setActivityThreshold(thresh);
}
}
const int16_t sp_step = (SPINNER_PPR*10)/(20*SPINNER_SENSITIVITY);
void loop()
{ {
// LEDs off // LEDs off
TXLED1; //RXLED1; TXLED1; //RXLED1;
analog[idx].update(); for(int idx=0; idx<DEV_NUM; idx++)
// paddle
int8_t newA = !digitalRead(pbtnpin[idx]);
//int8_t newB = 0; // reserved for paddles mixed in a single USB controller.
int8_t newX = 0;
int8_t newY = 0;
// spinner
int8_t newC = !digitalRead(dbtnpin[idx]);
int8_t newR = 0;
int8_t newL = 0;
if(newA) pdlena[idx] = 1;
if(newC) pdlena[idx] = 0;
if(pdlena[idx])
{
newX = (analog[idx].getValue()>>2) ^ 0x80;
}
else
{ {
analog[idx].update();
// paddle
int8_t newA = !digitalRead(pbtnpin[idx]);
//int8_t newB = 0; // reserved for paddles mixed in a single USB controller.
int8_t newX = 0;
int8_t newY = 0;
// spinner
int8_t newC = !digitalRead(dbtnpin[idx]);
int8_t newR = 0;
int8_t newL = 0;
if(newA) pdlena[idx] = 1;
if(newC) pdlena[idx] = 0;
if(pdlena[idx])
{
newX = (analog[idx].getValue()>>2);
}
else
{
#ifdef PADDLE_EMU
newX = ((sp_clamp[idx]*255)/sp_max);
#endif
}
if(!Gamepad[idx]._GamepadReport.b3 && !Gamepad[idx]._GamepadReport.b4) if(!Gamepad[idx]._GamepadReport.b3 && !Gamepad[idx]._GamepadReport.b4)
{ {
static uint16_t prev[2] = {0,0}; static uint16_t prev[2] = {0,0};
@ -223,38 +227,29 @@ void sendState(byte idx)
{ {
newR = 1; newR = 1;
prev[idx] += sp_step; prev[idx] += sp_step;
//Serial.println("RIGHT");
} }
else if(diff <= -sp_step) else if(diff <= -sp_step)
{ {
newL = 1; newL = 1;
prev[idx] -= sp_step; prev[idx] -= sp_step;
//Serial.println("LEFT");
} }
} }
#ifdef PADDLE_EMU int8_t diff = newX - Gamepad[idx]._GamepadReport.X;
uint16_t val = (sp_clamp[idx]*255)/sp_max;
newX = val ^ 0x80;
#endif
} // Only report controller state if it has changed
if (diff
int8_t diff = newX - Gamepad[idx]._GamepadReport.X; || ((Gamepad[idx]._GamepadReport.b0 ^ newA) & 1)
|| ((Gamepad[idx]._GamepadReport.b2 ^ newC) & 1)
// Only report controller state if it has changed || ((Gamepad[idx]._GamepadReport.b3 ^ newL) & 1)
if (diff || ((Gamepad[idx]._GamepadReport.b4 ^ newR) & 1))
|| ((Gamepad[idx]._GamepadReport.b0 ^ newA) & 1) {
|| ((Gamepad[idx]._GamepadReport.b2 ^ newC) & 1) Gamepad[idx]._GamepadReport.X = newX;
|| ((Gamepad[idx]._GamepadReport.b3 ^ newL) & 1) Gamepad[idx]._GamepadReport.b0 = newA;
|| ((Gamepad[idx]._GamepadReport.b4 ^ newR) & 1)) Gamepad[idx]._GamepadReport.b2 = newC;
{ Gamepad[idx]._GamepadReport.b3 = newL;
//if(!idx) Serial.println(newX); Gamepad[idx]._GamepadReport.b4 = newR;
Gamepad[idx]._GamepadReport.X = newX; Gamepad[idx].send();
Gamepad[idx]._GamepadReport.b0 = newA; }
Gamepad[idx]._GamepadReport.b2 = newC;
Gamepad[idx]._GamepadReport.b3 = newL;
Gamepad[idx]._GamepadReport.b4 = newR;
Gamepad[idx].send();
} }
} }