2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Routines for control of LFO generators (tremolo & vibrato) for
4 * GF1/InterWave chips...
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <sound/driver.h>
24 #include <sound/core.h>
25 #include <sound/gus.h>
28 * called by engine routines
31 static signed char snd_gf1_lfo_compute_value(snd_gus_card_t * gus,
34 unsigned int twaveinc, depth_delta;
36 unsigned short control, twave, depth, depth_final;
39 control = *(unsigned short *) (ptr + 0x00);
40 ptr1 = ptr + ((control & 0x4000) >> 12);
41 /* 1. add TWAVEINC to TWAVE and write the result back */
42 /* LFO update rate is 689Hz, effect timer is in ms */
43 if (gus->gf1.timer_slave)
44 twaveinc = (689 * gus->gf1.timer_master_gus->gf1.effect_timer) / 1000;
46 twaveinc = (689 * gus->gf1.effect_timer) / 1000;
50 printk("twaveinc = 0x%x, effect_timer = %i\n", twaveinc, gus->gf1.effect_timer);
53 depth = *(unsigned short *) (ptr1 + 0x0a);
54 depth_final = *(unsigned char *) (ptr + 0x02) << 5;
55 if (depth != depth_final) {
56 depth_delta = ((twaveinc * *(ptr + 0x03)) + *(unsigned short *) (ptr + 0x04));
57 *(unsigned short *) (ptr + 0x04) = depth_delta % 8000;
59 if (depth < depth_final) {
60 if (depth + depth_delta > depth_final)
65 if (depth > depth_final) {
66 if (depth - depth_delta < depth_final)
71 *(unsigned short *) (ptr1 + 0x0a) = depth;
73 twaveinc *= (unsigned int) control & 0x7ff;
74 twaveinc += *(unsigned short *) (ptr + 0x06);
75 *(unsigned short *) (ptr + 0x06) = twaveinc % 1000;
77 twave = *(unsigned short *) (ptr1 + 0x08);
78 twave += (unsigned short) (twaveinc / (unsigned int) 1000);
79 *(unsigned short *) (ptr1 + 0x08) = twave;
81 if (!(control & 0x2000)) {
82 /* 2. if shift is low */
83 if (twave & 0x4000) { /* bit 14 high -> invert TWAVE 13-0 */
87 /* TWAVE bit 15 is exclusive or'd with the invert bit (12) */
88 twave ^= (control & 0x1000) << 3;
90 /* 2. if shift is high */
91 if (twave & 0x8000) /* bit 15 high -> invert TWAVE 14-0 */
93 /* the invert bit (12) is used as sign bit */
99 /* 3. multiply the 14-bit LFO waveform magnitude by 13-bit DEPTH */
101 printk("c=0x%x,tw=0x%x,to=0x%x,d=0x%x,df=0x%x,di=0x%x,r=0x%x,r1=%i\n",
103 *(unsigned short *) (ptr1 + 0x08),
104 depth, depth_final, *(ptr + 0x03),
105 (twave & 0x7fff) * depth, ((twave & 0x7fff) * depth) >> 21);
107 result = (twave & 0x7fff) * depth;
117 printk("lfo final value = %i\n", result);
122 static void snd_gf1_lfo_register_setup(snd_gus_card_t * gus,
123 snd_gf1_voice_t * voice,
128 if (gus->gf1.enh_mode) {
130 gf1_select_voice(gus, voice->number);
132 snd_gf1_write8(gus, GF1_VB_FREQUENCY_LFO, voice->lfo_fc);
136 snd_gf1_write8(gus, GF1_VB_VOLUME_LFO, voice->lfo_volume);
137 voice->lfo_volume = 0;
142 * ok.. with old GF1 chip can be only vibrato emulated...
143 * volume register can be in volume ramp state, so tremolo isn't simple..
149 printk("setup - %i = %i\n", voice->number, voice->lfo_fc);
152 gf1_select_voice(gus, voice->number);
153 snd_gf1_write16(gus, GF1_VW_FREQUENCY, voice->fc_register + voice->lfo_fc);
158 void snd_gf1_lfo_effect_interrupt(snd_gus_card_t * gus, snd_gf1_voice_t * voice)
163 if (voice->number != 0)
166 ptr = gus->gf1.lfos + ((voice->number) << 5);
168 if (*(unsigned short *) (ptr + 0x00) & 0x8000)
169 voice->lfo_fc = snd_gf1_lfo_compute_value(gus, ptr);
172 if (*(unsigned short *) (ptr + 0x00) & 0x8000)
173 voice->lfo_volume = snd_gf1_lfo_compute_value(gus, ptr);
174 /* 3. register setup */
175 snd_gf1_lfo_register_setup(gus, voice, 3);
182 void snd_gf1_lfo_init(snd_gus_card_t * gus)
184 if (gus->gf1.hw_lfo) {
185 snd_gf1_i_write16(gus, GF1_GW_LFO_BASE, 0x0000);
186 snd_gf1_dram_setmem(gus, 0, 0x0000, 1024);
188 snd_gf1_i_write8(gus, GF1_GB_GLOBAL_MODE, snd_gf1_i_look8(gus, GF1_GB_GLOBAL_MODE) | 0x02);
190 if (gus->gf1.sw_lfo) {
192 gus->gf1.lfos = snd_calloc(1024);
199 void snd_gf1_lfo_done(snd_gus_card_t * gus)
201 if (gus->gf1.sw_lfo) {
203 snd_gf1_free(gus->gf1.lfos, 1024);
204 gus->gf1.lfos = NULL;
209 void snd_gf1_lfo_program(snd_gus_card_t * gus, int voice, int lfo_type,
210 struct ULTRA_STRU_IW_LFO_PROGRAM *program)
212 unsigned int lfo_addr, wave_select;
214 wave_select = (program->freq_and_control & 0x4000) >> 12;
215 lfo_addr = (voice << 5) | (lfo_type << 4);
216 if (gus->gf1.hw_lfo) {
218 printk("LMCI = 0x%x\n", snd_gf1_i_look8(gus, 0x53));
219 printk("lfo_program: lfo_addr=0x%x,wave_sel=0x%x,fac=0x%x,df=0x%x,di=0x%x,twave=0x%x,depth=0x%x\n",
220 lfo_addr, wave_select,
221 program->freq_and_control,
222 program->depth_final,
227 snd_gf1_poke(gus, lfo_addr + 0x02, program->depth_final);
228 snd_gf1_poke(gus, lfo_addr + 0x03, program->depth_inc);
229 snd_gf1_pokew(gus, lfo_addr + 0x08 + wave_select, program->twave);
230 snd_gf1_pokew(gus, lfo_addr + 0x0a + wave_select, program->depth);
231 snd_gf1_pokew(gus, lfo_addr + 0x00, program->freq_and_control);
235 for (i = 0; i < 16; i++)
236 printk("%02x:", snd_gf1_peek(gus, lfo_addr + i));
241 if (gus->gf1.sw_lfo) {
242 unsigned char *ptr = gus->gf1.lfos + lfo_addr;
244 *(ptr + 0x02) = program->depth_final;
245 *(ptr + 0x03) = program->depth_inc;
246 *(unsigned short *) (ptr + 0x08 + wave_select) = program->twave;
247 *(unsigned short *) (ptr + 0x0a + wave_select) = program->depth;
248 *(unsigned short *) (ptr + 0x00) = program->freq_and_control;
252 void snd_gf1_lfo_enable(snd_gus_card_t * gus, int voice, int lfo_type)
254 unsigned int lfo_addr;
256 lfo_addr = (voice << 5) | (lfo_type << 4);
258 snd_gf1_pokew(gus, lfo_addr + 0x00, snd_gf1_peekw(gus, lfo_addr + 0x00) | 0x8000);
259 if (gus->gf1.sw_lfo) {
260 unsigned char *ptr = gus->gf1.lfos + lfo_addr;
262 *(unsigned short *) (ptr + 0x00) |= 0x8000;
266 void snd_gf1_lfo_disable(snd_gus_card_t * gus, int voice, int lfo_type)
268 unsigned int lfo_addr;
270 lfo_addr = (voice << 5) | (lfo_type << 4);
272 snd_gf1_pokew(gus, lfo_addr + 0x00,
273 snd_gf1_peekw(gus, lfo_addr + 0x00) & ~0x8000);
274 if (gus->gf1.sw_lfo) {
275 unsigned char *ptr = gus->gf1.lfos + lfo_addr;
277 *(unsigned short *) (ptr + 0x00) &= ~0x8000;
281 void snd_gf1_lfo_change_freq(snd_gus_card_t * gus, int voice,
282 int lfo_type, int freq)
284 unsigned int lfo_addr;
286 lfo_addr = (voice << 5) | (lfo_type << 4);
288 snd_gf1_pokew(gus, lfo_addr + 0x00,
289 (snd_gf1_peekw(gus, lfo_addr + 0x00) & ~0x7ff) | (freq & 0x7ff));
290 if (gus->gf1.sw_lfo) {
292 unsigned char *ptr = gus->gf1.lfos + lfo_addr;
295 *(unsigned short *) (ptr + 0x00) &= ~0x7ff;
296 *(unsigned short *) (ptr + 0x00) |= freq & 0x7ff;
301 void snd_gf1_lfo_change_depth(snd_gus_card_t * gus, int voice,
302 int lfo_type, int depth)
305 unsigned int lfo_addr;
306 unsigned short control = 0;
309 lfo_addr = (voice << 5) | (lfo_type << 4);
310 ptr = gus->gf1.lfos + lfo_addr;
312 control = snd_gf1_peekw(gus, lfo_addr + 0x00);
314 control = *(unsigned short *) (ptr + 0x00);
320 if (gus->gf1.hw_lfo) {
322 snd_gf1_poke(gus, lfo_addr + 0x02, (unsigned char) depth);
323 snd_gf1_pokew(gus, lfo_addr + 0x0a + ((control & 0x4000) >> 12), depth << 5);
324 snd_gf1_pokew(gus, lfo_addr + 0x00, control);
327 if (gus->gf1.sw_lfo) {
328 unsigned char *ptr = gus->gf1.lfos + lfo_addr;
331 *(ptr + 0x02) = (unsigned char) depth;
332 *(unsigned short *) (ptr + 0x0a + ((control & 0x4000) >> 12)) = depth << 5;
333 *(unsigned short *) (ptr + 0x00) = control;
338 void snd_gf1_lfo_setup(snd_gus_card_t * gus, int voice, int lfo_type,
339 int freq, int current_depth, int depth, int sweep,
342 struct ULTRA_STRU_IW_LFO_PROGRAM program;
344 program.freq_and_control = 0x8000 | (freq & 0x7ff);
345 if (shape & ULTRA_STRU_IW_LFO_SHAPE_POSTRIANGLE)
346 program.freq_and_control |= 0x2000;
348 program.freq_and_control |= 0x1000;
352 program.depth = current_depth;
353 program.depth_final = depth;
355 program.depth_inc = (unsigned char) (((int) ((depth << 5) - current_depth) << 9) / (sweep * 4410L));
356 if (!program.depth_inc)
359 program.depth = (unsigned short) (depth << 5);
360 snd_gf1_lfo_program(gus, voice, lfo_type, &program);
363 void snd_gf1_lfo_shutdown(snd_gus_card_t * gus, int voice, int lfo_type)
366 unsigned int lfo_addr;
368 lfo_addr = (voice << 5) | (lfo_type << 4);
369 if (gus->gf1.hw_lfo) {
370 snd_gf1_pokew(gus, lfo_addr + 0x00, 0x0000);
372 gf1_select_voice(gus, voice);
373 snd_gf1_write8(gus, lfo_type == ULTRA_LFO_VIBRATO ? GF1_VB_FREQUENCY_LFO : GF1_VB_VOLUME_LFO, 0);
376 if (gus->gf1.sw_lfo) {
377 unsigned char *ptr = gus->gf1.lfos + lfo_addr;
378 snd_gf1_voice_t *pvoice;
380 *(unsigned short *) (ptr + 0x00) = 0;
381 *(unsigned short *) (ptr + 0x04) = 0;
382 *(unsigned short *) (ptr + 0x06) = 0;
383 if (gus->gf1.syn_voices) {
384 pvoice = gus->gf1.syn_voices + voice;
385 if (lfo_type == ULTRA_LFO_VIBRATO)
388 pvoice->lfo_volume = 0;
389 snd_gf1_lfo_register_setup(gus, pvoice, lfo_type == ULTRA_LFO_VIBRATO ? 1 : 2);
390 } else if (gus->gf1.enh_mode) {
392 gf1_select_voice(gus, voice);
393 snd_gf1_write8(gus, lfo_type == ULTRA_LFO_VIBRATO ? GF1_VB_FREQUENCY_LFO : GF1_VB_VOLUME_LFO, 0);
399 void snd_gf1_lfo_command(snd_gus_card_t * gus, int voice, unsigned char *data)
405 lfo_type = *data >> 7;
406 lfo_command = *data & 0x7f;
407 switch (lfo_command) {
408 case ULTRA_LFO_SETUP: /* setup */
409 temp1 = snd_gf1_get_word(data, 2);
410 temp2 = snd_gf1_get_word(data, 4);
411 snd_gf1_lfo_setup(gus, voice, lfo_type, temp1 & 0x7ff, 0, temp2 > 255 ? 255 : temp2, snd_gf1_get_byte(data, 1), (temp1 & 0x2000) >> 13);
413 case ULTRA_LFO_FREQ: /* freq */
414 snd_gf1_lfo_change_depth(gus, voice, lfo_type, snd_gf1_get_word(data, 2));
416 case ULTRA_LFO_DEPTH: /* depth */
417 snd_gf1_lfo_change_freq(gus, voice, lfo_type, snd_gf1_get_word(data, 2));
419 case ULTRA_LFO_ENABLE: /* enable */
420 snd_gf1_lfo_enable(gus, voice, lfo_type);
422 case ULTRA_LFO_DISABLE: /* disable */
423 snd_gf1_lfo_disable(gus, voice, lfo_type);
425 case ULTRA_LFO_SHUTDOWN: /* shutdown */
426 snd_gf1_lfo_shutdown(gus, voice, lfo_type);