diff options
author | Thomas Martitz <kugel@rockbox.org> | 2010-04-01 16:07:56 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2010-04-01 16:07:56 +0000 |
commit | f376fd2f4aa9b27f2a6299177b4cc3c014da01f3 (patch) | |
tree | e42edd558e2deff42d3522189d92d158e861a307 /firmware/target/arm/as3525 | |
parent | 47dcf58e28930af8b468aa2151f1288e9ec334df (diff) | |
download | rockbox-f376fd2f4aa9b27f2a6299177b4cc3c014da01f3.tar.gz rockbox-f376fd2f4aa9b27f2a6299177b4cc3c014da01f3.zip |
Fuzev2: Scrollwheel works like a charm :)
Move scrollwheel parsing function into separate file as it's reused.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25425 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/as3525')
7 files changed, 180 insertions, 111 deletions
diff --git a/firmware/target/arm/as3525/button-e200v2-fuze.c b/firmware/target/arm/as3525/button-e200v2-fuze.c index 2a75fa1e6f..2cbdcf5130 100644 --- a/firmware/target/arm/as3525/button-e200v2-fuze.c +++ b/firmware/target/arm/as3525/button-e200v2-fuze.c | |||
@@ -27,21 +27,14 @@ | |||
27 | #include "backlight.h" | 27 | #include "backlight.h" |
28 | #include "dbop-as3525.h" | 28 | #include "dbop-as3525.h" |
29 | 29 | ||
30 | extern void scrollwheel(unsigned wheel_value); | ||
30 | 31 | ||
31 | #if defined(SANSA_FUZE) || defined(SANSA_FUZEV2) | 32 | #if defined(SANSA_FUZE) |
32 | #define DBOP_BIT15_BUTTON BUTTON_HOME | 33 | #define DBOP_BIT15_BUTTON BUTTON_HOME |
33 | #define WHEEL_REPEAT_INTERVAL (HZ/5) | ||
34 | #define WHEEL_COUNTER_DIV 4 | ||
35 | #define ACCEL_INCREMENT 2 | ||
36 | #define ACCEL_SHIFT 2 | ||
37 | #endif | 34 | #endif |
38 | 35 | ||
39 | #ifdef SANSA_E200V2 | 36 | #ifdef SANSA_E200V2 |
40 | #define DBOP_BIT15_BUTTON BUTTON_REC | 37 | #define DBOP_BIT15_BUTTON BUTTON_REC |
41 | #define WHEEL_REPEAT_INTERVAL (HZ/5) | ||
42 | #define WHEEL_COUNTER_DIV 2 | ||
43 | #define ACCEL_INCREMENT 3 | ||
44 | #define ACCEL_SHIFT 1 | ||
45 | #endif | 38 | #endif |
46 | 39 | ||
47 | /* Buttons */ | 40 | /* Buttons */ |
@@ -56,103 +49,6 @@ void button_init_device(void) | |||
56 | GPIOA_PIN(1) = (1<<1); | 49 | GPIOA_PIN(1) = (1<<1); |
57 | } | 50 | } |
58 | 51 | ||
59 | #if !defined(BOOTLOADER) && defined(HAVE_SCROLLWHEEL) | ||
60 | static void scrollwheel(unsigned int wheel_value) | ||
61 | { | ||
62 | /* current wheel values, parsed from dbop and the resulting button */ | ||
63 | unsigned btn = BUTTON_NONE; | ||
64 | /* old wheel values */ | ||
65 | static unsigned old_wheel_value = 0; | ||
66 | static unsigned old_btn = BUTTON_NONE; | ||
67 | |||
68 | /* | ||
69 | * Getting BUTTON_REPEAT works like this: Remember when the btn value was | ||
70 | * posted to the button_queue last, and if it was recent enough, generate | ||
71 | * BUTTON_REPEAT | ||
72 | */ | ||
73 | static long last_wheel_post = 0; | ||
74 | |||
75 | /* | ||
76 | * Providing wheel acceleration works as follows: We increment accel | ||
77 | * by 2 if the wheel was turned, and decrement it by 1 each tick | ||
78 | * (no matter if it was turned), that means: the longer and faster you turn, | ||
79 | * the higher accel will be. accel>>2 will actually posted to the button_queue | ||
80 | */ | ||
81 | static int accel = 0; | ||
82 | /* We only post every 4th action, as this matches better with the physical | ||
83 | * clicks of the wheel */ | ||
84 | static int counter = 0; | ||
85 | /* Read wheel | ||
86 | * Bits 13 and 14 of DBOP_DIN change as follows (Gray Code): | ||
87 | * Clockwise rotation 00 -> 01 -> 11 -> 10 -> 00 | ||
88 | * Counter-clockwise 00 -> 10 -> 11 -> 01 -> 00 | ||
89 | * | ||
90 | * For easy look-up, actual wheel values act as indicies also, | ||
91 | * which is why the table seems to be not ordered correctly | ||
92 | */ | ||
93 | static const unsigned char wheel_tbl[2][4] = | ||
94 | { | ||
95 | { 2, 0, 3, 1 }, /* Clockwise rotation */ | ||
96 | { 1, 3, 0, 2 }, /* Counter-clockwise */ | ||
97 | }; | ||
98 | |||
99 | if(hold_button) | ||
100 | { | ||
101 | accel = counter = 0; | ||
102 | return; | ||
103 | } | ||
104 | |||
105 | if (old_wheel_value == wheel_tbl[0][wheel_value]) | ||
106 | btn = BUTTON_SCROLL_FWD; | ||
107 | else if (old_wheel_value == wheel_tbl[1][wheel_value]) | ||
108 | btn = BUTTON_SCROLL_BACK; | ||
109 | else if (old_wheel_value != wheel_value && accel > ACCEL_INCREMENT) | ||
110 | { /* if no button is read and wheel_value changed, assume old_btn */ | ||
111 | btn = old_btn; | ||
112 | } | ||
113 | /* else btn = BUTTON_NONE */ | ||
114 | |||
115 | if (btn != BUTTON_NONE) | ||
116 | { | ||
117 | if (btn != old_btn) | ||
118 | { | ||
119 | /* direction reversals nullify acceleration and counters */ | ||
120 | old_btn = btn; | ||
121 | accel = counter = 0; | ||
122 | } | ||
123 | /* wheel_delta will cause lists to jump over items, | ||
124 | * we want this for fast scrolling, but we must keep it accurate | ||
125 | * for slow scrolling */ | ||
126 | int wheel_delta = 0; | ||
127 | /* generate BUTTON_REPEAT if quick enough, scroll slightly faster too*/ | ||
128 | if (TIME_BEFORE(current_tick, last_wheel_post + WHEEL_REPEAT_INTERVAL)) | ||
129 | { | ||
130 | btn |= BUTTON_REPEAT; | ||
131 | wheel_delta = accel>>ACCEL_SHIFT; | ||
132 | } | ||
133 | |||
134 | accel += ACCEL_INCREMENT; | ||
135 | |||
136 | /* the wheel is more reliable if we don't send every change, | ||
137 | * every WHEEL_COUNTER_DIVth is basically one "physical click" | ||
138 | * which should make up 1 item in lists */ | ||
139 | if (++counter >= WHEEL_COUNTER_DIV && queue_empty(&button_queue)) | ||
140 | { | ||
141 | buttonlight_on(); | ||
142 | backlight_on(); | ||
143 | queue_post(&button_queue, btn, ((wheel_delta+1)<<24)); | ||
144 | /* message posted - reset count and remember post */ | ||
145 | counter = 0; | ||
146 | last_wheel_post = current_tick; | ||
147 | } | ||
148 | } | ||
149 | if (accel > 0) | ||
150 | accel--; | ||
151 | |||
152 | old_wheel_value = wheel_value; | ||
153 | } | ||
154 | #endif /* !defined(BOOTLOADER) && defined(SCROLLWHEEL) */ | ||
155 | |||
156 | bool button_hold(void) | 52 | bool button_hold(void) |
157 | { | 53 | { |
158 | return hold_button; | 54 | return hold_button; |
diff --git a/firmware/target/arm/as3525/kernel-as3525.c b/firmware/target/arm/as3525/kernel-as3525.c index 4c421e50fc..ebaef71c99 100644 --- a/firmware/target/arm/as3525/kernel-as3525.c +++ b/firmware/target/arm/as3525/kernel-as3525.c | |||
@@ -44,7 +44,7 @@ static inline void do_scrollwheel(void) | |||
44 | else | 44 | else |
45 | { | 45 | { |
46 | if (!button_hold()) | 46 | if (!button_hold()) |
47 | button_read_dbop(); /* Read the scrollwheel */ | 47 | get_scrollwheel(); /* Read the scrollwheel */ |
48 | } | 48 | } |
49 | 49 | ||
50 | poll_scrollwheel ^= 1; | 50 | poll_scrollwheel ^= 1; |
diff --git a/firmware/target/arm/as3525/sansa-e200v2/button-target.h b/firmware/target/arm/as3525/sansa-e200v2/button-target.h index b1feb58cad..7a0e9e50f1 100644 --- a/firmware/target/arm/as3525/sansa-e200v2/button-target.h +++ b/firmware/target/arm/as3525/sansa-e200v2/button-target.h | |||
@@ -31,6 +31,12 @@ bool button_hold(void); | |||
31 | void button_init_device(void); | 31 | void button_init_device(void); |
32 | int button_read_device(void); | 32 | int button_read_device(void); |
33 | unsigned short button_read_dbop(void); | 33 | unsigned short button_read_dbop(void); |
34 | #define get_scrollwheel button_read_dbop | ||
35 | |||
36 | #define WHEEL_REPEAT_INTERVAL (HZ/5) | ||
37 | #define WHEEL_COUNTER_DIV 2 | ||
38 | #define ACCEL_INCREMENT 3 | ||
39 | #define ACCEL_SHIFT 1 | ||
34 | 40 | ||
35 | /* Sandisk Sansa E200 button codes */ | 41 | /* Sandisk Sansa E200 button codes */ |
36 | 42 | ||
diff --git a/firmware/target/arm/as3525/sansa-fuze/button-target.h b/firmware/target/arm/as3525/sansa-fuze/button-target.h index 6dcd37460a..2cee93723e 100644 --- a/firmware/target/arm/as3525/sansa-fuze/button-target.h +++ b/firmware/target/arm/as3525/sansa-fuze/button-target.h | |||
@@ -31,6 +31,13 @@ void button_init_device(void); | |||
31 | bool button_hold(void); | 31 | bool button_hold(void); |
32 | int button_read_device(void); | 32 | int button_read_device(void); |
33 | unsigned short button_read_dbop(void); | 33 | unsigned short button_read_dbop(void); |
34 | #define get_scrollwheel button_read_dbop | ||
35 | |||
36 | #define WHEEL_REPEAT_INTERVAL (HZ/5) | ||
37 | #define WHEEL_COUNTER_DIV 4 | ||
38 | #define ACCEL_INCREMENT 2 | ||
39 | #define ACCEL_SHIFT 2 | ||
40 | |||
34 | /* Sandisk Sansa Fuze button codes */ | 41 | /* Sandisk Sansa Fuze button codes */ |
35 | 42 | ||
36 | /* Main unit's buttons */ | 43 | /* Main unit's buttons */ |
diff --git a/firmware/target/arm/as3525/sansa-fuzev2/button-fuzev2.c b/firmware/target/arm/as3525/sansa-fuzev2/button-fuzev2.c index 0a6d2c919c..4848d9e7d9 100644 --- a/firmware/target/arm/as3525/sansa-fuzev2/button-fuzev2.c +++ b/firmware/target/arm/as3525/sansa-fuzev2/button-fuzev2.c | |||
@@ -24,21 +24,50 @@ | |||
24 | #include "button.h" | 24 | #include "button.h" |
25 | #include "backlight.h" | 25 | #include "backlight.h" |
26 | 26 | ||
27 | /* | 27 | extern void scrollwheel(unsigned wheel_value); |
28 | * TODO: Scrollwheel! | 28 | |
29 | */ | ||
30 | |||
31 | #ifdef HAS_BUTTON_HOLD | 29 | #ifdef HAS_BUTTON_HOLD |
32 | static bool hold_button = false; | 30 | static bool hold_button = false; |
33 | #endif | 31 | #endif |
34 | void button_init_device(void) | 32 | void button_init_device(void) |
33 | { /* activate the wheel */ | ||
34 | volatile int i; | ||
35 | GPIOB_DIR |= 1<<4; | ||
36 | for(i = 20; i; i--) nop; | ||
37 | GPIOB_PIN(4) = 0x10; | ||
38 | } | ||
39 | |||
40 | unsigned read_GPIOA_67(void) | ||
35 | { | 41 | { |
42 | unsigned ret = 0; | ||
43 | volatile int i; | ||
44 | DBOP_CTRL |= 1<<19; | ||
45 | for(i = 20; i; i--) nop; | ||
46 | GPIOA_DIR &= ~0xc0; | ||
47 | for(i = 20; i; i--) nop; | ||
48 | if (GPIOA_PIN(6) != 0) | ||
49 | ret = 1<<0; | ||
50 | for(i = 20; i; i--) nop; | ||
51 | if (GPIOA_PIN(7) != 0) | ||
52 | ret |= 1<<1; | ||
53 | DBOP_CTRL &= ~(1<<19); | ||
54 | for(i = 20; i; i--) nop; | ||
55 | return ret; | ||
56 | } | ||
57 | |||
58 | void get_scrollwheel(void) | ||
59 | { | ||
60 | #if defined(HAVE_SCROLLWHEEL) && !defined(BOOTLOADER) | ||
61 | /* scroll wheel handling */ | ||
62 | scrollwheel(read_GPIOA_67()); | ||
63 | #endif | ||
36 | } | 64 | } |
37 | 65 | ||
38 | /* | 66 | /* |
39 | * Get button pressed from hardware | 67 | * Get button pressed from hardware |
40 | */ | 68 | */ |
41 | 69 | ||
70 | |||
42 | int button_read_device(void) | 71 | int button_read_device(void) |
43 | { | 72 | { |
44 | int btn = 0; | 73 | int btn = 0; |
@@ -48,6 +77,7 @@ int button_read_device(void) | |||
48 | unsigned gpiod = GPIOD_DATA; | 77 | unsigned gpiod = GPIOD_DATA; |
49 | unsigned gpioa_dir = GPIOA_DIR; | 78 | unsigned gpioa_dir = GPIOA_DIR; |
50 | unsigned gpiod6; | 79 | unsigned gpiod6; |
80 | get_scrollwheel(); | ||
51 | for(delay = 500; delay; delay--) nop; | 81 | for(delay = 500; delay; delay--) nop; |
52 | CCU_IO &= ~(1<<12); | 82 | CCU_IO &= ~(1<<12); |
53 | for(delay=8;delay;delay--) nop; | 83 | for(delay=8;delay;delay--) nop; |
diff --git a/firmware/target/arm/as3525/sansa-fuzev2/button-target.h b/firmware/target/arm/as3525/sansa-fuzev2/button-target.h index 6dcd37460a..14f3db18f7 100644 --- a/firmware/target/arm/as3525/sansa-fuzev2/button-target.h +++ b/firmware/target/arm/as3525/sansa-fuzev2/button-target.h | |||
@@ -31,6 +31,12 @@ void button_init_device(void); | |||
31 | bool button_hold(void); | 31 | bool button_hold(void); |
32 | int button_read_device(void); | 32 | int button_read_device(void); |
33 | unsigned short button_read_dbop(void); | 33 | unsigned short button_read_dbop(void); |
34 | void get_scrollwheel(void); | ||
35 | |||
36 | #define WHEEL_REPEAT_INTERVAL (HZ/5) | ||
37 | #define WHEEL_COUNTER_DIV 4 | ||
38 | #define ACCEL_INCREMENT 2 | ||
39 | #define ACCEL_SHIFT 2 | ||
34 | /* Sandisk Sansa Fuze button codes */ | 40 | /* Sandisk Sansa Fuze button codes */ |
35 | 41 | ||
36 | /* Main unit's buttons */ | 42 | /* Main unit's buttons */ |
diff --git a/firmware/target/arm/as3525/scrollwheel-as3525.c b/firmware/target/arm/as3525/scrollwheel-as3525.c new file mode 100644 index 0000000000..a9e012a31f --- /dev/null +++ b/firmware/target/arm/as3525/scrollwheel-as3525.c | |||
@@ -0,0 +1,124 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2009-2010 by Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "config.h" | ||
23 | #include "button.h" | ||
24 | #include "kernel.h" | ||
25 | #include "backlight.h" | ||
26 | |||
27 | void scrollwheel(unsigned int wheel_value) | ||
28 | { | ||
29 | #ifndef BOOTLOADER | ||
30 | /* current wheel values, parsed from dbop and the resulting button */ | ||
31 | unsigned btn = BUTTON_NONE; | ||
32 | /* old wheel values */ | ||
33 | static unsigned old_wheel_value = 0; | ||
34 | static unsigned old_btn = BUTTON_NONE; | ||
35 | |||
36 | /* | ||
37 | * Getting BUTTON_REPEAT works like this: Remember when the btn value was | ||
38 | * posted to the button_queue last, and if it was recent enough, generate | ||
39 | * BUTTON_REPEAT | ||
40 | */ | ||
41 | static long last_wheel_post = 0; | ||
42 | |||
43 | /* | ||
44 | * Providing wheel acceleration works as follows: We increment accel | ||
45 | * by 2 if the wheel was turned, and decrement it by 1 each tick | ||
46 | * (no matter if it was turned), that means: the longer and faster you turn, | ||
47 | * the higher accel will be. accel>>2 will actually posted to the button_queue | ||
48 | */ | ||
49 | static int accel = 0; | ||
50 | /* We only post every 4th action, as this matches better with the physical | ||
51 | * clicks of the wheel */ | ||
52 | static int counter = 0; | ||
53 | /* Read wheel | ||
54 | * Bits 13 and 14 of DBOP_DIN change as follows (Gray Code): | ||
55 | * Clockwise rotation 00 -> 01 -> 11 -> 10 -> 00 | ||
56 | * Counter-clockwise 00 -> 10 -> 11 -> 01 -> 00 | ||
57 | * | ||
58 | * For easy look-up, actual wheel values act as indicies also, | ||
59 | * which is why the table seems to be not ordered correctly | ||
60 | */ | ||
61 | static const unsigned char wheel_tbl[2][4] = | ||
62 | { | ||
63 | { 2, 0, 3, 1 }, /* Clockwise rotation */ | ||
64 | { 1, 3, 0, 2 }, /* Counter-clockwise */ | ||
65 | }; | ||
66 | |||
67 | if(button_hold()) | ||
68 | { | ||
69 | accel = counter = 0; | ||
70 | return; | ||
71 | } | ||
72 | |||
73 | if (old_wheel_value == wheel_tbl[0][wheel_value]) | ||
74 | btn = BUTTON_SCROLL_FWD; | ||
75 | else if (old_wheel_value == wheel_tbl[1][wheel_value]) | ||
76 | btn = BUTTON_SCROLL_BACK; | ||
77 | else if (old_wheel_value != wheel_value && accel > ACCEL_INCREMENT) | ||
78 | { /* if no button is read and wheel_value changed, assume old_btn */ | ||
79 | btn = old_btn; | ||
80 | } | ||
81 | /* else btn = BUTTON_NONE */ | ||
82 | |||
83 | if (btn != BUTTON_NONE) | ||
84 | { | ||
85 | if (btn != old_btn) | ||
86 | { | ||
87 | /* direction reversals nullify acceleration and counters */ | ||
88 | old_btn = btn; | ||
89 | accel = counter = 0; | ||
90 | } | ||
91 | /* wheel_delta will cause lists to jump over items, | ||
92 | * we want this for fast scrolling, but we must keep it accurate | ||
93 | * for slow scrolling */ | ||
94 | int wheel_delta = 0; | ||
95 | /* generate BUTTON_REPEAT if quick enough, scroll slightly faster too*/ | ||
96 | if (TIME_BEFORE(current_tick, last_wheel_post + WHEEL_REPEAT_INTERVAL)) | ||
97 | { | ||
98 | btn |= BUTTON_REPEAT; | ||
99 | wheel_delta = accel>>ACCEL_SHIFT; | ||
100 | } | ||
101 | |||
102 | accel += ACCEL_INCREMENT; | ||
103 | |||
104 | /* the wheel is more reliable if we don't send every change, | ||
105 | * every WHEEL_COUNTER_DIVth is basically one "physical click" | ||
106 | * which should make up 1 item in lists */ | ||
107 | if (++counter >= WHEEL_COUNTER_DIV && queue_empty(&button_queue)) | ||
108 | { | ||
109 | buttonlight_on(); | ||
110 | backlight_on(); | ||
111 | queue_post(&button_queue, btn, ((wheel_delta+1)<<24)); | ||
112 | /* message posted - reset count and remember post */ | ||
113 | counter = 0; | ||
114 | last_wheel_post = current_tick; | ||
115 | } | ||
116 | } | ||
117 | if (accel > 0) | ||
118 | accel--; | ||
119 | |||
120 | old_wheel_value = wheel_value; | ||
121 | #else | ||
122 | (void)wheel_value | ||
123 | #endif | ||
124 | } | ||