From 303b4abfc5b6e7f1fd85876a2c644a4661d9dd02 Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Wed, 1 Dec 2004 00:33:18 +0000 Subject: Button driver overhaul: (1) Unified the button driver functions as much as possible (2) Proper #defines for FM recorder button ADC channels (3) Got rid of old port B #defines only valid for recorder (4) button filtering for all models (5) RoLo with ON after panic should now work for FM/V2 git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5472 a1c6a512-1295-4272-9138-f99709370657 --- apps/debug_menu.c | 4 + firmware/drivers/button.c | 449 +++++++++++++++++----------------------------- firmware/export/adc.h | 4 +- firmware/export/sh7034.h | 15 +- firmware/system.c | 10 +- 5 files changed, 177 insertions(+), 305 deletions(-) diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 77ebe019f8..880f545d52 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -903,9 +903,12 @@ bool view_battery(void) y = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000; snprintf(buf, 30, "Battery: %d.%02d V", y / 100, y % 100); lcd_puts(0, 1, buf); +#ifdef ADC_EXT_POWER y = (adc_read(ADC_EXT_POWER) * EXT_SCALE_FACTOR) / 10000; snprintf(buf, 30, "External: %d.%02d V", y / 100, y % 100); lcd_puts(0, 2, buf); +#endif +#ifdef HAVE_CHARGING snprintf(buf, 30, "Charger: %s", charger_inserted() ? "present" : "absent"); lcd_puts(0, 3, buf); @@ -914,6 +917,7 @@ bool view_battery(void) charger_enabled ? "yes" : "no"); lcd_puts(0, 4, buf); #endif +#endif y = ( power_history[POWER_HISTORY_LEN-1] * 100 + power_history[POWER_HISTORY_LEN-2] * 100 - power_history[POWER_HISTORY_LEN-1-CHARGE_END_NEGD+1] * 100 diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c index 7e7eb97cf9..a368976d6e 100644 --- a/firmware/drivers/button.c +++ b/firmware/drivers/button.c @@ -16,8 +16,9 @@ * KIND, either express or implied. * ****************************************************************************/ + /* - * Archos Jukebox Recorder button functions + * Rockbox button functions */ #include @@ -36,9 +37,9 @@ struct event_queue button_queue; static int lastbtn; /* Last valid button status */ -#if (CONFIG_KEYPAD == RECORDER_PAD) || (CONFIG_KEYPAD == ONDIO_PAD) || (CONFIG_KEYPAD == IRIVER_H100_PAD) static int last_read; /* Last button status, for debouncing/filtering */ -static bool flipped; /* bottons can be flipped to match the LCD flip */ +#ifdef HAVE_LCD_BITMAP +static bool flipped; /* buttons can be flipped to match the LCD flip */ #endif /* how often we check to see if a button is pressed */ @@ -74,9 +75,9 @@ static void button_tick(void) if(btn) { queue_post(&button_queue, btn, NULL); - } + } #endif - + /* only poll every X ticks */ if ( ++tick >= POLL_FREQUENCY ) { @@ -120,8 +121,8 @@ static void button_tick(void) which doesn't shut down easily with the OFF key */ #ifdef HAVE_SW_POWEROFF - if(btn == BUTTON_OFF && !charger_inserted() && - repeat_count > POWEROFF_COUNT) + if (btn == BUTTON_OFF && !charger_inserted() && + repeat_count > POWEROFF_COUNT) queue_post(&button_queue, SYS_POWEROFF, NULL); #endif } @@ -140,7 +141,7 @@ static void button_tick(void) } if ( post ) { - if(repeat) + if (repeat) queue_post(&button_queue, BUTTON_REPEAT | btn, NULL); else queue_post(&button_queue, btn, NULL); @@ -166,7 +167,8 @@ int button_get(bool block) { struct event ev; - if ( block || !queue_empty(&button_queue) ) { + if ( block || !queue_empty(&button_queue) ) + { queue_wait(&button_queue, &ev); return ev.id; } @@ -180,23 +182,40 @@ int button_get_w_tmo(int ticks) return (ev.id != SYS_TIMEOUT)? ev.id: BUTTON_NONE; } -#if CONFIG_KEYPAD == IRIVER_H100_PAD -void button_init() +void button_init(void) { -#ifndef SIMULATOR + /* hardware inits */ +#if CONFIG_KEYPAD == IRIVER_H100_PAD /* Set GPIO37 as general purpose input */ GPIO1_FUNCTION |= 0x00000020; GPIO1_ENABLE &= ~0x00000020; -#endif +#elif CONFIG_KEYPAD == RECORDER_PAD + /* Set PB4 and PB8 as input pins */ + PBCR1 &= 0xfffc; /* PB8MD = 00 */ + PBCR2 &= 0xfcff; /* PB4MD = 00 */ + PBIOR &= ~0x0110; /* Inputs */ +#elif CONFIG_KEYPAD == PLAYER_PAD + /* set PA5 and PA11 as input pins */ + PACR1 &= 0xff3f; /* PA11MD = 00 */ + PACR2 &= 0xfbff; /* PA5MD = 0 */ + PAIOR &= ~0x0820; /* Inputs */ +#elif CONFIG_KEYPAD == ONDIO_PAD + /* nothing to initialize here */ +#endif /* CONFIG_KEYPAD */ + queue_init(&button_queue); lastbtn = 0; tick_add_task(button_tick); reset_poweroff_timer(); + +#ifdef HAVE_LCD_BITMAP flipped = false; +#endif } +#ifdef HAVE_LCD_BITMAP /* only bitmap displays can be flipped */ /* - * helper function to swap UP/DOWN, LEFT/RIGHT + * helper function to swap UP/DOWN, LEFT/RIGHT (and F1/F3 for Recorder) */ static int button_flip(int button) { @@ -204,7 +223,11 @@ static int button_flip(int button) newbutton = button & ~(BUTTON_UP | BUTTON_DOWN - | BUTTON_LEFT | BUTTON_RIGHT); + | BUTTON_LEFT | BUTTON_RIGHT +#if CONFIG_KEYPAD == RECORDER_PAD + | BUTTON_F1 | BUTTON_F3 +#endif + ); if (button & BUTTON_UP) newbutton |= BUTTON_DOWN; @@ -214,6 +237,12 @@ static int button_flip(int button) newbutton |= BUTTON_RIGHT; if (button & BUTTON_RIGHT) newbutton |= BUTTON_LEFT; +#if CONFIG_KEYPAD == RECORDER_PAD + if (button & BUTTON_F1) + newbutton |= BUTTON_F3; + if (button & BUTTON_F3) + newbutton |= BUTTON_F1; +#endif return newbutton; } @@ -233,6 +262,75 @@ void button_set_flip(bool flip) set_irq_level(oldlevel); } } +#endif /* HAVE_LCD_BITMAP */ + +/* + Archos hardware button hookup + ============================= + + Recorder / Recorder FM/V2 + ------------------------- + F1, F2, F3, UP: connected to AN4 through a resistor network + DOWN, PLAY, LEFT, RIGHT: likewise connected to AN5 + + The voltage on AN4/ AN5 depends on which keys (or key combo) is pressed + FM/V2 has PLAY and RIGHT switched compared to plain recorder + + ON: PB8, low active (plain recorder) / AN3, low active (fm/v2) + OFF: PB4, low active (plain recorder) / AN2, high active (fm/v2) + + Player + ------ + LEFT: AN0 + MENU: AN1 + RIGHT: AN2 + PLAY: AN3 + + STOP: PA11 + ON: PA5 + + All buttons are low active + + Ondio + ----- + LEFT, RIGHT, UP, DOWN: connected to AN4 through a resistor network + + The voltage on AN4 depends on which keys (or key combo) is pressed + + OPTION: AN2, high active (assigned as MENU) + ON/OFF: AN3, low active (assigned as OFF) + +*/ + +#if CONFIG_KEYPAD == RECORDER_PAD + +#ifdef HAVE_FMADC +/* FM Recorder super-special levels */ +#define LEVEL1 150 +#define LEVEL2 385 +#define LEVEL3 545 +#define LEVEL4 700 +#define ROW2_BUTTON1 BUTTON_PLAY +#define ROW2_BUTTON3 BUTTON_RIGHT + +#else +/* plain bog standard Recorder levels */ +#define LEVEL1 250 +#define LEVEL2 500 +#define LEVEL3 700 +#define LEVEL4 900 +#define ROW2_BUTTON1 BUTTON_RIGHT +#define ROW2_BUTTON3 BUTTON_PLAY +#endif /* HAVE_FMADC */ + +#elif CONFIG_KEYPAD == ONDIO_PAD +/* Ondio levels */ +#define LEVEL1 165 +#define LEVEL2 415 +#define LEVEL3 585 +#define LEVEL4 755 + +#endif /* CONFIG_KEYPAD */ /* * Get button pressed from hardware @@ -244,175 +342,57 @@ static int button_read(void) int data; +#if CONFIG_KEYPAD == IRIVER_H100_PAD + data = adc_scan(0); - if(data < 0x80) - if(data < 0x30) - if(data < 0x18) + if (data < 0x80) + if (data < 0x30) + if (data < 0x18) btn = BUTTON_SELECT; else btn = BUTTON_UP; else - if(data < 0x50) + if (data < 0x50) btn = BUTTON_LEFT; else btn = BUTTON_DOWN; else - if(data < 0xb0) - if(data < 0xa0) + if (data < 0xb0) + if (data < 0xa0) btn = BUTTON_RIGHT; else btn = BUTTON_OFF; else - if(data < 0xd0) + if (data < 0xd0) btn = BUTTON_MODE; else - if(data < 0xf0) + if (data < 0xf0) btn = BUTTON_REC; data = GPIO1_READ; if ((data & 0x20) == 0) btn |= BUTTON_ON; - - if (btn && flipped) - btn = button_flip(btn); /* swap upside down */ - - /* Filter the button status. It is only accepted if we get the same - status twice in a row. */ - if(btn != last_read) - retval = lastbtn; - else - retval = btn; - last_read = btn; - - return retval; -} - -bool button_hold(void) -{ - return (GPIO1_READ & 0x00000002)?true:false; -} - #elif CONFIG_KEYPAD == RECORDER_PAD -/* AJBR buttons are connected to the CPU as follows: - * - * ON and OFF are connected to separate port B input pins. - * - * F1, F2, F3, and UP are connected to the AN4 analog input, each through - * a separate voltage divider. The voltage on AN4 depends on which button - * (or none, or a combination) is pressed. - * - * DOWN, PLAY, LEFT, and RIGHT are likewise connected to AN5. */ - -/* Button analog voltage levels */ #ifdef HAVE_FMADC -/* FM Recorder super-special levels */ -#define LEVEL1 150 -#define LEVEL2 385 -#define LEVEL3 545 -#define LEVEL4 700 -#else -/* plain bog standard Recorder levels */ -#define LEVEL1 250 -#define LEVEL2 500 -#define LEVEL3 700 -#define LEVEL4 900 -#endif - -/* - *Initialize buttons - */ -void button_init() -{ -#ifndef SIMULATOR - /* Set PB4 and PB8 as input pins */ - PBCR1 &= 0xfffc; /* PB8MD = 00 */ - PBCR2 &= 0xfcff; /* PB4MD = 00 */ - PBIOR &= ~(PBDR_BTN_ON|PBDR_BTN_OFF); /* Inputs */ -#endif - queue_init(&button_queue); - lastbtn = 0; - tick_add_task(button_tick); - reset_poweroff_timer(); - flipped = false; -} - - -/* - * helper function to swap UP/DOWN, LEFT/RIGHT, F1/F3 - */ -static int button_flip(int button) -{ - int newbutton; - - newbutton = button & - ~(BUTTON_UP | BUTTON_DOWN - | BUTTON_LEFT | BUTTON_RIGHT - | BUTTON_F1 | BUTTON_F3); - - if (button & BUTTON_UP) - newbutton |= BUTTON_DOWN; - if (button & BUTTON_DOWN) - newbutton |= BUTTON_UP; - if (button & BUTTON_LEFT) - newbutton |= BUTTON_RIGHT; - if (button & BUTTON_RIGHT) - newbutton |= BUTTON_LEFT; - if (button & BUTTON_F1) - newbutton |= BUTTON_F3; - if (button & BUTTON_F3) - newbutton |= BUTTON_F1; - - return newbutton; -} - - -/* - * set the flip attribute - * better only call this when the queue is empty - */ -void button_set_flip(bool flip) -{ - if (flip != flipped) /* not the current setting */ - { - /* avoid race condition with the button_tick() */ - int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); - lastbtn = button_flip(lastbtn); - flipped = flip; - set_irq_level(oldlevel); - } -} - -/* - * Get button pressed from hardware - */ -static int button_read(void) -{ - int btn = BUTTON_NONE; - int retval; - - int data; - -#ifdef HAVE_FMADC - /* TODO: use proper defines here, and not the numerics in the - function argument */ - if ( adc_read(3) < 512 ) + if ( adc_read(ADC_BUTTON_ON) < 512 ) btn |= BUTTON_ON; - if ( adc_read(2) > 512 ) + if ( adc_read(ADC_BUTTON_OFF) > 512 ) btn |= BUTTON_OFF; #else - /* Check port B pins for ON and OFF */ + /* check port B pins for ON and OFF */ data = PBDR; - if ((data & PBDR_BTN_ON) == 0) + if ((data & 0x0100) == 0) btn |= BUTTON_ON; - else if ((data & PBDR_BTN_OFF) == 0) + if ((data & 0x0010) == 0) btn |= BUTTON_OFF; #endif - /* Check F1-3 and UP */ + /* check F1..F3 and UP */ data = adc_read(ADC_BUTTON_ROW1); + if (data >= LEVEL4) btn |= BUTTON_F3; else if (data >= LEVEL3) @@ -427,181 +407,68 @@ static int button_read(void) checks when UP is pressed. */ if(!(btn & BUTTON_UP)) { - /* Check DOWN, PLAY, LEFT, RIGHT */ + /* check DOWN, PLAY, LEFT, RIGHT */ data = adc_read(ADC_BUTTON_ROW2); + if (data >= LEVEL4) btn |= BUTTON_DOWN; - else if (data >= LEVEL3) { -#ifdef HAVE_FMADC - btn |= BUTTON_RIGHT; -#else - btn |= BUTTON_PLAY; -#endif - } + else if (data >= LEVEL3) + btn |= ROW2_BUTTON3; else if (data >= LEVEL2) btn |= BUTTON_LEFT; - else if (data >= LEVEL1) { -#ifdef HAVE_FMADC - btn |= BUTTON_PLAY; -#else - btn |= BUTTON_RIGHT; -#endif - } + else if (data >= LEVEL1) + btn |= ROW2_BUTTON1; } - if (btn && flipped) - btn = button_flip(btn); /* swap upside down */ - - /* Filter the button status. It is only accepted if we get the same - status twice in a row. */ - if(btn != last_read) - retval = lastbtn; - else - retval = btn; - last_read = btn; - - return retval; -} - #elif CONFIG_KEYPAD == PLAYER_PAD -/* The player has two buttons on port pins: - - STOP: PA11 - ON: PA5 - - The rest are on analog inputs: - - LEFT: AN0 - MENU: AN1 - RIGHT: AN2 - PLAY: AN3 -*/ - -void button_init(void) -{ -#ifndef SIMULATOR - /* set PA5 and PA11 as input */ - PACR1 &= 0xff3f; /* PA11MD = 00 */ - PACR2 &= 0xfbff; /* PA5MD = 0 */ - PAIOR &= ~0x820; -#endif - queue_init(&button_queue); - lastbtn = 0; - tick_add_task(button_tick); - - reset_poweroff_timer(); -} - -static int button_read(void) -{ - int porta = PADR; - int btn = BUTTON_NONE; - /* buttons are active low */ - if(adc_read(0) < 0x180) + if (adc_read(0) < 0x180) btn |= BUTTON_LEFT; - if(adc_read(1) < 0x180) + if (adc_read(1) < 0x180) btn |= BUTTON_MENU; if(adc_read(2) < 0x180) btn |= BUTTON_RIGHT; if(adc_read(3) < 0x180) btn |= BUTTON_PLAY; - if ( !(porta & 0x20) ) + /* check port A pins for ON and STOP */ + data = PADR; + if ( !(data & 0x0020) ) btn |= BUTTON_ON; - if ( !(porta & 0x800) ) + if ( !(data & 0x0800) ) btn |= BUTTON_STOP; - return btn; -} - #elif CONFIG_KEYPAD == ONDIO_PAD -/* - * helper function to swap UP/DOWN, LEFT/RIGHT - */ -static int button_flip(int button) -{ - int newbutton; - - newbutton = button & - ~(BUTTON_UP | BUTTON_DOWN - | BUTTON_LEFT | BUTTON_RIGHT); - - if (button & BUTTON_UP) - newbutton |= BUTTON_DOWN; - if (button & BUTTON_DOWN) - newbutton |= BUTTON_UP; - if (button & BUTTON_LEFT) - newbutton |= BUTTON_RIGHT; - if (button & BUTTON_RIGHT) - newbutton |= BUTTON_LEFT; - - return newbutton; -} - - -/* - * set the flip attribute - * better only call this when the queue is empty - */ -void button_set_flip(bool flip) -{ - if (flip != flipped) /* not the current setting */ - { - /* avoid race condition with the button_tick() */ - int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); - lastbtn = button_flip(lastbtn); - flipped = flip; - set_irq_level(oldlevel); - } -} - - -/* The Ondio its 6 buttons on analog inputs: - OPTION: AN2 (used as MENU for now) - ON/OFF: AN3 - LEFT/RIGHT/UP/DOWN: AN4 - We map them like the player keys for now, although this is far from optimal. -*/ -void button_init(void) -{ - queue_init(&button_queue); - lastbtn = 0; - tick_add_task(button_tick); - - reset_poweroff_timer(); -} - -static int button_read(void) -{ - int btn = BUTTON_NONE; - int retval; - - int data = adc_read(ADC_BUTTON_ROW1); - 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, hard-coded analog limits for now */ - if (data >= 0x2EF) + /* Check the 4 direction keys */ + data = adc_read(ADC_BUTTON_ROW1); + + if (data >= LEVEL4) btn |= BUTTON_LEFT; - else if (data >= 0x246) + else if (data >= LEVEL3) btn |= BUTTON_RIGHT; - else if (data >= 0x19D) + else if (data >= LEVEL2) btn |= BUTTON_UP; - else if (data >= 0x0A1) + else if (data >= LEVEL1) btn |= BUTTON_DOWN; +#endif /* CONFIG_KEYPAD */ + + +#ifdef HAVE_LCD_BITMAP if (btn && flipped) btn = button_flip(btn); /* swap upside down */ +#endif /* Filter the button status. It is only accepted if we get the same status twice in a row. */ - if(btn != last_read) + if (btn != last_read) retval = lastbtn; else retval = btn; @@ -610,6 +477,11 @@ static int button_read(void) return retval; } +#if CONFIG_KEYPAD == IRIVER_H100_PAD +bool button_hold(void) +{ + return (GPIO1_READ & 0x00000002)?true:false; +} #endif int button_status(void) @@ -621,3 +493,4 @@ void button_clear_queue(void) { queue_clear(&button_queue); } + diff --git a/firmware/export/adc.h b/firmware/export/adc.h index 044391b536..e2c87fa385 100644 --- a/firmware/export/adc.h +++ b/firmware/export/adc.h @@ -41,8 +41,6 @@ #define ADC_BUTTON_ROW1 4 /* Used for scanning the keys, different voltages for different keys */ #define ADC_UNREG_POWER 7 /* Battery voltage */ -/* FixMe: this doesn't exist, just to make the compiler happy */ -#define ADC_EXT_POWER 5 /* The external power voltage, V=X*0.0148 */ #else /* normal JBR channel assignment */ @@ -51,6 +49,8 @@ #ifdef HAVE_FMADC #define ADC_CHARGE_REGULATOR 0 /* Uh, we read the battery voltage? */ #define ADC_USB_POWER 1 /* USB, reads 0x000 when USB is inserted */ +#define ADC_BUTTON_OFF 2 /* the off button, high value if pressed */ +#define ADC_BUTTON_ON 3 /* the on button, low value if pressed */ #else #define ADC_CHARGE_REGULATOR 1 /* Regulator reference voltage, should read about 0x1c0 when charging, else 0x3FF */ diff --git a/firmware/export/sh7034.h b/firmware/export/sh7034.h index 90cbb5a0a4..c15ee2a88f 100644 --- a/firmware/export/sh7034.h +++ b/firmware/export/sh7034.h @@ -140,7 +140,7 @@ #define RSTCSR_ADDR 0x05FFFFBB #define SBYCR_ADDR 0x05FFFFBC - + #define PADR_ADDR 0x05FFFFC0 #define PBDR_ADDR 0x05FFFFC2 #define PAIOR_ADDR 0x05FFFFC4 @@ -150,7 +150,7 @@ #define PBCR1_ADDR 0x05FFFFCC #define PBCR2_ADDR 0x05FFFFCE #define PCDR_ADDR 0x05FFFFD0 - + #define CASCR_ADDR 0x05FFFFEE /* byte halves of the ports */ @@ -164,15 +164,6 @@ #define PBIORL_ADDR 0x05FFFFC7 -/* Port B data register bits */ -#define PBDR_LCD_SDA 0x0001 /* LCD serial data */ -#define PBDR_LCD_SCK 0x0002 /* LCD serial clock */ -#define PBDR_LCD_DC 0x0004 /* LCD data (1) / command (0) */ -#define PBDR_LCD_CS1 0x0008 /* LCD chip select 1 (active low) */ -#define PBDR_BTN_OFF 0x0010 /* Off button (active low) */ -#define PBDR_LED_RED 0x0040 /* Red LED */ -#define PBDR_BTN_ON 0x0100 /* On button (active low) */ - /* A/D control/status register bits */ #define ADCSR_CH 0x07 /* Channel/group select */ #define ADCSR_CKS 0x08 /* Clock select */ @@ -195,7 +186,7 @@ #define SMR1 (*((volatile unsigned char*)SMR1_ADDR)) #define BRR1 (*((volatile unsigned char*)BRR1_ADDR)) #define SCR1 (*((volatile unsigned char*)SCR1_ADDR)) -#define TDR1 (*((volatile unsigned char*)TDR1_ADDR)) +#define TDR1 (*((volatile unsigned char*)TDR1_ADDR)) #define SSR1 (*((volatile unsigned char*)SSR1_ADDR)) #define RDR1 (*((volatile unsigned char*)RDR1_ADDR)) diff --git a/firmware/system.c b/firmware/system.c index 0628eb64cb..726d7fd6cc 100644 --- a/firmware/system.c +++ b/firmware/system.c @@ -534,11 +534,15 @@ void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */ for (i = 0; i < 240000; ++i); /* try to restart firmware if ON is pressed */ -#ifdef HAVE_LCD_CHARCELLS - if (!(PADR & 0x20)) +#if CONFIG_KEYPAD == PLAYER_PAD + if (!(PADR & 0x0020)) rolo_load("/archos.mod"); +#elif CONFIG_KEYPAD == RECORDER_PAD +#ifdef HAVE_FMADC + if (!(PCDR & 0x0008)) #else - if (!(PBDR & PBDR_BTN_ON)) + if (!(PBDR & 0x0100)) +#endif rolo_load("/ajbrec.ajz"); #endif } -- cgit v1.2.3