          
*               
     The terse  MUSIC56000  manual.             
*
     Written by Keith Lent, University of Texas, 1988.
*
     This document includes the following :
         The introduction :          
         The necessities :          
         The miscellaneous :        
         A very simple instrument :                 
         The details :              
         The macros, listed :                  
         The macros, defined :      
         The rules for adding additional macros :
*
     The introduction :          
     MUSIC56000 is a library of DSP56001 macros that provide a  
basis for the creation of computer music instruments.           
                
     Code is written in a standard text file, compiled with the 
standard Motorola 56001 assembler (maclib'ed with the macro definitions),
and then downloaded into the DSP56001. Code should be compiled in
absolute mode.
*               
     The necessities :          
     All MUSIC56000 instruments must contain the following lines :              
                
     MACLIB     '\56000\MACROS\'              
     HEADER     40000.,32,$E0
                
     The first of these lines tells the assembler where the     
MUSIC56000 macro library is located. The second is a macro that sets
up the initial parameters i.e. memory origins, i/o ports, rom tables,           
and the sample rate label (S_RATE). In this case S_RATE is set equal            
to 40000. And, the i/o sample buffer is 32 locations long and located at
memory location Y:$E0.
*               
     The miscellaneous :        
     Comments may be inserted in the code as long as they are   
preceeded by a semi colon. All characters following the semicolon               
on that line are then declared to be a comment.                 
                
     All of the macros are interconnected or patched together with              
"WIRE"s. These wires are actually each assigned one 24 bit memory               
location in the lower part of the Y: memory space. All wires must               
be declared and given an initial value.         
*               
     A very simple instrument :                 
                
     MACLIB     ' \56000\MACROS\'              
     HEADER     40000.,32,$E0
;               
;  DECLARE ALL OF THE WIRES AND ASSIGN THE INITIAL VALUES       
     WIRE     SIGNAL,0          
     WIRE     SINC,440./S_RATE*2.  ;CALCULATE A SAMPLING INC. = 440 Hz          
LOOP            
     SINE     SIGNAL,,SINC,,     ;GENERATE A SINE WAVE AT 440Hz 
     OUT      SIGNAL,,     ;SEND "SIGNAL" TO THE OUTPUT DEVICE  
     JMP     LOOP          ;GO BACK TO LOOP FOR THE NEXT SAMPLE 
                
     This instrument plays a continuous sine wave forever (in a 
infinite loop). Notice how the output of the SINE macro, SIGNAL, is             
"WIRE"d  or patched into the "OUT"put device. And, how the sampling             
increment wire, SINC, is patched into the SINE macro.           
*               
     The details :              
     All MUSIC56000 macros have the following format :          
                
     MACRONAME     ARG1,ARG2,...,cARG1,cARG2...                 
                
     where :   MACRONAME is a 8 or less character mnemonic for  
     the macros function.
            ARG1 is the first "WIRE" to be connected to the macro.              
            ARG2 is the second "WIRE" etc...    
            cARG1 is the first compile time constant to be given                
     to the macro.              
            cARG2 is the second constant...     
                
     see chapter 5 of the DSP56000 assembly manual for more info                
on the macros and the compile time constants.   
*
     The macros, listed :                  
                
     Arguments that begin with a small "c" are compile          
time constants or expresions.
     Arguments that are in parenthesis are optional.            
1) Initialization and wire declaration          
     HEADER   cSR,cIOLEN,cIOLOC
     WIRE     WIRENAME,cINITVAL                 
     IVAL     WIRENAME,cINITVAL                 
2) i/o          
     MIDI     PITCH,VELOCITY,PWHEEL,MWHEEL,PROGNO               
     OUT      LCHAN,RCHAN        
     INOUT    LOUT,ROUT,LIN,RIN,cCHPOS,cCHLEN
     MIDID    PITCH,VELOCITY,PWHEEL,MWHEEL,PROGNO,'VAR1,VAR2,...'  
     MIDI3    P1,V1,cSplit1,P2,V2,cSplit2,P3,V3,PWH,MWH,PROGNO
3) Convertors
     SIMIDI     SINC,PITCH,cMINP,cMAXP          
     LOCPNO     LOC,PNO         
4) Oscilators                   
     SQUARE     SIGNAL,(GAINH),(GAINL),SINC,(PHASE)             
     SAW        SIGNAL,(GAIN),SINC,(PHASE)
     TRIANG     SIGNAL,(GAIN),SINC,(PHASE)      
     SINE       SIGNAL,(GAIN),SINC,(PHASE)
     SINEI      SIGNAL,(GAIN),SINC,(PHASE)
     OSCIL      SIGNAL,(GAIN),SINC,LOC,(PHASE)
     OSCILI     SIGNAL,(GAIN),SINC,LOC,(PHASE)  
     OSCIL1     SIGNAL,(GAIN),SINC,LOC,(PHASE)  
5) Envelopes    
     LINET     VALUE,R_UP,S_LEVEL,R_DOWN        
     EXPT      VALUE,R_UP,S_LEVEL,R_DOWN
6) Noise        
     RAND     SIGNAL,(GAIN),(SEED)              
7) Filters      
     HIPASS    OUT,IN
     RESON     OUT,IN,cCF,cBW,cSCL              
     VRESON    OUT,IN,COEFPTR,cPTR1,cPTR2,cCF1,cCF2,cBW1,cBW2,cEL,cSCL
     DELAY     OUT,IN,cN        
     VDELAY    OUT,IN,PDEL,cN
     VDELAYI   OUT,IN,PDEL,cN
     COMB      OUT,IN,RATE,cN,cSCL
     VCOMBI    OUT,IN,RATE,PDEL,cN,cSCL
8) Table Lookups                
     LOOKUP     OUT,IN,LOC      
     LOOKUPI    OUT,IN,LOC
9) Numeric operations           
     PLUS      C,A,B
     MODPLUS   C,A,B
     MINUS     C,A,B            
     TIMES     C,A,B            
     ITIMES    C,A,B
     SQRT      OUT,IN          ;very expensive but accurate ???
10) Triggers    
     ONTRIG     SIGNAL,(AMP),TRIG               
     CHTRIG     SIGNAL,(AMP),TRIG               
11) Conditional/unconditional patches           
     SETEQ     OUT,IN           
     SETIFZ    OUT,IN,TVAL
     SETIFNZ   OUT,IN,TVAL
12) Logical operations          
     LAND     C,A,B             
     LOR      C,A,B
                
*               
     The macros, defined :      
                
1) Initialization and wire declaration          
     HEADER     cSR,cIOLEN,cIOLOC
     initializes the following parameters :     
          memory space origins                  
          i/o ports             
          rom tables - turns them on i.e Y:$100..$1FF is a sine 
          sets the label S_RATE = cSR, typically cSR is 40000
          starts up the i/o (sample data, not MIDI) interupt driven routines.
          "cIOLEN" = the length of the i/o sample buffer (typically 32)
          "cIOLOC" = the location in Y: memory of the i/o buffer (i.e. $E0)
                
     WIRE     WIRENAME,cINITVAL                 
     declares the symbol "WIRENAME" as a pointer to Y: memory,  
     and preloads that memory location with "cINITVAL".         
     NOTE : wire names are treated as standard symbols by the   
     assembler. Therfor, they must be unique alphanumeric strings               
     that are not the same as macro names, 56000 registers, or  
     assembler mnemonics.       
                
     IVAL     WIRENAME,cINITVAL                 
     Sets the memory location for "WIRENAME" to "cINITVAL". The 
     wire must have already been declared with a "WIRE" macro.  
     "IVAL"'s can be placed anywhere after the wire is declared 
     and they are only performed at compile time.               
                
2) i/o          
     MIDI     PITCH,VELOCITY,PWHEEL,MWHEEL,PROGNO               
     A polled i/o midi input device driver. It polls the midi serial            
     port once each time it is called. And, when a value is recieved            
     the appropriate wire is loaded with the midi value.        
          "PITCH" = pitch number in MSB i.e. $000000 to $7F0000 
     or when interpreted as a real number           
                 0.0 to 1.- 2**-7               
          "VELOCITY" = velocity number in MSB   
          "PWHEEL" = pitch wheel values from -.5 to .5          
     this value has 14 bits of accuracy           
          "MWHEEL" = modulation wheel number in MSB             
          "PROGNO" = program number in MSB      
                
     OUT     LCHAN,RCHAN        
     Waits for room in the i/o buffer and then puts "LCHAN" and then "RCHAN"  
     in. Mean while the ssi port interupt empty this data out of the buffer.                "RCHAN" is optional, if unspecified, "RCHAN = LCHAN".               
                
     INOUT   LOUT,ROUT,LIN,RIN,cCHPOS,cCHLEN
     Waits for data in the i/o buffer and then gets "LIN" and "RIN",
     and then puts "LOUT" and "ROUT".
          "cCHPOS" = position of this 56001 in the chain (default = 1).
          "cCHLEN" = number of 56001s in the chain (default = 1).

     MIDID     PITCH,VELOCITY,PWHEEL,MWHEEL,PROGNO,'VAR1,VAR2,...'             
     The same as MIDI except for the last argument. This argument               
     must be in single quotes an contain a list of variables to 
     be "DISPLAY"ed. These values will be displayed every time that             
     a midi control switch is used (for example PORTA-MENTO on the              
     Casio CZ-1). 
              
     MIDI3     P1,V1,cSplit1,P2,V2,cSplit2,P3,V3,PWH,MWH,PROGNO
     The same as MIDI except that the keyboard has two split points. P1 
     is the pitch and V1 is the velocity for MIDI note numbers <= cSplit1.
     P2,V2 is for cSplit1<P2<=cSplit2. And P2,V2 is for P2>cSplit2.
     Typically, cSplit1 = 47, and cSplit2 = 84.              
                
3) Convertors
     SIMIDI     SINC,PITCH,cMINP,cMAXP          
     Converts from a midi "PITCH" value to a sampling increment.                
     Equitempered tuning.       
          SINC = f(PITCH)       
     since the function f() is implemented with a lookup table  
          "cMINP" specifies the minimum midi pitch # to be used 
          "cMAXP" specifies the maximum midi pitch # to be used 
          typical values might be cMINP = 36 and cMAXP = 96     
     The lookup table is stored in XH: memory.  
                
     LOCPNO     LOC,PNO         
     Converts from a midi "Prog. No." value to a Table location.                
     For example,  PNO .. 2  =>  table location $200            
                
4) Oscilators                   
     All oscilators have an output signal "SIGNAL",             
     a sampling increment input "SINC", phase input/output "PHASE",             
     and gain input "GAIN".     
     hence,     
          "SIGNAL" = f("PHASE")                 
          "PHASE"  = MOD1("PHASE" + "SINC")     
     where f() is the apropriate oscilators function.           
     since the range of "PHASE" is -1.0 to 1.0 one can calculate                
     the necessary sampling increment for a given frequency as  
     follows:                   
          sinc = fhz / S_RATE * 2.              
                
     the "GAIN" and "PHASE" arguments are optional. If they are 
     unspecified then "PHASE" initially = -1.   
      and      "GAIN" = 1.0 - 2**-7   i.e. almost 1.0           
                
     SQUARE     SIGNAL,(GAINH),(GAINL),SINC,(PHASE)             
     Generates a square wave with maximum value = "GAINH"       
     and minimum value = "GAINL"                
                
     SAW     SIGNAL,(GAIN),SINC,(PHASE)         
     Generates a sawtooth wave with values from -"GAIN" to "GAIN"               
                
     TRIANG     SIGNAL,(GAIN),SINC,(PHASE)      
     Generates a triangular wave with values from 0 to "GAIN"   
                
     SINE     SIGNAL,(GAIN),SINC,(PHASE)        
     Generates a sine wave without interpolation. (256 pt. table)               
                
     SINEI     SIGNAL,(GAIN),SINC,(PHASE)       
     Generates a sine wave with linear interpolation.           
                
     OSCIL     SIGNAL,(GAIN),SINC,LOC,(PHASE)   
     Generates a wave without interpolation by using the 256 point              
     lookup table located at "LOC" in Y: memory. Note : "LOC" must              
     be a number of the form $00nn00 due to the use of the 56000's              
     modulo 256 addressing feature.             
                
     OSCILI     SIGNAL,(GAIN),SINC,LOC,(PHASE)  
     Generates a wave with interpolation by using the 256 point 
     lookup table located at "LOC" in Y: memory. Note : "LOC" must              
     be a number of the form $00nn00 due to the use of the 56000's              
     modulo 256 addressing feature.             
                
     OSCIL1     SIGNAL,(GAIN),SINC,LOC,(PHASE)  
     This routine functions just like OSCIL except that only one                
     cycle of the waveform is generated and then the last value in              
     the table is held.         
                
5) Envelopes    
     LINET     VALUE,R_UP,S_LEVEL,R_DOWN        
     This envelope generator causes the "VALUE" to linearly track               
     to the "S__LEVEL". Specifically ,          
      if "VALUE" > "S_LEVEL"            then "VALUE" = "VALUE" - "R_DOWN"       
      if "VALUE"+"R_UP" < "S_LEVEL" then "VALUE" = "VALUE" + "R_UP"             
            else "VALUE" = "S_LEVEL"            
     EXPT     VALUE,R_UP,S_LEVEL,R_DOWN         
     This envelope generator causes the "VALUE" to exponentially                
     track to the "S__LEVEL". Specifically ,    
        if "VALUE" > "S_LEVEL"     then         
          "VALUE" = "S_LEVEL" + "R_DOWN" * ("VALUE" - "S_LEVEL")                
        if "VALUE" <= "S_LEVEL" then            
          "VALUE" = "S_LEVEL" + "R_UP" * ("VALUE" - "S_LEVEL")  
     Note : the least significant bit in these calculations is  
     always rounded to insure the "S_LEVEL" is reached.         
                
6) Noise        
     RAND     SIGNAL,(GAIN),(SEED)              
     A standard pseudo-random number generator.                 
                
7) Filters      
     HIPASS     OUT,IN          
     This filter completly eliminates any 0 Hx components.      
          "OUT" = "IN"-"INP"    
          "INP" = "IN"          
               i.e.  y(n)= x(n) - x(n-1)        
                
     RESON     OUT,IN,cCF,cBW,cSCL              
     This is a 2nd order recursive band pass filter of the form.                
     y(n)= a * x(n) - b * y(n-1) - c * y(n-2)   
     where :    
          x(n) = "IN"           
          "OUT" = y(n)          
          c = EXP(-2*pi*cBW/S_RATE)             
          b = -4*c/(1+c)*COS(2*pi*cCF/S_RATE)   
     if cSCL=2 (i.e. noise input)               
          a = SQT(((1+c)*(1+c)-b*b)*(1-c)/(1+c))                
     else       
          a = SQT(1-b*b/(4*c))*(1-c)            
     endif      
     note :     cCF is the center frequency in Hertz            
          cBW is the band width in Hertz        
          cSCL is a scale factor, use 1 for pitched sounds      
     use 2 for noise.           
     The three coef's are stored in XL: memory.                 
     The delayed samples are stored in YL: memory.              
                
     VRESON OUT,IN,COEFPTR,cPTR1,cPTR2,cCF1,cCF2,cBW1,cBW2,cEL,cSCL             
     This is a standard RESON type filter whose coefficients (a,b,c)            
     are obtained from a lookup table.          
       COEFPTR is the pointer to the look up table. It can have 
     values $000000 to $7FFFFF but only the most significant byte               
     is used as the pointer.    
     cPTR1 is the minimum coef pointer to be used  $00 to $7F   
     cPTR2 is the maximum coef pointer to be used  $00 to $7F   
     cCF1 is the center frequency for the coef's at cPTR1       
     cCF2 is the center frequency for the coef's at cPTR2       
     cBW1 is the band width for the coef's at cPTR1             
     cBW2 is the band width for the coef's at cPTR2             
     if "cEL"= E then           
          exponential interpolation will be used to calculate   
          the intermediate CFs and BWs          
     else       
          linear interpolation will be used     
     endif      
     and as in RESON "cSCL" determines a scaling factor.        
          i.e. "cSCL" = 2  ==>  noise input     
      otherwise scale for pitched input.        
     The lookup table is stored in XH: memory.  
     The delayed samples are stored in YL: memory.              
                
     DELAY     OUT,IN,cN        
     This unit provides a cN sample delay.      
     i.e.     y(n) = x(n-cN)    
     where :    
          x(n) = "IN"           
          "OUT" = y(n)          
     The delayed samples are stored in XH: memory.              
                
     VDELAY     OUT,IN,PDEL,cN                  
     This unit provides a variable sample delay.                
     cN is the maximum delay.   
     PDEL is the percentage of cN that is the actual delay      
     i.e.     y(n) = x(n-PDEL*cN)               
     where :    
          x(n) = "IN"           
          "OUT" = y(n)          
     The delayed samples are stored in XH: memory.              
                
     VDELAYI     OUT,IN,PDEL,cN                 
     This unit is the same as VDELAY except that interpolation is               
     used when calculating x(n-PDEL*cN)         
                
     COMB     OUT,IN,RATE,cN,cSCL               
     A standard comb filter with fixed delay length cN.         
     with "cSCL" meaning the same as in reson.  
     i.e. if "cSCL"=2  (WHITE NOISE) then       
          y(n)= x(n) + "RATE" * y(n-cN)         
     else       
          y(n)= (1-"RATE") * x(n) + "RATE" * y(n-cN)            
     endif      
     where :    
          x(n) = "IN"           
          "OUT" = y(n)          
     The delayed samples are stored in PH: memory.              
                
     VCOMBI     OUT,IN,RATE,PDEL,cN,cSCL        
     The same as COMB except PDEL provides variable percentage  
     delay. And, the delayed samples are stored in XH: memory.  
                
8) Table Lookups                
     LOOKUP     OUT,IN,LOC      
     Lookups a value in a 256 point lookup table located in     
     Y: memory at location "LOC". To lookup values in the sine  
     table LOC should have the value $100. Only the most significant            
     8 bits of "IN" will be used to determine the actual lookup 
     location.                  
        i.e if "IN" = $800000 = -1. then "OUT" = Y:(LOC+$80-1*$80)              
        i.e if "IN" = $407649 = .5  then "OUT" = Y:(LOC+$80+.5*$80)             
        i.e if "IN" = $000340 =  0. then "OUT" = Y:(LOC+$80)    
                
     LOOKUPI     OUT,IN,LOC     
     Does the same as LOOKUP but interpolation is performed to  
     obtain values in between the table locations.              
                
9) Numeric operations           
     PLUS     C,A,B             
     performs the calculation "C" = "A" + "B"   
                
     MODPLUS     C,A,B          
     performs the calculation "C" = mod24bit("A" + "B")         
     i.e. it wraps around. For example : mod24bit(.6 + .5) is -.9               
                
     MINUS     C,A,B            
     performs the calculation "C" = "A" - "B"   
                
     TIMES     C,A,B            
     performs the calculation "C" = "A" * "B"   
                
     ITIMES     C,A,B           
     performs the calculation "C" = "A" * "B" when it           
     is desired that one of the values "A" or "B" be interpreted                
     as an integer value instead of the as a real value (-1 to 1).              
                
     SQRT     OUT,IN          ;very expensive but accurate ???  
     performs the calculation "OUT" = the square root of "IN"   
                
10) Triggers    
     ONTRIG     SIGNAL,(AMP),TRIG               
     This unit generates an impulse of height "AMP" when        
     "TRIG" changes from zero to a non zero value. This can     
     be used with the conditional set routines to preform an    
     action only at the start of a note.        
     i.e. if "TRIG" becomes non zero "SIGNAL" = "AMP"           
          else     "SIGNAL" = 0                 
                
     CHTRIG     SIGNAL,(AMP),TRIG               
     This unit generates an impulse of height "AMP" when        
     "TRIG" changes to any value except zero. Otherwise, it     
     si identical to ONTRIG.    
                
11) Conditional/unconditional patches           
     SETEQ     OUT,IN           
     This unit simply sets "OUT" = "IN"         
                
     SETIFZ     OUT,IN,TVAL     
     If "TVAL" is zero then set "OUT" = "IN"    
     else no operation is preformed.            
                
     SETIFNZ     OUT,IN,TVAL    
     If "TVAL" is non-zero then set "OUT" = "IN"                
     else no operation is preformed.            
                
12) Logical operations          
     LAND     C,A,B             
     performs the bitwise calculation "C" = "A" AND "B"         
                
     LOR     C,A,B              
     performs the bitwise calculation "C" = "A" OR "B"          
                
*
     The rules for adding additional macros :

     Memory :
       Y:   is used for wire variable storage.
       X:   is used for local (to the macro) wire variable storage.
       XL: and YL: are used for small local blocks i.e. filter coeficients.
       XH: and YH: are used for large blocks of storage i.e. function tables and            delay lines.
       P:   is the location of the initializtion code found in the header.
       PH:,YH:   is the location of the overlay code which lies in Y: memory
       space during loading, but is copied (overlayed) into the internal P:
       memory by the HEADER macro after initialization.
       This allows all of the internal memory to be used for run time code,
       and therefore, increases the speed of execution.
       Hence, in this implimentation, all of the macros are compiled
       for PH: memory but are loaded into YH: memory. That is, they
       all begin with the statement   ORG PH:,YH:  .
       If this overlaying of code is not necessary in your system, you can
       simply replace all of the    ORG PH:,YH:  statements in the macros
       with    ORG P:   statements, and then eliminate the overlay copying
       found in HEADER.ASM.
       ****   (Note: the NeXT version does not use the overlay technique)
       X: and Y: spaces should begin at address 0. This allows short immediate
       addresses to be used when referencing wire data.
       XL: and YL: begin at address 80 hex. This allows parallel accesses
       to internal X and Y memory spaces to be made efficiently.
       XH: and YH: begin at 200 hex.
       PH:,YH: begins at   ORG PH:$20,YH:$3E20.
       However, these locations (initialised in HEADER.ASM) may be
       changed depending on your systems external memory configuration.

     Register usage :
         Any macro can use and destroy any register except the following:
              r6 and m6 are used by the interupt driven I/O routines and,
              therfore, can not be used by any macro.
              m7 is assumed to contain the value 255. Hence, if it is changed
              it must be restored.
         All inter macro communication is typically done through "wires"
        (i.e. Y: memory space variables).

