Index: apps/action.c
===================================================================
--- apps/action.c (revision 19748)
+++ apps/action.c (working copy)
@@ -34,6 +34,10 @@
#include "settings.h"
#include "pcmbuf.h"
+#ifdef HAVE_HARDWARE_CLICK
+#include "piezo.h"
+#endif
+
static int last_button = BUTTON_NONE|BUTTON_REL; /* allow the ipod wheel to
work on startup */
static intptr_t last_data = 0;
@@ -134,7 +138,40 @@
if (global_settings.keyclick && !(button & BUTTON_REL))
if (!(button & BUTTON_REPEAT) || global_settings.keyclick_repeats)
pcmbuf_beep(4000, KEYCLICK_DURATION, 2500*global_settings.keyclick);
+#ifdef HAVE_HARDWARE_CLICK
+ /* Produce speaker click */
+ if (global_settings.keyclick_hardware && !(button & BUTTON_REL))
+ {
+ if (!(button & BUTTON_REPEAT) ||
+ (button & (BUTTON_SCROLL_FWD | BUTTON_SCROLL_BACK)) ||
+ global_settings.keyclick_repeats)
+ {
+ switch (context)
+ {
+ case CONTEXT_WPS:
+ /* Reduce volume clicks by clickwheel to every 8dB */
+ if (button & BUTTON_SCROLL_FWD)
+ if ((global_settings.volume+1) % 8 != 0)
+ break;
+ if (button & BUTTON_SCROLL_BACK)
+ if ((global_settings.volume-1) % 8 != 0)
+ break;
+ piezo_button_beep(false, false);
+ break;
+ case CONTEXT_MAINMENU:
+ case CONTEXT_LIST:
+ case CONTEXT_TREE:
+ /* Don't make clickwheel click here - look in gui list handling */
+ if (button & (BUTTON_SCROLL_FWD | BUTTON_SCROLL_BACK))
+ break;
+ default:
+ piezo_button_beep(false, false);
+ break;
+ }
+ }
+ }
#endif
+#endif
if ((context != last_context) && ((last_button & BUTTON_REL) == 0))
{
Index: apps/features.txt
===================================================================
--- apps/features.txt (revision 19748)
+++ apps/features.txt (working copy)
@@ -185,3 +185,7 @@
#if defined(IPOD_ACCESSORY_PROTOCOL)
serial_port
#endif
+
+#if defined(HAVE_HARDWARE_CLICK)
+hardware_click
+#endif
Index: apps/gui/list.c
===================================================================
--- apps/gui/list.c (revision 19748)
+++ apps/gui/list.c (working copy)
@@ -41,6 +41,10 @@
#include "viewport.h"
#include "list.h"
+#ifdef HAVE_HARDWARE_CLICK
+#include "piezo.h"
+#endif
+
#ifdef HAVE_LCD_CHARCELLS
#define SCROLL_LIMIT 1
#else
@@ -335,11 +339,19 @@
new_selection = gui_list->selected_item + offset;
if (new_selection >= gui_list->nb_items)
{
+#ifdef HAVE_HARDWARE_CLICK
+ if (global_settings.keyclick_hardware && !gui_list->limit_scroll)
+ piezo_button_beep(false, false);
+#endif
gui_list->selected_item = gui_list->limit_scroll ?
gui_list->nb_items - gui_list->selected_size : 0;
}
else if (new_selection < 0)
{
+#ifdef HAVE_HARDWARE_CLICK
+ if (global_settings.keyclick_hardware && !gui_list->limit_scroll)
+ piezo_button_beep(false, false);
+#endif
gui_list->selected_item = gui_list->limit_scroll ?
0 : gui_list->nb_items - gui_list->selected_size;
}
@@ -372,7 +384,14 @@
}
return;
}
- else gui_list->selected_item += offset;
+ else
+ {
+#ifdef HAVE_HARDWARE_CLICK
+ if (global_settings.keyclick_hardware)
+ piezo_button_beep(false, false);
+#endif
+ gui_list->selected_item += offset;
+ }
gui_synclist_select_item(gui_list, gui_list->selected_item);
}
@@ -952,3 +971,5 @@
+
+
Index: apps/lang/english.lang
===================================================================
--- apps/lang/english.lang (revision 19748)
+++ apps/lang/english.lang (working copy)
@@ -11629,6 +11629,40 @@
+ id: LANG_KEYCLICK_SOFTWARE
+ desc: in keyclick settings menu
+ user:
+
+ *: none
+ hardware_click: "Headphone Keyclick"
+
+
+ *: none
+ hardware_click: "Headphone Keyclick"
+
+
+ *: none
+ hardware_click: "Headphone Keyclick"
+
+
+
+ id: LANG_KEYCLICK_HARDWARE
+ desc: in keyclick settings menu
+ user:
+
+ *: none
+ hardware_click: "Speaker Keyclick"
+
+
+ *: none
+ hardware_click: "Speaker Keyclick"
+
+
+ *: none
+ hardware_click: "Speaker Keyclick"
+
+
+
id: LANG_KEYCLICK_REPEATS
desc: in keyclick settings menu
user:
Index: apps/main.c
===================================================================
--- apps/main.c (revision 19748)
+++ apps/main.c (working copy)
@@ -596,6 +596,9 @@
#ifdef HAVE_ACCESSORY_SUPPLY
accessory_supply_set(global_settings.accessory_supply);
#endif
+#ifdef HAVE_HARDWARE_CLICK
+ piezo_init();
+#endif
}
#ifdef CPU_PP
Index: apps/menus/settings_menu.c
===================================================================
--- apps/menus/settings_menu.c (revision 19748)
+++ apps/menus/settings_menu.c (working copy)
@@ -222,9 +222,15 @@
#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
Index: apps/settings.h
===================================================================
--- apps/settings.h (revision 19748)
+++ apps/settings.h (working copy)
@@ -741,6 +741,11 @@
/* If values are just added to the end, no need to bump plugin API
version. */
/* new stuff to be added at the end */
+#if CONFIG_CODEC == SWCODEC
+#ifdef HAVE_HARDWARE_CLICK
+ bool keyclick_hardware; /* hardware piezo keyclick */
+#endif
+#endif
};
/** global variables **/
Index: apps/settings_list.c
===================================================================
--- apps/settings_list.c (revision 19748)
+++ apps/settings_list.c (working copy)
@@ -1431,12 +1431,16 @@
#endif
#if CONFIG_CODEC == SWCODEC
/* keyclick */
- CHOICE_SETTING(0, keyclick, LANG_KEYCLICK, 0,
+ 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),
+#ifdef HAVE_HARDWARE_CLICK
+ OFFON_SETTING(0, keyclick_hardware, LANG_KEYCLICK_HARDWARE, false,
+ "hardware keyclick", NULL),
+#endif
#endif /* CONFIG_CODEC == SWCODEC */
TEXT_SETTING(0, playlist_catalog_dir, "playlist catalog directory",
PLAYLIST_CATALOG_DEFAULT_DIR, NULL, NULL),
Index: firmware/export/config-ipod4g.h
===================================================================
--- firmware/export/config-ipod4g.h (revision 19748)
+++ firmware/export/config-ipod4g.h (working copy)
@@ -180,6 +180,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"
Index: firmware/export/config-ipodcolor.h
===================================================================
--- firmware/export/config-ipodcolor.h (revision 19748)
+++ firmware/export/config-ipodcolor.h (working copy)
@@ -160,6 +160,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"
Index: firmware/export/config-ipodmini.h
===================================================================
--- firmware/export/config-ipodmini.h (revision 19748)
+++ firmware/export/config-ipodmini.h (working copy)
@@ -173,6 +173,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"
Index: firmware/export/config-ipodmini2g.h
===================================================================
--- firmware/export/config-ipodmini2g.h (revision 19748)
+++ firmware/export/config-ipodmini2g.h (working copy)
@@ -184,6 +184,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"
Index: firmware/export/config-ipodnano.h
===================================================================
--- firmware/export/config-ipodnano.h (revision 19748)
+++ firmware/export/config-ipodnano.h (working copy)
@@ -161,6 +161,8 @@
#define HAVE_USBSTACK
#define USB_VENDOR_ID 0x05ac
#define USB_PRODUCT_ID 0x120a
+#define USE_ROCKBOX_USB
+#define USE_HIGH_SPEED
/* Virtual LED (icon) */
#define CONFIG_LED LED_VIRTUAL
@@ -171,6 +173,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"
Index: firmware/export/config-ipodvideo.h
===================================================================
--- firmware/export/config-ipodvideo.h (revision 19748)
+++ firmware/export/config-ipodvideo.h (working copy)
@@ -183,6 +183,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
Index: firmware/export/thread.h
===================================================================
--- firmware/export/thread.h (revision 19748)
+++ firmware/export/thread.h (working copy)
@@ -61,9 +61,9 @@
#if CONFIG_CODEC == SWCODEC
#ifdef HAVE_RECORDING
+#define BASETHREADS 18
+#else
#define BASETHREADS 17
-#else
-#define BASETHREADS 16
#endif
#else
Index: firmware/SOURCES
===================================================================
--- firmware/SOURCES (revision 19748)
+++ firmware/SOURCES (working copy)
@@ -874,6 +874,7 @@
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
@@ -892,6 +893,7 @@
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/power-ipod.c
target/arm/ipod/powermgmt-ipod-pcf.c
@@ -909,6 +911,7 @@
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/power-ipod.c
target/arm/ipod/powermgmt-ipod-pcf.c
@@ -926,6 +929,7 @@
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
@@ -977,6 +981,7 @@
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
Index: firmware/target/arm/ipod/piezo.c
===================================================================
--- firmware/target/arm/ipod/piezo.c (revision 0)
+++ firmware/target/arm/ipod/piezo.c (revision 0)
@@ -0,0 +1,206 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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"
+
+#define PIEZO_HZ_CONVERSION 91225
+/* 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
+*/
+
+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)
+{
+ logf("PIEZO: hw_init");
+ outl(inl(0x70000010) & ~0xc, 0x70000010);
+ outl(inl(0x6000600c) | 0x20000, 0x6000600c); /* enable device */
+}
+
+static void piezo_hw_tick(unsigned int form_and_period)
+{
+ outl(0x80000000 | form_and_period, 0x7000a000); /* set pitch */
+}
+
+static inline void piezo_hw_stop(void)
+{
+ outl(0x0, 0x7000a000); /* piezo off */
+}
+
+
+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);
+}
+
+unsigned int piezo_hz(unsigned int hz)
+{
+ if (hz > 0)
+ return PIEZO_HZ_CONVERSION/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);
+ }
+}
Index: firmware/target/arm/ipod/piezo.h
===================================================================
--- firmware/target/arm/ipod/piezo.h (revision 0)
+++ firmware/target/arm/ipod/piezo.h (revision 0)
@@ -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);