; LarkSlave.dsm ; Code for Lark Slave processor ; L. Stewart June 29, 1982 3:59 PM ; There are 8 copies of the basic code ( 8 x loop unrolled) because different ; things happen at the beginning of each loop ; Loop 0 ; read InGain, OutGain ; write sample pointer ; maybe write silence value (end of packet only) ; Loop 1 ; Read OutBuf1 ; Loop 2 ; Read OutBuf2 ; Loop 3 ; Read OutBuf3 ; Loop 4 ; write InBuf ; Loop 5 ; write zeros in OutBuf1 ; CLD ; Loop 6 ; write zeros in OutBuf2 ; Loop 7 ; write zeros in OutBuf3 ; There is a region of the Slave ROM which contains interleaved 256 byte ; tables (or a single 256 word table). This table, whose base is at OutGain, ; converts a u255 coded byte to a 16 bit two's complement value. ; There are a number of these tables, the main CPU tells the Slave which one ; to use by changing the pointer stored in OutGain ; There is a region of the slave ROM which translates from the two's ; complement value system back to u255. The table is 2048 bytes ; long and converts from positive values only. Negative values are ; handled by converting to positive. The output shift register is ; assigned two addresses, one of them, OSRNegPort, has the side effect ; of setting the U255 sign bit. ; There are a number of 256 byte tables in the ROM. Those at SilenceLoc ; and SilenceLoc+1 are the low and high bytes, respectively, of ; the silence detection value for the given shift register contents. ; These two tables are interleaved ( a word table ). ; The other tables, found at locations passed in InGain, ; contain the shift register value attenuated by 0 dB, 5 dB, 10 dB etc. ; These latter tables are maps from U255 spoace to U255 space. ; There is an EQU only for the high byte of SilenceLoc, since the silence detection ; code takes advantage of there being no dependence on the sign of the sample. ; 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 InBuf EQU 0C000H OutBuf1 EQU 0C200H OutBuf2 EQU 0C400H OutBuf3 EQU 0C600H InGain EQU 0C800H OutGain EQU 0C802H BufPtr EQU 0C804H SilVal EQU 0C806H ; constants for testing LastIL EQU 320 HalfIL EQU 160 ; addresses in local memory SPIN EQU 03FF0H ; 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 samples being read or writted this loop TS1In DB ? TS1Out DB ? TS13In DB ? TS13Out DB ? ; 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 SOut3 LABEL BYTE SO3L3 DB ? SO3L4 DB ? SO3L5 DB ? SO3L6 DB ? SO3L7 DB ? SO3L0 DB ? SO3L1 DB ? SO3L2 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 SIn LABEL BYTE SIL4 DB ? SIL5 DB ? SIL6 DB ? SIL7 DB ? SIL0 DB ? SIL1 DB ? SIL2 DB ? SIL3 DB ? ; Save area for input and output gain addresses SIGain DW ? SOGain DW ? C_DATA ENDS ASSUME CS:C_CODE,DS:C_DATA,SS:C_DATA,ES:C_DATA 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 ; read InGain and OutGain ; write BufBtr ; write SilVal on wraparound MidPkt: MOV SI,InGain MOV DI,OFFSET SIGain WAIT MOVSW ; read InGain MOVSW ; read OutGain MOV [SI],BP ; store pointer (was in BP) JMP StartL0 EndPkt: MOV SI,InGain MOV DI,OFFSET SIGain WAIT MOVSW ; read InGain MOVSW ; read OutGain MOV [SI],BP ; store pointer (was in BP) MOV [2+SI],DX ; store SilVal XOR DX,DX StartL0: ; Loop 0, label is xxxL0 MOV BX,TS1IGain IN AL,ISRPort ; must be after end of TS1 XLATB MOV IB1,AL MOV BX,TS13OGain MOV AL,OTS1 XLATB OUT OSRPort,AL ; wait for TSN MOV BX,TS1IGain IN AL,ISRPort ; must be after end of TS1 XLATB MOV IB1,AL MOV BX,TS13OGain MOV AL,OTS1 XLATB OUT OSRPort,AL EndL0: ; LOOP 1 ; read 4 words from outbuf 1 MOV SI,OutBuf1 ADD SI,BP MOV DI,OFFSET SOut1 MOV CX,4 WAIT REP MOVSW ; Loop 1, label is xxxL1 IN AL,ISRPort MOV BL,AL SHL BX,1 MOV BH,SilLocHi ADD DX,[BX] ; add to silence reg. MOV BX,SIGain XLATB ; get sample, with gain MOV SIL1,AL ; sample to input save area NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP MOV DI,SOGain MOV BL,SO1L1 XOR BH,BH SHL BX,1 MOV AX,[DI][BX] ; first MOV, others ADD MOV BL,SO2L1 XOR BH,BH SHL BX,1 ADD AX,[DI][BX] MOV BL,SO3L1 XOR BH,BH SHL BX,1 ADD AX,[DI][BX] JNS PosL1 NEG AX TEST AX,0F800H ; Check for underflow JNZ UFlowL1 MOV BX,AX MOV AL,[MuTbl+BX] OR AL,080H OUT OSRNegPort,AL JMP EndL1 UFlowL1: MOV AL,NegMaxMuVal ; smallest mu-law OUT OSRNegPort,AL JMP EndL1 PosL1: TEST AX,0F800H ; Check for underflow JNZ OFlowL1 MOV BX,AX MOV AL,[MuTbl+BX] OUT OSRPosPort,AL JMP EndL1 OFlowL1: MOV AL,MaxMuVal ; largest mu-law OUT OSRPosPort,AL EndL1: ; LOOP 2 ; read 4 words from outbuf 2 MOV SI,OutBuf2 ADD SI,BP MOV DI,OFFSET SOut2 MOV CX,4 WAIT REP MOVSW ; Loop 2, label is xxxL2 IN AL,ISRPort MOV BL,AL SHL BX,1 MOV BH,SilLocHi ADD DX,[BX] ; add to silence reg. MOV BX,SIGain XLATB ; get sample, with gain MOV SIL2,AL ; sample to input save area NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP MOV DI,SOGain MOV BL,SO1L2 XOR BH,BH SHL BX,1 MOV AX,[DI][BX] ; first MOV, others ADD MOV BL,SO2L2 XOR BH,BH SHL BX,1 ADD AX,[DI][BX] MOV BL,SO3L2 XOR BH,BH SHL BX,1 ADD AX,[DI][BX] JNS PosL2 NEG AX TEST AX,0F800H ; Check for underflow JNZ UFlowL2 MOV BX,AX MOV AL,[MuTbl+BX] OR AL,080H OUT OSRNegPort,AL JMP EndL2 UFlowL2: MOV AL,NegMaxMuVal ; smallest mu-law OUT OSRNegPort,AL JMP EndL2 PosL2: TEST AX,0F800H ; Check for underflow JNZ OFlowL2 MOV BX,AX MOV AL,[MuTbl+BX] OUT OSRPosPort,AL JMP EndL2 OFlowL2: MOV AL,MaxMuVal ; largest mu-law OUT OSRPosPort,AL EndL2: ; LOOP 3 ; read 4 words from outbuf 3 MOV SI,OutBuf3 ADD SI,BP MOV DI,OFFSET SOut3 MOV CX,4 WAIT REP MOVSW ; Loop 3, label is xxxL3 IN AL,ISRPort MOV BL,AL SHL BX,1 MOV BH,SilLocHi ADD DX,[BX] ; add to silence reg. MOV BX,SIGain XLATB ; get sample, with gain MOV SIL3,AL ; sample to input save area NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP MOV DI,SOGain MOV BL,SO1L3 XOR BH,BH SHL BX,1 MOV AX,[DI][BX] ; first MOV, others ADD MOV BL,SO2L3 XOR BH,BH SHL BX,1 ADD AX,[DI][BX] MOV BL,SO3L3 XOR BH,BH SHL BX,1 ADD AX,[DI][BX] JNS PosL3 NEG AX TEST AX,0F800H ; Check for underflow JNZ UFlowL3 MOV BX,AX MOV AL,[MuTbl+BX] OR AL,080H OUT OSRNegPort,AL JMP EndL3 UFlowL3: MOV AL,NegMaxMuVal ; smallest mu-law OUT OSRNegPort,AL JMP EndL3 PosL3: TEST AX,0F800H ; Check for underflow JNZ OFlowL3 MOV BX,AX MOV AL,[MuTbl+BX] OUT OSRPosPort,AL JMP EndL3 OFlowL3: MOV AL,MaxMuVal ; largest mu-law OUT OSRPosPort,AL EndL3: ; LOOP 4 ; move 4 words from input save area to shared memory MOV SI,OFFSET SIn MOV DI,InBuf ADD DI,BP MOV CX,4 WAIT REP MOVSW ; Loop 4, label is xxxL4 IN AL,ISRPort MOV BL,AL SHL BX,1 MOV BH,SilLocHi ADD DX,[BX] ; add to silence reg. MOV BX,SIGain XLATB ; get sample, with gain MOV SIL4,AL ; sample to input save area NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP MOV DI,SOGain MOV BL,SO1L4 XOR BH,BH SHL BX,1 MOV AX,[DI][BX] ; first MOV, others ADD MOV BL,SO2L4 XOR BH,BH SHL BX,1 ADD AX,[DI][BX] MOV BL,SO3L4 XOR BH,BH SHL BX,1 ADD AX,[DI][BX] JNS PosL4 NEG AX TEST AX,0F800H ; Check for underflow JNZ UFlowL4 MOV BX,AX MOV AL,[MuTbl+BX] OR AL,080H OUT OSRNegPort,AL JMP EndL4 UFlowL4: MOV AL,NegMaxMuVal ; smallest mu-law OUT OSRNegPort,AL JMP EndL4 PosL4: TEST AX,0F800H ; Check for underflow JNZ OFlowL4 MOV BX,AX MOV AL,[MuTbl+BX] OUT OSRPosPort,AL JMP EndL4 OFlowL4: MOV AL,MaxMuVal ; largest mu-law OUT OSRPosPort,AL EndL4: ; LOOP 5 ; write 4 zeros to outbuf 1 XOR AX,AX MOV DI,OutBuf1 ADD DI,BP MOV CX,4 WAIT REP STOSW CLD ; Loop 5, label is xxxL5 IN AL,ISRPort MOV BL,AL SHL BX,1 MOV BH,SilLocHi ADD DX,[BX] ; add to silence reg. MOV BX,SIGain XLATB ; get sample, with gain MOV SIL5,AL ; sample to input save area NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP MOV DI,SOGain MOV BL,SO1L5 XOR BH,BH SHL BX,1 MOV AX,[DI][BX] ; first MOV, others ADD MOV BL,SO2L5 XOR BH,BH SHL BX,1 ADD AX,[DI][BX] MOV BL,SO3L5 XOR BH,BH SHL BX,1 ADD AX,[DI][BX] JNS PosL5 NEG AX TEST AX,0F800H ; Check for underflow JNZ UFlowL5 MOV BX,AX MOV AL,[MuTbl+BX] OR AL,080H OUT OSRNegPort,AL JMP EndL5 UFlowL5: MOV AL,NegMaxMuVal ; smallest mu-law OUT OSRNegPort,AL JMP EndL5 PosL5: TEST AX,0F800H ; Check for underflow JNZ OFlowL5 MOV BX,AX MOV AL,[MuTbl+BX] OUT OSRPosPort,AL JMP EndL5 OFlowL5: MOV AL,MaxMuVal ; largest mu-law OUT OSRPosPort,AL EndL5: ; LOOP 6 ; write 4 zeros to outbuf 2 XOR AX,AX MOV DI,OutBuf2 ADD DI,BP MOV CX,4 WAIT REP STOSW ; Loop 6, label is xxxL6 IN AL,ISRPort MOV BL,AL SHL BX,1 MOV BH,SilLocHi ADD DX,[BX] ; add to silence reg. MOV BX,SIGain XLATB ; get sample, with gain MOV SIL6,AL ; sample to input save area NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP MOV DI,SOGain MOV BL,SO1L6 XOR BH,BH SHL BX,1 MOV AX,[DI][BX] ; first MOV, others ADD MOV BL,SO2L6 XOR BH,BH SHL BX,1 ADD AX,[DI][BX] MOV BL,SO3L6 XOR BH,BH SHL BX,1 ADD AX,[DI][BX] JNS PosL6 NEG AX TEST AX,0F800H ; Check for underflow JNZ UFlowL6 MOV BX,AX MOV AL,[MuTbl+BX] OR AL,080H OUT OSRNegPort,AL JMP EndL6 UFlowL6: MOV AL,NegMaxMuVal ; smallest mu-law OUT OSRNegPort,AL JMP EndL6 PosL6: TEST AX,0F800H ; Check for underflow JNZ OFlowL6 MOV BX,AX MOV AL,[MuTbl+BX] OUT OSRPosPort,AL JMP EndL6 OFlowL6: MOV AL,MaxMuVal ; largest mu-law OUT OSRPosPort,AL EndL6: ; LOOP 7 ; write 4 zeros to outbuf 3 XOR AX,AX MOV DI,OutBuf3 ADD DI,BP MOV CX,4 WAIT REP STOSW ; Loop 7, label is xxxL7 IN AL,ISRPort MOV BL,AL SHL BX,1 MOV BH,SilLocHi ADD DX,[BX] ; add to silence reg. MOV BX,SIGain XLATB ; get sample, with gain MOV SIL7,AL ; sample to input save area NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP MOV DI,SOGain MOV BL,SO1L7 XOR BH,BH SHL BX,1 MOV AX,[DI][BX] ; first MOV, others ADD MOV BL,SO2L7 XOR BH,BH SHL BX,1 ADD AX,[DI][BX] MOV BL,SO3L7 XOR BH,BH SHL BX,1 ADD AX,[DI][BX] JNS PosL7 NEG AX TEST AX,0F800H ; Check for underflow JNZ UFlowL7 MOV BX,AX MOV AL,[MuTbl+BX] OR AL,080H OUT OSRNegPort,AL JMP EndL7 UFlowL7: MOV AL,NegMaxMuVal ; smallest mu-law OUT OSRNegPort,AL JMP EndL7 PosL7: TEST AX,0F800H ; Check for underflow JNZ OFlowL7 MOV BX,AX MOV AL,[MuTbl+BX] OUT OSRPosPort,AL JMP EndL7 OFlowL7: MOV AL,MaxMuVal ; largest mu-law OUT OSRPosPort,AL 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 C_CODE ENDS END