source: buchla-68k/ram/fpuint.s

Last change on this file was 8325447, checked in by Thomas Lopatic <thomas@…>, 7 years ago

Removed _ prefix.

  • Property mode set to 100644
File size: 30.8 KB
Line 
1| ------------------------------------------------------------------------------
2| fpuint.s -- process FPU interrupts / clear FPU
3| Version 63 -- 1988-08-31 -- D.N. Lynx Crowe
4| ------------------------------------------------------------------------------
5 .text
6
7 .xdef fpuint | process an FPU interrupt
8 .xdef fpuclr | reset the FPU
9 .xdef clrvce | quiet a voice
10
11 .xdef fputrap | a very good debug trap point
12
13 .xdef fp_resv | 'spare' function reset value table
14 .xdef fpuifnc | FPU interrupt code (voice / function)
15
16 .xref irand | ranged random number function
17 .xref scope | diagnostic scope function
18 .xref xgetran | random number function
19
20 .xref expbit
21 .xref funcndx
22 .xref initcfg
23 .xref ndisp
24 .xref pflist
25 .xref pfqhdr
26 .xref prstab
27 .xref ptoftab
28 .xref scopef
29 .xref timemlt
30 .xref trgtab
31 .xref valents
32 .xref vce2grp
33 .xref vce2trg
34 .xref veltab
35
36 .page
37| ------------------------------------------------------------------------------
38| Register usage
39| --------------
40| d0 scratch
41| d1 FPU function index
42| d2 point index from FH_CPT (idfcpt)
43| d3 scratch
44| d4 jump point number from PT_PAR1 (ippar1)
45| d5 scratch
46
47| a0 scratch
48| a1 function header base
49| a2 point table base
50| a3 FPU base
51
52| ------------------------------------------------------------------------------
53| FPU definitions
54| ---------------
55
56UPD_BIT = 0x0001 | update bit (1 = update)
57INT_BIT = 0x0002 | int. bit (0 = disable)
58RAT_BIT = 0x0004 | ratio bit (0 = ratio)
59
60VSUBNBIT = 3 | new value select bit number
61VAL_BITS = 0x0018 | new value select bit mask
62
63MSK_RNVB = 0x000C | new value / ratio bits
64MSK_ONVB = 0x0010 | old new value bit
65
66FKILL = 0x0014 | kill value for function
67FSEND = 0x0015 | send new value to function
68
69CLREXP = 0x8000 | clear value for time exponent
70CLRMNT = 0x8000 | clear value for time mantissa
71
72| ------------------------------------------------------------------------------
73| Miscellaneous definitions
74| -------------------------
75
76PCHMAX = 21920 | maximum pitch value
77VALMAX = 32000 | maximum value to send to FPU
78VALMIN = -32000 | minimum value to send to FPU
79
80LSPCH = 2 | left shift for sources to freq
81
82VALLEN = 10 | length of the 'valent' struct
83VT_VAL = 8 | value offset in 'valent'
84
85 .page
86| ------------------------------------------------------------------------------
87| FPU addresses
88| -------------
89
90FPUBASE = 0x180000 | FPU base address
91
92FPUWST = FPUBASE | FPU waveshape base
93FPUFUNC = FPUBASE+0x4000 | FPU function base
94FPUINT1 = FPUBASE+0x4000 | FPU int. input address (R/O)
95FPUINT2 = FPUBASE+0x6000 | FPU int. reset address (W/O)
96FPUCFG = FPUBASE+0x5FE0 | FPU config. data address (W/O)
97
98F_CTL = 0x00 | control word
99F_VAL10 = 0x02 | new value "10"
100F_CV1 = 0x08 | control voltage 1
101F_SF1 = 0x0A | scale factor 1
102F_CV2 = 0x0C | control voltage 2
103F_SF2 = 0x0E | scale factor 2
104F_CV3 = 0x10 | control voltage 3
105F_SF3 = 0x12 | scale factor 3
106F_MNT = 0x14 | time mantissa
107F_EXP = 0x16 | time exponent
108F_VAL01 = 0x1C | new value "01"
109
110P_FREQ1 = 0x0020 | frequency 1
111P_FREQ2 = 0x0060 | frequency 2
112P_FREQ3 = 0x00A0 | frequency 3
113P_FREQ4 = 0x00E0 | frequency 4
114P_FILTER = 0x0140 | filter
115P_FILTRQ = 0x00C0 | filter q
116
117P_INDEX1 = 0x0120 | index 1
118P_INDEX2 = 0x0160 | index 2
119P_INDEX3 = 0x0180 | index 3
120P_INDEX4 = 0x01A0 | index 4
121P_INDEX5 = 0x01C0 | index 5
122P_INDEX6 = 0x01E0 | index 6
123
124P_LEVEL = 0x0040 | level
125
126P_LOCN = 0x0080 | location
127P_DYNAM = 0x0100 | dynamics
128
129 .page
130| ------------------------------------------------------------------------------
131| Structure definitions
132| ------------------------------------------------------------------------------
133| The following MUST match the idfnhdr structure definition in instdsp.h:
134
135FH_LEN = 12 | length of the idfnhdr structure
136
137FH_PCH = 0 | WORD - pitch offset (freq1 only)
138FH_MLT = 2 | WORD - overall value multiplier
139FH_SRC = 4 | BYTE - overall value source
140FH_PIF = 5 | BYTE - # of points in the function
141FH_PT1 = 6 | BYTE - index of first point
142FH_TMD = 7 | BYTE - trigger mode / control bits
143FH_CPT = 8 | BYTE - current point
144FH_PRM = 9 | BYTE - misc. function parameter
145FH_TRG = 10 | WORD - trigger
146
147I_ACTIVE = 1 | 'Active' bit number (in FH_TMD)
148
149MSK_CTL = 0x001C | mask for FPU hardware bits (in FH_TMD)
150
151| ------------------------------------------------------------------------------
152| The following MUST match the instpnt structure definition in instdsp.h:
153
154PT_LEN = 12 | length of the instpnt structure
155
156PT_TIM = 0 | WORD - time (packed)
157PT_VAL = 2 | WORD - value
158PT_VMLT = 4 | WORD - value multiplier
159PT_VSRC = 6 | BYTE - value source
160PT_ACT = 7 | BYTE - action
161PT_PAR1 = 8 | BYTE - parameter 1
162PT_PAR2 = 9 | BYTE - parameter 2
163PT_PAR3 = 10 | BYTE - parameter 3
164PT_PAD = 11 | BYTE - padding for even boundary
165
166MSK_MNT = 0xFFF0 | mask for mantissa (in PT_TIM)
167MSK_EXP = 0x000F | mask for exponent (in PT_TIM)
168
169MAX_ACT = 7 | maximum action code value
170
171 .page
172
173| ------------------------------------------------------------------------------
174| pflist definitions -- must match those in instdsp.h
175
176PF_NEXT = 0
177PF_TRIG = 4
178PF_FUNC = 6
179PF_D1 = 8
180PF_D2 = 12
181PF_D4 = 16
182PF_A1 = 20
183PF_A2 = 24
184PF_A3 = 28
185| ------------------------------------------------------------------------------
186| Source definitions -- must match those in 'smdefs.h'
187
188SM_RAND = 1 | random
189SM_PTCH = 5 | pitch
190SM_KPRS = 6 | key pressure
191SM_KVEL = 7 | key velocity
192SM_FREQ = 10 | frequency
193
194 .page
195| ------------------------------------------------------------------------------
196| fpuint() -- process FPU interrupts
197
198| void
199| fpuint();
200
201| Processes FPU interrupts. Must be the target of vector 26,
202| which is Autovector Interrupt level 2.
203
204| ------------------------------------------------------------------------------
205
206fpuint: movem.l d0-d5/a0-a3,-(a7) | preserve registers we use
207 move.w FPUINT1,d0 | read FPU interrupt status
208 andi.w #0x00FF,d0 | mask out garbage in MS bits
209 move.w d0,fpuifnc | save for later use
210 move.w ndisp,d1 | get display number
211 cmpi.w #11,d1 | see if we display
212 bne nodisp | jump if not
213
214 tst.w scopef | ...
215 beq nodisp | ...
216
217 move.w d0,-(a7) | display value
218 jsr scope | ...
219 tst.w (a7)+ | ...
220
221 move.w fpuifnc,d0 | get FPU status
222
223nodisp: move.w d0,d1 | save in d1 (becomes function offset)
224
225 lsl.w #5,d1 | develop FPU function offset
226 lea FPUFUNC,a3 | setup FPU function base address
227
228 lsl.w #3,d0 | develop funcndx[] index
229 lea funcndx,a0 | setup funcndx[] base address
230
231 tst.l 0(a0,d0.W) | see if function is defined
232 bne fnok | jump if so
233
234 move.w d1,d0 | get function offset in d0
235 andi.w #0x1E00,d0 | mask for voice number
236 cmpi.w #0x1800,d0 | see if it's a real voice (0..11)
237 bge fpexit | don't send a kill if not a real voice
238
239 move.w #FKILL,F_CTL(a3,d1.W) | kill the undefined function
240
241fpexit: clr.w FPUINT2 | reset the FPU interrupt latch
242 movem.l (a7)+,d0-d5/a0-a3 | restore the registers
243 rte | return to interrupted code
244
245 .page
246| ------------------------------------------------------------------------------
247| set up to process active functions, stop ones that should be inactive
248| ------------------------------------------------------------------------------
249fnok: movea.l 0(a0,d0.W),a1 | get pointer to function header
250 movea.l 4(a0,d0.W),a2 | get pointer to point table
251 btst #I_ACTIVE,FH_TMD(a1) | see if function is active
252 bne doact | go process action if so
253
254| ------------------------------------------------------------------------------
255| stop a function
256| ------------------------------------------------------------------------------
257stopfn: move.b FH_TMD(a1),d0 | get function control bits
258 andi.w #MSK_RNVB,d0 | mask for ratio / new new-value bit
259 move.w d0,d3 | isolate new new-value bit
260 add.w d3,d3 | ... from function header
261 andi.w #MSK_ONVB,d3 | ... shift to old new-value bit
262 or.w d3,d0 | ... and put new bit in old bit
263 move.w d0,F_CTL(a3,d1.W) | stop the function
264 bclr #I_ACTIVE,FH_TMD(a1) | reset the active bit
265 bra fpexit | go restore registers and exit
266
267 .page
268| ------------------------------------------------------------------------------
269| setup for and dispatch to the proper action handler
270| ------------------------------------------------------------------------------
271doact: clr.w d2 | get current point index in d2
272 move.b FH_CPT(a1),d2 | ...
273 lsl.w #2,d2 | multiply it by the length of a point
274 move.w d2,d0 | ... (fast multiply by PT_LEN = 12
275 add.w d2,d2 | ... via shift and add)
276 add.w d0,d2 | ...
277 clr.w d4 | get jump point # into d4
278 move.b PT_PAR1(a2,d2.W),d4 | ...
279 clr.w d3 | get action code in d3
280 move.b PT_ACT(a2,d2.W),d3 | ...
281 cmpi.b #MAX_ACT,d3 | check against the limit
282 bgt stopfn | stop things if it's a bad action code
283
284 lsl.w #2,d3 | develop index to action dispatch table
285 lea actab,a0 | get the address of the action handler
286 movea.l 0(a0,d3.W),a0 | ...
287
288| ------------------------------------------------------------------------------
289| At this point we're ready to do the action associated with the point,
290| and the registers are set up, and will remain, as follows:
291
292| d1 FPU function index a1 function header base
293| d2 point table index a2 point table base
294| a3 FPU function base
295| d4 jump point number
296
297| d0, d3, d5, and a0 are used as scratch throughout the code.
298
299| ------------------------------------------------------------------------------
300
301fputrap: jmp (a0) | dispatch to action handler
302
303 .page
304| ------------------------------------------------------------------------------
305| act0 -- AC_NULL -- no action
306| ---- --------------------
307act0: move.b FH_PT1(a1),d0 | get first point number
308 add.b FH_PIF(a1),d0 | add number of points in function
309 subq.b #1,d0 | make it last point number
310 cmp.b FH_CPT(a1),d0 | see if we're at the last point
311 beq stopfn | stop function if so
312
313 addq.b #1,FH_CPT(a1) | update function header for next point
314 addi.w #PT_LEN,d2 | advance the point index
315
316| ------------------------------------------------------------------------------
317| outseg -- output a segment
318| ------ ----------------
319outseg: move.w PT_TIM(a2,d2.w),d3 | get packed time
320 move.w d3,d0 | extract mantissa
321 andi.w #MSK_MNT,d0 | ...
322 mulu timemlt,d0 | multiply by panel time pot value
323 lsr.l #8,d0 | ... and scale it
324 lsr.l #7,d0 | ...
325 move.w d0,F_MNT(a3,d1.W) | send mantissa to FPU
326 andi.w #MSK_EXP,d3 | extract exponent code
327 add.w d3,d3 | look up decoded exponent
328 lea expbit,a0 | ... in expbit
329 move.w 0(a0,d3.W),F_EXP(a3,d1.W) | send exponent to FPU
330 move.w PT_VAL(a2,d2.W),d3 | get the function value
331
332| ------------------------------------------------------------------------------
333| get the point source, if any
334| ------------------------------------------------------------------------------
335 tst.w PT_VMLT(a2,d2.W) | see if we have a point mlt.
336 beq nosrc | don't do anything for zero
337
338 clr.w d0 | get the source number
339 move.b PT_VSRC(a2,d2.W),d0 | ...
340 beq nosrc | don't do anything for zero
341
342| ------------------------------------------------------------------------------
343| SM_RAND -- random
344| ------------------------------------------------------------------------------
345 cmpi.w #SM_RAND,d0 | is this the random source ?
346 bne srctyp0 | jump if not
347
348 movem.l d1-d2/a0-a2,-(a7) | preserve registers around call
349 move.w PT_VMLT(a2,d2.W),-(a7) | pass multiplier to xgetran()
350 jsr xgetran | call for a random number
351 tst.w (a7)+ | clean up stack
352 movem.l (a7)+,d1-d2/a0-a2 | restore registers
353 move.w d0,d5 | put random value in the value register
354 bra applym | go apply the multiplier
355
356 .page
357| ------------------------------------------------------------------------------
358| SM_FREQ -- frequency
359| ------------------------------------------------------------------------------
360srctyp0: cmpi.w #SM_FREQ,d0 | is this the frequency source ?
361 bne srctyp1 | jump if not
362
363 move.w (a1),d0 | get the pitch
364 lsr.w #6,d0 | shift to a word index
365 andi.w #0x01FE,d0 | mask out extraneous bits
366 lea ptoftab,a0 | get entry from ptoftab[]
367 move.w 0(a0,d0.W),d5 | ...
368 bra applym | go apply the multiplier
369
370| ------------------------------------------------------------------------------
371| SM_PTCH -- pitch
372| ------------------------------------------------------------------------------
373srctyp1: cmpi.w #SM_PTCH,d0 | is this the pitch source ?
374 bne srctyp2 | jump if not
375
376 move.w (a1),d5 | get the pitch as the value
377 bra applym | go apply the multiplier
378
379| ------------------------------------------------------------------------------
380| SM_KVEL -- velocity
381| ------------------------------------------------------------------------------
382srctyp2: cmpi.w #SM_KVEL,d0 | is this the key velocity source ?
383 bne srctyp3 | jump if not
384
385 move.w FH_TRG(a1),d0 | get the trigger number
386 add.w d0,d0 | ... as a word index
387 lea veltab,a0 | ... into veltab[]
388 move.w 0(a0,d0.W),d5 | get the velocity from veltab[trg]
389 bra applym | go apply the multiplier
390
391| ------------------------------------------------------------------------------
392| SM_KPRS -- pressure
393| ------------------------------------------------------------------------------
394srctyp3: cmpi.w #SM_KPRS,d0 | is this the key pressure source ?
395 bne srctyp4 | jump if not (must be an analog input)
396
397 move.w FH_TRG(a1),d0 | get the trigger number
398 add.w d0,d0 | ... as a word index
399 lea prstab,a0 | ... into prstab[]
400 move.w 0(a0,d0.W),d5 | get the pressure from prstab[trg]
401 bra applym | go apply the multiplier
402
403 .page
404| ------------------------------------------------------------------------------
405| all other sources come out of the valents[] array
406| ------------------------------------------------------------------------------
407srctyp4: lea vce2grp,a0 | point at vce2grp[]
408 move.w fpuifnc,d5 | get voice number in d5
409 lsr.w #3,d5 | ...
410 andi.w #0x001E,d5 | ... as a word index
411 move.w 0(a0,d5.W),d5 | get the group number
412 subq.w #1,d5 | ...
413 lsl.w #4,d5 | shift it left a nybble
414 or.w d5,d0 | OR it into the source number
415 add.w d0,d0 | make source number a valents[] index
416 move.w d0,d5 | ... (fast multiply by VALLEN = 10
417 lsl.w #2,d0 | ... via shift and add)
418 add.w d5,d0 | ...
419 lea valents,a0 | get base of valents[]
420 move.w VT_VAL(a0,d0.W),d5 | get value
421
422| ------------------------------------------------------------------------------
423| apply the multiplier to the source, and add it to the function value
424| ------------------------------------------------------------------------------
425applym: muls PT_VMLT(a2,d2.W),d5 | apply the multiplier
426 asr.l #7,d5 | scale the result
427 asr.l #8,d5 | ...
428 ext.l d3 | add the function value
429 add.l d3,d5 | ...
430 cmpi.l #VALMAX,d5 | check for overflow
431 ble srcmlt1 | jump if no overflow
432
433 move.l #VALMAX,d5 | limit at VALMAX
434 bra srcmlt2 | ...
435
436srcmlt1: cmpi.l #VALMIN,d5 | check for underflow
437 bge srcmlt2 | jump if no underflow
438
439 move.l #VALMIN,d5 | limit at VALMIN
440
441srcmlt2: move.w d5,d3 | setup value for output to FPU
442
443 .page
444| ------------------------------------------------------------------------------
445| adjust the value according to the function type
446| ------------------------------------------------------------------------------
447nosrc: move.w d1,d0 | get function type
448 andi.w #0x01E0,d0 | ...
449
450| ------------------------------------------------------------------------------
451| level or location
452| ------------------------------------------------------------------------------
453 cmpi.w #P_LEVEL,d0 | see if it's the level
454 beq outsegl | jump if so
455
456 cmpi.w #P_LOCN,d0 | see if it's the location
457 bne outsegf | jump if not
458
459 tst.w d3 | check sign of value
460 bpl outsegc | jump if positive
461
462 clr.w d3 | force negative values to 0
463
464outsegc: asr.w #5,d3 | shift value to LS bits
465 sub.w #500,d3 | subtract 5.00 from value
466 asl.w #6,d3 | readjust to MS bits
467 bra outseg3 | go output the value
468
469outsegl: tst.w d3 | check sign of value
470 bpl outsegm | jump if positive
471
472 clr.w d3 | limit negative values at 0
473
474outsegm: asr.w #5,d3 | shift value to LS bits
475 sub.w #500,d3 | subtract 5.00 from value
476 asl.w #6,d3 | readjust to MS bits
477 bra outseg3 | go output the value
478
479 .page
480| ------------------------------------------------------------------------------
481| filter
482| ------------------------------------------------------------------------------
483outsegf: cmpi.w #P_FILTER,d0 | see if it's filter
484 bne outsegp | jump if not
485
486 ext.l d3 | make function value a long
487 asr.l #1,d3 | multiply function value by .75
488 move.l d3,d0 | ... (fast multiply by .75
489 asr.l #1,d0 | ... via shift and add)
490 add.l d0,d3 | ...
491 move.w (a1),d0 | add pitch
492 ext.l d0 | ...
493 add.l d0,d3 | ...
494 cmpi.l #VALMAX,d3 | see if it's within limits
495 ble outsega | ...
496
497 move.w #VALMAX,d3 | limit at VALMAX
498 bra outseg3 | ...
499
500outsega: cmpi.l #VALMIN,d3 | ...
501 bge outseg3 | ...
502
503 move.w #VALMIN,d3 | limit at VALMIN
504 bra outseg3 | ...
505
506 .page
507| ------------------------------------------------------------------------------
508| freq 1..4
509| ------------------------------------------------------------------------------
510outsegp: cmpi.w #P_FREQ1,d0 | see if it's freq1
511 beq outseg0 | go process freq1
512
513outsegq: cmpi.w #P_FREQ2,d0 | see if it's freq2
514 beq outseg0 | process it if so
515
516 cmpi.w #P_FREQ3,d0 | see if it's freq3
517 beq outseg0 | process it if so
518
519 cmpi.w #P_FREQ4,d0 | see if it's freq4
520 bne outseg3 | jump if not
521
522outseg0: ext.l d3 | scale the point value to cents offset
523 asr.l #5,d3 | ...
524 sub.l #500,d3 | ... value - 500
525 asl.l #LSPCH,d3 | mult. by 2 and scale for 1/2 cent lsb
526 move.w (a1),d0 | add pitch from function header
527 ext.l d0 | ...
528 add.l d0,d3 | ...
529 cmp.l #PCHMAX,d3 | see if result is valid
530 ble outseg3 | jump if within pitch limits
531
532 move.l #PCHMAX,d3 | limit at maximum pitch
533
534| ------------------------------------------------------------------------------
535| send the value to the FPU
536| ------------------------------------------------------------------------------
537outseg3: move.b FH_TMD(a1),d0 | get hardware bits from function header
538 eor.w #VAL_BITS,d0 | toggle new value select bits
539 move.b d0,FH_TMD(a1) | store updated word
540 btst.l #VSUBNBIT,d0 | check which value address to use
541 beq outseg1
542
543 move.w d3,F_VAL01(a3,d1.W) | send value to FPU
544 bra outseg2
545
546outseg1: move.w d3,F_VAL10(a3,d1.W) | send value to FPU
547
548outseg2: andi.w #MSK_CTL,d0 | mask off software bits
549 ori.w #UPD_BIT+INT_BIT,d0 | set the update & !lastseg bits
550 move.w d0,F_CTL(a3,d1.W) | send control word to FPU
551 bra fpexit | done -- exit
552
553 .page
554
555| ------------------------------------------------------------------------------
556| act1 -- AC_SUST -- pause if key is down (sustain)
557| ---- ------------------------------------------
558act1: move.w fpuifnc,d0 | get voice as a word index
559 lsr.w #3,d0 | ...
560 andi.w #0x001E,d0 | ...
561 lea vce2trg,a0 | point at voice to trigger table
562 move.w 0(a0,d0.W),d0 | get trigger table entry into d0
563 cmpi.w #-1,d0 | see if voice is free
564 beq act0 | continue function if so
565
566 btst #15,d0 | see if voice is held by a pedal
567 bne act1a | sustain if so
568
569 btst #14,d0 | see if voice is sustained by a pedal
570 bne act1a | sustain if so
571
572 lea trgtab,a0 | point at trigger table
573 tst.b 0(a0,d0.W) | check trigger status
574 beq act0 | continue function if not active
575
576act1a: move.l pfqhdr,d3 | see if any pflist entries remain
577 beq act0 | continue if not (shouldn't happen!)
578
579 move.b FH_PT1(a1),d0 | get first point number
580 add.b FH_PIF(a1),d0 | add base to first point
581 subq.b #1,d0 | make d0 last point number
582 cmp.b FH_CPT(a1),d0 | check current point number
583 beq stopfn | done if this is the last point
584
585 addq.b #1,FH_CPT(a1) | update current point number
586 addi.w #PT_LEN,d2 | advance the point index
587 movea.l d3,a0 | acquire a new pflist entry
588 move.l (a0),pfqhdr | ...
589 move.l pflist,(a0) | chain it to pflist
590 move.l a0,pflist | ...
591 move.w FH_TRG(a1),PF_TRIG(a0) | set trigger number in entry
592 move.w fpuifnc,PF_FUNC(a0) | set v/p word in entry
593 movem.l d1-d2/d4/a1-a3,PF_D1(a0) | set registers in entry
594 move.b FH_TMD(a1),d0 | stop the function
595 andi.w #MSK_RNVB,d0 | ...
596 move.w d0,d3 | ...
597 add.w d3,d3 | ...
598 andi.w #MSK_ONVB,d3 | ...
599 or.w d3,d0 | ...
600 move.w d0,F_CTL(a3,d1.W) | ...
601 bra fpexit | exit
602
603 .page
604
605| ------------------------------------------------------------------------------
606| act2 -- AC_ENBL -- stop if key is up
607| ---- ----------------------------
608act2: move.w fpuifnc,d0 | get voice as a word index
609 lsr.w #3,d0 | ...
610 andi.w #0x001E,d0 | ...
611 lea vce2trg,a0 | check to see if voice is free
612 move.w 0(a0,d0.W),d0 | ...
613 cmpi.w #-1,d0 | ...
614 beq stopfn | if so, stop the function
615
616 btst #15,d0 | see if voice is held
617 bne act0 | continue if so
618
619 btst #14,d0 | ...
620 bne act0 | ...
621
622 lea trgtab,a0 | check trigger table entry
623 tst.b 0(a0,d0.W) | ...
624 bne act0 | if trigger is active, continue
625
626 bra stopfn | if not, stop the function
627
628| ------------------------------------------------------------------------------
629| act3 -- AC_JUMP -- unconditional jump
630| ---- -----------------------------
631act3: cmp.b FH_PIF(a1),d4 | check jump point against limit
632 bcc stopfn | stop function if jump point invalid
633
634 clr.w d2 | get index of first point
635 move.b FH_PT1(a1),d2 | ...
636 add.b d4,d2 | add jump point
637 move.b d2,FH_CPT(a1) | make it the current point
638 lsl.w #2,d2 | develop new point index in d2
639 move.w d2,d0 | ... (fast multiply by PT_LEN = 12
640 add.w d2,d2 | ... via shift and add)
641 add.w d0,d2 | ...
642 bra outseg | output the segment
643
644 .page
645
646| ------------------------------------------------------------------------------
647| act4 -- AC_LOOP -- jump to point PT_PAR1 PT_PAR2 times
648| ---- ----------------------------------------------
649act4: tst.b PT_PAR3(a2,d2.W) | check counter
650 bne act4a | jump if it's running
651
652 move.b PT_PAR2(a2,d2.W),d0 | get parameter
653 subi.w #90,d0 | put parameter in random range
654 bmi act4b | treat as normal if < 90
655
656 movem.l d1-d2/a0-a2,-(a7) | get ranged random number
657 move.w d0,-(a7) | ...
658 jsr irand | ...
659 tst.w (a7)+ | ...
660 movem.l (a7)+,d1-d2/a0-a2 | ...
661 move.b d0,PT_PAR3(a2,d2.w) | set counter
662 beq act0 | next segment if cntr set to 0
663
664 bra act3 | else jump to the point
665
666act4b: move.b PT_PAR2(a2,d2.W),PT_PAR3(a2,d2.W) | set counter
667 beq act0 | next segment if cntr set to 0
668
669 bra act3 | else jump to the point
670
671act4a: subq.b #1,PT_PAR3(a2,d2.W) | decrement counter
672 beq act0 | next segment if cntr ran out
673
674 bra act3 | jump if it's still non-zero
675
676| ------------------------------------------------------------------------------
677| act5 -- AC_KYUP -- jump if key is up
678| ---- ----------------------------
679act5: move.w fpuifnc,d0 | get voice as a word index
680 lsr.w #3,d0 | ...
681 andi.w #0x001E,d0 | ...
682 lea vce2trg,a0 | check to see if voice is free
683 move.w 0(a0,d0.W),d0 | ...
684 cmpi.w #-1,d0 | ...
685 beq act3 | if so (inactive), do the jump
686
687 btst #15,d0 | see if voice is held
688 bne act0 | continue if so
689
690 btst #14,d0 | ...
691 bne act0 | ...
692
693 lea trgtab,a0 | check trigger table entry
694 tst.b 0(a0,d0.W) | see if the trigger is active
695 beq act3 | if not, do the jump
696
697 bra act0 | if so, do next segment
698
699 .page
700
701| ------------------------------------------------------------------------------
702| act6 -- AC_KYDN -- jump if key is down
703| ---- ------------------------------
704act6: move.w fpuifnc,d0 | get voice as a word index
705 lsr.w #3,d0 | ...
706 andi.w #0x001E,d0 | ...
707 lea vce2trg,a0 | check to see if voice is free
708 move.w 0(a0,d0.W),d0 | ...
709 cmpi.w #-1,d0 | ...
710 beq act0 | if so (inactive), continue
711
712 btst #15,d0 | see if voice is held
713 bne act3 | do jump if so
714
715 btst #14,d0 | ...
716 bne act3 | ...
717
718 lea trgtab,a0 | check trigger table entry
719 tst.b 0(a0,d0.W) | see if the trigger is active
720 bne act3 | if so, do the jump
721
722 bra act0 | if not, do next segment
723
724| ------------------------------------------------------------------------------
725| Test stub
726| ---------
727act7: bra act0 | AC_HERE: treat act7 as AC_NULL
728
729 .page
730| ------------------------------------------------------------------------------
731
732| fpuclr -- clear the FPU
733| ------ -------------
734
735| void
736| fpuclr()
737
738| Resets the FPU functions to their nominal values.
739
740| ------------------------------------------------------------------------------
741
742fpuclr: link a6,#0 | link stack frames
743 move.w sr,-(a7) | save the interrupt level
744 ori.w #0x0700,sr | turn off interrupts
745
746 lea FPUFUNC,a0 | point at the first function
747 lea fp_resv,a2 | point at reset value table
748 move.w #11,d1 | set the outer loop count
749
750 .page
751| ------------------------------------------------------------------------------
752| reset the 'spare' function for the voice
753| ------------------------------------------------------------------------------
754clr0: move.w #CLREXP,F_EXP(a0) | set time exponent
755 tst.l actab | delay
756 tst.l actab | ...
757 move.w #CLRMNT,F_MNT(a0) | set time mantissa
758 tst.l actab | delay
759 tst.l actab | ...
760
761 move.w #0,F_SF3(a0) | set scale factor 3
762 tst.l actab | delay
763 tst.l actab | ...
764 move.w #0,F_CV3(a0) | set voltage 3
765 tst.l actab | delay
766 tst.l actab | ...
767
768 move.w #0,F_SF2(a0) | set scale factor 2
769 tst.l actab | delay
770 tst.l actab | ...
771 move.w #0,F_CV2(a0) | set voltage 2
772 tst.l actab | delay
773 tst.l actab | ...
774
775 move.w #0,F_SF1(a0) | set scale factor 1
776 tst.l actab | delay
777 tst.l actab | ...
778 move.w #0,F_CV1(a0) | set voltage 1
779 tst.l actab | delay
780 tst.l actab | ...
781
782 move.w (a2),F_VAL10(a0) | set value from variable table
783 tst.l actab | delay
784 tst.l actab | ...
785 move.w (a2)+,F_VAL01(a0) | ...
786 tst.l actab | delay
787 tst.l actab | ...
788 move.w #FSEND,F_CTL(a0) | set control word
789 tst.l actab | delay
790 tst.l actab | ...
791
792 .page
793 adda.w #0x0020,a0 | point at 2nd function
794 lea fprescon,a1 | set reset constant pointer
795 move.w #14,d0 | set inner loop count
796
797| ------------------------------------------------------------------------------
798| reset the other functions for the voice
799| ------------------------------------------------------------------------------
800clr1: move.w #CLREXP,F_EXP(a0) | set time exponent
801 tst.l actab | delay
802 tst.l actab | ...
803 move.w #CLRMNT,F_MNT(a0) | set time mantissa
804 tst.l actab | delay
805 tst.l actab | ...
806
807 move.w #0,F_SF3(a0) | set scale factor 3
808 tst.l actab | delay
809 tst.l actab | ...
810 move.w #0,F_CV3(a0) | set voltage 3
811 tst.l actab | delay
812 tst.l actab | ...
813
814 move.w #0,F_SF2(a0) | set scale factor 2
815 tst.l actab | delay
816 tst.l actab | ...
817 move.w #0,F_CV2(a0) | set voltage 2
818 tst.l actab | delay
819 tst.l actab | ...
820
821 move.w #0,F_SF1(a0) | set scale factor 1
822 tst.l actab | delay
823 tst.l actab | ...
824 move.w #0,F_CV1(a0) | set voltage 1
825 tst.l actab | delay
826 tst.l actab | ...
827
828 move.w (a1),F_VAL10(a0) | set value from constant table
829 tst.l actab | delay
830 tst.l actab | ...
831 move.w (a1)+,F_VAL01(a0) | ...
832 tst.l actab | delay
833 tst.l actab | ...
834 move.w #FSEND,F_CTL(a0) | set control word
835 tst.l actab | delay
836 tst.l actab | ...
837
838 .page
839| ------------------------------------------------------------------------------
840| loop through reset for all of the voices and functions
841| ------------------------------------------------------------------------------
842 adda.w #0x0020,a0 | point at next function
843 dbra d0,clr1 | loop until all funcs. cleared
844
845 dbra d1,clr0 | loop until all voices cleared
846| ------------------------------------------------------------------------------
847| clear the FPU interrupt, and return
848| ------------------------------------------------------------------------------
849 move.w #0,FPUINT2 | clear FPU interrupt
850 move.w (a7)+,sr | restore interrupts
851 unlk a6 | unlink stack frames
852 rts | return to caller
853
854 .page
855
856| clrvce -- quiet a voice
857| ------ -------------
858
859| void
860| clrvce(vce)
861| short vce;
862
863| Quiet the voice by resetting the FPU functions it uses.
864
865clrvce: link a6,#0 | link stack frames
866 move.w sr,-(a7) | save the interrupt level
867 ori.w #0x0700,sr | turn off interrupts
868
869 lea FPUFUNC+0x20,a0 | point at the 2nd function
870 move.w 8(a6),d0 | get voice number
871 ext.l d0 | ...
872 lsl.l #8,d0 | shift into position
873 add.l d0,d0 | ...
874 adda.l d0,a0 | add to function base
875 lea fprescon,a1 | set reset constant pointer
876 move.w #14,d0 | set inner loop count
877
878vclr1: move.l a0,d1 | see if we reset this function
879 and.w #0x01F0,d1 | ...
880
881 cmpi.w #0x0100,d1 | dynamics ?
882 beq vclr2 | skip it if so
883
884 move.w #CLREXP,F_EXP(a0) | set time exponent
885 tst.l actab | delay
886 tst.l actab | ...
887 move.w #CLRMNT,F_MNT(a0) | set time mantissa
888 tst.l actab | delay
889 tst.l actab | ...
890
891 cmpi.w #0x0020,d1 | freq 1 ?
892 beq vclr3 | don't reset CV3 (fine tune)
893
894 move.w #0,F_SF3(a0) | set scale factor 3
895 tst.l actab | delay
896 tst.l actab | ...
897 move.w #0,F_CV3(a0) | set voltage 3
898 tst.l actab | delay
899 tst.l actab | ...
900
901vclr3: move.w #0,F_SF1(a0) | set scale factor 1
902 tst.l actab | delay
903 tst.l actab | ...
904 move.w #0,F_CV1(a0) | set voltage 1
905 tst.l actab | delay
906 tst.l actab | ...
907
908 .page
909
910 move.w (a1),F_VAL10(a0) | set value from constant table
911 tst.l actab | delay
912 tst.l actab | ...
913 move.w (a1),F_VAL01(a0) | ...
914 tst.l actab | delay
915 tst.l actab | ...
916 move.w #FSEND,F_CTL(a0) | set control word
917 tst.l actab | delay
918 tst.l actab | ...
919
920vclr2: adda.w #2,a1 | point at next function
921 adda.w #0x0020,a0 |
922 dbra d0,vclr1 | loop until all funcs. cleared
923
924 move.w (a7)+,sr | restore interrupts
925 unlk a6 | unlink stack frames
926 rts | return to caller
927
928 .page
929| ------------------------------------------------------------------------------
930 .data
931| ------------------------------------------------------------------------------
932
933| actab -- action code dispatch table
934| ----- --------------------------
935actab: .dc.l act0 | 0 - AC_NULL: no action
936 .dc.l act1 | 1 - AC_SUST: sustain
937 .dc.l act2 | 2 - AC_ENBL: enable
938 .dc.l act3 | 3 - AC_JUMP: unconditional jump
939 .dc.l act4 | 4 - AC_LOOP: jump n times (loop)
940 .dc.l act5 | 5 - AC_KYUP: jump if key up (enable jump)
941 .dc.l act6 | 6 - AC_KYDN: jump if key down (sustain jump)
942 .dc.l act7 | 7 - AC_HERE: here on key up
943
944| fprescon -- FPU reset constant table
945| -------- ------------------------
946fprescon: .dc.w 0x0000 | frq 1 0.00
947 .dc.w 0x8300 | level -10.00
948 .dc.w 0x0000 | frq 2 0.00
949 .dc.w 0x0000 | locn 0.00
950 .dc.w 0x0000 | frq 3 0.00
951 .dc.w 0x0000 | reson 0.00
952 .dc.w 0x0000 | frq 4 0.00
953 .dc.w 0x7D00 | dyn +10.00
954 .dc.w 0x0000 | ind 1 0.00
955 .dc.w 0x3E80 | filt +5.00
956 .dc.w 0x0000 | ind 2 0.00
957 .dc.w 0x0000 | ind 3 0.00
958 .dc.w 0x0000 | ind 4 0.00
959 .dc.w 0x0000 | ind 5 0.00
960 .dc.w 0x0000 | ind 6 0.00
961
962| ------------------------------------------------------------------------------
963 .bss
964| ------------------------------------------------------------------------------
965
966fp_resv: .ds.w 12 | fpu spare function reset values
967fpuifnc: .ds.w 1 | interrupting function number from FPU
968
969 .end
Note: See TracBrowser for help on using the repository browser.