diff --git a/firmware/SOURCES b/firmware/SOURCES index f5ee7873a2..1e41e75188 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -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 diff --git a/firmware/target/arm/as3525/sansa-clipv2/button-clip.c b/firmware/target/arm/as3525/button-clip.c similarity index 62% rename from firmware/target/arm/as3525/sansa-clipv2/button-clip.c rename to firmware/target/arm/as3525/button-clip.c index 1356bfbc55..b6679ca359 100644 --- a/firmware/target/arm/as3525/sansa-clipv2/button-clip.c +++ b/firmware/target/arm/as3525/button-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; - 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) { diff --git a/firmware/target/arm/as3525/sansa-clip/button-clip.c b/firmware/target/arm/as3525/sansa-clip/button-clip.c deleted file mode 100644 index a64fddb564..0000000000 --- a/firmware/target/arm/as3525/sansa-clip/button-clip.c +++ /dev/null @@ -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; -} diff --git a/firmware/target/arm/as3525/sansa-clipzip/button-clipzip.c b/firmware/target/arm/as3525/sansa-clipzip/button-clipzip.c index 40b20cdce3..c22c5e24e9 100644 --- a/firmware/target/arm/as3525/sansa-clipzip/button-clipzip.c +++ b/firmware/target/arm/as3525/sansa-clipzip/button-clipzip.c @@ -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(); } -