Improve tap responsiveness in GL touch joystick

This commit is contained in:
Aaron Culliney
2016-01-08 00:19:35 -08:00
parent a64941694f
commit b2824e9145
2 changed files with 60 additions and 47 deletions

View File

@@ -350,7 +350,7 @@ public enum Apple2Preferences {
@Override @Override
public int intValue(Apple2Activity activity) { public int intValue(Apple2Activity activity) {
int defaultLatency = 3; // /TAPDELAY_NUM_CHOICES * TAPDELAY_SCALE -> 0.075f int defaultLatency = 8; // /TAPDELAY_NUM_CHOICES * TAPDELAY_SCALE -> 0.2f
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), defaultLatency); return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), defaultLatency);
} }
}, },

View File

@@ -26,6 +26,7 @@ static struct {
void (*buttonDrawCallback)(char newChar); void (*buttonDrawCallback)(char newChar);
bool trackingButton; bool trackingButton;
bool trackingButtonMove;
pthread_t tapDelayThreadId; pthread_t tapDelayThreadId;
pthread_mutex_t tapDelayMutex; pthread_mutex_t tapDelayMutex;
pthread_cond_t tapDelayCond; pthread_cond_t tapDelayCond;
@@ -71,54 +72,61 @@ static void *_button_tap_delayed_thread(void *dummyptr) {
pthread_mutex_lock(&joys.tapDelayMutex); pthread_mutex_lock(&joys.tapDelayMutex);
do { bool deepSleep = false;
pthread_cond_wait(&joys.tapDelayCond, &joys.tapDelayMutex); uint8_t currJoyButtonValue0 = 0x0;
TOUCH_JOY_LOG(">>> [DELAYEDTAP] begin ..."); uint8_t currJoyButtonValue1 = 0x0;
uint8_t currButtonDisplayChar = ' ';
for (;;) {
if (UNLIKELY(joyglobals.isShuttingDown)) { if (UNLIKELY(joyglobals.isShuttingDown)) {
break; break;
} }
struct timespec ts = { .tv_sec=0, .tv_nsec=joys.tapDelayNanos }; struct timespec wait;
clock_gettime(CLOCK_REALTIME, &wait); // should use CLOCK_MONOTONIC ?
wait = timespec_add(wait, joys.tapDelayNanos);
int timedOut = pthread_cond_timedwait(&joys.tapDelayCond, &joys.tapDelayMutex, &wait); // wait and possibly consume event
assert((!timedOut || timedOut == ETIMEDOUT) && "should not fail any other way");
// sleep for the configured delay time if (!timedOut) {
pthread_mutex_unlock(&joys.tapDelayMutex); if (!deepSleep) {
nanosleep(&ts, NULL); if (joys.trackingButtonMove) {
pthread_mutex_lock(&joys.tapDelayMutex); // dragging
currJoyButtonValue0 = 0x0;
// wait until touch up/cancel currJoyButtonValue1 = 0x0;
do { currButtonDisplayChar = joys.currButtonDisplayChar;
} else if (joys.trackingButton) {
// now set the joystick button values // touch down -- delay consumption to determine if tap or drag
joy_button0 = joys.currJoyButtonValue0; currJoyButtonValue0 = joys.currJoyButtonValue0;
joy_button1 = joys.currJoyButtonValue1; currJoyButtonValue1 = joys.currJoyButtonValue1;
joys.buttonDrawCallback(joys.currButtonDisplayChar); currButtonDisplayChar = joys.currButtonDisplayChar;
joys.buttonDrawCallback(currButtonDisplayChar);
if (!joys.trackingButton || joyglobals.isShuttingDown) { // zero the buttons before delay
break; _reset_buttons_state();
continue;
} else {
// touch up becomes tap
joys.currJoyButtonValue0 = currJoyButtonValue0;
joys.currJoyButtonValue1 = currJoyButtonValue1;
joys.currButtonDisplayChar = currButtonDisplayChar;
}
} }
pthread_cond_wait(&joys.tapDelayCond, &joys.tapDelayMutex);
if (!joys.trackingButton || joyglobals.isShuttingDown) {
break;
}
TOUCH_JOY_LOG(">>> [DELAYEDTAP] looping ...");
} while (1);
if (UNLIKELY(joyglobals.isShuttingDown)) {
break;
} }
// delay the ending of button tap or touch/move event by the configured delay time joy_button0 = joys.currJoyButtonValue0;
pthread_mutex_unlock(&joys.tapDelayMutex); joy_button1 = joys.currJoyButtonValue1;
nanosleep(&ts, NULL); joys.buttonDrawCallback(joys.currButtonDisplayChar);
pthread_mutex_lock(&joys.tapDelayMutex);
_reset_buttons_state(); deepSleep = false;
if (timedOut && !joys.trackingButton) {
TOUCH_JOY_LOG(">>> [DELAYEDTAP] end ..."); deepSleep = true;
} while (1); _reset_buttons_state();
TOUCH_JOY_LOG(">>> [DELAYEDTAP] end ...");
pthread_cond_wait(&joys.tapDelayCond, &joys.tapDelayMutex); // consume initial touch down
TOUCH_JOY_LOG(">>> [DELAYEDTAP] begin ...");
} else {
TOUCH_JOY_LOG(">>> [DELAYEDTAP] event looping ...");
}
}
pthread_mutex_unlock(&joys.tapDelayMutex); pthread_mutex_unlock(&joys.tapDelayMutex);
@@ -183,7 +191,7 @@ static void touchjoy_axisUp(int x, int y) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// button state // button state
static void _set_current_button_state(touchjoy_button_type_t theButtonChar, int theButtonScancode) { static void _set_current_button_state(touchjoy_button_type_t theButtonChar) {
if (theButtonChar == TOUCH_BUTTON0) { if (theButtonChar == TOUCH_BUTTON0) {
joys.currJoyButtonValue0 = 0x80; joys.currJoyButtonValue0 = 0x80;
joys.currJoyButtonValue1 = 0; joys.currJoyButtonValue1 = 0;
@@ -204,30 +212,30 @@ static void _set_current_button_state(touchjoy_button_type_t theButtonChar, int
} }
static void touchjoy_buttonDown(void) { static void touchjoy_buttonDown(void) {
_set_current_button_state(buttons.touchDownChar, buttons.touchDownScancode); _set_current_button_state(buttons.touchDownChar);
joys.trackingButton = true; joys.trackingButton = true;
_signal_tap_delay(); _signal_tap_delay();
} }
static void touchjoy_buttonMove(int dx, int dy) { static void touchjoy_buttonMove(int dx, int dy) {
if ((dy < -joyglobals.switchThreshold) || (dy > joyglobals.switchThreshold)) { if ((dy < -joyglobals.switchThreshold) || (dy > joyglobals.switchThreshold)) {
touchjoy_button_type_t theButtonChar = -1; touchjoy_button_type_t theButtonChar = -1;
int theButtonScancode = -1;
if (dy < 0) { if (dy < 0) {
theButtonChar = buttons.northChar; theButtonChar = buttons.northChar;
theButtonScancode = buttons.northScancode;
} else { } else {
theButtonChar = buttons.southChar; theButtonChar = buttons.southChar;
theButtonScancode = buttons.southScancode;
} }
_set_current_button_state(theButtonChar, theButtonScancode); _set_current_button_state(theButtonChar);
_signal_tap_delay(); _signal_tap_delay();
} }
joys.trackingButtonMove = true;
} }
static void touchjoy_buttonUp(int dx, int dy) { static void touchjoy_buttonUp(int dx, int dy) {
joys.trackingButton = false; joys.trackingButton = false;
joys.trackingButtonMove = false;
_signal_tap_delay(); _signal_tap_delay();
} }
@@ -238,7 +246,12 @@ static void gltouchjoy_setTapDelay(float secs) {
if (UNLIKELY(secs > 1.f)) { if (UNLIKELY(secs > 1.f)) {
ERRLOG("Clamping tap delay to 1.0 secs"); ERRLOG("Clamping tap delay to 1.0 secs");
} }
joys.tapDelayNanos = (unsigned int)((float)NANOSECONDS_PER_SECOND * secs); unsigned int tapDelayNanos = (unsigned int)((float)NANOSECONDS_PER_SECOND * secs);
#define MIN_WAIT_NANOS 1000000
if (tapDelayNanos < MIN_WAIT_NANOS) {
tapDelayNanos = MIN_WAIT_NANOS;
}
joys.tapDelayNanos = tapDelayNanos;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------