From be716c0be80e3f64a81a3f19b683db40489f47a1 Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Wed, 16 Nov 2011 10:25:43 +0000 Subject: [PATCH] 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 --- apps/features.txt | 4 + apps/lang/english.lang | 34 ++++ apps/main.c | 8 + apps/menus/settings_menu.c | 6 + apps/misc.c | 26 ++- apps/settings.h | 7 + apps/settings_list.c | 11 ++ firmware/SOURCES | 7 + firmware/export/config/ipod4g.h | 2 + firmware/export/config/ipodcolor.h | 2 + firmware/export/config/ipodmini1g.h | 2 + firmware/export/config/ipodmini2g.h | 2 + firmware/export/config/ipodnano1g.h | 2 + firmware/export/config/ipodnano2g.h | 2 + firmware/export/config/ipodvideo.h | 2 + firmware/export/thread.h | 8 + firmware/target/arm/ipod/piezo.c | 209 +++++++++++++++++++++ firmware/target/arm/ipod/piezo.h | 30 +++ .../target/arm/s5l8700/ipodnano2g/piezo-nano2g.c | 95 ++++++++++ firmware/target/arm/s5l8700/ipodnano2g/piezo.h | 24 +++ 20 files changed, 481 insertions(+), 2 deletions(-) create mode 100644 firmware/target/arm/ipod/piezo.c create mode 100644 firmware/target/arm/ipod/piezo.h create mode 100644 firmware/target/arm/s5l8700/ipodnano2g/piezo-nano2g.c create mode 100644 firmware/target/arm/s5l8700/ipodnano2g/piezo.h diff --git a/apps/features.txt b/apps/features.txt index 44ef3ddf95..35f7bb50e0 100644 --- a/apps/features.txt +++ b/apps/features.txt @@ -270,3 +270,7 @@ recording_digital #if MEMORYSIZE <= 2 lowmem #endif + +#if defined(HAVE_HARDWARE_CLICK) +hardware_click +#endif diff --git a/apps/lang/english.lang b/apps/lang/english.lang index de541af1f5..a228a78f7f 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -12917,3 +12917,37 @@ *: "Shortcuts" + + id: LANG_KEYCLICK_SOFTWARE + desc: in keyclick settings menu + user: core + + *: 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: core + + *: none + hardware_click: "Speaker Keyclick" + + + *: none + hardware_click: "Speaker Keyclick" + + + *: none + hardware_click: "Speaker Keyclick" + + diff --git a/apps/main.c b/apps/main.c index 38de780c8d..9d83c62965 100644 --- a/apps/main.c +++ b/apps/main.c @@ -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"); diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c index 02f68aa4ab..079e86616d 100644 --- a/apps/menus/settings_menu.c +++ b/apps/menus/settings_menu.c @@ -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 diff --git a/apps/misc.c b/apps/misc.c index 0608595d21..04a6d05c91 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -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 } } } diff --git a/apps/settings.h b/apps/settings.h index 92ffaf9019..06eba76e3c 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -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]; }; diff --git a/apps/settings_list.c b/apps/settings_list.c index e739f406cb..9232811ada 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c @@ -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), diff --git a/firmware/SOURCES b/firmware/SOURCES index 0f6c21d673..6a84b5fc11 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -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 diff --git a/firmware/export/config/ipod4g.h b/firmware/export/config/ipod4g.h index 165f5967b4..957e3a4da5 100644 --- a/firmware/export/config/ipod4g.h +++ b/firmware/export/config/ipod4g.h @@ -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" diff --git a/firmware/export/config/ipodcolor.h b/firmware/export/config/ipodcolor.h index 645e20041c..cf021019b4 100644 --- a/firmware/export/config/ipodcolor.h +++ b/firmware/export/config/ipodcolor.h @@ -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" diff --git a/firmware/export/config/ipodmini1g.h b/firmware/export/config/ipodmini1g.h index 777dc6f9a2..04fa68e500 100644 --- a/firmware/export/config/ipodmini1g.h +++ b/firmware/export/config/ipodmini1g.h @@ -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" diff --git a/firmware/export/config/ipodmini2g.h b/firmware/export/config/ipodmini2g.h index c401170459..c10284e7a4 100644 --- a/firmware/export/config/ipodmini2g.h +++ b/firmware/export/config/ipodmini2g.h @@ -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" diff --git a/firmware/export/config/ipodnano1g.h b/firmware/export/config/ipodnano1g.h index 388ba34447..50f0511384 100644 --- a/firmware/export/config/ipodnano1g.h +++ b/firmware/export/config/ipodnano1g.h @@ -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" diff --git a/firmware/export/config/ipodnano2g.h b/firmware/export/config/ipodnano2g.h index 37a21b33ba..96cec799e4 100644 --- a/firmware/export/config/ipodnano2g.h +++ b/firmware/export/config/ipodnano2g.h @@ -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 diff --git a/firmware/export/config/ipodvideo.h b/firmware/export/config/ipodvideo.h index 1dd7d48e30..c4e2cb2986 100644 --- a/firmware/export/config/ipodvideo.h +++ b/firmware/export/config/ipodvideo.h @@ -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 diff --git a/firmware/export/thread.h b/firmware/export/thread.h index d0f61f9d85..da06557f9c 100644 --- a/firmware/export/thread.h +++ b/firmware/export/thread.h @@ -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 diff --git a/firmware/target/arm/ipod/piezo.c b/firmware/target/arm/ipod/piezo.c new file mode 100644 index 0000000000..2c3968e79a --- /dev/null +++ b/firmware/target/arm/ipod/piezo.c @@ -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); + } +} diff --git a/firmware/target/arm/ipod/piezo.h b/firmware/target/arm/ipod/piezo.h new file mode 100644 index 0000000000..78b50d0d39 --- /dev/null +++ b/firmware/target/arm/ipod/piezo.h @@ -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); diff --git a/firmware/target/arm/s5l8700/ipodnano2g/piezo-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/piezo-nano2g.c new file mode 100644 index 0000000000..d555b7232f --- /dev/null +++ b/firmware/target/arm/s5l8700/ipodnano2g/piezo-nano2g.c @@ -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); + } +} diff --git a/firmware/target/arm/s5l8700/ipodnano2g/piezo.h b/firmware/target/arm/s5l8700/ipodnano2g/piezo.h new file mode 100644 index 0000000000..b8eae0943d --- /dev/null +++ b/firmware/target/arm/s5l8700/ipodnano2g/piezo.h @@ -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); -- 2.11.4.GIT