Changeset 4f508e6 in buchla-68k for ram/fpuint.s


Ignore:
Timestamp:
07/01/2017 02:34:46 PM (7 years ago)
Author:
Thomas Lopatic <thomas@…>
Branches:
master
Children:
08e1da1
Parents:
f40a309
Message:

Converted assembly language files.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • ram/fpuint.s

    rf40a309 r4f508e6  
    1 * ------------------------------------------------------------------------------
    2 * fpuint.s -- process FPU interrupts / clear FPU
    3 * Version 63 -- 1988-08-31 -- D.N. Lynx Crowe
    4 * ------------------------------------------------------------------------------
     1| ------------------------------------------------------------------------------
     2| fpuint.s -- process FPU interrupts / clear FPU
     3| Version 63 -- 1988-08-31 -- D.N. Lynx Crowe
     4| ------------------------------------------------------------------------------
    55                .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 *
     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
    2020                .xref   _expbit
    2121                .xref   _funcndx
     
    3333                .xref   _vce2trg
    3434                .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 *
    56 UPD_BIT         .equ    $0001                   * update bit  (1 = update)
    57 INT_BIT         .equ    $0002                   * int. bit    (0 = disable)
    58 RAT_BIT         .equ    $0004                   * ratio bit   (0 = ratio)
    59 *
    60 VSUBNBIT        .equ    3                       * new value select bit number
    61 VAL_BITS        .equ    $0018                   * new value select bit mask
    62 *
    63 MSK_RNVB        .equ    $000C                   * new value / ratio bits
    64 MSK_ONVB        .equ    $0010                   * old new value bit
    65 *
    66 FKILL           .equ    $0014                   * kill value for function
    67 FSEND           .equ    $0015                   * send new value to function
    68 *
    69 CLREXP          .equ    $8000                   * clear value for time exponent
    70 CLRMNT          .equ    $8000                   * clear value for time mantissa
    71 *
    72 * ------------------------------------------------------------------------------
    73 * Miscellaneous definitions
    74 * -------------------------
    75 *
    76 PCHMAX          .equ    21920                   * maximum pitch value
    77 VALMAX          .equ    32000                   * maximum value to send to FPU
    78 VALMIN          .equ    -32000                  * minimum value to send to FPU
    79 *
    80 LSPCH           .equ    2                       * left shift for sources to freq
    81 *
    82 VALLEN          .equ    10                      * length of the 'valent' struct
    83 VT_VAL          .equ    8                       * value offset in 'valent'
    84 *
    85                 .page
    86 * ------------------------------------------------------------------------------
    87 * FPU addresses
    88 * -------------
    89 *
    90 FPUBASE         .equ    $180000                 * FPU base address
    91 *
    92 FPUWST          .equ    FPUBASE                 * FPU waveshape base
    93 FPUFUNC         .equ    FPUBASE+$4000           * FPU function base
    94 FPUINT1         .equ    FPUBASE+$4000           * FPU int. input address (R/O)
    95 FPUINT2         .equ    FPUBASE+$6000           * FPU int. reset address (W/O)
    96 FPUCFG          .equ    FPUBASE+$5FE0           * FPU config. data address (W/O)
    97 *
    98 F_CTL           .equ    $00                     * control word
    99 F_VAL10         .equ    $02                     * new value "10"
    100 F_CV1           .equ    $08                     * control voltage 1
    101 F_SF1           .equ    $0A                     * scale factor 1
    102 F_CV2           .equ    $0C                     * control voltage 2
    103 F_SF2           .equ    $0E                     * scale factor 2
    104 F_CV3           .equ    $10                     * control voltage 3
    105 F_SF3           .equ    $12                     * scale factor 3
    106 F_MNT           .equ    $14                     * time mantissa
    107 F_EXP           .equ    $16                     * time exponent
    108 F_VAL01         .equ    $1C                     * new value "01"
    109 *
    110 P_FREQ1         .equ    $0020                   * frequency 1
    111 P_FREQ2         .equ    $0060                   * frequency 2
    112 P_FREQ3         .equ    $00A0                   * frequency 3
    113 P_FREQ4         .equ    $00E0                   * frequency 4
    114 P_FILTER        .equ    $0140                   * filter
    115 P_FILTRQ        .equ    $00C0                   * filter q
    116 *
    117 P_INDEX1        .equ    $0120                   * index 1
    118 P_INDEX2        .equ    $0160                   * index 2
    119 P_INDEX3        .equ    $0180                   * index 3
    120 P_INDEX4        .equ    $01A0                   * index 4
    121 P_INDEX5        .equ    $01C0                   * index 5
    122 P_INDEX6        .equ    $01E0                   * index 6
    123 *
    124 P_LEVEL         .equ    $0040                   * level
    125 *
    126 P_LOCN          .equ    $0080                   * location
    127 P_DYNAM         .equ    $0100                   * dynamics
    128 *
    129                 .page
    130 * ------------------------------------------------------------------------------
    131 * Structure definitions
    132 * ------------------------------------------------------------------------------
    133 * The following MUST match the idfnhdr structure definition in instdsp.h:
    134 *
    135 FH_LEN          .equ    12              * length of the idfnhdr structure
    136 *
    137 FH_PCH          .equ    0               * WORD - pitch offset  (freq1 only)
    138 FH_MLT          .equ    2               * WORD - overall value multiplier
    139 FH_SRC          .equ    4               * BYTE - overall value source
    140 FH_PIF          .equ    5               * BYTE - # of points in the function
    141 FH_PT1          .equ    6               * BYTE - index of first point
    142 FH_TMD          .equ    7               * BYTE - trigger mode / control bits
    143 FH_CPT          .equ    8               * BYTE - current point
    144 FH_PRM          .equ    9               * BYTE - misc. function parameter
    145 FH_TRG          .equ    10              * WORD - trigger
    146 *
    147 I_ACTIVE        .equ    1               * 'Active' bit number        (in FH_TMD)
    148 *
    149 MSK_CTL         .equ    $001C           * mask for FPU hardware bits (in FH_TMD)
    150 *
    151 * ------------------------------------------------------------------------------
    152 * The following MUST match the instpnt structure definition in instdsp.h:
    153 *
    154 PT_LEN          .equ    12              * length of the instpnt structure
    155 *
    156 PT_TIM          .equ    0               * WORD - time (packed)
    157 PT_VAL          .equ    2               * WORD - value
    158 PT_VMLT         .equ    4               * WORD - value multiplier
    159 PT_VSRC         .equ    6               * BYTE - value source
    160 PT_ACT          .equ    7               * BYTE - action
    161 PT_PAR1         .equ    8               * BYTE - parameter 1
    162 PT_PAR2         .equ    9               * BYTE - parameter 2
    163 PT_PAR3         .equ    10              * BYTE - parameter 3
    164 PT_PAD          .equ    11              * BYTE - padding for even boundary
    165 *
    166 MSK_MNT         .equ    $FFF0           * mask for mantissa  (in PT_TIM)
    167 MSK_EXP         .equ    $000F           * mask for exponent  (in PT_TIM)
    168 *
    169 MAX_ACT         .equ    7               * maximum action code value
    170 *
    171                 .page
    172 *
    173 * ------------------------------------------------------------------------------
    174 * pflist definitions -- must match those in instdsp.h
    175 *
    176 PF_NEXT         .equ    0
    177 PF_TRIG         .equ    4
    178 PF_FUNC         .equ    6
    179 PF_D1           .equ    8
    180 PF_D2           .equ    12
    181 PF_D4           .equ    16
    182 PF_A1           .equ    20
    183 PF_A2           .equ    24
    184 PF_A3           .equ    28
    185 * ------------------------------------------------------------------------------
    186 * Source definitions -- must match those in 'smdefs.h'
    187 *
    188 SM_RAND         .equ    1               * random
    189 SM_PTCH         .equ    5               * pitch
    190 SM_KPRS         .equ    6               * key pressure
    191 SM_KVEL         .equ    7               * key velocity
    192 SM_FREQ         .equ    10              * frequency
    193 *
    194                 .page
    195 * ------------------------------------------------------------------------------
    196 * _fpuint() -- process FPU interrupts
    197 *
    198 *       void
    199 *       fpuint();
    200 *
    201 *               Processes FPU interrupts.  Must be the target of vector 26,
    202 *               which is Autovector Interrupt level 2.
    203 *
    204 * ------------------------------------------------------------------------------
    205 *
    206 _fpuint:        movem.l d0-d5/a0-a3,-(a7)       * preserve registers we use
    207                 move.w  FPUINT1,d0      * read FPU interrupt status
    208                 andi.w  #$00FF,d0       * mask out garbage in MS bits
    209                 move.w  d0,_fpuifnc     * save for later use
    210                 move.w  _ndisp,d1       * get display number
    211                 cmpi.w  #11,d1          * see if we display
    212                 bne     nodisp          * jump if not
    213 *
    214                 tst.w   _scopef         * ...
    215                 beq     nodisp          * ...
    216 *
    217                 move.w  d0,-(a7)        * display value
    218                 jsr     _scope          * ...
    219                 tst.w   (a7)+           * ...
    220 *
    221                 move.w  _fpuifnc,d0     * get FPU status
    222 *
    223 nodisp:         move.w  d0,d1           * save in d1  (becomes function offset)
    224 *
    225                 lsl.w   #5,d1           * develop FPU function offset
    226                 lea     FPUFUNC,a3      * setup FPU function base address
    227 *
    228                 lsl.w   #3,d0           * develop funcndx[] index
    229                 lea     _funcndx,a0     * setup funcndx[] base address
    230 *
    231                 tst.l   0(a0,d0.W)      * see if function is defined
    232                 bne     fnok            * jump if so
    233 *
    234                 move.w  d1,d0           * get function offset in d0
    235                 andi.w  #$1E00,d0       * mask for voice number
    236                 cmpi.w  #$1800,d0       * see if it's a real voice  (0..11)
    237                 bge     fpexit          * don't send a kill if not a real voice
    238 *
    239                 move.w  #FKILL,F_CTL(a3,d1.W)   * kill the undefined function
    240 *
    241 fpexit:         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 * ------------------------------------------------------------------------------
    249 fnok:           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 * ------------------------------------------------------------------------------
    257 stopfn:         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 * ------------------------------------------------------------------------------
    271 doact:          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 * ----    --------------------
    307 act0:           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 * ------    ----------------
    319 outseg:         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 * ------------------------------------------------------------------------------
    360 srctyp0:        cmpi.w  #SM_FREQ,d0     * is this the frequency source ?
    361                 bne     srctyp1         * jump if not
    362 *
    363                 move.w  (a1),d0         * get the pitch
    364                 lsr.w   #6,d0           * shift to a word index
    365                 andi.w  #$01FE,d0       * mask out extraneous bits
    366                 lea     _ptoftab,a0     * get entry from ptoftab[]
    367                 move.w  0(a0,d0.W),d5   * ...
    368                 bra     applym          * go apply the multiplier
    369 *
    370 * ------------------------------------------------------------------------------
    371 * SM_PTCH -- pitch
    372 * ------------------------------------------------------------------------------
    373 srctyp1:        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 * ------------------------------------------------------------------------------
    382 srctyp2:        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 * ------------------------------------------------------------------------------
    394 srctyp3:        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 * ------------------------------------------------------------------------------
    407 srctyp4:        lea     _vce2grp,a0     * point at vce2grp[]
    408                 move.w  _fpuifnc,d5     * get voice number in d5
    409                 lsr.w   #3,d5           * ...
    410                 andi.w  #$001E,d5       * ... as a word index
    411                 move.w  0(a0,d5.W),d5   * get the group number
    412                 subq.w  #1,d5           * ...
    413                 lsl.w   #4,d5           * shift it left a nybble
    414                 or.w    d5,d0           * OR it into the source number
    415                 add.w   d0,d0           * make source number a valents[] index
    416                 move.w  d0,d5           * ... (fast multiply by VALLEN = 10
    417                 lsl.w   #2,d0           * ...  via shift and add)
    418                 add.w   d5,d0           * ...
    419                 lea     _valents,a0     * get base of valents[]
    420                 move.w  VT_VAL(a0,d0.W),d5      * get value
    421 *
    422 * ------------------------------------------------------------------------------
    423 * apply the multiplier to the source, and add it to the function value
    424 * ------------------------------------------------------------------------------
    425 applym:         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 *
    436 srcmlt1:        cmpi.l  #VALMIN,d5      * check for underflow
    437                 bge     srcmlt2         * jump if no underflow
    438 *
    439                 move.l  #VALMIN,d5      * limit at VALMIN
    440 *
    441 srcmlt2:        move.w  d5,d3           * setup value for output to FPU
    442 *
    443                 .page
    444 * ------------------------------------------------------------------------------
    445 * adjust the value according to the function type
    446 * ------------------------------------------------------------------------------
    447 nosrc:          move.w  d1,d0           * get function type
    448                 andi.w  #$01E0,d0       * ...
    449 *
    450 * ------------------------------------------------------------------------------
    451 * level or location
    452 * ------------------------------------------------------------------------------
    453                 cmpi.w  #P_LEVEL,d0     * see if it's the level
    454                 beq     outsegl         * jump if so
    455 *
    456                 cmpi.w  #P_LOCN,d0      * see if it's the location
    457                 bne     outsegf         * jump if not
    458 *
    459                 tst.w   d3              * check sign of value
    460                 bpl     outsegc         * jump if positive
    461 *
    462                 clr.w   d3              * force negative values to 0
    463 *
    464 outsegc:        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 *
    469 outsegl:        tst.w   d3              * check sign of value
    470                 bpl     outsegm         * jump if positive
    471 *
    472                 clr.w   d3              * limit negative values at 0
    473 *
    474 outsegm:        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 * ------------------------------------------------------------------------------
    483 outsegf:        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 *
    500 outsega:        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 * ------------------------------------------------------------------------------
    510 outsegp:        cmpi.w  #P_FREQ1,d0     * see if it's freq1
    511                 beq     outseg0         * go process freq1
    512 *
    513 outsegq:        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 *
    522 outseg0:        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 * ------------------------------------------------------------------------------
    537 outseg3:        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
     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
    541541                beq     outseg1
    542 *
    543                 move.w  d3,F_VAL01(a3,d1.W)     * send value to FPU
     542
     543                move.w  d3,F_VAL01(a3,d1.W)     | send value to FPU
    544544                bra     outseg2
    545 *
    546 outseg1:        move.w  d3,F_VAL10(a3,d1.W)     * send value to FPU
    547 *
    548 outseg2:        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 * ----    ------------------------------------------
    558 act1:           move.w  _fpuifnc,d0     * get voice as a word index
    559                 lsr.w   #3,d0           * ...
    560                 andi.w  #$001E,d0       * ...
    561                 lea     _vce2trg,a0     * point at voice to trigger table
    562                 move.w  0(a0,d0.W),d0   * get trigger table entry into d0
    563                 cmpi.w  #-1,d0          * see if voice is free
    564                 beq     act0            * continue function if so
    565 *
    566                 btst    #15,d0          * see if voice is held by a pedal
    567                 bne     act1a           * sustain if so
    568 *
    569                 btst    #14,d0          * see if voice is sustained by a pedal
    570                 bne     act1a           * sustain if so
    571 *
    572                 lea     _trgtab,a0      * point at trigger table
    573                 tst.b   0(a0,d0.W)      * check trigger status
    574                 beq     act0            * continue function if not active
    575 *
    576 act1a:          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 * ----    ----------------------------
    608 act2:           move.w  _fpuifnc,d0     * get voice as a word index
    609                 lsr.w   #3,d0           * ...
    610                 andi.w  #$001E,d0       * ...
    611                 lea     _vce2trg,a0     * check to see if voice is free
    612                 move.w  0(a0,d0.W),d0   * ...
    613                 cmpi.w  #-1,d0          * ...
    614                 beq     stopfn          * if so, stop the function
    615 *
    616                 btst    #15,d0          * see if voice is held
    617                 bne     act0            * continue if so
    618 *
    619                 btst    #14,d0          * ...
    620                 bne     act0            * ...
    621 *
    622                 lea     _trgtab,a0      * check trigger table entry
    623                 tst.b   0(a0,d0.W)      * ...
    624                 bne     act0            * if trigger is active, continue
    625 *
    626                 bra     stopfn          * if not, stop the function
    627 *
    628 * ------------------------------------------------------------------------------
    629 * act3 -- AC_JUMP -- unconditional jump
    630 * ----    -----------------------------
    631 act3:           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 * ----    ----------------------------------------------
    649 act4:           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 *
    666 act4b:          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 *
    671 act4a:          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 * ----    ----------------------------
    679 act5:           move.w  _fpuifnc,d0     * get voice as a word index
    680                 lsr.w   #3,d0           * ...
    681                 andi.w  #$001E,d0       * ...
    682                 lea     _vce2trg,a0     * check to see if voice is free
    683                 move.w  0(a0,d0.W),d0   * ...
    684                 cmpi.w  #-1,d0          * ...
    685                 beq     act3            * if so (inactive), do the jump
    686 *
    687                 btst    #15,d0          * see if voice is held
    688                 bne     act0            * continue if so
    689 *
    690                 btst    #14,d0          * ...
    691                 bne     act0            * ...
    692 *
    693                 lea     _trgtab,a0      * check trigger table entry
    694                 tst.b   0(a0,d0.W)      * see if the trigger is active
    695                 beq     act3            * if not, do the jump
    696 *
    697                 bra     act0            * if so, do next segment
    698 *
    699                 .page
    700 *
    701 * ------------------------------------------------------------------------------
    702 * act6 -- AC_KYDN -- jump if key is down
    703 * ----    ------------------------------
    704 act6:           move.w  _fpuifnc,d0     * get voice as a word index
    705                 lsr.w   #3,d0           * ...
    706                 andi.w  #$001E,d0       * ...
    707                 lea     _vce2trg,a0     * check to see if voice is free
    708                 move.w  0(a0,d0.W),d0   * ...
    709                 cmpi.w  #-1,d0          * ...
    710                 beq     act0            * if so (inactive), continue
    711 *
    712                 btst    #15,d0          * see if voice is held
    713                 bne     act3            * do jump if so
    714 *
    715                 btst    #14,d0          * ...
    716                 bne     act3            * ...
    717 *
    718                 lea     _trgtab,a0      * check trigger table entry
    719                 tst.b   0(a0,d0.W)      * see if the trigger is active
    720                 bne     act3            * if so, do the jump
    721 *
    722                 bra     act0            * if not, do next segment
    723 *
    724 * ------------------------------------------------------------------------------
    725 * Test stub
    726 * ---------
    727 act7:           bra     act0            * AC_HERE: treat act7 as AC_NULL
    728 *
    729                 .page
    730 * ------------------------------------------------------------------------------
    731 *
    732 * _fpuclr -- clear the FPU
    733 * -------    -------------
    734 *
    735 *       void
    736 *       fpuclr()
    737 *
    738 *               Resets the FPU functions to their nominal values.
    739 *
    740 * ------------------------------------------------------------------------------
    741 *
    742 _fpuclr:        link    a6,#0                   * link stack frames
    743                 move.w  sr,-(a7)                * save the interrupt level
    744                 ori.w   #$0700,sr               * turn off interrupts
    745 *
    746                 lea     FPUFUNC,a0              * point at the first function
    747                 lea     _fp_resv,a2             * point at reset value table
    748                 move.w  #11,d1                  * set the outer loop count
    749 *
    750                 .page
    751 * ------------------------------------------------------------------------------
    752 * reset the 'spare' function for the voice
    753 * ------------------------------------------------------------------------------
    754 clr0:           move.w  #CLREXP,F_EXP(a0)       * set time exponent
    755                 tst.l   actab                   * delay
    756                 tst.l   actab                   * ...
    757                 move.w  #CLRMNT,F_MNT(a0)       * set time mantissa
    758                 tst.l   actab                   * delay
    759                 tst.l   actab                   * ...
    760 *
    761                 move.w  #0,F_SF3(a0)            * set scale factor 3
    762                 tst.l   actab                   * delay
    763                 tst.l   actab                   * ...
    764                 move.w  #0,F_CV3(a0)            * set voltage 3
    765                 tst.l   actab                   * delay
    766                 tst.l   actab                   * ...
    767 *
    768                 move.w  #0,F_SF2(a0)            * set scale factor 2
    769                 tst.l   actab                   * delay
    770                 tst.l   actab                   * ...
    771                 move.w  #0,F_CV2(a0)            * set voltage 2
    772                 tst.l   actab                   * delay
    773                 tst.l   actab                   * ...
    774 *
    775                 move.w  #0,F_SF1(a0)            * set scale factor 1
    776                 tst.l   actab                   * delay
    777                 tst.l   actab                   * ...
    778                 move.w  #0,F_CV1(a0)            * set voltage 1
    779                 tst.l   actab                   * delay
    780                 tst.l   actab                   * ...
    781 *
    782                 move.w  (a2),F_VAL10(a0)        * set value from variable table
    783                 tst.l   actab                   * delay
    784                 tst.l   actab                   * ...
    785                 move.w  (a2)+,F_VAL01(a0)       * ...
    786                 tst.l   actab                   * delay
    787                 tst.l   actab                   * ...
    788                 move.w  #FSEND,F_CTL(a0)        * set control word
    789                 tst.l   actab                   * delay
    790                 tst.l   actab                   * ...
    791 *
    792                 .page
    793                 adda.w  #$0020,a0               * point at 2nd function
    794                 lea     fprescon,a1             * set reset constant pointer
    795                 move.w  #14,d0                  * set inner loop count
    796 *
    797 * ------------------------------------------------------------------------------
    798 * reset the other functions for the voice
    799 * ------------------------------------------------------------------------------
    800 clr1:           move.w  #CLREXP,F_EXP(a0)       * set time exponent
    801                 tst.l   actab                   * delay
    802                 tst.l   actab                   * ...
    803                 move.w  #CLRMNT,F_MNT(a0)       * set time mantissa
    804                 tst.l   actab                   * delay
    805                 tst.l   actab                   * ...
    806 *
    807                 move.w  #0,F_SF3(a0)            * set scale factor 3
    808                 tst.l   actab                   * delay
    809                 tst.l   actab                   * ...
    810                 move.w  #0,F_CV3(a0)            * set voltage 3
    811                 tst.l   actab                   * delay
    812                 tst.l   actab                   * ...
    813 *
    814                 move.w  #0,F_SF2(a0)            * set scale factor 2
    815                 tst.l   actab                   * delay
    816                 tst.l   actab                   * ...
    817                 move.w  #0,F_CV2(a0)            * set voltage 2
    818                 tst.l   actab                   * delay
    819                 tst.l   actab                   * ...
    820 *
    821                 move.w  #0,F_SF1(a0)            * set scale factor 1
    822                 tst.l   actab                   * delay
    823                 tst.l   actab                   * ...
    824                 move.w  #0,F_CV1(a0)            * set voltage 1
    825                 tst.l   actab                   * delay
    826                 tst.l   actab                   * ...
    827 *
    828                 move.w  (a1),F_VAL10(a0)        * set value from constant table
    829                 tst.l   actab                   * delay
    830                 tst.l   actab                   * ...
    831                 move.w  (a1)+,F_VAL01(a0)       * ...
    832                 tst.l   actab                   * delay
    833                 tst.l   actab                   * ...
    834                 move.w  #FSEND,F_CTL(a0)        * set control word
    835                 tst.l   actab                   * delay
    836                 tst.l   actab                   * ...
    837 *
    838                 .page
    839 * ------------------------------------------------------------------------------
    840 * loop through reset for all of the voices and functions
    841 * ------------------------------------------------------------------------------
    842                 adda.w  #$0020,a0               * point at next function
    843                 dbra    d0,clr1                 * loop until all funcs. cleared
    844 *
    845                 dbra    d1,clr0                 * loop until all voices cleared
    846 * ------------------------------------------------------------------------------
    847 * clear the FPU interrupt, and return
    848 * ------------------------------------------------------------------------------
    849                 move.w  #0,FPUINT2              * clear FPU interrupt
    850                 move.w  (a7)+,sr                * restore interrupts
    851                 unlk    a6                      * unlink stack frames
    852                 rts                             * return to caller
    853 *
    854                 .page
    855 *
    856 * _clrvce -- quiet a voice
    857 * -------    -------------
    858 *
    859 *       void
    860 *       clrvce(vce)
    861 *       short vce;
    862 *
    863 *               Quiet the voice by resetting the FPU functions it uses.
    864 *
    865 _clrvce:        link    a6,#0                   * link stack frames
    866                 move.w  sr,-(a7)                * save the interrupt level
    867                 ori.w   #$0700,sr               * turn off interrupts
    868 *
    869                 lea     FPUFUNC+$20,a0          * point at the 2nd function
    870                 move.w  8(a6),d0                * get voice number
    871                 ext.l   d0                      * ...
    872                 lsl.l   #8,d0                   * shift into position
    873                 add.l   d0,d0                   * ...
    874                 adda.l  d0,a0                   * add to function base
    875                 lea     fprescon,a1             * set reset constant pointer
    876                 move.w  #14,d0                  * set inner loop count
    877 *
    878 vclr1:          move.l  a0,d1                   * see if we reset this function
    879                 and.w   #$01F0,d1               * ...
    880 *
    881                 cmpi.w  #$0100,d1               * dynamics ?
    882                 beq     vclr2                   * skip it if so
    883 *
    884                 move.w  #CLREXP,F_EXP(a0)       * set time exponent
    885                 tst.l   actab                   * delay
    886                 tst.l   actab                   * ...
    887                 move.w  #CLRMNT,F_MNT(a0)       * set time mantissa
    888                 tst.l   actab                   * delay
    889                 tst.l   actab                   * ...
    890 *
    891                 cmpi.w  #$0020,d1               * freq 1 ?
    892                 beq     vclr3                   * don't reset CV3 (fine tune)
    893 *
    894                 move.w  #0,F_SF3(a0)            * set scale factor 3
    895                 tst.l   actab                   * delay
    896                 tst.l   actab                   * ...
    897                 move.w  #0,F_CV3(a0)            * set voltage 3
    898                 tst.l   actab                   * delay
    899                 tst.l   actab                   * ...
    900 *
    901 vclr3:          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 *
    920 vclr2:          adda.w  #2,a1                   * point at next function
    921                 adda.w  #$0020,a0               *
    922                 dbra    d0,vclr1                * loop until all funcs. cleared
    923 *
    924                 move.w  (a7)+,sr                * restore interrupts
    925                 unlk    a6                      * unlink stack frames
    926                 rts                             * return to caller
    927 *
    928                 .page
    929 * ------------------------------------------------------------------------------
     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| ------------------------------------------------------------------------------
    930930                .data
    931 * ------------------------------------------------------------------------------
    932 *
    933 * actab -- action code dispatch table
    934 * -----    --------------------------
    935 actab:          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 * --------    ------------------------
    946 fprescon:       dc.w    $0000   * frq 1           0.00
    947                 dc.w    $8300   * level         -10.00
    948                 dc.w    $0000   * frq 2           0.00
    949                 dc.w    $0000   * locn            0.00
    950                 dc.w    $0000   * frq 3           0.00
    951                 dc.w    $0000   * reson           0.00
    952                 dc.w    $0000   * frq 4           0.00
    953                 dc.w    $7D00   * dyn           +10.00
    954                 dc.w    $0000   * ind 1           0.00
    955                 dc.w    $3E80   * filt           +5.00
    956                 dc.w    $0000   * ind 2           0.00
    957                 dc.w    $0000   * ind 3           0.00
    958                 dc.w    $0000   * ind 4           0.00
    959                 dc.w    $0000   * ind 5           0.00
    960                 dc.w    $0000   * ind 6           0.00
    961 *
    962 * ------------------------------------------------------------------------------
     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| ------------------------------------------------------------------------------
    963963                .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 *
     964| ------------------------------------------------------------------------------
     965
     966_fp_resv:       ds.w    12              | fpu spare function reset values
     967_fpuifnc:       ds.w    1               | interrupting function number from FPU
     968
    969969                .end
Note: See TracChangeset for help on using the changeset viewer.