home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
sound
/
midi
/
mbb.asm
< prev
next >
Wrap
Assembly Source File
|
1988-03-20
|
113KB
|
2,569 lines
TITLE Modules for Modular Sequencer
NAME MBB
.SALL
;==============================================================
; MusicBox Modular Sequencer, Version 2
; modules code
;--------------------------------------------------------------
; author: John Dunn
; date: 03/07/86
; update: 03/20/88
;--------------------------------------------------------------
; COPYRIGHT (C) 1986 John Dunn, All Rights Reserved
; Entered into the Public Domain, March 20, 1988
;
; Use and copying of this software and preparation of derivative works
; based upon this software are permitted. Any distribution of this
; software or derivative works must comply with all applicable United
; States export control laws.
;
; This software is made available AS IS, and the author makes no warranty
; about the software, its performance, or its conformity to any specification.
;
; Any person obtaining a copy of this software is requested to send their
; name and address address to:
;
; John Dunn, Senior Research Fellow
; Time Arts Inc.
; 3436 Mendocino Ave.
; Santa Rosa, CA 95401
;
;==============================================================
include order.asm
;--------------------------------------------------------------
include equates.asm
;--------------------------------------------------------------
;_DATA SEGMENT
; ASSUME DS:DGROUP, CS:_TEXT
;--------------------------------------------------------------
extrn _nextv:near,_nextx:near,_nextl:near,_nextt:near
extrn _doit:near
;--------------------------------------------------------------
extrn ticka:byte,tickis:byte
extrn _header:byte
extrn varsav:word,cmdflg:byte,special:word,cmdcnt:byte
extrn locsav:word,cmdloc:word,vpage:word,curadr:word
extrn valflg:byte
extrn @zero:near,magflg:byte,usrflg:byte,holdv:word
extrn colr:byte
;--------------------------------------------------------------
extrn midisf:byte ; 0=no sync, 1=send sync
extrn midixsf:byte ; 0=not xtrn sync, NZ=is
extrn midiok:byte ; 0=off/not init, 2=off&init, 3=on
extrn mprstf:byte ; master program reset flag
extrn mpmodf:byte ; master program mode flag
extrn mpadrf:byte ; nz if change in prog address
extrn mpadr:byte ; master program address
extrn mmcount:word ; master measure count
extrn mmtick:word ; ticks left in current measure
extrn mmreset:byte ; master measure reset flag
extrn mmstart:byte ; master measurd start flag
;--------------------------------------------------------------
extrn rseed:word ; random number seed
extrn rhold:byte ; rng hold flag
extrn notetbl:byte ; note -> clocks xlate
extrn notes:word
extrn interv:byte ; intervals for modulation
;
extrn xcax:word ; register storage, used by xcall
extrn xcbx:word
extrn xccx:word
extrn xcdx:word
;
extrn temp0:byte ; temp storage, use within module
extrn temp1:byte
extrn temp2:byte
extrn temp3:byte
;--------------------------------------------------------------
; the following are saved/loaded
;--------------------------------------------------------------
extrn mvlsav:abs ; start of mod values to save
extrn mute:word ; channel mute flags
extrn mutef:byte ; 1=mute, 0=solo flag
;
extrn mbeat:byte ; master beats/measure
extrn mnote:byte ; master note value
extrn mtempo:byte ; master tempo
extrn mclocks:word ; master clocks/measure
;
extrn ctrlmap:byte ; midi controller map
extrn pcva:byte ; values sent to controller
extrn pcvb:byte ; values sent to controller
extrn pcvc:byte ; values sent to controller
extrn pcvd:byte ; values sent to controller
extrn pcve:byte ; values sent to controller
extrn pcvf:byte ; values sent to controller
;
extrn mvlnum:abs ; number of mod values to save
;--------------------------------------------------------------
;_DATA ENDS
;==============================================================
; Module Execution Code
; All inputs are word pointers to output word values.
; All outputs are binary words, with only the ls byte output.
;==============================================================
; EQUATES for modules
;
vseg equ 4 ; offset to video seg addr
vaddr equ 6 ; offset to video page addr
outn equ 8 ; offset to output
numvar equ 10 ; number of input variables
var0 equ 12 ; offset to variable 0
var1 equ var0+2 ; offset to variable 1
var2 equ var1+2 ; etc.
var3 equ var2+2 ; etc.
var4 equ var3+2 ; etc.
var5 equ var4+2 ; etc.
var6 equ var5+2 ; etc.
var7 equ var6+2 ; etc.
var8 equ var7+2 ; etc.
var9 equ var8+2 ; etc.
var10 equ var9+2 ; etc.
var11 equ var10+2 ; etc.
var12 equ var11+2 ; etc.
var13 equ var12+2 ; etc.
var14 equ var13+2 ; etc.
var15 equ var14+2 ; etc.
var16 equ var15+2 ; etc.
var17 equ var16+2 ; etc.
var18 equ var17+2 ; etc.
var19 equ var18+2 ; etc.
var20 equ var19+2 ; etc.
var21 equ var20+2 ; etc.
var22 equ var21+2 ; etc.
slewc equ var22 ; programmer slew buffer
slewd equ slewc+6 ; etc.
slewe equ slewd+6 ; etc.
slewf equ slewe+6 ; etc.
pubuf equ slewf+6 ; programmer undo buffer
psbuf equ pubuf+13 ; programmer save buffer
;
onflg equ 1 ; bit mask for note-on
offlg equ 2 ; bit mask for note-off
sentf equ 4 ; bit mask for note-sent
;--------------------------------------------------------------
_TEXT SEGMENT
ASSUME CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: NOTHING
;--------------------------------------------------------------
extrn ticks:word,loops:word,seconds:word,secondf:byte
extrn todec:near,tonote:near,startm:near
extrn _cancel:near,workx:near,split:near
extrn turnon:near,turnoff:near
extrn mstart:byte,mstop:byte,mcont:byte
extrn allmidi:near
;==============================================================
;==============================================================
; THE MODULES
;==============================================================
include macros.asm
;==============================================================
; generate melody & chord changes from input base & intervals
;--------------------------------------------------------------
; inputs:
; 0: chord array location (16 possible arrays of 4 values)
; 1: base input value
; 2: 1st interval above base
; 3: 2nd interval above base
; 4: 3rd interval above base
; 5: nz = normalize to octave
; 6: offset to base
; 7: nz = sort
; 8: foldover range
; 9: doit strobe
; 10x: clock ticks
; output: root # (always 0 unless sort)
;--------------------------------------------------------------
public _cgen
_cgen:
tick var9,var10 ; clock strobe
jc cgen0 ; yes, go do it
jmp cgenz ; exit if no tick
;
cgen0: getv al,var0 ; get array location
and ax,15 ; mask
add ax,ax ; *4
add ax,ax ; /
add ax,offset dgroup:interv ; add in int table addr
mov bp,ax ; save in bp
;
getv al,var1 ; get input
testv var5,-1 ; want to normalize?
jz cgen1 ; no, branch
normal ; yes, normalize to octave
mov al,ah ; put back in al
;
cgen1: getv ah,var6 ; get offset
add al,ah ; add to root
;
getv ah,var2 ; add intervals to root
add ah,al ; /
getv dl,var3 ; /
add dl,al ; /
getv dh,var4 ; /
add dh,al ; /
;
mov byte ptr outn[di],0 ; root is 0
testv var7,-1 ; want to sort
jnz cgen4 ; yes, do it
jmp cgenx ; no, exit
;
cgen4: push ax ; save root
getv al,var8 ; get max octave range
and al,15 ; limit
mov ch,12 ; /
mul ch ; /
add ch,al ; ch = range
pop ax ; restore root
;
range al,ch ; put in range
range ah,ch ; put in range
range dl,ch ; put in range
range dh,ch ; put in range
;
mov cl,al ; save root in cl
sort4 ; sort
mov ch,0 ; look for root
cmp al,cl ; /
jz cgen3 ; /
inc ch ; /
cmp ah,cl ; /
jz cgen3 ; /
inc ch ; /
cmp dl,cl ; /
jz cgen3 ; /
inc ch ; /
cgen3: mov byte ptr outn[di],ch ; send root # to output
;
cgenx: mov ds:[bp],ax ; set chord values
mov ds:2[bp],dx ; /
cgenz: nextv ; exit
;==============================================================
; set new chords table data from 4 inputs
;--------------------------------------------------------------
; inputs:
; 0: chord array location (16 possible arrays of 4 values)
; 1: root input
; 2: 1st interval input
; 3: 2nd interval input
; 4: 3rd interval input
; 5: nz = normalize to octave
; 6: offset to base
; 7: nz = sort
; 8: foldover range
; 9: doit strobe
; 10x: clock ticks
; output: root # (always 0 unless sort)
;--------------------------------------------------------------
public _cmak
_cmak:
tick var9,var10 ; clock strobe
jc cmak0 ; yes, go do it
jmp cmakz ; exit if no tick
;
cmak0: getv al,var0 ; get array location
and ax,15 ; mask
add ax,ax ; *4
add ax,ax ; /
add ax,offset dgroup:interv ; add in int table addr
mov bp,ax ; save in bp
;
getv cl,var6 ; get offset
getv al,var1 ; get inputs
add al,cl ; add offset
getv ah,var2 ; /
add ah,cl ; /
getv dl,var3 ; /
add dl,cl ; /
getv dh,var4 ; /
add dh,cl ; /
;
testv var5,-1 ; want to normalize?
jz cmak1 ; no, branch
mov cx,ax ; yes, save ax
mov bx,dx ; save dx
normal ; normalize
mov cl,ah ; /
mov al,ch ; /
normal ; /
mov ch,ah ; /
mov al,bl ; /
normal ; /
mov bl,ah ; /
mov al,bh ; /
normal ; /
mov bh,ah ; /
mov ax,cx ; restore to ax,dx
mov dx,bx ; /
;
cmak1: mov byte ptr outn[di],0 ; root is 0
testv var7,-1 ; want to sort
jnz cmak4 ; yes, do it
jmp cmakx ; no, exit
;
cmak4: push ax ; save root
getv al,var8 ; get max octave range
and al,15 ; limit
mov ch,12 ; /
mul ch ; /
add ch,al ; ch = range
pop ax ; restore root
;
range al,ch ; put in range
range ah,ch ; put in range
range dl,ch ; put in range
range dh,ch ; put in range
;
mov cl,al ; save root in cl
sort4 ; sort
mov ch,0 ; look for root
cmp al,cl ; /
jz cmak3 ; /
inc ch ; /
cmp ah,cl ; /
jz cmak3 ; /
inc ch ; /
cmp dl,cl ; /
jz cmak3 ; /
inc ch ; /
cmak3: mov byte ptr outn[di],ch ; send root # to output
;
cmakx: mov ds:[bp],ax ; set chord values
mov ds:2[bp],dx ; /
cmakz: nextv ; exit
;==============================================================
; select interval from modulated interval table
; inputs:
; 0: clock
; 1: location
; 2: interval step
; 3: nz = sort
; 4: offset
; 5x: clock tick
; output: note interval
;--------------------------------------------------------------
public _cplay,_cplai
_cplai: nop ; 2 sets of modules
_cplay: tick var0,var5 ; clock
jnc cplayz ; branch if no tick
getv cl,var1 ; get interval address
and cx,15 ; mask
add cx,cx ; *4
add cx,cx ; /
add cx,offset dgroup:interv ; cx = interval address
;
testv var3,-1 ; wanna sort?
jz cplay1 ; no, branch
;
mov bx,cx ; pick up intervals
mov ax,[bx] ; /
mov dx,2[bx] ; /
sort4 ; sort them
mov word ptr temp0,ax ; put in temp array
mov word ptr temp2,dx ; /
mov cx,offset dgroup:temp0 ; cx = sorted interval addr
;
cplay1: getv bl,var2 ; get interval number
and bx,3 ; mask
add bx,cx ; bx = table index
mov al,[bx] ; get the interval
;
getv ah,var4 ; get offset
add al,ah ; add offset to interval
putn al ; send it out
cplayz: nextv ; exit
;==============================================================
; store value to interval table
; inputs:
; 0: chord array location (16 possible arrays of 4 values)
; 1: location in array
; 2: base input value
; 3: nz = normalize to octave
; 4: offset to base
; 5: doit strobe
; 6x: clock tick
;
; output: previous value at address
;--------------------------------------------------------------
public _cstor
_cstor: tick var5,var6 ; strobe?
jnc cstorz ; no, exit
;
getv al,var2 ; get input
testv var3,-1 ; want to normalize?
jz cstor1 ; no, branch
normal ; yes, normalize to octave
mov al,ah ; put back in al
;
cstor1: getv ah,var4 ; get offset
add al,ah ; add to input
;
getv cl,var0 ; get interval address
and cx,15 ; mask
add cx,cx ; *4
add cx,cx ; /
add cx,offset dgroup:interv ; cx = interval address
;
getv bl,var1 ; get interval number
and bx,3 ; mask
add bx,cx ; bx = table index
;
xchg al,[bx] ; swap old with new
putn al ; send old to output
cstorz: nextv ; exit
;==============================================================
; generate bass note line, dithered input a,b
; inputs:
; 0: clock
; 1: nz = hold
; 2: strobe center to output
; 3: center
; 4: max distance from center
; 5: nz = use -, z = use +
; 6: input "a"
; 7: input "b"
; 8x:
; 8z: clock tick, init flag
; output: new bass note
;--------------------------------------------------------------
public _bassd
_bassd:
tickb1 var2,var8+1 ; strobe clock?
jnc bassd4 ; branch if no strobe
and byte ptr var8+1[di],0fbh; yes, flag/auto initialize
bassd4: tick var0,var8+1 ; wait for clock tick
jnc bassdz ; exit if not clock
hold var1 ; hold?
jnz bassdz ; exit if hold
;
test byte ptr var8+1[di],4 ; was flag set?
jnz bassd1 ; no, branch
or byte ptr var8+1[di],4 ; yes, clear flag
bassd0: getv al,var3 ; get the input
putn al ; send it to output
jmp short bassdz ; exit
;
bassd1: getv al,var6 ; load for "a"
testv var5,-1 ; test for +/-
jz bassd2 ; branch if +
getv al,var7 ; load for "b"
neg al ; make "b" -
bassd2: add outn[di],al ; add the offset
;
getv al,var3 ; get center
getv ah,var4 ; get max
mov dl,al ; test for upper limit
add dl,ah ; /
cmp dl,outn[di] ; /
jb bassd0 ; reset if above limit
sub al,ah ; test for lower limit
cmp outn[di],al ; /
jb bassd0 ; reset if below limit
bassdz: nextv ; exit
;==============================================================
; Bit Formatter
; inputs: 1 - 8: bit set inputs, zero clrs, nz sets
; output: byte formatted from the 8 inputs
;--------------------------------------------------------------
public _gout
_gout:
gettag ; es:bx = screen addr of tag
dec bx ; point to leds
add bx,480 ; point to the first bit led
mov ax,bx ; ax = screen address pointer
mov bp,var0 ; bp = addr of first variable
mov dx,100H ; dl=0, dh=1
mov cx,8 ; gonna do 8 bits
gout1: mov bx,ds:[bp+di] ; get the variable address
cmp byte ptr [bx],0 ; test for zero/not zero
mov bx,ax ; get screen address
jnz gout2 ; branch if not zero
mov byte ptr es:[bx],yellow; turn off the led
jmp short gout3 ; branch to finish up
gout2: mov byte ptr es:[bx],hi+red; turn on the led
or dl,dh ; set the bit
gout3: shl dh,1 ; bump bit flag
add ax,160 ; bump screen addr 1 line
add bp,2 ; bump variable pointer
loop gout1 ; loop til done
putn dl ; set the new byte value
nextv ; exit w screen update
;==============================================================
; Display bits in a byte as gate lites
; inputs: 0: byte
; output: none
;--------------------------------------------------------------
public _gatel
_gatel:
getv al,var0 ; get the byte
gettag ; es:bx = screen addr of tag
dec bx ; point to leds
add bx,480 ; point to the first bit led
mov cx,8 ; 8 bits to do
gatel1: shr al,1 ; bit --> cy
jc gatel2 ; branch if the bit is hi
and byte ptr es:[bx],7; turn the led off
jmp short gatel3 ; branch
gatel2: or byte ptr es:[bx],8; turn the led on
gatel3: add bx,160 ; go down 1 line
loop gatel1 ; do all 8 bits
nextx ; exit quiet
;==============================================================
; Display values as an indicator bar
; linear display
; inputs: 0: left row, 1: right 2: scale
; 3x: left save, 3z: right save
; output: none
;--------------------------------------------------------------
public _imeter
_imeter:
getv al,var0 ; al = left value
getv dl,var1 ; dl = right value
getv dh,var2 ; dh = scale
or dh,dh ; scale = 0?
jnz imeter0 ; no, branch
inc dh ; yes, start with 1
imeter0:mov es,4[di] ; get seg addr
mov bx,6[di] ; get module screen address
add bx,160*5 ; point to top row of leds
;
inc bx ; point to left leds
cmp al,var3[di] ; has left changed
jz imeter4 ; no, branch
mov var3[di],al ; yes, save new value
push dx ; save right value & scale
or al,al ; al = 0 ?
jz imeter7 ; yes, don't divide
mov ah,0 ; ax = left value
div dh ; al = ax/dl
imeter7:call imeter1 ; show the new value
pop dx ; restore right value & scale
imeter4:add bx,2 ; point to right column
cmp dl,var3+1[di] ; did middle change
jz imeter6 ; no, branch
mov var3+1[di],dl ; yes, save the new value
mov al,dl ; al = right value
or al,al ; al = 0 ?
jz imeter8 ; yes, don't divide
mov ah,0 ; ax = left value
div dh ; al = ax/dl
imeter8:call imeter1 ; show the new value
imeter6:nextx ; exit quiet
;--------------------------------------------------------------
; convert linear 0-8 to log bit position
; then jump to emeter1 to display
; call with al = value
;
imeter1:test al,0f8h ; if > 7, max out
jz imeter2 ; /
mov dl,-1 ; /
jmp short imeter3 ; /
imeter2:mov cl,al ; else convert
xor al,al ; /
stc ; /
rcl al,cl ; /
mov dl,al ; /
imeter3:jmp emeter1 ; display
;==============================================================
; Display values as an indicator bar
; inputs: 0: left row, 1: right 2: scale
; 3x: left save, 3z: right save
; output: none
;--------------------------------------------------------------
public _emeter
_emeter:
getv al,var0 ; al = left value
getv dl,var1 ; dl = right value
getv dh,var2 ; dh = multiplier
or dh,dh ; mult = 0?
jnz emeter0 ; no, branch
inc dh ; yes, start with 1
emeter0:mov es,4[di] ; get seg addr
mov bx,6[di] ; get module screen address
add bx,160*5 ; point to top row of leds
;
inc bx ; point to left leds
cmp al,var3[di] ; has left changed
jz emeter4 ; no, branch
mov var3[di],al ; yes, save new value
push dx ; save right value & mult
mul dh ; ax = bumped right value
or ah,ah ; > 255 ?
jz emeter5 ; no, branch
mov al,255 ; yes, make it 255
emeter5:mov dl,al ; set up for display
call emeter1 ; show the new value
pop dx ; restore right value & scale
emeter4:add bx,2 ; point to right column
mov al,dl ; al = right value
cmp al,var3+1[di] ; did right change
jz emeter6 ; no, branch
mov var3+1[di],al ; yes, save the new value
mul dh ; ax = bumped right value
or ah,ah ; > 255 ?
jz emeter7 ; no, branch
mov al,255 ; yes, make it 255
emeter7:mov dl,al ; set up for display
call emeter1 ; show the new value
emeter6:nextx ; exit quiet
;--------------------------------------------------------------
; subroutine to show a column of leds
; call with BX = address of top of column (preserved), DL = value
; display is log, sets top led high and all following if
; bit 7 is set, else sets top led low, then top-1 if bit 6, etc.
;
emeter1:push bx ; preserve bx
mov dh,0 ; use dh as flag byte
mov cx,8 ; 8 leds in the column
emeterl:shl dx,1 ; bump hi bit of dl into dh
test dh,-1 ; on or off?
jz emeter2 ; branch if off
or byte ptr es:[bx],8 ; make bright
jmp short emeter3 ; duck
emeter2:and byte ptr es:[bx],0f7h ; or make dark
emeter3:add bx,160 ; next line
loop emeterl ; loop til done
pop bx ; restore bx
ret ; exit
;==============================================================
; Set output to approximately the same as input, within limits
; inputs: 0: input 1: upper limit, 2: lower limit,
; 3x: last input
; output: scaled random number
;--------------------------------------------------------------
public _apprx
_apprx:
getv dl,var0 ; get the value
test rhold,-1 ; branch if alpha seed
jnz appr1 ; /
cmp dl,var3[di] ; same as last?
jnz appr1 ; no, go to work
nextx ; yes, easy exit
;
appr1: mov var3[di],dl ; set new value
random
getv al,var1 ; get upper offset
inc al ; fudge
add al,dl ; add in value
mov ah,0 ; msb = 0
getv bl,var2 ; get lower offset
sub dl,bl ; subtract from value
mov bl,dl ; keep it in bl
mov bh,0 ; msb = 0
sub ax,bx ; ax = upper - lower
mul cx ; dx = appr * (upper-lower)/10000H
add dx,bx ; dx = above + lower
putn dl ; send it out
nextv ; exit with video update
;==============================================================
; Generate random numbers
; inputs: 0: clock 1: hold 2: seed value, 3: range, 4: offset,
; 5: seed, 6x: saved value, 6z: clock-tick
; output: random number
;--------------------------------------------------------------
public _rand
_rand:
mov ah,var6[di] ; get last value
;
getv al,var1 ; local hold?
or al,rhold ; global rand hold?
jz rand0 ; no, branch
rand2: getv al,var2 ; yes, reset seed
mov ah,al ; /
mov var5[di],ax ; /
jmp rand1a ; go out
;
rand0: test mprstf,-1 ; master hold?
jnz rand1 ; yes, branch
;
tick var0,var6+1 ; clock tick
jnc rand1 ; branch if no tick
;
mov cx,var5[di] ;; get next raw seed
add cx,9248H ;; /
ror cx,1 ;; /
ror cx,1 ;; /
ror cx,1 ;; /
mov var5[di],cx ;; /
;
getv al,var3 ; get range
mul cl ; ah = rand * range /256
rand1a: mov var6[di],ah ; put it away
rand1: getv al,var4 ; get offset
add al,ah ; put them together
putn al ; send it out
nextv ; exit
;==============================================================
; Non-repeating random pattern
; inputs: 0: clock 1: hold 2: seed value, 3: inc/dec, 4: range
; 5x: saved value, 5z: clock-tick, 6: address pointer
; output: random number
;--------------------------------------------------------------
public _rrand
_rrand:
getv cl,var4 ; get range
cmp cl,1 ; check for 0,1
jna rrand0 ; split if 0
mov dx,1 ; for inc/dec
testv var3,-1 ; dec if nz
jz rrand03 ; /
mov dx,-1 ; /
;
rrand03:
getv al,var1 ; local hold?
or al,rhold ; global rand hold?
jz rrand01 ; no, branch
rrand2: getv al,var2 ; yes, get seed
putn al ; send it out
mov ah,64 ; /
mul ah ; /
mov var6[di],ax ; /
jmp rrandx ; split
;
rrand01:test mprstf,-1 ; master hold?
jnz rrand0 ; yes, branch
;
tick var0,var5+1 ; clock tick
jc rrand1 ; branch if tick
rrand0: nextx ; else just split
;
rrand1: add var6[di],dx ; bump pointer
rrandz: mov bx,var6[di] ; get it
and bx,3fffh ; keep in code range
add bx,offset _doit ; start of code
mov ax,cs:[bx] ; get the byte
add al,ah ; fill it out
mul cl ; ah = rand * range /256
cmp ah,var5[di] ; same as last?
jz rrand1 ; yes, do it again
mov var5[di],ah ; no, save it
putn ah ; send it out
rrandx: nextv ; exit
;==============================================================
; Random strobe generator
; output: 50% strobe
; input: 0: strobe, 1x: clock tick
;--------------------------------------------------------------
public _randp
_randp:
mov cl,0 ; setup for hold
test mprstf,-1 ; check alpha hold
jnz randpx ; yes, exit
tick var0,var1 ; clock input
jnc randpz ; exit if no clock
random ; get random value
and cl,1 ; isolate lsb
randpx: putn cl ; send it our
randpz: nextl ; show it
;==============================================================
; Random strobe generator
; output: clock strobe
; input: 0: reset, 1: count, 2: offset 3: dither
; 4x:countdown timer, 4z: copy of count
;--------------------------------------------------------------
public _nrand
_nrand: testv var1,-1 ; clock = 0
jz nrandz ; yes, just exit
hold var0 ; hold?
jz nrand0 ; no, branch
mov al,byte ptr cs:loops; get count
and al,1 ; /
mov var4[di],al ; reset clock counters
jmp short nrandz ; split
;
nrand0: getv ah,var1 ; get current count
cmp ah,var4+1[di] ; same as before?
jz nrand1 ; yes, branch
cmp ah,1 ; set to 1?
jnz nrand3 ; no, branch
mov ah,2 ; yes, set to 2
nrand3: mov al,byte ptr cs:loops; get count
and al,1 ; /
mov var4[di],ax ; /
;
nrand1: getv al,var2 ; get offset trigger
cmp al,ah ; out of range?
jb nrand4 ; no, branch
mov al,0 ; yes, zip it
nrand4: cmp al,var4[di] ; same as count?
jnz nrand2 ; no, branch
random ; yes, get random value
getv ch,var3 ; get ddithr value
sub ch,cl ; above threshold?
jna nrand2 ; no, branch
mov byte ptr outn[di],1; else output flag
;
nrand2: inc byte ptr var4[di]; tick
cmp ah,var4[di] ; reached count?
jnz nrandz ; no, exit
mov byte ptr var4[di],0; yes, reset timer
nrandz: nextt ; exit
;==============================================================
; Random slope output
; inputs 0: count, 1: range,
; 2x: target, 2+:
; 3x: current, 3+: +/-
; 4x: clock, 4+: old clock
;
; ouput last +/- 1
;--------------------------------------------------------------
public _variz,_variy
_variy: nop
_variz:
getv dh,var1 ; get range input
getv al,var0 ; get clock
;
test dh,80H ; test msb of range for reset
jnz varizz ; go reset if high
;
test mprstf,-1 ; check for master reset
jnz varizz ; reset if high
;
test rhold,-1 ; check for random reset
jnz varizz ; reset if high
;
cmp al,var4+1[di] ; clock same as before
jz variz0 ; yes, go to work
jmp varizk ; no, fix clock
;--------------------------------------------------------------
varizz: and dh,7fh ; strip msb
putn dh ; send it out
mov var2[di],dh ; set as target
mov byte ptr var3+1[di],1 ; set to count up
shr dh,1 ; current is range/2
shr dh,1 ; current is range/2
mov var3[di],dh ; /
;
varizk: mov var4+1[di],al ; save clock
mov byte ptr var4[di],1 ; new one next clock
nextv ; split
;--------------------------------------------------------------
varizzx:nextx ; split
variz0: dec byte ptr var4[di] ; bump clock
jnz varizzx ; exit if not 0
getv al,var0 ; else get it
mov var4+1[di],al ; save clock
inc al ; bump
mov var4[di],al ; put away
;--------------------------------------------------------------
mov dl,var3[di] ; get current value
add dl,var3+1[di] ; add bump
mov var3[di],dl ; put it away
cmp dl,var2[di] ; reached target?
jnz variz2 ; no, branch
;
variz1: random ; get new rand
mov al,dh ; get range
test ch,0E0H ; 3/4 of the time
jz variz1a ; ... use it straight
rcr cl,1 ; ... else cut 1/2
jnc variz1a ; ... and maybe more
shr cl,1 ; ... cut again
variz1a:mul cl ; ah = rand * range /256
;
mov byte ptr var3+1[di],0ffh; set up for inc
cmp ah,var2[di] ; is it < target?
jb variz3 ; yes,is <, exit
mov byte ptr var3+1[di],1 ; no, set up for dec
jnz variz3 ; exit if <>
inc ah ; else bump
variz3:
mov var2[di],ah ; save new target
variz2:
shr dh,1 ; calc offset
shr dh,1 ; calc offset
add dl,dh ; add in count
jns variz2a ; branch if <= 7fh
mov dl,7fh ; else make 7fh
variz2a:putn dl ; send it out
nextv ; exit
;==============================================================
; Random slope output
; inputs 0: clock 1: hold, 2: range 3: offset
; 4x: +/- 4+: clock tick, 5x: target, 5+: current
; ouput last +/- 1
;--------------------------------------------------------------
public _variv
_variv:
test rhold,-1 ; check for random reset
jnz variv00 ; reset if high
;
hold var1 ; hold?
jz variv0 ; no, branch
variv00:mov ah,var5+1[di] ; yes, get current
getv al,var3 ; get offset
add al,ah ; put them together
putn al ; send it
;
inc ah ; bump current
mov var5[di],ah ; set up target
mov byte ptr var4[di],1 ; set up counter
nextv ; exit
;--------------------------------------------------------------
variv0:
tick var0,var4+1 ; clock tick
jc variv1 ; branch if tick
nextx ; else just exit
;--------------------------------------------------------------
variv1: mov dl,var5+1[di] ; get current value
add dl,var4[di] ; add bump
mov var5+1[di],dl ; put it away
cmp dl,var5[di] ; reached target?
jnz variv2 ; no, branch
;
random ; else get new rand
getv al,var2 ; get range
mul cl ; ah = rand * range /256
;
mov byte ptr var4[di],-1 ; set up for inc
cmp ah,var5[di] ; is it < target?
jb variv3 ; yes,is <, exit
mov byte ptr var4[di],1 ; no, set up for dec
jnz variv3 ; exit if <>
inc ah ; else bump
variv3:
mov var5[di],ah ; save new target
variv2:
getv al,var3 ; get offset
add al,dl ; add current
putn al ; send it out
nextv ; exit
;==============================================================
; Random slope output
; inputs 0: clock
; 1: hold
; 2: addamt
; 3: range
; 4: offset
; 5x: target
; 6x: count
; 6+: b7=sign, b0=clock tick
;
; output: count+offset
;--------------------------------------------------------------
public _varix
_varix:
test rhold,-1 ; check for random reset
jnz varix00 ; reset if high
;
hold var1 ; hold?
jz varix0 ; no, branch
varix00:mov byte ptr var6[di],0 ; yes count = 0
mov byte ptr var5[di],0 ; target = 1
and byte ptr var6+1[di],7FH ; set sign bit
varixz: jmp varixx ; exit w count+offset
;--------------------------------------------------------------
varix0:
tick var0,var6+1 ; clock tick
jc varix1 ; branch if tick
nextx ; else just exit
;--------------------------------------------------------------
varix1: getv al,var2 ; get add ammt
getv ah,var3 ; is add amb > range
cmp al,ah ; add amt - range
jnb varixz ; yes, just exit
;
mov ah,0 ; ax = add amt
mov dl,var6[di] ; get count
mov dh,0 ; dx = count
;
test byte ptr var6+1[di],80H ; sign = count down?
jnz varix1a ; yes, branch
;
add dx,ax ; dx = count + add amt
mov al,var5[di] ; get target
mov ah,0 ; ax = target
cmp ax,dx ; target - new count
jnb varix4 ; send if target > nc
jmp varix2 ; else get a new one
;--------------------------------------------------------------
varix1a:sub dx,ax ; dx = count - add amt
jnc varix1b ; make 0 if underflow
mov dx,0 ; /
varix1b:mov al,var5[di] ; get target
mov ah,0 ; ax = target
cmp ax,dx ; target - new count
jna varix4 ; send if target < nc
; jmp varix2 ; else get a new one
;--------------------------------------------------------------
varix2: random ; else get new rand
getv al,var3 ; get range
or al,al ; exit if range=0
jz varixx ; /
mul cl ; ah = rand * range /256
or ah,ah ; don't want 0
jz varix2 ; /
xchg var5[di],ah ; save new target
mov var6[di],ah ; set count to old target
cmp ah,var5[di] ; old - new
ja varix2a ; old > new, go count down
;
and byte ptr var6+1[di],7FH ; clear sign
getv al,var2 ; get add ammt
mov ah,0 ; ax = add amt
mov dl,var6[di] ; get count
mov dh,0 ; dx = count
add dx,ax ; dx = count + add amt
jmp varix4 ; go with dl = new count
;
varix2a:or byte ptr var6+1[di],80H ; set sign
getv al,var2 ; get add ammt
mov ah,0 ; ax = add amt
mov dl,var6[di] ; get count
mov dh,0 ; dx = count
sub dx,ax ; dx = count - add amt
jnc varix4 ; make 0 if underflow
mov dl,0 ; /
;--------------------------------------------------------------
varix4: mov var6[di],dl ; save new count
varixx: getv al,var4 ; get offset
add al,var6[di] ; add count
putn al ; send it out
nextv ; exit
;==============================================================
; Generate a random tone row of 0-11
; inputs: 0: address
; 1: strobe
; 2x: tick
; 3-9:tone row table
; output: addressed value of tone row (0-11)
;--------------------------------------------------------------
public _trand
_trand:
test rhold,-1 ; check for random reset
jnz trand1 ; branch if high
;
tick var1,var2 ; clock tick
jnc trand1 ; branch if no tick
;
mov cx,12 ; 12 to do
mov bp,0 ; set up base
trand3: mov bx,0 ; set up index
test rhold,-1 ; holding?
jz trand7 ; no, get rand
mov dx,bp ; yes, do 0-1
jmp short trand2 ; get on with it
;
trand7: randdx ; get rng
and dl,15 ; 0-15 allowed
cmp dl,12 ; really 0-11
jb trand2 ; branch if ok
shr dl,1 ; else /2
;
trand2: cmp bx,bp ; at the target?
jnz trand4 ; no, branch
mov var3[bx+di],dl ; yes, put the byte away
trand6: inc bp ; bump index
loop trand3 ; do all 12
jmp short trand1 ; exit when done
;
trand4: cmp var3[bx+di],dl ; already got?
jz trand3 ; yes, try again
inc bx ; no, look at next
jmp short trand2 ; /
;
trand1: getv bl,var0 ; get address
mov bh,0 ; make into word
cmp bl,12 ; keep within range
jb trand0 ; branch if ok
;
mov ax,bx ; else mod 12
mov dl,12 ; /
div dl ; /
mov bl,ah ; /
;
trand0: mov al,var3[bx+di] ; pick up the byte
putn al ; send it out
nextv ; exit
;==============================================================
; Generate raw binary odds
; inputs: 0: clock 1x: clock-tick
; output: 0-7; 0 @ 1:2, 1 @ 1:4, ... 7 @ 1:256
;--------------------------------------------------------------
public _oddz
_oddz:
tick var0,var1 ; clock tick
jc oddz1 ; branch if there is a tick
nextx ; else exit easy
oddz1: random
mov al,0 ; output is 0-7
rol cl,1 ; test msb
jc oddzx ; branch if set
inc al ; else bump value
rol cl,1 ; test msb
jc oddzx ; branch if set
inc al ; else bump value
rol cl,1 ; test msb
jc oddzx ; branch if set
inc al ; else bump value
rol cl,1 ; test msb
jc oddzx ; branch if set
inc al ; else bump value
rol cl,1 ; test msb
jc oddzx ; branch if set
inc al ; else bump value
rol cl,1 ; test msb
jc oddzx ; branch if set
inc al ; else bump value
rol cl,1 ; test msb
jc oddzx ; branch if set
inc al ; else bump value
rol cl,1 ; test msb
jc oddzx ; branch if set
xor al,al ; else clr value
oddzx: putn al ; send it out
nextv ; exit
;==============================================================
; dither between 4 inputs
; inputs: 0: clock, 1-4: inputs, 5: offset, 6x: clock
; output: one of the 4 inputs
;--------------------------------------------------------------
public _odds
_odds:
test rhold,-1 ; branch if alpha seed
jnz odds1 ; /
tick var0,var6 ; clock tick
jc odds1 ; branch if there is a tick
oddsz: nextx ; else exit easy
odds1: random
test cl,80H ; 1:2 is input1
jz odds2 ; /
getv al,var1 ; /
jmp short oddsx ; /
odds2: test cl,40H ; 1:4 is input2
jz odds3 ; /
getv al,var2 ; /
jmp short oddsx ; /
odds3: test cl,20H ; 1:8 is input3
jz odds4 ; /
getv al,var3 ; /
jmp short oddsx ; /
odds4: test cl,10H ; 1:16 is input4
jz oddsz ; else no change
getv al,var4 ; /
;
oddsx: getv ah,var5 ; get the offset
add al,ah ; add to input
putn al ; send it out
nextv ; exit with video update
;==============================================================
; dither between 2 inputs
; inputs: 0: clock, 1: dither, 2,3 inputs, 4: offset, 5x: clock
; output: one of the 2 inputs
;--------------------------------------------------------------
public _dither
_dither:
test rhold,-1 ; branch if alpha seed
jnz dither1 ; /
tick var0,var5 ; clock tick
jc dither1 ; branch if there is a tick
ditherz:nextx ; else exit easy
dither1:random
;
dither2:getv ch,var1 ; get dither value
sub ch,cl ; above threshold?
jna dither3 ; no, branch
getv al,var3 ; yes, get "b" input
jmp short ditherx ; split
dither3:getv al,var2 ; no, get "a" input
ditherx:getv ah,var4 ; get the offset
add al,ah ; add to input
putn al ; send it out
nextv ; exit with video update
;==============================================================
; dither between and input and 0
; inputs: 0: clock, 1: dither, 2: input, 3: offset, 4x: clock
; output: the input or 0
;--------------------------------------------------------------
public _dithzr
_dithzr:
test rhold,-1 ; branch if alpha seed
jnz dithzr1 ; /
tick var0,var4 ; clock tick
jc dithzr1 ; branch if there is a tick
dithzrz:nextx ; else exit easy
dithzr1:random
;
dithzr2:getv ch,var1 ; get dithzr value
sub ch,cl ; above threshold?
jna dithzr3 ; yes, branch
getv al,var2 ; no, get the input
jmp short dithzrx ; split
dithzr3:mov al,0 ; no, make it 0
dithzrx:getv ah,var3 ; get the offset
add al,ah ; add to input
putn al ; send it out
nextv ; exit with video update
;==============================================================
; dither between 0 and 1
; inputs: 0: clock, 1: dither, 2x: clock
; output: 0/1
;--------------------------------------------------------------
public _ddithr
_ddithr:
test rhold,-1 ; branch if alpha seed
jnz ddithr1 ; /
tick var0,var2 ; clock tick
jc ddithr1 ; branch if there is a tick
ddithrz:nextx ; else exit easy
ddithr1:random
ddithr2:getv ch,var1 ; get ddithr value
sub ch,cl ; above threshold?
mov al,1 ; set flag
ja ddithrx ; yes, branch branch
dec al ; no, clear flag
ddithrx:putn al ; send it out
nextl ; exit with video update
;==============================================================
; calc given ratio based on clock input
; inputs: 0: master clock
; 1-4: clock inputs
; 5x: clock ticks
; 5z: storage for output until tick
; output: 0-F, based on input pattern
;--------------------------------------------------------------
public _ratio
_ratio:
mov al,var5+1[di] ; get current output
tick var1,var5 ; clock tick
jnc ratio1 ; branch if no tick
xor al,1 ; else flip the bit
ratio1: tickb1 var2,var5 ; clock tick
jnc ratio2 ; branch if no tick
xor al,2 ; else flip the bit
ratio2: tickb2 var3,var5 ; clock tick
jnc ratio3 ; branch if no tick
xor al,4 ; else flip the bit
ratio3: tickb3 var4,var5 ; clock tick
jnc ratio4 ; branch if no tick
xor al,8 ; else flip the bit
ratio4: mov var5+1[di],al ; put it away
tickb4 var0,var5 ; master clock tick?
jnc ratioz ; no, exit
putn al ; yes, send out new tick
ratioz: nextv ; exit with video update
;==============================================================
; calc given ratio based on dither input
; inputs: 0: clock
; 1-4: dither levels
; 5x: clock tick
; output: 0-F, based on input pattern
;--------------------------------------------------------------
public _ratiz
_ratiz:
test rhold,-1 ; branch if alpha seed
jnz ratiz0 ; /
tick var0,var5 ; tick?
jc ratiz0 ; yes, branch
jmp ratizz ; no, just exit
ratiz0: mov al,outn[di] ; get current output
random
getv ch,var1 ; get ddithr value
or ch,ch ; anything there
jnz ratiza ; yes, branch
and al,0feh ; no, clear the bit
ratiza: sub ch,cl ; above threshold?
jna ratiz1 ; no, branch
xor al,1 ; yes, set flag
ratiz1: random
getv ch,var2 ; get ddithr value
or ch,ch ; anything there
jnz ratizb ; yes, branch
and al,0fdh ; no, clear the bit
ratizb: sub ch,cl ; above threshold?
jna ratiz2 ; no, branch
xor al,2 ; yes, set flag
ratiz2: random
getv ch,var3 ; get ddithr value
or ch,ch ; anything there
jnz ratizc ; yes, branch
and al,0fbh ; no, clear the bit
ratizc: sub ch,cl ; above threshold?
jna ratiz3 ; no, branch
xor al,4 ; yes, set flag
ratiz3: random
getv ch,var4 ; get ddithr value
or ch,ch ; anything there
jnz ratizd ; yes, branch
and al,0f7h ; no, clear the bit
ratizd: sub ch,cl ; above threshold?
jna ratiz4 ; no, branch
xor al,8 ; yes, set flag
ratiz4: putn al ; send it out
ratizz: nextv ; exit with video update
;==============================================================
; select intervals
; inputs:
; 0: sort step
; 1-4: inputs
;
; output: value at sorted step
;--------------------------------------------------------------
public _sort
_sort: getv al,var1 ; get the inputs
getv ah,var2 ; /
getv dl,var3 ; /
getv dh,var4 ; /
sort4 ; sort them
mov word ptr temp0,ax ; put in temp array
mov word ptr temp2,dx ; /
getv bl,var0 ; get interval number
and bx,3 ; mask
add bx,offset dgroup:temp0 ; bx = table index
mov al,[bx] ; get the value
putn al ; send it out
nextv ; exit
;==============================================================
; delta test
; inputs:
; 0: nz = hold
; 1: delta
; 2: nz = normalize within octave
; 3: input
; 4x: last input
; output: strobe when delta is detected
;--------------------------------------------------------------
public _deltat
_deltat:
hold var0 ; hold?
jnz deltatz ; exit if hold
testv var1,-1 ; delta 0?
jz deltatz ; yes, just exit
;
getv al,var3 ; get pitch input for delta
mov ah,al ; setup
testv var2,-1 ; want to normalize
jz deltat1 ; no, branch
normal ; normalize
deltat1:getv al,var1 ; get delta
xchg ah,var4[di] ; swap input with last one
sub ah,var4[di] ; delta match?
cmp ah,al ; /
jz deltat2 ; yes, branch
neg al ; else swap sign
cmp ah,al ; try again
jz deltat2 ; branch if = delta
jmp deltatz ; no, exit
;
deltat2:mov byte ptr outn[di],1; set flag
deltatz:nextt ; strobe
;==============================================================
; * 12, + offset
; inputs:
; 0: value
; 1: offset
;
; output: value * 12 + offset
;--------------------------------------------------------------
public _mul12
_mul12:
getv al,var0 ; get value
mov dl,12 ; for octave
mul dl ; * 12
getv ah,var1 ; get offset
add al,ah ; add it in
putn al ; send it out
nextv ; exit
;==============================================================
; / 12
; input: 0: value
; output: value / 12
;--------------------------------------------------------------
public _div12
_div12:
getv al,var0 ; get value
or al,al ; zero not allowed
jz div12x ; split if zero
mov dl,12 ; for octave
mov ah,0 ; make into word
div dl ; / 12
div12x: putn al ; send it out
nextv ; exit
;==============================================================
; mod 12
; input: 0: value
; 1: offset
; output: value mod 12
;--------------------------------------------------------------
public _mod12
_mod12:
getv al,var0 ; get value
mov ah,0 ; load for 0
or al,al ; zero not allowed
jz mod12x ; split if zero
mov dl,12 ; for octave
div dl ; / 12
mod12x: getv al,var1 ; get offset
add al,ah ; add in mod value
putn al ; send it out
nextv ; exit
;==============================================================
; fold to octave range
; input: 0: value
; 1: octave range
; 2: offset
; output: value mod 12
;--------------------------------------------------------------
public _fold
_fold:
getv al,var1 ; get max octave range
and al,15 ; limit
mov ch,12 ; octave
mul ch ; /
add ch,al ; ch = max
;
getv ah,var0 ; get input
range ah,ch ; put in range
getv al,var2 ; get offset
add al,ah ; add in mod value
putn al ; send it out
nextv ; exit
;==============================================================
; Union
; inputs: 0: trigger, 1: sync, 2x: clocks, 2z: trig flag
; output: pulse of one loop cycle duration
;--------------------------------------------------------------
public _union
_union:
tick var0,var2 ; clock trig input
jnc union0 ; branch if no tick
mov byte ptr var2+1[di],1 ; else set holding byte
union0: tickb1 var1,var2 ; clock sync input
jnc unionz ; branch if no tick
mov al,0 ; else clear trigger, if any
xchg al,var2+1[di] ; get trigger, if any
putn al ; send it out
unionz: nextt ; strobe
;==============================================================
; Flip-flop
; inputs: 0: set, 1: reset, 2x: set-tick, 2z: reset-tick
; output: pulse of one loop cycle duration
;--------------------------------------------------------------
public _fflop
_fflop:
tick var0,var2 ; clock tick
jnc fflop1 ; branch if no set input
mov byte ptr outn[di],1; set the pulse
fflop1: tick var1,var2+1 ; clock tick
jnc fflop2 ; branch if no reset input
mov byte ptr outn[di],0; reset the pulse
fflop2: nextl ; exit with led update
;==============================================================
; shift left
; inputs: 0: value, 1: shift ammount, 2: mask
; output: shifted value
;--------------------------------------------------------------
public _lshift
_lshift:
getv cl,var1 ; get the exponent
and cl,07H ; 0-7 allowed
getv al,var0 ; get the value
rol al,cl ; shift
getv ah,var2 ; get mask
and al,ah ; mask output
putn al ; send it out
nextv ; exit with video update
;==============================================================
; shift right
; inputs: 0: value, 1: shift ammount, 2: mask
; output: shifted value
;--------------------------------------------------------------
public _rshift
_rshift:
getv cl,var1 ; get the exponent
and cl,07H ; 0-7 allowed
getv al,var0 ; get the value
ror al,cl ; shift
getv ah,var2 ; get mask
and al,ah ; mask output
putn al ; send it out
nextv ; exit with video update
;==============================================================
; Low Pass Filter
; inputs: 0: clock, 1: value, 2: slope, 3: offset
; 4x: index, 4z: clock tick, 5-12: storage
; output: average of last 2, 4, 8, or 16 inputs (slope 0-3)
;--------------------------------------------------------------
public _filter
_filter:
tick var0,var4+1 ; clock tick
jc filte1 ; branch if there is a tick
nextx ; else easy exit
;
filte1: getv al,var1 ; get the input value
getv cl,var2 ; get the slope
and cl,03H ; 0-3 allowed
mov dl,2 ; shift
shl dl,cl ; dl = 2, 4, 8, or 16
mov dh,dl ; copy
dec dh ; dh = 1, 3, 7, or 15
mov bl,var4[di] ; get index
inc bl ; bump it
and bl,dh ; keep in bounds
mov var4[di],bl ; put it away
mov bh,0 ; bx = index offset
mov var5[bx+di],al ; put value into save list
mov dh,cl ; dh = slope value (for later)
mov cl,dl ; get slope count
mov ch,0 ; cx = 2, 4, 8, or 16
mov bx,var5 ; bx = start of save table
mov bp,0 ; bp will get sum of saved inputs
mov ah,0 ; ax will get each byte saved
filte2: mov al,[bx+di] ; get the saved byte
add bp,ax ; sum of saved bytes
inc bx ; /
loop filte2 ; /
mov ax,bp ; ax = sum of saved byte values
mov cl,dh ; dh = slope value
inc cl ; bump
shr ax,cl ; ax = average of saved inputs
getv ah,var3 ; get offset
add al,ah ; add to averaged value
putn al ; send it out
nextv ; exit with video update
;==============================================================
; Power of 2
; inputs: 0: value
; output: 2 ^^ value
;--------------------------------------------------------------
public _twopwr
_twopwr:
getv cl,var0 ; get the exponent
and cl,07H ; 0-7 allowed
mov al,1 ; shift
shl al,cl ; /
putn al ; send it out
nextv ; exit with video update
;==============================================================
; Test for flagged bits
; inputs: 0: input, 1: value
; output: 1 if any masked bits are hi, else 0
;--------------------------------------------------------------
public _bitsp
_bitsp: getv al,var0 ; get input
mov dl,0 ; flag = false
test al,-1 ; any bits hi?
jz bitsp1 ; no, branch
getv dl,var1 ; yes, get the value
bitsp1: putn dl ; send the flag
nextl ; exit with led update
;==============================================================
; Test for flagged bits
; inputs: 0: input, 1: bitmask, 2: value
; output: 1 if any masked bits are hi, else 0
;--------------------------------------------------------------
public _bitsq
_bitsq: getv al,var0 ; get input
getv ah,var1 ; get mask byte
mov dl,0 ; flag = false
test al,ah ; any bits hi?
jz bitsq1 ; no, branch
getv dl,var2 ; yes, get the value
bitsq1: putn dl ; send the flag
nextl ; exit with led update
;==============================================================
; Test for minus ( bit 7 high)
; inputs: 0: input
; output: 1 if bit 7 hi, else 0
;--------------------------------------------------------------
public _minusp
_minusp:
getv al,var0 ; get input
mov dl,0 ; flag = false
test al,80H ; is negative?
jz minusp1 ; no, branch
inc dl ; yes, flag = true
minusp1:putn dl ; send the flag
nextl ; exit with led update
;==============================================================
; Test for non-zero
; inputs: 0: input
; output: 0 if input is 0, else 1
;--------------------------------------------------------------
public _truep
_truep:
getv al,var0 ; get input
mov dl,1 ; flag = false
or al,al ; is zero?
jnz truep1 ; no, branch
dec dl ; yes, flag = true
truep1: putn dl ; send the flag
nextl ; exit with led update
;==============================================================
; Test for zero
; inputs: 0: input
; output: 1 if input is 0, else 0
;--------------------------------------------------------------
public _zerop
_zerop:
getv al,var0 ; get input
mov dl,0 ; flag = false
or al,al ; is zero?
jnz zerop1 ; no, branch
inc dl ; yes, flag = true
zerop1: putn dl ; send the flag
nextl ; exit with led update
;==============================================================
; Test for within range
; inputs: 0: input, 1: hi bounds, 2: low bounds
; output: 1 if within range, else 0
;--------------------------------------------------------------
public _rangep
_rangep:
getv al,var0 ; get input
mov dl,0 ; flag = false
getv ah,var1 ; get hi range
cmp al,ah ; input > hi range?
ja range1 ; yes, exit False
getv ah,var2 ; get lo range
cmp al,ah ; input < lo range?
jb range1 ; yes, exit False
inc dl ; no, flag = True
range1: putn dl ; send the flag
nextl ; exit with led update
;==============================================================
; Test for a > b
; inputs: 0: input a, 1: input b
; output: 1 if a > b, else 0
;--------------------------------------------------------------
public _great
_great:
getv al,var0 ; get input a
getv ah,var1 ; get inmpu b
mov dl,0 ; flag = false
cmp al,ah ; is a > b ?
jna great1 ; no, branch
inc dl ; yes, flag = true
great1: putn dl ; send the flag
nextl ; exit with led update
;==============================================================
; Test for a < b
; inputs: 0: input a, 1: input b
; output: 1 if a < b, else 0
;--------------------------------------------------------------
public _lessp
_lessp:
getv al,var0 ; get input a
getv ah,var1 ; get inmpu b
mov dl,0 ; flag = false
cmp al,ah ; is a < b ?
jnb lessp1 ; no, branch
inc dl ; yes, flag = true
lessp1: putn dl ; send the flag
nextl ; exit with led update
;==============================================================
; Test for change
; inputs: 0: input, 1x: last input value
; output: 1 if change else 0
;--------------------------------------------------------------
public _change
_change:
mov ah,0 ; clear flag
getv al,var0 ; get input 1
cmp al,var1[di] ; same as last?
jz chang1 ; yes, send "no change"
inc ah ; else send change
chang1: putn ah ; send the flag
mov var1[di],al ; save value for next time
nextl ; exit with led update
;==============================================================
; Test for equal
; inputs: 0: input, 1: input
; output: 1 if equal, else 0
;--------------------------------------------------------------
public _equal
_equal:
getv al,var0 ; get input 1
getv ah,var1 ; get inmpu 2
mov dl,0 ; flag = false
cmp al,ah ; are they equal
jnz equal1 ; no, branch
inc dl ; yes, flag = true
equal1: putn dl ; send the flag
nextl ; exit with led update
;==============================================================
; Test for not equal
; inputs: 0: input, 1: input
; output: 1 if not equal, else 0
;--------------------------------------------------------------
public _nequal
_nequal:
getv al,var0 ; get input 1
getv ah,var1 ; get inmpu 2
mov dl,0 ; flag = false
cmp al,ah ; are they equal
jz nequal1 ; yes, branch
inc dl ; no, flag = true
nequal1:putn dl ; send the flag
nextl ; exit with led update
;==============================================================
; output: delayed input
; input: 0: value
; 1: delay clocks
; 2: offset
; 3: index
; 4-131: value array
;--------------------------------------------------------------
public _delay
_delay: getv al,var0 ; get input value
getv dl,var1 ; get number of clocks delay
getv dh,var2 ; get offset
mov bl,var3[di] ; get current count
dec byte ptr var3[di]; bump it
mov bh,0 ; byte --> word
mov var4[bx+di],al ; set input byte
add bl,dl ; add delay
mov al,var4[bx+di] ; get the output byte
add al,dh ; add offset
putn al ; send the new output
nextv
;==============================================================
; output: the last changed input
; input: 0-7: values
; 8x - 9+: saved values
;--------------------------------------------------------------
public _lastv
_lastv: mov bp,si ; save si
mov dx,di ; save di
mov si,di ; set si to saved values
add si,var8 ; /
add di,var0 ; set di to input values
mov cx,8 ; 8 to do
lastvl: mov bx,[di] ; point to var addr
mov al,[bx] ; get it
cmp al,[si] ; same?
jnz lastvx ; yes, exit
add di,2 ; point to next
inc si ; /
loop lastvl ; do all 8
mov di,dx ; restore registers
mov si,bp ; /
nextx ; easy exit if no change
;
lastvx: mov [si],al ; set the flag
mov di,dx ; restore registers
mov si,bp ; /
putn al ; send the new output
nextv
;==============================================================
; Quantize value input to nearest match input
; inputs: 0: value input, 1: extract value, 2-9: match inputs
; output: nearest match input
;--------------------------------------------------------------
public _quant
_quant:
getv dl,var0 ; dl = value input
;
getv cl,var1 ; get extract root
or cl,cl ; if zero, ignore
jz quant0 ; /
;
mov al,dl ; get the value
or al,al ; zero not allowed
jz quant0a ; split if zero
mov ah,0 ; make into word
div cl ; divide by extract value
mov dl,ah ; mod result is compare value
mul cl ; restore to base
quant0a:mov cl,al ; cl is base
;
quant0: mov dh,-1 ; dh = initialized test
;
getv al,var2 ; get match input
mov ah,dl ; get value input
sub ah,al ; get difference
cmp ah,dh ; difference < test
jnb quant1a ; no, branch
mov dh,ah ; yes, difference is new test
putn al ; match input --> output
quant1a:neg ah ; test abs difference
cmp ah,dh ; abs difference < test
jnb quant2 ; no, branch
mov dh,ah ; yes, difference is new test
putn al ; match input --> output
;
quant2: getv al,var3 ; get match input
mov ah,dl ; get value input
sub ah,al ; get difference
cmp ah,dh ; difference < test
jnb quant2a ; no, branch
mov dh,ah ; yes, difference is new test
putn al ; match input --> output
quant2a:neg ah ; test abs difference
cmp ah,dh ; abs difference < test
jnb quant3 ; no, branch
mov dh,ah ; yes, difference is new test
putn al ; match input --> output
;
quant3: getv al,var4 ; get match input
mov ah,dl ; get value input
sub ah,al ; get difference
cmp ah,dh ; difference < test
jnb quant3a ; no, branch
mov dh,ah ; yes, difference is new test
putn al ; match input --> output
quant3a:neg ah ; test abs difference
cmp ah,dh ; abs difference < test
jnb quant4 ; no, branch
mov dh,ah ; yes, difference is new test
putn al ; match input --> output
;
quant4: getv al,var5 ; get match input
mov ah,dl ; get value input
sub ah,al ; get difference
cmp ah,dh ; difference < test
jnb quant4a ; no, branch
mov dh,ah ; yes, difference is new test
putn al ; match input --> output
quant4a:neg ah ; test abs difference
cmp ah,dh ; abs difference < test
jnb quant5 ; no, branch
mov dh,ah ; yes, difference is new test
putn al ; match input --> output
;
quant5: getv al,var6 ; get match input
mov ah,dl ; get value input
sub ah,al ; get difference
cmp ah,dh ; difference < test
jnb quant5a ; no, branch
mov dh,ah ; yes, difference is new test
putn al ; match input --> output
quant5a:neg ah ; test abs difference
cmp ah,dh ; abs difference < test
jnb quant6 ; no, branch
mov dh,ah ; yes, difference is new test
putn al ; match input --> output
;
quant6: getv al,var7 ; get match input
mov ah,dl ; get value input
sub ah,al ; get difference
cmp ah,dh ; difference < test
jnb quant6a ; no, branch
mov dh,ah ; yes, difference is new test
putn al ; match input --> output
quant6a:neg ah ; test abs difference
cmp ah,dh ; abs difference < test
jnb quant7 ; no, branch
mov dh,ah ; yes, difference is new test
putn al ; match input --> output
;
quant7: getv al,var8 ; get match input
mov ah,dl ; get value input
sub ah,al ; get difference
cmp ah,dh ; difference < test
jnb quant7a ; no, branch
mov dh,ah ; yes, difference is new test
putn al ; match input --> output
quant7a:neg ah ; test abs difference
cmp ah,dh ; abs difference < test
jnb quant8 ; no, branch
mov dh,ah ; yes, difference is new test
putn al ; match input --> output
;
quant8: getv al,var9 ; get match input
mov ah,dl ; get value input
sub ah,al ; get difference
cmp ah,dh ; difference < test
jnb quant8a ; no, branch
mov dh,ah ; yes, difference is new test
putn al ; match input --> output
quant8a:neg ah ; test abs difference
cmp ah,dh ; abs difference < test
jnb quant9 ; no, branch
mov dh,ah ; yes, difference is new test
putn al ; match input --> output
;
quant9: add outn[di],cl ; add base
nextv ; exit with video update
;==============================================================
; Keep the highest input
; inputs: 0: hold/reset 1: input
; output: highest input since reset
;--------------------------------------------------------------
public _higher
_higher:
hold var0 ; hold?
jz higher0 ; branch if no hold
getv al,var1 ; else get the input
putn al ; send it to the output
nextv ; exit
higher0:getv al,var1 ; get the value
cmp al,outn[di] ; higher than already there?
jna higher1 ; no, branch
putn al ; yes, send the new value
higher1:nextv ; exit with video update
;==============================================================
; Keep the lowest input
; inputs: 0: hold/reset 1: input
; output: lowest input since reset
;--------------------------------------------------------------
public _lower
_lower:
hold var0 ; hold?
jz lower0 ; branch if no hold
getv al,var1 ; else get the input
putn al ; send it to the output
nextv ; exit
lower0: getv al,var1 ; get the value
cmp al,outn[di] ; lower than already there?
jnb lower1 ; no, branch
putn al ; yes, send the new value
lower1: nextv ; exit with video update
;==============================================================
; Keep input between limits
; inputs: 0: input, 1: upper bounds, 2: lower bounds
; output: input between bounds
;--------------------------------------------------------------
public _limit
_limit:
getv al,var0 ; get the value
getv ah,var1 ; get upper limit
cmp al,ah ; less than upper limit?
jna limit1 ; yes, branch
mov al,ah ; else set it to upper limit
limit1: getv ah,var2 ; get lower limit
cmp al,ah ; greater than lower limit?
jnb limit2 ; yes, branch
mov al,ah ; else set it to lower limit
limit2: putn al ; send the value
nextv ; exit w video
;==============================================================
; Sample & Hold
; inputs: 0: follow 1: clock, 2: read 3: offset 4x: clock tick
; output: scaled sample
;--------------------------------------------------------------
public _sandh
_sandh:
testv var0,-1 ; follow on?
jnz sandh1 ; yes, branch
tick var1,var4 ; clock tick
jc sandh1 ; branch if there is a tick
nextx ; else exit easy
sandh1: getv al,var2 ; get sample
getv ah,var3 ; get offset
add al,ah ; put it together
putn al ; send it
nextv ; exit with video update
;==============================================================
; Midi sync control interface for Stop, Start, Continue, etc.
; output: bit flags
; bit 0: stop
; bit 1: start
; bit 2: continue
; input:
; 0: NZ = send Stop to Midi
; 1: NZ = send Start to MIDI
; 2: NZ = send Continue to MIDI
; 3: NZ = send Reset to MIDI
; 4: NZ = send Tune req to midi
; 5: NZ bits = clear output bits
; 6x: last stop input
; 6+: last start input
; 7x: last continue input
; 7+: initialized flag
; 8x: tick for stop, start, continue
; 8+: tick for reset, tune, clear
;--------------------------------------------------------------
public _stopo
_stopo: cmp byte ptr var7+1[di],0abh; initialized?
jz stopo0 ; yes, branch
mov word ptr var7[di],0ab00h; no, initialize
mov word ptr var8[di],0 ; /
mov word ptr var6[di],0 ; /
jmp stopox ; exit from init
;
stopo0: mov al,cs:mstop ; change in ext stop?
cmp al,var6[di] ; /
jz stopo0a ; no, branch
or byte ptr outn[di],1 ; yes, set the flag
mov var6[di],al ; /
;
stopo0a:mov al,cs:mstart ; change in ext start?
cmp al,var6+1[di] ; /
jz stopo0b ; no, branch
or byte ptr outn[di],2 ; yes, set the flag
mov var6+1[di],al ; /
;
stopo0b:mov al,cs:mcont ; change in ext cont?
cmp al,var7[di] ; /
jz stopo1 ; no, branch
or byte ptr outn[di],4 ; yes, set the flag
mov var7[di],al ; /
;--------------------------------------------------------------
stopo1: tick var0,var8 ; stop cmd input?
jnc stopo1a ; no, branch
mov al,0fch ; send Stop cmd to midi
call allmidi
;
stopo1a:tickb1 var1,var8 ; start cmd input?
jnc stopo1b ; no, branch
mov al,0fah ; send Start cmd to midi
call allmidi
;
stopo1b:tickb2 var2,var8 ; Cont cmd input?
jnc stopo2 ; no, branch
mov al,0fbh ; send Cont cmd to midi
call allmidi
;--------------------------------------------------------------
stopo2: tick var3,var8+1 ; Reset cmd input?
jnc stopo2a ; no, branch
mov al,0ffh ; send Reset cmd to midi
call allmidi
;
stopo2a:tickb1 var4,var8+1 ; Tune Request input?
jnc stopo3 ; no, branch
mov al,0f6h ; send Tune Request to midi
call allmidi
;--------------------------------------------------------------
stopo3: tickb2 var5,var8+1 ; clear output?
jnc stopox ; no, branch
mov byte ptr outn[di],0 ; clear the output
stopox: nextl ; show it
;==============================================================
; Sum of 5 inputs
; inputs: 0-4: inputs, 5: scale 6: offset
; output: scaled and offset input
;--------------------------------------------------------------
public _sumit
_sumit:
xor cx,cx ; clr cx
mov ah,ch ; clr ah
getv al,var0 ; get input
add cx,ax ; add to total
getv al,var1 ; get input
add cx,ax ; add to total
getv al,var2 ; get input
add cx,ax ; add to total
getv al,var3 ; get input
add cx,ax ; add to total
getv al,var4 ; get input
add cx,ax ; add to total
;
getv al,var5 ; get scale value
xchg al,ah ; al = 0, ah = scale
mul cx ; dx = scaled value
getv al,var6 ; get offset
add al,dl ; put it together
putn al ; send it
nextv ; exit with video update
;==============================================================
; Mix 3 Scaled inputs
; inputs: 0,2,4: input, 1,3,5: scale 6: offset
; output: scaled and offset input
;--------------------------------------------------------------
public _mixit
_mixit:
getv al,var0 ; get input
getv cl,var1 ; get scale value
mul cl ; ah = scaled value
mov ch,ah ; for sum
getv al,var2 ; get input
getv cl,var3 ; get scale value
mul cl ; ah = scaled value
add ch,ah ; sum
getv al,var4 ; get input
getv cl,var5 ; get scale value
mul cl ; ah = scaled value
add ch,ah ; sum
;
getv al,var6 ; get offset
add al,ch ; put it together
putn al ; send it
nextv ; exit with video update
;==============================================================
; Scale and offset input
; inputs: 0: input, 1: scale 2: offset
; output: scaled and offset input
;--------------------------------------------------------------
public _scale
_scale:
getv al,var0 ; get input
getv cl,var1 ; get scale value
mul cl ; ah = scaled value
getv al,var2 ; get offset
add al,ah ; put it together
putn al ; send it
nextv ; exit with video update
;==============================================================
; Max of two inputs
; inputs: 0: input, 1: input
; output: max
;--------------------------------------------------------------
public _maxf
_maxf:
getv al,var0 ; get input
getv ah,var1 ; get input
cmp ah,al ; select larger
jb maxf1 ; /
mov al,ah ; /
maxf1: putn al ; send it
nextv ; exit with video update
;==============================================================
; Min of two inputs
; inputs: 0: input, 1: input
; output: min
;--------------------------------------------------------------
public _minf
_minf:
getv al,var0 ; get input
getv ah,var1 ; get input
cmp al,ah ; select larger
jb minf1 ; /
mov al,ah ; /
minf1: putn al ; send it
nextv ; exit with video update
;==============================================================
; Rate of change (delta)
; inputs: 0: input, 1x: last input
; output: delta from last changed input
;
public _delta
_delta:
getv al,var0 ; get input
cmp al,byte ptr var1[di]; any change
jnz delta1 ; yes, branch
nextx ; no, easy exit
;
delta1: mov ah,byte ptr var1[di]; get old value
sub ah,al ; calc delta
jnb delta2 ; keep it positive
neg ah ; /
delta2: mov byte ptr var1[di],al; save new input
putn ah ; send delta
nextv ; exit with video update
;==============================================================
; Add three inputs
; inputs: 0: input, 1: input, 2: input
; output: sum of the three inputs
;
public _plus
_plus:
getv al,var0 ; get input
getv ah,var1 ; get input
add al,ah ; put it together
getv ah,var2 ; get input
add al,ah ; put it together
putn al ; send it
nextv ; exit with video update
;==============================================================
; Add two inputs, subtract the third
; inputs: 0: input, 1: input, 2: input
; output: sum of first two inputs minus the third
;
public _plusm,_plusn
_plusn: nop
_plusm: getv al,var0 ; get input
getv ah,var1 ; get input
add al,ah ; put it together
getv ah,var2 ; get input
sub al,ah ; put it together
putn al ; send it
nextv ; exit with video update
;==============================================================
; multiply input by 2nd input, divide by 3rd if nz
; inputs: 0: input, 1: mult, 2: divid
; output: product of the 3 inputs
;
public _times
_times:
getv al,var0 ; get input
getv cl,var1 ; get input
mul cl ; put it together
getv cl,var2 ; get input
or cl,cl ; zero?
jz times1 ; yes, do not divide
mov dx,0 ; give it headroom
mov ch,0
div cx ; divide dx:ax / cx
times1: putn al ; send it
nextv ; exit with video update
;==============================================================
; divide first input by 2nd, return remainder
; inputs: 0: input, 1: divide
; output: product of the 3 inputs
;
public _modulo
_modulo:
getv al,var0 ; get input
mov ah,0 ; setup for 0
getv cl,var1 ; get input
or cl,cl ; zero?
jz modulx ; yes, do not divide
div cl ; divide ax / cl
modulx: putn ah ; send remainder
nextv ; exit with video update
;==============================================================
; AND gate
; inputs: 0,1,2
; output: result of input0 AND input1 XOR input2
;--------------------------------------------------------------
public _andl
_andl:
getv al,var0 ; al = 1st variable
getv ah,var1 ; ah = 2nd variable
and al,ah ; AND them
getv ah,var2 ; ah = 3rd variable
xor al,ah ; xor them
putn al ; send to output
nextv
;==============================================================
; AND gate
; inputs: 0: &input 1: &input 2: +input
; output: result of input 0 AND input 1 PLUS input 2
;--------------------------------------------------------------
public _mask
_mask:
getv al,var0 ; al = 1st variable
getv ah,var1 ; ah = 2nd variable
and al,ah ; var0 AND var1
getv ah,var2 ; ah = 3rd variable
add al,ah ; add it to the AND stuff
putn al ; send to output
nextv
;==============================================================
; AND gate
; inputs: 0: &input 1: &input, 2: shift
; output: shifted result of input 0 AND input 1
;--------------------------------------------------------------
public _maskl
_maskl: getv al,var0 ; al = 1st variable
getv ah,var1 ; ah = 2nd variable
and al,ah ; var0 AND var1
getv cl,var2 ; get shift
rol al,cl ; shift
putn al ; send to output
nextv
;--------------------------------------------------------------
public _maskr
_maskr: getv al,var0 ; al = 1st variable
getv ah,var1 ; ah = 2nd variable
and al,ah ; var0 AND var1
getv cl,var2 ; get shift
ror al,cl ; shift
putn al ; send to output
nextv
;==============================================================
; NOT logic
; inputs: 0: value
; 1: mask
; output: NOT input0 AND input 1
;--------------------------------------------------------------
public _notl
_notl:
getv al,var0 ; al = 1st variable
not al ; complement
getv ah,var1 ; get mask
and al,ah ; AND them
putn al ; send to output
nextv
;==============================================================
; Slope detector
; inputs: 0
; output: nz if positive slope, z if neg, no change if 0
;
;--------------------------------------------------------------
public _slope
_slope:
getv ah,var0 ; al = 1st variable
cmp ah,var1[di] ; same as last?
jz slopex ; yes, just exit
mov var1[di],ah ; no, save it
mov al,1 ; setup for pos
ja slope1 ; branch if pos
mov al,0 ; else flag neg
slope1: putn al ; send to output
slopex: nextl
;==============================================================
; negate
; inputs: 0: input
; output: NEG of input
;--------------------------------------------------------------
public _negate
_negate:
getv al,var0 ; al = 1st variable
neg al ; negate it
putn al ; send to output
nextv
;==============================================================
; OR gate
; inputs: 0,1,2
; output: result of input0 OR input1 OR input2
;--------------------------------------------------------------
public _orl
_orl:
getv al,var0 ; var0 OR var1...
getv ah,var1 ; /
or al,ah ; /
getv ah,var2 ; ...OR var2
or al,ah ; /
putn al ; send out
nextv
;==============================================================
; shunt input to output
; inputs: 0: value
; output: input 0 unchanged
;--------------------------------------------------------------
public _value
_value:
getv al,var0 ; get variable 1
putn al ; send it
nextv
;==============================================================
; display input value in ascii
; inputs: 0-2: values to be displayed
; outputs: none
;--------------------------------------------------------------
public _ascii
_ascii:
getv al,var0 ; get the input value
getv ah,var1 ; /
getv cl,var2 ; /
mov es,4[di] ; get seg addr
mov bx,6[di] ; get module screen address
mov es:318[bx],al ; put to the screen
mov es:320[bx],ah ; /
mov es:322[bx],cl ; /
nextx ; exit
;==============================================================
; display input value in ascii from seq "s"
; inputs: 0: lo addr of value, 1: hi addr, 2: offset to addr
; outputs: none
;--------------------------------------------------------------
public _ascis
_ascis:
mov ax,seg bufsp ; setup seg register
mov es,ax ; es = seg addr
getv dl,var0 ; get address
getv dh,var1 ; get hi address
and dh,15 ; 16 max
getv bl,var2 ; get offset
add dl,bl ; put them together
mov bx,dx ; /
mov al,es:[bx] ; get the byte
inc bl ; bump addr low
mov ah,es:[bx] ; and the next
inc bl ; bump addr low
mov cl,es:[bx] ; and the next
;
mov es,4[di] ; get seg addr
mov bx,6[di] ; get module screen address
mov es:318[bx],al ; put to the screen
mov es:320[bx],ah ; /
mov es:322[bx],cl ; /
nextx ; exit
;==============================================================
; display input value in ascii from seq "S"
; inputs: 0: lo addr of value, 1: hi addr, 2: offset
; outputs: none
;--------------------------------------------------------------
public _asciz
_asciz:
mov ax,seg buffs ; setup seg register
mov es,ax ; es = seg addr
getv dl,var0 ; get address lo
getv dh,var1 ; get address hi
getv bl,var2 ; get offset
mov bh,0 ; /
add bx,dx ; set up as index
mov al,es:[bx] ; get the byte
mov ah,es:1[bx] ; and the next
mov cl,es:2[bx] ; and the next
;
mov es,4[di] ; get seg addr
mov bx,6[di] ; get module screen address
mov es:318[bx],al ; put to the screen
mov es:320[bx],ah ; /
mov es:322[bx],cl ; /
nextx ; exit
;==============================================================
; display input value in decimal
; inputs: x: (display location)
; 0: value to be displayed
; outputs: copy of value
;--------------------------------------------------------------
public _decin
_decin:
getv al,var0 ; get the input value
putn al ; send to output
mov colr,yellow ; set color to yellow
mov es,4[di] ; get seg addr
mov bx,6[di] ; get module screen address
add bx,478 ; point to readout
call todec ; do it
mov colr,green ; fix it back to green
nextv ; exit with update
;==============================================================
; display input value in decimal
; inputs: 0: decimal display
; outputs: none (display location)
;--------------------------------------------------------------
public _decim
_decim:
mov colr,yellow ; set color to yellow
getv al,var0 ; get the input value
mov es,4[di] ; get seg addr
mov bx,6[di] ; get module screen address
add bx,318 ; point to readout
call todec ; do it
mov colr,green ; fix it back to green
nextx ; exit, no update
;==============================================================
; slew over time
; formula:
; initialize:
; input * rate --> sum; input --> output
; thereafter until sum/rate = target:
; sum - input + target --> sum
; sum/rate --> output
;
; output: slewed input, with led hi while slewing
; inputs:
; 0: input
; 1: target
; 2: rate
; 3x: sum
; 4x: saved input
; 4+: saved target
; 5x: saved rate
; 5+: flag nz = busy
;--------------------------------------------------------------
public _slew
_slew: test byte ptr var5+1[di],1 ; busy?
jnz slewa ; yes, branch
getv dl,var1 ; no, see if target=output
cmp dl,outn[di] ; /
jnz slewb ; yes, go slew
getv al,var0 ; no, see if input has changed
cmp al,var4[di] ; /
jz slewx ; yes, exit no change
;
slewb: mov var4+1[di],dl ; save target
getv al,var0 ; get input
mov var4[di],al ; save input
getv cl,var2 ; get rate
mov var5[di],cl ; save rate
;
putn dl ; target --> output
or cl,cl ; rate = 0?
jz slewx ; yes, just exit
putn al ; no, start with input --> output
mov byte ptr var5+1[di],1 ; flag busy
mul cl ; ax = input * rate
mov var3[di],ax ; set new sum
jmp short slewx ; exit
;
slewa: test byte ptr cs:loops,1 ; every other clock
jnz slewx ; branch if not even
mov ax,var3[di] ; ax = sum
mov dl,var4[di] ; dx = input
mov dh,0 ; /
sub ax,dx ; ax = sum - input
mov dl,var4+1[di] ; dx = target
add ax,dx ; ax = sum - input + target
mov var3[di],ax ; save new sum
mov cl,var5[di] ; cl = rate
div cl ; al = new sum / rate
putn al ; send to output
cmp al,dl ; output = target
jnz slewx ; no, exit
mov byte ptr var5+1[di],0 ; yes, flag not busy
;
slewx: nextv ; exit
;==============================================================
; slew over time
; formula:
; initialize:
; input * 256 --> sum; input --> output
; thereafter until sum/256 = target:
; sum - input + target --> sum
; sum/256 --> output
;
; output: slewed input, with led hi while slewing
; inputs:
; 0: input
; 1: target
; 2: rate
; 3x: sum
; 4x: saved input
; 4+: saved target
; 5x: rate countdown
; 5+: flag nz = busy
;--------------------------------------------------------------
public _xslew
_xslew: test byte ptr var5+1[di],1 ; busy?
jnz xslewa ; yes, branch
getv dl,var1 ; no, see if target=output
cmp dl,outn[di] ; /
jnz xslewb ; yes, go slew
getv al,var0 ; no, see if input has changed
cmp al,var4[di] ; /
jz xslewx ; yes, exit no change
;
xslewb: mov var4+1[di],dl ; save target
getv cl,var2 ; get rate
mov var5[di],cl ; save rate
getv al,var0 ; get input
mov var4[di],al ; save input
;
putn dl ; target --> output
or cl,cl ; rate = 0?
jz xslewx ; yes, just exit
putn al ; no, start with input --> output
mov byte ptr var5+1[di],1 ; flag busy
mov ah,al ; ax = input * 256
mov al,0 ; /
mov var3[di],ax ; set new sum
jmp short xslewx ; exit
;
xslewa: dec byte ptr var5[di] ; countdown
jnz xslewx ; /
getv al,var2 ; get rate
or al,al ; somebody make it 0?
jnz xslewc ; no, go on
getv al,var1 ; yes, set output to target
mov dl,al ; ...short cut
jmp short xslewz ; exit finished
;
xslewc: mov var5[di],al ; save rate count
mov ax,var3[di] ; ax = sum
mov dl,var4[di] ; dx = input
mov dh,0 ; /
sub ax,dx ; ax = sum - input
mov dl,var4+1[di] ; dx = target
add ax,dx ; ax = sum - input + target
mov var3[di],ax ; save new sum
mov al,ah ; al = new sum / 256
xslewz: putn al ; send to output
cmp al,dl ; output = target
jnz xslewx ; no, exit
mov byte ptr var5+1[di],0 ; yes, flag not busy
;
xslewx: nextv ; exit
;==============================================================
; display input value in scale of CM
; inputs: 0: value to be displayed
; outputs: none
;--------------------------------------------------------------
public _noter
_noter:
mov colr,yellow ; set value color
getv al,var0 ; get the input value
mov es,4[di] ; get seg addr
mov bx,6[di] ; get module screen address
add bx,318 ; point to readout
call tonote ; do it
mov colr,green ; restore to green again
nextx
;==============================================================
_TEXT ENDS
END