* PROCEDURE profile(VAR x,y : INT_ARRAY; * VAR n : INTEGER; * dc : byte; * maxn : INTEGER; * VAR penup : BOOLEAN); * A PASCAL/Z EXTERNAL ROUTINE TO FILL ARRAYS X AND Y USING A HOUSTON HIPAD * DIGITIZER FOR INPUT.ASSUMES THAT THE HIPAD IS IN STREAM MODE AND SETUP * FOR PARALLEL BINARY METRIC TRANSMISSION. * POINT COLLECTING STARTS WHEN THE PEN GOES DOWN.(i.e.CONTROL BYTE = 0F4H) * A POINT IS REJECTED IF (ABS(dx) + ABS(dy)) IS LESS THAN dc UNITS FROM THE * PRECEDING POINT (ONE UNIT = 0.1mm). * THE PROCEDURE ENDS IF : * 1 : THE PEN COMES UP , * 2 : MAXN POINTS HAVE BEEN READ, * OR 3 : MORE THAN min# POINTS HAVE BEEN READ AND A POINT * IS ACQUIRED CLOSER THAN closed TO THE FIRST POINT. * THUS THE ARRAYS WILL HOLD COORDINATES OF POINTS ON THE PERIMETER OF A * CLOSED PROFILE. vbytes EQU 12 # OF BYTES ON STACK xhi EQU 19 xlo EQU 18 OFFSETS TO (IX) FOR ADDRESS OF POINTERS yhi EQU 17 ylo EQU 16 TO TRANSMITTED VARIABLES. nhi EQU 15 nlo EQU 14 dc EQU 12 maxnhi EQU 11 maxnlo EQU 10 penup EQU 9 min# EQU 30 closed EQU 5 ( 1 = 0.1mm ) FALSE EQU 0 TRUE EQU NOT FALSE STAT_RDY EQU 0F7H STATUS PORT DATA AVAILABLE CODE STAT_PRT EQU 00AH ADDRESS OF STATUS PORT DATA_PRT EQU 008H " " DATA " NAME profile ENTRY profile PASS: MACRO ARG ; STORES THE 16BIT NO. IN DE ; IN A LOCATION WHOSE BASE ; ADDRESS IS CALCULATED FROM ARG. ; & WHOSE OFFSET = 2 x IY PUSH H MOV H,ARG(IX) ; GET BASE ADDRESS OF MOV L,ARG-1(IX) ; ARRAY => HL CALL passxy POP H ENDMAC invert: MACRO arg PUSH P MOV A,arg NEG MOV arg,A POP P ENDMAC profile: ENTR D,2,0 JMP START old_x: DS 2 old_y: DS 2 x1: DS 2 y1: DS 2 start: PUSH Y : SAVE IY FOR PASCAL/Z MOV B,maxnhi(IX) : GET VALUE OF MOV C,maxnlo(IX) : MAXN => BC. LXI H,0 STC CMC DSBC B : MAXN = or > 1 ? JC START2 : IF YES THEN START PUSH B POP Y CALL PASS_N : ELSE MAXN --> N JMP done : and RETURN. START2: MOV H,penup(ix) : initialise penup to FALSE MOV L,penup-1(ix) MVI M,FALSE CALL W8_4_PEN : PEN DOWN YET? CALL FIRST_PR LOOP: JMP ANYMORE : DOES N := MAXN YET ? PROCEED: JMP PEN_UP_YET STILL_DOWN: JMP NEXT_PR done: CALL PASS_N POP Y : RESTORE ORIGINAL Y FOR PASCAL/Z EXIT D,VBYTES ********************* SUBROUTINES ******************************** W8_4_PEN: * READS DATA PORT UNTIL CONTROL BYTE = F4 * i.e. UNTIL THE PEN IS DOWN. CALL STAT_CHK ;WAIT TILL DATA AVAILABLE IN DATA_PRT ;GET IT CPI 0F4H ;PEN DOWN ? JNZ W8_4_PEN ;NO : KEEP WAITING. RET ;YES! FIRST_PR: * GETS THE INITIAL X,Y PAIR CALL X_IN DISCARD THE FIRST CALL Y_IN POINT AS IT CAN CALL W8_4_PEN BE GARBAGE. CALL X_IN X[1] => DE CALL Y_IN Y[1] => HL PUSH H SAVE Y[1] MOV B,xhi(IX) ; MOV C,xlo(IX) MOV A,D STA OLD_X ;SAVE IT TO COMPARE WITH NEXT X STA x1 STAX B ;& ALSO SEND IT TO PASCAL/Z LAND. DCX B MOV A,E STA OLD_X+1 STA x1+1 STAX B MOV B,yhi(IX) MOV C,ylo(IX) POP H Y[1] => HL MOV A,H STA old_y ;SAVE IT TO COMPARE WITH NEXT y STA y1 STAX B ;& ALSO SEND IT TO PASCAL/Z LAND. DCX B MOV A,L STA old_y+1 STA y1+1 STAX B LXI Y,1 : COUNTER FOR POINTS READ. RET ANYMORE: * N = MAXN ? (i.e. IS BUFFER FULL ?) PUSH H MOV H,maxnhi(IX) MOV L,maxnlo(IX) PUSH D PUSH Y ;GET COUNT FROM Y POP D ;TO DE + COMPARE STC CMC DSBC D ;TO MAXN. POP D POP H JZ done JMP proceed PEN_UP_YET: * READ DATA PORT : IS CONTROL BYTE = F3 ? CALL STAT_CHK ;WAIT FOR DATA IN DATA_PRT ;GET A BYTE CPI 0F4H ;CONTROL BYTE = F4?(PEN STILL DOWN) JZ STILL_DOWN MOV H,penup(ix) : set penup TRUE MOV L,penup-1(ix) MVI M,TRUE JMP done ;and EXIT IF PEN NOT DOWN NEXT_PR: * GETS ALL POINTS AFTER (X[1],Y[1]) CALL X_IN : GET NEW X => DE PUSH D : & SAVE IT LXI H,OLD_X MOV B,M INX H MOV C,M : GET OLD_X => BC XCHG : MOVE NEW X => HL CALL absdiff : abs(dx) => A PUSH p : save abs(dx) for later LXI H,old_y : MOV B,M : get last y value INX H : into BC MOV C,M : CALL y_in : new y => HL PUSH H POP D : copy y to DE CALL absdiff : abs(dy) => A POP B : abs(dx) => B ADD B : (abs(dx) + abs(dy)) => A CC overflow MOV C,dc(IX) SUB C : > dc ? JNC point_ok POP D : if not : too close ! so fix stack JMP loop point_ok: INX Y : N := N + 1 MOV A,D : IF SO : y => old_y STA old_y MOV A,E STA old_y+1 pass yhi : and y => y[i] XCHG : y => HL POP D : RESTORE X MOV A,D STA old_x : SAVE IT TO COMPARE WITH NEXT X MOV A,E STA old_x+1 pass xhi : x => x[i] * n.b. we now have y in HL,X in DE & n in IY: have we >= min# points? PUSH H : save y PUSH IY POP B : n => BC LXI H,min# STC CMC DSBC B POP H JNC loop : no! so keep going. * yes! so see if circle can be closed : i.e.are we close enough to (x1,y1) ? LDA y1 MOV B,A LDA y1+1 MOV C,A : y[1] => BC CALL absdiff : abs(y[1] - y[i]) => A PUSH p : " " " => stack XCHG : x[i] => HL LDA x1 MOV B,A LDA x1+1 MOV C,A : x[1] => BC CALL absdiff : abs(X[1] - Y[i]) => A POP B : abs(y[1] - y[i]) => B ADD B : abs(distance from (x[1],y[1])) => A CC overflow MOV C,A : into C. MVI A,closed : close enough to end? SUB C JNC done : yes! JMP loop : no! absdiff: * arg1 in HL,arg2 in BC : abs(diff) => A BIT 7,H JNZ hlneg BIT 7,B JNZ subtract bothpos: PUSH H STC CMC DSBC B JC bcbigger POP B JMP subdone bcbigger: POP H CALL switch subtract: STC CMC DSBC B JMP subdone hlneg: BIT 7,B JNZ negate CALL switch JMP subtract negate: invert H invert L invert B invert C JMP bothpos switch: PUSH H PUSH B POP H POP B RET subdone: MOV A,H ORA A JNZ overflow MOV A,L RET overflow: MVI A,07FH * largest +ve 8bit # RET STAT_CHK: * CHECKS STATUS PORT IN STAT_PRT ;DATA IN? CPI STAT_RDY RZ ;IF SO:GO GET IT. JMP STAT_CHK ;ELSE TRY AGAIN. X_IN: * GET X VALUE FROM HIPAD INTO DE CALL STAT_CHK ;WAIT FOR DATA IN DATA_PRT ;GET 1ST BYTE (X7..X13) MOV D,A ;INTO D PUSH D CALL STAT_CHK POP D IN DATA_PRT ;2ND BYTE (X0..X6) MOV E,A ;INTO E SLAR E ;---| SLAR D ; |JUSTIFY SRAR D ; | RIGHT SRAR D ; | IN DE RRAR E ;---| RET Y_IN: * GET Y VALUE FROM HIPAD INTO HL XCHG CALL X_IN XCHG RET PASS_N: ; PUT CONTENTS OF IY INTO N. PUSH IY POP H ; IY => HL. MOV D,nhi(IX) : ADDRESS OF N MOV E,nlo(IX) : => DE. MOV A,H STAX D DCX D MOV A,L STAX D RET passxy: * base address in HL ,value in DE ,N in IY. PUSH D PUSH B PUSH Y DCX Y ; DADY Y ; OFFSET = 2 * (Y - 1) PUSH Y POP B ; OFFSET --> BC stc cmc DSBC B ; ADDRESS OF ARRAY[N] = HL-OFFSET XCHG ; ADDRESS => DE : value => HL MOV A,H STAX D DCX D MOV A,L STAX D POP Y POP B POP D RET END profile