From be716c0be80e3f64a81a3f19b683db40489f47a1 Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Wed, 16 Nov 2011 10:25:43 +0000 Subject: 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 --- firmware/target/arm/ipod/piezo.c | 209 +++++++++++++++++++++++++++++++++++++++ firmware/target/arm/ipod/piezo.h | 30 ++++++ 2 files changed, 239 insertions(+) create mode 100644 firmware/target/arm/ipod/piezo.c create mode 100644 firmware/target/arm/ipod/piezo.h (limited to 'firmware/target/arm/ipod') 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); -- cgit v1.2.3