On 5/8/07, Antonius Hellmann <[EMAIL PROTECTED]> wrote:
The keys definitely change the HI_INT_STAT bit6. So if someone wants to
implement key/scrollwheel interrupt handling, the bit6 in the
CPU-/COP_HI_INT_EN register should do it.

I had a go at doing this a while ago but didn't know about bit6 then.
I tried updating my patch today but haven't got my Sansa with my to
try it out. I've attached it so someone with a Sansa can try it out.

Since I haven't actually tested, there could be plenty of bugs
floating around. It does at least compile cleanly.
Index: firmware/target/arm/sandisk/sansa-e200/button-e200.c
===================================================================
--- firmware/target/arm/sandisk/sansa-e200/button-e200.c	(revision 13357)
+++ firmware/target/arm/sandisk/sansa-e200/button-e200.c	(working copy)
@@ -26,6 +26,9 @@
 static unsigned int old_wheel_value = 0;
 static unsigned int wheel_repeat = BUTTON_NONE;
 
+/* Variable to use for setting button status in interrupt handler */
+int int_btn = BUTTON_NONE;
+
 void button_init_device(void)
 {
     /* Enable all buttons */
@@ -45,16 +48,118 @@
     return (GPIOF_INPUT_VAL & 0x80)?true:false;
 }
 
+int e200_button_read(void)
+{
+    unsigned char source, wheel_source, state, wheel_state;
+    int btn = BUTTON_NONE;
+    unsigned int new_wheel_value;
+
+    /* get source(s) of interupt */
+    source = GPIOF_INT_STAT & 0xff;
+    wheel_source = GPIOH_INT_STAT & 0xc0;
+
+    if (source == 0 && wheel_source ==0) {
+        return BUTTON_NONE; /* not for us */
+    }
+
+    /* get current keypad & wheel status */
+    state = GPIOF_INPUT_VAL & 0xff;
+    wheel_state = GPIOH_INPUT_VAL & 0xc0;
+
+    /* toggle interrupt level */
+    GPIOF_INT_LEV = ~state;
+    GPIOH_INT_LEV = ~wheel_state;
+
+    /* device buttons */
+    if (!button_hold())
+    {
+        if(source)
+        {
+            /* Read normal buttons */
+            if ((state & 0x1) == 0) btn |= BUTTON_REC;
+            if ((state & 0x2) == 0) btn |= BUTTON_DOWN;
+            if ((state & 0x4) == 0) btn |= BUTTON_RIGHT;
+            if ((state & 0x8) == 0) btn |= BUTTON_LEFT;
+            if ((state & 0x10) == 0) btn |= BUTTON_SELECT; /* The centre button */
+            if ((state & 0x20) == 0) btn |= BUTTON_UP; /* The "play" button */
+            if ((state & 0x40) != 0) btn |= BUTTON_POWER;
+        }
+        
+        /* Read scrollwheel */
+        if (wheel_source)
+        {
+            new_wheel_value = GPIOH_INPUT_VAL & 0xc0;
+            switch(new_wheel_value){
+            case 0x00:
+                if(old_wheel_value==0x80)
+                    btn |= BUTTON_SCROLL_UP;
+                else if (old_wheel_value==0x40)
+                    btn |= BUTTON_SCROLL_DOWN;
+                break;
+            case 0x40:
+                if(old_wheel_value==0x00)
+                    btn |= BUTTON_SCROLL_UP;
+                else if (old_wheel_value==0xc0)
+                    btn |= BUTTON_SCROLL_DOWN;
+                break;
+            case 0x80:
+                if(old_wheel_value==0xc0)
+                    btn |= BUTTON_SCROLL_UP;
+                else if (old_wheel_value==0x00)
+                    btn |= BUTTON_SCROLL_DOWN;
+                break;
+            case 0xc0:
+                if(old_wheel_value==0x40)
+                    btn |= BUTTON_SCROLL_UP;
+                else if (old_wheel_value==0x80)
+                    btn |= BUTTON_SCROLL_DOWN;
+                break;
+            }
+            
+            if(wheel_repeat == BUTTON_NONE){
+                if(btn & BUTTON_SCROLL_UP)
+                    wheel_repeat = BUTTON_SCROLL_UP;
+                
+                if(btn & BUTTON_SCROLL_DOWN)
+                    wheel_repeat = BUTTON_SCROLL_DOWN;
+            } else if (wheel_repeat == BUTTON_SCROLL_UP)  {
+                btn |= BUTTON_SCROLL_UP;
+                wheel_repeat = BUTTON_NONE;
+            } else if (wheel_repeat == BUTTON_SCROLL_DOWN) {
+                btn |= BUTTON_SCROLL_DOWN;
+                wheel_repeat = BUTTON_NONE;
+            }
+            
+            old_wheel_value = new_wheel_value;
+        }
+    }
+
+    /* ack any active interrupts */
+    if (source)
+        GPIOF_INT_CLR = source;
+    if (wheel_source)
+        GPIOH_INT_CLR = wheel_source;
+
+    return btn;
+}
+
 /*
+ * Respond to interrupt
+ */
+void button_int(void)
+{
+    CPU_HI_INT_CLR = 0x40;
+    int_btn = e200_button_read();
+    CPU_HI_INT_EN = 0x40;
+}
+
+/*
  * Get button pressed from hardware
  */
 int button_read_device(void)
 {
-    int btn = BUTTON_NONE;
-    unsigned char state;
     static bool hold_button = false;
     bool hold_button_old;
-    unsigned int new_wheel_value = 0; /* read later, but this stops a warning */
 
     /* Hold */
     hold_button_old = hold_button;
@@ -68,83 +173,13 @@
     }
 #endif
 
-    /* device buttons */
-    if (!hold_button)
-    {
-        /* Read normal buttons */
-        state = GPIOF_INPUT_VAL & 0xff;
-        if ((state & 0x1) == 0) btn |= BUTTON_REC;
-        if ((state & 0x2) == 0) btn |= BUTTON_DOWN;
-        if ((state & 0x4) == 0) btn |= BUTTON_RIGHT;
-        if ((state & 0x8) == 0) btn |= BUTTON_LEFT;
-        if ((state & 0x10) == 0) btn |= BUTTON_SELECT; /* The centre button */
-        if ((state & 0x20) == 0) btn |= BUTTON_UP; /* The "play" button */
-        if ((state & 0x40) != 0) btn |= BUTTON_POWER;
-        
-        /* Read wheel 
-         * Bits 6 and 7 of GPIOH change as follows:
-         * Clockwise rotation   01 -> 00 -> 10 -> 11
-         * Counter-clockwise    11 -> 10 -> 00 -> 01
-         *
-         * This is equivalent to wheel_value of:
-         * Clockwise rotation   0x40 -> 0x00 -> 0x80 -> 0xc0
-         * Counter-clockwise    0xc0 -> 0x80 -> 0x00 -> 0x40
-         */
-        new_wheel_value = GPIOH_INPUT_VAL & 0xc0;
-        switch(new_wheel_value){
-        case 0x00:
-            if(old_wheel_value==0x80)
-                btn |= BUTTON_SCROLL_UP;
-            else if (old_wheel_value==0x40)
-                btn |= BUTTON_SCROLL_DOWN;
-            break;
-        case 0x40:
-            if(old_wheel_value==0x00)
-                btn |= BUTTON_SCROLL_UP;
-            else if (old_wheel_value==0xc0)
-                btn |= BUTTON_SCROLL_DOWN;
-            break;
-        case 0x80:
-            if(old_wheel_value==0xc0)
-                btn |= BUTTON_SCROLL_UP;
-            else if (old_wheel_value==0x00)
-                btn |= BUTTON_SCROLL_DOWN;
-            break;
-        case 0xc0:
-            if(old_wheel_value==0x40)
-                btn |= BUTTON_SCROLL_UP;
-            else if (old_wheel_value==0x80)
-                btn |= BUTTON_SCROLL_DOWN;
-            break;
-        }
-        
-        if(wheel_repeat == BUTTON_NONE){
-            if(btn & BUTTON_SCROLL_UP)
-                wheel_repeat = BUTTON_SCROLL_UP;
-            
-            if(btn & BUTTON_SCROLL_DOWN)
-                wheel_repeat = BUTTON_SCROLL_DOWN;
-        } else if (wheel_repeat == BUTTON_SCROLL_UP)  {
-            btn |= BUTTON_SCROLL_UP;
-            wheel_repeat = BUTTON_NONE;
-        } else if (wheel_repeat == BUTTON_SCROLL_DOWN) {
-            btn |= BUTTON_SCROLL_DOWN;
-            wheel_repeat = BUTTON_NONE;
-        }
-        
-        old_wheel_value = new_wheel_value;
-    }
-    
-    if( (btn & BUTTON_SCROLL_UP) || (btn & BUTTON_SCROLL_DOWN) ){
-        /* only trigger once per click */
-        if ((new_wheel_value == 0x00) || (new_wheel_value == 0xc0))
-        {
-            btn = btn&(~(BUTTON_SCROLL_UP|BUTTON_SCROLL_DOWN));
-        }
+
+    if( (int_btn & BUTTON_SCROLL_UP) || (int_btn & BUTTON_SCROLL_DOWN) ){
 #ifndef BOOTLOADER
         button_backlight_on();
 #endif
     }
-    
-    return btn;
+
+   /* The int_btn variable is set in the button interrupt handler */
+    return int_btn;
 }
Index: firmware/target/arm/sandisk/sansa-e200/button-target.h
===================================================================
--- firmware/target/arm/sandisk/sansa-e200/button-target.h	(revision 13357)
+++ firmware/target/arm/sandisk/sansa-e200/button-target.h	(working copy)
@@ -28,6 +28,7 @@
 bool button_hold(void);
 void button_init_device(void);
 int button_read_device(void);
+void button_int(void);
 
 /* Sandisk Sansa E200 button codes */
 
Index: firmware/target/arm/system-pp502x.c
===================================================================
--- firmware/target/arm/system-pp502x.c	(revision 13357)
+++ firmware/target/arm/system-pp502x.c	(working copy)
@@ -64,6 +64,8 @@
             TIMER1();
         else if (CPU_INT_STAT & TIMER2_MASK)
             TIMER2();
+        else if (HI_INT_STAT & 0x40)
+            button_int();
     } else {
         if (COP_INT_STAT & TIMER1_MASK)
             TIMER1();

Reply via email to