Index: firmware/export/config-h10.h =================================================================== --- firmware/export/config-h10.h (revision 15998) +++ firmware/export/config-h10.h (working copy) @@ -95,6 +95,10 @@ /* Define this for LCD backlight available */ #define HAVE_BACKLIGHT +/* Define this to make the sliderbar on the front do more than a simple up/down + * button above/below the middle of it */ +#define HAVE_TOUCHPAD + #define AB_REPEAT_ENABLE 1 #define BATTERY_CAPACITY_DEFAULT 1550 /* default battery capacity */ Index: firmware/export/config-h10_5gb.h =================================================================== --- firmware/export/config-h10_5gb.h (revision 15998) +++ firmware/export/config-h10_5gb.h (working copy) @@ -72,6 +72,10 @@ /* WM8731 has no tone controls, so we use the software ones */ #define HAVE_SW_TONE_CONTROLS +/* Define this to make the sliderbar on the front do more than a simple up/down + * button above/below the middle of it */ +#define HAVE_TOUCHPAD + #define AB_REPEAT_ENABLE 1 /* FM Tuner */ Index: firmware/target/arm/iriver/h10/button-h10.c =================================================================== --- firmware/target/arm/iriver/h10/button-h10.c (revision 15998) +++ firmware/target/arm/iriver/h10/button-h10.c (working copy) @@ -68,6 +68,36 @@ bool hold_button_old; bool remote_hold_button_old; +#ifdef HAVE_TOUCHPAD + /* + * the position on the slider when it was first pressed or the value of + * the slider when we last returned a DOWN/UP button pressed state + */ + static int latchedSliderPosition = -1; + + /* + * the number of times this function has been called with the user's + * finger resting on the slider in one position + */ + static int callCountWithUsersFingerResting = 0; + static bool userDidSlideFinger = false; + + /* + * the amount that the slider value has to change before returning another + * down/up pressed state + */ + #define SLIDER_PAD_INITIAL_MOVE_THRESHOLD 0x150 + static int sliderPadMoveDownThreshold = SLIDER_PAD_INITIAL_MOVE_THRESHOLD; + static int sliderPadMoveUpThreshold = SLIDER_PAD_INITIAL_MOVE_THRESHOLD; + + /* values on the scroll pad below this are considered the "down" button */ + #define DOWN_BUTTON_ZONE (0x14A+0x20) /* the lower 30% of the slider */ + + /* values on the scroll pad above this are considered the "up" button */ + #define UP_BUTTON_ZONE 0x2B6 /* the upper 30% of the slider */ + +#endif + /* Hold */ hold_button_old = hold_button; hold_button = button_hold(); @@ -102,13 +132,128 @@ data = adc_scan(ADC_SCROLLPAD); GPIO_SET_BITWISE(GPIOD_OUTPUT_VAL, 0x40); +#ifdef HAVE_TOUCHPAD + /* + * New slider bar functionality + * + * Note: since this function is called simply to get the current + * state of the buttons it is called very frequently. If we want + * to simulate the user pressing up/down very rapidly, then this + * function has to return a button-released state followed by a + * button-pressed state to fool the caller into thinking that the + * user is just pressing the up/down button repeatedly. If we + * don't return the button-release state between button-press + * states, then the auto-repeat logic in the calling code kicks + * in which is not what we want. + * + * $data is is the position of the user's finger on the scroll pad + * its range returned by the hardware is 0x20 to 0x400 (32 to 1024) + */ + + /* + * the user just placed their finger on the slider since releasing + * it (or for the first time) + */ + if(latchedSliderPosition == -1) + latchedSliderPosition = data; + + /* + * The logic below handles that the user must initially move SLIDER_PAD_INITIAL_MOVE_THRESHOLD + * units up/down before the button pressed state is returned. After that only a 1/6th + * of the units is required, but the full number of units is still required to start + * moving in the other direction. + * + * The reason for this is that we need a large area for their thumb to wiggle around on + * before moving anything, but after they get going, we scroll in the direction they're + * moving. + * + * And if the the user rests their finger in the upper or lower zones of the slider for + * a while, the it will return a button down state to activate the auto-repeat for either + * up or down respective to which zone their finger is resting in. + */ + + if((latchedSliderPosition-data) > sliderPadMoveDownThreshold) + { + btn |= BUTTON_SCROLL_DOWN; + latchedSliderPosition = data; + callCountWithUsersFingerResting = 0; + userDidSlideFinger = true; + + /* if first move, require half the change for subsequent moves */ + if(sliderPadMoveDownThreshold == SLIDER_PAD_INITIAL_MOVE_THRESHOLD) + sliderPadMoveDownThreshold /= 6; + sliderPadMoveUpThreshold = SLIDER_PAD_INITIAL_MOVE_THRESHOLD; + } + else if((data-latchedSliderPosition) > sliderPadMoveUpThreshold) + { + btn |= BUTTON_SCROLL_UP; + latchedSliderPosition = data; + callCountWithUsersFingerResting = 0; + userDidSlideFinger = true; + + /* if first move, require half the change for subsequent moves */ + if(sliderPadMoveUpThreshold == SLIDER_PAD_INITIAL_MOVE_THRESHOLD) + sliderPadMoveUpThreshold /= 6; + sliderPadMoveDownThreshold = SLIDER_PAD_INITIAL_MOVE_THRESHOLD; + } + else + { + callCountWithUsersFingerResting++; + + /* + * the user is leaving their finger pressed on the slider + * so return a up or down button pressed state so that the + * auto-repeat logic will kick in in the calling code. + */ + if(callCountWithUsersFingerResting>70) + { + if(dataUP_BUTTON_ZONE) + btn |= BUTTON_SCROLL_UP; + } + } +#else + /* original simple implementation of sliderpad (as just up/down buttons) */ if(data < 0x224) { btn |= BUTTON_SCROLL_DOWN; } else { btn |= BUTTON_SCROLL_UP; } +#endif } + else + { /* the user's finger is not on the scrollpad */ +#ifdef HAVE_TOUCHPAD + /* + * if the user didn't slide their finger since placing it on the + * slider, then generate a button up/down pressed event if the + * slider was pressed within the top or bottom 30% + */ + if(!userDidSlideFinger && latchedSliderPosition>0) + { + if(latchedSliderPositionUP_BUTTON_ZONE) + btn |= BUTTON_SCROLL_UP; + #if 0 /* might be cool to tap middle for select .. perhaps use middle 20% instead */ + else /* middle */ + btn |= BUTTON_RIGHT; /* user tapped middle */ + #endif + } + + /* + * reset intermediate state values to when the scroll pad is no + * longer being touched + */ + latchedSliderPosition = -1; + callCountWithUsersFingerResting = 0; + userDidSlideFinger = false; + sliderPadMoveDownThreshold = SLIDER_PAD_INITIAL_MOVE_THRESHOLD; + sliderPadMoveUpThreshold = SLIDER_PAD_INITIAL_MOVE_THRESHOLD; +#endif + } } /* remote buttons */