Index: apps/lang/deutsch.lang
===================================================================
--- apps/lang/deutsch.lang (revision 14668)
+++ apps/lang/deutsch.lang (working copy)
@@ -11166,3 +11166,20 @@
rtc: "Uhr"
+
+ id: LANG_WHEEL_ACCEL_START
+ desc: wheel acceleration start
+ user:
+
+ *: none
+ scrollwheel: "Wheelspeed for Acceleration"
+
+
+ *: none
+ scrollwheel: "Startwert für Listenbeschleunigung"
+
+
+ *: none
+ scrollwheel: "Startwert für Listenbeschleunigung"
+
+
Index: apps/lang/english.lang
===================================================================
--- apps/lang/english.lang (revision 14668)
+++ apps/lang/english.lang (working copy)
@@ -11242,3 +11242,20 @@
usbstack: "Device Driver"
+
+ id: LANG_WHEEL_ACCEL_START
+ desc: wheel acceleration start
+ user:
+
+ *: none
+ scrollwheel: "Wheelspeed for Acceleration"
+
+
+ *: none
+ scrollwheel: "Wheelspeed for Acceleration"
+
+
+ *: none
+ scrollwheel: "Wheelspeed for Acceleration"
+
+
Index: apps/gui/list.c
===================================================================
--- apps/gui/list.c (revision 14668)
+++ apps/gui/list.c (working copy)
@@ -898,8 +898,7 @@
int i;
#ifdef HAVE_SCROLLWHEEL
- int next_item_modifier = button_apply_acceleration(get_action_data(),
- WHEEL_ACCELERATION_FACTOR);
+ int next_item_modifier = button_apply_acceleration(get_action_data(), global_settings.wheel_accel_start);
#else
static int next_item_modifier = 1;
static int last_accel_tick = 0;
Index: apps/settings.h
===================================================================
--- apps/settings.h (revision 14668)
+++ 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 14668)
+++ 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 14668)
+++ 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, 50, 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/config-ipodmini2g.h
===================================================================
--- firmware/export/config-ipodmini2g.h (revision 14668)
+++ firmware/export/config-ipodmini2g.h (working copy)
@@ -75,6 +75,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 100
+
/* Define this if you can detect headphones */
#define HAVE_HEADPHONE_DETECTION
Index: firmware/export/config-ipodnano.h
===================================================================
--- firmware/export/config-ipodnano.h (revision 14668)
+++ firmware/export/config-ipodnano.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 100
+
/* Define this if you can detect headphones */
#define HAVE_HEADPHONE_DETECTION
Index: firmware/export/button.h
===================================================================
--- firmware/export/button.h (revision 14668)
+++ 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(const unsigned int data, unsigned int factor);
#endif
#define BUTTON_NONE 0x00000000
Index: firmware/export/config-ipod4g.h
===================================================================
--- firmware/export/config-ipod4g.h (revision 14668)
+++ firmware/export/config-ipod4g.h (working copy)
@@ -78,6 +78,11 @@
/* Define this for LCD backlight available */
#define HAVE_BACKLIGHT
+/* 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 100
+
/* Define this if you can detect headphones */
#define HAVE_HEADPHONE_DETECTION
Index: firmware/export/config-e200.h
===================================================================
--- firmware/export/config-e200.h (revision 14668)
+++ 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 100
/* 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 14668)
+++ 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 100
+
/* Define this if you can detect headphones */
#define HAVE_HEADPHONE_DETECTION
Index: firmware/export/config-ipodcolor.h
===================================================================
--- firmware/export/config-ipodcolor.h (revision 14668)
+++ firmware/export/config-ipodcolor.h (working copy)
@@ -70,6 +70,11 @@
/* Define this for LCD backlight available */
#define HAVE_BACKLIGHT
+/* 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 100
+
/* 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 14668)
+++ firmware/target/arm/ipod/button-clickwheel.c (working copy)
@@ -40,6 +40,18 @@
#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;
+#ifdef HAVE_SCROLLWHEEL
+ 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;
+#endif
+
/* Variable to use for setting button status in interrupt handler */
int int_btn = BUTTON_NONE;
#ifdef HAVE_WHEEL_POSITION
@@ -96,9 +108,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,47 +122,104 @@
/* 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 (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;
+
+ if (wheel_keycode != BUTTON_NONE)
+ {
+#ifdef HAVE_SCROLLWHEEL
+ unsigned long usec = USEC_TIMER;
+ long v = (usec - last_wheel_usec) & 0x7fffffff;
+
+ /* add the current wheel_delta */
+ accumulated_wheel_delta += wheel_delta;
+ v = v ? (1000000 * accumulated_wheel_delta) / v : 0; /* clicks/s = 1000000 * clicks/usec */
+ v = (v<0) ? -v : v; /* undo signedness */
+ v = (v>0xffffff) ? 0xffffff : v; /* limit to 24 bit */
+
+ /* 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;
+ }
+#endif
+
#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);
+ if (queue_empty(&button_queue))
+ {
+#ifdef HAVE_SCROLLWHEEL
+ /* 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);
+
+ accumulated_wheel_delta = 0;
+#else
+ queue_post(&button_queue, wheel_keycode | repeat,
+ (wheel_delta << 16) | new_wheel_value);
+#endif
+ }
+
+ if (!repeat) repeat = BUTTON_REPEAT;
+#ifdef HAVE_SCROLLWHEEL
+ last_wheel_usec = usec;
+#endif
}
-
- 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();
}
}
@@ -200,14 +266,23 @@
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;
+
+#ifdef HAVE_SCROLLWHEEL
+ /* Get current tick before enabling button interrupts */
+ last_wheel_usec = USEC_TIMER;
+#endif
+
/* enable interrupts */
GPIOA_INT_EN = 0x20;
+
/* unmask interrupt */
CPU_INT_EN = 0x40000000;
CPU_HI_INT_EN = I2C_MASK;
Index: firmware/target/arm/sandisk/sansa-e200/button-e200.c
===================================================================
--- firmware/target/arm/sandisk/sansa-e200/button-e200.c (revision 14668)
+++ firmware/target/arm/sandisk/sansa-e200/button-e200.c (working copy)
@@ -136,11 +136,9 @@
unsigned long usec = USEC_TIMER;
unsigned v = (usec - last_wheel_usec) & 0x7fffffff;
- /* wheel velocity in 0.24 fixed point - clicks/uS */
+ v = (v>0) ? 1000000 / v : 0; /* clicks/s = 1000000 * clicks/usec */
+ v = (v>0xffffff) ? 0xffffff : v; /* limit to 24 bit */
- /* velocity cap to 18 bits to allow up to x16 scaling */
- v = (v < 0x40) ? 0xffffff / 0x40 : 0xffffff / v;
-
/* some velocity filtering to smooth things out */
wheel_velocity = (7*wheel_velocity + v) / 8;
@@ -172,12 +170,12 @@
else
{
/* fast ON gets filtered to avoid inadvertent jumps to fast mode */
- if (repeat && wheel_velocity > 0xffffff/WHEEL_FAST_ON_INTERVAL)
+ if (repeat && wheel_velocity > 1000000/WHEEL_FAST_ON_INTERVAL)
{
/* moving into fast mode */
wheel_fast_mode = 1 << 31;
wheel_click_count = 0;
- wheel_velocity = 0xffffff/WHEEL_FAST_OFF_INTERVAL;
+ wheel_velocity = 1000000/WHEEL_FAST_OFF_INTERVAL;
}
else if (++wheel_click_count < 2)
{
@@ -189,7 +187,7 @@
}
if (TIME_AFTER(current_tick, next_backlight_on) ||
- v <= 0xffffff/(1000000/4))
+ v <= 4)
{
/* poke backlight to turn it on or maintain it no more often
than every 1/4 second*/
Index: firmware/drivers/button.c
===================================================================
--- firmware/drivers/button.c (revision 14668)
+++ firmware/drivers/button.c (working copy)
@@ -490,22 +490,29 @@
* data:
* [31] Use acceleration
* [30:24] Message post count (skipped + 1) (1-127)
- * [23:0] Velocity - clicks/uS - 0.24 fixed point
+ * [23:0] Velocity - clicks/sec
*
* factor:
- * Wheel acceleration scaling factor - x.24 fixed point -
- * no greater than what will not overflow 64 bits when multiplied
- * by the driver's maximum velocity in (clicks/usec)^2 in 0.24
+ * Value in clicks/sec -- configurable via settings (50...200) -- above
+ * which the accelerated scrolling starts. Factor is internally scaled by
+ * 1<<20 in respect to the following 32bit integer operations.
*/
-int button_apply_acceleration(unsigned int data, unsigned int factor)
+int button_apply_acceleration(const unsigned int data, unsigned int factor)
{
int delta = (data >> 24) & 0x7f;
+
+ /* factor = 2^20 / (global_settings.wheel_accel_start)^2 */
+ /* 2^20 needed as normalization */
+ /* factor = 26...419 (200 clicks/sec ... 50 clicks/sec) */
+ factor = (1<<20)/(factor*factor);
if ((data & (1 << 31)) != 0)
{
unsigned int v = data & 0xffffff;
- v = factor * (unsigned long long)v*v / 0xffffffffffffull;
+ /* limit velocity to 10 bit to prevent from overflow */
+ v = (v<=0x3ff) ? v : 0x3ff;
+ v = (factor * v*v)>>20;
if (v > 1)
delta *= v;