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

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

Use .ds and .dc pseudo-ops. Generate debug symbols.

  • 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.