From f376fd2f4aa9b27f2a6299177b4cc3c014da01f3 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Thu, 1 Apr 2010 16:07:56 +0000 Subject: 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 --- firmware/SOURCES | 3 + firmware/export/config/sansafuzev2.h | 8 +- firmware/target/arm/as3525/button-e200v2-fuze.c | 108 +----------------- firmware/target/arm/as3525/kernel-as3525.c | 2 +- .../target/arm/as3525/sansa-e200v2/button-target.h | 6 + .../target/arm/as3525/sansa-fuze/button-target.h | 7 ++ .../target/arm/as3525/sansa-fuzev2/button-fuzev2.c | 38 ++++++- .../target/arm/as3525/sansa-fuzev2/button-target.h | 6 + firmware/target/arm/as3525/scrollwheel-as3525.c | 124 +++++++++++++++++++++ 9 files changed, 187 insertions(+), 115 deletions(-) create mode 100644 firmware/target/arm/as3525/scrollwheel-as3525.c diff --git a/firmware/SOURCES b/firmware/SOURCES index 0d845f2b3c..b5151c3950 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -408,6 +408,9 @@ target/arm/pnx0101/timer-pnx0101.c target/arm/as3525/system-as3525.c target/arm/as3525/kernel-as3525.c target/arm/as3525/timer-as3525.c +#ifdef HAVE_SCROLLWHEEL +target/arm/as3525/scrollwheel-as3525.c +#endif #if CONFIG_CPU == AS3525 target/arm/as3525/sd-as3525.c #else /* AS3535v2 */ diff --git a/firmware/export/config/sansafuzev2.h b/firmware/export/config/sansafuzev2.h index b71f852007..88d7650ca3 100644 --- a/firmware/export/config/sansafuzev2.h +++ b/firmware/export/config/sansafuzev2.h @@ -127,13 +127,13 @@ #define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_SETTING /* define this if the unit uses a scrollwheel for navigation */ -//#define HAVE_SCROLLWHEEL +#define HAVE_SCROLLWHEEL /* define to activate advanced wheel acceleration code */ -//#define HAVE_WHEEL_ACCELERATION +#define HAVE_WHEEL_ACCELERATION /* define from which rotation speed [degree/sec] on the acceleration starts */ -//#define WHEEL_ACCEL_START 540 +#define WHEEL_ACCEL_START 540 /* define type of acceleration (1 = ^2, 2 = ^3, 3 = ^4) */ -//#define WHEEL_ACCELERATION 1 +#define WHEEL_ACCELERATION 1 /* define this if you have a flash memory storage */ #define HAVE_FLASH_STORAGE 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 @@ #include "backlight.h" #include "dbop-as3525.h" +extern void scrollwheel(unsigned wheel_value); -#if defined(SANSA_FUZE) || defined(SANSA_FUZEV2) +#if defined(SANSA_FUZE) #define DBOP_BIT15_BUTTON BUTTON_HOME -#define WHEEL_REPEAT_INTERVAL (HZ/5) -#define WHEEL_COUNTER_DIV 4 -#define ACCEL_INCREMENT 2 -#define ACCEL_SHIFT 2 #endif #ifdef SANSA_E200V2 #define DBOP_BIT15_BUTTON BUTTON_REC -#define WHEEL_REPEAT_INTERVAL (HZ/5) -#define WHEEL_COUNTER_DIV 2 -#define ACCEL_INCREMENT 3 -#define ACCEL_SHIFT 1 #endif /* Buttons */ @@ -56,103 +49,6 @@ void button_init_device(void) GPIOA_PIN(1) = (1<<1); } -#if !defined(BOOTLOADER) && defined(HAVE_SCROLLWHEEL) -static void scrollwheel(unsigned int wheel_value) -{ - /* current wheel values, parsed from dbop and the resulting button */ - unsigned btn = BUTTON_NONE; - /* old wheel values */ - static unsigned old_wheel_value = 0; - static unsigned old_btn = BUTTON_NONE; - - /* - * Getting BUTTON_REPEAT works like this: Remember when the btn value was - * posted to the button_queue last, and if it was recent enough, generate - * BUTTON_REPEAT - */ - static long last_wheel_post = 0; - - /* - * Providing wheel acceleration works as follows: We increment accel - * by 2 if the wheel was turned, and decrement it by 1 each tick - * (no matter if it was turned), that means: the longer and faster you turn, - * the higher accel will be. accel>>2 will actually posted to the button_queue - */ - static int accel = 0; - /* We only post every 4th action, as this matches better with the physical - * clicks of the wheel */ - static int counter = 0; - /* Read wheel - * Bits 13 and 14 of DBOP_DIN change as follows (Gray Code): - * Clockwise rotation 00 -> 01 -> 11 -> 10 -> 00 - * Counter-clockwise 00 -> 10 -> 11 -> 01 -> 00 - * - * For easy look-up, actual wheel values act as indicies also, - * which is why the table seems to be not ordered correctly - */ - static const unsigned char wheel_tbl[2][4] = - { - { 2, 0, 3, 1 }, /* Clockwise rotation */ - { 1, 3, 0, 2 }, /* Counter-clockwise */ - }; - - if(hold_button) - { - accel = counter = 0; - return; - } - - if (old_wheel_value == wheel_tbl[0][wheel_value]) - btn = BUTTON_SCROLL_FWD; - else if (old_wheel_value == wheel_tbl[1][wheel_value]) - btn = BUTTON_SCROLL_BACK; - else if (old_wheel_value != wheel_value && accel > ACCEL_INCREMENT) - { /* if no button is read and wheel_value changed, assume old_btn */ - btn = old_btn; - } - /* else btn = BUTTON_NONE */ - - if (btn != BUTTON_NONE) - { - if (btn != old_btn) - { - /* direction reversals nullify acceleration and counters */ - old_btn = btn; - accel = counter = 0; - } - /* wheel_delta will cause lists to jump over items, - * we want this for fast scrolling, but we must keep it accurate - * for slow scrolling */ - int wheel_delta = 0; - /* generate BUTTON_REPEAT if quick enough, scroll slightly faster too*/ - if (TIME_BEFORE(current_tick, last_wheel_post + WHEEL_REPEAT_INTERVAL)) - { - btn |= BUTTON_REPEAT; - wheel_delta = accel>>ACCEL_SHIFT; - } - - accel += ACCEL_INCREMENT; - - /* the wheel is more reliable if we don't send every change, - * every WHEEL_COUNTER_DIVth is basically one "physical click" - * which should make up 1 item in lists */ - if (++counter >= WHEEL_COUNTER_DIV && queue_empty(&button_queue)) - { - buttonlight_on(); - backlight_on(); - queue_post(&button_queue, btn, ((wheel_delta+1)<<24)); - /* message posted - reset count and remember post */ - counter = 0; - last_wheel_post = current_tick; - } - } - if (accel > 0) - accel--; - - old_wheel_value = wheel_value; -} -#endif /* !defined(BOOTLOADER) && defined(SCROLLWHEEL) */ - bool button_hold(void) { 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) else { if (!button_hold()) - button_read_dbop(); /* Read the scrollwheel */ + get_scrollwheel(); /* Read the scrollwheel */ } 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); void button_init_device(void); int button_read_device(void); unsigned short button_read_dbop(void); +#define get_scrollwheel button_read_dbop + +#define WHEEL_REPEAT_INTERVAL (HZ/5) +#define WHEEL_COUNTER_DIV 2 +#define ACCEL_INCREMENT 3 +#define ACCEL_SHIFT 1 /* Sandisk Sansa E200 button codes */ 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); bool button_hold(void); int button_read_device(void); unsigned short button_read_dbop(void); +#define get_scrollwheel button_read_dbop + +#define WHEEL_REPEAT_INTERVAL (HZ/5) +#define WHEEL_COUNTER_DIV 4 +#define ACCEL_INCREMENT 2 +#define ACCEL_SHIFT 2 + /* Sandisk Sansa Fuze button codes */ /* 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 @@ #include "button.h" #include "backlight.h" -/* - * TODO: Scrollwheel! - */ - +extern void scrollwheel(unsigned wheel_value); + #ifdef HAS_BUTTON_HOLD static bool hold_button = false; #endif void button_init_device(void) +{ /* activate the wheel */ + volatile int i; + GPIOB_DIR |= 1<<4; + for(i = 20; i; i--) nop; + GPIOB_PIN(4) = 0x10; +} + +unsigned read_GPIOA_67(void) { + unsigned ret = 0; + volatile int i; + DBOP_CTRL |= 1<<19; + for(i = 20; i; i--) nop; + GPIOA_DIR &= ~0xc0; + for(i = 20; i; i--) nop; + if (GPIOA_PIN(6) != 0) + ret = 1<<0; + for(i = 20; i; i--) nop; + if (GPIOA_PIN(7) != 0) + ret |= 1<<1; + DBOP_CTRL &= ~(1<<19); + for(i = 20; i; i--) nop; + return ret; +} + +void get_scrollwheel(void) +{ +#if defined(HAVE_SCROLLWHEEL) && !defined(BOOTLOADER) + /* scroll wheel handling */ + scrollwheel(read_GPIOA_67()); +#endif } /* * Get button pressed from hardware */ + int button_read_device(void) { int btn = 0; @@ -48,6 +77,7 @@ int button_read_device(void) unsigned gpiod = GPIOD_DATA; unsigned gpioa_dir = GPIOA_DIR; unsigned gpiod6; + get_scrollwheel(); for(delay = 500; delay; delay--) nop; CCU_IO &= ~(1<<12); 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); bool button_hold(void); int button_read_device(void); unsigned short button_read_dbop(void); +void get_scrollwheel(void); + +#define WHEEL_REPEAT_INTERVAL (HZ/5) +#define WHEEL_COUNTER_DIV 4 +#define ACCEL_INCREMENT 2 +#define ACCEL_SHIFT 2 /* Sandisk Sansa Fuze button codes */ /* 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 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009-2010 by Thomas Martitz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "config.h" +#include "button.h" +#include "kernel.h" +#include "backlight.h" + +void scrollwheel(unsigned int wheel_value) +{ +#ifndef BOOTLOADER + /* current wheel values, parsed from dbop and the resulting button */ + unsigned btn = BUTTON_NONE; + /* old wheel values */ + static unsigned old_wheel_value = 0; + static unsigned old_btn = BUTTON_NONE; + + /* + * Getting BUTTON_REPEAT works like this: Remember when the btn value was + * posted to the button_queue last, and if it was recent enough, generate + * BUTTON_REPEAT + */ + static long last_wheel_post = 0; + + /* + * Providing wheel acceleration works as follows: We increment accel + * by 2 if the wheel was turned, and decrement it by 1 each tick + * (no matter if it was turned), that means: the longer and faster you turn, + * the higher accel will be. accel>>2 will actually posted to the button_queue + */ + static int accel = 0; + /* We only post every 4th action, as this matches better with the physical + * clicks of the wheel */ + static int counter = 0; + /* Read wheel + * Bits 13 and 14 of DBOP_DIN change as follows (Gray Code): + * Clockwise rotation 00 -> 01 -> 11 -> 10 -> 00 + * Counter-clockwise 00 -> 10 -> 11 -> 01 -> 00 + * + * For easy look-up, actual wheel values act as indicies also, + * which is why the table seems to be not ordered correctly + */ + static const unsigned char wheel_tbl[2][4] = + { + { 2, 0, 3, 1 }, /* Clockwise rotation */ + { 1, 3, 0, 2 }, /* Counter-clockwise */ + }; + + if(button_hold()) + { + accel = counter = 0; + return; + } + + if (old_wheel_value == wheel_tbl[0][wheel_value]) + btn = BUTTON_SCROLL_FWD; + else if (old_wheel_value == wheel_tbl[1][wheel_value]) + btn = BUTTON_SCROLL_BACK; + else if (old_wheel_value != wheel_value && accel > ACCEL_INCREMENT) + { /* if no button is read and wheel_value changed, assume old_btn */ + btn = old_btn; + } + /* else btn = BUTTON_NONE */ + + if (btn != BUTTON_NONE) + { + if (btn != old_btn) + { + /* direction reversals nullify acceleration and counters */ + old_btn = btn; + accel = counter = 0; + } + /* wheel_delta will cause lists to jump over items, + * we want this for fast scrolling, but we must keep it accurate + * for slow scrolling */ + int wheel_delta = 0; + /* generate BUTTON_REPEAT if quick enough, scroll slightly faster too*/ + if (TIME_BEFORE(current_tick, last_wheel_post + WHEEL_REPEAT_INTERVAL)) + { + btn |= BUTTON_REPEAT; + wheel_delta = accel>>ACCEL_SHIFT; + } + + accel += ACCEL_INCREMENT; + + /* the wheel is more reliable if we don't send every change, + * every WHEEL_COUNTER_DIVth is basically one "physical click" + * which should make up 1 item in lists */ + if (++counter >= WHEEL_COUNTER_DIV && queue_empty(&button_queue)) + { + buttonlight_on(); + backlight_on(); + queue_post(&button_queue, btn, ((wheel_delta+1)<<24)); + /* message posted - reset count and remember post */ + counter = 0; + last_wheel_post = current_tick; + } + } + if (accel > 0) + accel--; + + old_wheel_value = wheel_value; +#else + (void)wheel_value +#endif +} -- cgit v1.2.3