File: FPEAK.MC of Tape: Various/ETH/eth11-3
(Source file text)
.TITLE THE PEAK PROCESSING SUBROUTINE(PEAK) ;LABORATORY SUBROUTINES ;DEC-11 ;FILENAME FPEAK.MAC ;FILE ID FPEAK.1 .CSECT FPEAK ; COPYRIGHT (C) 1976 BY ; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. ; ; ;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED ;ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE ;INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER ;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY ;OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY ;TRANSFERRED. ; ;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE ;AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT ;CORPORATION. ; ;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS ;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL. ; ; ; ;LDP SOFTWARE DEVELOPMENT GROUP SEPTEMBER, 1977. .SBTTL CONDITIONALS ;CONDITIONAL ASSEMBLY PARAMETERS ; DEFINE PARAMETERS BY REMOVING FIRST ";" IN LINE WHICH ; PRECEEDS THE APPROPRIATE PARAMETER. ;EIS=1 ;EAE=1 ;AUTOG$=1 .IFDF EAE DIV=177300 AC=DIV+2 MQ=AC+2 MUL=MQ+2 EAESR=MUL+3 .ENDC ;CONDITIONAL ASSEMBLY PARAMETER DESCRIPTIONS ;EIS "EIS" SHOULD BE DEFINED IF EIS(KE11-E) HARDWARE IS AVAILABLE ; ON THE SYSTEM WHERE THIS SOFTWARE IS TO BE USED. IF NOT DEFINED, ; SUBROUTINES WHICH MIMIC THE REQUIRED FUNCTIONS OF THIS HARDWARE ; ARE ASSEMBLED AND SUBSTITUTED. ; ;EAE "EAE" SHOULD BE DEFINED IF EIS HARDWARE IS NOT AVAILABLE BUT ; THE EAE IS. ; NOTE: IF EAE HARDWARE IS AVAILABLE AND IS TO BE USED, THE ; DEFAULT ADDRESSES ASSOCIATED WITH THE DEVICE ARE USED. ; IF YOUR "EAE" IS NOT INSTALLED AT THE NORMAL LOCATIONS ; THE DEFAULT ADDRESSES OF THE STATUS WORDS SHOULD BE ; MODIFIED TO REFLECT THIS DESCREPENCY BY REDEFINING "DIV" ; BY EDITING THIS FILE AND SETTING IT EQUAL TO THE STARTING ; ADDRESS OF THE STATUS WORDS ASSOCIATED WITH THE "EAE". ; ;AUTOG$ THIS SUBROUTINE IS GREATLY AFFECTED BY THIS CONDITIONAL ; ASSEMBLY PARAMETER. ; IF DEFINED, THE DATA WILL ALWAYS BE HANDLED IN THE PROCESSING ; PORTION OF THE ROUTINE AS IF THE DATA WAS OBTAINED VIA AUTO- ; GAINING, THUS HAVING A POSSIBILITY OF EIGHTEEN(18) BIT ; SIGNIFICANCE, EVEN THOUGH THE ACTUAL DATA MAY BE EITHER ; AUTO-GAINED DATA OR 12-BIT NON-AUTO-GAINED DATA DEPENDING ; ON THE EIGHTH VALUE IN THE PARAMETER TABLE. SEE OPERATING ; MANUAL. ; .IF DF,AUTOG$ OFSET=4 .IFF OFSET=2 .ENDC .SBTTL MACROS,GLOBALS R0=%0 R1=%1 R2=%2 R3=%3 R4=%4 R5=%5 SP=%6 PC=%7 ;INTERNAL GLOBAL .GLOBL PEAK ;MACROS .MACRO $MUL SRC,RX .IFDF EIS MUL SRC,RX .IFF .NTYPE .SYM,RX .IIF NE .SYM .ERROR ;REGISTER MUST BE R0 .IF NB SRC .IIF DIF SRC,R1 MOV SRC,R1 .ENDC JSR PC,MULR0 .ENDC .ENDM .MACRO $DIV SRC,RX .IFDF EIS DIV SRC,RX .IFF .NTYPE .SYM,RX .IIF NE .SYM,.ERROR ;REGISTER MUST BE R0 .IF NB SRC .IIF DIF SRC,-(SP) MOV SRC,-(SP) .ENDC JSR PC,DIVR0 .ENDC .ENDM .SBTTL MULR0,DIVR0 .IFNDF EIS ;MULR0 SUBROUTINE TO SERVE $MUL SRC,REG MACRO ;USED TO SIMULATE THE INTEGER MULTIPLY INSTRUCTION WHEN THE USER ;DOES NOT HAVE THE EXTENDED INSTRUCTION SET (EIS). ;CALLED BY THE FOLLOWING ; MOV SRC,R1 ; JSR PC,MULR0 ; RETURNS HIGH PRODUCT IN R0, LOW IN R1 ;ON RETURN ONLY C-BIT OF CONDITION CODES IS MEANINGFUL ;C=1 IMPLIES MORE THAN 16-BIT PRODUCT, C=0 IMPLIES SINGLE PREC. OK ;THE MACRO $MUL SRC,REG WILL ALSO GENERATE THIS CALLING SEQUENCE ;WHEN THE CONDITIONAL ASSEMBLY PARAMETER 'EIS' IS NOT DEFINED. MULR0: .IFDF EAE MOV R1,@#MQ ;PUT 1ST NUMBER IN MQ MOV R0,@#MUL ;MULTIPLY BY SECOND NUMBER MOV @#MQ,R1 ;LOW ORDER PRODUCT MOV @#AC,R0 ;HIGH ORDER PRODUCT CLC BITB #2,@#EAESR ;TEST FOR SINGLE PRECISION BNE 1$ SEC ;C=0 IMPLIES 16-BIT PRODUCT OK 1$: RTS PC .ENDC .IFNDF EAE MOV R2,-(SP) ;PUSH TWO REGISTERS AND A FLAG MOV R4,-(SP) CLR -(SP) TST R0 ;CHECK SIGNS BPL 2$ NEG R0 ;TAKE ABSOLUTE VALUES INC @SP ;AND FLAG NEGATIONS 2$: TST R1 BPL 4$ NEG R1 DEC @SP ;MINUS*MINUS=PLUS 4$: MOV #17.,R2 ;COUNT ITERATIONS CLR R4 ;HIGH ORDER PRODUCT BUILT HERE 6$: CLC ;CLEAR CARRY FOR ROTATES ROR R4 ;SHIFT MULTIPLIER AND PARTIAL PRODUCT ROR R1 BCC 8$ ;NO ADD NEEDED ADD R0,R4 8$: DEC R2 ;COUNT ITERATION BGT 6$ TST R4 ;WAS RESULT DOUBLE? BNE 10$ ;YES CMP R1,#100000 ;MAYBE BLO 12$ ;DEFINITELY NOT BHI 10$ ;DEFINITELY TST @SP ;SPECIAL CASE -2**15 OK BNE 12$ ;YES 10$: COM R2 ;USE THIS AS CARRY FLAG 12$: TST (SP)+ ;IS RESULT TO BE NEGATED? BEQ 14$ ;NO NEG R4 ;YES NEG R1 SBC R4 14$: MOV R4,R0 ASR R2 ;SET CARRY BIT FOR TWO WORD CASE MOV (SP)+,R4 ;RST REG MOV (SP)+,R2 RTS PC .ENDC ;DIVR0 32 BY 16 BIT DIVIDE TO SUPPORT MACRO $DIV SRC,R0 ;CALLED BY USING THE MACRO $DIV SRC,R0 ;WHICH EXPANDS TO THE FOLLOWING WHEN EIS IS NOT AVAILABLE: ; MOV SRC,-(SP) ; JSR PC,DIVR0 ; ON RETURN R0 CONTAINS QUOTIENT, R1 CONTAINS REMAINDER ; SIGN OF REMAINDER SAME AS SIGN OF DIVIDEND ; CONDITION CODES N AND V CORRECTLY SET, Z AND C NOT DIVR0: .IFDF EAE MOV R1,@#MQ ;LOW ORDER DIVEND MOV R0,@#AC ;HIGH ORDER DIFIDEND MOV 2(SP),@#DIV ;DIVIDE MOV (SP)+,@SP ;PUT RETURN ADDR WHERE NEEDED MOV @#MQ,R0 ;QUOTIENT MOV @#AC,R1 ;REMAINDER ROLB @#EAESR ;SET N AND V RTS PC .ENDC .IFNDF EAE MOV 2(SP),-(SP) ;GET SOURCE MOV 2(SP),4(SP) ;PUT RETURN WHERE NEEDED MOV R2,2(SP) ;FREE A REGISTER MOV (SP)+,R2 ;AND FILL IT WITH SOURCE MOV R3,-(SP) ;SAVE ANOTHER REGISTER CLR -(SP) ;SET UP A SIGN CONTROL WORD TST R0 BGE 1$ DECB 1(SP) ;KEEP TRACK OF THE ORIGINAL NEG R0 ;SIGN AND NEGATE NEG R1 ;THE ORIGINAL NUMBER SBC R0 ; I 1$: TST R2 BEQ 12$ ;DIVISION BY ZERO IS A NO-NO BGT 2$ ;-> CHECK THE SIGN INC @SP ;AND KEEP TRACK AS ABOVE NEG R2 ; I 2$: MOV R2,R3 ;<- MOVE THE DIVISOR AND NEG R3 ;NEGATE FOR THE ALGORITHM ADD R3,R0 ;PREFORM THE INITIAL SUBTRACTION BCS 12$ ;CARRY SET IS AN OVERFLOW MOV #20,-(SP) ;SET UP A COUNTER CLR -(SP) ;THIS IS A LASTING CARRY BIT 3$: ROL R1 ;ROTATE ONE LEFT ROL R0 TST @SP ;CHECK THE LAST CARRY BEQ 4$ ;IF ZERO ADD ELSE SUBTRACT CLR @SP ;CLEAR THE CARRY ADD R3,R0 ;DO ONE MORE STEP BR 5$ 4$: ADD R2,R0 ;-2N+N=N FOR THIS STEP 5$: ADC @SP ;KEEP IT A WHILE BEQ 6$ ;IF ZERO OMIT UPDATE INC R1 ;NO CARRY POSSIBLE 6$: DEC 2(SP) ;DECREMENT COUNTER BGT 3$ ;BRANCH IF MORE TO DO ROR R1 ;SEE ABOUT THE LAST CYCLE BCS 7$ ;OMIT CORRECTION IF ONE ADD R2,R0 ;CORRECT REMAINDER CLC 7$: ROL R1 ;REPLACE THE LAST BIT CMP (SP)+,(SP)+ ;POP TWO WORDS TST @SP ;TEST FOR REMAINDER CHANGES BGE 8$ ;OMIT IF POSITVE NEG R0 ;NEGATE REMAINDER CLRB 1(SP) ;CLEAR SIGN DEC @SP ;BUT DO A GOOD JOB ON QUOTIENT 8$: CMP #100000,R1 ;TEST FOR THE BUG IN THE ALGORITHM BLO 12$ ;EXIT WITH ERROR OF TOO BIG BEQ 11$ ;CHECK FOR OVERFLOW 9$: TST (SP)+ ;TEST FOR QUOTIENT ADJUSTMENT BEQ 10$ ;IF ZERO NONE NEEDED NEG R1 10$: MOV R0,R2 ;SAVE REMAINDER MOV R1,R0 ;GET QUOTIENT MOV R2,R1 ;AND REMAINDER WHERE NEEDED CLC BR 13$ ;EXIT WITH NO OVERFLOW 11$: TST @SP ;TEST FOR NEGATIVE BNE 9$ ;IF NEGATIVE, OK 12$: TST (SP)+ ;REMOVE SIGN WORD SEC ;MARK OVERFLOW 13$: MOV (SP)+,R3 ;THIS CLEARS V-BIT MOV (SP)+,R2 MOV R0,R0 ;THIS SETS Z,N BCC 14$ SEV 14$: RTS PC .ENDC .ENDC .SBTTL PARAMETER-VARIABLE TABLE OFFSETS ; THE FOLLOWING LIST OF OFFSETS INTO THE PARAMETER TABLE - SCRATCH ; AREA DEFINED BY THE ADDRESS IN REGISTER FIVE(R5) WHEN "PEAK" IS ; CALLED IS USED BY THE ROUTINE. SR=0 ;ITABLE(1), ORIGINAL POINT DENSITY WT=2 ;ITALBE(2), BASELINE TEST PARAMETER GT=4 ;ITABLE(3), NO. OF PERSIST. CHANGES TO CHANGE DIRECTION HM=6 ;ITABLE(4), MINIMUM CHANGE CONSIDERED AN INCREASE OUTTYP=HM+2 ;ITABLE(5) ;PARAMETER SPECIFIES FLOATING POINT CONVERT AS FOLLOWS ; = 0 =>LEAVE RESULTS AS DOUBLE PRECISION INTEGER ; = 1 =>CONVERT TO SINGLE PRECISION FLOATING POINT ; = -1 =>CONVERT TO DOUBLE PRECISION FLOATING POINT ERROR=OUTTYP+2 ;ITABLE(6), PARAMETER SPECIFYING CALLING ERROR ; = 0 => NO ERROR ; = N => ITABLE(N) IS IN ERROR(USUALLY NEG.) ; = -N => THE NTH ARGUMENT IN THE CALL IS ; INCORRECT ; = -8 => NOT ENOUGH ARGUMENTS IN CALL FIRSTM=ERROR+2 ;ITABLE(7), SET EQUAL ZERO MEANS INITIAL MODULE CALL .IF DF,AUTOG$ AUT=FIRSTM+2 ;PPAUTG,SET NON-ZERO FOR AUTO-GAINED INPUT .ENDC CNTR1=FIRSTM+OFSET ;NEEDED COUNTER SC=CNTR1+1 ;BASELINE TEST INCREASE COUNTER BS=SC+1 ;BASELINE SWITCH. 0=PEAK STARTED ON BASELINE ; 1=LOOK FOR PEAK WIDTH ; 2=LOOK FOR END ON BASELINE S1=BS+1 ;SWITCH SET IF DECREASING W/OUT A PREV. INCREASE S2=S1+1 ;SWITCH SET IF INCREASING AFTER A DECRES OR BASELINE Y1=S2+2 ;FIRST POINT OF ARRAY USED FOR SMOOTHING WINDOW .IF DF,AUTOG$ Y1H=Y1+2 ;HI-ORDER PART OF FIRST POINT OF ARRAY .ENDC Y2=Y1+OFSET ;SECOND POINT OF ARRAY .IF DF,AUTOG$ Y2H=Y2+2 ;HI-ORDER OF 2ND PT .ENDC Y3=Y2+OFSET ;THIRD PT .IF DF,AUTOG$ Y3H=Y3+2 .ENDC Y4=Y3+OFSET ;FOURTH PT .IF DF,AUTOG$ Y4H=Y4+2 .ENDC Y5=Y4+OFSET ;FIFTH PT .IF DF,AUTOG$ Y5H=Y5+2 .ENDC Y6=Y5+OFSET ;SIXTH PT .IF DF,AUTOG$ Y6H=Y6+2 .ENDC Y7=Y6+OFSET ;SEVENTH PT .IF DF,AUTOG$ Y7H=Y7+2 .ENDC WS=Y7+OFSET ;SWITCH TO DOUBLE DN IF RATE DECREASE IS NEEDED PTR=WS+2 ;PTR FOR INITIAL SIX POINTS NEEDED FOR DIGITAL FILTER CAL=PTR+2 ;LO-ORDER PART OF AREA ACCUM. DURING SIGNAL INCREASE CAH=CAL+2 ;HI-ORDER PART OSL=CAH+2 ;LO-ORDER PART OF OLD SLOPE MINIMUM OSH=OSL+2 ;HI-ORDER PART TML=OSH+2 ;LO-ORDER PART OF CURRENT PT COUNTER TMH=TML+2 ;HI-ORDER PART CNTR2=TMH+2 ;COUNTER OF POINTS TO AVERAGE SAV0=CNTR2+2 ;WORD TO STORE R0 WHILE WAITING FOR NEXT INPUT BUFFER SAV1=SAV0+2 ;WORD TO STORE R1 SAV6=SAV1+2 ;WORD TO STORE SP MC=SAV6+2 ;TEMPORARY COUNTER FOR # OF MINS FOUND CC=MC+2 ;TEMPORARY COUNTER FOR # OF MAXS FOUND MX=CC+2 ;CURRENT MAXIMUM .IF DF,AUTOG$ MXH=MX+2 ;HIGH ORDER PART OF CURRENT MAXIMUM .ENDC KM=MX+OFSET ;LAST CREST HEIGHT .IF DF,AUTOG$ KMH=KM+2 ;HIGH ORDER PART .ENDC CTL=KM+OFSET ;LO-ORDER PART OF TIME OF LATEST MAXIMUM CTH=CTL+2 ;HI-ORDER PART KTL=CTH+2 ;LO-ORDER PART OF PEAK LEADING MINIMUM TIME KTH=KTL+2 ;HI-ORDER PART BTL=KTH+2 ;LO-ORDER PART OF LEADING BASELINE MINIMUM TIME BTH=BTL+2 ;HI-ORDER PART BM=BTH+2 ;LEADING BASELINE MINIMUM .IF DF,AUTOG$ BMH=BM+2 ;HI-ORDER PART .ENDC SLL=BM+OFSET ;LO-ORDER PART OF NEW OR CURRENT SLOPE*1000 SLH=SLL+2 ;HI-ORDER PART OAL=SLH+2 ;LO-ORDER PART OAH=OAL+2 ;HI-ORDER PART OF AREA PH=OAH+2 ;LOW ORDER PART OF PEAK HEIGHT PHH=PH+2 ;PEAK HEIGHT (SAVED FOR OUTPUT) PTL=PHH+2 ;LO-ORDER PART PTH=PTL+2 ;HI-ORDER PART OF TIME OF PEAK (SAVED FOR OUTPUT) LMH=PTH+2 ;LO-ORDER PART LMHH=LMH+2 ;LEADING MINIMUM HEIGHT(SAVED FOR OUTPUT) LMTL=LMHH+2 ;LO-ORDER PART LMTH=LMTL+2 ;HI-ORDER PART OF TIME OR LEADING MINIMUM WDL=LMTH+2 ;LO-ORDER PART WDH=WDL+2 ;HI-ORDER PART OF WIDTH(IN SAMPLE CNTS) MN=WDH+2 ;LO-ORDER PART MNH=MN+2 ;TRAILING MINIMUM MTL=MNH+2 ;LO-ORDER PART MTH=MTL+2 ;HI-ORDER PART OF TIME OF TRAILING MINIMUM TYPE=MTH+2 ;OUTPUT PEAK TYPE INDICATOR ; =0, IMPLIES PEAK ENDED ON BASELINE ; =1, IMPLIES PEAK ENDED ON VALLEY DN=TYPE+4 ;ACTUAL DENSITY OF THE POINTS IN THE PROCESS INPUT=DN+4 ;ADDRESS OF INPUT BUFFER INSIZ=INPUT+2 ;ADDRESS OF INPUT BUFFER SIZE INPTR=INSIZ+2 ;ADDRESS OF INPUT BUFFER POINTER OUTPUT=INPTR+2 ;ADDRESS OF OUTPUT BUFFER OUTSIZ=OUTPUT+2 ;ADDRESS OF OUTPUT BUFFER SIZE IN PEAK SETS OUTPTR=OUTSIZ+2 ;ADDRESS OF OUTPUT BUFFER PEAK SET POINTER .SBTTL PEAK CALLING DESCRIPTION ;FORMAT OF FORTRAN CALL SHOULD BE AS FOLLOWS: ;CALL PEAK(ITABLE,INPUT,INLAST,INPTR,OUTPUT,IDIMO,NPEAKS) ;WHERE ;"ITABLE" IS AN INTEGER*2 ARRAY OF LENGTH 68 IF "AUTOG$" IS NOT ; DEFINED OR OF LENGTH 79 IF "AUTOG$" IS DEFINED. ; THE FIRST SEVEN, OR EIGHT IF "AUTOG$" IS DEFINED, ELEMENTS OF ; THIS ARRAY CONTAIN PARAMETERS WHICH ARE USED TO GIVE FINAL ; DEFINITION TO THE PEAK PROCESSING ALGORITHM. THEY ARE AS ; FOLLOWS: ; 1) ITABLE(1) IS A VALUE INDICATING THE NUMBER OF SAMPLES ; TO AVERAGE TO GET ONE POINT FOR THE SEVEN ; POINT DIGITAL FILTER USED IN THE ALGORITHM. ; AS THE PEAKS GROW IN WIDTH DURING THE RUN, ; THE VALUE ACTUALLY USED BY THE ALGORITHM ; WILL INCREASE BY "ITABLE(1)". ; 2) ITABLE(2) IS A VALUE USED FOR THE WIDTH TEST TO FIND ; THE BASELINE. WHEN VALUES ARE RECEIVED ; THAT ARE "ITABLE(2)"*WIDTH PAST THE PEAK ; TIME, THE BASELINE IS THEN SOUGHT. ; 3) ITABLE(3) IS A VALUE USED FOR THE DIRECTIONAL CHANGE ; INDICATOR. IT REPRESENTS THE NUMBER OF ; CONSECUTIVE MOVEMENTS BY THE DATA IN THE ; OPPOSITE DIRECTION TO CHANGE DIRECTION. ; 4) ITABLE(4) IS A VALUE REPRESENTING THE MINIMUM CHANGE ; IN INPUT UNITS TO BE CONSIDERED AN INCREASE. ; 5) ITABLE(5) THIS ELEMENT RELATES THE "DATA TYPE" OF THE ; OUTPUT ARRAY AS FOLLOWS: ; = 0 => OUTPUT ARRAY IS INTEGER*4 ; = 1 => OUTPUT ARRAY IS REAL*4 ; = -1 => OUTPUT ARRAY IS REAL*8 ; 6) ITABLE(6) THIS ELEMENT CONTAINS THE ERROR INDICATION ; ON RETURN FROM SUBROUTINE ; = 0 => NO ERROR ; = N => ITABLE(N) IS IN ERROR(USUALLY NEG.) ; = -N => THE NTH ARGUMENT IN THE CALL IS ; INCORRECT ; = -8 => NOT ENOUGH ARGUMENTS IN CALL ; !!! NOTE !!! ; IF ITABLE IS OMITTED, THE SUBROUTINE WILL CAUSE A ; FATAL MEMORY TRAP ERROR. ; ; 7) ITABLE(7) IS AN ELEMENT WHICH MUST BE ZERO ON THE ; INITIAL ENTRY TO THE SUBROUTINE. THIS TELL ; THE ROUTINE TO DO THE INITIALIZATION ; WHICH IS NEEDED ONLY ONCE. THE ROUTINE THEN ; USES THIS ELEMENT FOR REENTRY PURPOSES AND ; THUS SHOULD NOT BE USED BY THE USER AFTER ; INITIAL ENTRY IS MADE. ; IF "AUTOG$" HAS BEEN DEFINED WHEN THE MODULE WAS ASSEMBLED ; THEN: ; 8) ITABLE(8) IS AN ELEMENT WHICH INDICATES IF THE INPUT ; DATA HAS BEEN AUTOGAINED AS IN LA-11. ; A) 0 INDICATES NO AUTOGAINED INPUT. ; B) 1 INDICATES ALL AUTOGAINED INPUT. ;"INPUT" IS AN INTEGER*2 ARRAY OF LENGTH AT LEAST EQUAL TO ; "INLAST". ;"INLAST" IS AN INTEGER*2 VARIABLE EQUAL TO THE VALUE OF THE ; SUBSCRIPT OF THE LAST ELEMENT IN THE INPUT ARRAY WHICH ; CONTAINS DATA TO BE PROCESSED. ;"INPTR" IS AN INTEGER*2 VARIABLE EQUAL TO THE VALUE OF THE ; SUBSCRIPT OF THE LAST ELEMEMT IN THE "INPUT" ARRAY PROCESSED ; BY THE SUBROUTINE. ; A) WHEN A NEW "INPUT" ARRAY IS BEING PROVIDED THE ; SUBROUTINE, AS ON ORIGINAL ENTRY, "INPTR" SHOULD ; BE ZERO. ; B) WHEN A PARTIALLY PROCESSED ARRAY IS BEING PROVIDED ; THE SUBROUTINE, AS ON REENTRY AFTER THE OUTPUT ARRAY ; HAD BEEN FILLED BUT ALL PROCESSABLE ELEMENTS OF INPUT ; HAD NOT BEEN PROCESSED, "INPTR" SHOULD BE EQUAL TO THE ; SUBSCRIPT OF THE LAST ELEMENT OF "INPUT" WHICH HAS ; BEEN PROCESSED. ALTERNATIVELY, "INPTR" EQUALS THE ; SUBSCRIPT OF THE ELEMENT OF "INPUT" MINUS ONE OF THE ; NEXT ELEMENT TO BE PROCESSED. ; NOTE: ON RETURN FROM "PEAK" ONE OF TWO CONDITIONS ; EXISTS, AND "INPTR" WILL HAVE A VALUE ; INDICATING THE CONDITION AS FOLLOWS: ; 1) IF ALL ELEMENTS IN "INPUT" HAVE BEEN ; PROCESSED, "INPTR" WILL EQUAL "-1" ON ; RETURN. ; 2) IF SOME ELEMENTS IN "INPUT" HAVE NOT ; BEEN PROCESSED, "INPTR" WILL HAVE THE ; PROPER VALUE FOR REENTRY(SEE (B)). ; CAUTION!!!! ; NOTE: IF "INPTR" = -1 ON REENTRY TO THE ; ROUTINE, IT WILL DEFAULT TO A VALUE OF ; ZERO"0". ; ;"OUTPUT" IS A DOUBLE SUBCRIPTED(OR EQUIVALENT SINGLE SUBCRIPTED) ; ARRAY OF LENGTH (10,XXX) WHERE "XXX" IS AT LEAST ; "IDIMO". FOR EVERY VALUE OF THE SECOND SUBSCRIPT THERE ARE ; 10 PEAK DATA DESCRIPTOR ELEMENTS AS FOLLOWS: ; NOTE: THE DATA TYPE OF "OUTPUT" IS ASSUMED TO BE ; THAT SPECIFIED BY "ITABLE(5)". ; 1) OUTPUT(1,N) IS THE AREA OF THE NTH PEAK. ; 2) OUTPUT(2,N) IS THE HEIGHT OF THE NTH PEAK. ; 3) OUTPUT(3,N) IS THE TIME OF THE NTH PEAK. ; 4) OUTPUT(4,N) IS THE LEADING MINIMUM HEIGHT OF THE NTH ; PEAK. ; 5) OUTPUT(5,N) IS THE TIME OF THE LEADING MINIMUM. ; 6) OUTPUT(6,N) IS THE HALF WIDTH AT HALF HEIGHT OF THE ; NTH PEAK. ; 7) OUTPUT(7,N) IS THE HEIGHT OF THE TRAILING MINIMUM OF ; THE NTH PEAK. ; 8) OUTPUT(8,N) IS THE TIME OF THE TRAILING MINIMUM OF THE ; NTH PEAK. ; 9) OUTPUT(9,N) IS THE TYPE INDICATOR OF THE NTH PEAK. ; A) 0 INDICATES PEAK ENDED ON BASELINE. ; B) 1 INDICATES PEAK ENDED ON VALLEY. ; 10)OUTPUT(10,N) IS THE CURRENT NUMBER OF SAMPLES BEING ; AVERAGED TO OBTAIN A "POINT" FOR THE SEVEN ; POINT DIGITAL FILTER. ; NOTE: ALL TIMES AND WIDTHS ARE MEASURED IN ; SAMPLE PERIODS, AND ALL HEIGHTS ARE ; MEASURED IN INPUT UNITS. ;"IDIMO" IS THE NUMBER OF PEAKS THAT CAN BE DETECTED BEFORE THE ; "OUTPUT" ARRAY IS FILLED. IT IS AN INTEGER*2 VARIABLE, AND ; SERVES AS THE SECOND DIMENSION OF "OUTPUT". ;"NPEAKS" IS AN INTEGER*2 VARIABLE EQUAL TO THE LAST VALUE ; OF THE SECOND SUBSCRIPT OF "OUTPUT" USED BY THE SUBROUTINE. ; ALTERNATIVELY, IT IS THE NUMBER OF SETS OF PEAK DATA STORED ; BY THE SUBROUTINE IN THE ARRAY "OUTPUT". ; A) WHEN THE "OUTPUT" ARRAY HAS NO PEAK DATA IN IT, OR ; THE PEAK DATA HAS BEEN COPIED SO THAT DATA CAN BE ; STORED AT THE START OF THE ARRAY, "NPEAKS" SHOULD ; EQUAL ZERO. ; B) WHEN A PARTIALLY FILLED ARRAY IS BEING PROVIDED THE ; SUBROUTINE, AS ON REENTRY AFTER THE INPUT ARRAY HAS ; BEEN COMPLETELY PROCESSED BUT THE OUTPUT ARRAY WAS ; NOT FILLED, "NPEAKS" SHOULD BE SET EQUAL TO THE LAST ; VALUE OF THE SECOND SUBSCRIPT OF THE ARRAY "OUTPUT" ; WHICH POINTS TO PEAK DATA. ALTERNATIVELY, "NPEAKS" ; SHOULD BE SET EQUAL TO THE VALUE MINUS ONE OF THE ; NEXT VALUE OF THE SECOND SUBSCRIPT OF "OUTPUT" WHERE ; PEAK DATA CAN BE STORED. ; NOTE: ON RETURN FROM "PEAK" ONE OF TWO CONDITIONS ; EXISTS, AND "NPEAKS" WILL HAVE A VALUE ; INDICATING THE CONDITION AS FOLLOWS: ; 1) IF ALL ELEMENTS IN "OUTPUT" HAVE BEEN ; FILLED WITH PEAK DATA, "NPEAKS" WILL ; EQUAL (-1) ON RETURN. ; 2) IF SOME ELEMENTS IN "OUTPUT" HAVE NOT ; BEEN FILLED, "NPEAKS" WILL HAVE THE ; PROPER VALUE FOR REENTRY(SEE (B)). ; CAUTION!!!! ; NOTE: IF "NPEAKS" = -1 ON REENTRY TO THE ; ROUTINE, IT WILL DEFAULT TO A VALUE OF ; ZERO"0". .SBTTL PEAK ENTRY POINT PEAK: MOV R5,R2 ;COPY R5 MOVB (R2),R3 ;GET NO. OF ENTRIES BNE SOME ;IF NONE, TRAPER: MOV R0,1 ;IF FIRST ARGUMENT IS MISSING OR ; DEFAULTED, CAUSE A M-TRAP THROUGH 4 ; ERROR 61 IN FORTRAN ERRET: MOV R3,ERROR(R5) ;INDICATE ERROR RTS PC ;AND RETURN SOME: TST (R2)+ ;POINT TO FIRST ARG ADDRESS MOV (R2)+,R5 ;GET WORK AREA ADDRESS CMP #-1,R5 ;TEST FOR "ITABLE" PRESENT BEQ TRAPER ;IF NOT, GO TRAP OUT CLR ERROR(R5) ;CLEAR ERROR INDICATOR MOV R5,R4 ;GET COPY OF ADDRESS CMP R3,#7 ;MAKE SURE THERE ARE ENOUGH BGE 2$ ;IF ENOUGH CONTINUE MOV #-8.,R3 ;OTHERWISE, INDICATE WRONG NO. OF ARGS. BR ERRET ; AND RETURN 2$: MOV #4,R3 ;GET NO. OF PARAMETERS TO CHECK ADD #10,R4 ;POINT R4 TO 5TH ELEMENT 3$: TST -(R4) ;CHECK NEXT PARAMENTER BLE ERRET ;IF NEG, RETURN WITH ERROR DEC R3 ;AND MORE PARAMETERS TO CHECK BNE 3$ ;IF SO BRANCH ADD #INPUT,R4 ;GET ADDRESS TO STORE I/O ADDRESSES AT COM R3 ;SET R3 TO -1 INLOOP: DEC R3 MOV (R2),(R4)+ ;STORE NEXT QUANTITY CMP #-1,(R2)+ ;MAKE SURE THE ARGUMENT IS NOT DEFAULTED BEQ ERRET ;IF DEFAULTED, REPORT ERROR CMP #-7,R3 ;CHECK FOR END OF LOOP BNE INLOOP ;COUNT THEM MOV @INPTR(R5),R4 ;GET OFFSET BGE 3$ ;IF POS., IS BEING CONTROLLED BY USER CLR R4 ;OTHERWISE, DEFAULT TO START OF ARRAY 3$: ASL R4 ;IN BYTES ADD R4,INPUT(R5) ;GET INPUT BUFFER POINTING RIGHT ASR R4 ;GET POINTER BACK IN WORDS NEG R4 ; THEN PREPARE TO FIND COUNT MOV #-3,R3 ;SET R3 TO INDICATE POSSIBLE ERROR TST @INSIZ(R5) BLE ERRET ;ERROR RETURN IF ARRAY SIZE IS FAULTY DEC R3 ;IF NOT, UPDATE POSSIBLE ERROR INDICATOR ADD @INSIZ(R5),R4 ; FIND REMAINING COUNT BLE ERRET ;ERROR RETURN IF ARRAY POINTER IS FAULTY SUB #2,R3 ;UPDATE POSSIBLE ERROR INDICATOR MOV @OUTPTR(R5),R2 ;GET OUTPUT OFFSET BGE 4$ ;IF POS., IS BEING CONTROLLED BY USER CLR R2 ;OTHERWISE, DEFAULT TO START OF ARRAY BR 5$ 4$: MOV #40.,R1 ;GET REG. OUTPUT OFFSETT TST OUTTYP(R5) ;SEE IF DOUBLE PRECISION REAL BGE 1$ ;IF NOT BRANCH ASL R1 ;OTHERWISE, DOUBLE 1$: MOV R2,R0 ;GET POINTER IN MULTIPLYING REGISTER $MUL R1,R0 ADD R1,OUTPUT(R5) ;GET OUTPUT BUFFER POINTING RIGHT NEG R2 ;PREPARE TO FIND OUTPUT COUNT 5$: TST @OUTSIZ(R5) ;CHECK ARRAY SIZE BLE ERRET ;ERROR RETURN IF ARRAY SIZE IS FAULTY DEC R3 ;OTHERWISE, UPDATE POSSIBLE ERROR IND. ADD @OUTSIZ(R5),R2 ; FIND REMAINING COUNT BLE ERRET ;ERROR RETURN IF ARRAY POINTER IS FAULTY TST FIRSTM(R5) ;CHECK FOR INITIAL ENTRY BEQ INTIL ;IF SO , BRANCH CMP #IRESUM-INTIL,FIRSTM(R5) ;CHECK FOR CORRECT VALUE BEQ 2$ ;IF CORRECT , B+C CMP #ORESUM-INTIL,FIRSTM(R5) ;CHECK OTHER POSSIBILITY BEQ 2$ MOV #7,R3 ;IF NONE OF THE ABOVE, ERROR BR ERRET ;INDICATE AND RETUR 2$: MOV R2,@OUTPTR(R5) ;SAVE OUTPUT COUNT MOV R4,@INPTR(R5) ;SAVE INPUT COUNT ADD FIRSTM(R5),PC ;GO RESUME - PIC,REENTRANTLY ;COMES HERE ONLY ONCE AT THE FIRST CALL TO ;INITIALIZE VARIABLES AND PROCESSING INTIL: MOV R2,@OUTPTR(R5) ;SAVE OUTPUT COUNT MOV R4,@INPTR(R5) ;SAVE INPUT COUNT MOV #24,R3 ;GET COUNT OF LOCS TO CLEAR MOV R5,R4 ;GET LOCS ADD #OAL,R4 ; START ADDRESS CLRLOC: CLR (R4)+ ;CLEAR LOCS DEC R3 BNE CLRLOC ; ALL OF THEM CLRB SC(R5) ;CLEAR FLAGS. BASELINE SLOPE CHANGE CNTR CLRB BS(R5) ;BASLINE SWITCH CLR CAL(R5) ;ACC. AREA DURING INCREASE CLR CAH(R5) MOV #77777,OSH(R5) ;SET SLOPE TO LARGE NO. MOV #177777,OSL(R5) ; CLR WS(R5) ;RATE CHANGE SWITCH MOV SR(R5),DN(R5) ;TAKE SAMPLE RATE FROM TABLE MOV DN(R5),TML(R5) ;SET UP CURRENT TIME(IN SAMPLE PERIODS) CLR TMH(R5) ;CLEAR HIGH PART OF TIME ASL TML(R5) ; ROL TMH(R5) ADD DN(R5),TML(R5) ADC TMH(R5) ;TIME=3*DENSITY MOV R5,PTR(R5) ;GET ADDR ADD #Y1,PTR(R5) ; OF FIRST AVERAGED ELEMENT MOVB #6,CNTR1(R5) ;GET CNT OF AVERAGED ELEMENTS NEEDED ;GET FIRST SIX AVERAGED POINTS FOR DIGITAL FILTER. FIRST6: JSR PC,NEXTPT ;GET NEXT AVERAGED POINT MOV R0,@PTR(R5) ;STORE LOW ORDER RESULT ADD #2,PTR(R5) ;POINT TO NEXT LOC .IF DF,AUTOG$ MOV R1,@PTR(R5) ;STORE HIGH ORDER RESULT ADD #2,PTR(R5) ;POINT TO NEXT LOC .ENDC DECB CNTR1(R5) ;HAVE THE 1ST 6 AVERAGED POINTS BEEN CAL BNE FIRST6 ;IF NOT , B+C ;START OF NEW PEAK N247: MOVB #1,S1(R5) ;SET DECREASING WITHOUT INCREASE CLR MC(R5) ;CLR MINIMUM COUNTER CLR CC(R5) ;CLR MAXIMUM COUNTER CLRB S2(R5) ;SET NOT INCREASING AFTER A DECREASE MOV #77777,MN(R5) ;SET MINIMUM TO LARGE NO. CLR MX(R5) ;SET MAXIMUM LOW .IF DF,AUTOG$ MOV #77777,MNH(R5) ;FINISH SETTING MINIMUM CLR MXH(R5) ;FINISH SETTING MAXIMUM .ENDC ;GETTING NEXT POINT N100: ADD WS(R5),DN(R5) ;UPDATE SAMPLES TO AVERAGE CLR WS(R5) ;CLEAR CHANGE SAMPLE RATE INDICATOR ADD DN(R5),TML(R5) ;UPDATE CURRENT TIME ADC TMH(R5) JSR PC,NEXTPT ;GET NEXT AVERAGED POINT MOV R0,Y7(R5) ;STORE LOW PART OF VALUE .IF DF,AUTOG$ MOV R1,Y7H(R5) ;STORE HI PART OF VALUE .ENDC ;START OF ALGORITHM FOR DIGITAL FILTER MOV Y7(R5),R0 ;ALGORITHM FOR GETTING CNTR WGTD VALUE ADD Y1(R5),R0 ; -(Y1+Y7) .IF DF,AUTOG$ MOV Y1H(R5),R1 ADC R1 ADD Y7H(R5),R1 ; MOST SIG. HALVES .ENDC CLR R2 MOV Y6(R5),R3 ;+ 4(Y6+Y2) ADD Y2(R5),R3 .IF DF,AUTOG$ ADC R2 ADD Y6H(R5),R2 ADD Y2H(R5),R2 ; MOST SIG. HALVES .ENDC ASL R3 .IF DF,AUTOG$ ROL R2 .ENDC ASL R3 .IF DF,AUTOG$ ROL R2 .ENDC SUB R0,R3 ;TERM2 - TERM1 SBC R2 .IF DF,AUTOG$ SUB R1,R2 .ENDC MOV Y5(R5),R0 ; + 11 * (Y5 + Y3) ADD Y3(R5),R0 .IF DF,AUTOG$ MOV Y5H(R5),R4 ADC R4 ADD Y3H(R5),R4 .ENDC MOV #11.,R1 JSR PC,MULUNS ADD R1,R3 ADC R2 ADD R0,R2 .IF DF,AUTOG$ MOV R4,R0 $MUL #11.,R0 ADD R1,R2 .ENDC MOV Y4(R5),R0 ; + 14 * Y4 MOV #14.,R1 JSR PC,MULUNS ADD R1,R3 ADC R2 ADD R0,R2 .IF DF,AUTOG$ MOV Y4H(R5),R0 $MUL #14.,R0 ADD R1,R2 BGE DOD ;CHECK IF QUOTIENT IS POSITIVE CLR R0 ; IF NOT, SET Y4 TO ZERO CLR R1 BR DOND DOD: MOV R2,R0 MOV R3,R1 MOV #42.,R3 ;[-(Y1+Y7)+4*(Y2+Y6)+11.*(Y3+Y5)+14.*Y4]/ CLR R2 ; 42. JSR PC,DDIVD DOND: MOV R1,Y4(R5) ;STORE NEW FILTERED POINT MOV R0,Y4H(R5) .ENDC .IF NDF,AUTOG$ MOV R2,R0 MOV R3,R1 $DIV #42.,R0 ;[-(Y1+Y7)+4*(Y2+Y6)+11.*(Y3+Y5)+14.*Y4]/ ; 42. MOV R0,Y4(R5) ;STORE NEW FILTERED POINT .ENDC ;END OF ALGORITHM FOR DIGITAL FILTER ;SHIFT POINTS FOR ALGORITHM DOWN ONE MOV R5,R4 ;SET Y(I) = Y(I+1) ADD #Y1,R4 .IF NDF,AUTOG$ MOV #6,R3 .ENDC .IF DF,AUTOG$ MOV #14,R3 .ENDC .ENABL LSB 1$: MOV OFSET(R4),(R4)+ DEC R3 BNE 1$ .IF DF,AUTOG$ CMP Y3H(R5),MNH(R5) ;COMP. CENTER VALUE TO CURRENT MIN BLT 2$ BEQ 3$ ;IF EQUAL, CHECK LO-ORDER JMP N150 ;IF GREATER THAN OR EQUAL, B+C .ENDC 3$: CMP Y3(R5),MN(R5) ;CMPARE CENTER VALUE TO CURRENT MIN BLO 2$ JMP N150 ;IF GREATER THAN OR EQUAL, B+C ;NEW POINT LOWER THAN MINIMUM 2$: CMPB #1,BS(R5) ;ARE WE LOOKING FOR PEAK WIDTH BNE N117 ;IF NOT, B+C MOV PH(R5),R1 ;IF SO, CHECK IF LOW ENOUGH TO ADD KM(R5),R1 ; CALCULATE PEAK WIDTH .IF DF,AUTOG$ MOV PHH(R5),R0 ADC R0 ADD KMH(R5),R0 ASR R0 ;CAL (KM+PH)/2 .ENDC ROR R1 ;(KM+PH)/2 = TERM .IF DF,AUTOG$ CMP Y3H(R5),R0 ;IS CENTERED PT > TERM BGT N117 ;IF SO, B+C BLT 4$ ;IF LESS, B+C .ENDC CMP Y3(R5),R1 ;IS CENTERED PT > TERM BHI N117 ;IF SO, B+C 4$: MOV TMH(R5),R0 ;OTHERWISE, CALCULATE 1/2WID AT 1/2HT MOV TML(R5),R1 SUB PTH(R5),R0 SUB PTL(R5),R1 SBC R0 MOV R0,WDH(R5) ;SET WIDTH MOV R1,WDL(R5) MOVB #2,BS(R5) ;INDICATE LOOKING FOR END PEAK ON BASLIN $DIV DN(R5),R0 ;IS WIDTH LESS THAN 25 PTS CMP R0,#25. BLT N117 ;IF SO , B+C MOV Y5(R5),R1 ;OTHERWISE, ADD 1/2 Y5 TO ACC. AREA .IF NDF,AUTOG$ ASR R1 .ENDC .IF DF,AUTOG$ MOV Y5H(R5),R0 ASR R0 ROR R1 .ENDC ADD R1,OAL(R5) ;ADJUSTING ACC. AREA FOR STEP CHANGE ADC OAH(R5) .IF DF,AUTOG$ ADD R0,OAH(R5) .ENDC MOV DN(R5),WS(R5) ;SET SWITCH TO HALVE SAMPLE RATE N117: MOV Y3(R5),MN(R5) ;RECORD CURRENT MINIMUM VALUE .IF DF,AUTOG$ MOV Y3H(R5),MNH(R5) .ENDC MOV TMH(R5),MTH(R5) ;RECORD CURRENT PT COUNTER MOV TML(R5),MTL(R5) INC MC(R5) ;INC MINS FOUND COUNTER MOV Y3(R5),R0 ;INC ACC. AREA BY MOV DN(R5),R1 ; CENTERED PT. * SAMPLE RATE JSR PC,MULUNS ADD R1,OAL(R5) ADC R0 ADD R0,OAH(R5) .IF DF,AUTOG$ MOV Y3H(R5),R0 $MUL DN(R5),R0 ADD R1,OAH(R5) .ENDC ADD CAL(R5),OAL(R5) ; AND INCREASE ACC. AREA BY AREA ACC. ADC OAH(R5) ; DURING INCREASE ADD CAH(R5),OAH(R5) .ENABL LSB TSTB BS(R5) ;IS PEAK START ON BASELINE? BNE 1$ ;IF NOT, B+C TSTB S1(R5) ;ARE WE ON BACK SIDE OF PEAK BEQ 1$ ;IF NOT, B+C CLR OAH(R5) ;IF SO, ZERO ACC. AREA CLR OAL(R5) 1$: CLR CAH(R5) ;CLEAR ACC. AREA DURING INCREASE CLR CAL(R5) CMP MC(R5),GT(R5) ;COMPARE #MINS TO GATE BGE 2$ ;IF GREATER OR EQUAL, B+C JMP N100 ;OTHERWISE 2$: MOVB #1,S1(R5) ;INDICATE NOT ON BACKSIDE CLR CC(R5) ;CLEAR MAXIMUMS COUNTER TSTB S2(R5) ;WAS THERE AN INCR. AFTER A DECR. OR BASL BNE 3$ ;IF SO, B+C CLR MX(R5) ;IF NOT, SET MAX LO .IF DF,AUTOG$ CLR MXH(R5) .ENDC JMP N200 3$: MOV CTL(R5),PTL(R5) ;RECORD PEAK TIME MOV CTH(R5),PTH(R5) MOV KTL(R5),LMTL(R5);RECORD LEADING MINIMUM TIME MOV KTH(R5),LMTH(R5) MOV MX(R5),PH(R5) ;RECORD PEAK HEIGHT MOV KM(R5),LMH(R5) ;RECORD LEADING MINIMUM HEIGHT .IF DF,AUTOG$ MOV MXH(R5),PHH(R5) ;RECORD PEAK HEIGHT(MSH) MOV KMH(R5),LMHH(R5);RECORD LEADING MINIMUM HEIGHT(MSH) .ENDC MOVB #1,BS(R5) ;INDICATE LOOKING FOR HALF HEIGHT JMP N247 ;PREPARE FOR NEXT PEAK ;NEW POINT LARGER THAN CURRENT MINIMUM N150: MOV Y3(R5),R0 ;UPDATE AREA ACC. DURING INCR BY MOV DN(R5),R1 ;CURRENT AREA JSR PC,MULUNS ADD R1,CAL(R5) ADC R0 ADD R0,CAH(R5) .IF DF,AUTOG$ MOV Y3H(R5),R0 $MUL DN(R5),R0 ADD R1,CAH(R5) .ENDC MOV MX(R5),R1 ;CHECK IF NEW PT. SIGNIFICANTLY INCREASED ADD HM(R5),R1 ; OVER LATEST MAX .ENABL LSB .IF DF,AUTOG$ MOV MXH(R5),R0 ADC R0 CMP Y3H(R5),R0 BGT 1$ BLT 2$ .ENDC CMP Y3(R5),R1 BHI 1$ 2$: JMP N200 1$: MOV TML(R5),CTL(R5) ;IF INCREASE IS SIGNIFICANT, UPDATE MAX MOV TMH(R5),CTH(R5) ; INFORMATION INC CC(R5) ;UPDATE TIME,MAXS FOUND COUNT, MOV Y3(R5),MX(R5) ; AND HEIGHT .IF DF,AUTOG$ MOV Y3H(R5),MXH(R5) .ENDC CMP CC(R5),GT(R5) ;CMPARE #MAXS TO GATE VALUE BGE 3$ ;IF HIGH ENOUGH, B+C JMP N200 ;OTHERWISE WAIT 3$: CLR MC(R5) ;CLR MINS COUNTER TSTB S1(R5) ;ARE WE ON BACKSIDE OF PEAK BNE 4$ ;IF SO, B+C JMP N160 ;OTHERWISE 4$: MOV MN(R5),R0 ;UPDATE AREA ACC. DURING INCR. BY MOV DN(R5),R1 ; 1/2 LEADING MINIMUM * SAMPLE RATE JSR PC,MULUNS .IF DF,AUTOG$ MOV R1,R3 MOV R0,R2 MOV MNH(R5),R0 $MUL DN(R5),R0 ADD R0,R3 MOV R3,R1 MOV R2,R0 .ENDC ASR R0 ROR R1 ADD R1,CAL(R5) ;UPDATE AREA ADC R0 ADD R0,CAH(R5) MOVB #1,S2(R5) ;IND INCREASE AFTER DECREASE CLRB S1(R5) ;IND NO DECREASE MOV MTL(R5),KTL(R5) ;RECORD PEAK LEADING MINIMUM TIME MOV MTH(R5),KTH(R5) MOV MN(R5),KM(R5) ;RECORD PEAK LEADING MINIMUM .IF DF,AUTOG$ MOV MNH(R5),KMH(R5) .ENDC .ENABL LSB CMPB #1,BS(R5) ;DETERMINE WHAT TO DO BY WHERE WE ARE BLE 1$ ;IF NOT STARTING ON BASELINE,END OF PEAK MOV KTL(R5),BTL(R5) ;IF STARTING ON BASELINE, RECORD NEW MOV KTH(R5),BTH(R5) ; BASELINE TIME AND MOV KM(R5),BM(R5) ; HEIGHT .IF DF,AUTOG$ MOV KMH(R5),BMH(R5) .ENDC JMP N160 1$: BNE 2$ ;IF NOT LOOKING FOR WIDTH, B+C MOV MTL(R5),R1 ;OTHERWISE,MUST CAL. PEAK WIDTH NOW MOV MTH(R5),R0 ; SINCE PEAK HAS ENDED BEFORE SUB PTH(R5),R0 ; HALF HEIGHT WAS REACHED SUB PTL(R5),R1 SBC R0 ASR R0 ROR R1 ;WIDTH EQUALS 1/2(MIN TIM - LEAD MIN TIM) MOV R0,WDH(R5) ;SET WIDTH MOV R1,WDL(R5) 2$: CLR TYPE(R5) ;IND. NOT ON BASELINE JSR PC,RITOUT ;OUTPUT PEAK DATA MOVB #2,BS(R5) ;IND. LOOKING FOR END ON BASELINE MOV WDL(R5),R1 ;CHECK WIDTH MOV WDH(R5),R0 $DIV DN(R5),R0 CMP #25.,R0 BLE 4$ ;IF WIDER THAN 24 PTS, GO LOWER SAMP RATE JMP N160 4$: MOV Y5(R5),R1 ;CORRECT ACC AREA BY 1/2 Y5 .IF NDF,AUTOG$ ASR R1 .ENDC .IF DF,AUTOG$ MOV Y3H(R5),R0 ASR R0 ROR R1 ADD R0,OAH(R5) .ENDC ADD R1,OAL(R5) ADC OAH(R5) MOV DN(R5),WS(R5) ; CHANGE. SET SWITCH TO CHANGE SAMP RATE ;LOOKING FOR BASELINE N160: MOV MX(R5),MN(R5) ;SET CURRENT MAX TO CURRENT MIN .IF DF,AUTOG$ MOV MXH(R5),MNH(R5) .ENDC N200: CMPB #2,BS(R5) ;HAS THE WIDTH BEEN CALCULATED YET .ENABL LSB BEQ 1$ ;IF SO, B+C 2$: JMP N100 ;IF NOT, GO GET NEXT PT 1$: TSTB S1(R5) ;IS PT ON BACKSIDE OF PEAK BEQ 2$ ;IF NOT, GO GET NEXT POINT MOV WDH(R5),R0 $MUL WT(R5),R0 ;CAL WIDTH*WIDTH TEST MOV R1,R3 MOV WDL(R5),R0 ;IF SO, TEST TO SEE IF FAR ENOUGH PAST MOV WT(R5),R1 ; TO START LOOKING FOR BASELINE JSR PC,MULUNS ADD R3,R0 MOV TML(R5),R3 ;CAL TIME FROM CREST TO CURRENT POINT MOV TMH(R5),R2 SUB PTH(R5),R2 SUB PTL(R5),R3 SBC R2 CMP R2,R0 ;COMPARE TWO CALCULATED QUANTITIES BGT 4$ ;IF FIRST IS GREATER, B+C BEQ 3$ ;IF HIGH PARTS EQUAL, GO CHECK LO PARTS 5$: JMP N100 ;IF FIRST IS LESS, GO GET NEXT POINT 3$: CMP R3,R1 ;COMPARE LSH OF TWO CAL. QUANTITIES BLO 5$ ;IF FIRST IS LESS, GO GET NEXT POINT 4$: MOV Y3(R5),R0 ;OTHERWISE, CALCULATE CURRENT SLOPE CLR -(SP) ; CLEAR SIGN FLAG SUB BM(R5),R0 ;SLOPE = (CURRENT POINT-LEADING BASELINE ; MINIMUM)/ .IF DF,AUTOG$ MOV Y3H(R5),R2 SBC R2 SUB BMH(R5),R2 BPL 55$ ;IF POSITIVE, B+C INC (SP) ;OTHERWISE, INDICATE SIGN CHANGE NEG R2 NEG R0 SBC R2 55$: TST R2 ;CHECK FOR ZERO SLOPE BNE 7$ .ENDC .IF NDF,AUTOG$ BGE 6$ ;IF POSITIVE, B+C INC (SP) ;OTHERWISE, INDICATE SIGN CHANGE NEG R0 .ENDC 6$: TST R0 ;CHECK FOR ZERO SLOPE BEQ 9$ ;IF NON-ZERO , B+C 7$: MOV #1000.,R1 JSR PC,MULUNS .IF DF,AUTOG$ MOV R0,R4 MOV R1,R3 MOV R2,R0 $MUL #1000.,R0 ADD R3,R0 MOV R0,R1 MOV R4,R0 .ENDC MOV TML(R5),R3 ; (CURRENT TIME-LEADING BASELINE MOV TMH(R5),R2 ; TIME) SUB BTH(R5),R2 SUB BTL(R5),R3 SBC R3 JSR PC,DDIVD TST (SP)+ BEQ 9$ NEG R0 ;IF SIGNS DIFFERED, SLOPE NEGATIVE NEG R1 SBC R0 9$: MOV R0,SLH(R5) MOV R1,SLL(R5) CMP OSH(R5),SLH(R5) ;COMPARE TO OLD SLOPE BGT 10$ ;IF OLD GREATER, GO UPDATE AND TRY AGAIN BLT 11$ ;IF OLD IS LESS, CHECK IF BASELINE CMP OSL(R5),SLL(R5) ;COMPARE TO LSH TO OLD SLOPE BLOS 11$ ;IF OLD IS LESS, CHECK IF BASELINE 10$: MOV SLL(R5),OSL(R5) ;SET OLD TO NEW MOV SLH(R5),OSH(R5) CLRB SC(R5) ;CLEAR SLOPE INCR COUNTER JMP N100 ;GO GET NEXT POINT 11$: INCB SC(R5) ;INCRE SLOPE INCR COUNTER CMPB #2,SC(R5) ;HAS SLOPE INCR TWICE IN A ROW BGE 12$ ;IF SO, B+C JMP N100 ;OTHERWISE, GO GET NEXT POINT 12$: MOV #1,TYPE(R5) ;IND. ENDING PEAK ON BASELINE JSR PC,RITOUT ;OUTPUT PEAK DATA BLOCK CLRB SC(R5) ;CLEAR SLOPE INCR. COUNTER MOV #77777,OSH(R5) ;SET SLOPE TO LARGE NO. CLRB BS(R5) ;SET FLAG TO INDICATE STARTING AT BASELIN JMP N100 ;GO GET NEXT POINT .SBTTL UTILITIES ;ROUTINE TO GET NEXT AVERAGED POINT NEXTPT: MOV DN(R5),CNTR2(R5) ;GET NO.OF PTS TO AVERAGE MOV INPUT(R5),R2 ;GET INPUT TABLE ADDRESS CLR R0 ;GET SUM READY CLR R1 NEXTIN: DEC @INPTR(R5) ;CHECK REMAINING INPUT COUNT BGE NEXTC ;IF MORE INPUT, BRANCH NEG @OUTPTR(R5) ;OTHERWISE, FIX OUTPTR ADD @OUTSIZ(R5),@OUTPTR(R5) ;FOR RETURN MOV #IRESUM-INTIL,FIRSTM(R5) ;SET OFFSET FOR RESTART MOV R0,SAV0(R5) ;SAVE APPROPRIATE INFO MOV R1,SAV1(R5) MOV (SP)+,SAV6(R5) RTS PC ;RETURN IRESUM: MOV SAV0(R5),R0 ;RESTORE APPROPRIATE INFO MOV SAV1(R5),R1 MOV SAV6(R5),-(SP) MOV INPUT(R5),R2 ;GET ADDR OF INPUT BUFFER DEC @INPTR(R5) ;DECREMENT INPUT BUFFER COUNT NEXTC: MOV (R2)+,R3 ;GET NEXT DATUM .ENABL LSB .IF DF,AUTOG$ .IFF BMI 6$ ;IF NEGATIVE, TREAT AS ZERO .IFT CLR R4 ;GET MSH READY TST AUT(R5) BEQ 5$ ;IF NOT, B+C MOV -2(R2),-(SP) ;GET GAIN BITS BIC #7777,(SP) BIC (SP),R3 ;GET RID OF GAIN BITS IN DATA SUB #4000,R3 ;GET IN RIGHT RANGE(SHOULD NOT BE NEG) BPL 20$ CLR R3 ;IF NOT POSITIVE: ZERO BR 21$ 20$: SBC R4 ;GET RIGHT SIGN(SHOULD BE POSITIVE) SWAB (SP) ;PUT IN RIGHT JUSTIFIED POSITION ASR (SP) ASR (SP) ASR (SP) COM (SP) ;GET COMPLEMENT,I.E., # OF SHIFTS BIC #177771,(SP) ;IN 2 LEAST SIGN. BITS BEQ 2$ ;IF DONE, B+C 4$: ASL R3 ;NORMALIZE VALUE ROL R4 DEC (SP) ;MORE SHIFTS 2$: BNE 4$ ;IF SO, B+C 21$: TST (SP)+ ;POP STACK .ENDC 5$: ADD R3,R1 ;KEEP SUMMING ADC R0 .IF DF,AUTOG$ ADD R4,R0 ;ADD MSH .ENDC 6$: DEC CNTR2(R5) ;SHOULD MORE BE SUMMED BNE NEXTIN ;IF SO , B+C MOV R2,INPUT(R5) ;SAVE CURRENT ADDRESS OF INPUT BUFFER MOV DN(R5),R3 ;GET NO. IN SAMPLES AVERAGED .IF DF,AUTOG$ CLR R2 ;DIVID R0,R1 BY R2,R3. RESULT IN R0,R1 JSR PC,DDIVD MOV R0,-(SP) MOV R1,R0 MOV (SP)+,R1 .ENDC .IF NDF,AUTOG$ $DIV R3,R0 ;DIVD R0,R1 BY R3. RESULT R0 .ENDC RTS PC ;ROUTINE TO OUTPUT A BLOCK OF PEAK DATA. RITOUT: MOV MN(R5),R0 ;UPDATE AREA BY SUBTRACTING MOV DN(R5),R1 ; 1/2 LEADING MINIMUM * SAMPLE RATE JSR PC,MULUNS .IF DF,AUTOG$ MOV R1,R3 MOV R0,R2 MOV MNH(R5),R0 $MUL DN(R5),R0 ADD R0,R3 MOV R3,R1 MOV R2,R0 .ENDC ASR R0 ROR R1 SUB R1,OAL(R5) ADC R0 SUB R0,OAH(R5) .ENABL LSB MOV OUTPUT(R5),R3 ;GET OUTPUT BUFFER ADDRESS DEC @OUTPTR(R5) ;CHECK OUTPUT SPACE REMAINING BGE OUTCON ;IF THERE IS ANY, BRANCH AND CONTINUE NEG @INPTR(R5) ;OTHERWISE, FIX UP INPTR ADD @INSIZ(R5),@INPTR(R5) ; FOR RETURN MOV #ORESUM-INTIL,FIRSTM(R5) ;SET OFFSET FOR REENTRY MOV (SP)+,SAV6(R5) ;SAVE SUBROUTINE RETURN ADDRESS(INTERNAL) RTS PC ;AND RETURN ORESUM: MOV OUTPUT(R5),R3 ;GET OUTPUT BUFFER ADDRESS DEC @OUTPTR(R5) ;DECREMENT COUNT MOV SAV6(R5),-(SP) ;RETURN RETURN ADDRESS TO STACK OUTCON: MOV #OAL,R4 ;GET ADDR OF OUTPUT BLOCK ADD R5,R4 MOV #10.,R0 ;GET BLOCK LENGTH TST OUTTYP(R5) ;TEST FOR FLOATING CONVERT BEQ OUTLOP ;IF NO FLOATIN POINT, BRANCH MOV R0,CNTR2(R5) ;SET COUNTER FLTLOP: MOV R3,-(SP) ;SAVE OUTADDRESS CLR R2 ;INIT POSSIBLE 3RD WORD OF RESULT MOV (R4)+,R1 ;GET LOW PART BNE 1$ ;BRANCH IF NOT 0 MOV @R4,R0 ;IS ENTIRE NUMBER 0 BEQ 7$ ;BRANCH IF YES 1$: MOV @R4,R0 ;GET HIGH PART BPL 2$ ;BRANCH IF POSITIVE NEG R0 ;NEGATE HIGH PART, C=1 NEG R1 ;NEGATE LOW PART SBC R0 2$: MOV #237,R3 ;SET MAXIMUM EXP+1 3$: BIT #177400,R0 ;LOOK FOR A STRING OF 8 0 BITS BNE 5$ ;BRANCH IF NOT FOUND SWAB R0 ;LEFT JUSTIFY THEM SUB #8.,R3 ;PERFORM A SHIFT BY 8 SWAB R1 BISB R1,R0 ;INSERT NEW BITS CLRB R1 ;REMOVE THEM BR 3$ ;TRY AGAIN 4$: DEC R3 ;FIX EXP COUNT ROL R1 ;NORMALIZE R0:R1 ROL R0 5$: BPL 4$ ;LOOP TILL IMPLIED NORM BIT IN SIGN BISB R1,R2 ;PUT IN BITS 25-32 SWAB R2 ;JUSTIFY IT CLRB R1 ;REMOVE THE BITS FROM 2ND WORD BISB R0,R1 ;MOVE THE NEW ONES IN FROM R0 SWAB R1 ;JUSTIFY IT CLRB R0 ;REMOVE THEM FROM HIGH WORD SWAB R0 ;JUSTIFY IT SWAB R3 ;GET EXP INTO HIGH BYTE TST @R4 ;WAS ORIGINAL NUMBER + OR - BPL 6$ ;BRANCH IF POSITIVE, C=0 SEC 6$: ROR R3 ;INSERT WITH EXP ADD R3,R0 ;CREATE RESULT 7$: TST (R4)+ ;BUMP DATA POINTER MOV (SP)+,R3 ;GET ADDRESS MOV R0,(R3)+ ;STORE FIRST PART MOV R1,(R3)+ ;STORE NEXT PART TST OUTTYP(R5) ;CHECK FOR DOUBE PRECISION FLOATING BPL 8$ ;IF NOT, BRANCH MOV R2,(R3)+ CLR (R3)+ ;STORE LAST TWO PARTS 8$: DEC CNTR2(R5) ;CHECK FOR MORE BNE FLTLOP ;IF MORE BRANCH BACK BR OUTRET ;IF NOT RETURN OUTLOP: MOV (R4)+,(R3)+ ;PUT OUTPUT BLOCK IN OUTPUT BUFFER MOV (R4)+,(R3)+ ;PUT OUTPUT BLOCK IN OUTPUT BUFFER DEC R0 BNE OUTLOP ;DECR BLOCK WORD CNT. B+C IF NOT ZERO OUTRET: MOV R3,OUTPUT(R5) ;STORE CURRENT BUFFER POINTER CLR OAL(R5) ;CLEAR AREA CLR OAH(R5) RTS PC ;ROUTINE TO DIVIDE R0, R1 BY R2, R3 WITH RESULT IN R0,R1 DDIVD: MOV R5,-(SP) ;SAVE R5 MOV #32.,-(SP) ;GET LOOP COUNT CLR R4 ;READY REMAINDER(R4+R5) CLR R5 .ENABL LSB 1$: ROL R1 ROL R0 ;EXPOSE NEW BIT OF NEWMERATOR ROL R4 ROL R5 CMP R2,R5 ;DOES DENOMINATOR FIT BHI 3$ ;IF NOT, B+C(CARRY = 0) BLT 2$ ;IF SO, B+C CMP R3,R4 ;IF HIGH EQUAL, CHECK LOW PARTS BHI 3$ ;BRANCH IF DENOM. TOO BIG(C=0) 2$: SUB R3,R4 ;SUB DENOM FROM REMAINDER SBC R5 SUB R2,R5 SEC ;INDECATE NEW QUOTIENT BIT 3$: DEC (SP) ;CHECK LOOP COUNT BGE 1$ ;IF MORE TO COME B+C TST (SP)+ ;UP SP MOV (SP)+,R5 ;RESTORE R5 RTS PC ;RESULT IN R3,R2 ;UNSIGNED SINGLE PRECISION MULTIPLY ;MULTIPLIES THE CONTENTS OF R0 BY R1 AND STORES ;RESULTS IN R0 AND R1 MULUNS: .ENABL LSB MOV R3,-(SP) ;SAVE REGS 2 AND 3 MOV R2,-(SP) MOV #100000,R3 ;R3 CONTAINS COMPLETION FLAG CLR R2 ;R2 WILL CONTAIN HIGH ORDER PRODUCT 1$: ROR R1 ;C = MULTIPLIER BIT BCC 2$ ;BR IF ZERO MULTIPLIER BIT ADD R0,R2 ;BIT MULTIPLY 2$: ROR R2 ;SHIFT HIGH ORDER ROR R3 ;THE LOW ORDER & COMPLETION FLAG BCC 1$ ;BR IF MULTIPLICATION IS NOT COMPLETE MOV R2,R0 ;LEAVE RESULT IN R0 & R1 MOV R3,R1 MOV (SP)+,R2 ;RESTORE REGISTERS MOV (SP)+,R3 RTS PC .END