; LarkSlave2io.dsm
; Code for Lark Slave processor
; L. Stewart July 9, 1982  3:42 PM

; organization of the slave EPROM
; E000 : xxxx code
; EA00 : EBFF U255 -> linear -0 dB (256 words)
; EC00 : EDFF U255 -> linear -3 dB (256 words)
; EE00 : EFFF U255 -> linear -6 dB (256 words)
; F000 : F7FF linear -> U255 table (2048 bytes)
; F800 : F9FF U255 -> silence value  (256 words)
; FA00 : FAFF U255 -> U255 -0dB (256 bytes)
; FB00 : FBFF U255 -> U255 -5dB (256 bytes)
; FC00 : FCFF U255 -> U255 -10dB (256 bytes)
; FD00 : FDFF U255 -> U255 -15dB (256 bytes)
; FE00 : FEFF U255 -> U255 -20dB (256 bytes)
; FFF0 : FFF5 long jump to 0:E000

; Constants

; Ports
ISRPort	EQU	000H
OSRPosPort EQU	004H
OSRNegPort EQU	00CH

; addresses in main memory
InBuf1	EQU	0C000H
OutBuf1	EQU	0C200H
OutBuf2	EQU	0C400H
InBuf2	EQU	0C600H
In1Gain	EQU	0C800H
In2Gain	EQU	0C802H
Sil1Val	EQU	0C804H
Sil2Val	EQU	0C806H
BufPtr	EQU	0C808H
CodeLoc	EQU	0C80AH
CodeLen	EQU	0C80EH
; constants for testing
LastIL	EQU	320
HalfIL	EQU	160
Delay	EQU	15

; addresses in local memory
RAMAdr	EQU	02000H
MaxCode	EQU	00300H		; Ram code in words
SPIN	EQU	027F0H		; initial stack pointer, top of the RAM
MuTbl	EQU	0F000H		; linear to U255, 2048 bytes
MaxMuVal EQU	07FH
NegMaxMuVal EQU	0FFH
SilLocHi EQU	0F8H		; U255 to silence value, 512 bytes

C←CODE	SEGMENT

; .ld file will set up the data segment at 02000H

C←DATA	SEGMENT

; Save area for OutBuf1
; This table is rotated by 1 because the block of 8 samples is read
; from the shared memory during Loop 1
SOut1	LABEL	BYTE
SO1L1	DB	?
SO1L2	DB	?
SO1L3	DB	?
SO1L4	DB	?
SO1L5	DB	?
SO1L6	DB	?
SO1L7	DB	?
SO1L0	DB	?

; Save area for OutBuf2
; This table is rotated by 2 because the block of 8 samples is read
; from the shared memory during Loop 2
SOut2	LABEL	BYTE
SO2L2	DB	?
SO2L3	DB	?
SO2L4	DB	?
SO2L5	DB	?
SO2L6	DB	?
SO2L7	DB	?
SO2L0	DB	?
SO2L1	DB	?

; Save area for OutBuf3
; This table is rotated by 3 because the block of 8 samples is read
; from the shared memory during Loop 3
SIn2	LABEL	BYTE
SI2L3	DB	?
SI2L4	DB	?
SI2L5	DB	?
SI2L6	DB	?
SI2L7	DB	?
SI2L0	DB	?
SI2L1	DB	?
SI2L2	DB	?

; Save area for InBuf
; This table is rotated by 4 because the block of 8 samples is written
; from the shared memory during Loop 4
SIn1	LABEL	BYTE
SI1L4	DB	?
SI1L5	DB	?
SI1L6	DB	?
SI1L7	DB	?
SI1L0	DB	?
SI1L1	DB	?
SI1L2	DB	?
SI1L3	DB	?

; Save area for gains
; Save area for input and output gain addresses
SI1Gain	DW	?
SI2Gain	DW	?
SilVal1	DW	?
SilVal2	DW	?

C←DATA	ENDS

ASSUME	CS:C←CODE,DS:C←DATA,SS:C←DATA,ES:C←DATA

; This code is at loc E000 (or 0)
	JMP	Init
	DB	0
	DW	0
	DW	0
	DW	0000CH	; NMI IP
	DW	0	; NMI CS
SlaveNMI:
	JMP	RealNMI
Init:
; set up segment registers
	MOV	AX,0
	MOV	DS,AX
	MOV	ES,AX
	MOV	SS,AX
; initialize registers for loop
	MOV	SP,SPIN		; probably don't need a stack but...
	XOR	DX,DX		; initialize silence register
	XOR	BP,BP		; initialize buffer pointer
	CLD			; string ops increment
	JMP	MidPkt
; read InGain and OutGain
; write BufBtr
; write SilVal on wraparound

MidPkt:
	MOV	SI,BufPtr
	WAIT
	MOV	[SI],BP		; store pointer (was in BP)
	JMP	StartL0

EndPkt:
	MOV	SI,OFFSET SilVal1
	MOV	DI,Sil1Val
	WAIT
	MOVSW			; store SilVal1
	MOVSW			; store SilVal2
	MOV	[SI],BP		; store pointer (was in BP)
	MOV	SilVal1,0
	MOV	SilVal2,0

StartL0:
	MOV	AL,SO2L0	; output for TS13
	TEST	AL,080H
	JNZ	Neg1L0
	OUT	OSRPosPort,AL
	JMP	In1L0
Neg1L0:
	OUT	OSRNegPort,AL
In1L0:
	IN	AL,ISRPort	; input from TS1
	MOV	CL,AL
	SHL	CX,1
	MOV	CH,SilLocHi
	MOV	BX,SI1Gain
	XLATB			; get sample, with gain
	MOV	SI1L0,AL	; sample to input save area
	MOV	AX,SilVal1
	MOV	BX,CX
	ADD	AX,[BX]		; add to silence reg.
	MOV	SilVal1,AX
; halfway
	MOV	CX,Delay
MidL0:
	LOOP	MidL0
	
	MOV	AL,SO1L0	; output for TS1
	TEST	AL,080H
	JNZ	Neg2L0
	OUT	OSRPosPort,AL
	JMP	In2L0
Neg2L0:
	OUT	OSRNegPort,AL
In2L0:
	IN	AL,ISRPort	; Input from TS13
	MOV	CL,AL
	SHL	CX,1
	MOV	CH,SilLocHi
	MOV	BX,SI2Gain
	XLATB			; get sample, with gain
	MOV	SI2L0,AL	; sample to input save area
	MOV	AX,SilVal2
	MOV	BX,CX
	ADD	AX,[BX]		; add to silence reg.
	MOV	SilVal2,AX
EndL0:

; read 4 words from outbuf 1
	MOV	SI,OutBuf1
	ADD	SI,BP
	MOV	DI,OFFSET SOut1
	MOV	CX,4
	WAIT
	REP MOVSW

StartL1:
; Loop 1, label is xxxL1
	MOV	AL,SO2L1	; output for TS13
	TEST	AL,080H
	JNZ	Neg1L1
	OUT	OSRPosPort,AL
	JMP	In1L1
Neg1L1:
	OUT	OSRNegPort,AL
In1L1:
	IN	AL,ISRPort	; input from TS1
	MOV	CL,AL
	SHL	CX,1
	MOV	CH,SilLocHi
	MOV	BX,SI1Gain
	XLATB			; get sample, with gain
	MOV	SI1L1,AL	; sample to input save area
	MOV	AX,SilVal1
	MOV	BX,CX
	ADD	AX,[BX]		; add to silence reg.
	MOV	SilVal1,AX
; halfway
	MOV	CX,Delay
MidL1:
	LOOP	MidL1
	
	MOV	AL,SO1L1	; output for TS1
	TEST	AL,080H
	JNZ	Neg2L1
	OUT	OSRPosPort,AL
	JMP	In2L1
Neg2L1:
	OUT	OSRNegPort,AL
In2L1:
	IN	AL,ISRPort	; Input from TS13
	MOV	CL,AL
	SHL	CX,1
	MOV	CH,SilLocHi
	MOV	BX,SI2Gain
	XLATB			; get sample, with gain
	MOV	SI2L1,AL	; sample to input save area
	MOV	AX,SilVal2
	MOV	BX,CX
	ADD	AX,[BX]		; add to silence reg.
	MOV	SilVal2,AX

EndL1:


; read 4 words from outbuf 2
	MOV	SI,OutBuf2
	ADD	SI,BP
	MOV	DI,OFFSET SOut2
	MOV	CX,4
	WAIT
	REP MOVSW

StartL2:
; Loop 2, label is xxxL2
	MOV	AL,SO2L2	; output for TS13
	TEST	AL,080H
	JNZ	Neg1L2
	OUT	OSRPosPort,AL
	JMP	In1L2
Neg1L2:
	OUT	OSRNegPort,AL
In1L2:
	IN	AL,ISRPort	; input from TS1
	MOV	CL,AL
	SHL	CX,1
	MOV	CH,SilLocHi
	MOV	BX,SI1Gain
	XLATB			; get sample, with gain
	MOV	SI1L2,AL	; sample to input save area
	MOV	AX,SilVal1
	MOV	BX,CX
	ADD	AX,[BX]		; add to silence reg.
	MOV	SilVal1,AX
; halfway
	MOV	CX,Delay
MidL2:
	LOOP	MidL2
	
	MOV	AL,SO1L2	; output for TS1
	TEST	AL,080H
	JNZ	Neg2L2
	OUT	OSRPosPort,AL
	JMP	In2L2
Neg2L2:
	OUT	OSRNegPort,AL
In2L2:
	IN	AL,ISRPort	; Input from TS13
	MOV	CL,AL
	SHL	CX,1
	MOV	CH,SilLocHi
	MOV	BX,SI2Gain
	XLATB			; get sample, with gain
	MOV	SI2L2,AL	; sample to input save area
	MOV	AX,SilVal2
	MOV	BX,CX
	ADD	AX,[BX]		; add to silence reg.
	MOV	SilVal2,AX
EndL2:


; move 4 words from input (2) save area to shared memory
	MOV	SI,OFFSET SIn2
	MOV	DI,InBuf2
	ADD	DI,BP
	MOV	CX,4
	WAIT
	REP MOVSW

StartL3:
; Loop 3, label is xxxL3
	MOV	AL,SO2L3	; output for TS13
	TEST	AL,080H
	JNZ	Neg1L3
	OUT	OSRPosPort,AL
	JMP	In1L3
Neg1L3:
	OUT	OSRNegPort,AL
In1L3:
	IN	AL,ISRPort	; input from TS1
	MOV	CL,AL
	SHL	CX,1
	MOV	CH,SilLocHi
	MOV	BX,SI1Gain
	XLATB			; get sample, with gain
	MOV	SI1L3,AL	; sample to input save area
	MOV	AX,SilVal1
	MOV	BX,CX
	ADD	AX,[BX]		; add to silence reg.
	MOV	SilVal1,AX
; halfway
	MOV	CX,Delay
MidL3:
	LOOP	MidL3
	
	MOV	AL,SO1L3	; output for TS1
	TEST	AL,080H
	JNZ	Neg2L3
	OUT	OSRPosPort,AL
	JMP	In2L3
Neg2L3:
	OUT	OSRNegPort,AL
In2L3:
	IN	AL,ISRPort	; Input from TS13
	MOV	CL,AL
	SHL	CX,1
	MOV	CH,SilLocHi
	MOV	BX,SI2Gain
	XLATB			; get sample, with gain
	MOV	SI2L3,AL	; sample to input save area
	MOV	AX,SilVal2
	MOV	BX,CX
	ADD	AX,[BX]		; add to silence reg.
	MOV	SilVal2,AX
EndL3:

; move 4 words from input save area to shared memory
	MOV	SI,OFFSET SIn1
	MOV	DI,InBuf1
	ADD	DI,BP
	MOV	CX,4
	WAIT
	REP MOVSW

StartL4:
; Loop 4, label is xxxL4
	MOV	AL,SO2L4	; output for TS13
	TEST	AL,080H
	JNZ	Neg1L4
	OUT	OSRPosPort,AL
	JMP	In1L4
Neg1L4:
	OUT	OSRNegPort,AL
In1L4:
	IN	AL,ISRPort	; input from TS1
	MOV	CL,AL
	SHL	CX,1
	MOV	CH,SilLocHi
	MOV	BX,SI1Gain
	XLATB			; get sample, with gain
	MOV	SI1L4,AL	; sample to input save area
	MOV	AX,SilVal1
	MOV	BX,CX
	ADD	AX,[BX]		; add to silence reg.
	MOV	SilVal1,AX
; halfway
	MOV	CX,Delay
MidL4:
	LOOP	MidL4
	
	MOV	AL,SO1L4	; output for TS1
	TEST	AL,080H
	JNZ	Neg2L4
	OUT	OSRPosPort,AL
	JMP	In2L4
Neg2L4:
	OUT	OSRNegPort,AL
In2L4:
	IN	AL,ISRPort	; Input from TS13
	MOV	CL,AL
	SHL	CX,1
	MOV	CH,SilLocHi
	MOV	BX,SI2Gain
	XLATB			; get sample, with gain
	MOV	SI2L4,AL	; sample to input save area
	MOV	AX,SilVal2
	MOV	BX,CX
	ADD	AX,[BX]		; add to silence reg.
	MOV	SilVal2,AX
EndL4:

; write 4 zeros to outbuf 1
	XOR	AX,AX
	MOV	DI,OutBuf1
	ADD	DI,BP
	MOV	CX,4
	WAIT
	REP STOSW
	CLD

StartL5:
; Loop 5, label is xxxL5
	MOV	AL,SO2L5	; output for TS13
	TEST	AL,080H
	JNZ	Neg1L5
	OUT	OSRPosPort,AL
	JMP	In1L5
Neg1L5:
	OUT	OSRNegPort,AL
In1L5:
	IN	AL,ISRPort	; input from TS1
	MOV	CL,AL
	SHL	CX,1
	MOV	CH,SilLocHi
	MOV	BX,SI1Gain
	XLATB			; get sample, with gain
	MOV	SI1L5,AL	; sample to input save area
	MOV	AX,SilVal1
	MOV	BX,CX
	ADD	AX,[BX]		; add to silence reg.
	MOV	SilVal1,AX
; halfway
	MOV	CX,Delay
MidL5:
	LOOP	MidL5
	
	MOV	AL,SO1L5	; output for TS1
	TEST	AL,080H
	JNZ	Neg2L5
	OUT	OSRPosPort,AL
	JMP	In2L5
Neg2L5:
	OUT	OSRNegPort,AL
In2L5:
	IN	AL,ISRPort	; Input from TS13
	MOV	CL,AL
	SHL	CX,1
	MOV	CH,SilLocHi
	MOV	BX,SI2Gain
	XLATB			; get sample, with gain
	MOV	SI2L5,AL	; sample to input save area
	MOV	AX,SilVal2
	MOV	BX,CX
	ADD	AX,[BX]		; add to silence reg.
	MOV	SilVal2,AX
EndL5:

; write 4 zeros to outbuf 2
	XOR	AX,AX
	MOV	DI,OutBuf2
	ADD	DI,BP
	MOV	CX,4
	WAIT
	REP STOSW

StartL6:
; Loop 6, label is xxxL6
	MOV	AL,SO2L6	; output for TS13
	TEST	AL,080H
	JNZ	Neg1L6
	OUT	OSRPosPort,AL
	JMP	In1L6
Neg1L6:
	OUT	OSRNegPort,AL
In1L6:
	IN	AL,ISRPort	; input from TS1
	MOV	CL,AL
	SHL	CX,1
	MOV	CH,SilLocHi
	MOV	BX,SI1Gain
	XLATB			; get sample, with gain
	MOV	SI1L6,AL	; sample to input save area
	MOV	AX,SilVal1
	MOV	BX,CX
	ADD	AX,[BX]		; add to silence reg.
	MOV	SilVal1,AX
; halfway
	MOV	CX,Delay
MidL6:
	LOOP	MidL6
	
	MOV	AL,SO1L6	; output for TS1
	TEST	AL,080H
	JNZ	Neg2L6
	OUT	OSRPosPort,AL
	JMP	In2L6
Neg2L6:
	OUT	OSRNegPort,AL
In2L6:
	IN	AL,ISRPort	; Input from TS13
	MOV	CL,AL
	SHL	CX,1
	MOV	CH,SilLocHi
	MOV	BX,SI2Gain
	XLATB			; get sample, with gain
	MOV	SI2L6,AL	; sample to input save area
	MOV	AX,SilVal2
	MOV	BX,CX
	ADD	AX,[BX]		; add to silence reg.
	MOV	SilVal2,AX
EndL6:

; save pointer
	MOV	SI,In1Gain
	MOV	DI,OFFSET SI1Gain
	WAIT
	MOVSW			; read In1Gain
	MOVSW			; read In2Gain
	WAIT
; wait 8 microseconds
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
StartL7:
; Loop 7, label is xxxL7
	MOV	AL,SO2L7	; output for TS13
	TEST	AL,080H
	JNZ	Neg1L7
	OUT	OSRPosPort,AL
	JMP	In1L7
Neg1L7:
	OUT	OSRNegPort,AL
In1L7:
	IN	AL,ISRPort	; input from TS1
	MOV	CL,AL
	SHL	CX,1
	MOV	CH,SilLocHi
	MOV	BX,SI1Gain
	XLATB			; get sample, with gain
	MOV	SI1L7,AL	; sample to input save area
	MOV	AX,SilVal1
	MOV	BX,CX
	ADD	AX,[BX]		; add to silence reg.
	MOV	SilVal1,AX
; halfway
	MOV	CX,Delay
MidL7:
	LOOP	MidL7
	
	MOV	AL,SO1L7	; output for TS1
	TEST	AL,080H
	JNZ	Neg2L7
	OUT	OSRPosPort,AL
	JMP	In2L7
Neg2L7:
	OUT	OSRNegPort,AL
In2L7:
	IN	AL,ISRPort	; Input from TS13
	MOV	CL,AL
	SHL	CX,1
	MOV	CH,SilLocHi
	MOV	BX,SI2Gain
	XLATB			; get sample, with gain
	MOV	SI2L7,AL	; sample to input save area
	MOV	AX,SilVal2
	MOV	BX,CX
	ADD	AX,[BX]		; add to silence reg.
	MOV	SilVal2,AX
EndL7:
; now complete the work
	ADD	BP,8
	CMP	BP,LastIL	; 320
	JGE	AllDone
	CMP	BP,HalfIL	; 160
	JE	HalfDone
	JMP	MidPkt
	
AllDone:
	XOR	BP,BP
HalfDone:
	JMP	EndPkt

RealNMI:
; set up segment registers
	MOV	AX,0
	MOV	DS,AX
	MOV	ES,AX
	MOV	SS,AX
; initialize registers for loop
	MOV	SP,SPIN		; probably don't need a stack but...
	CLD
	MOV	DI,RAMAdr	; address of RAM
	MOV	BX,CodeLoc
	MOV	SI,[BX]
	MOV	BX,CodeLen
	MOV	CX,[BX]
	CMP	CX,MaxCode
	JBE	LenOK
	MOV	CX,MaxCode
LenOk:
	REP MOVSW
	MOV	BX,RAMAdr
	JMP	BX

C←CODE	ENDS
	END