iPod: Remove/reduce the udelay()s in the button driver. They were in the IPL source...
[Rockbox.git] / firmware / drivers / button.c
blob79378cda488ed907c9191e55df4845a3ab41a56c
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Daniel Stenberg
12 * iPod driver based on code from the ipodlinux project - http://ipodlinux.org
13 * Adapted for Rockbox in December 2005
14 * Original file: linux/arch/armnommu/mach-ipod/keyboard.c
15 * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org)
18 * All files in this archive are subject to the GNU General Public License.
19 * See the file COPYING in the source tree root for full license agreement.
21 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
22 * KIND, either express or implied.
24 ****************************************************************************/
27 * Rockbox button functions
30 #include <stdlib.h>
31 #include "config.h"
32 #include "cpu.h"
33 #include "system.h"
34 #include "button.h"
35 #include "kernel.h"
36 #include "backlight.h"
37 #include "adc.h"
38 #include "serial.h"
39 #include "power.h"
40 #include "system.h"
41 #include "powermgmt.h"
43 struct event_queue button_queue;
45 static long lastbtn; /* Last valid button status */
46 static long last_read; /* Last button status, for debouncing/filtering */
47 #ifdef HAVE_LCD_BITMAP
48 static bool flipped; /* buttons can be flipped to match the LCD flip */
49 #endif
51 /* how often we check to see if a button is pressed */
52 #define POLL_FREQUENCY HZ/100
54 /* how long until repeat kicks in */
55 #define REPEAT_START 30
57 /* the speed repeat starts at */
58 #define REPEAT_INTERVAL_START 16
60 /* speed repeat finishes at */
61 #define REPEAT_INTERVAL_FINISH 5
63 /* the power-off button and number of repeated keys before shutting off */
64 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IRIVER_IFP7XX_PAD)
65 #define POWEROFF_BUTTON BUTTON_PLAY
66 #define POWEROFF_COUNT 40
67 #else
68 #define POWEROFF_BUTTON BUTTON_OFF
69 #define POWEROFF_COUNT 10
70 #endif
72 static int button_read(void);
74 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
75 static bool remote_button_hold_only(void);
76 #endif
78 #if CONFIG_KEYPAD == IPOD_4G_PAD
79 /* Variable to use for setting button status in interrupt handler */
80 int int_btn = BUTTON_NONE;
82 static void opto_i2c_init(void)
84 int i, curr_value;
86 /* wait for value to settle */
87 i = 1000;
88 curr_value = (inl(0x7000c104) << 16) >> 24;
89 while (i > 0)
91 int new_value = (inl(0x7000c104) << 16) >> 24;
93 if (new_value != curr_value) {
94 i = 10000;
95 curr_value = new_value;
97 else {
98 i--;
102 GPIOB_OUTPUT_VAL |= 0x10;
103 DEV_EN |= 0x10000;
104 DEV_RS |= 0x10000;
105 udelay(5);
106 DEV_RS &= ~0x10000; /* finish reset */
108 outl(0xffffffff, 0x7000c120);
109 outl(0xffffffff, 0x7000c124);
110 outl(0xc00a1f00, 0x7000c100);
111 outl(0x1000000, 0x7000c104);
114 static int ipod_4g_button_read(void)
116 unsigned reg, status;
117 static int clickwheel_down = 0;
118 static int old_wheel_value = -1;
119 int wheel_keycode = BUTTON_NONE;
120 int wheel_delta, wheel_delta_abs;
121 int new_wheel_value;
122 int btn = BUTTON_NONE;
124 /* The ipodlinux source had a udelay(250) here, but testing has shown that
125 it is not needed - tested on Nano, Color/Photo and Video. */
126 /* udelay(250);*/
128 reg = 0x7000c104;
129 if ((inl(0x7000c104) & 0x4000000) != 0) {
130 reg = reg + 0x3C; /* 0x7000c140 */
132 status = inl(0x7000c140);
133 outl(0x0, 0x7000c140); /* clear interrupt status? */
135 if ((status & 0x800000ff) == 0x8000001a) {
136 /* NB: highest wheel = 0x5F, clockwise increases */
137 new_wheel_value = ((status << 9) >> 25) & 0xff;
139 if (status & 0x100)
140 btn |= BUTTON_SELECT;
141 if (status & 0x200)
142 btn |= BUTTON_RIGHT;
143 if (status & 0x400)
144 btn |= BUTTON_LEFT;
145 if (status & 0x800)
146 btn |= BUTTON_PLAY;
147 if (status & 0x1000)
148 btn |= BUTTON_MENU;
149 if (status & 0x40000000) {
150 /* scroll wheel down */
151 clickwheel_down = 1;
152 backlight_on();
153 if (old_wheel_value != -1) {
154 wheel_delta = new_wheel_value - old_wheel_value;
155 wheel_delta_abs = wheel_delta < 0 ? -wheel_delta
156 : wheel_delta;
158 if (wheel_delta_abs > 48) {
159 if (old_wheel_value > new_wheel_value)
160 /* wrapped around the top going clockwise */
161 wheel_delta += 96;
162 else if (old_wheel_value < new_wheel_value)
163 /* wrapped around the top going counterclockwise */ wheel_delta -= 96;
165 /* TODO: these thresholds should most definitely be
166 settings, and we're probably going to want a more
167 advanced scheme than this anyway. */
168 if (wheel_delta > 4) {
169 wheel_keycode = BUTTON_SCROLL_FWD;
170 old_wheel_value = new_wheel_value;
171 } else if (wheel_delta < -4) {
172 wheel_keycode = BUTTON_SCROLL_BACK;
173 old_wheel_value = new_wheel_value;
176 if (wheel_keycode != BUTTON_NONE)
177 queue_post(&button_queue, wheel_keycode, NULL);
179 else {
180 old_wheel_value = new_wheel_value;
183 else if (clickwheel_down) {
184 /* scroll wheel up */
185 old_wheel_value = -1;
186 clickwheel_down = 0;
190 Don't know why this should be needed, let me know if you do.
191 else if ((status & 0x800000FF) == 0x8000003A) {
192 wheel_value = status & 0x800000FF;
195 else if (status == 0xffffffff) {
196 opto_i2c_init();
200 if ((inl(reg) & 0x8000000) != 0) {
201 outl(0xffffffff, 0x7000c120);
202 outl(0xffffffff, 0x7000c124);
204 return btn;
207 void ipod_4g_button_int(void)
209 CPU_HI_INT_CLR = I2C_MASK;
210 /* The following delay was 250 in the ipodlinux source, but 10 seems to
211 work fine - tested on Nano, Color/Photo and Video. */
212 udelay(10);
213 outl(0x0, 0x7000c140);
214 int_btn = ipod_4g_button_read();
215 outl(inl(0x7000c104) | 0xC000000, 0x7000c104);
216 outl(0x400a1f00, 0x7000c100);
218 GPIOB_OUTPUT_VAL |= 0x10;
219 CPU_INT_EN = 0x40000000;
220 CPU_HI_INT_EN = I2C_MASK;
222 #endif
224 static void button_tick(void)
226 static int tick = 0;
227 static int count = 0;
228 static int repeat_speed = REPEAT_INTERVAL_START;
229 static int repeat_count = 0;
230 static bool repeat = false;
231 int diff;
232 int btn;
234 #if (CONFIG_KEYPAD == PLAYER_PAD) || (CONFIG_KEYPAD == RECORDER_PAD)
236 /* Post events for the remote control */
237 btn = remote_control_rx();
238 if(btn)
240 queue_post(&button_queue, btn, NULL);
242 #endif
244 /* only poll every X ticks */
245 if ( ++tick >= POLL_FREQUENCY )
247 bool post = false;
248 btn = button_read();
250 /* Find out if a key has been released */
251 diff = btn ^ lastbtn;
252 if(diff && (btn & diff) == 0)
254 queue_post(&button_queue, BUTTON_REL | diff, NULL);
256 else
258 if ( btn )
260 /* normal keypress */
261 if ( btn != lastbtn )
263 post = true;
264 repeat = false;
265 repeat_speed = REPEAT_INTERVAL_START;
268 else /* repeat? */
270 if ( repeat )
272 count--;
273 if (count == 0) {
274 post = true;
275 /* yes we have repeat */
276 repeat_speed--;
277 if (repeat_speed < REPEAT_INTERVAL_FINISH)
278 repeat_speed = REPEAT_INTERVAL_FINISH;
279 count = repeat_speed;
281 repeat_count++;
283 /* Send a SYS_POWEROFF event if we have a device
284 which doesn't shut down easily with the OFF
285 key */
286 #ifdef HAVE_SW_POWEROFF
287 #ifdef BUTTON_RC_STOP
288 if ((btn == POWEROFF_BUTTON || btn == BUTTON_RC_STOP) &&
289 #else
290 if (btn == POWEROFF_BUTTON &&
291 #endif
292 #if defined(HAVE_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING)
293 !charger_inserted() &&
294 #endif
295 repeat_count > POWEROFF_COUNT)
297 /* Tell the main thread that it's time to
298 power off */
299 sys_poweroff();
301 /* Safety net for players without hardware
302 poweroff */
303 if(repeat_count > POWEROFF_COUNT * 10)
304 power_off();
306 #endif
309 else
311 if (count++ > REPEAT_START)
313 post = true;
314 repeat = true;
315 repeat_count = 0;
316 /* initial repeat */
317 count = REPEAT_INTERVAL_START;
321 if ( post )
323 if (repeat)
324 queue_post(&button_queue, BUTTON_REPEAT | btn, NULL);
325 else
326 queue_post(&button_queue, btn, NULL);
327 #ifdef HAVE_REMOTE_LCD
328 if(btn & BUTTON_REMOTE)
329 remote_backlight_on();
330 else
331 #endif
332 backlight_on();
334 reset_poweroff_timer();
337 else
339 repeat = false;
340 count = 0;
343 lastbtn = btn & ~(BUTTON_REL | BUTTON_REPEAT);
344 tick = 0;
348 long button_get(bool block)
350 struct event ev;
352 if ( block || !queue_empty(&button_queue) )
354 queue_wait(&button_queue, &ev);
355 return ev.id;
357 return BUTTON_NONE;
360 long button_get_w_tmo(int ticks)
362 struct event ev;
363 queue_wait_w_tmo(&button_queue, &ev, ticks);
364 return (ev.id != SYS_TIMEOUT)? ev.id: BUTTON_NONE;
367 void button_init(void)
369 /* hardware inits */
370 #if CONFIG_KEYPAD == IRIVER_H100_PAD
371 /* Set GPIO33, GPIO37, GPIO38 and GPIO52 as general purpose inputs */
372 GPIO1_FUNCTION |= 0x00100062;
373 GPIO1_ENABLE &= ~0x00100060;
374 #elif CONFIG_KEYPAD == IRIVER_H300_PAD
375 /* Set GPIO9 and GPIO15 as general purpose inputs */
376 GPIO_ENABLE &= ~0x00008200;
377 GPIO_FUNCTION |= 0x00008200;
378 /* Set GPIO33, GPIO37, GPIO38 and GPIO52 as general purpose inputs */
379 GPIO1_ENABLE &= ~0x00100060;
380 GPIO1_FUNCTION |= 0x00100062;
381 #elif CONFIG_KEYPAD == RECORDER_PAD
382 /* Set PB4 and PB8 as input pins */
383 PBCR1 &= 0xfffc; /* PB8MD = 00 */
384 PBCR2 &= 0xfcff; /* PB4MD = 00 */
385 PBIOR &= ~0x0110; /* Inputs */
386 #elif CONFIG_KEYPAD == PLAYER_PAD
387 /* set PA5 and PA11 as input pins */
388 PACR1 &= 0xff3f; /* PA11MD = 00 */
389 PACR2 &= 0xfbff; /* PA5MD = 0 */
390 PAIOR &= ~0x0820; /* Inputs */
391 #elif CONFIG_KEYPAD == ONDIO_PAD
392 /* nothing to initialize here */
393 #elif CONFIG_KEYPAD == GMINI100_PAD
394 /* nothing to initialize here */
395 #elif CONFIG_KEYPAD == IPOD_4G_PAD
396 opto_i2c_init();
397 /* hold button - enable as input */
398 GPIOA_ENABLE |= 0x20;
399 GPIOA_OUTPUT_EN &= ~0x20;
400 /* hold button - set interrupt levels */
401 GPIOA_INT_LEV = ~(GPIOA_INPUT_VAL & 0x20);
402 GPIOA_INT_CLR = GPIOA_INT_STAT & 0x20;
403 /* enable interrupts */
404 GPIOA_INT_EN = 0x20;
405 CPU_INT_EN = 0x40000000;
406 CPU_HI_INT_EN = I2C_MASK;
407 #endif /* CONFIG_KEYPAD */
409 queue_init(&button_queue);
410 button_read();
411 lastbtn = button_read();
412 tick_add_task(button_tick);
413 reset_poweroff_timer();
415 #ifdef HAVE_LCD_BITMAP
416 flipped = false;
417 #endif
420 #ifdef HAVE_LCD_BITMAP /* only bitmap displays can be flipped */
421 #if (CONFIG_KEYPAD != IPOD_4G_PAD)
423 * helper function to swap UP/DOWN, LEFT/RIGHT (and F1/F3 for Recorder)
425 static int button_flip(int button)
427 int newbutton;
429 newbutton = button &
430 ~(BUTTON_UP | BUTTON_DOWN
431 | BUTTON_LEFT | BUTTON_RIGHT
432 #if CONFIG_KEYPAD == RECORDER_PAD
433 | BUTTON_F1 | BUTTON_F3
434 #endif
437 if (button & BUTTON_UP)
438 newbutton |= BUTTON_DOWN;
439 if (button & BUTTON_DOWN)
440 newbutton |= BUTTON_UP;
441 if (button & BUTTON_LEFT)
442 newbutton |= BUTTON_RIGHT;
443 if (button & BUTTON_RIGHT)
444 newbutton |= BUTTON_LEFT;
445 #if CONFIG_KEYPAD == RECORDER_PAD
446 if (button & BUTTON_F1)
447 newbutton |= BUTTON_F3;
448 if (button & BUTTON_F3)
449 newbutton |= BUTTON_F1;
450 #endif
452 return newbutton;
454 #else
455 /* We don't flip the iPod's keypad yet*/
456 #define button_flip(x) (x)
457 #endif
460 * set the flip attribute
461 * better only call this when the queue is empty
463 void button_set_flip(bool flip)
465 if (flip != flipped) /* not the current setting */
467 /* avoid race condition with the button_tick() */
468 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
469 lastbtn = button_flip(lastbtn);
470 flipped = flip;
471 set_irq_level(oldlevel);
474 #endif /* HAVE_LCD_BITMAP */
477 Archos hardware button hookup
478 =============================
480 Recorder / Recorder FM/V2
481 -------------------------
482 F1, F2, F3, UP: connected to AN4 through a resistor network
483 DOWN, PLAY, LEFT, RIGHT: likewise connected to AN5
485 The voltage on AN4/ AN5 depends on which keys (or key combo) is pressed
486 FM/V2 has PLAY and RIGHT switched compared to plain recorder
488 ON: PB8, low active (plain recorder) / AN3, low active (fm/v2)
489 OFF: PB4, low active (plain recorder) / AN2, high active (fm/v2)
491 Player
492 ------
493 LEFT: AN0
494 MENU: AN1
495 RIGHT: AN2
496 PLAY: AN3
498 STOP: PA11
499 ON: PA5
501 All buttons are low active
503 Ondio
504 -----
505 LEFT, RIGHT, UP, DOWN: connected to AN4 through a resistor network
507 The voltage on AN4 depends on which keys (or key combo) is pressed
509 OPTION: AN2, high active (assigned as MENU)
510 ON/OFF: AN3, low active (assigned as OFF)
514 #if CONFIG_KEYPAD == RECORDER_PAD
516 #ifdef HAVE_FMADC
517 /* FM Recorder super-special levels */
518 #define LEVEL1 150
519 #define LEVEL2 385
520 #define LEVEL3 545
521 #define LEVEL4 700
522 #define ROW2_BUTTON1 BUTTON_PLAY
523 #define ROW2_BUTTON3 BUTTON_RIGHT
525 #else
526 /* plain bog standard Recorder levels */
527 #define LEVEL1 250
528 #define LEVEL2 500
529 #define LEVEL3 700
530 #define LEVEL4 900
531 #define ROW2_BUTTON1 BUTTON_RIGHT
532 #define ROW2_BUTTON3 BUTTON_PLAY
533 #endif /* HAVE_FMADC */
535 #elif CONFIG_KEYPAD == ONDIO_PAD
536 /* Ondio levels */
537 #define LEVEL1 165
538 #define LEVEL2 415
539 #define LEVEL3 585
540 #define LEVEL4 755
542 #endif /* CONFIG_KEYPAD */
545 * Get button pressed from hardware
547 static int button_read(void)
549 int btn = BUTTON_NONE;
550 int retval;
552 int data;
554 #if CONFIG_KEYPAD == IRIVER_H100_PAD
556 static bool hold_button = false;
557 static bool remote_hold_button = false;
559 /* light handling */
560 if (hold_button && !button_hold())
562 backlight_on();
564 if (remote_hold_button && !remote_button_hold_only())
566 remote_backlight_on();
569 hold_button = button_hold();
570 remote_hold_button = remote_button_hold_only();
572 /* normal buttons */
573 if (!hold_button)
575 data = adc_scan(ADC_BUTTONS);
577 if (data < 0x80)
578 if (data < 0x30)
579 if (data < 0x18)
580 btn = BUTTON_SELECT;
581 else
582 btn = BUTTON_UP;
583 else
584 if (data < 0x50)
585 btn = BUTTON_LEFT;
586 else
587 btn = BUTTON_DOWN;
588 else
589 if (data < 0xb0)
590 if (data < 0xa0)
591 btn = BUTTON_RIGHT;
592 else
593 btn = BUTTON_OFF;
594 else
595 if (data < 0xd0)
596 btn = BUTTON_MODE;
597 else
598 if (data < 0xf0)
599 btn = BUTTON_REC;
602 /* remote buttons */
603 if (!remote_hold_button)
605 data = adc_scan(ADC_REMOTE);
607 if (data < 0x74)
608 if (data < 0x40)
609 if (data < 0x20)
610 if(data < 0x10)
611 btn = BUTTON_RC_STOP;
612 else
613 btn = BUTTON_RC_VOL_DOWN;
614 else
615 btn = BUTTON_RC_MODE;
616 else
617 if (data < 0x58)
618 btn = BUTTON_RC_VOL_UP;
619 else
620 btn = BUTTON_RC_BITRATE;
621 else
622 if (data < 0xb0)
623 if (data < 0x88)
624 btn = BUTTON_RC_REC;
625 else
626 btn = BUTTON_RC_SOURCE;
627 else
628 if (data < 0xd8)
629 if(data < 0xc0)
630 btn = BUTTON_RC_FF;
631 else
632 btn = BUTTON_RC_MENU;
633 else
634 if (data < 0xf0)
635 btn = BUTTON_RC_REW;
638 /* special buttons */
639 data = GPIO1_READ;
640 if (!hold_button && ((data & 0x20) == 0))
641 btn |= BUTTON_ON;
642 if (!remote_hold_button && ((data & 0x40) == 0))
643 btn |= BUTTON_RC_ON;
645 #elif CONFIG_KEYPAD == IRIVER_H300_PAD
647 static bool hold_button = false;
648 static bool remote_hold_button = false;
650 /* light handling */
651 if (hold_button && !button_hold())
653 backlight_on();
655 if (remote_hold_button && !remote_button_hold_only())
657 remote_backlight_on();
660 hold_button = button_hold();
661 remote_hold_button = remote_button_hold_only();
663 /* normal buttons */
664 if (!hold_button)
666 data = adc_scan(ADC_BUTTONS);
668 if (data < 0x50)
669 if (data < 0x30)
670 if (data < 0x10)
671 btn = BUTTON_SELECT;
672 else
673 btn = BUTTON_UP;
674 else
675 btn = BUTTON_LEFT;
676 else
677 if (data < 0x90)
678 if (data < 0x70)
679 btn = BUTTON_DOWN;
680 else
681 btn = BUTTON_RIGHT;
682 else
683 if(data < 0xc0)
684 btn = BUTTON_OFF;
687 /* remote buttons */
688 if (!remote_hold_button)
690 data = adc_scan(ADC_REMOTE);
692 if (data < 0x74)
693 if (data < 0x40)
694 if (data < 0x20)
695 if(data < 0x10)
696 btn = BUTTON_RC_STOP;
697 else
698 btn = BUTTON_RC_VOL_DOWN;
699 else
700 btn = BUTTON_RC_MODE;
701 else
702 if (data < 0x58)
703 btn = BUTTON_RC_VOL_UP;
704 else
705 btn = BUTTON_RC_BITRATE;
706 else
707 if (data < 0xb0)
708 if (data < 0x88)
709 btn = BUTTON_RC_REC;
710 else
711 btn = BUTTON_RC_SOURCE;
712 else
713 if (data < 0xd8)
714 if(data < 0xc0)
715 btn = BUTTON_RC_FF;
716 else
717 btn = BUTTON_RC_MENU;
718 else
719 if (data < 0xf0)
720 btn = BUTTON_RC_REW;
723 /* special buttons */
724 if (!hold_button)
726 data = GPIO_READ;
727 if ((data & 0x0200) == 0)
728 btn |= BUTTON_MODE;
729 if ((data & 0x8000) == 0)
730 btn |= BUTTON_REC;
733 data = GPIO1_READ;
734 if (!hold_button && ((data & 0x20) == 0))
735 btn |= BUTTON_ON;
736 if (!remote_hold_button && ((data & 0x40) == 0))
737 btn |= BUTTON_RC_ON;
739 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
741 static bool hold_button = false;
743 /* light handling */
744 if (hold_button && !button_hold())
746 backlight_on();
748 hold_button = button_hold();
750 /* normal buttons */
751 if (!button_hold())
753 data = adc_read(ADC_BUTTONS);
755 if (data < 0x151)
756 if (data < 0xc7)
757 if (data < 0x41)
758 btn = BUTTON_LEFT;
759 else
760 btn = BUTTON_RIGHT;
761 else
762 btn = BUTTON_SELECT;
763 else
764 if (data < 0x268)
765 if (data < 0x1d7)
766 btn = BUTTON_UP;
767 else
768 btn = BUTTON_DOWN;
769 else
770 if (data < 0x2f9)
771 btn = BUTTON_EQ;
772 else
773 if (data < 0x35c)
774 btn = BUTTON_MODE;
777 if (!button_hold() && (adc_read(ADC_BUTTON_PLAY) < 0x64))
778 btn |= BUTTON_PLAY;
780 #elif CONFIG_KEYPAD == RECORDER_PAD
782 #ifdef HAVE_FMADC
783 if ( adc_read(ADC_BUTTON_ON) < 512 )
784 btn |= BUTTON_ON;
785 if ( adc_read(ADC_BUTTON_OFF) > 512 )
786 btn |= BUTTON_OFF;
787 #else
788 /* check port B pins for ON and OFF */
789 data = PBDR;
790 if ((data & 0x0100) == 0)
791 btn |= BUTTON_ON;
792 if ((data & 0x0010) == 0)
793 btn |= BUTTON_OFF;
794 #endif
796 /* check F1..F3 and UP */
797 data = adc_read(ADC_BUTTON_ROW1);
799 if (data >= LEVEL4)
800 btn |= BUTTON_F3;
801 else if (data >= LEVEL3)
802 btn |= BUTTON_UP;
803 else if (data >= LEVEL2)
804 btn |= BUTTON_F2;
805 else if (data >= LEVEL1)
806 btn |= BUTTON_F1;
808 /* Some units have mushy keypads, so pressing UP also activates
809 the Left/Right buttons. Let's combat that by skipping the AN5
810 checks when UP is pressed. */
811 if(!(btn & BUTTON_UP))
813 /* check DOWN, PLAY, LEFT, RIGHT */
814 data = adc_read(ADC_BUTTON_ROW2);
816 if (data >= LEVEL4)
817 btn |= BUTTON_DOWN;
818 else if (data >= LEVEL3)
819 btn |= ROW2_BUTTON3;
820 else if (data >= LEVEL2)
821 btn |= BUTTON_LEFT;
822 else if (data >= LEVEL1)
823 btn |= ROW2_BUTTON1;
826 #elif CONFIG_KEYPAD == PLAYER_PAD
828 /* buttons are active low */
829 if (adc_read(0) < 0x180)
830 btn |= BUTTON_LEFT;
831 if (adc_read(1) < 0x180)
832 btn |= BUTTON_MENU;
833 if(adc_read(2) < 0x180)
834 btn |= BUTTON_RIGHT;
835 if(adc_read(3) < 0x180)
836 btn |= BUTTON_PLAY;
838 /* check port A pins for ON and STOP */
839 data = PADR;
840 if ( !(data & 0x0020) )
841 btn |= BUTTON_ON;
842 if ( !(data & 0x0800) )
843 btn |= BUTTON_STOP;
845 #elif CONFIG_KEYPAD == ONDIO_PAD
847 if(adc_read(ADC_BUTTON_OPTION) > 0x200) /* active high */
848 btn |= BUTTON_MENU;
849 if(adc_read(ADC_BUTTON_ONOFF) < 0x120) /* active low */
850 btn |= BUTTON_OFF;
852 /* Check the 4 direction keys */
853 data = adc_read(ADC_BUTTON_ROW1);
855 if (data >= LEVEL4)
856 btn |= BUTTON_LEFT;
857 else if (data >= LEVEL3)
858 btn |= BUTTON_RIGHT;
859 else if (data >= LEVEL2)
860 btn |= BUTTON_UP;
861 else if (data >= LEVEL1)
862 btn |= BUTTON_DOWN;
864 #elif CONFIG_KEYPAD == GMINI100_PAD
866 if (adc_read(7) < 0xE3)
867 btn |= BUTTON_LEFT;
868 else if (adc_read(7) < 0x1c5)
869 btn |= BUTTON_DOWN;
870 else if (adc_read(7) < 0x2a2)
871 btn |= BUTTON_RIGHT;
872 else if (adc_read(7) < 0x38a)
873 btn |= BUTTON_UP;
875 if (adc_read(6) < 0x233)
876 btn |= BUTTON_OFF;
877 else if (adc_read(6) < 0x288)
878 btn |= BUTTON_PLAY;
879 else if (adc_read(6) < 0x355)
880 btn |= BUTTON_MENU;
882 data = P7;
883 if (data & 0x01)
884 btn |= BUTTON_ON;
886 #elif CONFIG_KEYPAD == IPOD_4G_PAD
887 (void)data;
888 /* The int_btn variable is set in the button interrupt handler */
889 btn = int_btn;
890 #endif /* CONFIG_KEYPAD */
893 #ifdef HAVE_LCD_BITMAP
894 if (btn && flipped)
895 btn = button_flip(btn); /* swap upside down */
896 #endif
898 /* Filter the button status. It is only accepted if we get the same
899 status twice in a row. */
900 if (btn != last_read)
901 retval = lastbtn;
902 else
903 retval = btn;
904 last_read = btn;
906 return retval;
909 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
910 bool button_hold(void)
912 return (GPIO1_READ & 0x00000002)?true:false;
915 static bool remote_button_hold_only(void)
917 return (GPIO1_READ & 0x00100000)?true:false;
920 bool remote_button_hold(void)
922 return ((GPIO_READ & 0x40000000) == 0)?remote_button_hold_only():false;
924 #endif
926 #if CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
927 bool button_hold(void)
929 return (GPIO5_READ & 4) ? false : true;
931 #endif
933 int button_status(void)
935 return lastbtn;
938 void button_clear_queue(void)
940 queue_clear(&button_queue);