diff options
author | Sascha Hlusiak <saschahlusiak@arcor.de> | 2009-02-19 23:40:58 +0100 |
---|---|---|
committer | Sascha Hlusiak <saschahlusiak@arcor.de> | 2009-02-19 23:40:58 +0100 |
commit | 4978e78e7c49bc0aabf5c7ade4223c2529a9f046 (patch) | |
tree | bec93c47658cd1cb730b055c796ad024f5b0e70c | |
parent | d4bb86ddb0ba570de0f501cd0edb13861456b711 (diff) |
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.
-rw-r--r-- | src/jstk.c | 24 | ||||
-rw-r--r-- | src/jstk.h | 4 | ||||
-rw-r--r-- | src/jstk_axis.c | 167 | ||||
-rw-r--r-- | src/jstk_axis.h | 1 |
4 files changed, 183 insertions, 13 deletions
@@ -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 { diff --git a/src/jstk_axis.c b/src/jstk_axis.c index 7e59e97..b314122 100644 --- a/src/jstk_axis.c +++ b/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); +} diff --git a/src/jstk_axis.h b/src/jstk_axis.h index e759f39..028c65f 100644 --- a/src/jstk_axis.h +++ b/src/jstk_axis.h @@ -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 |