Category : Miscellaneous Language Source Code
Archive   : NEC-V20.ZIP
Filename : FILTER.ASM

 
Output of file : FILTER.ASM contained in archive : NEC-V20.ZIP
$TITLE(DSP Benchmark - Eighth Order Cascaded Digital Filter)

NAME FILTER

;-------------------------------------------------------------------------------:
; :
; This benchmark comes from an article in the 2/81 issue of IEEE Micro :
; by Nagle and Nelson. It implements the digital filter found in the :
; accompanying article that begins on page 32 and benchmarks a variety :
; of 16 bit processors. This is the version for the 8086. :
; :
;-------------------------------------------------------------------------------:
$INCLUDE(\SIII\VSERIES.MAC)

CODE SEGMENT WORD PUBLIC

EXTRN EPILOGUE : NEAR, PROLOGUE : NEAR, PUTS : NEAR

ORG 0100H

ASSUME CS:CODE, DS:CODE, ES:CODE, SS:CODE

MAIN PROC NEAR

;
; Begin by determining if the processor is a V20/V30 or a 8086/8088.
; In this case, a V20/V30 with set the least significant bit of the CW
; register, while an 8086/8088 will execute a POP CS and a SBC with an
; immediate operand. Since CW is cleared to begin with, if the contents
; of CW are not zero the processor must be a V20/V30.
;

MOV V20_V30, -1 ; Assume a V20/V30 microprocessor

PUSH CS ; Push the PS on stack

XOR CX, CX ; Clear the CW register
SET1 CX, 0 ; Execute the determining instruction

OR CX, CX ; Test if CW has changed value
JNZ VSERIES ; Continue with the V-Series demonstration

MOV V20_V30, 0 ; Set the V-Series flag
JMP UPD8086 ; And continue

VSERIES:
POP AX ; Restore the stack
; No pop was performed by V-Series processor

UPD8086:
MOV DX, OFFSET FILTER_STR ; Display the benchmark message
CALL PUTS

CALL PROLOGUE ; Initialize the demo

CALL INIT ; Perform the filter initialization

MOV CX, 20000 ; Do 20000 iterations

NEXT:
PUSH CX

CALL FILTER ; Perform a filter iteration

POP CX

LOOP NEXT

CALL EPILOGUE ; Compute the run time

INT 20H ; Return to DOS

MAIN ENDP

PUBLIC V20_V30

V20_V30 DB ?

FILTER_STR DB 'IEEE Micro (2/81) Digital Filter Benchmark (20,000 Iterations)', 13, '$'

$EJECT
;
; Declare the filter coefficients
;

A10 EQU 12484D
A11 EQU 12484D
A12 EQU 12484D
A13 EQU -14776D
A14 EQU 10847D

A20 EQU 3217D
A21 EQU 3217D
A22 EQU 3217D
A23 EQU -9825D
A24 EQU 15783D

A30 EQU 4574D
A31 EQU 4574D
A32 EQU 4574D
A33 EQU -19307D
A34 EQU 6940D

A40 EQU 7636D
A41 EQU 7636D
A42 EQU 7636D
A43 EQU -11206D
A44 EQU 14068


$EJECT
FILTER PROC NEAR

F_LOOP:
CALL INPUT ; Get the sample X(n) from the A/D converter
IMUL S0 ; Multiply by the scalar
SAL DX, 1 ; Adjust for the half value coefficients
MOV AX, DX ; Copy to AX

MOV CX, 4 ; Do four stages
CALL OUTP_1D ; Compute Y(k)

MOV PORT_2, AX ; Output Y(k) to the D/A converter

MOV CX, 4 ; Do four stages
CALL DELAY_1D ; Do the time delay

MOV CX, 4 ; Do four stages
CALL PRE_1D ; Preprocess for the next sample

RET

FILTER ENDP
$EJECT
;-------------------------------------------------------------------------------:
; :
; These functions are used by the root filter module to perform the :
; the various processing functions. :
; :
;-------------------------------------------------------------------------------:

INIT PROC NEAR

MOV AX, 0 ; Initial value of filter data
MOV CX, 20D ; Do twenty words of RAM

MOV DI, OFFSET M0 ; Point to the RAM data area
REP STOSW ; Fill with zero's

MOV PORT_1, 4000H ; Pseudo A/D input step function

RET ; Exit - Filter initialized

INIT ENDP


;
; This function returns the next input sample from the A/D input
;

INPUT PROC NEAR

MOV PORT_4, 0EH ; Issue a start A/D conversion pulse
MOV PORT_4, 0FH

IN_LP:
MOV AL, PORT_3 ; Read the A/D conversion status
AND AL, 10H ; Test for the end of the converison
JZ IN_LP ; Wait for the conversion to complete

MOV AX, PORT_1 ; Read the new sample

RET ; Exit

INPUT ENDP

;
;
;

OUTP_1D PROC NEAR

MOV SI, 0 ; Initialize the loop index
MOV DI, OFFSET M0 ; Point to the data RAM

OLP_1D:
ADD AX, T1[SI] ;
STOSW ; Store the result back
IMUL A0[SI] ; A0 * M0/2
SAL DX, 1 ; A0 * M0
ADD DX, T2[SI] ; Y
MOV AX, DX ; Y in AX
ADD SI, 2 ; Adjust the index to the next value
LOOP OLP_1D ; Continue until all done

RET ; Exit with Y(k) in AX

OUTP_1D ENDP


;
;
;

DELAY_1D PROC NEAR

MOV DI, OFFSET T1 - 2 ; Point to the M2 results
MOV SI, OFFSET M2 - 2 ; Point to the M1 results

STD ; Go backward

SAL CX, 1 ; Double the loop count
REP MOVSW ; Perform the time delay

RET ; Exit

DELAY_1D ENDP

;
;
;

PRE_1D PROC NEAR

MOV SI, OFFSET A1 ; Point to the coefficents
MOV DI, 0 ; Initialize the destination index

PLP_1D:
LODSW ; Get the coefficent A1/2
IMUL M1[DI] ; Multiply the data
MOV BX, DX ; Save a copy

LODSW ; Get cofficent A2/2
IMUL M2[DI] ; M2 * A2/2 in DX

ADD BX, DX ; T2/2
SAL BX, 1 ; T2
MOV T2[DI], BX ; Save it away

LODSW ; B1/2
IMUL M1[DI] ; M1 * B1/2
MOV BX, DX ; Save a copy

LODSW ; B2/2
IMUL M2[DI] ; M2 * B2/2

ADD BX, DX ; -T1/2
SAL BX, 1 ; -T1
NEG BX ; T1

MOV T1[DI], BX ; Save it away
ADD DI, 2 ; Increment the index
LOOP PLP_1D ; and continue

RET ; Exit

PRE_1D ENDP
$EJECT
;
; Coefficent storage
;

S0 DW 7181D

A0 DW A10, A20, A30, A40

A1 DW A11, A12, A13, A14
DW A21, A22, A23, A24
DW A31, A32, A33, A34
DW A41, A42, A43, A44

;
; RAM Data
;

M0 DW 4 DUP( 0 )
M1 DW 4 DUP( 0 )
M2 DW 4 DUP( 0 )

T1 DW 4 DUP( 0 )
T2 DW 4 DUP( 0 )

;
; Memory Mapped I/O Ports
;

PORT_1 DW ?
PORT_2 DW ?
PORT_3 DB 10H ; Returns End_of_Conversion when read
PORT_4 DB ?

CODE ENDS

END MAIN


  3 Responses to “Category : Miscellaneous Language Source Code
Archive   : NEC-V20.ZIP
Filename : FILTER.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/