Sansa Clip: simplify matrix key scan
Merge clipv1/clipv2 code since they use the same 3x3 matrix clipzip keyscan buttons now work in bootloader clipplus untouched (no matrix) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31235 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
744adcba81
commit
dfff88562e
4 changed files with 84 additions and 288 deletions
|
@ -1418,7 +1418,7 @@ target/arm/as3525/tuner-as3525v2.c
|
|||
#ifndef SIMULATOR
|
||||
target/arm/as3525/lcd-ssd1303.c
|
||||
target/arm/as3525/sansa-clipv2/lcd-clipv2.c
|
||||
target/arm/as3525/sansa-clipv2/button-clip.c
|
||||
target/arm/as3525/button-clip.c
|
||||
target/arm/as3525/sansa-clipv2/backlight-clipv2.c
|
||||
#ifndef BOOTLOADER
|
||||
target/arm/powermgmt-ascodec.c
|
||||
|
@ -1432,7 +1432,7 @@ target/arm/as3525/sansa-clipv2/lcd-as-clipv2.S
|
|||
#ifndef SIMULATOR
|
||||
target/arm/as3525/lcd-ssd1303.c
|
||||
target/arm/as3525/sansa-clip/lcd-clip.c
|
||||
target/arm/as3525/sansa-clip/button-clip.c
|
||||
target/arm/as3525/button-clip.c
|
||||
#ifndef BOOTLOADER
|
||||
target/arm/powermgmt-ascodec.c
|
||||
target/arm/as3525/sansa-clip/powermgmt-clip.c
|
||||
|
|
|
@ -27,14 +27,37 @@
|
|||
#include "backlight.h"
|
||||
#endif
|
||||
|
||||
#if defined(SANSA_CLIP)
|
||||
# define OUT_PIN GPIOC_PIN
|
||||
# define OUT_DIR GPIOC_DIR
|
||||
# define OUT_INITIAL 0
|
||||
# define IN_PIN GPIOB_PIN
|
||||
# define IN_DIR GPIOB_DIR
|
||||
#elif defined(SANSA_CLIPV2)
|
||||
# define OUT_PIN GPIOD_PIN
|
||||
# define OUT_DIR GPIOD_DIR
|
||||
# define OUT_INITIAL 1
|
||||
# define IN_PIN GPIOD_PIN
|
||||
# define IN_DIR GPIOD_DIR
|
||||
#endif
|
||||
|
||||
static const int rows[3] = {
|
||||
#if defined(SANSA_CLIP)
|
||||
4, 5, 6
|
||||
#elif defined(SANSA_CLIPV2)
|
||||
5, 6, 4
|
||||
#endif
|
||||
};
|
||||
|
||||
void button_init_device(void)
|
||||
{
|
||||
GPIOA_DIR &= ~((1<<7) | (1<<3));
|
||||
GPIOD_DIR &= ~((1<<2) | (1<<1) | (1<<0));
|
||||
GPIOD_PIN(3) = 1<<3;
|
||||
GPIOD_PIN(4) = 1<<4;
|
||||
GPIOD_PIN(5) = 1<<5;
|
||||
GPIOD_DIR |= ((1<<5) | (1<<4) | (1<<3));
|
||||
IN_DIR &= ~((1<<2) | (1<<1) | (1<<0));
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
OUT_PIN(rows[i]) = OUT_INITIAL << rows[i];
|
||||
OUT_DIR |= 1 << rows[i];
|
||||
}
|
||||
|
||||
/* get initial readings */
|
||||
button_read_device();
|
||||
|
@ -44,9 +67,8 @@ void button_init_device(void)
|
|||
|
||||
int button_read_device(void)
|
||||
{
|
||||
static int row = 0;
|
||||
static int buttons = 0;
|
||||
static unsigned power_counter = 0;
|
||||
static int row, buttons;
|
||||
static unsigned power_counter;
|
||||
|
||||
if(button_hold())
|
||||
{
|
||||
|
@ -66,84 +88,47 @@ int button_read_device(void)
|
|||
else
|
||||
buttons &= ~BUTTON_POWER;
|
||||
|
||||
/* This is a keypad using D3-D5 as columns and D0-D2 as rows */
|
||||
switch (row) {
|
||||
static const int matrix [3][3] = {
|
||||
{ 0 /*unused*/, BUTTON_VOL_UP, BUTTON_UP },
|
||||
{ BUTTON_LEFT, BUTTON_SELECT, BUTTON_RIGHT },
|
||||
{ BUTTON_DOWN, BUTTON_VOL_DOWN, BUTTON_HOME },
|
||||
};
|
||||
|
||||
case 0:
|
||||
buttons &= ~(BUTTON_VOL_UP | BUTTON_UP);
|
||||
for (int i = 0; i<3; i++)
|
||||
if (IN_PIN(i))
|
||||
buttons |= matrix[row][i];
|
||||
else
|
||||
buttons &= ~matrix[row][i];
|
||||
|
||||
(void)GPIOD_PIN(0); /* D3D0 is unused */
|
||||
|
||||
if (!GPIOD_PIN(1))
|
||||
buttons |= BUTTON_VOL_UP;
|
||||
|
||||
if (!GPIOD_PIN(2))
|
||||
buttons |= BUTTON_UP;
|
||||
|
||||
GPIOD_PIN(3) = 1<<3;
|
||||
GPIOD_PIN(4) = 0x00;
|
||||
/* prepare next row */
|
||||
OUT_PIN(rows[row]) = 0 << rows[row];
|
||||
row++;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
buttons &= ~(BUTTON_LEFT | BUTTON_SELECT | BUTTON_RIGHT);
|
||||
|
||||
if (!GPIOD_PIN(0))
|
||||
buttons |= BUTTON_LEFT;
|
||||
|
||||
if (!GPIOD_PIN(1))
|
||||
buttons |= BUTTON_SELECT;
|
||||
|
||||
if (!GPIOD_PIN(2))
|
||||
buttons |= BUTTON_RIGHT;
|
||||
|
||||
GPIOD_PIN(4) = 1<<4;
|
||||
GPIOD_PIN(5) = 0x00;
|
||||
row++;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
buttons &= ~(BUTTON_DOWN | BUTTON_VOL_DOWN | BUTTON_HOME);
|
||||
|
||||
if (!GPIOD_PIN(0))
|
||||
buttons |= BUTTON_DOWN;
|
||||
|
||||
if (!GPIOD_PIN(1))
|
||||
buttons |= BUTTON_VOL_DOWN;
|
||||
|
||||
if (!GPIOD_PIN(2))
|
||||
buttons |= BUTTON_HOME;
|
||||
|
||||
GPIOD_PIN(5) = 1<<5;
|
||||
GPIOD_PIN(3) = 0x00;
|
||||
|
||||
default:
|
||||
row = 0;
|
||||
break;
|
||||
}
|
||||
row %= 3;
|
||||
OUT_PIN(rows[row]) = 1 << rows[row];
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
bool button_hold(void)
|
||||
{
|
||||
#ifndef BOOTLOADER
|
||||
static bool hold_button_old = false;
|
||||
#endif
|
||||
|
||||
#ifdef SANSA_CLIPV2
|
||||
GPIOA_DIR |= 1<<7;
|
||||
GPIOA_PIN(7) = 1<<7;
|
||||
|
||||
int delay = 50;
|
||||
while(delay--)
|
||||
asm("nop");
|
||||
#endif
|
||||
|
||||
bool hold_button = (GPIOA_PIN(3) != 0);
|
||||
|
||||
#ifdef SANSA_CLIPV2
|
||||
GPIOA_PIN(7) = 0;
|
||||
GPIOA_DIR &= ~(1<<7);
|
||||
#endif
|
||||
|
||||
#ifndef BOOTLOADER
|
||||
static bool hold_button_old = false;
|
||||
/* light handling */
|
||||
if (hold_button != hold_button_old)
|
||||
{
|
|
@ -1,156 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2009 Bertrik Sikken
|
||||
* Copyright (C) 2008 François Dinel
|
||||
* Copyright (C) 2008 Rafaël Carré
|
||||
*
|
||||
* 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 "system.h"
|
||||
#include "button-target.h"
|
||||
#include "as3525.h"
|
||||
#ifndef BOOTLOADER /* backlight on hold handling */
|
||||
#include "backlight.h"
|
||||
#endif
|
||||
|
||||
/* The Sansa Clip uses a button matrix that is scanned by selecting one of
|
||||
three rows and reading back the button states from the columns.
|
||||
|
||||
In this driver, the row is changed at each call (i.e. once per tick).
|
||||
In one tick, column data from one row is read back and then the next row
|
||||
is selected for the following tick. This mechanism ensures that there is
|
||||
plenty time between selecting a row and reading the columns, avoiding the
|
||||
need for explicit delays.
|
||||
*/
|
||||
|
||||
|
||||
void button_init_device(void)
|
||||
{
|
||||
GPIOA_DIR &= ~((1<<7) | (1<<3));
|
||||
GPIOB_DIR &= ~((1<<2) | (1<<1) | (1<<0));
|
||||
GPIOC_PIN(4) = 0;
|
||||
GPIOC_PIN(5) = 0;
|
||||
GPIOC_PIN(6) = 0;
|
||||
GPIOC_DIR |= ((1<<6) | (1<<5) | (1<<4));
|
||||
|
||||
/* get initial readings */
|
||||
button_read_device();
|
||||
button_read_device();
|
||||
button_read_device();
|
||||
}
|
||||
|
||||
int button_read_device(void)
|
||||
{
|
||||
static int row = 0;
|
||||
static int buttons = 0;
|
||||
static unsigned power_counter = 0;
|
||||
|
||||
if(button_hold())
|
||||
{
|
||||
power_counter = HZ;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* direct GPIO connections */
|
||||
/* read power, but not if hold button was just released, since
|
||||
* you basically always hit power due to the slider mechanism after
|
||||
* releasing hold (wait 1 sec) */
|
||||
if (power_counter)
|
||||
power_counter--;
|
||||
|
||||
if (GPIOA_PIN(7) && !power_counter)
|
||||
buttons |= BUTTON_POWER;
|
||||
else
|
||||
buttons &= ~BUTTON_POWER;
|
||||
|
||||
/* This is a keypad using C4-C6 as columns and B0-B2 as rows */
|
||||
switch (row) {
|
||||
|
||||
case 0:
|
||||
buttons &= ~(BUTTON_VOL_UP | BUTTON_UP);
|
||||
|
||||
(void)GPIOB_PIN(0); /* C4B0 is unused */
|
||||
|
||||
if (GPIOB_PIN(1))
|
||||
buttons |= BUTTON_VOL_UP;
|
||||
|
||||
if (GPIOB_PIN(2))
|
||||
buttons |= BUTTON_UP;
|
||||
|
||||
GPIOC_PIN(4) = 0;
|
||||
GPIOC_PIN(5) = (1<<5);
|
||||
row++;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
buttons &= ~(BUTTON_LEFT | BUTTON_SELECT | BUTTON_RIGHT);
|
||||
|
||||
if (GPIOB_PIN(0))
|
||||
buttons |= BUTTON_LEFT;
|
||||
|
||||
if (GPIOB_PIN(1))
|
||||
buttons |= BUTTON_SELECT;
|
||||
|
||||
if (GPIOB_PIN(2))
|
||||
buttons |= BUTTON_RIGHT;
|
||||
|
||||
GPIOC_PIN(5) = 0;
|
||||
GPIOC_PIN(6) = (1<<6);
|
||||
row++;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
buttons &= ~(BUTTON_DOWN | BUTTON_VOL_DOWN | BUTTON_HOME);
|
||||
|
||||
if (GPIOB_PIN(0))
|
||||
buttons |= BUTTON_DOWN;
|
||||
|
||||
if (GPIOB_PIN(1))
|
||||
buttons |= BUTTON_VOL_DOWN;
|
||||
|
||||
if (GPIOB_PIN(2))
|
||||
buttons |= BUTTON_HOME;
|
||||
|
||||
GPIOC_PIN(6) = 0;
|
||||
GPIOC_PIN(4) = (1<<4);
|
||||
|
||||
default:
|
||||
row = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
bool button_hold(void)
|
||||
{
|
||||
bool hold_button = (GPIOA_PIN(3) != 0);
|
||||
|
||||
#ifndef BOOTLOADER
|
||||
/* backlight handling */
|
||||
|
||||
static bool hold_button_old = false;
|
||||
|
||||
if (hold_button != hold_button_old)
|
||||
{
|
||||
hold_button_old = hold_button;
|
||||
backlight_hold_changed(hold_button);
|
||||
}
|
||||
#endif /* BOOTLOADER */
|
||||
|
||||
return hold_button;
|
||||
}
|
|
@ -21,61 +21,33 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "button-target.h"
|
||||
#include "as3525v2.h"
|
||||
#include "system.h"
|
||||
#include "kernel.h"
|
||||
#include "system-target.h"
|
||||
|
||||
static int keyscan(void)
|
||||
{
|
||||
static int buttons = 0;
|
||||
static int row = 1;
|
||||
static int buttons, row;
|
||||
static const int matrix[2][3] = {
|
||||
{ BUTTON_RIGHT, BUTTON_SELECT, BUTTON_UP },
|
||||
{ BUTTON_HOME, BUTTON_DOWN, BUTTON_LEFT },
|
||||
};
|
||||
|
||||
switch (row) {
|
||||
for (int i = 0; i < 3; i++)
|
||||
if (GPIOC_PIN(3 + i))
|
||||
buttons |= matrix[row][i];
|
||||
else
|
||||
buttons &= ~matrix[row][i];
|
||||
|
||||
case 1:
|
||||
/* read row 1 */
|
||||
buttons &= ~(BUTTON_RIGHT | BUTTON_SELECT | BUTTON_UP);
|
||||
if (GPIOC_PIN(3)) {
|
||||
buttons |= BUTTON_RIGHT;
|
||||
}
|
||||
if (GPIOC_PIN(4)) {
|
||||
buttons |= BUTTON_SELECT;
|
||||
}
|
||||
if (GPIOC_PIN(5)) {
|
||||
buttons |= BUTTON_UP;
|
||||
}
|
||||
/* prepare next row */
|
||||
GPIOC_PIN(1) = row << 1;
|
||||
row ^= 1;
|
||||
GPIOC_PIN(2) = row << 2;
|
||||
|
||||
/* prepare row 2 */
|
||||
GPIOC_PIN(1) = 0;
|
||||
GPIOC_PIN(2) = (1 << 2);
|
||||
row = 2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* read row 2 */
|
||||
buttons &= ~(BUTTON_HOME | BUTTON_DOWN | BUTTON_LEFT);
|
||||
if (GPIOC_PIN(3)) {
|
||||
buttons |= BUTTON_HOME;
|
||||
}
|
||||
if (GPIOC_PIN(4)) {
|
||||
buttons |= BUTTON_DOWN;
|
||||
}
|
||||
if (GPIOC_PIN(5)) {
|
||||
buttons |= BUTTON_LEFT;
|
||||
}
|
||||
|
||||
/* prepare row 1 */
|
||||
GPIOC_PIN(1) = (1 << 1);
|
||||
GPIOC_PIN(2) = 0;
|
||||
row = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
row = 1;
|
||||
break;
|
||||
}
|
||||
/* delay a bit if interrupts are disabled, to be sure next row will read */
|
||||
if (!irq_enabled())
|
||||
for (volatile int i = 0; i < 0x500; i++) ;
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
@ -83,35 +55,30 @@ static int keyscan(void)
|
|||
void button_init_device(void)
|
||||
{
|
||||
/* GPIO A6, A7 and D6 are direct button inputs */
|
||||
GPIOA_DIR &= ~(1 << 6);
|
||||
GPIOA_DIR &= ~(1 << 7);
|
||||
GPIOA_DIR &= ~(1 << 6 | 1<< 7);
|
||||
GPIOD_DIR &= ~(1 << 6);
|
||||
|
||||
/* GPIO C1, C2, C3, C4, C5 are used in a column/row key scan matrix */
|
||||
GPIOC_DIR |= ((1 << 1) | (1 << 2));
|
||||
GPIOC_DIR &= ~((1 << 3) | (1 << 4) | (1 << 5));
|
||||
|
||||
/* initial reading */
|
||||
button_read_device();
|
||||
sleep(1);
|
||||
button_read_device();
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
int button_read_device(void)
|
||||
{
|
||||
int buttons = 0;
|
||||
|
||||
/* power */
|
||||
if (GPIOD_PIN(6)) {
|
||||
if (GPIOD_PIN(6))
|
||||
buttons |= BUTTON_POWER;
|
||||
}
|
||||
|
||||
/* volume */
|
||||
if (GPIOA_PIN(6)) {
|
||||
if (GPIOA_PIN(6))
|
||||
buttons |= BUTTON_VOL_DOWN;
|
||||
}
|
||||
if (GPIOA_PIN(7)) {
|
||||
if (GPIOA_PIN(7))
|
||||
buttons |= BUTTON_VOL_UP;
|
||||
}
|
||||
|
||||
/* keyscan buttons */
|
||||
buttons |= keyscan();
|
||||
|
||||
return buttons;
|
||||
return buttons | keyscan();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue