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

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

Converted assembly language files.

  • Property mode set to 100644
File size: 30.9 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
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 #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
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 #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
742_fpuclr: 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
865_clrvce: 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
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.