summaryrefslogtreecommitdiff
path: root/firmware/target/arm/ipod/piezo.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/ipod/piezo.c')
-rw-r--r--firmware/target/arm/ipod/piezo.c209
1 files changed, 209 insertions, 0 deletions
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006-2007 Robert Keevil
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "thread.h"
21#include "system.h"
22#include "kernel.h"
23#include "usb.h"
24#include "logf.h"
25#include "piezo.h"
26
27static long piezo_stack[DEFAULT_STACK_SIZE/sizeof(long)];
28static const char piezo_thread_name[] = "piezo";
29static struct event_queue piezo_queue;
30static unsigned int duration;
31static bool beeping;
32
33enum {
34 Q_PIEZO_BEEP = 1,
35 Q_PIEZO_BEEP_FOR_TICK,
36 Q_PIEZO_BEEP_FOR_USEC,
37 Q_PIEZO_STOP
38};
39
40static inline void piezo_hw_init(void)
41{
42#ifndef SIMULATOR
43 /*logf("PIEZO: hw_init");*/
44 outl(inl(0x70000010) & ~0xc, 0x70000010);
45 outl(inl(0x6000600c) | 0x20000, 0x6000600c); /* enable device */
46#endif
47}
48
49static void piezo_hw_tick(unsigned int form_and_period)
50{
51#ifndef SIMULATOR
52 outl(0x80000000 | form_and_period, 0x7000a000); /* set pitch */
53#endif
54}
55
56static inline void piezo_hw_stop(void)
57{
58#ifndef SIMULATOR
59 outl(0x0, 0x7000a000); /* piezo off */
60#endif
61}
62
63static void piezo_thread(void)
64{
65 struct queue_event ev;
66 long piezo_usec_off;
67
68 while(1)
69 {
70 queue_wait(&piezo_queue, &ev);
71 switch(ev.id)
72 {
73 case Q_PIEZO_BEEP:
74 piezo_hw_tick((unsigned int)ev.data);
75 beeping = true;
76 break;
77 case Q_PIEZO_BEEP_FOR_TICK:
78 piezo_hw_tick((unsigned int)ev.data);
79 beeping = true;
80 sleep(duration);
81 if (beeping)
82 piezo_hw_stop();
83 beeping = false;
84 /* remove anything that appeared while sleeping */
85 queue_clear(&piezo_queue);
86 break;
87 case Q_PIEZO_BEEP_FOR_USEC:
88 piezo_usec_off = USEC_TIMER + duration;
89 piezo_hw_tick((unsigned int)ev.data);
90 beeping = true;
91 while (TIME_BEFORE(USEC_TIMER, piezo_usec_off))
92 if (duration >= 5000) yield();
93 if (beeping)
94 piezo_hw_stop();
95 beeping = false;
96 /* remove anything that appeared while sleeping */
97 queue_clear(&piezo_queue);
98 break;
99 case Q_PIEZO_STOP:
100 if (beeping)
101 piezo_hw_stop();
102 beeping = false;
103 break;
104#ifndef SIMULATOR
105 case SYS_USB_CONNECTED:
106 /*logf("USB: Piezo core");*/
107 piezo_hw_stop();
108 queue_clear(&piezo_queue);
109 usb_acknowledge(SYS_USB_CONNECTED_ACK);
110 usb_wait_for_disconnect(&piezo_queue);
111 break ;
112#endif
113 case SYS_TIMEOUT:
114 break;
115 }
116 yield();
117 }
118}
119
120
121void piezo_play(unsigned short inv_freq, unsigned char form)
122{
123 queue_post(&piezo_queue, Q_PIEZO_BEEP,
124 (intptr_t)((unsigned int)form << 16 | inv_freq));
125}
126
127void piezo_play_for_tick(unsigned short inv_freq,
128 unsigned char form, unsigned int dur)
129{
130 duration = dur;
131 queue_post(&piezo_queue, Q_PIEZO_BEEP_FOR_TICK,
132 (intptr_t)((unsigned int)form << 16 | inv_freq));
133}
134
135void piezo_play_for_usec(unsigned short inv_freq,
136 unsigned char form, unsigned int dur)
137{
138 duration = dur;
139 queue_post(&piezo_queue, Q_PIEZO_BEEP_FOR_USEC,
140 (intptr_t)((unsigned int)form << 16 | inv_freq));
141}
142
143void piezo_stop(void)
144{
145 queue_post(&piezo_queue, Q_PIEZO_STOP, 0);
146}
147
148void piezo_clear(void)
149{
150 queue_clear(&piezo_queue);
151 piezo_stop();
152}
153
154bool piezo_busy(void)
155{
156 return !queue_empty(&piezo_queue);
157}
158
159/* conversion factor based on the following data
160
161 period Hz
162 10 8547
163 20 4465
164 30 3024
165 40 2286
166 50 1846
167 60 1537
168 70 1320
169 80 1165
170 90 1030
171 100 928
172
173 someone with better recording/analysing equipment should be able
174 to get more accurate figures
175*/
176unsigned int piezo_hz(unsigned int hz)
177{
178 if (hz > 0)
179 return 91225/hz;
180 else
181 return 0;
182}
183
184void piezo_init(void)
185{
186 /*logf("PIEZO: init");*/
187 piezo_hw_init();
188 queue_init(&piezo_queue, true);
189 create_thread(piezo_thread, piezo_stack, sizeof(piezo_stack), 0,
190 piezo_thread_name IF_PRIO(, PRIORITY_REALTIME)
191 IF_COP(, CPU));
192}
193
194void piezo_button_beep(bool beep, bool force)
195{
196 /* old on clickwheel action - piezo_play_for_usec(50, 0x80, 400);
197 old on button action - piezo_play_for_usec(50, 0x80, 3000); */
198
199 if (force)
200 piezo_clear();
201
202 if (queue_empty(&piezo_queue))
203 {
204 if (beep)
205 piezo_play_for_tick(40, 0x80, HZ/5);
206 else
207 piezo_play_for_usec(91, 0x80, 4000);
208 }
209}