From cef83c782f0904e536229ffda935ca502dc1015f Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Thu, 6 Apr 2006 07:27:11 +0000 Subject: Do extra filtering in H300 (and H100) main unit button reading to suppress wrong readings during voltage transitions. * Optimised multi-button ADC reads to use a balanced binary tree with an initial check for 'any button' to determine the pressed button. * The iriver button driver wouldn't have detected main unit (ADC-connected) buttons as long as remote buttons (ADC-connected) were pressed (btn = value; vs. btn |= value), * Do extra filtering in the recorder v1 OFF button read, to suppress spurious OFF events. * Some more tweaks. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9530 a1c6a512-1295-4272-9138-f99709370657 --- firmware/drivers/button.c | 452 ++++++++++++++++++++++++---------------------- 1 file changed, 240 insertions(+), 212 deletions(-) (limited to 'firmware') diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c index 6a95932763..00b9dc4e50 100644 --- a/firmware/drivers/button.c +++ b/firmware/drivers/button.c @@ -222,7 +222,7 @@ void ipod_4g_button_int(void) CPU_HI_INT_EN = I2C_MASK; } #endif -#if (CONFIG_KEYPAD == IPOD_3G_PAD) || defined(IPOD_MINI) +#if (CONFIG_KEYPAD == IPOD_3G_PAD) || defined(IPOD_MINI) /* iPod 3G and mini 1G, mini 2G uses iPod 4G code */ void handle_scroll_wheel(int new_scroll, int was_hold, int reverse) { @@ -393,8 +393,8 @@ static int ipod_3g_button_read(void) return btn; } +#endif -#endif static void button_tick(void) { static int tick = 0; @@ -482,10 +482,9 @@ static void button_tick(void) #ifdef HAVE_SW_POWEROFF if ((btn == POWEROFF_BUTTON #ifdef BUTTON_RC_STOP - || btn == BUTTON_RC_STOP) && -#else - ) && + || btn == BUTTON_RC_STOP #endif + ) && #if defined(HAVE_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING) !charger_inserted() && #endif @@ -836,14 +835,12 @@ static int button_read(void) { int btn = BUTTON_NONE; int retval; - int data; -#if (CONFIG_KEYPAD == IRIVER_H100_PAD)\ - || (CONFIG_KEYPAD == IRIVER_H300_PAD) - +#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) static bool hold_button = false; static bool remote_hold_button = false; + static int last_button_val= 0xff; /* light handling */ if (hold_button && !button_hold()) @@ -862,136 +859,146 @@ static int button_read(void) if (!hold_button) { data = adc_scan(ADC_BUTTONS); -#if CONFIG_KEYPAD == IRIVER_H100_PAD - if (data < 0x80) - if (data < 0x30) - if (data < 0x18) - btn = BUTTON_SELECT; - else - btn = BUTTON_UP; - else - if (data < 0x50) - btn = BUTTON_LEFT; - else - btn = BUTTON_DOWN; - else - if (data < 0xb0) - if (data < 0xa0) - btn = BUTTON_RIGHT; +#if CONFIG_KEYPAD == IRIVER_H100_PAD + if ((data < 0xf0) && ((unsigned)(data - last_button_val + 1) <= 2)) + { + if (data < 0x80) + if (data < 0x30) + if (data < 0x18) + btn = BUTTON_SELECT; + else + btn = BUTTON_UP; else - btn = BUTTON_OFF; + if (data < 0x50) + btn = BUTTON_LEFT; + else + btn = BUTTON_DOWN; else - if (data < 0xd0) - btn = BUTTON_MODE; + if (data < 0xb0) + if (data < 0xa0) + btn = BUTTON_RIGHT; + else + btn = BUTTON_OFF; else - if (data < 0xf0) + if (data < 0xd0) + btn = BUTTON_MODE; + else btn = BUTTON_REC; + } #else /* H300 */ - if (data < 0x54) - if (data < 0x30) - if (data < 0x10) - btn = BUTTON_SELECT; + if ((data < 0xba) && ((unsigned)(data - last_button_val + 1) <= 2)) + { + if (data < 0x54) + if (data < 0x30) + if (data < 0x10) + btn = BUTTON_SELECT; + else + btn = BUTTON_UP; else - btn = BUTTON_UP; + btn = BUTTON_LEFT; else - btn = BUTTON_LEFT; - else - if (data < 0x98) - if (data < 0x76) - btn = BUTTON_DOWN; + if (data < 0x98) + if (data < 0x76) + btn = BUTTON_DOWN; + else + btn = BUTTON_RIGHT; else - btn = BUTTON_RIGHT; - else - if(data < 0xba) btn = BUTTON_OFF; - + } #endif + last_button_val = data; } - + /* remote buttons */ if (!remote_hold_button) { data = adc_scan(ADC_REMOTE); - switch(remote_type()) + switch (remote_type()) { case REMOTETYPE_H100_LCD: - if (data < 0x73) - if (data < 0x3f) - if (data < 0x25) - if(data < 0x0c) - btn = BUTTON_RC_STOP; + if (data < 0xf5) + { + if (data < 0x73) + if (data < 0x3f) + if (data < 0x25) + if(data < 0x0c) + btn |= BUTTON_RC_STOP; + else + btn |= BUTTON_RC_VOL_DOWN; else - btn = BUTTON_RC_VOL_DOWN; - else - btn = BUTTON_RC_MODE; - else - if (data < 0x5a) - btn = BUTTON_RC_VOL_UP; - else - btn = BUTTON_RC_BITRATE; - else - if (data < 0xa8) - if (data < 0x8c) - btn = BUTTON_RC_REC; + btn |= BUTTON_RC_MODE; else - btn = BUTTON_RC_SOURCE; + if (data < 0x5a) + btn |= BUTTON_RC_VOL_UP; + else + btn |= BUTTON_RC_BITRATE; else - if (data < 0xdf) - if(data < 0xc5) - btn = BUTTON_RC_FF; + if (data < 0xa8) + if (data < 0x8c) + btn |= BUTTON_RC_REC; else - btn = BUTTON_RC_MENU; + btn |= BUTTON_RC_SOURCE; else - if (data < 0xf5) - btn = BUTTON_RC_REW; + if (data < 0xdf) + if(data < 0xc5) + btn |= BUTTON_RC_FF; + else + btn |= BUTTON_RC_MENU; + else + btn |= BUTTON_RC_REW; + } break; - case REMOTETYPE_H300_LCD: - if (data < 0x73) - if (data < 0x42) - if (data < 0x27) - if(data < 0x0c) - btn = BUTTON_RC_VOL_DOWN; + case REMOTETYPE_H300_LCD: + if (data < 0xf5) + { + if (data < 0x73) + if (data < 0x42) + if (data < 0x27) + if(data < 0x0c) + btn |= BUTTON_RC_VOL_DOWN; + else + btn |= BUTTON_RC_FF; else - btn = BUTTON_RC_FF; + btn |= BUTTON_RC_STOP; else - btn = BUTTON_RC_STOP; - else - if (data < 0x5b) - btn = BUTTON_RC_MODE; - else - btn = BUTTON_RC_REC; - else - if (data < 0xab) - if (data < 0x8e) - btn = BUTTON_RC_ON; - else - btn = BUTTON_RC_BITRATE; + if (data < 0x5b) + btn |= BUTTON_RC_MODE; + else + btn |= BUTTON_RC_REC; else - if (data < 0xde) - if(data < 0xc5) - btn = BUTTON_RC_SOURCE; + if (data < 0xab) + if (data < 0x8e) + btn |= BUTTON_RC_ON; else - btn = BUTTON_RC_VOL_UP; + btn |= BUTTON_RC_BITRATE; else - if (data < 0xf5) - btn = BUTTON_RC_REW; + if (data < 0xde) + if(data < 0xc5) + btn |= BUTTON_RC_SOURCE; + else + btn |= BUTTON_RC_VOL_UP; + else + btn |= BUTTON_RC_REW; + } break; case REMOTETYPE_H300_NONLCD: - if(data<0x7d) - if(data<0x25) - btn = BUTTON_RC_FF; - else - btn = BUTTON_RC_REW; - else - if(data<0xd5) - btn = BUTTON_RC_VOL_DOWN; + if (data < 0xf1) + { + if (data < 0x7d) + if (data < 0x25) + btn |= BUTTON_RC_FF; + else + btn |= BUTTON_RC_REW; else - if(data<0xf1) /* 0xff no button pressed */ - btn = BUTTON_RC_VOL_UP; + if (data < 0xd5) + btn |= BUTTON_RC_VOL_DOWN; + else + btn |= BUTTON_RC_VOL_UP; + } break; } } - + /* special buttons */ #if CONFIG_KEYPAD == IRIVER_H300_PAD if (!hold_button) @@ -1020,7 +1027,6 @@ static int button_read(void) } #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD - static bool hold_button = false; /* light handling */ @@ -1032,67 +1038,56 @@ static int button_read(void) /* normal buttons */ if (!button_hold()) - { + { data = adc_read(ADC_BUTTONS); - - if (data < 0x151) - if (data < 0xc7) - if (data < 0x41) - btn = BUTTON_LEFT; - else - btn = BUTTON_RIGHT; - else - btn = BUTTON_SELECT; - else - if (data < 0x268) - if (data < 0x1d7) - btn = BUTTON_UP; + if (data < 0x35c) + { + if (data < 0x151) + if (data < 0xc7) + if (data < 0x41) + btn = BUTTON_LEFT; + else + btn = BUTTON_RIGHT; else - btn = BUTTON_DOWN; + btn = BUTTON_SELECT; else - if (data < 0x2f9) - btn = BUTTON_EQ; + if (data < 0x268) + if (data < 0x1d7) + btn = BUTTON_UP; + else + btn = BUTTON_DOWN; else - if (data < 0x35c) + if (data < 0x2f9) + btn = BUTTON_EQ; + else btn = BUTTON_MODE; + } + + if (adc_read(ADC_BUTTON_PLAY) < 0x64) + btn |= BUTTON_PLAY; } - - if (!button_hold() && (adc_read(ADC_BUTTON_PLAY) < 0x64)) - btn |= BUTTON_PLAY; #elif CONFIG_KEYPAD == RECORDER_PAD - -#ifdef HAVE_FMADC - if ( adc_read(ADC_BUTTON_ON) < 512 ) - btn |= BUTTON_ON; - if ( adc_read(ADC_BUTTON_OFF) > 512 ) - btn |= BUTTON_OFF; -#else - /* check port B pins for ON and OFF */ - data = PBDR; - if ((data & 0x0100) == 0) - btn |= BUTTON_ON; - if ((data & 0x0010) == 0) - btn |= BUTTON_OFF; +#ifndef HAVE_FMADC + static int off_button_count = 0; #endif /* check F1..F3 and UP */ data = adc_read(ADC_BUTTON_ROW1); - if (data >= LEVEL1) { if (data >= LEVEL3) if (data >= LEVEL4) - btn |= BUTTON_F3; + btn = BUTTON_F3; else - btn |= BUTTON_UP; + btn = BUTTON_UP; else if (data >= LEVEL2) - btn |= BUTTON_F2; + btn = BUTTON_F2; else - btn |= BUTTON_F1; + btn = BUTTON_F1; } - + /* Some units have mushy keypads, so pressing UP also activates the Left/Right buttons. Let's combat that by skipping the AN5 checks when UP is pressed. */ @@ -1100,7 +1095,6 @@ static int button_read(void) { /* check DOWN, PLAY, LEFT, RIGHT */ data = adc_read(ADC_BUTTON_ROW2); - if (data >= LEVEL1) { if (data >= LEVEL3) @@ -1116,11 +1110,33 @@ static int button_read(void) } } -#elif CONFIG_KEYPAD == PLAYER_PAD +#ifdef HAVE_FMADC + if ( adc_read(ADC_BUTTON_ON) < 512 ) + btn |= BUTTON_ON; + if ( adc_read(ADC_BUTTON_OFF) > 512 ) + btn |= BUTTON_OFF; +#else + /* check port B pins for ON and OFF */ + data = PBDR; + if ((data & 0x0100) == 0) + btn |= BUTTON_ON; + + if ((data & 0x0010) == 0) + { + /* When the batteries are low, the low-battery shutdown logic causes + * spurious OFF events due to voltage fluctuation on some units. + * Only accept OFF when read several times in sequence. */ + if (++off_button_count > 3) + btn |= BUTTON_OFF; + } + else + off_button_count = 0; +#endif +#elif CONFIG_KEYPAD == PLAYER_PAD /* buttons are active low */ if (adc_read(0) < 0x180) - btn |= BUTTON_LEFT; + btn = BUTTON_LEFT; if (adc_read(1) < 0x180) btn |= BUTTON_MENU; if(adc_read(2) < 0x180) @@ -1136,46 +1152,54 @@ static int button_read(void) btn |= BUTTON_STOP; #elif CONFIG_KEYPAD == ONDIO_PAD - - if(adc_read(ADC_BUTTON_OPTION) > 0x200) /* active high */ - btn |= BUTTON_MENU; - if(adc_read(ADC_BUTTON_ONOFF) < 0x120) /* active low */ - btn |= BUTTON_OFF; - /* Check the 4 direction keys */ data = adc_read(ADC_BUTTON_ROW1); - if (data >= LEVEL1) { if (data >= LEVEL3) if (data >= LEVEL4) - btn |= BUTTON_LEFT; + btn = BUTTON_LEFT; else - btn |= BUTTON_RIGHT; + btn = BUTTON_RIGHT; else if (data >= LEVEL2) - btn |= BUTTON_UP; + btn = BUTTON_UP; else - btn |= BUTTON_DOWN; - } + btn = BUTTON_DOWN; + } -#elif CONFIG_KEYPAD == GMINI100_PAD + if(adc_read(ADC_BUTTON_OPTION) > 0x200) /* active high */ + btn |= BUTTON_MENU; + if(adc_read(ADC_BUTTON_ONOFF) < 0x120) /* active low */ + btn |= BUTTON_OFF; - if (adc_read(7) < 0xE3) - btn |= BUTTON_LEFT; - else if (adc_read(7) < 0x1c5) - btn |= BUTTON_DOWN; - else if (adc_read(7) < 0x2a2) - btn |= BUTTON_RIGHT; - else if (adc_read(7) < 0x38a) - btn |= BUTTON_UP; +#elif CONFIG_KEYPAD == GMINI100_PAD + data = adc_read(7); + if (data < 0x38a) + { + if (data < 0x1c5) + if (data < 0xe3) + btn = BUTTON_LEFT; + else + btn = BUTTON_DOWN; + else + if (data < 0x2a2) + btn = BUTTON_RIGHT; + else + btn = BUTTON_UP; + } - if (adc_read(6) < 0x233) - btn |= BUTTON_OFF; - else if (adc_read(6) < 0x288) - btn |= BUTTON_PLAY; - else if (adc_read(6) < 0x355) - btn |= BUTTON_MENU; + data = adc_read(6); + if (data < 0x355) + { + if (data < 0x288) + if (data < 0x233) + btn |= BUTTON_OFF; + else + btn |= BUTTON_PLAY; + else + btn |= BUTTON_MENU; + } data = P7; if (data & 0x01) @@ -1185,6 +1209,7 @@ static int button_read(void) (void)data; /* The int_btn variable is set in the button interrupt handler */ btn = int_btn; + #elif (CONFIG_KEYPAD == IPOD_3G_PAD) (void)data; btn = ipod_3g_button_read(); @@ -1200,27 +1225,29 @@ static int button_read(void) if (!hold_button) { data = adc_scan(ADC_BUTTONS); - if(data < 0x7c) - if(data < 0x42) - btn = BUTTON_LEFT; - else - if(data < 0x62) - btn = BUTTON_RIGHT; - else - btn = BUTTON_SELECT; - else - if(data < 0xb6) - if(data < 0x98) - btn = BUTTON_REC; + if (data < 0xf0) + { + if(data < 0x7c) + if(data < 0x42) + btn = BUTTON_LEFT; else - btn = BUTTON_PLAY; + if(data < 0x62) + btn = BUTTON_RIGHT; + else + btn = BUTTON_SELECT; else - if(data < 0xd3) - btn = BUTTON_DOWN; + if(data < 0xb6) + if(data < 0x98) + btn = BUTTON_REC; + else + btn = BUTTON_PLAY; else - if(data < 0xf0) + if(data < 0xd3) + btn = BUTTON_DOWN; + else btn = BUTTON_UP; - } + } + } /* remote buttons */ data = adc_scan(ADC_REMOTE); @@ -1229,28 +1256,30 @@ static int button_read(void) if(!remote_hold_button) { - if(data < 0x7a) - if(data < 0x41) - btn = BUTTON_RC_REW; - else - if(data < 0x61) - btn = BUTTON_RC_FF; - else - btn = BUTTON_RC_MODE; - else - if(data < 0xb4) - if(data < 0x96) - btn = BUTTON_RC_REC; + if (data < 0xee) + { + if(data < 0x7a) + if(data < 0x41) + btn |= BUTTON_RC_REW; else - btn = BUTTON_RC_MENU; + if(data < 0x61) + btn |= BUTTON_RC_FF; + else + btn |= BUTTON_RC_MODE; else - if(data < 0xd1) - btn = BUTTON_RC_VOL_UP; + if(data < 0xb4) + if(data < 0x96) + btn |= BUTTON_RC_REC; + else + btn |= BUTTON_RC_MENU; else - if(data < 0xee) - btn = BUTTON_RC_VOL_DOWN; + if(data < 0xd1) + btn |= BUTTON_RC_VOL_UP; + else + btn |= BUTTON_RC_VOL_DOWN; + } } - + data = GPIO_READ; if (!(data & 0x04000000)) btn |= BUTTON_POWER; @@ -1260,7 +1289,6 @@ static int button_read(void) #endif /* CONFIG_KEYPAD */ - #ifdef HAVE_LCD_BITMAP if (btn && flipped) btn = button_flip(btn); /* swap upside down */ -- cgit v1.2.3