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:
Rafaël Carré 2011-12-13 23:12:21 +00:00
parent 744adcba81
commit dfff88562e
4 changed files with 84 additions and 288 deletions

View file

@ -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

View file

@ -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;
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;
}
/* prepare next row */
OUT_PIN(rows[row]) = 0 << rows[row];
row++;
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)
{

View file

@ -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;
}

View file

@ -21,97 +21,64 @@
****************************************************************************/
#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) {
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 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;
for (int i = 0; i < 3; i++)
if (GPIOC_PIN(3 + i))
buttons |= matrix[row][i];
else
buttons &= ~matrix[row][i];
/* prepare next row */
GPIOC_PIN(1) = row << 1;
row ^= 1;
GPIOC_PIN(2) = row << 2;
/* 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++) ;
default:
row = 1;
break;
}
return buttons;
}
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();
}