Index: apps/lang/english.lang =================================================================== --- apps/lang/english.lang (revision 14653) +++ apps/lang/english.lang (working copy) @@ -3345,6 +3345,20 @@ + id: LANG_WHEEL_ACCEL_START + desc: wheel acceleration start + user: + + *: "Wheel Acceleration Start" + + + *: "Wheel Acceleration Start" + + + *: "Wheel Acceleration Start" + + + id: LANG_BARS_MENU desc: in the display sub menu user: Index: apps/gui/list.c =================================================================== --- apps/gui/list.c (revision 14653) +++ apps/gui/list.c (working copy) @@ -898,8 +898,13 @@ int i; #ifdef HAVE_SCROLLWHEEL - int next_item_modifier = button_apply_acceleration(get_action_data(), - WHEEL_ACCELERATION_FACTOR); + unsigned long long factor = global_settings.wheel_accel_start; + + /* factor = (10^6 / global_settings.wheel_accel_start)^2 */ + factor = 1000000/factor; + factor *= factor; + + int next_item_modifier = button_apply_acceleration(get_action_data(), factor); #else static int next_item_modifier = 1; static int last_accel_tick = 0; Index: apps/settings.h =================================================================== --- apps/settings.h (revision 14653) +++ apps/settings.h (working copy) @@ -747,6 +747,8 @@ #ifndef HAVE_SCROLLWHEEL int list_accel_start_delay; /* ms before we start increaseing step size */ int list_accel_wait; /* ms between increases */ +#else + unsigned int wheel_accel_start; /* value in clicks/sec from which acceleration starts */ #endif #ifdef HAVE_USBSTACK int usb_stack_mode; /* device or host */ Index: apps/menus/display_menu.c =================================================================== --- apps/menus/display_menu.c (revision 14653) +++ apps/menus/display_menu.c (working copy) @@ -317,6 +317,8 @@ MENUITEM_SETTING(list_accel_start_delay, &global_settings.list_accel_start_delay, NULL); MENUITEM_SETTING(list_accel_wait, &global_settings.list_accel_wait, NULL); +#else +MENUITEM_SETTING(wheel_accel_start, &global_settings.wheel_accel_start, NULL); #endif /* HAVE_SCROLLWHEEL */ #ifdef HAVE_LCD_BITMAP int screenscroll_callback(int action,const struct menu_item_ex *this_item) @@ -354,6 +356,8 @@ &scroll_paginated, #ifndef HAVE_SCROLLWHEEL &list_accel_start_delay, &list_accel_wait +#else + &wheel_accel_start #endif ); /* SCROLL MENU */ Index: apps/settings_list.c =================================================================== --- apps/settings_list.c (revision 14653) +++ apps/settings_list.c (working copy) @@ -242,6 +242,12 @@ (void)unit; snprintf(buffer, buffer_size, "%ds", ff_rewind_min_stepvals[val]); } +static long wheel_accel_getlang(int value) +{ + if (value == 0) + return LANG_OFF; + return TALK_ID(value, UNIT_INT); +} static long scanaccel_getlang(int value) { if (value == 0) @@ -257,6 +263,15 @@ else snprintf(buffer, buffer_size, "2x/%ds", val); } +static void wheel_accel_formatter(char *buffer, size_t buffer_size, + int val, const char *unit) +{ + (void)unit; + if (val == 0) + strcpy(buffer, str(LANG_OFF)); + else + snprintf(buffer, buffer_size, "%3d clicks/s", val); +} static const unsigned char poweroff_idle_timer_times[] = {0,1,2,3,4,5,6,7,8,9,10,15,30,45,60}; static long poweroff_idle_timer_getlang(int value) @@ -1262,6 +1277,10 @@ INT_SETTING(0, list_accel_wait, LANG_LISTACCEL_ACCEL_SPEED, 3, "list_accel_wait", UNIT_SEC, 1, 10, 1, scanaccel_formatter, scanaccel_getlang, NULL), +#else + INT_SETTING(0, wheel_accel_start, LANG_WHEEL_ACCEL_START, DEFAULT_WHEEL_ACCEL_START, + "wheel_accel_start", UNIT_INT, 10, 200, 10, + wheel_accel_formatter, wheel_accel_getlang, NULL), #endif /* HAVE_SCROLLWHEEL */ #ifdef HAVE_USBSTACK CHOICE_SETTING(0, usb_stack_mode, LANG_USBSTACK_MODE, 0, "usb mode", Index: firmware/export/button.h =================================================================== --- firmware/export/button.h (revision 14653) +++ firmware/export/button.h (working copy) @@ -51,7 +51,7 @@ #endif #ifdef HAVE_SCROLLWHEEL -int button_apply_acceleration(unsigned int data, unsigned int factor); +int button_apply_acceleration(unsigned int data, unsigned long long factor); #endif #define BUTTON_NONE 0x00000000 Index: firmware/export/config-e200.h =================================================================== --- firmware/export/config-e200.h (revision 14653) +++ firmware/export/config-e200.h (working copy) @@ -97,9 +97,8 @@ /* define this if the unit uses a scrollwheel for navigation */ #define HAVE_SCROLLWHEEL -/* define wheel acceleration scaling factor */ -/* Range for this target: 0xffffff*(0.0-16.000000894069724921567733381255) */ -#define WHEEL_ACCELERATION_FACTOR (0xffffff*7) +/* define from which wheelticks/sec on the acceleration starts */ +#define DEFAULT_WHEEL_ACCEL_START 90 /* define this if you have a flash memory storage */ #define HAVE_FLASH_STORAGE Index: firmware/export/config-ipodvideo.h =================================================================== --- firmware/export/config-ipodvideo.h (revision 14653) +++ firmware/export/config-ipodvideo.h (working copy) @@ -73,6 +73,11 @@ /* We can fade the backlight by using PWM */ #define HAVE_BACKLIGHT_PWM_FADING +/* define this if the unit uses a scrollwheel for navigation */ +#define HAVE_SCROLLWHEEL +/* define from which wheelticks/sec on the acceleration starts */ +#define DEFAULT_WHEEL_ACCEL_START 10 + /* Define this if you can detect headphones */ #define HAVE_HEADPHONE_DETECTION Index: firmware/target/arm/ipod/button-clickwheel.c =================================================================== --- firmware/target/arm/ipod/button-clickwheel.c (revision 14653) +++ firmware/target/arm/ipod/button-clickwheel.c (working copy) @@ -40,6 +40,16 @@ #include "system.h" #include "powermgmt.h" +#define WHEEL_FAST_OFF_INTERVAL 500000 /* 500ms */ + +static int old_wheel_value = -1; +static int repeat = 0; +static int wheel_delta = 0; +static int accumulated_wheel_delta = 0; +static unsigned int wheel_repeat = 0; +static unsigned long last_wheel_usec = 0; +static unsigned long wheel_velocity = 0; + /* Variable to use for setting button status in interrupt handler */ int int_btn = BUTTON_NONE; #ifdef HAVE_WHEEL_POSITION @@ -96,9 +106,6 @@ outl(0x0, 0x7000c140); /* clear interrupt status? */ if ((status & 0x800000ff) == 0x8000001a) { - static int old_wheel_value IDATA_ATTR = -1; - static int wheel_repeat = 0; - if (status & 0x100) btn |= BUTTON_SELECT; if (status & 0x200) @@ -113,53 +120,101 @@ /* NB: highest wheel = 0x5F, clockwise increases */ int new_wheel_value = (status << 9) >> 25; whl = new_wheel_value; + + /* switch on backlight (again), reset power-off timer */ backlight_on(); reset_poweroff_timer(); + /* The queue should have no other events when scrolling */ - if (queue_empty(&button_queue) && old_wheel_value >= 0) { - + if (queue_empty(&button_queue) && old_wheel_value >= 0) + { /* This is for later = BUTTON_SCROLL_TOUCH;*/ - int wheel_delta = new_wheel_value - old_wheel_value; - unsigned long data; - int wheel_keycode; - + wheel_delta = new_wheel_value - old_wheel_value; + unsigned int wheel_keycode = BUTTON_NONE; + if (wheel_delta < -48) wheel_delta += 96; /* Forward wrapping case */ else if (wheel_delta > 48) wheel_delta -= 96; /* Backward wrapping case */ - - if (wheel_delta > 4) { + + /* getting wheel_keycode from wheel_delta */ + if (wheel_delta > 4) wheel_keycode = BUTTON_SCROLL_FWD; - } else if (wheel_delta < -4) { + else if (wheel_delta < -4) wheel_keycode = BUTTON_SCROLL_BACK; - } else goto wheel_end; - + else + wheel_keycode = BUTTON_NONE; + + /* add the current wheel_delta */ + accumulated_wheel_delta += wheel_delta; + + if (wheel_keycode != BUTTON_NONE) + { + unsigned long usec = USEC_TIMER; + long v = (usec - last_wheel_usec) & 0x7fffffff; + + v = v ? (0xffffff * accumulated_wheel_delta) / v : 0; /* clicks/usec * 0xffffff */ + v = (v<0) ? -v : v; /* undo signedness */ + v = (v>0x3ffff) ? 0x3ffff : v; /* limit to 2^18 */ + + /* some velocity filtering to smooth things out */ + wheel_velocity = (7*wheel_velocity + v) / 8; + + /* direction reversals nullify acceleration */ + if (wheel_keycode != wheel_repeat) + { + wheel_repeat = wheel_keycode; + wheel_velocity = 0; + } + /* timeout nullifies acceleration */ + if (TIME_AFTER(usec, last_wheel_usec + WHEEL_FAST_OFF_INTERVAL)) + { + wheel_velocity = 0; + } + #ifdef HAVE_WHEEL_POSITION - if (send_events) + if (send_events) #endif - { - data = (wheel_delta << 16) | new_wheel_value; - queue_post(&button_queue, wheel_keycode | wheel_repeat, - data); + { + /* use data-format for HAVE_SCROLLWHEEL */ + /* always use acceleration mode (1<<31) */ + /* always set message post count to (1<<24) */ + /* this way the scrolling is always calculated from wheel_velocity */ + queue_post(&button_queue, wheel_keycode | repeat, + (1<<31) | (1 << 24) | wheel_velocity); + } + + if (!repeat) repeat = BUTTON_REPEAT; + + accumulated_wheel_delta = 0; + + last_wheel_usec = usec; } - - if (!wheel_repeat) wheel_repeat = BUTTON_REPEAT; + else + { + /* take from former revision */ + goto wheel_end; + } } old_wheel_value = new_wheel_value; - } else if (old_wheel_value >= 0) { - /* scroll wheel up */ + } + else if (old_wheel_value >= 0) + { + // scroll wheel up old_wheel_value = -1; - wheel_repeat = 0; + repeat = 0; } - } else if (status == 0xffffffff) { + } + else if (status == 0xffffffff) + { opto_i2c_init(); } } wheel_end: - + if ((inl(reg) & 0x8000000) != 0) { outl(0xffffffff, 0x7000c120); outl(0xffffffff, 0x7000c124); @@ -200,14 +255,21 @@ void button_init_device(void) { opto_i2c_init(); + /* hold button - enable as input */ GPIOA_ENABLE |= 0x20; GPIOA_OUTPUT_EN &= ~0x20; + /* hold button - set interrupt levels */ GPIOA_INT_LEV = ~(GPIOA_INPUT_VAL & 0x20); GPIOA_INT_CLR = GPIOA_INT_STAT & 0x20; + + /* Get current tick before enabling button interrupts */ + last_wheel_usec = USEC_TIMER; + /* enable interrupts */ GPIOA_INT_EN = 0x20; + /* unmask interrupt */ CPU_INT_EN = 0x40000000; CPU_HI_INT_EN = I2C_MASK; Index: firmware/drivers/button.c =================================================================== --- firmware/drivers/button.c (revision 14653) +++ firmware/drivers/button.c (working copy) @@ -497,7 +497,7 @@ * no greater than what will not overflow 64 bits when multiplied * by the driver's maximum velocity in (clicks/usec)^2 in 0.24 */ -int button_apply_acceleration(unsigned int data, unsigned int factor) +int button_apply_acceleration(unsigned int data, unsigned long long factor) { int delta = (data >> 24) & 0x7f;