rockbox/firmware/target/arm/ipod/button-mini1g.c
Daniel Stenberg 2acc0ac542 Updated our source code header to explicitly mention that we are GPL v2 or
later. We still need to hunt down snippets used that are not. 1324 modified
files...
http://www.rockbox.org/mail/archive/rockbox-dev-archive-2008-06/0060.shtml


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17847 a1c6a512-1295-4272-9138-f99709370657
2008-06-28 18:10:04 +00:00

212 lines
5.9 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Daniel Stenberg
*
* iPod driver based on code from the ipodlinux project - http://ipodlinux.org
* Adapted for Rockbox in December 2005
* Original file: linux/arch/armnommu/mach-ipod/keyboard.c
* Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org)
*
*
* 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.
*
****************************************************************************/
/*
* Rockbox button functions
*/
#include <stdlib.h>
#include "config.h"
#include "cpu.h"
#include "system.h"
#include "button.h"
#include "kernel.h"
#include "backlight.h"
#include "adc.h"
#include "serial.h"
#include "power.h"
#include "system.h"
#include "powermgmt.h"
/* Variable to use for setting button status in interrupt handler */
int int_btn = BUTTON_NONE;
#ifdef HAVE_WHEEL_POSITION
static int wheel_position = -1;
static bool send_events = true;
#endif
static void handle_scroll_wheel(int new_scroll, int was_hold)
{
int wheel_keycode = BUTTON_NONE;
static int prev_scroll = -1;
static int direction = 0;
static int count = 0;
static int scroll_state[4][4] = {
{0, 1, -1, 0},
{-1, 0, 0, 1},
{1, 0, 0, -1},
{0, -1, 1, 0}
};
if ( prev_scroll == -1 ) {
prev_scroll = new_scroll;
}
else if (direction != scroll_state[prev_scroll][new_scroll]) {
direction = scroll_state[prev_scroll][new_scroll];
count = 0;
}
else if (!was_hold) {
backlight_on();
reset_poweroff_timer();
if (++count == 6) { /* reduce sensitivity */
count = 0;
/* Mini 1st Gen wheel has inverse direction mapping
* compared to 1st..3rd Gen wheel. */
switch (direction) {
case 1:
wheel_keycode = BUTTON_SCROLL_FWD;
break;
case -1:
wheel_keycode = BUTTON_SCROLL_BACK;
break;
default:
/* only happens if we get out of sync */
break;
}
}
}
if (wheel_keycode != BUTTON_NONE && queue_empty(&button_queue))
queue_post(&button_queue, wheel_keycode, 0);
prev_scroll = new_scroll;
}
/* mini 1 only, mini 2G uses iPod 4G code */
static int ipod_mini_button_read(void)
{
unsigned char source, wheel_source, state, wheel_state;
static bool was_hold = false;
int btn = BUTTON_NONE;
/* The ipodlinux source had a udelay(250) here, but testing has shown that
it is not needed - tested on mini 1g. */
/* udelay(250);*/
/* get source(s) of interupt */
source = GPIOA_INT_STAT & 0x3f;
wheel_source = GPIOB_INT_STAT & 0x30;
if (source == 0 && wheel_source == 0) {
return BUTTON_NONE; /* not for us */
}
/* get current keypad & wheel status */
state = GPIOA_INPUT_VAL & 0x3f;
wheel_state = GPIOB_INPUT_VAL & 0x30;
/* toggle interrupt level */
GPIOA_INT_LEV = ~state;
GPIOB_INT_LEV = ~wheel_state;
/* hold switch causes all outputs to go low */
/* we shouldn't interpret these as key presses */
if ((state & 0x20)) {
if (!(state & 0x1))
btn |= BUTTON_SELECT;
if (!(state & 0x2))
btn |= BUTTON_MENU;
if (!(state & 0x4))
btn |= BUTTON_PLAY;
if (!(state & 0x8))
btn |= BUTTON_RIGHT;
if (!(state & 0x10))
btn |= BUTTON_LEFT;
if (wheel_source & 0x30) {
handle_scroll_wheel((wheel_state & 0x30) >> 4, was_hold);
}
}
was_hold = button_hold();
/* ack any active interrupts */
if (source)
GPIOA_INT_CLR = source;
if (wheel_source)
GPIOB_INT_CLR = wheel_source;
return btn;
}
void ipod_mini_button_int(void)
{
CPU_HI_INT_DIS = GPIO0_MASK;
int_btn = ipod_mini_button_read();
//CPU_INT_EN = 0x40000000;
CPU_HI_INT_EN = GPIO0_MASK;
}
void button_init_device(void)
{
/* iPod Mini G1 */
/* buttons - enable as input */
GPIOA_ENABLE |= 0x3f;
GPIOA_OUTPUT_EN &= ~0x3f;
/* scroll wheel- enable as input */
GPIOB_ENABLE |= 0x30; /* port b 4,5 */
GPIOB_OUTPUT_EN &= ~0x30; /* port b 4,5 */
/* buttons - set interrupt levels */
GPIOA_INT_LEV = ~(GPIOA_INPUT_VAL & 0x3f);
GPIOA_INT_CLR = GPIOA_INT_STAT & 0x3f;
/* scroll wheel - set interrupt levels */
GPIOB_INT_LEV = ~(GPIOB_INPUT_VAL & 0x30);
GPIOB_INT_CLR = GPIOB_INT_STAT & 0x30;
/* enable interrupts */
GPIOA_INT_EN = 0x3f;
GPIOB_INT_EN = 0x30;
/* unmask interrupt */
CPU_INT_EN = 0x40000000;
CPU_HI_INT_EN = GPIO0_MASK;
}
/*
* Get button pressed from hardware
*/
int button_read_device(void)
{
static bool hold_button = false;
bool hold_button_old;
/* normal buttons */
hold_button_old = hold_button;
hold_button = button_hold();
if (hold_button != hold_button_old)
backlight_hold_changed(hold_button);
/* The int_btn variable is set in the button interrupt handler */
return int_btn;
}
bool button_hold(void)
{
return (GPIOA_INPUT_VAL & 0x20)?false:true;
}
bool headphones_inserted(void)
{
return (GPIOA_INPUT_VAL & 0x80)?true:false;
}