home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / sound / midi / mbb.asm < prev    next >
Assembly Source File  |  1988-03-20  |  113KB  |  2,569 lines

  1.     TITLE    Modules for Modular Sequencer
  2.     NAME    MBB
  3.     .SALL
  4. ;==============================================================
  5. ; MusicBox Modular Sequencer, Version 2
  6. ; modules code
  7. ;--------------------------------------------------------------
  8. ; author: John Dunn
  9. ; date:   03/07/86
  10. ; update: 03/20/88
  11. ;--------------------------------------------------------------
  12. ; COPYRIGHT (C) 1986 John Dunn, All Rights Reserved 
  13. ; Entered into the Public Domain, March 20, 1988
  14. ;
  15. ; Use and copying of this software and preparation of derivative works
  16. ; based upon this software are permitted.  Any distribution of this
  17. ; software or derivative works must comply with all applicable United
  18. ; States export control laws.
  19. ; This software is made available AS IS, and the author makes no warranty 
  20. ; about the software, its performance, or its conformity to any specification.
  21. ; Any person obtaining a copy of this software is requested to send their
  22. ; name and address address to:
  23. ;
  24. ;       John Dunn, Senior Research Fellow
  25. ;       Time Arts Inc.
  26. ;       3436 Mendocino Ave.
  27. ;       Santa Rosa, CA 95401
  28. ;
  29. ;==============================================================
  30.         include    order.asm
  31. ;--------------------------------------------------------------
  32.         include equates.asm
  33. ;--------------------------------------------------------------
  34. ;_DATA   SEGMENT
  35. ;        ASSUME DS:DGROUP, CS:_TEXT
  36. ;--------------------------------------------------------------
  37.         extrn   _nextv:near,_nextx:near,_nextl:near,_nextt:near
  38.         extrn   _doit:near
  39. ;--------------------------------------------------------------
  40.         extrn   ticka:byte,tickis:byte
  41.         extrn   _header:byte
  42.         extrn   varsav:word,cmdflg:byte,special:word,cmdcnt:byte
  43.         extrn   locsav:word,cmdloc:word,vpage:word,curadr:word
  44.         extrn   valflg:byte
  45.         extrn   @zero:near,magflg:byte,usrflg:byte,holdv:word
  46.         extrn   colr:byte
  47. ;--------------------------------------------------------------
  48.         extrn   midisf:byte     ; 0=no sync, 1=send sync
  49.         extrn   midixsf:byte    ; 0=not xtrn sync, NZ=is
  50.         extrn   midiok:byte     ; 0=off/not init, 2=off&init, 3=on
  51.         extrn   mprstf:byte     ; master program reset flag
  52.         extrn   mpmodf:byte     ; master program mode flag
  53.         extrn   mpadrf:byte     ; nz if change in prog address
  54.         extrn   mpadr:byte      ; master program address
  55.         extrn   mmcount:word    ; master measure count
  56.         extrn   mmtick:word     ; ticks left in current measure
  57.         extrn   mmreset:byte    ; master measure reset flag
  58.         extrn   mmstart:byte    ; master measurd start flag
  59. ;--------------------------------------------------------------
  60.         extrn   rseed:word      ; random number seed
  61.         extrn   rhold:byte      ; rng hold flag
  62.         extrn   notetbl:byte    ; note -> clocks xlate
  63.         extrn   notes:word
  64.         extrn   interv:byte     ; intervals for modulation
  65.         ;
  66.         extrn   xcax:word       ; register storage, used by xcall
  67.         extrn   xcbx:word
  68.         extrn   xccx:word
  69.         extrn   xcdx:word
  70.         ;
  71.         extrn   temp0:byte      ; temp storage, use within module
  72.         extrn   temp1:byte
  73.         extrn   temp2:byte
  74.         extrn   temp3:byte
  75. ;--------------------------------------------------------------
  76. ; the following are saved/loaded
  77. ;--------------------------------------------------------------
  78.         extrn   mvlsav:abs      ; start of mod values to save
  79.         extrn   mute:word       ; channel mute flags
  80.         extrn   mutef:byte      ; 1=mute, 0=solo flag
  81.         ;
  82.         extrn   mbeat:byte      ; master beats/measure
  83.         extrn   mnote:byte      ; master note value
  84.         extrn   mtempo:byte     ; master tempo
  85.         extrn   mclocks:word    ; master clocks/measure
  86.         ;
  87.         extrn   ctrlmap:byte    ; midi controller map
  88.         extrn   pcva:byte       ; values sent to controller
  89.         extrn   pcvb:byte       ; values sent to controller
  90.         extrn   pcvc:byte       ; values sent to controller
  91.         extrn   pcvd:byte       ; values sent to controller
  92.         extrn   pcve:byte       ; values sent to controller
  93.         extrn   pcvf:byte       ; values sent to controller
  94.         ;
  95.         extrn   mvlnum:abs      ; number of mod values to save
  96. ;--------------------------------------------------------------
  97. ;_DATA   ENDS
  98. ;==============================================================
  99. ; Module Execution Code
  100. ; All inputs are word pointers to output word values.
  101. ; All outputs are binary words, with only the ls byte output.
  102. ;==============================================================
  103. ; EQUATES for modules
  104. ;
  105. vseg    equ 4                   ; offset to video seg addr
  106. vaddr   equ 6                   ; offset to video page addr
  107. outn    equ 8                   ; offset to output
  108. numvar  equ 10                  ; number of input variables
  109. var0    equ 12                  ; offset to variable 0
  110. var1    equ var0+2              ; offset to variable 1
  111. var2    equ var1+2              ; etc.
  112. var3    equ var2+2              ; etc.
  113. var4    equ var3+2              ; etc.
  114. var5    equ var4+2              ; etc.
  115. var6    equ var5+2              ; etc.
  116. var7    equ var6+2              ; etc.
  117. var8    equ var7+2              ; etc.
  118. var9    equ var8+2              ; etc.
  119. var10   equ var9+2              ; etc.
  120. var11   equ var10+2             ; etc.
  121. var12   equ var11+2             ; etc.
  122. var13   equ var12+2             ; etc.
  123. var14   equ var13+2             ; etc.
  124. var15   equ var14+2             ; etc.
  125. var16   equ var15+2             ; etc.
  126. var17   equ var16+2             ; etc.
  127. var18   equ var17+2             ; etc.
  128. var19   equ var18+2             ; etc.
  129. var20   equ var19+2             ; etc.
  130. var21   equ var20+2             ; etc.
  131. var22   equ var21+2             ; etc.
  132. slewc   equ var22               ; programmer slew buffer
  133. slewd   equ slewc+6             ; etc.
  134. slewe   equ slewd+6             ; etc.
  135. slewf   equ slewe+6             ; etc.
  136. pubuf   equ slewf+6             ; programmer undo buffer
  137. psbuf   equ pubuf+13            ; programmer save buffer
  138.         ;
  139. onflg   equ 1                   ; bit mask for note-on
  140. offlg   equ 2                   ; bit mask for note-off
  141. sentf   equ 4                   ; bit mask for note-sent
  142. ;--------------------------------------------------------------
  143. _TEXT   SEGMENT
  144.     ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: NOTHING
  145. ;--------------------------------------------------------------
  146.         extrn   ticks:word,loops:word,seconds:word,secondf:byte
  147.         extrn   todec:near,tonote:near,startm:near
  148.         extrn   _cancel:near,workx:near,split:near
  149.         extrn   turnon:near,turnoff:near
  150.         extrn   mstart:byte,mstop:byte,mcont:byte
  151.         extrn   allmidi:near
  152. ;==============================================================
  153.  
  154. ;==============================================================
  155. ; THE MODULES
  156. ;==============================================================
  157.         include    macros.asm
  158. ;==============================================================
  159. ; generate melody & chord changes from input base & intervals
  160. ;--------------------------------------------------------------
  161. ; inputs:
  162. ;    0:   chord array location (16 possible arrays of 4 values)
  163. ;    1:   base input value
  164. ;    2:   1st interval above base
  165. ;    3:   2nd interval above base
  166. ;    4:   3rd interval above base
  167. ;    5:   nz = normalize to octave
  168. ;    6:   offset to base
  169. ;    7:   nz = sort
  170. ;    8:   foldover range
  171. ;    9:   doit strobe
  172. ;    10x: clock ticks
  173. ; output: root # (always 0 unless sort)
  174. ;--------------------------------------------------------------
  175.         public _cgen 
  176. _cgen:
  177.         tick    var9,var10              ; clock strobe
  178.         jc      cgen0                   ; yes, go do it
  179.         jmp     cgenz                   ; exit if no tick
  180.         ;
  181. cgen0:  getv    al,var0                 ; get array location
  182.         and     ax,15                   ; mask
  183.         add     ax,ax                   ; *4
  184.         add     ax,ax                   ; /
  185.         add     ax,offset dgroup:interv ; add in int table addr
  186.         mov     bp,ax                   ; save in bp
  187.         ;       
  188.         getv    al,var1                 ; get input
  189.         testv   var5,-1                 ; want to normalize?
  190.         jz      cgen1                   ; no, branch
  191.         normal                          ; yes, normalize to octave
  192.         mov     al,ah                   ; put back in al
  193.         ;
  194. cgen1:  getv    ah,var6                 ; get offset
  195.         add     al,ah                   ; add to root
  196.         ;
  197.         getv    ah,var2                 ; add intervals to root
  198.         add     ah,al                   ;       /
  199.         getv    dl,var3                 ;      /
  200.         add     dl,al                   ;     /
  201.         getv    dh,var4                 ;    /
  202.         add     dh,al                   ;   /
  203.         ;
  204.         mov     byte ptr outn[di],0     ; root is 0
  205.         testv   var7,-1                 ; want to sort
  206.         jnz     cgen4                   ; yes, do it
  207.         jmp     cgenx                   ; no, exit
  208.         ;
  209. cgen4:  push    ax                      ; save root
  210.         getv    al,var8                 ; get max octave range
  211.         and     al,15                   ; limit
  212.         mov     ch,12                   ;   /
  213.         mul     ch                      ;  /
  214.         add     ch,al                   ; ch = range
  215.         pop     ax                      ; restore root
  216.         ;
  217.         range   al,ch                   ; put in range
  218.         range   ah,ch                   ; put in range
  219.         range   dl,ch                   ; put in range 
  220.         range   dh,ch                   ; put in range 
  221.         ;
  222.         mov     cl,al                   ; save root in cl
  223.         sort4                           ; sort
  224.         mov     ch,0                    ; look for root
  225.         cmp     al,cl                   ;         /
  226.         jz      cgen3                   ;        /
  227.         inc     ch                      ;       /
  228.         cmp     ah,cl                   ;      /
  229.         jz      cgen3                   ;     /
  230.         inc     ch                      ;    /
  231.         cmp     dl,cl                   ;   /
  232.         jz      cgen3                   ;  /
  233.         inc     ch                      ; /
  234. cgen3:  mov     byte ptr outn[di],ch    ; send root # to output
  235.         ;
  236. cgenx:  mov     ds:[bp],ax              ; set chord values
  237.         mov     ds:2[bp],dx             ; /
  238. cgenz:  nextv                           ; exit
  239. ;==============================================================
  240. ; set new chords table data from 4 inputs
  241. ;--------------------------------------------------------------
  242. ; inputs:
  243. ;    0:   chord array location (16 possible arrays of 4 values)
  244. ;    1:   root input
  245. ;    2:   1st interval input
  246. ;    3:   2nd interval input
  247. ;    4:   3rd interval input
  248. ;    5:   nz = normalize to octave
  249. ;    6:   offset to base
  250. ;    7:   nz = sort
  251. ;    8:   foldover range
  252. ;    9:   doit strobe
  253. ;    10x: clock ticks
  254. ; output: root # (always 0 unless sort)
  255. ;--------------------------------------------------------------
  256.         public _cmak 
  257. _cmak:
  258.         tick    var9,var10              ; clock strobe
  259.         jc      cmak0                   ; yes, go do it
  260.         jmp     cmakz                   ; exit if no tick
  261.         ;
  262. cmak0:  getv    al,var0                 ; get array location
  263.         and     ax,15                   ; mask
  264.         add     ax,ax                   ; *4
  265.         add     ax,ax                   ; /
  266.         add     ax,offset dgroup:interv ; add in int table addr
  267.         mov     bp,ax                   ; save in bp
  268.         ;       
  269.         getv    cl,var6                 ; get offset
  270.         getv    al,var1                 ; get inputs
  271.         add     al,cl                   ; add offset
  272.         getv    ah,var2                 ;      /
  273.         add     ah,cl                   ;     /
  274.         getv    dl,var3                 ;    /
  275.         add     dl,cl                   ;   /
  276.         getv    dh,var4                 ;  /
  277.         add     dh,cl                   ; /
  278.         ;
  279.         testv   var5,-1                 ; want to normalize?
  280.         jz      cmak1                   ; no, branch
  281.         mov     cx,ax                   ; yes, save ax
  282.         mov     bx,dx                   ; save dx
  283.         normal                          ; normalize
  284.         mov     cl,ah                   ;          /
  285.         mov     al,ch                   ;         /
  286.         normal                          ;        /
  287.         mov     ch,ah                   ;       /
  288.         mov     al,bl                   ;      /
  289.         normal                          ;     /
  290.         mov     bl,ah                   ;    /
  291.         mov     al,bh                   ;   /
  292.         normal                          ;  /
  293.         mov     bh,ah                   ; /
  294.         mov     ax,cx                   ; restore to ax,dx
  295.         mov     dx,bx                   ; /
  296.         ;
  297. cmak1:  mov     byte ptr outn[di],0     ; root is 0
  298.         testv   var7,-1                 ; want to sort
  299.         jnz     cmak4                   ; yes, do it
  300.         jmp     cmakx                   ; no, exit
  301.         ;
  302. cmak4:  push    ax                      ; save root
  303.         getv    al,var8                 ; get max octave range
  304.         and     al,15                   ; limit
  305.         mov     ch,12                   ;   /
  306.         mul     ch                      ;  /
  307.         add     ch,al                   ; ch = range
  308.         pop     ax                      ; restore root
  309.         ;
  310.         range   al,ch                   ; put in range
  311.         range   ah,ch                   ; put in range
  312.         range   dl,ch                   ; put in range 
  313.         range   dh,ch                   ; put in range 
  314.         ;
  315.         mov     cl,al                   ; save root in cl
  316.         sort4                           ; sort
  317.         mov     ch,0                    ; look for root
  318.         cmp     al,cl                   ;         /
  319.         jz      cmak3                   ;        /
  320.         inc     ch                      ;       /
  321.         cmp     ah,cl                   ;      /
  322.         jz      cmak3                   ;     /
  323.         inc     ch                      ;    /
  324.         cmp     dl,cl                   ;   /
  325.         jz      cmak3                   ;  /
  326.         inc     ch                      ; /
  327. cmak3:  mov     byte ptr outn[di],ch    ; send root # to output
  328.         ;
  329. cmakx:  mov     ds:[bp],ax              ; set chord values
  330.         mov     ds:2[bp],dx             ; /
  331. cmakz:  nextv                           ; exit
  332. ;==============================================================
  333. ; select interval from modulated interval table
  334. ; inputs:
  335. ;    0:   clock
  336. ;    1:   location
  337. ;    2:   interval step
  338. ;    3:   nz = sort
  339. ;    4:   offset
  340. ;    5x:  clock tick
  341. ; output: note interval
  342. ;--------------------------------------------------------------
  343.         public _cplay,_cplai
  344. _cplai: nop                             ; 2 sets of modules
  345. _cplay: tick    var0,var5               ; clock
  346.         jnc     cplayz                  ; branch if no tick
  347.         getv    cl,var1                 ; get interval address
  348.         and     cx,15                   ; mask
  349.         add     cx,cx                   ; *4
  350.         add     cx,cx                   ; /
  351.         add     cx,offset dgroup:interv ; cx = interval address
  352.         ;
  353.         testv   var3,-1                 ; wanna sort?   
  354.         jz      cplay1                  ; no, branch
  355.         ;
  356.         mov     bx,cx                   ; pick up intervals
  357.         mov     ax,[bx]                 ;  /
  358.         mov     dx,2[bx]                ; /
  359.         sort4                           ; sort them
  360.         mov     word ptr temp0,ax       ; put in temp array
  361.         mov     word ptr temp2,dx       ; /
  362.         mov     cx,offset dgroup:temp0  ; cx = sorted interval addr
  363.         ;
  364. cplay1: getv    bl,var2                 ; get interval number
  365.         and     bx,3                    ; mask
  366.         add     bx,cx                   ; bx = table index
  367.         mov     al,[bx]                 ; get the interval
  368.         ;
  369.         getv    ah,var4                 ; get offset
  370.         add     al,ah                   ; add offset to interval
  371.         putn    al                      ; send it out
  372. cplayz: nextv                           ; exit
  373. ;==============================================================
  374. ; store value to interval table
  375. ; inputs:
  376. ;    0:   chord array location (16 possible arrays of 4 values)
  377. ;    1:   location in array
  378. ;    2:   base input value
  379. ;    3:   nz = normalize to octave
  380. ;    4:   offset to base
  381. ;    5:   doit strobe
  382. ;    6x:  clock tick 
  383. ;
  384. ; output: previous value at address
  385. ;--------------------------------------------------------------
  386.         public _cstor
  387. _cstor: tick    var5,var6               ; strobe?
  388.         jnc     cstorz                  ; no, exit
  389.         ;
  390.         getv    al,var2                 ; get input
  391.         testv   var3,-1                 ; want to normalize?
  392.         jz      cstor1                  ; no, branch
  393.         normal                          ; yes, normalize to octave
  394.         mov     al,ah                   ; put back in al
  395.         ;
  396. cstor1: getv    ah,var4                 ; get offset
  397.         add     al,ah                   ; add to input
  398.         ;
  399.         getv    cl,var0                 ; get interval address
  400.         and     cx,15                   ; mask
  401.         add     cx,cx                   ; *4
  402.         add     cx,cx                   ; /
  403.         add     cx,offset dgroup:interv ; cx = interval address
  404.         ;
  405.         getv    bl,var1                 ; get interval number
  406.         and     bx,3                    ; mask
  407.         add     bx,cx                   ; bx = table index
  408.         ;
  409.         xchg    al,[bx]                 ; swap old with new
  410.         putn    al                      ; send old to output
  411. cstorz: nextv                           ; exit
  412. ;==============================================================
  413. ; generate bass note line, dithered input a,b
  414. ; inputs:
  415. ;    0:   clock
  416. ;    1:   nz = hold
  417. ;    2:   strobe center to output
  418. ;    3:   center
  419. ;    4:   max distance from center
  420. ;    5:   nz = use -, z = use +
  421. ;    6:   input "a"
  422. ;    7:   input "b"
  423. ;    8x:  
  424. ;    8z:  clock tick, init flag
  425. ; output: new bass note
  426. ;--------------------------------------------------------------
  427.         public _bassd 
  428. _bassd:
  429.         tickb1  var2,var8+1             ; strobe clock?
  430.         jnc     bassd4                  ; branch if no strobe
  431.         and     byte ptr var8+1[di],0fbh; yes, flag/auto initialize
  432. bassd4: tick    var0,var8+1             ; wait for clock tick
  433.         jnc     bassdz                  ; exit if not clock
  434.         hold    var1                    ; hold?
  435.         jnz     bassdz                  ; exit if hold
  436.         ;
  437.         test    byte ptr var8+1[di],4   ; was flag set?
  438.         jnz     bassd1                  ; no, branch
  439.         or      byte ptr var8+1[di],4   ; yes, clear flag
  440. bassd0: getv    al,var3                 ; get the input
  441.         putn    al                      ; send it to output
  442.         jmp     short bassdz            ; exit
  443.         ;
  444. bassd1: getv    al,var6                 ; load for "a"
  445.         testv   var5,-1                 ; test for +/-
  446.         jz      bassd2                  ; branch if +
  447.         getv    al,var7                 ; load for "b"
  448.         neg     al                      ; make "b" -
  449. bassd2: add     outn[di],al             ; add the offset
  450.         ;
  451.         getv    al,var3                 ; get center
  452.         getv    ah,var4                 ; get max
  453.         mov     dl,al                   ; test for upper limit
  454.         add     dl,ah                   ;  /
  455.         cmp     dl,outn[di]             ; /
  456.         jb      bassd0                  ; reset if above limit
  457.         sub     al,ah                   ; test for lower limit
  458.         cmp     outn[di],al             ; /
  459.         jb      bassd0                  ; reset if below limit
  460. bassdz: nextv                           ; exit
  461. ;==============================================================
  462. ; Bit Formatter
  463. ; inputs: 1 - 8: bit set inputs, zero clrs, nz sets
  464. ; output: byte formatted from the 8 inputs
  465. ;--------------------------------------------------------------
  466.         public _gout
  467. _gout:  
  468.         gettag                  ; es:bx = screen addr of tag
  469.         dec     bx              ; point to leds
  470.         add     bx,480          ; point to the first bit led
  471.         mov     ax,bx           ; ax = screen address pointer
  472.         mov     bp,var0         ; bp = addr of first variable
  473.         mov     dx,100H         ; dl=0, dh=1
  474.         mov     cx,8            ; gonna do 8 bits
  475. gout1:  mov     bx,ds:[bp+di]   ; get the variable address
  476.         cmp     byte ptr [bx],0 ; test for zero/not zero
  477.         mov     bx,ax           ; get screen address
  478.         jnz     gout2           ; branch if not zero
  479.         mov     byte ptr es:[bx],yellow; turn off the led
  480.         jmp     short gout3     ; branch to finish up
  481. gout2:  mov     byte ptr es:[bx],hi+red; turn on the led
  482.         or      dl,dh           ; set the bit
  483. gout3:  shl     dh,1            ; bump bit flag
  484.         add     ax,160          ; bump screen addr 1 line
  485.         add     bp,2            ; bump variable pointer
  486.         loop    gout1           ; loop til done
  487.         putn    dl              ; set the new byte value
  488.         nextv                   ; exit w screen update
  489. ;==============================================================
  490. ; Display bits in a byte as gate lites
  491. ; inputs: 0: byte 
  492. ; output: none
  493. ;--------------------------------------------------------------
  494.         public _gatel
  495. _gatel: 
  496.         getv    al,var0         ; get the byte
  497.         gettag                  ; es:bx = screen addr of tag
  498.         dec     bx              ; point to leds
  499.         add     bx,480          ; point to the first bit led
  500.         mov     cx,8            ; 8 bits to do
  501. gatel1: shr     al,1            ; bit --> cy
  502.         jc      gatel2          ; branch if the bit is hi
  503.         and     byte ptr es:[bx],7; turn the led off
  504.         jmp     short gatel3    ; branch
  505. gatel2: or      byte ptr es:[bx],8; turn the led on
  506. gatel3: add     bx,160          ; go down 1 line
  507.         loop    gatel1          ; do all 8 bits
  508.         nextx                   ; exit quiet
  509.  
  510. ;==============================================================
  511. ; Display values as an indicator bar
  512. ; linear display
  513. ; inputs: 0: left row, 1: right 2: scale
  514. ;         3x: left save, 3z: right save
  515. ; output: none
  516. ;--------------------------------------------------------------
  517.         public _imeter
  518. _imeter:
  519.         getv    al,var0         ; al = left value
  520.         getv    dl,var1         ; dl = right value
  521.         getv    dh,var2         ; dh = scale
  522.         or      dh,dh           ; scale = 0?
  523.         jnz     imeter0         ; no, branch
  524.         inc     dh              ; yes, start with 1
  525. imeter0:mov     es,4[di]        ; get seg addr
  526.         mov     bx,6[di]        ; get module screen address
  527.         add     bx,160*5        ; point to top row of leds
  528.         ;
  529.         inc     bx              ; point to left leds
  530.         cmp     al,var3[di]     ; has left changed
  531.         jz      imeter4         ; no, branch
  532.         mov     var3[di],al     ; yes, save new value
  533.         push    dx              ; save right value & scale
  534.         or      al,al           ; al = 0 ?
  535.         jz      imeter7         ; yes, don't divide
  536.         mov     ah,0            ; ax = left value
  537.         div     dh              ; al = ax/dl
  538. imeter7:call    imeter1         ; show the new value
  539.         pop     dx              ; restore right value & scale
  540. imeter4:add     bx,2            ; point to right column
  541.         cmp     dl,var3+1[di]   ; did middle change
  542.         jz      imeter6         ; no, branch
  543.         mov     var3+1[di],dl   ; yes, save the new value
  544.         mov     al,dl           ; al = right value
  545.         or      al,al           ; al = 0 ?
  546.         jz      imeter8         ; yes, don't divide
  547.         mov     ah,0            ; ax = left value
  548.         div     dh              ; al = ax/dl
  549. imeter8:call    imeter1         ; show the new value
  550. imeter6:nextx                   ; exit quiet
  551.  
  552. ;--------------------------------------------------------------
  553. ; convert linear 0-8 to log bit position
  554. ; then jump to emeter1 to display
  555. ; call with al = value 
  556. ;
  557. imeter1:test    al,0f8h         ; if > 7, max out
  558.         jz      imeter2         ;   /
  559.         mov     dl,-1           ;  /
  560.         jmp     short imeter3   ; /
  561. imeter2:mov     cl,al           ; else convert
  562.         xor     al,al           ;    /
  563.         stc                     ;   /
  564.         rcl     al,cl           ;  /
  565.         mov     dl,al           ; /
  566. imeter3:jmp     emeter1         ; display
  567.  
  568. ;==============================================================
  569. ; Display values as an indicator bar
  570. ; inputs: 0: left row, 1: right 2: scale
  571. ;         3x: left save, 3z: right save
  572. ; output: none
  573. ;--------------------------------------------------------------
  574.         public _emeter
  575. _emeter:
  576.         getv    al,var0         ; al = left value
  577.         getv    dl,var1         ; dl = right value
  578.         getv    dh,var2         ; dh = multiplier
  579.         or      dh,dh           ; mult = 0?
  580.         jnz     emeter0         ; no, branch
  581.         inc     dh              ; yes, start with 1
  582. emeter0:mov     es,4[di]        ; get seg addr
  583.         mov     bx,6[di]        ; get module screen address
  584.         add     bx,160*5        ; point to top row of leds
  585.         ;
  586.         inc     bx              ; point to left leds
  587.         cmp     al,var3[di]     ; has left changed
  588.         jz      emeter4         ; no, branch
  589.         mov     var3[di],al     ; yes, save new value
  590.         push    dx              ; save right value & mult
  591.         mul     dh              ; ax = bumped right value
  592.         or      ah,ah           ; > 255 ?
  593.         jz      emeter5         ; no, branch
  594.         mov     al,255          ; yes, make it 255
  595. emeter5:mov     dl,al           ; set up for display
  596.         call    emeter1         ; show the new value
  597.         pop     dx              ; restore right value & scale
  598. emeter4:add     bx,2            ; point to right column
  599.         mov     al,dl           ; al = right value
  600.         cmp     al,var3+1[di]   ; did right change
  601.         jz      emeter6         ; no, branch
  602.         mov     var3+1[di],al   ; yes, save the new value
  603.         mul     dh              ; ax = bumped right value
  604.         or      ah,ah           ; > 255 ?
  605.         jz      emeter7         ; no, branch
  606.         mov     al,255          ; yes, make it 255
  607. emeter7:mov     dl,al           ; set up for display
  608.         call    emeter1         ; show the new value
  609. emeter6:nextx                   ; exit quiet
  610.  
  611. ;--------------------------------------------------------------
  612. ; subroutine to show a column of leds
  613. ; call with BX = address of top of column (preserved), DL = value
  614. ; display is log, sets top led high and all following if
  615. ; bit 7 is set, else sets top led low, then top-1 if bit 6, etc.
  616. ;
  617. emeter1:push    bx              ; preserve bx
  618.         mov     dh,0            ; use dh as flag byte
  619.         mov     cx,8            ; 8 leds in the column
  620. emeterl:shl     dx,1            ; bump hi bit of dl into dh
  621.         test    dh,-1           ; on or off?
  622.         jz      emeter2         ; branch if off
  623.         or      byte ptr es:[bx],8    ; make bright
  624.         jmp     short emeter3         ; duck
  625. emeter2:and     byte ptr es:[bx],0f7h ; or make dark  
  626. emeter3:add     bx,160          ; next line
  627.         loop    emeterl         ; loop til done 
  628.         pop     bx              ; restore bx
  629.         ret                     ; exit
  630. ;==============================================================
  631. ; Set output to approximately the same as input, within limits
  632. ; inputs: 0: input 1: upper limit, 2: lower limit, 
  633. ;         3x: last input
  634. ; output: scaled random number
  635. ;--------------------------------------------------------------
  636.         public _apprx
  637. _apprx: 
  638.         getv    dl,var0         ; get the value
  639.         test    rhold,-1        ; branch if alpha seed
  640.         jnz     appr1           ; /
  641.         cmp     dl,var3[di]     ; same as last?
  642.         jnz     appr1           ; no, go to work
  643.         nextx                   ; yes, easy exit
  644.         ;
  645. appr1:  mov     var3[di],dl     ; set new value
  646.         random
  647.         getv    al,var1         ; get upper offset
  648.         inc     al              ; fudge
  649.         add     al,dl           ; add in value
  650.         mov     ah,0            ; msb = 0
  651.         getv    bl,var2         ; get lower offset
  652.         sub     dl,bl           ; subtract from value
  653.         mov     bl,dl           ; keep it in bl
  654.         mov     bh,0            ; msb = 0
  655.         sub     ax,bx           ; ax = upper - lower
  656.         mul     cx              ; dx = appr * (upper-lower)/10000H
  657.         add     dx,bx           ; dx = above + lower 
  658.         putn    dl              ; send it out
  659.         nextv                   ; exit with video update
  660. ;==============================================================
  661. ; Generate random numbers
  662. ; inputs: 0: clock 1: hold 2: seed value, 3: range, 4: offset, 
  663. ;         5: seed, 6x: saved value,   6z: clock-tick
  664. ; output: random number
  665. ;--------------------------------------------------------------
  666.         public _rand
  667. _rand:
  668.         mov     ah,var6[di]     ; get last value
  669.         ;
  670.         getv    al,var1         ; local hold?
  671.         or      al,rhold        ; global rand hold?
  672.         jz      rand0           ; no, branch
  673. rand2:  getv    al,var2         ; yes, reset seed
  674.         mov     ah,al           ;  /
  675.         mov     var5[di],ax     ; /
  676.         jmp     rand1a          ; go out
  677.         ;
  678. rand0:  test    mprstf,-1       ; master hold?
  679.         jnz     rand1           ; yes, branch
  680.         ;
  681.         tick    var0,var6+1     ; clock tick
  682.         jnc     rand1           ; branch if no tick
  683.         ;
  684.         mov     cx,var5[di]     ;; get next raw seed
  685.         add     cx,9248H        ;;     /
  686.         ror     cx,1            ;;    /
  687.         ror     cx,1            ;;   /
  688.         ror     cx,1            ;;  /
  689.         mov     var5[di],cx     ;; /
  690.         ;
  691.         getv    al,var3         ; get range
  692.         mul     cl              ; ah = rand * range /256
  693. rand1a: mov     var6[di],ah     ; put it away
  694. rand1:  getv    al,var4         ; get offset
  695.         add     al,ah           ; put them together
  696.         putn    al              ; send it out
  697.         nextv                   ; exit
  698. ;==============================================================
  699. ; Non-repeating random pattern
  700. ; inputs: 0: clock 1: hold  2: seed value, 3: inc/dec, 4: range
  701. ;         5x: saved value, 5z: clock-tick, 6: address pointer
  702. ; output: random number
  703. ;--------------------------------------------------------------
  704.         public _rrand
  705. _rrand:
  706.         getv    cl,var4         ; get range
  707.         cmp     cl,1            ; check for 0,1
  708.         jna     rrand0          ; split if 0
  709.         mov     dx,1            ; for inc/dec
  710.         testv   var3,-1         ; dec if nz
  711.         jz      rrand03         ;  /
  712.         mov     dx,-1           ; /
  713.         ;
  714. rrand03:
  715.         getv    al,var1         ; local hold?
  716.         or      al,rhold        ; global rand hold?
  717.         jz      rrand01         ; no, branch
  718. rrand2: getv    al,var2         ; yes, get seed
  719.         putn    al              ; send it out
  720.         mov     ah,64           ;   /
  721.         mul     ah              ;  /
  722.         mov     var6[di],ax     ; /
  723.         jmp     rrandx          ; split
  724.         ;
  725. rrand01:test    mprstf,-1       ; master hold?
  726.         jnz     rrand0          ; yes, branch
  727.         ;
  728.         tick    var0,var5+1     ; clock tick
  729.         jc      rrand1          ; branch if tick
  730. rrand0: nextx                   ; else just split
  731.         ;
  732. rrand1: add     var6[di],dx     ; bump pointer
  733. rrandz: mov     bx,var6[di]     ; get it
  734.         and     bx,3fffh        ; keep in code range
  735.         add     bx,offset _doit ; start of code
  736.         mov     ax,cs:[bx]      ; get the byte
  737.         add     al,ah           ; fill it out
  738.         mul     cl              ; ah = rand * range /256
  739.         cmp     ah,var5[di]     ; same as last?
  740.         jz      rrand1          ; yes, do it again
  741.         mov     var5[di],ah     ; no, save it
  742.         putn    ah              ; send it out
  743. rrandx: nextv                   ; exit
  744. ;==============================================================
  745. ; Random strobe generator
  746. ; output: 50% strobe
  747. ; input: 0: strobe, 1x: clock tick
  748. ;--------------------------------------------------------------
  749.         public _randp
  750. _randp:
  751.         mov     cl,0            ; setup for hold
  752.         test    mprstf,-1       ; check alpha hold
  753.         jnz     randpx          ; yes, exit
  754.         tick    var0,var1       ; clock input
  755.         jnc     randpz          ; exit if no clock
  756.         random                  ; get random value
  757.         and     cl,1            ; isolate lsb
  758. randpx: putn    cl              ; send it our
  759. randpz: nextl                   ; show it
  760. ;==============================================================
  761. ; Random strobe generator
  762. ; output: clock strobe
  763. ; input: 0: reset, 1: count, 2: offset 3: dither
  764. ;        4x:countdown timer, 4z: copy of count
  765. ;--------------------------------------------------------------
  766.         public _nrand
  767. _nrand: testv   var1,-1         ; clock = 0
  768.         jz      nrandz          ; yes, just exit
  769.         hold    var0            ; hold?
  770.         jz      nrand0          ; no, branch
  771.         mov     al,byte ptr cs:loops; get count
  772.         and     al,1            ; /
  773.         mov     var4[di],al     ; reset clock counters
  774.         jmp     short nrandz    ; split
  775.         ;
  776. nrand0: getv    ah,var1         ; get current count
  777.         cmp     ah,var4+1[di]   ; same as before?
  778.         jz      nrand1          ; yes, branch
  779.         cmp     ah,1            ; set to 1?
  780.         jnz     nrand3          ; no, branch
  781.         mov     ah,2            ; yes, set to 2
  782. nrand3: mov     al,byte ptr cs:loops; get count
  783.         and     al,1            ; /
  784.         mov     var4[di],ax     ; /
  785.         ;
  786. nrand1: getv    al,var2         ; get offset trigger
  787.         cmp     al,ah           ; out of range?
  788.         jb      nrand4          ; no, branch
  789.         mov     al,0            ; yes, zip it
  790. nrand4: cmp     al,var4[di]     ; same as count?
  791.         jnz     nrand2          ; no, branch
  792.         random                  ; yes, get random value
  793.         getv    ch,var3         ; get ddithr value
  794.         sub     ch,cl           ; above threshold?
  795.         jna     nrand2          ; no, branch
  796.         mov     byte ptr outn[di],1; else output flag
  797.         ;
  798. nrand2: inc     byte ptr var4[di]; tick
  799.         cmp     ah,var4[di]     ; reached count?
  800.         jnz     nrandz          ; no, exit
  801.         mov     byte ptr var4[di],0; yes, reset timer
  802. nrandz: nextt                   ; exit
  803. ;==============================================================
  804. ; Random slope output
  805. ; inputs 0: count,    1: range,  
  806. ;        2x: target,  2+:
  807. ;        3x: current, 3+: +/-
  808. ;        4x: clock,   4+: old clock    
  809. ;
  810. ; ouput  last +/- 1
  811. ;--------------------------------------------------------------
  812.         public _variz,_variy
  813. _variy: nop
  814. _variz:
  815.         getv    dh,var1                 ; get range input
  816.         getv    al,var0                 ; get clock
  817.         ;
  818.         test    dh,80H                  ; test msb of range for reset
  819.         jnz     varizz                  ; go reset if high
  820.         ;
  821.         test    mprstf,-1               ; check for master reset
  822.         jnz     varizz                  ; reset if high
  823.         ;
  824.         test    rhold,-1                ; check for random reset
  825.         jnz     varizz                  ; reset if high
  826.         ;
  827.         cmp     al,var4+1[di]           ; clock same as before
  828.         jz      variz0                  ; yes, go to work
  829.         jmp     varizk                  ; no, fix clock
  830. ;--------------------------------------------------------------
  831. varizz: and     dh,7fh                  ; strip msb
  832.         putn    dh                      ; send it out
  833.         mov     var2[di],dh             ; set as target
  834.         mov     byte ptr var3+1[di],1   ; set to count up
  835.         shr     dh,1                    ; current is range/2
  836.         shr     dh,1                    ; current is range/2
  837.         mov     var3[di],dh             ;  /
  838.         ;
  839. varizk: mov     var4+1[di],al           ; save clock
  840.         mov     byte ptr var4[di],1     ; new one next clock
  841.         nextv                           ; split
  842. ;--------------------------------------------------------------
  843. varizzx:nextx                           ; split
  844. variz0: dec     byte ptr var4[di]       ; bump clock
  845.         jnz     varizzx                 ; exit if not 0
  846.         getv    al,var0                 ; else get it
  847.         mov     var4+1[di],al           ; save clock
  848.         inc     al                      ; bump
  849.         mov     var4[di],al             ; put away
  850. ;--------------------------------------------------------------
  851.         mov     dl,var3[di]             ; get current value
  852.         add     dl,var3+1[di]           ; add bump
  853.         mov     var3[di],dl             ; put it away
  854.         cmp     dl,var2[di]             ; reached target?
  855.         jnz     variz2                  ; no, branch
  856.         ;
  857. variz1: random                          ; get new rand
  858.         mov     al,dh                   ; get range
  859.         test    ch,0E0H                 ; 3/4 of the time
  860.         jz      variz1a                 ; ... use it straight
  861.         rcr     cl,1                    ; ... else cut 1/2
  862.         jnc     variz1a                 ; ... and maybe more
  863.         shr     cl,1                    ; ... cut again
  864. variz1a:mul     cl                      ; ah = rand * range /256
  865.         ;
  866.         mov     byte ptr var3+1[di],0ffh; set up for inc
  867.         cmp     ah,var2[di]             ; is it < target?
  868.         jb      variz3                  ; yes,is <, exit
  869.         mov     byte ptr var3+1[di],1   ; no, set up for dec
  870.         jnz     variz3                  ; exit if <>
  871.         inc     ah                      ; else bump
  872. variz3:
  873.         mov     var2[di],ah             ; save new target
  874. variz2:
  875.         shr     dh,1                    ; calc offset
  876.         shr     dh,1                    ; calc offset
  877.         add     dl,dh                   ; add in count
  878.         jns     variz2a                 ; branch if <= 7fh
  879.         mov     dl,7fh                  ; else make 7fh
  880. variz2a:putn    dl                      ; send it out
  881.         nextv                           ; exit
  882. ;==============================================================
  883. ; Random slope output
  884. ; inputs 0: clock 1: hold, 2: range 3: offset
  885. ;        4x: +/-  4+: clock tick, 5x: target, 5+: current
  886. ; ouput  last +/- 1
  887. ;--------------------------------------------------------------
  888.         public _variv
  889. _variv:
  890.         test    rhold,-1                ; check for random reset
  891.         jnz     variv00                 ; reset if high
  892.         ;
  893.         hold    var1                    ; hold?
  894.         jz      variv0                  ; no, branch
  895. variv00:mov     ah,var5+1[di]           ; yes, get current
  896.         getv    al,var3                 ; get offset
  897.         add     al,ah                   ; put them together
  898.         putn    al                      ; send it   
  899.         ;
  900.         inc     ah                      ; bump current
  901.         mov     var5[di],ah             ; set up target
  902.         mov     byte ptr var4[di],1     ; set up counter
  903.         nextv                           ; exit
  904. ;--------------------------------------------------------------
  905. variv0:
  906.         tick    var0,var4+1             ; clock tick
  907.         jc      variv1                  ; branch if tick
  908.         nextx                           ; else just exit
  909. ;--------------------------------------------------------------
  910. variv1: mov     dl,var5+1[di]           ; get current value
  911.         add     dl,var4[di]             ; add bump
  912.         mov     var5+1[di],dl           ; put it away
  913.         cmp     dl,var5[di]             ; reached target?
  914.         jnz     variv2                  ; no, branch
  915.         ;
  916.         random                          ; else get new rand
  917.         getv    al,var2                 ; get range
  918.         mul     cl                      ; ah = rand * range /256
  919.         ;
  920.         mov     byte ptr var4[di],-1    ; set up for inc
  921.         cmp     ah,var5[di]             ; is it < target?
  922.         jb      variv3                  ; yes,is <, exit
  923.         mov     byte ptr var4[di],1     ; no, set up for dec
  924.         jnz     variv3                  ; exit if <>
  925.         inc     ah                      ; else bump
  926. variv3:
  927.         mov     var5[di],ah             ; save new target
  928. variv2:
  929.         getv    al,var3                 ; get offset
  930.         add     al,dl                   ; add current
  931.         putn    al                      ; send it out
  932.         nextv                           ; exit
  933. ;==============================================================
  934. ; Random slope output
  935. ; inputs 0:  clock 
  936. ;        1:  hold
  937. ;        2:  addamt
  938. ;        3:  range 
  939. ;        4:  offset
  940. ;        5x: target
  941. ;        6x: count
  942. ;        6+: b7=sign, b0=clock tick
  943. ;
  944. ; output: count+offset
  945. ;--------------------------------------------------------------
  946.         public _varix
  947. _varix:
  948.         test    rhold,-1                ; check for random reset
  949.         jnz     varix00                 ; reset if high
  950.         ;
  951.         hold    var1                    ; hold?
  952.         jz      varix0                  ; no, branch
  953. varix00:mov     byte ptr var6[di],0     ; yes count = 0
  954.         mov     byte ptr var5[di],0     ; target = 1
  955.         and     byte ptr var6+1[di],7FH ; set sign bit
  956. varixz: jmp     varixx                  ; exit w count+offset
  957. ;--------------------------------------------------------------
  958. varix0:
  959.         tick    var0,var6+1             ; clock tick
  960.         jc      varix1                  ; branch if tick
  961.         nextx                           ; else just exit
  962. ;--------------------------------------------------------------
  963. varix1: getv    al,var2                 ; get add ammt
  964.         getv    ah,var3                 ; is add amb > range
  965.         cmp     al,ah                   ; add amt - range
  966.         jnb     varixz                  ; yes, just exit
  967.         ;       
  968.         mov     ah,0                    ; ax = add amt
  969.         mov     dl,var6[di]             ; get count
  970.         mov     dh,0                    ; dx = count
  971.         ;
  972.         test    byte ptr var6+1[di],80H ; sign = count down?
  973.         jnz     varix1a                 ; yes, branch
  974.         ;
  975.         add     dx,ax                   ; dx = count + add amt
  976.         mov     al,var5[di]             ; get target
  977.         mov     ah,0                    ; ax = target
  978.         cmp     ax,dx                   ; target - new count
  979.         jnb     varix4                  ; send if target > nc
  980.         jmp     varix2                  ; else get a new one
  981. ;--------------------------------------------------------------
  982. varix1a:sub     dx,ax                   ; dx = count - add amt
  983.         jnc     varix1b                 ; make 0 if underflow
  984.         mov     dx,0                    ; /
  985. varix1b:mov     al,var5[di]             ; get target
  986.         mov     ah,0                    ; ax = target
  987.         cmp     ax,dx                   ; target - new count
  988.         jna     varix4                  ; send if target < nc
  989. ;       jmp     varix2                  ; else get a new one
  990. ;--------------------------------------------------------------
  991. varix2: random                          ; else get new rand
  992.         getv    al,var3                 ; get range
  993.         or      al,al                   ; exit if range=0
  994.         jz      varixx                  ; /
  995.         mul     cl                      ; ah = rand * range /256
  996.         or      ah,ah                   ; don't want 0
  997.         jz      varix2                  ; /  
  998.         xchg    var5[di],ah             ; save new target
  999.         mov     var6[di],ah             ; set count to old target
  1000.         cmp     ah,var5[di]             ; old - new
  1001.         ja      varix2a                 ; old >  new, go count down
  1002.         ;
  1003.         and     byte ptr var6+1[di],7FH ; clear sign
  1004.         getv    al,var2                 ; get add ammt
  1005.         mov     ah,0                    ; ax = add amt
  1006.         mov     dl,var6[di]             ; get count
  1007.         mov     dh,0                    ; dx = count
  1008.         add     dx,ax                   ; dx = count + add amt
  1009.         jmp     varix4                  ; go with dl = new count
  1010.         ;
  1011. varix2a:or      byte ptr var6+1[di],80H ; set sign
  1012.         getv    al,var2                 ; get add ammt
  1013.         mov     ah,0                    ; ax = add amt
  1014.         mov     dl,var6[di]             ; get count
  1015.         mov     dh,0                    ; dx = count
  1016.         sub     dx,ax                   ; dx = count - add amt
  1017.         jnc     varix4                  ; make 0 if underflow
  1018.         mov     dl,0                    ; /
  1019. ;--------------------------------------------------------------
  1020. varix4: mov     var6[di],dl             ; save new count
  1021. varixx: getv    al,var4                 ; get offset
  1022.         add     al,var6[di]             ; add count
  1023.         putn    al                      ; send it out
  1024.         nextv                           ; exit
  1025. ;==============================================================
  1026. ; Generate a random tone row of 0-11
  1027. ; inputs: 0:  address
  1028. ;         1:  strobe
  1029. ;         2x: tick
  1030. ;         3-9:tone row table
  1031. ; output: addressed value of tone row (0-11)
  1032. ;--------------------------------------------------------------
  1033.         public _trand
  1034. _trand: 
  1035.         test    rhold,-1        ; check for random reset
  1036.         jnz     trand1          ; branch if high
  1037.         ;
  1038.         tick    var1,var2       ; clock tick
  1039.         jnc     trand1          ; branch if no tick
  1040.         ;
  1041.         mov     cx,12           ; 12 to do
  1042.         mov     bp,0            ; set up base
  1043. trand3: mov     bx,0            ; set up index
  1044.         test    rhold,-1        ; holding?
  1045.         jz      trand7          ; no, get rand
  1046.         mov     dx,bp           ; yes, do 0-1
  1047.         jmp     short trand2    ; get on with it
  1048.         ;
  1049. trand7: randdx                  ; get rng
  1050.         and     dl,15           ; 0-15 allowed
  1051.         cmp     dl,12           ; really 0-11
  1052.         jb      trand2          ; branch if ok
  1053.         shr     dl,1            ; else /2
  1054.         ;
  1055. trand2: cmp     bx,bp           ; at the target?
  1056.         jnz     trand4          ; no, branch
  1057.         mov     var3[bx+di],dl  ; yes, put the byte away
  1058. trand6: inc     bp              ; bump index
  1059.         loop    trand3          ; do all 12
  1060.         jmp     short trand1    ; exit when done
  1061.         ;
  1062. trand4: cmp     var3[bx+di],dl  ; already got?
  1063.         jz      trand3          ; yes, try again
  1064.         inc     bx              ; no, look at next
  1065.         jmp     short trand2    ; /
  1066.         ;
  1067. trand1: getv    bl,var0         ; get address
  1068.         mov     bh,0            ; make into word
  1069.         cmp     bl,12           ; keep within range
  1070.         jb      trand0          ; branch if ok
  1071.         ;
  1072.         mov     ax,bx           ; else mod 12
  1073.         mov     dl,12           ;   /
  1074.         div     dl              ;  /
  1075.         mov     bl,ah           ; /
  1076.         ;
  1077. trand0: mov     al,var3[bx+di]  ; pick up the byte
  1078.         putn    al              ; send it out
  1079.         nextv                   ; exit
  1080. ;==============================================================
  1081. ; Generate raw binary odds
  1082. ; inputs: 0: clock  1x: clock-tick
  1083. ; output: 0-7; 0 @ 1:2, 1 @ 1:4, ... 7 @ 1:256
  1084. ;--------------------------------------------------------------
  1085.         public _oddz 
  1086. _oddz:  
  1087.         tick    var0,var1       ; clock tick
  1088.         jc      oddz1           ; branch if there is a tick
  1089.         nextx                   ; else exit easy
  1090. oddz1:  random
  1091.         mov     al,0            ; output is 0-7
  1092.         rol     cl,1            ; test msb
  1093.         jc      oddzx           ; branch if set
  1094.         inc     al              ; else bump value
  1095.         rol     cl,1            ; test msb
  1096.         jc      oddzx           ; branch if set
  1097.         inc     al              ; else bump value
  1098.         rol     cl,1            ; test msb
  1099.         jc      oddzx           ; branch if set
  1100.         inc     al              ; else bump value
  1101.         rol     cl,1            ; test msb
  1102.         jc      oddzx           ; branch if set
  1103.         inc     al              ; else bump value
  1104.         rol     cl,1            ; test msb
  1105.         jc      oddzx           ; branch if set
  1106.         inc     al              ; else bump value
  1107.         rol     cl,1            ; test msb
  1108.         jc      oddzx           ; branch if set
  1109.         inc     al              ; else bump value
  1110.         rol     cl,1            ; test msb
  1111.         jc      oddzx           ; branch if set
  1112.         inc     al              ; else bump value
  1113.         rol     cl,1            ; test msb
  1114.         jc      oddzx           ; branch if set
  1115.         xor     al,al           ; else clr value
  1116. oddzx:  putn    al              ; send it out
  1117.         nextv                   ; exit
  1118. ;==============================================================
  1119. ; dither between 4 inputs
  1120. ; inputs: 0: clock, 1-4: inputs, 5: offset, 6x: clock
  1121. ; output: one of the 4 inputs
  1122. ;--------------------------------------------------------------
  1123.         public _odds
  1124. _odds:  
  1125.         test    rhold,-1        ; branch if alpha seed
  1126.         jnz     odds1           ; /
  1127.         tick    var0,var6       ; clock tick
  1128.         jc      odds1           ; branch if there is a tick
  1129. oddsz:  nextx                   ; else exit easy
  1130. odds1:  random
  1131.         test    cl,80H          ; 1:2 is input1
  1132.         jz      odds2           ;     /
  1133.         getv    al,var1         ;   /
  1134.         jmp     short oddsx     ; /
  1135. odds2:  test    cl,40H          ; 1:4 is input2
  1136.         jz      odds3           ;     /
  1137.         getv    al,var2         ;   /
  1138.         jmp     short oddsx     ; /
  1139. odds3:  test    cl,20H          ; 1:8 is input3
  1140.         jz      odds4           ;     /
  1141.         getv    al,var3         ;   /
  1142.         jmp     short oddsx     ; /
  1143. odds4:  test    cl,10H          ; 1:16 is input4
  1144.         jz      oddsz           ; else no change
  1145.         getv    al,var4         ; /
  1146.         ;
  1147. oddsx:  getv    ah,var5         ; get the offset
  1148.         add     al,ah           ; add to input
  1149.         putn    al              ; send it out
  1150.         nextv                   ; exit with video update
  1151. ;==============================================================
  1152. ; dither between 2 inputs
  1153. ; inputs: 0: clock, 1: dither, 2,3 inputs, 4: offset, 5x: clock
  1154. ; output: one of the 2 inputs
  1155. ;--------------------------------------------------------------
  1156.         public _dither
  1157. _dither:
  1158.         test    rhold,-1        ; branch if alpha seed
  1159.         jnz     dither1         ; /
  1160.         tick    var0,var5       ; clock tick
  1161.         jc      dither1         ; branch if there is a tick
  1162. ditherz:nextx                   ; else exit easy
  1163. dither1:random
  1164.         ;
  1165. dither2:getv    ch,var1         ; get dither value
  1166.         sub     ch,cl           ; above threshold?
  1167.         jna     dither3         ; no, branch
  1168.         getv    al,var3         ; yes, get "b" input
  1169.         jmp     short ditherx   ; split
  1170. dither3:getv    al,var2         ; no, get "a" input
  1171. ditherx:getv    ah,var4         ; get the offset
  1172.         add     al,ah           ; add to input
  1173.         putn    al              ; send it out
  1174.         nextv                   ; exit with video update
  1175. ;==============================================================
  1176. ; dither between and input and 0
  1177. ; inputs: 0: clock, 1: dither, 2: input, 3: offset, 4x: clock
  1178. ; output: the input or 0
  1179. ;--------------------------------------------------------------
  1180.         public _dithzr
  1181. _dithzr:
  1182.         test    rhold,-1        ; branch if alpha seed
  1183.         jnz     dithzr1         ; /
  1184.         tick    var0,var4       ; clock tick
  1185.         jc      dithzr1         ; branch if there is a tick
  1186. dithzrz:nextx                   ; else exit easy
  1187. dithzr1:random
  1188.         ;
  1189. dithzr2:getv    ch,var1         ; get dithzr value
  1190.         sub     ch,cl           ; above threshold?
  1191.         jna     dithzr3         ; yes, branch
  1192.         getv    al,var2         ; no, get the input
  1193.         jmp     short dithzrx   ; split
  1194. dithzr3:mov     al,0            ; no, make it 0
  1195. dithzrx:getv    ah,var3         ; get the offset
  1196.         add     al,ah           ; add to input
  1197.         putn    al              ; send it out
  1198.         nextv                   ; exit with video update
  1199. ;==============================================================
  1200. ; dither between 0 and 1
  1201. ; inputs: 0: clock, 1: dither, 2x: clock
  1202. ; output: 0/1
  1203. ;--------------------------------------------------------------
  1204.         public _ddithr
  1205. _ddithr:
  1206.         test    rhold,-1        ; branch if alpha seed
  1207.         jnz     ddithr1         ; /
  1208.         tick    var0,var2       ; clock tick
  1209.         jc      ddithr1         ; branch if there is a tick
  1210. ddithrz:nextx                   ; else exit easy
  1211. ddithr1:random
  1212. ddithr2:getv    ch,var1         ; get ddithr value
  1213.         sub     ch,cl           ; above threshold?
  1214.         mov     al,1            ; set flag
  1215.         ja      ddithrx         ; yes, branch branch
  1216.         dec     al              ; no, clear flag
  1217. ddithrx:putn    al              ; send it out
  1218.         nextl                   ; exit with video update
  1219. ;==============================================================
  1220. ; calc given ratio based on clock input
  1221. ; inputs: 0:   master clock
  1222. ;         1-4: clock inputs
  1223. ;         5x:  clock ticks
  1224. ;         5z:  storage for output until tick
  1225. ; output: 0-F, based on input pattern
  1226. ;--------------------------------------------------------------
  1227.         public _ratio
  1228. _ratio:
  1229.         mov     al,var5+1[di]   ; get current output
  1230.         tick    var1,var5       ; clock tick
  1231.         jnc     ratio1          ; branch if no tick
  1232.         xor     al,1            ; else flip the bit
  1233. ratio1: tickb1  var2,var5       ; clock tick
  1234.         jnc     ratio2          ; branch if no tick
  1235.         xor     al,2            ; else flip the bit
  1236. ratio2: tickb2  var3,var5       ; clock tick
  1237.         jnc     ratio3          ; branch if no tick
  1238.         xor     al,4            ; else flip the bit
  1239. ratio3: tickb3  var4,var5       ; clock tick
  1240.         jnc     ratio4          ; branch if no tick
  1241.         xor     al,8            ; else flip the bit
  1242. ratio4: mov     var5+1[di],al   ; put it away
  1243.         tickb4  var0,var5       ; master clock tick?
  1244.         jnc     ratioz          ; no, exit
  1245.         putn    al              ; yes, send out new tick
  1246. ratioz: nextv                   ; exit with video update
  1247. ;==============================================================
  1248. ; calc given ratio based on dither input
  1249. ; inputs: 0:   clock
  1250. ;         1-4: dither levels
  1251. ;         5x:  clock tick 
  1252. ; output: 0-F, based on input pattern
  1253. ;--------------------------------------------------------------
  1254.         public _ratiz
  1255. _ratiz:
  1256.         test    rhold,-1        ; branch if alpha seed
  1257.         jnz     ratiz0          ; /
  1258.         tick    var0,var5       ; tick?
  1259.         jc      ratiz0          ; yes, branch
  1260.         jmp     ratizz          ; no, just exit
  1261. ratiz0: mov     al,outn[di]     ; get current output
  1262.         random
  1263.         getv    ch,var1         ; get ddithr value
  1264.         or      ch,ch           ; anything there
  1265.         jnz     ratiza          ; yes, branch
  1266.         and     al,0feh         ; no, clear the bit
  1267. ratiza: sub     ch,cl           ; above threshold?
  1268.         jna     ratiz1          ; no, branch
  1269.         xor     al,1            ; yes, set flag
  1270. ratiz1: random
  1271.         getv    ch,var2         ; get ddithr value
  1272.         or      ch,ch           ; anything there
  1273.         jnz     ratizb          ; yes, branch
  1274.         and     al,0fdh         ; no, clear the bit
  1275. ratizb: sub     ch,cl           ; above threshold?
  1276.         jna     ratiz2          ; no, branch
  1277.         xor     al,2            ; yes, set flag
  1278. ratiz2: random
  1279.         getv    ch,var3         ; get ddithr value
  1280.         or      ch,ch           ; anything there
  1281.         jnz     ratizc          ; yes, branch
  1282.         and     al,0fbh         ; no, clear the bit
  1283. ratizc: sub     ch,cl           ; above threshold?
  1284.         jna     ratiz3          ; no, branch
  1285.         xor     al,4            ; yes, set flag
  1286. ratiz3: random
  1287.         getv    ch,var4         ; get ddithr value
  1288.         or      ch,ch           ; anything there
  1289.         jnz     ratizd          ; yes, branch
  1290.         and     al,0f7h         ; no, clear the bit
  1291. ratizd: sub     ch,cl           ; above threshold?
  1292.         jna     ratiz4          ; no, branch
  1293.         xor     al,8            ; yes, set flag
  1294. ratiz4: putn    al              ; send it out
  1295. ratizz: nextv                   ; exit with video update
  1296. ;==============================================================
  1297. ; select intervals
  1298. ; inputs:
  1299. ;    0:   sort step
  1300. ;    1-4: inputs
  1301. ;
  1302. ; output: value at sorted step
  1303. ;--------------------------------------------------------------
  1304.         public _sort
  1305. _sort:  getv    al,var1                 ; get the inputs
  1306.         getv    ah,var2                 ;   /
  1307.         getv    dl,var3                 ;  /
  1308.         getv    dh,var4                 ; /
  1309.         sort4                           ; sort them
  1310.         mov     word ptr temp0,ax       ; put in temp array
  1311.         mov     word ptr temp2,dx       ; /
  1312.         getv    bl,var0                 ; get interval number
  1313.         and     bx,3                    ; mask
  1314.         add     bx,offset dgroup:temp0  ; bx = table index
  1315.         mov     al,[bx]                 ; get the value
  1316.         putn    al                      ; send it out
  1317.         nextv                           ; exit
  1318. ;==============================================================
  1319. ; delta test
  1320. ; inputs:
  1321. ;    0:   nz = hold
  1322. ;    1:   delta
  1323. ;    2:   nz = normalize within octave
  1324. ;    3:   input
  1325. ;    4x:  last input
  1326. ; output: strobe when delta is detected
  1327. ;--------------------------------------------------------------
  1328.         public _deltat
  1329. _deltat:
  1330.         hold    var0            ; hold?
  1331.         jnz     deltatz         ; exit if hold
  1332.         testv   var1,-1         ; delta 0?
  1333.         jz      deltatz         ; yes, just exit
  1334.         ;
  1335.         getv    al,var3         ; get pitch input for delta
  1336.         mov     ah,al           ; setup
  1337.         testv   var2,-1         ; want to normalize
  1338.         jz      deltat1         ; no, branch
  1339.         normal                  ; normalize
  1340. deltat1:getv    al,var1         ; get delta
  1341.         xchg    ah,var4[di]     ; swap input with last one
  1342.         sub     ah,var4[di]     ; delta match?
  1343.         cmp     ah,al           ; /
  1344.         jz      deltat2         ; yes, branch
  1345.         neg     al              ; else swap sign
  1346.         cmp     ah,al           ; try again
  1347.         jz      deltat2         ; branch if = delta
  1348.         jmp     deltatz         ; no, exit
  1349.         ;
  1350. deltat2:mov     byte ptr outn[di],1; set flag
  1351. deltatz:nextt                   ; strobe
  1352. ;==============================================================
  1353. ; * 12, + offset
  1354. ; inputs:
  1355. ;    0:   value
  1356. ;    1:   offset
  1357. ;
  1358. ; output: value * 12 + offset
  1359. ;--------------------------------------------------------------
  1360.         public _mul12
  1361. _mul12:
  1362.         getv    al,var0         ; get value
  1363.         mov     dl,12           ; for octave
  1364.         mul     dl              ; * 12
  1365.         getv    ah,var1         ; get offset
  1366.         add     al,ah           ; add it in
  1367.         putn    al              ; send it out
  1368.         nextv                   ; exit
  1369. ;==============================================================
  1370. ; / 12
  1371. ; input:  0: value
  1372. ; output: value / 12
  1373. ;--------------------------------------------------------------
  1374.         public _div12
  1375. _div12:
  1376.         getv    al,var0         ; get value
  1377.         or      al,al           ; zero not allowed
  1378.         jz      div12x          ; split if zero
  1379.         mov     dl,12           ; for octave
  1380.         mov     ah,0            ; make into word
  1381.         div     dl              ; / 12
  1382. div12x: putn    al              ; send it out
  1383.         nextv                   ; exit
  1384. ;==============================================================
  1385. ; mod 12
  1386. ; input:  0: value
  1387. ;         1: offset
  1388. ; output: value mod 12
  1389. ;--------------------------------------------------------------
  1390.         public _mod12
  1391. _mod12:
  1392.         getv    al,var0         ; get value
  1393.         mov     ah,0            ; load for 0
  1394.         or      al,al           ; zero not allowed
  1395.         jz      mod12x          ; split if zero
  1396.         mov     dl,12           ; for octave
  1397.         div     dl              ; / 12
  1398. mod12x: getv    al,var1         ; get offset
  1399.         add     al,ah           ; add in mod value
  1400.         putn    al              ; send it out
  1401.         nextv                   ; exit
  1402. ;==============================================================
  1403. ; fold to octave range
  1404. ; input:  0: value
  1405. ;         1: octave range
  1406. ;         2: offset
  1407. ; output: value mod 12
  1408. ;--------------------------------------------------------------
  1409.         public _fold
  1410. _fold: 
  1411.         getv    al,var1         ; get max octave range
  1412.         and     al,15           ; limit
  1413.         mov     ch,12           ; octave
  1414.         mul     ch              ; /
  1415.         add     ch,al           ; ch = max
  1416.         ;
  1417.         getv    ah,var0         ; get input
  1418.         range   ah,ch           ; put in range
  1419.         getv    al,var2         ; get offset
  1420.         add     al,ah           ; add in mod value
  1421.         putn    al              ; send it out
  1422.         nextv                   ; exit
  1423. ;==============================================================
  1424. ; Union
  1425. ; inputs: 0: trigger, 1: sync, 2x: clocks, 2z: trig flag
  1426. ; output: pulse of one loop cycle duration
  1427. ;--------------------------------------------------------------
  1428.         public _union
  1429. _union: 
  1430.         tick    var0,var2               ; clock trig input
  1431.         jnc     union0                  ; branch if no tick
  1432.         mov     byte ptr var2+1[di],1   ; else set holding byte
  1433. union0: tickb1  var1,var2               ; clock sync input
  1434.         jnc     unionz                  ; branch if no tick
  1435.         mov     al,0                    ; else clear trigger, if any
  1436.         xchg    al,var2+1[di]           ; get trigger, if any
  1437.         putn    al                      ; send it out
  1438. unionz: nextt                           ; strobe
  1439.  
  1440. ;==============================================================
  1441. ; Flip-flop
  1442. ; inputs: 0: set, 1: reset, 2x: set-tick, 2z: reset-tick 
  1443. ; output: pulse of one loop cycle duration
  1444. ;--------------------------------------------------------------
  1445.         public _fflop
  1446. _fflop: 
  1447.         tick    var0,var2       ; clock tick
  1448.         jnc     fflop1          ; branch if no set input
  1449.         mov     byte ptr outn[di],1; set the pulse
  1450. fflop1: tick    var1,var2+1     ; clock tick
  1451.         jnc     fflop2          ; branch if no reset input
  1452.         mov     byte ptr outn[di],0; reset the pulse
  1453. fflop2: nextl                   ; exit with led update
  1454. ;==============================================================
  1455. ; shift left
  1456. ; inputs: 0: value, 1: shift ammount, 2: mask
  1457. ; output: shifted value
  1458. ;--------------------------------------------------------------
  1459.         public _lshift
  1460. _lshift:
  1461.         getv    cl,var1         ; get the exponent
  1462.         and     cl,07H          ; 0-7 allowed
  1463.         getv    al,var0         ; get the value
  1464.         rol     al,cl           ; shift
  1465.         getv    ah,var2         ; get mask
  1466.         and     al,ah           ; mask output
  1467.         putn    al              ; send it out
  1468.         nextv                   ; exit with video update
  1469. ;==============================================================
  1470. ; shift right
  1471. ; inputs: 0: value, 1: shift ammount, 2: mask
  1472. ; output: shifted value
  1473. ;--------------------------------------------------------------
  1474.         public _rshift
  1475. _rshift:
  1476.         getv    cl,var1         ; get the exponent
  1477.         and     cl,07H          ; 0-7 allowed
  1478.         getv    al,var0         ; get the value
  1479.         ror     al,cl           ; shift
  1480.         getv    ah,var2         ; get mask
  1481.         and     al,ah           ; mask output
  1482.         putn    al              ; send it out
  1483.         nextv                   ; exit with video update
  1484. ;==============================================================
  1485. ; Low Pass Filter
  1486. ; inputs: 0: clock, 1: value, 2: slope, 3: offset
  1487. ;        4x: index, 4z: clock tick, 5-12: storage
  1488. ; output: average of last 2, 4, 8, or 16 inputs (slope 0-3)
  1489. ;--------------------------------------------------------------
  1490.         public _filter
  1491. _filter:
  1492.         tick    var0,var4+1     ; clock tick
  1493.         jc      filte1          ; branch if there is a tick
  1494.         nextx                   ; else easy exit
  1495.         ;
  1496. filte1: getv    al,var1         ; get the input value
  1497.         getv    cl,var2         ; get the slope
  1498.         and     cl,03H          ; 0-3 allowed
  1499.         mov     dl,2            ; shift
  1500.         shl     dl,cl           ; dl = 2, 4, 8, or 16
  1501.         mov     dh,dl           ; copy
  1502.         dec     dh              ; dh = 1, 3, 7, or 15
  1503.         mov     bl,var4[di]     ; get index
  1504.         inc     bl              ; bump it
  1505.         and     bl,dh           ; keep in bounds
  1506.         mov     var4[di],bl     ; put it away
  1507.         mov     bh,0            ; bx = index offset
  1508.         mov     var5[bx+di],al  ; put value into save list
  1509.         mov     dh,cl           ; dh = slope value (for later)
  1510.         mov     cl,dl           ; get slope count
  1511.         mov     ch,0            ; cx = 2, 4, 8, or 16
  1512.         mov     bx,var5         ; bx = start of save table
  1513.         mov     bp,0            ; bp will get sum of saved inputs
  1514.         mov     ah,0            ; ax will get each byte saved
  1515. filte2: mov     al,[bx+di]      ; get the saved byte
  1516.         add     bp,ax           ; sum of saved bytes
  1517.         inc     bx              ;   /
  1518.         loop    filte2          ; /
  1519.         mov     ax,bp           ; ax = sum of saved byte values
  1520.         mov     cl,dh           ; dh = slope value
  1521.         inc     cl              ; bump
  1522.         shr     ax,cl           ; ax = average of saved inputs
  1523.         getv    ah,var3         ; get offset
  1524.         add     al,ah           ; add to averaged value
  1525.         putn    al              ; send it out
  1526.         nextv                   ; exit with video update
  1527. ;==============================================================
  1528. ; Power of 2
  1529. ; inputs: 0: value
  1530. ; output: 2 ^^ value
  1531. ;--------------------------------------------------------------
  1532.         public _twopwr
  1533. _twopwr:
  1534.         getv    cl,var0         ; get the exponent
  1535.         and     cl,07H          ; 0-7 allowed
  1536.         mov     al,1            ; shift
  1537.         shl     al,cl           ; /
  1538.         putn    al              ; send it out
  1539.         nextv                   ; exit with video update
  1540. ;==============================================================
  1541. ; Test for flagged bits
  1542. ; inputs: 0: input, 1: value
  1543. ; output: 1 if any masked bits are hi, else 0
  1544. ;--------------------------------------------------------------
  1545.         public _bitsp
  1546. _bitsp: getv    al,var0         ; get input
  1547.         mov     dl,0            ; flag = false
  1548.         test    al,-1           ; any bits hi?
  1549.         jz      bitsp1          ; no, branch
  1550.         getv    dl,var1         ; yes, get the value
  1551. bitsp1: putn    dl              ; send the flag
  1552.         nextl                   ; exit with led update
  1553. ;==============================================================
  1554. ; Test for flagged bits
  1555. ; inputs: 0: input, 1: bitmask, 2: value
  1556. ; output: 1 if any masked bits are hi, else 0
  1557. ;--------------------------------------------------------------
  1558.         public _bitsq
  1559. _bitsq: getv    al,var0         ; get input
  1560.         getv    ah,var1         ; get mask byte
  1561.         mov     dl,0            ; flag = false
  1562.         test    al,ah           ; any bits hi?
  1563.         jz      bitsq1          ; no, branch
  1564.         getv    dl,var2         ; yes, get the value
  1565. bitsq1: putn    dl              ; send the flag
  1566.         nextl                   ; exit with led update
  1567. ;==============================================================
  1568. ; Test for minus ( bit 7 high)
  1569. ; inputs: 0: input
  1570. ; output: 1 if bit 7 hi, else 0
  1571. ;--------------------------------------------------------------
  1572.         public _minusp
  1573. _minusp:
  1574.         getv    al,var0         ; get input
  1575.         mov     dl,0            ; flag = false
  1576.         test    al,80H          ; is negative?
  1577.         jz      minusp1         ; no, branch
  1578.         inc     dl              ; yes, flag = true
  1579. minusp1:putn    dl              ; send the flag
  1580.         nextl                   ; exit with led update
  1581. ;==============================================================
  1582. ; Test for non-zero
  1583. ; inputs: 0: input
  1584. ; output: 0 if input is 0, else 1
  1585. ;--------------------------------------------------------------
  1586.         public _truep
  1587. _truep: 
  1588.         getv    al,var0         ; get input
  1589.         mov     dl,1            ; flag = false
  1590.         or      al,al           ; is zero?
  1591.         jnz     truep1          ; no, branch
  1592.         dec     dl              ; yes, flag = true
  1593. truep1: putn    dl              ; send the flag
  1594.         nextl                   ; exit with led update
  1595. ;==============================================================
  1596. ; Test for zero 
  1597. ; inputs: 0: input
  1598. ; output: 1 if input is 0, else 0
  1599. ;--------------------------------------------------------------
  1600.         public _zerop
  1601. _zerop: 
  1602.         getv    al,var0         ; get input
  1603.         mov     dl,0            ; flag = false
  1604.         or      al,al           ; is zero?
  1605.         jnz     zerop1          ; no, branch
  1606.         inc     dl              ; yes, flag = true
  1607. zerop1: putn    dl              ; send the flag
  1608.         nextl                   ; exit with led update
  1609. ;==============================================================
  1610. ; Test for within range
  1611. ; inputs: 0: input, 1: hi bounds, 2: low bounds
  1612. ; output: 1 if within range, else 0
  1613. ;--------------------------------------------------------------
  1614.         public _rangep
  1615. _rangep:
  1616.         getv    al,var0         ; get input 
  1617.         mov     dl,0            ; flag = false
  1618.         getv    ah,var1         ; get hi range
  1619.         cmp     al,ah           ; input > hi range?
  1620.         ja      range1          ; yes, exit False
  1621.         getv    ah,var2         ; get lo range
  1622.         cmp     al,ah           ; input < lo range?
  1623.         jb      range1          ; yes, exit False
  1624.         inc     dl              ; no, flag = True
  1625. range1: putn    dl              ; send the flag
  1626.         nextl                   ; exit with led update
  1627. ;==============================================================
  1628. ; Test for a > b
  1629. ; inputs: 0: input a, 1: input b
  1630. ; output: 1 if a > b, else 0
  1631. ;--------------------------------------------------------------
  1632.         public _great
  1633. _great: 
  1634.         getv    al,var0         ; get input a
  1635.         getv    ah,var1         ; get inmpu b
  1636.         mov     dl,0            ; flag = false
  1637.         cmp     al,ah           ; is a > b ?
  1638.         jna     great1          ; no, branch
  1639.         inc     dl              ; yes, flag = true
  1640. great1: putn    dl              ; send the flag
  1641.         nextl                   ; exit with led update
  1642. ;==============================================================
  1643. ; Test for a < b
  1644. ; inputs: 0: input a, 1: input b
  1645. ; output: 1 if a < b, else 0
  1646. ;--------------------------------------------------------------
  1647.         public _lessp
  1648. _lessp: 
  1649.         getv    al,var0         ; get input a
  1650.         getv    ah,var1         ; get inmpu b
  1651.         mov     dl,0            ; flag = false
  1652.         cmp     al,ah           ; is a < b ?
  1653.         jnb     lessp1          ; no, branch
  1654.         inc     dl              ; yes, flag = true
  1655. lessp1: putn    dl              ; send the flag
  1656.         nextl                   ; exit with led update
  1657. ;==============================================================
  1658. ; Test for change
  1659. ; inputs: 0: input, 1x: last input value
  1660. ; output: 1 if change else 0
  1661. ;--------------------------------------------------------------
  1662.         public _change
  1663. _change:
  1664.         mov     ah,0            ; clear flag
  1665.         getv    al,var0         ; get input 1
  1666.         cmp     al,var1[di]     ; same as last?
  1667.         jz      chang1          ; yes, send "no change"
  1668.         inc     ah              ; else send change
  1669. chang1: putn    ah              ; send the flag
  1670.         mov     var1[di],al     ; save value for next time
  1671.         nextl                   ; exit with led update
  1672. ;==============================================================
  1673. ; Test for equal
  1674. ; inputs: 0: input, 1: input
  1675. ; output: 1 if equal, else 0
  1676. ;--------------------------------------------------------------
  1677.         public _equal
  1678. _equal: 
  1679.         getv    al,var0         ; get input 1
  1680.         getv    ah,var1         ; get inmpu 2
  1681.         mov     dl,0            ; flag = false
  1682.         cmp     al,ah           ; are they equal
  1683.         jnz     equal1          ; no, branch
  1684.         inc     dl              ; yes, flag = true
  1685. equal1: putn    dl              ; send the flag
  1686.         nextl                   ; exit with led update
  1687. ;==============================================================
  1688. ; Test for not equal
  1689. ; inputs: 0: input, 1: input
  1690. ; output: 1 if not equal, else 0
  1691. ;--------------------------------------------------------------
  1692.         public _nequal
  1693. _nequal: 
  1694.         getv    al,var0         ; get input 1
  1695.         getv    ah,var1         ; get inmpu 2
  1696.         mov     dl,0            ; flag = false
  1697.         cmp     al,ah           ; are they equal
  1698.         jz      nequal1         ; yes, branch
  1699.         inc     dl              ; no, flag = true
  1700. nequal1:putn    dl              ; send the flag
  1701.         nextl                   ; exit with led update
  1702. ;==============================================================
  1703. ; output: delayed input
  1704. ; input: 0: value
  1705. ;        1: delay clocks
  1706. ;        2: offset
  1707. ;        3: index
  1708. ;        4-131: value array
  1709. ;--------------------------------------------------------------
  1710.         public _delay
  1711. _delay: getv    al,var0         ; get input value
  1712.         getv    dl,var1         ; get number of clocks delay
  1713.         getv    dh,var2         ; get offset
  1714.         mov     bl,var3[di]     ; get current count
  1715.         dec     byte ptr var3[di]; bump it
  1716.         mov     bh,0            ; byte --> word
  1717.         mov     var4[bx+di],al  ; set input byte
  1718.         add     bl,dl           ; add delay
  1719.         mov     al,var4[bx+di]  ; get the output byte
  1720.         add     al,dh           ; add offset
  1721.         putn    al              ; send the new output
  1722.         nextv
  1723. ;==============================================================
  1724. ; output: the last changed input
  1725. ; input: 0-7: values
  1726. ;        8x - 9+: saved values 
  1727. ;--------------------------------------------------------------
  1728.         public _lastv
  1729. _lastv: mov     bp,si           ; save si
  1730.         mov     dx,di           ; save di
  1731.         mov     si,di           ; set si to saved values
  1732.         add     si,var8         ; /
  1733.         add     di,var0         ; set di to input values
  1734.         mov     cx,8            ; 8 to do
  1735. lastvl: mov     bx,[di]         ; point to var addr
  1736.         mov     al,[bx]         ; get it
  1737.         cmp     al,[si]         ; same?
  1738.         jnz     lastvx          ; yes, exit
  1739.         add     di,2            ; point to next
  1740.         inc     si              ; /
  1741.         loop    lastvl          ; do all 8
  1742.         mov     di,dx           ; restore registers
  1743.         mov     si,bp           ; /
  1744.         nextx                   ; easy exit if no change
  1745.         ;       
  1746. lastvx: mov     [si],al         ; set the flag
  1747.         mov     di,dx           ; restore registers
  1748.         mov     si,bp           ; /
  1749.         putn    al              ; send the new output
  1750.         nextv
  1751. ;==============================================================
  1752. ; Quantize value input to nearest match input
  1753. ; inputs: 0: value input, 1: extract value, 2-9: match inputs
  1754. ; output: nearest match input
  1755. ;--------------------------------------------------------------
  1756.         public _quant
  1757. _quant:
  1758.         getv    dl,var0         ; dl = value input
  1759.         ;
  1760.         getv    cl,var1         ; get extract root
  1761.         or      cl,cl           ; if zero, ignore
  1762.         jz      quant0          ; /
  1763.         ;       
  1764.         mov     al,dl           ; get the value
  1765.         or      al,al           ; zero not allowed
  1766.         jz      quant0a         ; split if zero
  1767.         mov     ah,0            ; make into word
  1768.         div     cl              ; divide by extract value
  1769.         mov     dl,ah           ; mod result is compare value
  1770.         mul     cl              ; restore to base
  1771. quant0a:mov     cl,al           ; cl is base
  1772.         ;
  1773. quant0: mov     dh,-1           ; dh = initialized test
  1774.         ;
  1775.         getv    al,var2         ; get match input
  1776.         mov     ah,dl           ; get value input
  1777.         sub     ah,al           ; get difference
  1778.         cmp     ah,dh           ; difference < test
  1779.         jnb     quant1a         ; no, branch
  1780.         mov     dh,ah           ; yes, difference is new test
  1781.         putn    al              ; match input --> output
  1782. quant1a:neg     ah              ; test abs difference 
  1783.         cmp     ah,dh           ; abs difference < test
  1784.         jnb     quant2          ; no, branch
  1785.         mov     dh,ah           ; yes, difference is new test
  1786.         putn    al              ; match input --> output
  1787.         ;
  1788. quant2: getv    al,var3         ; get match input
  1789.         mov     ah,dl           ; get value input
  1790.         sub     ah,al           ; get difference
  1791.         cmp     ah,dh           ; difference < test
  1792.         jnb     quant2a         ; no, branch
  1793.         mov     dh,ah           ; yes, difference is new test
  1794.         putn    al              ; match input --> output
  1795. quant2a:neg     ah              ; test abs difference 
  1796.         cmp     ah,dh           ; abs difference < test
  1797.         jnb     quant3          ; no, branch
  1798.         mov     dh,ah           ; yes, difference is new test
  1799.         putn    al              ; match input --> output
  1800.         ;
  1801. quant3: getv    al,var4         ; get match input
  1802.         mov     ah,dl           ; get value input
  1803.         sub     ah,al           ; get difference
  1804.         cmp     ah,dh           ; difference < test
  1805.         jnb     quant3a         ; no, branch
  1806.         mov     dh,ah           ; yes, difference is new test
  1807.         putn    al              ; match input --> output
  1808. quant3a:neg     ah              ; test abs difference 
  1809.         cmp     ah,dh           ; abs difference < test
  1810.         jnb     quant4          ; no, branch
  1811.         mov     dh,ah           ; yes, difference is new test
  1812.         putn    al              ; match input --> output
  1813.         ;
  1814. quant4: getv    al,var5         ; get match input
  1815.         mov     ah,dl           ; get value input
  1816.         sub     ah,al           ; get difference
  1817.         cmp     ah,dh           ; difference < test
  1818.         jnb     quant4a         ; no, branch
  1819.         mov     dh,ah           ; yes, difference is new test
  1820.         putn    al              ; match input --> output
  1821. quant4a:neg     ah              ; test abs difference 
  1822.         cmp     ah,dh           ; abs difference < test
  1823.         jnb     quant5          ; no, branch
  1824.         mov     dh,ah           ; yes, difference is new test
  1825.         putn    al              ; match input --> output
  1826.         ;
  1827. quant5: getv    al,var6         ; get match input
  1828.         mov     ah,dl           ; get value input
  1829.         sub     ah,al           ; get difference
  1830.         cmp     ah,dh           ; difference < test
  1831.         jnb     quant5a         ; no, branch
  1832.         mov     dh,ah           ; yes, difference is new test
  1833.         putn    al              ; match input --> output
  1834. quant5a:neg     ah              ; test abs difference 
  1835.         cmp     ah,dh           ; abs difference < test
  1836.         jnb     quant6          ; no, branch
  1837.         mov     dh,ah           ; yes, difference is new test
  1838.         putn    al              ; match input --> output
  1839.         ;
  1840. quant6: getv    al,var7         ; get match input
  1841.         mov     ah,dl           ; get value input
  1842.         sub     ah,al           ; get difference
  1843.         cmp     ah,dh           ; difference < test
  1844.         jnb     quant6a         ; no, branch
  1845.         mov     dh,ah           ; yes, difference is new test
  1846.         putn    al              ; match input --> output
  1847. quant6a:neg     ah              ; test abs difference 
  1848.         cmp     ah,dh           ; abs difference < test
  1849.         jnb     quant7          ; no, branch
  1850.         mov     dh,ah           ; yes, difference is new test
  1851.         putn    al              ; match input --> output
  1852.         ;
  1853. quant7: getv    al,var8         ; get match input
  1854.         mov     ah,dl           ; get value input
  1855.         sub     ah,al           ; get difference
  1856.         cmp     ah,dh           ; difference < test
  1857.         jnb     quant7a         ; no, branch
  1858.         mov     dh,ah           ; yes, difference is new test
  1859.         putn    al              ; match input --> output
  1860. quant7a:neg     ah              ; test abs difference 
  1861.         cmp     ah,dh           ; abs difference < test
  1862.         jnb     quant8          ; no, branch
  1863.         mov     dh,ah           ; yes, difference is new test
  1864.         putn    al              ; match input --> output
  1865.         ;
  1866. quant8: getv    al,var9         ; get match input
  1867.         mov     ah,dl           ; get value input
  1868.         sub     ah,al           ; get difference
  1869.         cmp     ah,dh           ; difference < test
  1870.         jnb     quant8a         ; no, branch
  1871.         mov     dh,ah           ; yes, difference is new test
  1872.         putn    al              ; match input --> output
  1873. quant8a:neg     ah              ; test abs difference 
  1874.         cmp     ah,dh           ; abs difference < test
  1875.         jnb     quant9          ; no, branch
  1876.         mov     dh,ah           ; yes, difference is new test
  1877.         putn    al              ; match input --> output
  1878.         ;
  1879. quant9: add     outn[di],cl     ; add base
  1880.         nextv                   ; exit with video update
  1881. ;==============================================================
  1882. ; Keep the highest input
  1883. ; inputs: 0: hold/reset 1: input 
  1884. ; output: highest input since reset
  1885. ;--------------------------------------------------------------
  1886.         public _higher
  1887. _higher:
  1888.         hold    var0            ; hold?
  1889.         jz      higher0         ; branch if no hold
  1890.         getv    al,var1         ; else get the input
  1891.         putn    al              ; send it to the output
  1892.         nextv                   ; exit
  1893. higher0:getv    al,var1         ; get the value
  1894.         cmp     al,outn[di]     ; higher than already there?
  1895.         jna     higher1         ; no, branch
  1896.         putn    al              ; yes, send the new value
  1897. higher1:nextv                   ; exit with video update
  1898. ;==============================================================
  1899. ; Keep the lowest input
  1900. ; inputs: 0: hold/reset 1: input 
  1901. ; output: lowest input since reset
  1902. ;--------------------------------------------------------------
  1903.         public _lower
  1904. _lower: 
  1905.         hold    var0            ; hold?
  1906.         jz      lower0          ; branch if no hold
  1907.         getv    al,var1         ; else get the input
  1908.         putn    al              ; send it to the output
  1909.         nextv                   ; exit
  1910. lower0: getv    al,var1         ; get the value
  1911.         cmp     al,outn[di]     ; lower than already there?
  1912.         jnb     lower1          ; no, branch
  1913.         putn    al              ; yes, send the new value
  1914. lower1: nextv                   ; exit with video update
  1915. ;==============================================================
  1916. ; Keep input between limits
  1917. ; inputs: 0: input, 1: upper bounds, 2: lower bounds 
  1918. ; output: input between bounds
  1919. ;--------------------------------------------------------------
  1920.         public _limit
  1921. _limit: 
  1922.         getv    al,var0         ; get the value
  1923.         getv    ah,var1         ; get upper limit
  1924.         cmp     al,ah           ; less than upper limit?
  1925.         jna     limit1          ; yes, branch
  1926.         mov     al,ah           ; else set it to upper limit
  1927. limit1: getv    ah,var2         ; get lower limit
  1928.         cmp     al,ah           ; greater than lower limit?
  1929.         jnb     limit2          ; yes, branch
  1930.         mov     al,ah           ; else set it to lower limit
  1931. limit2: putn    al              ; send the value
  1932.         nextv                   ; exit w video
  1933. ;==============================================================
  1934. ; Sample & Hold
  1935. ; inputs: 0: follow 1: clock, 2: read 3: offset 4x: clock tick
  1936. ; output: scaled sample
  1937. ;--------------------------------------------------------------
  1938.         public _sandh
  1939. _sandh: 
  1940.         testv   var0,-1         ; follow on?
  1941.         jnz     sandh1          ; yes, branch
  1942.         tick    var1,var4       ; clock tick
  1943.         jc      sandh1          ; branch if there is a tick
  1944.         nextx                   ; else exit easy
  1945. sandh1: getv    al,var2         ; get sample
  1946.         getv    ah,var3         ; get offset
  1947.         add     al,ah           ; put it together
  1948.         putn    al              ; send it
  1949.         nextv                   ; exit with video update
  1950. ;==============================================================
  1951. ; Midi sync control interface for Stop, Start, Continue, etc.
  1952. ; output: bit flags
  1953. ;       bit 0: stop 
  1954. ;       bit 1: start
  1955. ;       bit 2: continue
  1956. ; input:
  1957. ;       0: NZ = send Stop to Midi
  1958. ;       1: NZ = send Start to MIDI
  1959. ;       2: NZ = send Continue to MIDI
  1960. ;       3: NZ = send Reset to MIDI
  1961. ;       4: NZ = send Tune req to midi
  1962. ;       5: NZ bits = clear output bits
  1963. ;       6x: last stop input
  1964. ;       6+: last start input
  1965. ;       7x: last continue input
  1966. ;       7+: initialized flag
  1967. ;       8x: tick for stop, start, continue
  1968. ;       8+: tick for reset, tune, clear
  1969. ;--------------------------------------------------------------
  1970.         public _stopo
  1971. _stopo: cmp     byte ptr var7+1[di],0abh; initialized?
  1972.         jz      stopo0                  ; yes, branch
  1973.         mov     word ptr var7[di],0ab00h; no, initialize
  1974.         mov     word ptr var8[di],0     ;    /
  1975.         mov     word ptr var6[di],0     ;  /
  1976.         jmp     stopox                  ; exit from init
  1977.         ;
  1978. stopo0: mov     al,cs:mstop             ; change in ext stop?
  1979.         cmp     al,var6[di]             ; /
  1980.         jz      stopo0a                 ; no, branch
  1981.         or      byte ptr outn[di],1     ; yes, set the flag
  1982.         mov     var6[di],al             ; /
  1983.         ;
  1984. stopo0a:mov     al,cs:mstart            ; change in ext start?
  1985.         cmp     al,var6+1[di]           ; /
  1986.         jz      stopo0b                 ; no, branch
  1987.         or      byte ptr outn[di],2     ; yes, set the flag
  1988.         mov     var6+1[di],al           ; /
  1989.         ;
  1990. stopo0b:mov     al,cs:mcont             ; change in ext cont?
  1991.         cmp     al,var7[di]             ; /
  1992.         jz      stopo1                  ; no, branch
  1993.         or      byte ptr outn[di],4     ; yes, set the flag
  1994.         mov     var7[di],al             ; /
  1995. ;--------------------------------------------------------------
  1996. stopo1: tick    var0,var8               ; stop cmd input?
  1997.         jnc     stopo1a                 ; no, branch
  1998.         mov     al,0fch                 ; send Stop cmd to midi
  1999.         call    allmidi
  2000.         ;
  2001. stopo1a:tickb1  var1,var8               ; start cmd input?
  2002.         jnc     stopo1b                 ; no, branch
  2003.         mov     al,0fah                 ; send Start cmd to midi
  2004.         call    allmidi
  2005.         ;
  2006. stopo1b:tickb2  var2,var8               ; Cont cmd input?
  2007.         jnc     stopo2                  ; no, branch
  2008.         mov     al,0fbh                 ; send Cont cmd to midi
  2009.         call    allmidi
  2010. ;--------------------------------------------------------------
  2011. stopo2: tick    var3,var8+1             ; Reset cmd input?
  2012.         jnc     stopo2a                 ; no, branch
  2013.         mov     al,0ffh                 ; send Reset cmd to midi
  2014.         call    allmidi
  2015.         ;
  2016. stopo2a:tickb1  var4,var8+1             ; Tune Request input?
  2017.         jnc     stopo3                  ; no, branch
  2018.         mov     al,0f6h                 ; send Tune Request to midi
  2019.         call    allmidi
  2020. ;--------------------------------------------------------------
  2021. stopo3: tickb2  var5,var8+1             ; clear output?
  2022.         jnc     stopox                  ; no, branch
  2023.         mov     byte ptr outn[di],0     ; clear the output
  2024. stopox: nextl                           ; show it
  2025. ;==============================================================
  2026. ; Sum of 5 inputs
  2027. ; inputs: 0-4:  inputs, 5: scale 6: offset
  2028. ; output: scaled and offset input
  2029. ;--------------------------------------------------------------
  2030.         public _sumit
  2031. _sumit: 
  2032.         xor     cx,cx           ; clr cx
  2033.         mov     ah,ch           ; clr ah
  2034.         getv    al,var0         ; get input 
  2035.         add     cx,ax           ; add to total
  2036.         getv    al,var1         ; get input 
  2037.         add     cx,ax           ; add to total
  2038.         getv    al,var2         ; get input 
  2039.         add     cx,ax           ; add to total
  2040.         getv    al,var3         ; get input 
  2041.         add     cx,ax           ; add to total
  2042.         getv    al,var4         ; get input 
  2043.         add     cx,ax           ; add to total
  2044.         ;
  2045.         getv    al,var5         ; get scale value
  2046.         xchg    al,ah           ; al = 0, ah = scale
  2047.         mul     cx              ; dx = scaled value
  2048.         getv    al,var6         ; get offset
  2049.         add     al,dl           ; put it together
  2050.         putn    al              ; send it
  2051.         nextv                   ; exit with video update
  2052. ;==============================================================
  2053. ; Mix 3 Scaled inputs
  2054. ; inputs: 0,2,4: input, 1,3,5: scale 6: offset
  2055. ; output: scaled and offset input
  2056. ;--------------------------------------------------------------
  2057.         public _mixit
  2058. _mixit: 
  2059.         getv    al,var0         ; get input 
  2060.         getv    cl,var1         ; get scale value
  2061.         mul     cl              ; ah = scaled value
  2062.         mov     ch,ah           ; for sum
  2063.         getv    al,var2         ; get input 
  2064.         getv    cl,var3         ; get scale value
  2065.         mul     cl              ; ah = scaled value
  2066.         add     ch,ah           ; sum
  2067.         getv    al,var4         ; get input 
  2068.         getv    cl,var5         ; get scale value
  2069.         mul     cl              ; ah = scaled value
  2070.         add     ch,ah           ; sum
  2071.         ;
  2072.         getv    al,var6         ; get offset
  2073.         add     al,ch           ; put it together
  2074.         putn    al              ; send it
  2075.         nextv                   ; exit with video update
  2076. ;==============================================================
  2077. ; Scale and offset input
  2078. ; inputs: 0: input, 1: scale 2: offset
  2079. ; output: scaled and offset input
  2080. ;--------------------------------------------------------------
  2081.         public _scale
  2082. _scale: 
  2083.         getv    al,var0         ; get input 
  2084.         getv    cl,var1         ; get scale value
  2085.         mul     cl              ; ah = scaled value
  2086.         getv    al,var2         ; get offset
  2087.         add     al,ah           ; put it together
  2088.         putn    al              ; send it
  2089.         nextv                   ; exit with video update
  2090. ;==============================================================
  2091. ; Max of two inputs
  2092. ; inputs: 0: input, 1: input
  2093. ; output: max
  2094. ;--------------------------------------------------------------
  2095.         public _maxf
  2096. _maxf:  
  2097.         getv    al,var0         ; get input 
  2098.         getv    ah,var1         ; get input
  2099.         cmp     ah,al           ; select larger
  2100.         jb      maxf1           ;   /
  2101.         mov     al,ah           ; /
  2102. maxf1:  putn    al              ; send it
  2103.         nextv                   ; exit with video update
  2104. ;==============================================================
  2105. ; Min of two inputs
  2106. ; inputs: 0: input, 1: input
  2107. ; output: min
  2108. ;--------------------------------------------------------------
  2109.         public _minf
  2110. _minf:  
  2111.         getv    al,var0         ; get input 
  2112.         getv    ah,var1         ; get input
  2113.         cmp     al,ah           ; select larger
  2114.         jb      minf1           ;   /
  2115.         mov     al,ah           ; /
  2116. minf1:  putn    al              ; send it
  2117.         nextv                   ; exit with video update
  2118. ;==============================================================
  2119. ; Rate of change (delta)
  2120. ; inputs: 0: input, 1x: last input
  2121. ; output: delta from last changed input
  2122. ;
  2123.         public _delta
  2124. _delta: 
  2125.         getv    al,var0         ; get input 
  2126.         cmp     al,byte ptr var1[di]; any change
  2127.         jnz     delta1          ; yes, branch
  2128.         nextx                   ; no, easy exit
  2129.         ;
  2130. delta1: mov     ah,byte ptr var1[di]; get old value
  2131.         sub     ah,al           ; calc delta
  2132.         jnb     delta2          ; keep it positive
  2133.         neg     ah              ; /
  2134. delta2: mov     byte ptr var1[di],al; save new input
  2135.         putn    ah              ; send delta
  2136.         nextv                   ; exit with video update
  2137. ;==============================================================
  2138. ; Add three inputs
  2139. ; inputs: 0: input, 1: input, 2: input
  2140. ; output: sum of the three inputs
  2141. ;
  2142.         public _plus 
  2143. _plus:  
  2144.         getv    al,var0         ; get input 
  2145.         getv    ah,var1         ; get input
  2146.         add     al,ah           ; put it together
  2147.         getv    ah,var2         ; get input
  2148.         add     al,ah           ; put it together
  2149.         putn    al              ; send it
  2150.         nextv                   ; exit with video update
  2151. ;==============================================================
  2152. ; Add two inputs, subtract the third
  2153. ; inputs: 0: input, 1: input, 2: input
  2154. ; output: sum of first two inputs minus the third
  2155. ;
  2156.         public _plusm,_plusn
  2157. _plusn: nop
  2158. _plusm: getv    al,var0         ; get input 
  2159.         getv    ah,var1         ; get input
  2160.         add     al,ah           ; put it together
  2161.         getv    ah,var2         ; get input
  2162.         sub     al,ah           ; put it together
  2163.         putn    al              ; send it
  2164.         nextv                   ; exit with video update
  2165. ;==============================================================
  2166. ; multiply input by 2nd input, divide by 3rd if nz
  2167. ; inputs: 0: input, 1: mult, 2: divid
  2168. ; output: product of the 3 inputs
  2169. ;
  2170.         public _times
  2171. _times: 
  2172.         getv    al,var0         ; get input 
  2173.         getv    cl,var1         ; get input
  2174.         mul     cl              ; put it together
  2175.         getv    cl,var2         ; get input
  2176.         or      cl,cl           ; zero?
  2177.         jz      times1          ; yes, do not divide
  2178.         mov     dx,0            ; give it headroom
  2179.         mov     ch,0
  2180.         div     cx              ; divide dx:ax / cx
  2181. times1: putn    al              ; send it
  2182.         nextv                   ; exit with video update
  2183. ;==============================================================
  2184. ; divide first input by 2nd, return remainder
  2185. ; inputs: 0: input, 1: divide
  2186. ; output: product of the 3 inputs
  2187. ;
  2188.         public _modulo
  2189. _modulo:
  2190.         getv    al,var0         ; get input 
  2191.         mov     ah,0            ; setup for 0
  2192.         getv    cl,var1         ; get input
  2193.         or      cl,cl           ; zero?
  2194.         jz      modulx          ; yes, do not divide
  2195.         div     cl              ; divide ax / cl
  2196. modulx: putn    ah              ; send remainder
  2197.         nextv                   ; exit with video update
  2198. ;==============================================================
  2199. ; AND gate
  2200. ; inputs: 0,1,2
  2201. ; output: result of input0 AND input1 XOR input2
  2202. ;--------------------------------------------------------------
  2203.         public _andl
  2204. _andl:  
  2205.         getv    al,var0         ; al = 1st variable
  2206.         getv    ah,var1         ; ah = 2nd variable
  2207.         and     al,ah           ; AND them
  2208.         getv    ah,var2         ; ah = 3rd variable
  2209.         xor     al,ah           ; xor them
  2210.         putn    al              ; send to output
  2211.         nextv         
  2212. ;==============================================================
  2213. ; AND gate
  2214. ; inputs: 0: &input 1: &input 2: +input  
  2215. ; output: result of input 0 AND input 1 PLUS input 2
  2216. ;--------------------------------------------------------------
  2217.         public _mask
  2218. _mask:  
  2219.         getv    al,var0         ; al = 1st variable
  2220.         getv    ah,var1         ; ah = 2nd variable
  2221.         and     al,ah           ; var0 AND var1
  2222.         getv    ah,var2         ; ah = 3rd variable
  2223.         add     al,ah           ; add it to the AND stuff
  2224.         putn    al              ; send to output
  2225.         nextv
  2226. ;==============================================================
  2227. ; AND gate
  2228. ; inputs: 0: &input 1: &input, 2: shift
  2229. ; output: shifted result of input 0 AND input 1
  2230. ;--------------------------------------------------------------
  2231.         public _maskl
  2232. _maskl: getv    al,var0         ; al = 1st variable
  2233.         getv    ah,var1         ; ah = 2nd variable
  2234.         and     al,ah           ; var0 AND var1
  2235.         getv    cl,var2         ; get shift
  2236.         rol     al,cl           ; shift
  2237.         putn    al              ; send to output
  2238.         nextv
  2239. ;--------------------------------------------------------------
  2240.         public _maskr
  2241. _maskr: getv    al,var0         ; al = 1st variable
  2242.         getv    ah,var1         ; ah = 2nd variable
  2243.         and     al,ah           ; var0 AND var1
  2244.         getv    cl,var2         ; get shift
  2245.         ror     al,cl           ; shift
  2246.         putn    al              ; send to output
  2247.         nextv
  2248. ;==============================================================
  2249. ; NOT logic
  2250. ; inputs: 0: value
  2251. ;         1: mask 
  2252. ; output: NOT input0 AND input 1 
  2253. ;--------------------------------------------------------------
  2254.         public _notl
  2255. _notl:  
  2256.         getv    al,var0         ; al = 1st variable
  2257.         not     al              ; complement
  2258.         getv    ah,var1         ; get mask
  2259.         and     al,ah           ; AND them
  2260.         putn    al              ; send to output
  2261.         nextv         
  2262. ;==============================================================
  2263. ; Slope detector
  2264. ; inputs: 0
  2265. ; output: nz if positive slope, z if neg, no change if 0
  2266. ;
  2267. ;--------------------------------------------------------------
  2268.         public _slope
  2269. _slope: 
  2270.         getv    ah,var0         ; al = 1st variable
  2271.         cmp     ah,var1[di]     ; same as last?
  2272.         jz      slopex          ; yes, just exit
  2273.         mov     var1[di],ah     ; no, save it
  2274.         mov     al,1            ; setup for pos
  2275.         ja      slope1          ; branch if pos
  2276.         mov     al,0            ; else flag neg
  2277. slope1: putn    al              ; send to output
  2278. slopex: nextl         
  2279.  
  2280. ;==============================================================
  2281. ; negate
  2282. ; inputs: 0: input
  2283. ; output: NEG of input
  2284. ;--------------------------------------------------------------
  2285.         public _negate
  2286. _negate:
  2287.         getv    al,var0         ; al = 1st variable
  2288.         neg     al              ; negate it
  2289.         putn    al              ; send to output
  2290.         nextv
  2291. ;==============================================================
  2292. ; OR gate
  2293. ; inputs: 0,1,2
  2294. ; output: result of input0 OR input1 OR input2
  2295. ;--------------------------------------------------------------
  2296.         public _orl
  2297. _orl:   
  2298.         getv    al,var0         ; var0 OR var1...
  2299.         getv    ah,var1         ;   /
  2300.         or      al,ah           ; /
  2301.         getv    ah,var2         ; ...OR var2
  2302.         or      al,ah           ; /
  2303.         putn    al              ; send out
  2304.         nextv
  2305. ;==============================================================
  2306. ; shunt input to output
  2307. ; inputs: 0: value
  2308. ; output: input 0 unchanged
  2309. ;--------------------------------------------------------------
  2310.         public _value
  2311. _value: 
  2312.         getv    al,var0         ; get variable 1
  2313.         putn    al              ; send it
  2314.         nextv
  2315. ;==============================================================
  2316. ; display input value in ascii
  2317. ; inputs: 0-2: values to be displayed
  2318. ; outputs: none
  2319. ;--------------------------------------------------------------
  2320.      public _ascii
  2321. _ascii: 
  2322.         getv    al,var0         ; get the input value
  2323.         getv    ah,var1         ;  /
  2324.         getv    cl,var2         ; /
  2325.         mov     es,4[di]        ; get seg addr
  2326.         mov     bx,6[di]        ; get module screen address
  2327.         mov     es:318[bx],al   ; put to the screen
  2328.         mov     es:320[bx],ah   ;  /
  2329.         mov     es:322[bx],cl   ; /
  2330.         nextx                   ; exit
  2331. ;==============================================================
  2332. ; display input value in ascii from seq "s"
  2333. ; inputs: 0: lo addr of value, 1: hi addr,  2: offset to addr
  2334. ; outputs: none
  2335. ;--------------------------------------------------------------
  2336.      public _ascis
  2337. _ascis: 
  2338.         mov     ax,seg bufsp    ; setup seg register
  2339.         mov     es,ax           ; es = seg addr
  2340.         getv    dl,var0         ; get address
  2341.         getv    dh,var1         ; get hi address
  2342.         and     dh,15           ; 16 max
  2343.         getv    bl,var2         ; get offset
  2344.         add     dl,bl           ; put them together
  2345.         mov     bx,dx           ; /
  2346.         mov     al,es:[bx]      ; get the byte
  2347.         inc     bl              ; bump addr low
  2348.         mov     ah,es:[bx]      ; and the next
  2349.         inc     bl              ; bump addr low
  2350.         mov     cl,es:[bx]      ; and the next
  2351.         ;
  2352.         mov     es,4[di]        ; get seg addr
  2353.         mov     bx,6[di]        ; get module screen address
  2354.         mov     es:318[bx],al   ; put to the screen
  2355.         mov     es:320[bx],ah   ;  /
  2356.         mov     es:322[bx],cl   ; /
  2357.         nextx                   ; exit
  2358. ;==============================================================
  2359. ; display input value in ascii from seq "S"
  2360. ; inputs: 0: lo addr of value, 1: hi addr, 2: offset
  2361. ; outputs: none
  2362. ;--------------------------------------------------------------
  2363.      public _asciz
  2364. _asciz: 
  2365.         mov     ax,seg buffs    ; setup seg register
  2366.         mov     es,ax           ; es = seg addr
  2367.         getv    dl,var0         ; get address lo
  2368.         getv    dh,var1         ; get address hi
  2369.         getv    bl,var2         ; get offset
  2370.         mov     bh,0            ; /
  2371.         add     bx,dx           ; set up as index
  2372.         mov     al,es:[bx]      ; get the byte
  2373.         mov     ah,es:1[bx]     ; and the next
  2374.         mov     cl,es:2[bx]     ; and the next
  2375.         ;
  2376.         mov     es,4[di]        ; get seg addr
  2377.         mov     bx,6[di]        ; get module screen address
  2378.         mov     es:318[bx],al   ; put to the screen
  2379.         mov     es:320[bx],ah   ;  /
  2380.         mov     es:322[bx],cl   ; /
  2381.         nextx                   ; exit
  2382. ;==============================================================
  2383. ; display input value in decimal
  2384. ; inputs:  x: (display location)
  2385. ;          0: value to be displayed
  2386. ; outputs: copy of value
  2387. ;--------------------------------------------------------------
  2388.      public _decin
  2389. _decin: 
  2390.         getv    al,var0         ; get the input value
  2391.         putn    al              ; send to output
  2392.         mov     colr,yellow     ; set color to yellow
  2393.         mov     es,4[di]        ; get seg addr
  2394.         mov     bx,6[di]        ; get module screen address
  2395.         add     bx,478          ; point to readout
  2396.         call    todec           ; do it
  2397.         mov     colr,green      ; fix it back to green
  2398.         nextv                   ; exit with update
  2399. ;==============================================================
  2400. ; display input value in decimal
  2401. ; inputs:  0: decimal display 
  2402. ; outputs: none (display location)
  2403. ;--------------------------------------------------------------
  2404.      public _decim
  2405. _decim: 
  2406.         mov     colr,yellow     ; set color to yellow
  2407.         getv    al,var0         ; get the input value
  2408.         mov     es,4[di]        ; get seg addr
  2409.         mov     bx,6[di]        ; get module screen address
  2410.         add     bx,318          ; point to readout
  2411.         call    todec           ; do it
  2412.         mov     colr,green      ; fix it back to green
  2413.         nextx                   ; exit, no update
  2414. ;==============================================================
  2415. ; slew over time
  2416. ; formula:
  2417. ;       initialize:
  2418. ;               input * rate --> sum; input --> output
  2419. ;       thereafter until sum/rate = target:
  2420. ;               sum - input + target --> sum
  2421. ;               sum/rate             --> output
  2422. ;
  2423. ; output: slewed input, with led hi while slewing
  2424. ; inputs:
  2425. ; 0:  input
  2426. ; 1:  target
  2427. ; 2:  rate
  2428. ; 3x: sum
  2429. ; 4x: saved input
  2430. ; 4+: saved target
  2431. ; 5x: saved rate
  2432. ; 5+: flag nz = busy
  2433. ;--------------------------------------------------------------
  2434.         public _slew
  2435. _slew:  test    byte ptr var5+1[di],1   ; busy?
  2436.         jnz     slewa                   ; yes, branch
  2437.         getv    dl,var1                 ; no, see if target=output
  2438.         cmp     dl,outn[di]             ; /
  2439.         jnz     slewb                   ; yes, go slew
  2440.         getv    al,var0                 ; no, see if input has changed
  2441.         cmp     al,var4[di]             ; /
  2442.         jz      slewx                   ; yes, exit no change                
  2443.         ;
  2444. slewb:  mov     var4+1[di],dl           ; save target
  2445.         getv    al,var0                 ; get input
  2446.         mov     var4[di],al             ; save input
  2447.         getv    cl,var2                 ; get rate
  2448.         mov     var5[di],cl             ; save rate
  2449.         ;
  2450.         putn    dl                      ; target --> output
  2451.         or      cl,cl                   ; rate = 0?
  2452.         jz      slewx                   ; yes, just exit
  2453.         putn    al                      ; no, start with input --> output
  2454.         mov     byte ptr var5+1[di],1   ; flag busy
  2455.         mul     cl                      ; ax = input * rate
  2456.         mov     var3[di],ax             ; set new sum
  2457.         jmp     short slewx             ; exit
  2458.         ;
  2459. slewa:  test    byte ptr cs:loops,1     ; every other clock
  2460.         jnz     slewx                   ; branch if not even
  2461.         mov     ax,var3[di]             ; ax = sum
  2462.         mov     dl,var4[di]             ; dx = input
  2463.         mov     dh,0                    ; /
  2464.         sub     ax,dx                   ; ax = sum - input
  2465.         mov     dl,var4+1[di]           ; dx = target
  2466.         add     ax,dx                   ; ax = sum - input + target
  2467.         mov     var3[di],ax             ; save new sum
  2468.         mov     cl,var5[di]             ; cl = rate
  2469.         div     cl                      ; al = new sum / rate
  2470.         putn    al                      ; send to output
  2471.         cmp     al,dl                   ; output = target
  2472.         jnz     slewx                   ; no, exit
  2473.         mov     byte ptr var5+1[di],0   ; yes, flag not busy
  2474.         ;
  2475. slewx:  nextv                           ; exit
  2476.         
  2477. ;==============================================================
  2478. ; slew over time
  2479. ; formula:
  2480. ;       initialize:
  2481. ;               input * 256 --> sum; input --> output
  2482. ;       thereafter until sum/256 = target:
  2483. ;               sum - input + target --> sum
  2484. ;               sum/256              --> output
  2485. ;
  2486. ; output: slewed input, with led hi while slewing
  2487. ; inputs:
  2488. ; 0:  input
  2489. ; 1:  target
  2490. ; 2:  rate
  2491. ; 3x: sum
  2492. ; 4x: saved input
  2493. ; 4+: saved target
  2494. ; 5x: rate countdown
  2495. ; 5+: flag nz = busy
  2496. ;--------------------------------------------------------------
  2497.         public _xslew
  2498. _xslew: test    byte ptr var5+1[di],1   ; busy?
  2499.         jnz     xslewa                  ; yes, branch
  2500.         getv    dl,var1                 ; no, see if target=output
  2501.         cmp     dl,outn[di]             ; /
  2502.         jnz     xslewb                  ; yes, go slew
  2503.         getv    al,var0                 ; no, see if input has changed
  2504.         cmp     al,var4[di]             ; /
  2505.         jz      xslewx                  ; yes, exit no change                
  2506.         ;
  2507. xslewb: mov     var4+1[di],dl           ; save target
  2508.         getv    cl,var2                 ; get rate
  2509.         mov     var5[di],cl             ; save rate
  2510.         getv    al,var0                 ; get input
  2511.         mov     var4[di],al             ; save input
  2512.         ;
  2513.         putn    dl                      ; target --> output
  2514.         or      cl,cl                   ; rate = 0?
  2515.         jz      xslewx                  ; yes, just exit
  2516.         putn    al                      ; no, start with input --> output
  2517.         mov     byte ptr var5+1[di],1   ; flag busy
  2518.         mov     ah,al                   ; ax = input * 256
  2519.         mov     al,0                    ; /
  2520.         mov     var3[di],ax             ; set new sum
  2521.         jmp     short xslewx            ; exit
  2522.         ;
  2523. xslewa: dec     byte ptr var5[di]       ; countdown 
  2524.         jnz     xslewx                  ; /
  2525.         getv    al,var2                 ; get rate
  2526.         or      al,al                   ; somebody make it 0?
  2527.         jnz     xslewc                  ; no, go on
  2528.         getv    al,var1                 ; yes, set output to target
  2529.         mov     dl,al                   ; ...short cut
  2530.         jmp     short xslewz            ; exit finished
  2531.         ;
  2532. xslewc: mov     var5[di],al             ; save rate count
  2533.         mov     ax,var3[di]             ; ax = sum
  2534.         mov     dl,var4[di]             ; dx = input
  2535.         mov     dh,0                    ; /
  2536.         sub     ax,dx                   ; ax = sum - input
  2537.         mov     dl,var4+1[di]           ; dx = target
  2538.         add     ax,dx                   ; ax = sum - input + target
  2539.         mov     var3[di],ax             ; save new sum
  2540.         mov     al,ah                   ; al = new sum / 256
  2541. xslewz: putn    al                      ; send to output
  2542.         cmp     al,dl                   ; output = target
  2543.         jnz     xslewx                  ; no, exit
  2544.         mov     byte ptr var5+1[di],0   ; yes, flag not busy
  2545.         ;
  2546. xslewx: nextv                           ; exit
  2547.         
  2548. ;==============================================================
  2549. ; display input value in scale of CM
  2550. ; inputs: 0: value to be displayed
  2551. ; outputs: none
  2552. ;--------------------------------------------------------------
  2553.      public _noter
  2554. _noter: 
  2555.         mov     colr,yellow     ; set value color
  2556.         getv    al,var0         ; get the input value
  2557.         mov     es,4[di]        ; get seg addr
  2558.         mov     bx,6[di]        ; get module screen address
  2559.         add     bx,318          ; point to readout
  2560.         call    tonote          ; do it
  2561.         mov     colr,green      ; restore to green again
  2562.         nextx
  2563. ;==============================================================
  2564. _TEXT   ENDS
  2565.         END
  2566.  
  2567.