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

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

Added RAM files.

  • Property mode set to 100644
File size: 32.2 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 .equ $0001 * update bit (1 = update)
57INT_BIT .equ $0002 * int. bit (0 = disable)
58RAT_BIT .equ $0004 * ratio bit (0 = ratio)
59*
60VSUBNBIT .equ 3 * new value select bit number
61VAL_BITS .equ $0018 * new value select bit mask
62*
63MSK_RNVB .equ $000C * new value / ratio bits
64MSK_ONVB .equ $0010 * old new value bit
65*
66FKILL .equ $0014 * kill value for function
67FSEND .equ $0015 * send new value to function
68*
69CLREXP .equ $8000 * clear value for time exponent
70CLRMNT .equ $8000 * clear value for time mantissa
71*
72* ------------------------------------------------------------------------------
73* Miscellaneous definitions
74* -------------------------
75*
76PCHMAX .equ 21920 * maximum pitch value
77VALMAX .equ 32000 * maximum value to send to FPU
78VALMIN .equ -32000 * minimum value to send to FPU
79*
80LSPCH .equ 2 * left shift for sources to freq
81*
82VALLEN .equ 10 * length of the 'valent' struct
83VT_VAL .equ 8 * value offset in 'valent'
84*
85 .page
86* ------------------------------------------------------------------------------
87* FPU addresses
88* -------------
89*
90FPUBASE .equ $180000 * FPU base address
91*
92FPUWST .equ FPUBASE * FPU waveshape base
93FPUFUNC .equ FPUBASE+$4000 * FPU function base
94FPUINT1 .equ FPUBASE+$4000 * FPU int. input address (R/O)
95FPUINT2 .equ FPUBASE+$6000 * FPU int. reset address (W/O)
96FPUCFG .equ FPUBASE+$5FE0 * FPU config. data address (W/O)
97*
98F_CTL .equ $00 * control word
99F_VAL10 .equ $02 * new value "10"
100F_CV1 .equ $08 * control voltage 1
101F_SF1 .equ $0A * scale factor 1
102F_CV2 .equ $0C * control voltage 2
103F_SF2 .equ $0E * scale factor 2
104F_CV3 .equ $10 * control voltage 3
105F_SF3 .equ $12 * scale factor 3
106F_MNT .equ $14 * time mantissa
107F_EXP .equ $16 * time exponent
108F_VAL01 .equ $1C * new value "01"
109*
110P_FREQ1 .equ $0020 * frequency 1
111P_FREQ2 .equ $0060 * frequency 2
112P_FREQ3 .equ $00A0 * frequency 3
113P_FREQ4 .equ $00E0 * frequency 4
114P_FILTER .equ $0140 * filter
115P_FILTRQ .equ $00C0 * filter q
116*
117P_INDEX1 .equ $0120 * index 1
118P_INDEX2 .equ $0160 * index 2
119P_INDEX3 .equ $0180 * index 3
120P_INDEX4 .equ $01A0 * index 4
121P_INDEX5 .equ $01C0 * index 5
122P_INDEX6 .equ $01E0 * index 6
123*
124P_LEVEL .equ $0040 * level
125*
126P_LOCN .equ $0080 * location
127P_DYNAM .equ $0100 * dynamics
128*
129 .page
130* ------------------------------------------------------------------------------
131* Structure definitions
132* ------------------------------------------------------------------------------
133* The following MUST match the idfnhdr structure definition in instdsp.h:
134*
135FH_LEN .equ 12 * length of the idfnhdr structure
136*
137FH_PCH .equ 0 * WORD - pitch offset (freq1 only)
138FH_MLT .equ 2 * WORD - overall value multiplier
139FH_SRC .equ 4 * BYTE - overall value source
140FH_PIF .equ 5 * BYTE - # of points in the function
141FH_PT1 .equ 6 * BYTE - index of first point
142FH_TMD .equ 7 * BYTE - trigger mode / control bits
143FH_CPT .equ 8 * BYTE - current point
144FH_PRM .equ 9 * BYTE - misc. function parameter
145FH_TRG .equ 10 * WORD - trigger
146*
147I_ACTIVE .equ 1 * 'Active' bit number (in FH_TMD)
148*
149MSK_CTL .equ $001C * 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 .equ 12 * length of the instpnt structure
155*
156PT_TIM .equ 0 * WORD - time (packed)
157PT_VAL .equ 2 * WORD - value
158PT_VMLT .equ 4 * WORD - value multiplier
159PT_VSRC .equ 6 * BYTE - value source
160PT_ACT .equ 7 * BYTE - action
161PT_PAR1 .equ 8 * BYTE - parameter 1
162PT_PAR2 .equ 9 * BYTE - parameter 2
163PT_PAR3 .equ 10 * BYTE - parameter 3
164PT_PAD .equ 11 * BYTE - padding for even boundary
165*
166MSK_MNT .equ $FFF0 * mask for mantissa (in PT_TIM)
167MSK_EXP .equ $000F * mask for exponent (in PT_TIM)
168*
169MAX_ACT .equ 7 * maximum action code value
170*
171 .page
172*
173* ------------------------------------------------------------------------------
174* pflist definitions -- must match those in instdsp.h
175*
176PF_NEXT .equ 0
177PF_TRIG .equ 4
178PF_FUNC .equ 6
179PF_D1 .equ 8
180PF_D2 .equ 12
181PF_D4 .equ 16
182PF_A1 .equ 20
183PF_A2 .equ 24
184PF_A3 .equ 28
185* ------------------------------------------------------------------------------
186* Source definitions -- must match those in 'smdefs.h'
187*
188SM_RAND .equ 1 * random
189SM_PTCH .equ 5 * pitch
190SM_KPRS .equ 6 * key pressure
191SM_KVEL .equ 7 * key velocity
192SM_FREQ .equ 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*
206_fpuint: movem.l d0-d5/a0-a3,-(a7) * preserve registers we use
207 move.w FPUINT1,d0 * read FPU interrupt status
208 andi.w #$00FF,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 #$1E00,d0 * mask for voice number
236 cmpi.w #$1800,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*
301_fputrap: 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 #$01FE,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 #$001E,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 #$01E0,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 #$001E,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 #$001E,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 #$001E,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 #$001E,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*
742_fpuclr: link a6,#0 * link stack frames
743 move.w sr,-(a7) * save the interrupt level
744 ori.w #$0700,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 #$0020,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 #$0020,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*
865_clrvce: link a6,#0 * link stack frames
866 move.w sr,-(a7) * save the interrupt level
867 ori.w #$0700,sr * turn off interrupts
868*
869 lea FPUFUNC+$20,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 #$01F0,d1 * ...
880*
881 cmpi.w #$0100,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 #$0020,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 #$0020,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 $0000 * frq 1 0.00
947 dc.w $8300 * level -10.00
948 dc.w $0000 * frq 2 0.00
949 dc.w $0000 * locn 0.00
950 dc.w $0000 * frq 3 0.00
951 dc.w $0000 * reson 0.00
952 dc.w $0000 * frq 4 0.00
953 dc.w $7D00 * dyn +10.00
954 dc.w $0000 * ind 1 0.00
955 dc.w $3E80 * filt +5.00
956 dc.w $0000 * ind 2 0.00
957 dc.w $0000 * ind 3 0.00
958 dc.w $0000 * ind 4 0.00
959 dc.w $0000 * ind 5 0.00
960 dc.w $0000 * ind 6 0.00
961*
962* ------------------------------------------------------------------------------
963 .bss
964* ------------------------------------------------------------------------------
965*
966_fp_resv: ds.w 12 * fpu spare function reset values
967_fpuifnc: ds.w 1 * interrupting function number from FPU
968*
969 .end
Note: See TracBrowser for help on using the repository browser.