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)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x80, // LOGICAL_MINIMUM (-128)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xFF, 0x00, // LOGICAL_MAXIMUM (255)
0x95, 0x02, // REPORT_COUNT (2)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x02, // INPUT (Data,Var,Abs)

View File

@ -80,6 +80,9 @@
// Optional parameter. Leave it commented out.
//#define SPINNER_SENSITIVITY 1
// Set it to 1 if you want only single input device.
#define DEV_NUM 2
/////////////////////////////////////////////////////////////////
// pins map
@ -111,46 +114,16 @@ const char *gp_serial = "MiSTer PD/SP v1";
#include <ResponsiveAnalogRead.h>
#include "Gamepad.h"
Gamepad_ Gamepad[2];
Gamepad_ Gamepad[DEV_NUM];
ResponsiveAnalogRead analog[2] = {ResponsiveAnalogRead(pdlpin[0], true),ResponsiveAnalogRead(pdlpin[1], true)};
int8_t pdlena[2] = {0,0};
uint16_t drvpos[2];
int16_t drvX[2] = {0,0};
void setup()
{
float snap = .01;
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};
#define SP_MAX ((SPINNER_PPR*4*270UL)/360)
const uint16_t sp_max = SP_MAX;
int32_t sp_clamp[2] = {SP_MAX/2,SP_MAX/2};
void drv_proc(int8_t idx)
{
@ -185,35 +158,66 @@ void drv1_isr()
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
TXLED1; //RXLED1;
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) ^ 0x80;
}
else
for(int idx=0; idx<DEV_NUM; idx++)
{
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)
{
static uint16_t prev[2] = {0,0};
@ -223,38 +227,29 @@ void sendState(byte idx)
{
newR = 1;
prev[idx] += sp_step;
//Serial.println("RIGHT");
}
else if(diff <= -sp_step)
{
newL = 1;
prev[idx] -= sp_step;
//Serial.println("LEFT");
}
}
#ifdef PADDLE_EMU
uint16_t val = (sp_clamp[idx]*255)/sp_max;
newX = val ^ 0x80;
#endif
int8_t diff = newX - Gamepad[idx]._GamepadReport.X;
}
int8_t diff = newX - Gamepad[idx]._GamepadReport.X;
// Only report controller state if it has changed
if (diff
|| ((Gamepad[idx]._GamepadReport.b0 ^ newA) & 1)
|| ((Gamepad[idx]._GamepadReport.b2 ^ newC) & 1)
|| ((Gamepad[idx]._GamepadReport.b3 ^ newL) & 1)
|| ((Gamepad[idx]._GamepadReport.b4 ^ newR) & 1))
{
//if(!idx) Serial.println(newX);
Gamepad[idx]._GamepadReport.X = newX;
Gamepad[idx]._GamepadReport.b0 = newA;
Gamepad[idx]._GamepadReport.b2 = newC;
Gamepad[idx]._GamepadReport.b3 = newL;
Gamepad[idx]._GamepadReport.b4 = newR;
Gamepad[idx].send();
// Only report controller state if it has changed
if (diff
|| ((Gamepad[idx]._GamepadReport.b0 ^ newA) & 1)
|| ((Gamepad[idx]._GamepadReport.b2 ^ newC) & 1)
|| ((Gamepad[idx]._GamepadReport.b3 ^ newL) & 1)
|| ((Gamepad[idx]._GamepadReport.b4 ^ newR) & 1))
{
Gamepad[idx]._GamepadReport.X = newX;
Gamepad[idx]._GamepadReport.b0 = newA;
Gamepad[idx]._GamepadReport.b2 = newC;
Gamepad[idx]._GamepadReport.b3 = newL;
Gamepad[idx]._GamepadReport.b4 = newR;
Gamepad[idx].send();
}
}
}