summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-05-11 08:09:49 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-05-11 08:09:49 +0000
commitd92e09556fdec3fbd65e153c6f41c31cb1e04c42 (patch)
tree38ceff3ef5ea2664f408675533dfe7292cb9c8b5
parent198845fe91d09153c092df86e0337020eba79c87 (diff)
downloadrockbox-d92e09556fdec3fbd65e153c6f41c31cb1e04c42.tar.gz
rockbox-d92e09556fdec3fbd65e153c6f41c31cb1e04c42.zip
GPIO IRQ ready button driver for e200 series. Can't actually use them yet but their status is polled. Easy to switch over once that works. Cheapo acceleration added or else it would be too fast for selecting items. Too much scrolling might cause the PCM buffer to empty out - beware. )
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13371 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/keymaps/keymap-e200.c10
-rw-r--r--firmware/export/pp5024.h6
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/button-e200.c270
-rw-r--r--firmware/target/arm/system-pp502x.c30
4 files changed, 213 insertions, 103 deletions
diff --git a/apps/keymaps/keymap-e200.c b/apps/keymaps/keymap-e200.c
index 8e11cadb8b..c946b5feca 100644
--- a/apps/keymaps/keymap-e200.c
+++ b/apps/keymaps/keymap-e200.c
@@ -31,9 +31,9 @@
31 * Insert LAST_ITEM_IN_LIST at the end of each mapping 31 * Insert LAST_ITEM_IN_LIST at the end of each mapping
32 */ 32 */
33static const struct button_mapping button_context_standard[] = { 33static const struct button_mapping button_context_standard[] = {
34 { ACTION_STD_PREV, BUTTON_SCROLL_UP|BUTTON_REL, BUTTON_NONE }, 34 { ACTION_STD_PREV, BUTTON_SCROLL_UP, BUTTON_NONE },
35 { ACTION_STD_PREVREPEAT, BUTTON_SCROLL_UP|BUTTON_REPEAT, BUTTON_NONE }, 35 { ACTION_STD_PREVREPEAT, BUTTON_SCROLL_UP|BUTTON_REPEAT, BUTTON_NONE },
36 { ACTION_STD_NEXT, BUTTON_SCROLL_DOWN|BUTTON_REL, BUTTON_NONE }, 36 { ACTION_STD_NEXT, BUTTON_SCROLL_DOWN, BUTTON_NONE },
37 { ACTION_STD_NEXTREPEAT, BUTTON_SCROLL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, 37 { ACTION_STD_NEXTREPEAT, BUTTON_SCROLL_DOWN|BUTTON_REPEAT, BUTTON_NONE },
38 38
39 { ACTION_STD_MENU, BUTTON_POWER|BUTTON_REL, BUTTON_POWER }, 39 { ACTION_STD_MENU, BUTTON_POWER|BUTTON_REL, BUTTON_POWER },
@@ -159,9 +159,9 @@ static const struct button_mapping button_context_quickscreen[] = {
159}; /* button_context_quickscreen */ 159}; /* button_context_quickscreen */
160 160
161static const struct button_mapping button_context_settings_right_is_inc[] = { 161static const struct button_mapping button_context_settings_right_is_inc[] = {
162 { ACTION_SETTINGS_INC, BUTTON_SCROLL_DOWN|BUTTON_REL, BUTTON_NONE }, 162 { ACTION_SETTINGS_INC, BUTTON_SCROLL_DOWN, BUTTON_NONE },
163 { ACTION_SETTINGS_INCREPEAT, BUTTON_SCROLL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, 163 { ACTION_SETTINGS_INCREPEAT, BUTTON_SCROLL_DOWN|BUTTON_REPEAT, BUTTON_NONE },
164 { ACTION_SETTINGS_DEC, BUTTON_SCROLL_UP|BUTTON_REL, BUTTON_NONE }, 164 { ACTION_SETTINGS_DEC, BUTTON_SCROLL_UP, BUTTON_NONE },
165 { ACTION_SETTINGS_DECREPEAT, BUTTON_SCROLL_UP|BUTTON_REPEAT,BUTTON_NONE }, 165 { ACTION_SETTINGS_DECREPEAT, BUTTON_SCROLL_UP|BUTTON_REPEAT,BUTTON_NONE },
166 166
167 { ACTION_STD_PREV, BUTTON_UP|BUTTON_REL, BUTTON_NONE }, 167 { ACTION_STD_PREV, BUTTON_UP|BUTTON_REL, BUTTON_NONE },
diff --git a/firmware/export/pp5024.h b/firmware/export/pp5024.h
index 3ed3d5dade..b9238ae98d 100644
--- a/firmware/export/pp5024.h
+++ b/firmware/export/pp5024.h
@@ -23,4 +23,10 @@
23 completely */ 23 completely */
24#include "pp5020.h" 24#include "pp5020.h"
25 25
26#undef GPIO_IRQ
27#define GPIO_IRQ (32+6)
28
29#undef GPIO_MASK
30#define GPIO_MASK (1 << (GPIO_IRQ-32))
31
26#endif 32#endif
diff --git a/firmware/target/arm/sandisk/sansa-e200/button-e200.c b/firmware/target/arm/sandisk/sansa-e200/button-e200.c
index 028a76f7a8..168332e3c1 100644
--- a/firmware/target/arm/sandisk/sansa-e200/button-e200.c
+++ b/firmware/target/arm/sandisk/sansa-e200/button-e200.c
@@ -23,26 +23,193 @@
23#include "button.h" 23#include "button.h"
24#include "backlight.h" 24#include "backlight.h"
25 25
26static unsigned int old_wheel_value = 0; 26#define WHEEL_REPEAT_INTERVAL 30
27static unsigned int wheel_repeat = BUTTON_NONE; 27#define WHEEL_FAST_ON_INTERVAL 2
28#define WHEEL_FAST_OFF_INTERVAL 6
29
30/* Clickwheel */
31static unsigned int old_wheel_value = 0;
32static unsigned int wheel_repeat = BUTTON_NONE;
33static unsigned int wheel_click_count = 0;
34static int wheel_fast_mode = 0;
35static unsigned long last_wheel_tick = 0;
36static unsigned long last_wheel_post = 0;
37#ifndef BOOTLOADER
38static unsigned long next_backlight_on = 0;
39#endif
40/* Buttons */
41static bool hold_button = false;
42static bool hold_button_old = false;
43static int int_btn = BUTTON_NONE;
28 44
29void button_init_device(void) 45void button_init_device(void)
30{ 46{
31 /* Enable all buttons */ 47 /* Enable all buttons */
48 GPIOF_OUTPUT_EN &= ~0xff;
32 GPIOF_ENABLE |= 0xff; 49 GPIOF_ENABLE |= 0xff;
33 GPIOH_ENABLE |= 0xc0;
34 50
35 /* Scrollwheel light - enable control through GPIOG pin 7 and set timeout */ 51 /* Scrollwheel light - enable control through GPIOG pin 7 and set timeout */
36 GPIOG_ENABLE = 0x80;
37 GPIOG_OUTPUT_EN |= 0x80; 52 GPIOG_OUTPUT_EN |= 0x80;
38 53 GPIOG_ENABLE = 0x80;
54
55 GPIOH_ENABLE |= 0xc0;
56 GPIOH_OUTPUT_EN &= ~0xc0;
57
58#if 0
59 CPU_INT_PRIORITY &= ~HI_MASK;
60 CPU_HI_INT_PRIORITY &= ~GPIO_MASK;
61
62 CPU_INT_CLR = HI_MASK;
63 CPU_HI_INT_CLR = GPIO_MASK;
64#endif
65 GPIOF_INT_CLR = 0xff;
66 GPIOH_INT_CLR = 0xc0;
67
68 /* Read initial buttons */
69 old_wheel_value = GPIOF_INPUT_VAL & 0xff;
70 GPIOF_INT_LEV = (GPIOF_INT_LEV & ~0xff) | (old_wheel_value ^ 0xff);
71 hold_button = (GPIOF_INPUT_VAL & 0x80) != 0;
72
39 /* Read initial wheel value (bit 6-7 of GPIOH) */ 73 /* Read initial wheel value (bit 6-7 of GPIOH) */
40 old_wheel_value = GPIOH_INPUT_VAL & 0xc0; 74 old_wheel_value = GPIOH_INPUT_VAL & 0xc0;
75 GPIOH_INT_LEV = (GPIOH_INT_LEV & ~0xc0) | (old_wheel_value ^ 0xc0);
76
77 GPIOF_INT_EN = 0xff;
78 GPIOH_INT_EN = 0xc0;
79#if 0
80 CPU_HI_INT_EN = GPIO_MASK;
81 CPU_INT_EN = HI_MASK;
82#endif
83
84 last_wheel_tick = current_tick;
85 last_wheel_post = current_tick;
41} 86}
42 87
43bool button_hold(void) 88bool button_hold(void)
44{ 89{
45 return (GPIOF_INPUT_VAL & 0x80)?true:false; 90 return hold_button;
91}
92
93void clickwheel_int(void)
94{
95 /* Read wheel
96 * Bits 6 and 7 of GPIOH change as follows:
97 * Clockwise rotation 01 -> 00 -> 10 -> 11
98 * Counter-clockwise 11 -> 10 -> 00 -> 01
99 *
100 * This is equivalent to wheel_value of:
101 * Clockwise rotation 0x40 -> 0x00 -> 0x80 -> 0xc0
102 * Counter-clockwise 0xc0 -> 0x80 -> 0x00 -> 0x40
103 */
104 static const unsigned char wheel_tbl[2][4] =
105 {
106 /* 0x00 0x40 0x80 0xc0 */ /* Wheel value */
107 { 0x40, 0xc0, 0x00, 0x80 }, /* Clockwise rotation */
108 { 0x80, 0x00, 0xc0, 0x40 }, /* Counter-clockwise */
109 };
110
111 unsigned int wheel_value;
112
113 GPIOH_INT_CLR = GPIOH_INT_STAT & 0xc0;
114
115 wheel_value = GPIOH_INPUT_VAL & 0xc0;
116 GPIOH_INT_LEV = (GPIOH_INT_LEV & ~0xc0) | (wheel_value ^ 0xc0);
117
118 if (!hold_button)
119 {
120 unsigned int btn = BUTTON_NONE;
121
122 if (old_wheel_value == wheel_tbl[0][wheel_value >> 6])
123 btn = BUTTON_SCROLL_DOWN;
124 else if (old_wheel_value == wheel_tbl[1][wheel_value >> 6])
125 btn = BUTTON_SCROLL_UP;
126
127 if (btn != BUTTON_NONE)
128 {
129 int repeat = 1;
130
131 if (btn != wheel_repeat)
132 {
133 wheel_repeat = btn;
134 repeat =
135 wheel_fast_mode =
136 wheel_click_count = 0;
137 }
138
139 if (wheel_fast_mode)
140 {
141 if (TIME_AFTER(current_tick,
142 last_wheel_tick + WHEEL_FAST_OFF_INTERVAL))
143 {
144 if (++wheel_click_count < 2)
145 btn = BUTTON_NONE;
146 wheel_fast_mode = 0;
147 }
148 }
149 else
150 {
151 if (repeat && TIME_BEFORE(current_tick,
152 last_wheel_tick + WHEEL_FAST_ON_INTERVAL))
153 wheel_fast_mode = 1;
154 else if (++wheel_click_count < 2)
155 btn = BUTTON_NONE;
156 }
157
158#ifndef BOOTLOADER
159 if (TIME_AFTER(current_tick, next_backlight_on))
160 {
161 next_backlight_on = current_tick + HZ/4;
162 backlight_on();
163 button_backlight_on();
164 }
165#endif
166 if (btn != BUTTON_NONE)
167 {
168 wheel_click_count = 0;
169
170 if (repeat && TIME_BEFORE(current_tick,
171 last_wheel_post + WHEEL_REPEAT_INTERVAL))
172 btn |= BUTTON_REPEAT;
173
174 last_wheel_post = current_tick;
175
176 if (queue_empty(&button_queue))
177 queue_post(&button_queue, btn, 0);
178 }
179
180 last_wheel_tick = current_tick;
181 }
182 }
183
184 old_wheel_value = wheel_value;
185}
186
187void button_int(void)
188{
189 unsigned char state;
190
191 GPIOF_INT_CLR = GPIOF_INT_STAT;
192
193 state = GPIOF_INPUT_VAL & 0xff;
194
195 GPIOF_INT_LEV = (GPIOF_INT_LEV & ~0xff) | (state ^ 0xff);
196
197 int_btn = BUTTON_NONE;
198
199 hold_button = (state & 0x80) != 0;
200
201 /* device buttons */
202 if (!hold_button)
203 {
204 /* Read normal buttons */
205 if ((state & 0x01) == 0) int_btn |= BUTTON_REC;
206 if ((state & 0x02) == 0) int_btn |= BUTTON_DOWN;
207 if ((state & 0x04) == 0) int_btn |= BUTTON_RIGHT;
208 if ((state & 0x08) == 0) int_btn |= BUTTON_LEFT;
209 if ((state & 0x10) == 0) int_btn |= BUTTON_SELECT; /* The centre button */
210 if ((state & 0x20) == 0) int_btn |= BUTTON_UP; /* The "play" button */
211 if ((state & 0x40) != 0) int_btn |= BUTTON_POWER;
212 }
46} 213}
47 214
48/* 215/*
@@ -50,101 +217,16 @@ bool button_hold(void)
50 */ 217 */
51int button_read_device(void) 218int button_read_device(void)
52{ 219{
53 int btn = BUTTON_NONE;
54 unsigned char state;
55 static bool hold_button = false;
56 bool hold_button_old;
57 unsigned int new_wheel_value = 0; /* read later, but this stops a warning */
58
59 /* Hold */ 220 /* Hold */
60 hold_button_old = hold_button;
61 hold_button = button_hold();
62
63#ifndef BOOTLOADER 221#ifndef BOOTLOADER
64 /* light handling */ 222 /* light handling */
65 if (hold_button != hold_button_old) 223 if (hold_button != hold_button_old)
66 { 224 {
225 hold_button_old = hold_button;
67 backlight_hold_changed(hold_button); 226 backlight_hold_changed(hold_button);
68 } 227 }
69#endif 228#endif
70 229
71 /* device buttons */ 230 /* The int_btn variable is set in the button interrupt handler */
72 if (!hold_button) 231 return int_btn;
73 {
74 /* Read normal buttons */
75 state = GPIOF_INPUT_VAL & 0xff;
76 if ((state & 0x1) == 0) btn |= BUTTON_REC;
77 if ((state & 0x2) == 0) btn |= BUTTON_DOWN;
78 if ((state & 0x4) == 0) btn |= BUTTON_RIGHT;
79 if ((state & 0x8) == 0) btn |= BUTTON_LEFT;
80 if ((state & 0x10) == 0) btn |= BUTTON_SELECT; /* The centre button */
81 if ((state & 0x20) == 0) btn |= BUTTON_UP; /* The "play" button */
82 if ((state & 0x40) != 0) btn |= BUTTON_POWER;
83
84 /* Read wheel
85 * Bits 6 and 7 of GPIOH change as follows:
86 * Clockwise rotation 01 -> 00 -> 10 -> 11
87 * Counter-clockwise 11 -> 10 -> 00 -> 01
88 *
89 * This is equivalent to wheel_value of:
90 * Clockwise rotation 0x40 -> 0x00 -> 0x80 -> 0xc0
91 * Counter-clockwise 0xc0 -> 0x80 -> 0x00 -> 0x40
92 */
93 new_wheel_value = GPIOH_INPUT_VAL & 0xc0;
94 switch(new_wheel_value){
95 case 0x00:
96 if(old_wheel_value==0x80)
97 btn |= BUTTON_SCROLL_UP;
98 else if (old_wheel_value==0x40)
99 btn |= BUTTON_SCROLL_DOWN;
100 break;
101 case 0x40:
102 if(old_wheel_value==0x00)
103 btn |= BUTTON_SCROLL_UP;
104 else if (old_wheel_value==0xc0)
105 btn |= BUTTON_SCROLL_DOWN;
106 break;
107 case 0x80:
108 if(old_wheel_value==0xc0)
109 btn |= BUTTON_SCROLL_UP;
110 else if (old_wheel_value==0x00)
111 btn |= BUTTON_SCROLL_DOWN;
112 break;
113 case 0xc0:
114 if(old_wheel_value==0x40)
115 btn |= BUTTON_SCROLL_UP;
116 else if (old_wheel_value==0x80)
117 btn |= BUTTON_SCROLL_DOWN;
118 break;
119 }
120
121 if(wheel_repeat == BUTTON_NONE){
122 if(btn & BUTTON_SCROLL_UP)
123 wheel_repeat = BUTTON_SCROLL_UP;
124
125 if(btn & BUTTON_SCROLL_DOWN)
126 wheel_repeat = BUTTON_SCROLL_DOWN;
127 } else if (wheel_repeat == BUTTON_SCROLL_UP) {
128 btn |= BUTTON_SCROLL_UP;
129 wheel_repeat = BUTTON_NONE;
130 } else if (wheel_repeat == BUTTON_SCROLL_DOWN) {
131 btn |= BUTTON_SCROLL_DOWN;
132 wheel_repeat = BUTTON_NONE;
133 }
134
135 old_wheel_value = new_wheel_value;
136 }
137
138 if( (btn & BUTTON_SCROLL_UP) || (btn & BUTTON_SCROLL_DOWN) ){
139 /* only trigger once per click */
140 if ((new_wheel_value == 0x00) || (new_wheel_value == 0xc0))
141 {
142 btn = btn&(~(BUTTON_SCROLL_UP|BUTTON_SCROLL_DOWN));
143 }
144#ifndef BOOTLOADER
145 button_backlight_on();
146#endif
147 }
148
149 return btn;
150} 232}
diff --git a/firmware/target/arm/system-pp502x.c b/firmware/target/arm/system-pp502x.c
index 1f1cdf47b6..72e3a9b361 100644
--- a/firmware/target/arm/system-pp502x.c
+++ b/firmware/target/arm/system-pp502x.c
@@ -56,12 +56,21 @@ void irq(void)
56/* TODO: this should really be in the target tree, but moving it there caused 56/* TODO: this should really be in the target tree, but moving it there caused
57 crt0.S not to find it while linking */ 57 crt0.S not to find it while linking */
58/* TODO: Even if it isn't in the target tree, this should be the default case */ 58/* TODO: Even if it isn't in the target tree, this should be the default case */
59extern void button_int(void);
60extern void clickwheel_int(void);
61
59void irq(void) 62void irq(void)
60{ 63{
61 if(CURRENT_CORE == CPU) 64 if(CURRENT_CORE == CPU) {
62 { 65 if (CPU_INT_STAT & TIMER1_MASK) {
63 if (CPU_INT_STAT & TIMER1_MASK) 66#ifdef SANSA_E200
67 if (GPIOF_INT_STAT & 0xff)
68 button_int();
69 if (GPIOH_INT_STAT & 0xc0)
70 clickwheel_int();
71#endif
64 TIMER1(); 72 TIMER1();
73 }
65 else if (CPU_INT_STAT & TIMER2_MASK) 74 else if (CPU_INT_STAT & TIMER2_MASK)
66 TIMER2(); 75 TIMER2();
67 } else { 76 } else {
@@ -222,7 +231,20 @@ void system_init(void)
222 COP_INT_CLR = -1; 231 COP_INT_CLR = -1;
223 CPU_INT_CLR = -1; 232 CPU_INT_CLR = -1;
224 INT_FORCED_CLR = -1; 233 INT_FORCED_CLR = -1;
225 234
235 GPIOA_INT_EN = 0;
236 GPIOB_INT_EN = 0;
237 GPIOC_INT_EN = 0;
238 GPIOD_INT_EN = 0;
239 GPIOE_INT_EN = 0;
240 GPIOF_INT_EN = 0;
241 GPIOG_INT_EN = 0;
242 GPIOH_INT_EN = 0;
243 GPIOI_INT_EN = 0;
244 GPIOJ_INT_EN = 0;
245 GPIOK_INT_EN = 0;
246 GPIOL_INT_EN = 0;
247
226# if NUM_CORES > 1 && defined(HAVE_ADJUSTABLE_CPU_FREQ) 248# if NUM_CORES > 1 && defined(HAVE_ADJUSTABLE_CPU_FREQ)
227 spinlock_init(&boostctrl_mtx); 249 spinlock_init(&boostctrl_mtx);
228# endif 250# endif