All pastes #280241 Raw Edit

e200 button int

public text v1 · immutable
·published 2006-12-15 19:21 UTC
rendered paste body
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id: button-e200.c,v 1.2 2006-10-16 00:18:49 dan_a Exp $
 *
 * Copyright (C) 2006 by Barry Wardell
 *
 * 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.
 *
 ****************************************************************************/

/* Taken from button-h10.c by Barry Wardell and reverse engineering by MrH. */

#include <stdlib.h>
#include "config.h"
#include "cpu.h"
#include "system.h"
#include "button.h"
#include "kernel.h"
#include "backlight.h"
#include "system.h"

static unsigned int old_wheel_value = 0;
int int_btn = BUTTON_NONE;
static bool hold_button = false;
static unsigned int wheel_repeat = BUTTON_NONE;

static int e200_button_read(void)
{
    unsigned char source, wheel_source, state, wheel_state;
    int btn = BUTTON_NONE;
    
    /* 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 (!hold_button)
    {
        /* 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 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
         */
        switch(wheel_state){
        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 = wheel_state;
    }

    /* ack any active interrupts */
    if (source)
        GPIOF_INT_CLR = source;
    if (wheel_source)
        GPIOH_INT_CLR = wheel_source;

    return btn;
}

void e200_button_int(void)
{
    CPU_HI_INT_CLR = GPIO_MASK;
    int_btn = e200_button_read();
    //CPU_INT_EN = 0x40000000;
    CPU_HI_INT_EN = GPIO_MASK;
}

void button_init_device(void)
{
    /* Enable all buttons except the wheel */
    GPIOF_ENABLE |= 0xff;
    
    /* Enable scroll wheel */
    GPIOH_ENABLE |= 0xc0;
    
    /* buttons - set interrupt levels */
    GPIOF_INT_LEV = ~(GPIOF_INPUT_VAL & 0xff);
    GPIOF_INT_CLR = GPIOF_INT_STAT & 0xff;
    
    /* scroll wheel - set interrupt levels */
    GPIOH_INT_LEV = ~(GPIOH_INPUT_VAL & 0xc0);
    GPIOH_INT_CLR = GPIOH_INT_STAT & 0xc0;
    
    /* enable interrupts */
    GPIOF_INT_EN = 0xff;
    GPIOH_INT_EN = 0xc0;
    
    /* unmask interrupt */
    CPU_INT_EN = 0x40000000;
    CPU_HI_INT_EN = GPIO_MASK;
    
    /* Read initial wheel value (bit 6-7 of GPIOH) */
    old_wheel_value = GPIOH_INPUT_VAL & 0xc0;
}

/*
 * Get button pressed from hardware
 */
int button_read_device(void)
{
    bool hold_button_old;

    /* Hold */
    hold_button_old = hold_button;
    hold_button = button_hold();

#if 0
#ifndef BOOTLOADER
    /* light handling */
    if (hold_button != hold_button_old)
    {
        backlight_hold_changed(hold_button);
    }
#endif
#endif

    /* The int_btn variable is set in the button interrupt handler */
    return int_btn;
}

bool button_hold(void)
{
    return (GPIOF_INPUT_VAL & 0x80)?true:false;
}