This source file includes following definitions.
- tmr2ticks
- reprogram_timer
- sound_timer_syncinterval
- tmr_reset
- timer_open
- timer_close
- timer_event
- timer_get_time
- timer_ioctl
- timer_arm
- sound_timer_interrupt
- sound_timer_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 #define SEQUENCER_C
29 #include "sound_config.h"
30
31 #if defined(CONFIG_SEQUENCER)
32
33 static volatile int initialized = 0, opened = 0, tmr_running = 0;
34 static volatile time_t tmr_offs, tmr_ctr;
35 static volatile unsigned long ticks_offs;
36 static volatile int curr_tempo, curr_timebase;
37 static volatile unsigned long curr_ticks;
38 static volatile unsigned long next_event_time;
39 static unsigned long prev_event_time;
40 static volatile unsigned long usecs_per_tmr;
41
42 static struct sound_lowlev_timer *tmr = NULL;
43
44 static unsigned long
45 tmr2ticks (int tmr_value)
46 {
47
48
49
50
51 unsigned long tmp;
52 unsigned long scale;
53
54 tmp = tmr_value * usecs_per_tmr;
55
56 scale = (60 * 1000000) / (curr_tempo * curr_timebase);
57
58 return (tmp + (scale / 2)) / scale;
59 }
60
61 static void
62 reprogram_timer (void)
63 {
64 unsigned long usecs_per_tick;
65
66 usecs_per_tick = (60 * 1000000) / (curr_tempo * curr_timebase);
67
68
69
70
71 if (usecs_per_tick < 2000)
72 usecs_per_tick = 2000;
73
74 usecs_per_tmr = tmr->tmr_start (tmr->dev, usecs_per_tick);
75 }
76
77 void
78 sound_timer_syncinterval (unsigned int new_usecs)
79 {
80
81
82
83
84 tmr_offs = tmr_ctr;
85 ticks_offs += tmr2ticks (tmr_ctr);
86 tmr_ctr = 0;
87
88 usecs_per_tmr = new_usecs;
89 }
90
91 static void
92 tmr_reset (void)
93 {
94 unsigned long flags;
95
96 save_flags (flags);
97 cli ();
98 tmr_offs = 0;
99 ticks_offs = 0;
100 tmr_ctr = 0;
101 next_event_time = 0xffffffff;
102 prev_event_time = 0;
103 curr_ticks = 0;
104 restore_flags (flags);
105 }
106
107 static int
108 timer_open (int dev, int mode)
109 {
110 if (opened)
111 return -EBUSY;
112
113 tmr_reset ();
114 curr_tempo = 60;
115 curr_timebase = HZ;
116 opened = 1;
117 reprogram_timer ();
118
119 return 0;
120 }
121
122 static void
123 timer_close (int dev)
124 {
125 opened = tmr_running = 0;
126 tmr->tmr_disable (tmr->dev);
127 }
128
129 static int
130 timer_event (int dev, unsigned char *event)
131 {
132 unsigned char cmd = event[1];
133 unsigned long parm = *(int *) &event[4];
134
135 switch (cmd)
136 {
137 case TMR_WAIT_REL:
138 parm += prev_event_time;
139 case TMR_WAIT_ABS:
140 if (parm > 0)
141 {
142 long time;
143
144 if (parm <= curr_ticks)
145 return TIMER_NOT_ARMED;
146
147 time = parm;
148 next_event_time = prev_event_time = time;
149
150 return TIMER_ARMED;
151 }
152 break;
153
154 case TMR_START:
155 tmr_reset ();
156 tmr_running = 1;
157 reprogram_timer ();
158 break;
159
160 case TMR_STOP:
161 tmr_running = 0;
162 break;
163
164 case TMR_CONTINUE:
165 tmr_running = 1;
166 reprogram_timer ();
167 break;
168
169 case TMR_TEMPO:
170 if (parm)
171 {
172 if (parm < 8)
173 parm = 8;
174 if (parm > 250)
175 parm = 250;
176 tmr_offs = tmr_ctr;
177 ticks_offs += tmr2ticks (tmr_ctr);
178 tmr_ctr = 0;
179 curr_tempo = parm;
180 reprogram_timer ();
181 }
182 break;
183
184 case TMR_ECHO:
185 seq_copy_to_input (event, 8);
186 break;
187
188 default:;
189 }
190
191 return TIMER_NOT_ARMED;
192 }
193
194 static unsigned long
195 timer_get_time (int dev)
196 {
197 if (!opened)
198 return 0;
199
200 return curr_ticks;
201 }
202
203 static int
204 timer_ioctl (int dev,
205 unsigned int cmd, ioctl_arg arg)
206 {
207 switch (cmd)
208 {
209 case SNDCTL_TMR_SOURCE:
210 return snd_ioctl_return ((int *) arg, TMR_INTERNAL);
211 break;
212
213 case SNDCTL_TMR_START:
214 tmr_reset ();
215 tmr_running = 1;
216 return 0;
217 break;
218
219 case SNDCTL_TMR_STOP:
220 tmr_running = 0;
221 return 0;
222 break;
223
224 case SNDCTL_TMR_CONTINUE:
225 tmr_running = 1;
226 return 0;
227 break;
228
229 case SNDCTL_TMR_TIMEBASE:
230 {
231 int val = get_fs_long ((long *) arg);
232
233 if (val)
234 {
235 if (val < 1)
236 val = 1;
237 if (val > 1000)
238 val = 1000;
239 curr_timebase = val;
240 }
241
242 return snd_ioctl_return ((int *) arg, curr_timebase);
243 }
244 break;
245
246 case SNDCTL_TMR_TEMPO:
247 {
248 int val = get_fs_long ((long *) arg);
249
250 if (val)
251 {
252 if (val < 8)
253 val = 8;
254 if (val > 250)
255 val = 250;
256 tmr_offs = tmr_ctr;
257 ticks_offs += tmr2ticks (tmr_ctr);
258 tmr_ctr = 0;
259 curr_tempo = val;
260 reprogram_timer ();
261 }
262
263 return snd_ioctl_return ((int *) arg, curr_tempo);
264 }
265 break;
266
267 case SNDCTL_SEQ_CTRLRATE:
268 if (get_fs_long ((long *) arg) != 0)
269 return -EINVAL;
270
271 return snd_ioctl_return ((int *) arg, ((curr_tempo * curr_timebase) + 30) / 60);
272 break;
273
274 case SNDCTL_TMR_METRONOME:
275
276 break;
277
278 default:;
279 }
280
281 return -EINVAL;
282 }
283
284 static void
285 timer_arm (int dev, long time)
286 {
287 if (time < 0)
288 time = curr_ticks + 1;
289 else if (time <= curr_ticks)
290 return;
291
292 next_event_time = prev_event_time = time;
293
294 return;
295 }
296
297 static struct sound_timer_operations sound_timer =
298 {
299 {"GUS Timer", 0},
300 1,
301 0,
302 timer_open,
303 timer_close,
304 timer_event,
305 timer_get_time,
306 timer_ioctl,
307 timer_arm
308 };
309
310 void
311 sound_timer_interrupt (void)
312 {
313 if (!opened)
314 return;
315
316 tmr->tmr_restart (tmr->dev);
317
318 if (!tmr_running)
319 return;
320
321 tmr_ctr++;
322 curr_ticks = ticks_offs + tmr2ticks (tmr_ctr);
323
324 if (curr_ticks >= next_event_time)
325 {
326 next_event_time = 0xffffffff;
327 sequencer_timer (0);
328 }
329 }
330
331 void
332 sound_timer_init (struct sound_lowlev_timer *t, char *name)
333 {
334 int n;
335
336 if (initialized || t == NULL)
337 return;
338
339 initialized = 1;
340 tmr = t;
341
342 if (num_sound_timers >= MAX_TIMER_DEV)
343 n = 0;
344 else
345 n = num_sound_timers++;
346
347 strcpy (sound_timer.info.name, name);
348
349 sound_timer_devs[n] = &sound_timer;
350 }
351
352 #endif