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

Last change on this file since 8325447 was 8325447, checked in by Thomas Lopatic <thomas@…>, 2 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.