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