FS#7738 - Scroll wheel acceleration for iPod
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15681 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
a8c020288c
commit
e75327b332
11 changed files with 231 additions and 67 deletions
|
@ -1011,8 +1011,7 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifdef HAVE_SCROLLWHEEL
|
#ifdef HAVE_SCROLLWHEEL
|
||||||
int next_item_modifier = button_apply_acceleration(get_action_data(),
|
int next_item_modifier = button_apply_acceleration(get_action_data());
|
||||||
WHEEL_ACCELERATION_FACTOR);
|
|
||||||
#else
|
#else
|
||||||
static int next_item_modifier = 1;
|
static int next_item_modifier = 1;
|
||||||
static int last_accel_tick = 0;
|
static int last_accel_tick = 0;
|
||||||
|
|
|
@ -522,26 +522,40 @@ void button_clear_queue(void)
|
||||||
#endif /* SIMULATOR */
|
#endif /* SIMULATOR */
|
||||||
|
|
||||||
#ifdef HAVE_SCROLLWHEEL
|
#ifdef HAVE_SCROLLWHEEL
|
||||||
|
/* WHEEL_ACCEL_FACTOR = 2^16 / WHEEL_ACCEL_START */
|
||||||
|
#define WHEEL_ACCEL_FACTOR (1<<16)/WHEEL_ACCEL_START
|
||||||
/**
|
/**
|
||||||
* data:
|
* data:
|
||||||
* [31] Use acceleration
|
* [31] Use acceleration
|
||||||
* [30:24] Message post count (skipped + 1) (1-127)
|
* [30:24] Message post count (skipped + 1) (1-127)
|
||||||
* [23:0] Velocity - clicks/uS - 0.24 fixed point
|
* [23:0] Velocity - degree/sec
|
||||||
*
|
*
|
||||||
* factor:
|
* WHEEL_ACCEL_FACTOR:
|
||||||
* Wheel acceleration scaling factor - x.24 fixed point -
|
* Value in degree/sec -- configurable via settings -- above which
|
||||||
* no greater than what will not overflow 64 bits when multiplied
|
* the accelerated scrolling starts. Factor is internally scaled by
|
||||||
* by the driver's maximum velocity in (clicks/usec)^2 in 0.24
|
* 1<<16 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)
|
||||||
{
|
{
|
||||||
int delta = (data >> 24) & 0x7f;
|
int delta = (data >> 24) & 0x7f;
|
||||||
|
|
||||||
if ((data & (1 << 31)) != 0)
|
if ((data & (1 << 31)) != 0)
|
||||||
{
|
{
|
||||||
|
/* read driver's velocity from data */
|
||||||
unsigned int v = data & 0xffffff;
|
unsigned int v = data & 0xffffff;
|
||||||
|
|
||||||
v = factor * (unsigned long long)v*v / 0xffffffffffffull;
|
/* v = 28.4 fixed point */
|
||||||
|
v = (WHEEL_ACCEL_FACTOR * v)>>(16-4);
|
||||||
|
|
||||||
|
/* Calculate real numbers item to scroll based upon acceleration
|
||||||
|
* setting, use correct roundoff */
|
||||||
|
#if (WHEEL_ACCELERATION == 1)
|
||||||
|
v = (v*v + (1<< 7))>> 8;
|
||||||
|
#elif (WHEEL_ACCELERATION == 2)
|
||||||
|
v = (v*v*v + (1<<11))>>12;
|
||||||
|
#elif (WHEEL_ACCELERATION == 3)
|
||||||
|
v = (v*v*v*v + (1<<15))>>16;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (v > 1)
|
if (v > 1)
|
||||||
delta *= v;
|
delta *= v;
|
||||||
|
|
|
@ -52,7 +52,7 @@ void wheel_send_events(bool send);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SCROLLWHEEL
|
#ifdef HAVE_SCROLLWHEEL
|
||||||
int button_apply_acceleration(unsigned int data, unsigned int factor);
|
int button_apply_acceleration(const unsigned int data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define BUTTON_NONE 0x00000000
|
#define BUTTON_NONE 0x00000000
|
||||||
|
|
|
@ -100,9 +100,10 @@
|
||||||
|
|
||||||
/* define this if the unit uses a scrollwheel for navigation */
|
/* define this if the unit uses a scrollwheel for navigation */
|
||||||
#define HAVE_SCROLLWHEEL
|
#define HAVE_SCROLLWHEEL
|
||||||
/* define wheel acceleration scaling factor */
|
/* define from which rotation speed [degree/sec] on the acceleration starts */
|
||||||
/* Range for this target: 0xffffff*(0.0-16.000000894069724921567733381255) */
|
#define WHEEL_ACCEL_START 540
|
||||||
#define WHEEL_ACCELERATION_FACTOR (0xffffff*7)
|
/* define type of acceleration (1 = ^2, 2 = ^3, 3 = ^4) */
|
||||||
|
#define WHEEL_ACCELERATION 1
|
||||||
|
|
||||||
/* define this if you have a flash memory storage */
|
/* define this if you have a flash memory storage */
|
||||||
#define HAVE_FLASH_STORAGE
|
#define HAVE_FLASH_STORAGE
|
||||||
|
|
|
@ -86,6 +86,13 @@
|
||||||
/* Define this for LCD backlight available */
|
/* Define this for LCD backlight available */
|
||||||
#define HAVE_BACKLIGHT
|
#define HAVE_BACKLIGHT
|
||||||
|
|
||||||
|
/* define this if the unit uses a scrollwheel for navigation */
|
||||||
|
#define HAVE_SCROLLWHEEL
|
||||||
|
/* define from which rotation speed [degree/sec] on the acceleration starts */
|
||||||
|
#define WHEEL_ACCEL_START 270
|
||||||
|
/* define type of acceleration (1 = ^2, 2 = ^3, 3 = ^4) */
|
||||||
|
#define WHEEL_ACCELERATION 3
|
||||||
|
|
||||||
/* Define this if you can detect headphones */
|
/* Define this if you can detect headphones */
|
||||||
#define HAVE_HEADPHONE_DETECTION
|
#define HAVE_HEADPHONE_DETECTION
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,13 @@
|
||||||
/* Define this for LCD backlight available */
|
/* Define this for LCD backlight available */
|
||||||
#define HAVE_BACKLIGHT
|
#define HAVE_BACKLIGHT
|
||||||
|
|
||||||
|
/* define this if the unit uses a scrollwheel for navigation */
|
||||||
|
#define HAVE_SCROLLWHEEL
|
||||||
|
/* define from which rotation speed [degree/sec] on the acceleration starts */
|
||||||
|
#define WHEEL_ACCEL_START 270
|
||||||
|
/* define type of acceleration (1 = ^2, 2 = ^3, 3 = ^4) */
|
||||||
|
#define WHEEL_ACCELERATION 3
|
||||||
|
|
||||||
/* Define this if you can detect headphones */
|
/* Define this if you can detect headphones */
|
||||||
#define HAVE_HEADPHONE_DETECTION
|
#define HAVE_HEADPHONE_DETECTION
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,13 @@
|
||||||
/* We can fade the backlight by using PWM */
|
/* We can fade the backlight by using PWM */
|
||||||
#define HAVE_BACKLIGHT_PWM_FADING
|
#define HAVE_BACKLIGHT_PWM_FADING
|
||||||
|
|
||||||
|
/* define this if the unit uses a scrollwheel for navigation */
|
||||||
|
#define HAVE_SCROLLWHEEL
|
||||||
|
/* define from which rotation speed [degree/sec] on the acceleration starts */
|
||||||
|
#define WHEEL_ACCEL_START 270
|
||||||
|
/* define type of acceleration (1 = ^2, 2 = ^3, 3 = ^4) */
|
||||||
|
#define WHEEL_ACCELERATION 3
|
||||||
|
|
||||||
/* Define this if you can detect headphones */
|
/* Define this if you can detect headphones */
|
||||||
#define HAVE_HEADPHONE_DETECTION
|
#define HAVE_HEADPHONE_DETECTION
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,13 @@
|
||||||
/* We can fade the backlight by using PWM */
|
/* We can fade the backlight by using PWM */
|
||||||
#define HAVE_BACKLIGHT_PWM_FADING
|
#define HAVE_BACKLIGHT_PWM_FADING
|
||||||
|
|
||||||
|
/* define this if the unit uses a scrollwheel for navigation */
|
||||||
|
#define HAVE_SCROLLWHEEL
|
||||||
|
/* define from which rotation speed [degree/sec] on the acceleration starts */
|
||||||
|
#define WHEEL_ACCEL_START 270
|
||||||
|
/* define type of acceleration (1 = ^2, 2 = ^3, 3 = ^4) */
|
||||||
|
#define WHEEL_ACCELERATION 3
|
||||||
|
|
||||||
/* Define this if you can detect headphones */
|
/* Define this if you can detect headphones */
|
||||||
#define HAVE_HEADPHONE_DETECTION
|
#define HAVE_HEADPHONE_DETECTION
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,13 @@
|
||||||
/* We can fade the backlight by using PWM */
|
/* We can fade the backlight by using PWM */
|
||||||
#define HAVE_BACKLIGHT_PWM_FADING
|
#define HAVE_BACKLIGHT_PWM_FADING
|
||||||
|
|
||||||
|
/* define this if the unit uses a scrollwheel for navigation */
|
||||||
|
#define HAVE_SCROLLWHEEL
|
||||||
|
/* define from which rotation speed [degree/sec] on the acceleration starts */
|
||||||
|
#define WHEEL_ACCEL_START 270
|
||||||
|
/* define type of acceleration (1 = ^2, 2 = ^3, 3 = ^4) */
|
||||||
|
#define WHEEL_ACCELERATION 3
|
||||||
|
|
||||||
/* Define this if you can detect headphones */
|
/* Define this if you can detect headphones */
|
||||||
#define HAVE_HEADPHONE_DETECTION
|
#define HAVE_HEADPHONE_DETECTION
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,30 @@
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "powermgmt.h"
|
#include "powermgmt.h"
|
||||||
|
|
||||||
|
#define WHEEL_FAST_OFF_TIMEOUT 250000 /* timeout for acceleration = 250ms */
|
||||||
|
#define WHEEL_REPEAT_TIMEOUT 250000 /* timeout for button repeat = 250ms */
|
||||||
|
#define WHEEL_UNTOUCH_TIMEOUT 150000 /* timeout for untouching wheel = 100ms */
|
||||||
|
#define WHEELCLICKS_PER_ROTATION 96 /* wheelclicks per full rotation */
|
||||||
|
|
||||||
|
/* This amount of clicks is needed for at least scrolling 1 item. Choose small values
|
||||||
|
* to have high sensitivity but few precision, choose large values to have less
|
||||||
|
* sensitivity and good precision. */
|
||||||
|
#if defined(IPOD_NANO)
|
||||||
|
#define WHEEL_SENSITIVITY 6 /* iPod nano has smaller wheel, lower sensitivity needed */
|
||||||
|
#else
|
||||||
|
#define WHEEL_SENSITIVITY 4 /* default sensitivity */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int old_wheel_value = -1;
|
||||||
|
int new_wheel_value = 0;
|
||||||
|
int repeat = 0;
|
||||||
|
int wheel_delta = 0;
|
||||||
|
bool wheel_is_touched = false;
|
||||||
|
unsigned int accumulated_wheel_delta = 0;
|
||||||
|
unsigned int wheel_repeat = 0;
|
||||||
|
unsigned int wheel_velocity = 0;
|
||||||
|
unsigned long last_wheel_usec = 0;
|
||||||
|
|
||||||
/* Variable to use for setting button status in interrupt handler */
|
/* Variable to use for setting button status in interrupt handler */
|
||||||
int int_btn = BUTTON_NONE;
|
int int_btn = BUTTON_NONE;
|
||||||
#ifdef HAVE_WHEEL_POSITION
|
#ifdef HAVE_WHEEL_POSITION
|
||||||
|
@ -89,16 +113,15 @@ static inline int ipod_4g_button_read(void)
|
||||||
|
|
||||||
int btn = BUTTON_NONE;
|
int btn = BUTTON_NONE;
|
||||||
unsigned reg = 0x7000c104;
|
unsigned reg = 0x7000c104;
|
||||||
if ((inl(0x7000c104) & 0x4000000) != 0) {
|
if ((inl(0x7000c104) & 0x4000000) != 0)
|
||||||
|
{
|
||||||
unsigned status = inl(0x7000c140);
|
unsigned status = inl(0x7000c140);
|
||||||
|
|
||||||
reg = reg + 0x3C; /* 0x7000c140 */
|
reg = reg + 0x3C; /* 0x7000c140 */
|
||||||
outl(0x0, 0x7000c140); /* clear interrupt status? */
|
outl(0x0, 0x7000c140); /* clear interrupt status? */
|
||||||
|
|
||||||
if ((status & 0x800000ff) == 0x8000001a) {
|
if ((status & 0x800000ff) == 0x8000001a)
|
||||||
static int old_wheel_value IDATA_ATTR = -1;
|
{
|
||||||
static int wheel_repeat = 0;
|
|
||||||
|
|
||||||
if (status & 0x100)
|
if (status & 0x100)
|
||||||
btn |= BUTTON_SELECT;
|
btn |= BUTTON_SELECT;
|
||||||
if (status & 0x200)
|
if (status & 0x200)
|
||||||
|
@ -109,63 +132,152 @@ static inline int ipod_4g_button_read(void)
|
||||||
btn |= BUTTON_PLAY;
|
btn |= BUTTON_PLAY;
|
||||||
if (status & 0x1000)
|
if (status & 0x1000)
|
||||||
btn |= BUTTON_MENU;
|
btn |= BUTTON_MENU;
|
||||||
if (status & 0x40000000) {
|
if (status & 0x40000000)
|
||||||
/* NB: highest wheel = 0x5F, clockwise increases */
|
{
|
||||||
int new_wheel_value = (status << 9) >> 25;
|
unsigned long usec = USEC_TIMER;
|
||||||
|
|
||||||
|
/* Highest wheel = 0x5F, clockwise increases */
|
||||||
|
new_wheel_value = (status >> 16) & 0x7f;
|
||||||
whl = new_wheel_value;
|
whl = new_wheel_value;
|
||||||
|
|
||||||
|
/* switch on backlight (again), reset power-off timer */
|
||||||
backlight_on();
|
backlight_on();
|
||||||
reset_poweroff_timer();
|
reset_poweroff_timer();
|
||||||
/* The queue should have no other events when scrolling */
|
|
||||||
if (queue_empty(&button_queue) && old_wheel_value >= 0) {
|
/* Check whether the scrollwheel was untouched by accident or by will. */
|
||||||
|
/* This is needed because wheel may be untoched very shortly during rotation */
|
||||||
/* This is for later = BUTTON_SCROLL_TOUCH;*/
|
if ( (!wheel_is_touched) && TIME_AFTER(usec, last_wheel_usec + WHEEL_UNTOUCH_TIMEOUT) )
|
||||||
int wheel_delta = new_wheel_value - old_wheel_value;
|
{
|
||||||
unsigned long data;
|
/* wheel has been really untouched -> reset internal variables */
|
||||||
int wheel_keycode;
|
old_wheel_value = -1;
|
||||||
|
wheel_velocity = 0;
|
||||||
if (wheel_delta < -48)
|
accumulated_wheel_delta = 0;
|
||||||
wheel_delta += 96; /* Forward wrapping case */
|
wheel_repeat = BUTTON_NONE;
|
||||||
else if (wheel_delta > 48)
|
}
|
||||||
wheel_delta -= 96; /* Backward wrapping case */
|
else
|
||||||
|
{
|
||||||
if (wheel_delta > 4) {
|
/* wheel was shortly untouched by accident -> leave internal variables */
|
||||||
wheel_keycode = BUTTON_SCROLL_FWD;
|
wheel_is_touched = true;
|
||||||
} else if (wheel_delta < -4) {
|
|
||||||
wheel_keycode = BUTTON_SCROLL_BACK;
|
|
||||||
} else goto wheel_end;
|
|
||||||
|
|
||||||
#ifdef HAVE_WHEEL_POSITION
|
|
||||||
if (send_events)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
data = (wheel_delta << 16) | new_wheel_value;
|
|
||||||
queue_post(&button_queue, wheel_keycode | wheel_repeat,
|
|
||||||
data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wheel_repeat) wheel_repeat = BUTTON_REPEAT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
old_wheel_value = new_wheel_value;
|
if (old_wheel_value >= 0)
|
||||||
} else if (old_wheel_value >= 0) {
|
{
|
||||||
/* scroll wheel up */
|
/* This is for later = BUTTON_SCROLL_TOUCH;*/
|
||||||
old_wheel_value = -1;
|
wheel_delta = new_wheel_value - old_wheel_value;
|
||||||
wheel_repeat = 0;
|
unsigned int wheel_keycode = BUTTON_NONE;
|
||||||
|
|
||||||
|
/* Taking into account wrapping during transition from highest
|
||||||
|
* to lowest wheel position and back */
|
||||||
|
if (wheel_delta < -WHEELCLICKS_PER_ROTATION/2)
|
||||||
|
wheel_delta += WHEELCLICKS_PER_ROTATION; /* Forward wrapping case */
|
||||||
|
else if (wheel_delta > WHEELCLICKS_PER_ROTATION/2)
|
||||||
|
wheel_delta -= WHEELCLICKS_PER_ROTATION; /* Backward wrapping case */
|
||||||
|
|
||||||
|
/* Getting direction and wheel_keycode from wheel_delta.
|
||||||
|
* Need at least some clicks to be sure to avoid haptic fuzziness */
|
||||||
|
if (wheel_delta >= WHEEL_SENSITIVITY)
|
||||||
|
wheel_keycode = BUTTON_SCROLL_FWD;
|
||||||
|
else if (wheel_delta <= -WHEEL_SENSITIVITY)
|
||||||
|
wheel_keycode = BUTTON_SCROLL_BACK;
|
||||||
|
else
|
||||||
|
wheel_keycode = BUTTON_NONE;
|
||||||
|
|
||||||
|
if (wheel_keycode != BUTTON_NONE)
|
||||||
|
{
|
||||||
|
long v = (usec - last_wheel_usec) & 0x7fffffff;
|
||||||
|
|
||||||
|
/* undo signedness */
|
||||||
|
wheel_delta = (wheel_delta>0) ? wheel_delta : -wheel_delta;
|
||||||
|
|
||||||
|
/* add the current wheel_delta */
|
||||||
|
accumulated_wheel_delta += wheel_delta;
|
||||||
|
|
||||||
|
v = v ? (1000000 * wheel_delta) / v : 0; /* clicks/sec = 1000000 * clicks/usec */
|
||||||
|
v = (v * 360) / WHEELCLICKS_PER_ROTATION; /* conversion to degree/sec */
|
||||||
|
v = (v<0) ? -v : v; /* undo signedness */
|
||||||
|
|
||||||
|
/* some velocity filtering to smooth things out */
|
||||||
|
wheel_velocity = (31 * wheel_velocity + v) / 32;
|
||||||
|
/* limit to 24 bit */
|
||||||
|
wheel_velocity = (wheel_velocity>0xffffff) ? 0xffffff : wheel_velocity;
|
||||||
|
|
||||||
|
/* assume REPEAT = off */
|
||||||
|
repeat = 0;
|
||||||
|
|
||||||
|
/* direction reversals must nullify acceleration and accumulator */
|
||||||
|
if (wheel_keycode != wheel_repeat)
|
||||||
|
{
|
||||||
|
wheel_repeat = wheel_keycode;
|
||||||
|
wheel_velocity = 0;
|
||||||
|
accumulated_wheel_delta = 0;
|
||||||
|
}
|
||||||
|
/* on same direction REPEAT is assumed when new click is within timeout */
|
||||||
|
else if (TIME_BEFORE(usec, last_wheel_usec + WHEEL_REPEAT_TIMEOUT))
|
||||||
|
{
|
||||||
|
repeat = BUTTON_REPEAT;
|
||||||
|
}
|
||||||
|
/* timeout nullifies acceleration and accumulator */
|
||||||
|
if (TIME_AFTER(usec, last_wheel_usec + WHEEL_FAST_OFF_TIMEOUT))
|
||||||
|
{
|
||||||
|
wheel_velocity = 0;
|
||||||
|
accumulated_wheel_delta = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_WHEEL_POSITION
|
||||||
|
if (send_events)
|
||||||
|
#endif
|
||||||
|
/* The queue should have no other events when scrolling */
|
||||||
|
if (queue_empty(&button_queue))
|
||||||
|
{
|
||||||
|
/* each WHEEL_SENSITIVITY clicks = scrolling 1 item */
|
||||||
|
accumulated_wheel_delta /= WHEEL_SENSITIVITY;
|
||||||
|
#ifdef HAVE_SCROLLWHEEL
|
||||||
|
/* use data-format for HAVE_SCROLLWHEEL */
|
||||||
|
/* always use acceleration mode (1<<31) */
|
||||||
|
/* always set message post count to (1<<24) for iPod */
|
||||||
|
/* this way the scrolling is always calculated from wheel_velocity */
|
||||||
|
queue_post(&button_queue, wheel_keycode | repeat,
|
||||||
|
(1<<31) | (1 << 24) | wheel_velocity);
|
||||||
|
|
||||||
|
#else
|
||||||
|
queue_post(&button_queue, wheel_keycode | repeat,
|
||||||
|
(accumulated_wheel_delta << 16) | new_wheel_value);
|
||||||
|
#endif
|
||||||
|
accumulated_wheel_delta = 0;
|
||||||
|
}
|
||||||
|
last_wheel_usec = usec;
|
||||||
|
old_wheel_value = new_wheel_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* scrollwheel was touched for the first time after finger lifting */
|
||||||
|
old_wheel_value = new_wheel_value;
|
||||||
|
wheel_is_touched = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* In this case the finger was lifted from the scrollwheel. */
|
||||||
|
wheel_is_touched = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (status == 0xffffffff) {
|
}
|
||||||
|
else if (status == 0xffffffff)
|
||||||
|
{
|
||||||
opto_i2c_init();
|
opto_i2c_init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wheel_end:
|
if ((inl(reg) & 0x8000000) != 0)
|
||||||
|
{
|
||||||
if ((inl(reg) & 0x8000000) != 0) {
|
|
||||||
outl(0xffffffff, 0x7000c120);
|
outl(0xffffffff, 0x7000c120);
|
||||||
outl(0xffffffff, 0x7000c124);
|
outl(0xffffffff, 0x7000c124);
|
||||||
}
|
}
|
||||||
/* Save the new absolute wheel position */
|
/* Save the new absolute wheel position */
|
||||||
|
#ifdef HAVE_WHEEL_POSITION
|
||||||
wheel_position = whl;
|
wheel_position = whl;
|
||||||
|
#endif
|
||||||
return btn;
|
return btn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,14 +312,18 @@ void ipod_4g_button_int(void)
|
||||||
void button_init_device(void)
|
void button_init_device(void)
|
||||||
{
|
{
|
||||||
opto_i2c_init();
|
opto_i2c_init();
|
||||||
|
|
||||||
/* hold button - enable as input */
|
/* hold button - enable as input */
|
||||||
GPIOA_ENABLE |= 0x20;
|
GPIOA_ENABLE |= 0x20;
|
||||||
GPIOA_OUTPUT_EN &= ~0x20;
|
GPIOA_OUTPUT_EN &= ~0x20;
|
||||||
|
|
||||||
/* hold button - set interrupt levels */
|
/* hold button - set interrupt levels */
|
||||||
GPIOA_INT_LEV = ~(GPIOA_INPUT_VAL & 0x20);
|
GPIOA_INT_LEV = ~(GPIOA_INPUT_VAL & 0x20);
|
||||||
GPIOA_INT_CLR = GPIOA_INT_STAT & 0x20;
|
GPIOA_INT_CLR = GPIOA_INT_STAT & 0x20;
|
||||||
|
|
||||||
/* enable interrupts */
|
/* enable interrupts */
|
||||||
GPIOA_INT_EN = 0x20;
|
GPIOA_INT_EN = 0x20;
|
||||||
|
|
||||||
/* unmask interrupt */
|
/* unmask interrupt */
|
||||||
CPU_INT_EN = 0x40000000;
|
CPU_INT_EN = 0x40000000;
|
||||||
CPU_HI_INT_EN = I2C_MASK;
|
CPU_HI_INT_EN = I2C_MASK;
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#define WHEEL_REPEAT_INTERVAL 300000
|
#define WHEEL_REPEAT_INTERVAL 300000
|
||||||
#define WHEEL_FAST_ON_INTERVAL 20000
|
#define WHEEL_FAST_ON_INTERVAL 20000
|
||||||
#define WHEEL_FAST_OFF_INTERVAL 60000
|
#define WHEEL_FAST_OFF_INTERVAL 60000
|
||||||
|
#define WHEELCLICKS_PER_ROTATION 48 /* wheelclicks per full rotation */
|
||||||
|
|
||||||
/* Clickwheel */
|
/* Clickwheel */
|
||||||
#ifndef BOOTLOADER
|
#ifndef BOOTLOADER
|
||||||
|
@ -137,10 +138,8 @@ void clickwheel_int(void)
|
||||||
unsigned long usec = USEC_TIMER;
|
unsigned long usec = USEC_TIMER;
|
||||||
unsigned v = (usec - last_wheel_usec) & 0x7fffffff;
|
unsigned v = (usec - last_wheel_usec) & 0x7fffffff;
|
||||||
|
|
||||||
/* wheel velocity in 0.24 fixed point - clicks/uS */
|
v = (v>0) ? 1000000 / v : 0; /* clicks/sec = 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 */
|
/* some velocity filtering to smooth things out */
|
||||||
wheel_velocity = (7*wheel_velocity + v) / 8;
|
wheel_velocity = (7*wheel_velocity + v) / 8;
|
||||||
|
@ -173,12 +172,12 @@ void clickwheel_int(void)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* fast ON gets filtered to avoid inadvertent jumps to fast mode */
|
/* 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 */
|
/* moving into fast mode */
|
||||||
wheel_fast_mode = 1 << 31;
|
wheel_fast_mode = 1 << 31;
|
||||||
wheel_click_count = 0;
|
wheel_click_count = 0;
|
||||||
wheel_velocity = 0xffffff/WHEEL_FAST_OFF_INTERVAL;
|
wheel_velocity = 1000000/WHEEL_FAST_OFF_INTERVAL;
|
||||||
}
|
}
|
||||||
else if (++wheel_click_count < 2)
|
else if (++wheel_click_count < 2)
|
||||||
{
|
{
|
||||||
|
@ -190,7 +189,7 @@ void clickwheel_int(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TIME_AFTER(current_tick, next_backlight_on) ||
|
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
|
/* poke backlight to turn it on or maintain it no more often
|
||||||
than every 1/4 second*/
|
than every 1/4 second*/
|
||||||
|
@ -214,7 +213,7 @@ void clickwheel_int(void)
|
||||||
if (queue_empty(&button_queue))
|
if (queue_empty(&button_queue))
|
||||||
{
|
{
|
||||||
queue_post(&button_queue, btn, wheel_fast_mode |
|
queue_post(&button_queue, btn, wheel_fast_mode |
|
||||||
(wheel_delta << 24) | wheel_velocity);
|
(wheel_delta << 24) | wheel_velocity*360/WHEELCLICKS_PER_ROTATION);
|
||||||
/* message posted - reset delta */
|
/* message posted - reset delta */
|
||||||
wheel_delta = 1;
|
wheel_delta = 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue