Index: apps/main.c
===================================================================
RCS file: /cvsroot/rockbox/apps/main.c,v
retrieving revision 1.169
diff -u -r1.169 main.c
--- apps/main.c	13 Apr 2006 21:20:13 -0000	1.169
+++ apps/main.c	15 Apr 2006 20:19:18 -0000
@@ -88,6 +88,10 @@
 #include "lcd-remote.h"
 #endif
 
+#ifdef HAVE_PIEZO
+#include "piezo.h"
+#endif
+
 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
 
 const char appsversion[]=APPSVERSION;
@@ -444,6 +448,10 @@
 #ifdef HAVE_CHARGING
     car_adapter_mode_init();
 #endif
+
+#ifdef HAVE_PIEZO
+    piezo_init();
+#endif
 }
 
 int main(void)
Index: apps/plugin.c
===================================================================
RCS file: /cvsroot/rockbox/apps/plugin.c,v
retrieving revision 1.167
diff -u -r1.167 plugin.c
--- apps/plugin.c	6 Apr 2006 18:26:10 -0000	1.167
+++ apps/plugin.c	15 Apr 2006 20:19:19 -0000
@@ -72,6 +72,10 @@
 #include "lcd-remote.h"
 #endif
 
+#ifdef HAVE_PIEZO
+#include "piezo.h"
+#endif
+
 #ifdef SIMULATOR
 static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE];
 void *sim_plugin_load(char *plugin, void **pd);
@@ -434,6 +438,14 @@
     gui_synclist_scroll_left,
 #endif
     gui_synclist_do_button,
+#ifdef HAVE_PIEZO
+    piezo_play,
+    piezo_play_for,
+    piezo_stop,
+    piezo_clear,
+    piezo_busy,
+    piezo_hz,
+#endif
 };
 
 int plugin_load(const char* plugin, void* parameter)
Index: apps/plugin.h
===================================================================
RCS file: /cvsroot/rockbox/apps/plugin.h,v
retrieving revision 1.173
diff -u -r1.173 plugin.h
--- apps/plugin.h	3 Apr 2006 08:51:08 -0000	1.173
+++ apps/plugin.h	15 Apr 2006 20:19:19 -0000
@@ -510,6 +510,14 @@
     void (*gui_synclist_scroll_left)(struct gui_synclist * lists);
 #endif
     unsigned (*gui_synclist_do_button)(struct gui_synclist * lists, unsigned button);
+#ifdef HAVE_PIEZO
+    void (*piezo_play)(unsigned int inv_freq);
+    void (*piezo_play_for)(unsigned int inv_freq, unsigned int dur);
+    void (*piezo_stop)(void);
+    void (*piezo_clear)(void);
+    bool (*piezo_busy)(void);
+    unsigned int (*piezo_hz)(unsigned int hz);
+#endif
 };
 
 /* plugin header */
Index: firmware/SOURCES
===================================================================
RCS file: /cvsroot/rockbox/firmware/SOURCES,v
retrieving revision 1.84
diff -u -r1.84 SOURCES
--- firmware/SOURCES	30 Mar 2006 20:18:02 -0000	1.84
+++ firmware/SOURCES	15 Apr 2006 20:19:21 -0000
@@ -202,6 +202,9 @@
 common/sscanf.c
 usb_serial.c
 #endif
+#ifdef HAVE_PIEZO
+drivers/piezo.c
+#endif
 
 #ifndef SIMULATOR
 #ifdef IAUDIO_X5
Index: firmware/drivers/piezo.c
===================================================================
RCS file: firmware/drivers/piezo.c
diff -N firmware/drivers/piezo.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ firmware/drivers/piezo.c	15 Apr 2006 20:19:21 -0000
@@ -0,0 +1,133 @@
+#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;
+unsigned int duration;
+bool beeping;
+
+enum {
+    Q_PIEZO_BEEP = 1,
+	Q_PIEZO_BEEP_FOR,
+    Q_PIEZO_STOP
+};
+
+static inline void piezo_hw_init(void)
+{
+    outl(inl(0x70000010) & ~0xc, 0x70000010);
+    outl(inl(0x6000600c) | 0x20000, 0x6000600c);    /* enable device */
+}
+
+static void piezo_hw_tick(unsigned int period)
+{    
+    outl(0x80000000 | 0x800000 | period, 0x7000a000); /* set pitch */
+}
+
+static inline void piezo_hw_stop(void)
+{
+    outl(0x0, 0x7000a000);    /* piezo off */
+}
+
+/*
+void piezo_start_for(void)
+{
+    piezo_hw_tick(frequency);
+    sleep(duration);
+    piezo_hw_stop();
+}
+*/
+
+void piezo_thread(void)
+{
+    struct event ev;
+
+    while(1)
+    {
+        queue_wait(&piezo_queue, &ev);
+        switch(ev.id)
+        {
+            case Q_PIEZO_BEEP:
+                piezo_hw_tick((unsigned int)ev.data);
+                beeping = true;
+                logf("PIEZO: beep");
+                break;
+            case Q_PIEZO_BEEP_FOR:
+                logf("PIEZO: beep_for start");
+                piezo_hw_tick((unsigned int)ev.data);
+                beeping = true;
+                sleep(duration);
+                if (beeping)
+                    piezo_hw_stop();
+                beeping = false;
+                logf("PIEZO: beep_for end");
+                /* remove anything that appeared while sleeping */
+                queue_clear(&piezo_queue);
+                break;
+            case Q_PIEZO_STOP:
+                if (beeping)
+                    piezo_hw_stop();
+                beeping = false;
+                logf("PIEZO: beep stop");
+                break;
+#ifndef SIMULATOR
+            case SYS_USB_CONNECTED:
+                logf("USB: Piezo core");
+                piezo_hw_stop();
+                usb_acknowledge(SYS_USB_CONNECTED_ACK);
+                usb_wait_for_disconnect(&piezo_queue);
+                break ;
+#endif
+            case SYS_TIMEOUT:
+                break;
+        }
+        yield();
+    }
+}
+
+void piezo_play(unsigned int inv_freq)
+{
+    queue_post(&piezo_queue, Q_PIEZO_BEEP, (unsigned int *)inv_freq);
+}
+
+void piezo_play_for(unsigned int inv_freq, unsigned int dur)
+{
+    duration = dur;
+    queue_post(&piezo_queue, Q_PIEZO_BEEP_FOR, (unsigned int *)inv_freq);
+}
+
+void piezo_stop(void)
+{
+    queue_post(&piezo_queue, Q_PIEZO_STOP, NULL);
+}
+
+void piezo_clear(void)
+{
+    queue_clear(&piezo_queue);
+    piezo_stop();
+}
+
+bool piezo_busy(void)
+{
+    return !queue_empty(&piezo_queue) || beeping;
+}
+
+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);
+    create_thread(piezo_thread, piezo_stack, sizeof(piezo_stack), piezo_thread_name);
+}
Index: firmware/export/piezo.h
===================================================================
RCS file: firmware/export/piezo.h
diff -N firmware/export/piezo.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ firmware/export/piezo.h	15 Apr 2006 20:19:21 -0000
@@ -0,0 +1,28 @@
+
+#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
+*/
+
+void piezo_init(void);
+void piezo_play(unsigned int inv_freq);
+void piezo_play_for(unsigned int inv_freq, unsigned int dur);
+void piezo_stop(void);
+void piezo_clear(void);
+bool piezo_busy(void);
+unsigned int piezo_hz(unsigned int hz);
