diff -U 3 -H -d -r -N -- rockbox-bleeding/apps/SOURCES rockbox-bleeding-dest/apps/SOURCES
--- rockbox-bleeding/apps/SOURCES	2007-04-16 03:15:22.000000000 -0600
+++ rockbox-bleeding-dest/apps/SOURCES	2007-04-24 16:19:31.000000000 -0600
@@ -43,6 +43,9 @@
 #endif
 filetree.c
 scrobbler.c
+#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
+ipod_scroll_wheel_gui.c
+#endif
 
 screen_access.c
 gui/buttonbar.c
diff -U 3 -H -d -r -N -- rockbox-bleeding/apps/gui/list.c rockbox-bleeding-dest/apps/gui/list.c
--- rockbox-bleeding/apps/gui/list.c	2007-04-21 05:15:45.000000000 -0600
+++ rockbox-bleeding-dest/apps/gui/list.c	2007-04-24 16:27:45.000000000 -0600
@@ -35,6 +35,10 @@
 #include "lang.h"
 #include "sound.h"
 
+#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
+#include "ipod_scroll_wheel_gui.h"
+#endif
+
 #ifdef HAVE_LCD_CHARCELLS
 #define SCROLL_LIMIT 1
 #else
@@ -612,7 +616,7 @@
  * - gui_list : the list structure
  * - nb_lines : the number of lines to try to move the cursor
  */
-static void gui_list_select_next_page(struct gui_list * gui_list, int nb_lines)
+void gui_list_select_next_page(struct gui_list * gui_list, int nb_lines)
 {
     if(gui_list->selected_item == gui_list->nb_items-gui_list->selected_size)
     {
@@ -637,7 +641,7 @@
  * - gui_list : the list structure
  * - nb_lines : the number of lines to try to move the cursor
  */
-static void gui_list_select_previous_page(struct gui_list * gui_list, int nb_lines)
+void gui_list_select_previous_page(struct gui_list * gui_list, int nb_lines)
 {
     if(gui_list->selected_item == 0)
     {
@@ -823,14 +827,14 @@
         gui_list_select_item(&(lists->gui_list[i]), item_number);
 }
 
-static void gui_synclist_select_next(struct gui_synclist * lists)
+void gui_synclist_select_next(struct gui_synclist * lists)
 {
     int i;
     FOR_NB_SCREENS(i)
         gui_list_select_next(&(lists->gui_list[i]));
 }
 
-static void gui_synclist_select_previous(struct gui_synclist * lists)
+void gui_synclist_select_previous(struct gui_synclist * lists)
 {
     int i;
     FOR_NB_SCREENS(i)
@@ -949,7 +953,11 @@
 #endif
         case ACTION_STD_PREV:
         case ACTION_STD_PREVREPEAT:
+ #if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
+             gui_synclist_handle_accel( lists, SCREEN_MAIN, BACKWARD );
+ #else
             gui_synclist_select_previous(lists);
+ #endif
             if (queue_count(&button_queue) < FRAMEDROP_TRIGGER)
                 gui_synclist_draw(lists);
             yield();
@@ -957,7 +965,11 @@
 
         case ACTION_STD_NEXT:
         case ACTION_STD_NEXTREPEAT:
+ #if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
+             gui_synclist_handle_accel( lists, SCREEN_MAIN, FORWARD );
+ #else
             gui_synclist_select_next(lists);
+ #endif
             if (queue_count(&button_queue) < FRAMEDROP_TRIGGER)
                 gui_synclist_draw(lists);
             yield();
diff -U 3 -H -d -r -N -- rockbox-bleeding/apps/gui/list.h rockbox-bleeding-dest/apps/gui/list.h
--- rockbox-bleeding/apps/gui/list.h	2007-04-16 03:15:21.000000000 -0600
+++ rockbox-bleeding-dest/apps/gui/list.h	2007-04-24 16:19:31.000000000 -0600
@@ -190,6 +190,23 @@
 extern void gui_synclist_set_title(struct gui_synclist * lists, char * title,
                                    int icon);
 
+extern void gui_synclist_select_next(struct gui_synclist * lists);
+extern void gui_synclist_select_previous(struct gui_synclist * lists);
+extern void gui_list_select_next_page(struct gui_list * gui_list, int nb_lines);
+extern void gui_list_select_previous_page(struct gui_list * gui_list, int nb_lines);
+
+ /*
+ * Advance/retreat in the list by n percent of the total list elements,
+ * by at least one line if percent_lines != 0
+ * - gui_list : the list structure
+ * - percent_lines : the percent of the total number of lines to try to move the cursor
+ *   postive adavnces forward, negative retreats back, 0 has no effect
+ */
+#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
+extern void gui_list_select_relative_percent( struct gui_list * gui_list,
+                                                int percent_lines );
+#endif
+
 /*
  * Do the action implied by the given button,
  * returns the action taken if any, 0 else
diff -U 3 -H -d -r -N -- rockbox-bleeding/apps/ipod_scroll_wheel_gui.c rockbox-bleeding-dest/apps/ipod_scroll_wheel_gui.c
--- rockbox-bleeding/apps/ipod_scroll_wheel_gui.c	1969-12-31 17:00:00.000000000 -0700
+++ rockbox-bleeding-dest/apps/ipod_scroll_wheel_gui.c	2007-04-24 16:19:31.000000000 -0600
@@ -0,0 +1,160 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ *
+ * Copyright (C) TP Diffenbach (2006)
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+
+#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
+
+#include "button.h"
+#include "settings.h"
+#include "logf.h"
+#include "list.h"
+#include "screen_access.h"
+#include "statusbar.h"
+#include "ipod_scroll_wheel_gui.h"
+
+ struct scroll_accel_jump {
+    enum { NOACCEL, PAGE, PERCENT } jump_type;
+    unsigned int amount;
+    unsigned int lines;
+};
+
+struct scroll_accel_jump scroll_accel_jumps[] = { { NOACCEL, 0, 0 }, { PAGE, 1, 0  }, { PAGE, 8, 0  } , { PERCENT, 10, 0 } };
+
+static void calculate_jump_lines( struct scroll_accel_jump* j, unsigned int list_items, unsigned int screen_lines ) {
+    j->lines = j->jump_type == PERCENT 
+        ? ( j->amount * list_items ) / 100 
+        :  j->amount * screen_lines;
+}
+
+static inline unsigned int list_items( struct gui_list* list ) {
+    return list->nb_items;
+}
+
+static inline unsigned int screen_lines( struct gui_list* list ) {
+    return list->display->nb_lines;
+}
+
+static struct scroll_accel_jump* find_accel_for_list( 
+        struct gui_list* list, struct scroll_accel_jump* jump, unsigned int raw_accel ) {
+    unsigned int l_items = list_items( list );
+    unsigned int s_lines = screen_lines( list );
+
+    /* never accel in a list <= page long */
+    if( raw_accel == 0 || l_items <= s_lines ) {
+        return jump;
+    }
+
+    /* otherwise, find the highest possible accel  */        
+    calculate_jump_lines( jump + raw_accel, l_items, s_lines );
+
+    while( raw_accel > 1 ) {
+        calculate_jump_lines( jump + raw_accel - 1, l_items, s_lines );
+        if( jump[ raw_accel ].lines > jump[ raw_accel - 1 ].lines ) break;
+        --raw_accel;
+    }
+    return jump + raw_accel;
+}
+
+
+/* public functions declared in header */
+/* these next two really belong in list.c */
+void gui_synclist_select_forward_n_lines( struct gui_synclist* lists, unsigned int lines )
+{
+    int i;
+    FOR_NB_SCREENS(i)
+        gui_list_select_next_page(&(lists->gui_list[i]), lines );
+}
+
+void gui_synclist_select_back_n_lines( struct gui_synclist* lists, unsigned int lines )
+{
+    int i;
+    FOR_NB_SCREENS(i)
+        gui_list_select_previous_page(&(lists->gui_list[i]), lines);
+}
+
+
+/* this goes away in production, I think */
+static int get_ipod_scroll_wheel_acceration_and_cps( int* speed ) {
+#ifdef SIMULATOR
+	int cps = 4;
+#else
+    int cps = get_ipod_scroll_wheel_clicks_per_second();
+#endif
+    *speed = cps;
+    unsigned int acps = cps < 0 ? -cps : cps;
+    int a =  acps < global_settings.ipod_scroll_wheel_acceleration_fast
+        ? 0
+        : ( acps < global_settings.ipod_scroll_wheel_acceleration_faster 
+        ? 1
+        : ( acps < global_settings.ipod_scroll_wheel_acceleration_fastest
+        ? 2
+        : 3 ) );
+#ifdef ROCKBOX_HAS_LOGF
+    logf( "g:%d,%d", cps, a );
+#endif
+    return a;
+}
+
+
+/* dispatch the correct synclist function depending on scroll acceleration factor */
+void gui_synclist_handle_accel( struct gui_synclist * lists, enum screen_type screen, enum list_dir dir)
+{
+    int cps;
+    struct scroll_accel_jump* jump = find_accel_for_list( 
+        &(lists->gui_list[ screen ] ), scroll_accel_jumps, get_ipod_scroll_wheel_acceration_and_cps( &cps ) );
+
+    if( jump->jump_type == NOACCEL ) {
+        if( dir == FORWARD )
+            gui_synclist_select_next( lists );
+        else
+            gui_synclist_select_previous( lists );
+    } else {
+        if( dir == FORWARD )
+            gui_synclist_select_forward_n_lines( lists, jump->lines );
+        else
+            gui_synclist_select_back_n_lines( lists, jump->lines );
+    }
+
+}
+
+ unsigned int get_ipod_scroll_wheel_acceration( void ) {
+#ifdef SIMULATOR
+	int cps = 4;
+#else
+    int cps = get_ipod_scroll_wheel_clicks_per_second();
+#endif
+
+    unsigned int acps = cps < 0 ? -cps : cps;
+    int a =  acps < global_settings.ipod_scroll_wheel_acceleration_fast
+        ? 0
+        : ( acps < global_settings.ipod_scroll_wheel_acceleration_faster 
+        ? 1
+        : ( acps < global_settings.ipod_scroll_wheel_acceleration_fastest
+        ? 2
+        : 3 ) );
+
+    return a;
+ }
+
+unsigned int get_and_display_ipod_scroll_wheel_acceration( void ) {
+    int cps;
+    int a = get_ipod_scroll_wheel_acceration_and_cps( &cps );
+    return a;
+}
+#endif
diff -U 3 -H -d -r -N -- rockbox-bleeding/apps/ipod_scroll_wheel_gui.h rockbox-bleeding-dest/apps/ipod_scroll_wheel_gui.h
--- rockbox-bleeding/apps/ipod_scroll_wheel_gui.h	1969-12-31 17:00:00.000000000 -0700
+++ rockbox-bleeding-dest/apps/ipod_scroll_wheel_gui.h	2007-04-24 16:19:31.000000000 -0600
@@ -0,0 +1,45 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ *
+ * Copyright (C) TP Diffenbach (2006)
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _IPOD_SCROLL_WHEEL_GUI_H_
+#define _IPOD_SCROLL_WHEEL_GUI_H_
+#include "config.h"
+
+#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
+#include "list.h"
+#include "screen_access.h"
+
+extern void gui_synclist_select_forward_n_lines(struct gui_synclist* lists, unsigned int lines );
+extern void gui_synclist_select_back_n_lines(struct gui_synclist* lists, unsigned int lines );
+
+enum list_dir { BACKWARD, FORWARD };
+/* dispatch the correct synclist function depending on scroll acceleration factor 
+ * may adjust the actual accelration depending on list length
+ * displays adjusted acceleration to the statusbar (if the statusbar is on, clients don't need to check)
+*/
+extern void gui_synclist_handle_accel( struct gui_synclist* lists, enum screen_type screen, enum list_dir dir);
+
+/* returns the accelreation */
+#ifndef SIMULATOR
+extern unsigned int get_ipod_scroll_wheel_acceration( void );
+#endif
+
+/* returns the accelreation and displays it to the statusbar (if the statusbar is on, clients don't need to check) */
+extern unsigned int get_and_display_ipod_scroll_wheel_acceration( void );
+
+#endif
+#endif
diff -U 3 -H -d -r -N -- rockbox-bleeding/apps/lang/english.lang rockbox-bleeding-dest/apps/lang/english.lang
--- rockbox-bleeding/apps/lang/english.lang	2007-04-22 07:02:53.000000000 -0600
+++ rockbox-bleeding-dest/apps/lang/english.lang	2007-04-24 16:19:31.000000000 -0600
@@ -10758,3 +10758,59 @@
     e200: "Wheel Light Timeout"
   </voice>
 </phrase>
+<phrase>
+  id: LANG_IPOD_SCROLL_WHEEL_SPEED
+  desc: "Ipod Scroll Wheel Acceleration By Speed" Submenu in "System" menu
+  user:
+  <source>
+    *: "Ipod Scroll Wheel Acceleration"
+  </source>
+  <dest>
+    *: "Ipod Scroll Wheel Acceleration"
+  </dest>
+  <voice>
+    *: "Ipod Scroll Wheel Acceleration"
+  </voice>
+</phrase>
+<phrase>
+  id: LANG_IPOD_SCROLL_WHEEL_FAST
+  desc: "Ipod Scroll Wheel By Speed Fast Threshold" Submenu in "Ipod Scroll Wheel Acceleration By Speed" menu
+  user:
+  <source>
+    *: "Minimum speed for 'fast' acceleration"
+  </source>
+  <dest>
+    *: "Minimum speed for 'fast' acceleration"
+  </dest>
+  <voice>
+    *: "Minimum speed for 'fast' acceleration"
+  </voice>
+</phrase>
+<phrase>
+  id: LANG_IPOD_SCROLL_WHEEL_FASTER
+  desc: "Ipod Scroll Wheel By Speed Faster Threshold" Submenu in "Ipod Scroll Wheel Acceleration By Speed" menu
+  user:
+  <source>
+    *: "Minimum speed for 'faster' acceleration"
+  </source>
+  <dest>
+    *: "Minimum speed for 'faster' acceleration"
+  </dest>
+  <voice>
+    *: "Minimum speed for 'faster' acceleration"
+  </voice>
+</phrase>
+<phrase>
+  id: LANG_IPOD_SCROLL_WHEEL_FASTEST
+  desc: "Ipod Scroll Wheel By Speed Fastest Threshold" Submenu in "Ipod Scroll Wheel Acceleration By Speed" menu
+  user:
+  <source>
+    *: "Minimum speed for 'fastest' acceleration"
+  </source>
+  <dest>
+    *: "Minimum speed for 'fastest' acceleration"
+  </dest>
+  <voice>
+    *: "Minimum speed for 'fastest' acceleration"
+  </voice>
+</phrase>
diff -U 3 -H -d -r -N -- rockbox-bleeding/apps/menus/settings_menu.c rockbox-bleeding-dest/apps/menus/settings_menu.c
--- rockbox-bleeding/apps/menus/settings_menu.c	2007-04-22 07:02:53.000000000 -0600
+++ rockbox-bleeding-dest/apps/menus/settings_menu.c	2007-04-24 16:19:31.000000000 -0600
@@ -323,6 +323,18 @@
 MENUITEM_SETTING(button_light_timeout, &global_settings.button_light_timeout, NULL);
 #endif
 
+#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
+MENUITEM_SETTING(ipod_scroll_wheel_acceleration_fast, &global_settings.ipod_scroll_wheel_acceleration_fast, NULL);
+MENUITEM_SETTING(ipod_scroll_wheel_acceleration_faster, &global_settings.ipod_scroll_wheel_acceleration_faster, NULL);
+MENUITEM_SETTING(ipod_scroll_wheel_acceleration_fastest, &global_settings.ipod_scroll_wheel_acceleration_fastest, NULL);
+
+MAKE_MENU(ipod_scroll_wheel_acceleration_menu, ID2P(LANG_IPOD_SCROLL_WHEEL_SPEED), 0, Icon_NOICON,
+          &ipod_scroll_wheel_acceleration_fast,
+          &ipod_scroll_wheel_acceleration_faster,
+          &ipod_scroll_wheel_acceleration_fastest,
+         );
+#endif
+
 MAKE_MENU(system_menu, ID2P(LANG_SYSTEM), 
           0, Icon_System_menu,
             &start_screen,
@@ -352,6 +364,9 @@
 #ifdef HAVE_BUTTON_LIGHT
             &button_light_timeout,
 #endif
+#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
+            &ipod_scroll_wheel_acceleration_menu,
+#endif
          );
 
 /*    SYSTEM MENU                  */
diff -U 3 -H -d -r -N -- rockbox-bleeding/apps/settings.h rockbox-bleeding-dest/apps/settings.h
--- rockbox-bleeding/apps/settings.h	2007-04-22 07:02:53.000000000 -0600
+++ rockbox-bleeding-dest/apps/settings.h	2007-04-24 16:28:08.000000000 -0600
@@ -707,6 +707,12 @@
 #if defined(HAVE_RTC_ALARM) && \
     (defined(HAVE_RECORDING) || CONFIG_TUNER)
     int alarm_wake_up_screen;
+ #if (CONFIG_KEYPAD == IPOD_4G_PAD) && !defined(IPOD_MINI)
+     unsigned int ipod_scroll_wheel_acceleration_fast;
+     unsigned int ipod_scroll_wheel_acceleration_faster;
+     unsigned int ipod_scroll_wheel_acceleration_fastest;
+ #endif
+  };
 #endif
     /* customizable icons */
 #ifdef HAVE_LCD_BITMAP
diff -U 3 -H -d -r -N -- rockbox-bleeding/apps/settings_list.c rockbox-bleeding-dest/apps/settings_list.c
--- rockbox-bleeding/apps/settings_list.c	2007-04-22 07:02:53.000000000 -0600
+++ rockbox-bleeding-dest/apps/settings_list.c	2007-04-24 16:19:31.000000000 -0600
@@ -714,6 +714,21 @@
         "id3 tag priority", "v2-v1,v1-v2",
         LANG_ID3_V1_FIRST, LANG_ID3_V2_FIRST, mpeg_id3_options),
 
+#if (CONFIG_KEYPAD == IPOD_4G_PAD) && !defined(IPOD_MINI)
+	INT_SETTING(0, ipod_scroll_wheel_acceleration_fast, LANG_IPOD_SCROLL_WHEEL_FAST, 135,
+                "ipod scroll wheel fast threshold in clicks/sec", UNIT_SEC,
+                5, 500, 5,
+                NULL, NULL, NULL),
+	INT_SETTING(0, ipod_scroll_wheel_acceleration_faster, LANG_IPOD_SCROLL_WHEEL_FASTER, 235,
+                "ipod scroll wheel faster threshold in clicks/sec", UNIT_SEC,
+                5, 500, 5,
+                NULL, NULL, NULL),
+	INT_SETTING(0, ipod_scroll_wheel_acceleration_fastest, LANG_IPOD_SCROLL_WHEEL_FASTEST, 400,
+                "ipod scroll wheel fastest threshold in clicks/sec", UNIT_SEC,
+                5, 500, 5,
+                NULL, NULL, NULL),
+#endif
+
 #ifdef HAVE_RECORDING
     /* recording */
     STRINGCHOICE_SETTING(0, rec_timesplit, LANG_SPLIT_TIME, 0,
diff -U 3 -H -d -r -N -- rockbox-bleeding/firmware/target/arm/ipod/button-clickwheel.c rockbox-bleeding-dest/firmware/target/arm/ipod/button-clickwheel.c
--- rockbox-bleeding/firmware/target/arm/ipod/button-clickwheel.c	2007-01-18 15:10:34.000000000 -0700
+++ rockbox-bleeding-dest/firmware/target/arm/ipod/button-clickwheel.c	2007-04-24 16:19:31.000000000 -0600
@@ -40,6 +40,10 @@
 #include "system.h"
 #include "powermgmt.h"
 
+#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
+#include "logf.h"
+#endif
+
 /* Variable to use for setting button status in interrupt handler */
 int int_btn = BUTTON_NONE;
 #ifdef HAVE_WHEEL_POSITION
@@ -47,6 +51,35 @@
     static bool send_events = true;
 #endif
 
+#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
+void ipod_4g_button_int( void );
+
+static int accumulated_wheel_scroll_delta = 0;
+unsigned long wheel_scroll_down_microsecond_tick = 0;
+unsigned long wheel_scroll_key_microsecond_tick = 0;
+unsigned long wheel_scroll_key_microsecond_tick_elapsed = 0;
+const unsigned long ONE_MILLION = 1000000;
+
+int get_accumulated_wheel_scroll_delta( void ) {
+    return accumulated_wheel_scroll_delta;
+}
+
+int get_ipod_scroll_wheel_clicks_per_second( void ) {
+    unsigned long wst = wheel_scroll_key_microsecond_tick;
+    int accum = accumulated_wheel_scroll_delta;
+    unsigned int abs_accum = accum < 0 ? -accum : accum;
+    unsigned long  wste = wheel_scroll_key_microsecond_tick_elapsed;
+    if( wste == wst ) wst = wheel_scroll_down_microsecond_tick;
+    unsigned long diff = wste - wst;
+    unsigned int r = diff ? ( ( abs_accum *  ONE_MILLION ) / diff ) : 0;
+#ifdef ROCKBOX_HAS_LOGF
+    logf( "d1,%d,%d", wst, wste );
+    logf( "d2,%d,%d,%d", diff, accum, r );
+#endif
+    return accum < 0 ? -r : r;
+}
+#endif
+
 static void opto_i2c_init(void)
 {
     int i, curr_value;
@@ -115,6 +148,21 @@
                 whl = new_wheel_value;
                 backlight_on();
                 reset_poweroff_timer();
+#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
+                if( old_wheel_value == -1 ) {
+                    /* -1 is a sentinal value, meaning there is no old value 
+                     * because the finger was lifted and thus, no key to emit
+                     */
+                    old_wheel_value = new_wheel_value;
+                    accumulated_wheel_scroll_delta = 0;
+                    wheel_scroll_down_microsecond_tick = USEC_TIMER;
+                } else {
+                    /* calculate the delta regardless of whether we'll add a key
+                     * for the use of the acceleration fucntion
+                     */
+                    /* This is for later = BUTTON_SCROLL_TOUCH;*/
+                    int wheel_delta = new_wheel_value - old_wheel_value;
+#else
                 /* The queue should have no other events when scrolling */
                 if (queue_empty(&button_queue) && old_wheel_value >= 0) {
 
@@ -122,31 +170,55 @@
                     int wheel_delta = new_wheel_value - old_wheel_value;
                     unsigned long data;
                     int wheel_keycode;
+#endif
 
                     if (wheel_delta < -48)
                         wheel_delta += 96; /* Forward wrapping case */
                     else if (wheel_delta > 48)
                         wheel_delta -= 96; /* Backward wrapping case */
 
+#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
+                   if( wheel_delta > 4 || wheel_delta < -4 ) {
+                   /* ignore anything less than a jiggle factor */
+#else
                     if (wheel_delta > 4) {
                         wheel_keycode = BUTTON_SCROLL_FWD;
                     } else if (wheel_delta < -4) {
                         wheel_keycode = BUTTON_SCROLL_BACK;
                     } else goto wheel_end;
+#endif
 
 #ifdef HAVE_WHEEL_POSITION
                     if (send_events)
 #endif
                     {
+#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
+                       if ( queue_empty(&button_queue) ) {
+                       /* only post a scroll button if the queue is empty */
+                           int wheel_keycode = wheel_delta > 0 ? BUTTON_SCROLL_FWD : BUTTON_SCROLL_BACK;
+                           unsigned long data =  (wheel_delta << 16) | new_wheel_value;
+                           wheel_scroll_key_microsecond_tick = wheel_scroll_key_microsecond_tick_elapsed;
+                           accumulated_wheel_scroll_delta = 0;
+                           queue_post(&button_queue, wheel_keycode | wheel_repeat, (void *)data);
+#else
                         data = (wheel_delta << 16) | new_wheel_value;
                         queue_post(&button_queue, wheel_keycode | wheel_repeat,
                                    data);
+#endif
                     }
 
                     if (!wheel_repeat) wheel_repeat = BUTTON_REPEAT;
                 }
+#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
+                       accumulated_wheel_scroll_delta += wheel_delta ;
+                       old_wheel_value = new_wheel_value ;
+                       wheel_scroll_key_microsecond_tick_elapsed = USEC_TIMER ;
 
+                   } else goto wheel_end ; /* not clear this is still needed, basically skips call to opto_i2c_init() */
+               }
+#else
                 old_wheel_value = new_wheel_value;
+#endif
             } else if (old_wheel_value >= 0) {
                 /* scroll wheel up */
                 old_wheel_value = -1;
diff -U 3 -H -d -r -N -- rockbox-bleeding/firmware/target/arm/ipod/button-target.h rockbox-bleeding-dest/firmware/target/arm/ipod/button-target.h
--- rockbox-bleeding/firmware/target/arm/ipod/button-target.h	2007-01-09 14:34:38.000000000 -0700
+++ rockbox-bleeding-dest/firmware/target/arm/ipod/button-target.h	2007-04-24 16:19:31.000000000 -0600
@@ -32,6 +32,21 @@
 void ipod_mini_button_int(void);
 void ipod_4g_button_int(void);
 
+#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
+extern unsigned long wheel_scroll_tick ;
+extern int get_accumulated_wheel_scroll_delta( void )  ;
+extern int get_ipod_scroll_wheel_clicks_per_second( void ) ;
+#endif
+
+/* warning to clients calling get_ipod_scroll_wheel_acceration:
+ * Calling this function may have side-effects; 
+ * this function should be called once per call to button_get
+ * or button_get_w_tmo, and results locally cached as needed.
+ * In particular, some acceleration implementations
+ * may need to reset a calculated delta when 
+ * get_ipod_scroll_wheel_acceration is called.
+ */
+
 /* iPod specific button codes */
 
 #define BUTTON_SELECT       0x00000001
