mirror of
https://github.com/X11Libre/xf86-input-joystick.git
synced 2026-03-24 01:34:06 +00:00
Add PWM key generation when axis in accelerated mode
When axis is in accelerated mode and keyhigh/keylow is set, the deflection of the axis will be linked to the _percent of time_ the key will be down. Full deflection will set the key permanently down (old behaviour). 50% deflection will result in the key being 50ms down and 50ms up. 75% deflection will result in the key being 150ms down and 50ms up. etc. Minimum interval is 50ms, maximum is 600ms.
This commit is contained in:
24
src/jstk.c
24
src/jstk.c
@@ -283,20 +283,9 @@ jstkReadProc(LocalDevicePtr local)
|
||||
|
||||
case JSTK_MAPPING_KEY: if (priv->keys_enabled == TRUE) {
|
||||
if (priv->axis[number].type == JSTK_TYPE_ACCELERATED) {
|
||||
if ((priv->axis[number].value > 0) !=
|
||||
(priv->axis[number].oldvalue > 0))
|
||||
jstkGenerateKeys(priv->keyboard_device,
|
||||
priv->axis[number].keys_high,
|
||||
(priv->axis[number].value > 0) ? 1:0);
|
||||
|
||||
if ((priv->axis[number].value < 0) !=
|
||||
(priv->axis[number].oldvalue < 0))
|
||||
jstkGenerateKeys(priv->keyboard_device,
|
||||
priv->axis[number].keys_low,
|
||||
(priv->axis[number].value < 0) ? 1:0);
|
||||
jstkHandlePWMAxis(local, number);
|
||||
} else if (priv->axis[number].type == JSTK_TYPE_BYVALUE) {
|
||||
if (priv->keys_enabled == TRUE)
|
||||
jstkStartAxisTimer(local, number);
|
||||
jstkStartAxisTimer(local, number);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -449,6 +438,12 @@ jstkDeviceControlProc(DeviceIntPtr pJstk,
|
||||
priv->timerrunning = FALSE;
|
||||
TimerCancel(priv->timer);
|
||||
}
|
||||
for (i = 0; i < MAXAXES; i++)
|
||||
if (priv->axis[i].timerrunning)
|
||||
{
|
||||
priv->axis[i].timerrunning = FALSE;
|
||||
TimerCancel(priv->axis[i].timer);
|
||||
}
|
||||
|
||||
if (local->fd >= 0)
|
||||
RemoveEnabledDevice(local->fd);
|
||||
@@ -552,6 +547,9 @@ jstkCorePreInit(InputDriverPtr drv, IDevPtr dev, int flags)
|
||||
priv->axis[i].amplify = 1.0f;
|
||||
priv->axis[i].valuator = -1;
|
||||
priv->axis[i].subpixel = 0.0f;
|
||||
priv->axis[i].timer = NULL;
|
||||
priv->axis[i].timerrunning = FALSE;
|
||||
priv->axis[i].key_isdown = 0;
|
||||
for (j=0; j<MAXKEYSPERBUTTON; j++)
|
||||
priv->axis[i].keys_low[j] = priv->axis[i].keys_high[j] = 0;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,11 @@ typedef struct _AXIS {
|
||||
float previousposition; /* TYPE_ABSOLUTE */
|
||||
float amplify;
|
||||
float subpixel; /* Pending subpixel movement */
|
||||
|
||||
KEYSCANCODES keys_low, keys_high; /* MAPPING_KEY */
|
||||
int key_isdown;
|
||||
OsTimerPtr timer;
|
||||
Bool timerrunning;
|
||||
} AXIS;
|
||||
|
||||
typedef struct _BUTTON {
|
||||
|
||||
167
src/jstk_axis.c
167
src/jstk_axis.c
@@ -384,3 +384,170 @@ jstkHandleAbsoluteAxis(LocalDevicePtr device, int number)
|
||||
xf86PostMotionEvent(device->dev, 0, 0, 2, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* jstkPWMAxisTimer --
|
||||
*
|
||||
* The timer that will generate Key events.
|
||||
* The deflection of the axis will control the PERCENT OF TIME the key is
|
||||
* down, not the amount of impulses.
|
||||
* Return 0, when timer can be stopped.
|
||||
*
|
||||
***********************************************************************
|
||||
*/
|
||||
static CARD32
|
||||
jstkPWMAxisTimer(OsTimerPtr timer,
|
||||
CARD32 atime,
|
||||
pointer arg)
|
||||
{
|
||||
DeviceIntPtr device = (DeviceIntPtr)arg;
|
||||
JoystickDevPtr priv = (JoystickDevPtr)XI_PRIVATE(device);
|
||||
|
||||
int sigstate, i;
|
||||
int nexttimer;
|
||||
|
||||
nexttimer = 0;
|
||||
|
||||
sigstate = xf86BlockSIGIO();
|
||||
|
||||
for (i=0; i<MAXAXES; i++)
|
||||
if (priv->axis[i].timer == timer) /* The timer handles only one axis! Find it. */
|
||||
{
|
||||
AXIS *axis;
|
||||
axis = &priv->axis[i];
|
||||
|
||||
DBG(8, ErrorF("PWM Axis %d value %d (old %d)\n", i, axis->value, axis->oldvalue));
|
||||
|
||||
/* Force key_high down if centered */
|
||||
if ((axis->value <= 0) &&
|
||||
(axis->oldvalue > 0) &&
|
||||
(axis->key_isdown))
|
||||
{
|
||||
DBG(7, ErrorF("PWM Axis %d jumped over. Forcing keys_high up.\n", i));
|
||||
jstkGenerateKeys(priv->keyboard_device,
|
||||
axis->keys_high,
|
||||
0);
|
||||
axis->key_isdown = 0;
|
||||
}
|
||||
|
||||
/* Force key_low down if centered */
|
||||
if ((axis->value >= 0) &&
|
||||
(axis->oldvalue < 0) &&
|
||||
(axis->key_isdown))
|
||||
{
|
||||
DBG(7, ErrorF("PWM Axis %d jumped over. Forcing keys_low up.\n", i));
|
||||
jstkGenerateKeys(priv->keyboard_device,
|
||||
axis->keys_low,
|
||||
0);
|
||||
axis->key_isdown = 0;
|
||||
}
|
||||
|
||||
if (axis->value == 0)
|
||||
nexttimer = 0;
|
||||
else {
|
||||
float time_on, time_off;
|
||||
float scale;
|
||||
KEYSCANCODES *keys;
|
||||
|
||||
if (axis->value < 0)
|
||||
keys = &axis->keys_low;
|
||||
else keys = &axis->keys_high;
|
||||
|
||||
/* Calculate next timer */
|
||||
time_on = (float)(abs(axis->value) - axis->deadzone) / 32768.0;
|
||||
time_on *= (32768.0f / (float)(32768 - axis->deadzone));
|
||||
|
||||
time_off = 1.0f - time_on;
|
||||
|
||||
time_on += 0.01f; /* Ugly but ensures we don't divide by 0 */
|
||||
time_off += 0.01f;
|
||||
|
||||
/* Scale both durations, so the smaller always is 50ms */
|
||||
scale = 50.0f * axis->amplify;
|
||||
|
||||
if (time_on < time_off)
|
||||
scale /= time_on;
|
||||
else scale /= time_off;
|
||||
|
||||
time_on *= scale;
|
||||
time_off *= scale;
|
||||
|
||||
|
||||
if (time_off > 600.0f) {
|
||||
/* Might as well just have it down forever */
|
||||
DBG(7, ErrorF("PWM Axis %d up time too long (%.0fms). Forcing up)\n", i, time_off));
|
||||
if (axis->key_isdown == 1) {
|
||||
axis->key_isdown = 0;
|
||||
jstkGenerateKeys(priv->keyboard_device,
|
||||
*keys,
|
||||
axis->key_isdown);
|
||||
}
|
||||
nexttimer = 0;
|
||||
} else if (time_on > 600.0f) {
|
||||
/* Might as well just have it up forever */
|
||||
DBG(7, ErrorF("PWM Axis %d down time too long (%.0fms). Forcing down)\n", i, time_on));
|
||||
if (axis->key_isdown == 0) {
|
||||
axis->key_isdown = 1;
|
||||
jstkGenerateKeys(priv->keyboard_device,
|
||||
*keys,
|
||||
axis->key_isdown);
|
||||
}
|
||||
nexttimer = 0;
|
||||
} else {
|
||||
/* Flip key state */
|
||||
axis->key_isdown = 1 - axis->key_isdown;
|
||||
jstkGenerateKeys(priv->keyboard_device,
|
||||
*keys,
|
||||
axis->key_isdown);
|
||||
|
||||
DBG(7, ErrorF("PWM Axis %d state=%d (%.0fms down, %.0fms up).\n", i, axis->key_isdown, time_on, time_off));
|
||||
|
||||
nexttimer = axis->key_isdown ? (int)time_on : (int)time_off;
|
||||
}
|
||||
}
|
||||
|
||||
if (nexttimer == 0) { /* No next timer, stop */
|
||||
axis->timerrunning = FALSE;
|
||||
|
||||
DBG(2, ErrorF("Stopping PWM Axis %d Timer\n", i));
|
||||
}
|
||||
axis->oldvalue = axis->value;
|
||||
break;
|
||||
}
|
||||
|
||||
xf86UnblockSIGIO (sigstate);
|
||||
return nexttimer;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* jstkStartAxisTimer --
|
||||
*
|
||||
* Starts the timer for the movement.
|
||||
* Will already prepare for moving one pixel, for "tipping" the stick
|
||||
*
|
||||
***********************************************************************
|
||||
*/
|
||||
void
|
||||
jstkHandlePWMAxis(LocalDevicePtr device, int number)
|
||||
{
|
||||
JoystickDevPtr priv = device->private;
|
||||
if (priv->axis[number].timerrunning) return;
|
||||
|
||||
priv->axis[number].timerrunning = TRUE;
|
||||
|
||||
DBG(2, ErrorF("Starting PWM Axis Timer (triggered by axis %d, value %d)\n",
|
||||
number, priv->axis[number].value));
|
||||
priv->axis[number].timer = TimerSet(
|
||||
priv->axis[number].timer,
|
||||
0, /* Relative */
|
||||
1, /* What about NOW? */
|
||||
jstkPWMAxisTimer,
|
||||
device->dev);
|
||||
}
|
||||
|
||||
@@ -27,5 +27,6 @@
|
||||
void jstkStartAxisTimer(LocalDevicePtr device, int number);
|
||||
void jstkStartButtonAxisTimer(LocalDevicePtr device, int number);
|
||||
void jstkHandleAbsoluteAxis(LocalDevicePtr device, int number);
|
||||
void jstkHandlePWMAxis(LocalDevicePtr device, int number);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user