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:
Sascha Hlusiak
2009-02-19 23:40:58 +01:00
parent d4bb86ddb0
commit 4978e78e7c
4 changed files with 183 additions and 13 deletions

View File

@@ -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;
}

View File

@@ -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 {

View File

@@ -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);
}

View File

@@ -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