Finally commit FS#5111 - piezo clicker for ipods!

Origional implementation by Robert Keevil with contributions from Frederik Vestre,  Stoyan Stratev, Craig Elliott, Michael Sparmann,  Thomas Schott, Rosso Maltese, and syncs from a bunch of other people!

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30995 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Jonathan Gordon 2011-11-16 10:25:43 +00:00
parent b7508a766d
commit be716c0be8
20 changed files with 481 additions and 2 deletions

View File

@ -270,3 +270,7 @@ recording_digital
#if MEMORYSIZE <= 2
lowmem
#endif
#if defined(HAVE_HARDWARE_CLICK)
hardware_click
#endif

View File

@ -12917,3 +12917,37 @@
*: "Shortcuts"
</voice>
</phrase>
<phrase>
id: LANG_KEYCLICK_SOFTWARE
desc: in keyclick settings menu
user: core
<source>
*: none
hardware_click: "Headphone Keyclick"
</source>
<dest>
*: none
hardware_click: "Headphone Keyclick"
</dest>
<voice>
*: none
hardware_click: "Headphone Keyclick"
</voice>
</phrase>
<phrase>
id: LANG_KEYCLICK_HARDWARE
desc: in keyclick settings menu
user: core
<source>
*: none
hardware_click: "Speaker Keyclick"
</source>
<dest>
*: none
hardware_click: "Speaker Keyclick"
</dest>
<voice>
*: none
hardware_click: "Speaker Keyclick"
</voice>
</phrase>

View File

@ -118,6 +118,10 @@
#include "m5636.h"
#endif
#ifdef HAVE_HARDWARE_CLICK
#include "piezo.h"
#endif
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
#define MAIN_NORETURN_ATTR NORETURN_ATTR
#else
@ -507,6 +511,10 @@ static void init(void)
radio_init();
#endif
#ifdef HAVE_HARDWARE_CLICK
piezo_init();
#endif
/* Keep the order of this 3 (viewportmanager handles statusbars)
* Must be done before any code uses the multi-screen API */
CHART(">gui_syncstatusbar_init");

View File

@ -229,9 +229,15 @@ MAKE_MENU(limits_menu, ID2P(LANG_LIMITS_MENU), 0, Icon_NOICON,
#if CONFIG_CODEC == SWCODEC
MENUITEM_SETTING(keyclick, &global_settings.keyclick, NULL);
MENUITEM_SETTING(keyclick_repeats, &global_settings.keyclick_repeats, NULL);
#ifdef HAVE_HARDWARE_CLICK
MENUITEM_SETTING(keyclick_hardware, &global_settings.keyclick_hardware, NULL);
MAKE_MENU(keyclick_menu, ID2P(LANG_KEYCLICK), 0, Icon_NOICON,
&keyclick, &keyclick_hardware, &keyclick_repeats);
#else
MAKE_MENU(keyclick_menu, ID2P(LANG_KEYCLICK), 0, Icon_NOICON,
&keyclick, &keyclick_repeats);
#endif
#endif
#if CONFIG_CODEC == MAS3507D

View File

@ -94,6 +94,10 @@
#endif
#endif
#ifdef HAVE_HARDWARE_CLICK
#include "piezo.h"
#endif
/* units used with output_dyn_value */
const unsigned char * const byte_units[] =
{
@ -873,14 +877,32 @@ void system_sound_play(enum system_sound sound)
void keyclick_click(int button)
{
/* Settings filters */
if (global_settings.keyclick &&
(global_settings.keyclick_repeats || !(button & BUTTON_REPEAT)))
if (
#ifdef HAVE_HARDWARE_CLICK
(global_settings.keyclick || global_settings.keyclick_hardware)
#else
global_settings.keyclick
#endif
&& (global_settings.keyclick_repeats || !(button & BUTTON_REPEAT)))
{
/* Button filters */
if (button != BUTTON_NONE && !(button & BUTTON_REL)
&& !(button & (SYS_EVENT|BUTTON_MULTIMEDIA)) )
{
#ifdef HAVE_HARDWARE_CLICK
if (global_settings.keyclick)
{
system_sound_play(SOUND_KEYCLICK);
}
if (global_settings.keyclick_hardware)
{
#if !defined(SIMULATOR)
piezo_button_beep(false, false);
#endif
}
#else
system_sound_play(SOUND_KEYCLICK);
#endif
}
}
}

View File

@ -835,6 +835,13 @@ struct user_settings
#endif
} hw_eq_bands[AUDIOHW_EQ_BAND_NUM];
#endif /* AUDIOHW_HAVE_EQ */
#ifdef HAVE_HARDWARE_CLICK
#if CONFIG_CODEC == SWCODEC
bool keyclick_hardware; /* hardware piezo keyclick */
#endif
#endif
char start_directory[MAX_PATHNAME+1];
};

View File

@ -1757,12 +1757,23 @@ const struct settings_list settings[] = {
#endif /* HAVE_WHEEL_ACCELERATION */
#if CONFIG_CODEC == SWCODEC
/* keyclick */
#ifdef HAVE_HARDWARE_CLICK
CHOICE_SETTING(0, keyclick, LANG_KEYCLICK_SOFTWARE, 0,
"keyclick", "off,weak,moderate,strong", NULL, 4,
ID2P(LANG_OFF), ID2P(LANG_WEAK), ID2P(LANG_MODERATE),
ID2P(LANG_STRONG)),
OFFON_SETTING(0, keyclick_repeats, LANG_KEYCLICK_REPEATS, false,
"keyclick repeats", NULL),
OFFON_SETTING(0, keyclick_hardware, LANG_KEYCLICK_HARDWARE, false,
"hardware keyclick", NULL),
#else
CHOICE_SETTING(0, keyclick, LANG_KEYCLICK, 0,
"keyclick", "off,weak,moderate,strong", NULL, 4,
ID2P(LANG_OFF), ID2P(LANG_WEAK), ID2P(LANG_MODERATE),
ID2P(LANG_STRONG)),
OFFON_SETTING(0, keyclick_repeats, LANG_KEYCLICK_REPEATS, false,
"keyclick repeats", NULL),
#endif
#endif /* CONFIG_CODEC == SWCODEC */
TEXT_SETTING(0, playlist_catalog_dir, "playlist catalog directory",
PLAYLIST_CATALOG_DEFAULT_DIR, NULL, NULL),

View File

@ -1160,6 +1160,7 @@ target/arm/ata-pp5020.c
target/arm/ipod/adc-ipod-pcf.c
target/arm/ipod/backlight-4g_color.c
target/arm/ipod/button-clickwheel.c
target/arm/ipod/piezo.c
target/arm/ipod/lcd-as-gray.S
target/arm/ipod/lcd-gray.c
target/arm/ipod/power-ipod.c
@ -1178,6 +1179,7 @@ target/arm/i2s-pp.c
target/arm/ipod/adc-ipod-pcf.c
target/arm/ipod/backlight-4g_color.c
target/arm/ipod/button-clickwheel.c
target/arm/ipod/piezo.c
target/arm/ipod/lcd-color_nano.c
target/arm/ipod/lcd-as-color-nano.S
target/arm/ipod/power-ipod.c
@ -1196,6 +1198,7 @@ target/arm/i2s-pp.c
target/arm/ipod/adc-ipod-pcf.c
target/arm/ipod/backlight-nano_video.c
target/arm/ipod/button-clickwheel.c
target/arm/ipod/piezo.c
target/arm/ipod/lcd-color_nano.c
target/arm/ipod/lcd-as-color-nano.S
target/arm/ipod/power-ipod.c
@ -1214,6 +1217,7 @@ target/arm/i2s-pp.c
target/arm/ipod/adc-ipod-pcf.c
target/arm/ipod/backlight-nano_video.c
target/arm/ipod/button-clickwheel.c
target/arm/ipod/piezo.c
target/arm/ipod/power-ipod.c
target/arm/ipod/powermgmt-ipod-pcf.c
target/arm/ipod/video/lcd-as-video.S
@ -1268,6 +1272,7 @@ target/arm/i2s-pp.c
target/arm/ipod/adc-ipod-pcf.c
target/arm/ipod/backlight-mini1g_mini2g.c
target/arm/ipod/button-mini1g.c
target/arm/ipod/piezo.c
target/arm/ipod/lcd-as-gray.S
target/arm/ipod/lcd-gray.c
target/arm/ipod/power-ipod.c
@ -1286,6 +1291,7 @@ target/arm/i2s-pp.c
target/arm/ipod/adc-ipod-pcf.c
target/arm/ipod/backlight-mini1g_mini2g.c
target/arm/ipod/button-clickwheel.c
target/arm/ipod/piezo.c
target/arm/ipod/lcd-as-gray.S
target/arm/ipod/lcd-gray.c
target/arm/ipod/power-ipod.c
@ -1639,6 +1645,7 @@ target/arm/s5l8700/pcm-s5l8700.c
target/arm/s5l8700/wmcodec-s5l8700.c
target/arm/s5l8700/ipodnano2g/audio-nano2g.c
target/arm/s5l8700/ipodnano2g/adc-nano2g.c
target/arm/s5l8700/ipodnano2g/piezo-nano2g.c
#endif
#endif
#endif

View File

@ -212,6 +212,8 @@
/* Define this if you can read an absolute wheel position */
#define HAVE_WHEEL_POSITION
#define HAVE_HARDWARE_CLICK
#define BOOTFILE_EXT "ipod"
#define BOOTFILE "rockbox." BOOTFILE_EXT
#define BOOTDIR "/.rockbox"

View File

@ -199,6 +199,8 @@
/* Define this if you can read an absolute wheel position */
#define HAVE_WHEEL_POSITION
#define HAVE_HARDWARE_CLICK
#define BOOTFILE_EXT "ipod"
#define BOOTFILE "rockbox." BOOTFILE_EXT
#define BOOTDIR "/.rockbox"

View File

@ -202,6 +202,8 @@
/* Define this if you have adjustable CPU frequency */
#define HAVE_ADJUSTABLE_CPU_FREQ
#define HAVE_HARDWARE_CLICK
#define BOOTFILE_EXT "ipod"
#define BOOTFILE "rockbox." BOOTFILE_EXT
#define BOOTDIR "/.rockbox"

View File

@ -205,6 +205,8 @@
/* Define this if you can read an absolute wheel position */
#define HAVE_WHEEL_POSITION
#define HAVE_HARDWARE_CLICK
#define BOOTFILE_EXT "ipod"
#define BOOTFILE "rockbox." BOOTFILE_EXT
#define BOOTDIR "/.rockbox"

View File

@ -199,6 +199,8 @@
/* Define this if you can read an absolute wheel position */
#define HAVE_WHEEL_POSITION
#define HAVE_HARDWARE_CLICK
#define BOOTFILE_EXT "ipod"
#define BOOTFILE "rockbox." BOOTFILE_EXT
#define BOOTDIR "/.rockbox"

View File

@ -191,6 +191,8 @@
/* Define this if you can read an absolute wheel position */
#define HAVE_WHEEL_POSITION
#define HAVE_HARDWARE_CLICK
/* Define this if you have adjustable CPU frequency */
#define HAVE_ADJUSTABLE_CPU_FREQ

View File

@ -218,6 +218,8 @@
/* Define this if you can read an absolute wheel position */
#define HAVE_WHEEL_POSITION
#define HAVE_HARDWARE_CLICK
/* define this if the device has larger sectors when accessed via USB */
/* (only relevant in disk.c, fat.c now always supports large virtual sectors) */
#define MAX_LOG_SECTOR_SIZE 2048

View File

@ -65,10 +65,18 @@
#if CONFIG_CODEC == SWCODEC
#ifdef HAVE_RECORDING
#ifdef HAVE_HARDWARE_CLICK
#define BASETHREADS 18
#else
#define BASETHREADS 17
#endif
#else
#ifdef HAVE_HARDWARE_CLICK
#define BASETHREADS 17
#else
#define BASETHREADS 16
#endif
#endif
#else
#define BASETHREADS 11

View File

@ -0,0 +1,209 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006-2007 Robert Keevil
*
* 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.
*
****************************************************************************/
#include "thread.h"
#include "system.h"
#include "kernel.h"
#include "usb.h"
#include "logf.h"
#include "piezo.h"
static long piezo_stack[DEFAULT_STACK_SIZE/sizeof(long)];
static const char piezo_thread_name[] = "piezo";
static struct event_queue piezo_queue;
static unsigned int duration;
static bool beeping;
enum {
Q_PIEZO_BEEP = 1,
Q_PIEZO_BEEP_FOR_TICK,
Q_PIEZO_BEEP_FOR_USEC,
Q_PIEZO_STOP
};
static inline void piezo_hw_init(void)
{
#ifndef SIMULATOR
/*logf("PIEZO: hw_init");*/
outl(inl(0x70000010) & ~0xc, 0x70000010);
outl(inl(0x6000600c) | 0x20000, 0x6000600c); /* enable device */
#endif
}
static void piezo_hw_tick(unsigned int form_and_period)
{
#ifndef SIMULATOR
outl(0x80000000 | form_and_period, 0x7000a000); /* set pitch */
#endif
}
static inline void piezo_hw_stop(void)
{
#ifndef SIMULATOR
outl(0x0, 0x7000a000); /* piezo off */
#endif
}
static void piezo_thread(void)
{
struct queue_event ev;
long piezo_usec_off;
while(1)
{
queue_wait(&piezo_queue, &ev);
switch(ev.id)
{
case Q_PIEZO_BEEP:
piezo_hw_tick((unsigned int)ev.data);
beeping = true;
break;
case Q_PIEZO_BEEP_FOR_TICK:
piezo_hw_tick((unsigned int)ev.data);
beeping = true;
sleep(duration);
if (beeping)
piezo_hw_stop();
beeping = false;
/* remove anything that appeared while sleeping */
queue_clear(&piezo_queue);
break;
case Q_PIEZO_BEEP_FOR_USEC:
piezo_usec_off = USEC_TIMER + duration;
piezo_hw_tick((unsigned int)ev.data);
beeping = true;
while (TIME_BEFORE(USEC_TIMER, piezo_usec_off))
if (duration >= 5000) yield();
if (beeping)
piezo_hw_stop();
beeping = false;
/* remove anything that appeared while sleeping */
queue_clear(&piezo_queue);
break;
case Q_PIEZO_STOP:
if (beeping)
piezo_hw_stop();
beeping = false;
break;
#ifndef SIMULATOR
case SYS_USB_CONNECTED:
/*logf("USB: Piezo core");*/
piezo_hw_stop();
queue_clear(&piezo_queue);
usb_acknowledge(SYS_USB_CONNECTED_ACK);
usb_wait_for_disconnect(&piezo_queue);
break ;
#endif
case SYS_TIMEOUT:
break;
}
yield();
}
}
void piezo_play(unsigned short inv_freq, unsigned char form)
{
queue_post(&piezo_queue, Q_PIEZO_BEEP,
(intptr_t)((unsigned int)form << 16 | inv_freq));
}
void piezo_play_for_tick(unsigned short inv_freq,
unsigned char form, unsigned int dur)
{
duration = dur;
queue_post(&piezo_queue, Q_PIEZO_BEEP_FOR_TICK,
(intptr_t)((unsigned int)form << 16 | inv_freq));
}
void piezo_play_for_usec(unsigned short inv_freq,
unsigned char form, unsigned int dur)
{
duration = dur;
queue_post(&piezo_queue, Q_PIEZO_BEEP_FOR_USEC,
(intptr_t)((unsigned int)form << 16 | inv_freq));
}
void piezo_stop(void)
{
queue_post(&piezo_queue, Q_PIEZO_STOP, 0);
}
void piezo_clear(void)
{
queue_clear(&piezo_queue);
piezo_stop();
}
bool piezo_busy(void)
{
return !queue_empty(&piezo_queue);
}
/* conversion factor based on the following data
period Hz
10 8547
20 4465
30 3024
40 2286
50 1846
60 1537
70 1320
80 1165
90 1030
100 928
someone with better recording/analysing equipment should be able
to get more accurate figures
*/
unsigned int piezo_hz(unsigned int hz)
{
if (hz > 0)
return 91225/hz;
else
return 0;
}
void piezo_init(void)
{
/*logf("PIEZO: init");*/
piezo_hw_init();
queue_init(&piezo_queue, true);
create_thread(piezo_thread, piezo_stack, sizeof(piezo_stack), 0,
piezo_thread_name IF_PRIO(, PRIORITY_REALTIME)
IF_COP(, CPU));
}
void piezo_button_beep(bool beep, bool force)
{
/* old on clickwheel action - piezo_play_for_usec(50, 0x80, 400);
old on button action - piezo_play_for_usec(50, 0x80, 3000); */
if (force)
piezo_clear();
if (queue_empty(&piezo_queue))
{
if (beep)
piezo_play_for_tick(40, 0x80, HZ/5);
else
piezo_play_for_usec(91, 0x80, 4000);
}
}

View File

@ -0,0 +1,30 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006-2007 Robert Keevil
*
* 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.
*
****************************************************************************/
void piezo_init(void);
void piezo_play(unsigned short inv_freq, unsigned char form);
void piezo_play_for_tick(unsigned short inv_freq,
unsigned char form, unsigned int dur);
void piezo_play_for_usec(unsigned short inv_freq,
unsigned char form, unsigned int dur);
void piezo_stop(void);
void piezo_clear(void);
bool piezo_busy(void);
unsigned int piezo_hz(unsigned int hz);
void piezo_button_beep(bool beep, bool force);

View File

@ -0,0 +1,95 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006-2007 Robert Keevil
*
* 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.
*
****************************************************************************/
#include "system.h"
#include "kernel.h"
#include "piezo.h"
static unsigned int duration;
static bool beeping;
void INT_TIMERD(void)
{
/* clear interrupt */
TDCON = TDCON;
if (!(--duration))
{
beeping = 0;
TDCMD = (1 << 1); /* TD_CLR */
}
}
void piezo_start(unsigned short cycles, unsigned short periods)
{
#ifndef SIMULATOR
duration = periods;
beeping = 1;
/* configure timer for 100 kHz */
TDCMD = (1 << 1); /* TD_CLR */
TDPRE = 30 - 1; /* prescaler */
TDCON = (1 << 13) | /* TD_INT1_EN */
(0 << 12) | /* TD_INT0_EN */
(0 << 11) | /* TD_START */
(2 << 8) | /* TD_CS = PCLK / 16 */
(1 << 4); /* TD_MODE_SEL = PWM mode */
TDDATA0 = cycles; /* set interval period */
TDDATA1 = cycles << 1; /* set interval period */
TDCMD = (1 << 0); /* TD_EN */
/* enable timer interrupt */
INTMSK |= INTMSK_TIMERD;
#endif
}
void piezo_stop(void)
{
#ifndef SIMULATOR
TDCMD = (1 << 1); /* TD_CLR */
#endif
}
void piezo_clear(void)
{
piezo_stop();
}
bool piezo_busy(void)
{
return beeping;
}
void piezo_init(void)
{
beeping = 0;
}
void piezo_button_beep(bool beep, bool force)
{
if (force)
while (beeping)
yield();
if (!beeping)
{
if (beep)
piezo_start(22, 457);
else
piezo_start(40, 4);
}
}

View File

@ -0,0 +1,24 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006-2007 Robert Keevil
*
* 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.
*
****************************************************************************/
void piezo_init(void);
void piezo_stop(void);
void piezo_clear(void);
bool piezo_busy(void);
void piezo_button_beep(bool beep, bool force);