perm filename ARMSOL.PAL[V,VDS]1 blob sn#264831 filedate 1977-02-15 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00018 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00003 00002	.TITLE ARMSOL
C00004 00003	UPDATE - COMPUTES THE ARM TRANSFORM GIVEN THE JOINT ANGLES
C00007 00004		[T1: TRANFORMATION FOR JOINTS 1,2,3]
C00011 00005		[T2: TRANFORMATION FOR JOINTS 4,5,6]
C00014 00006		[MULTIPLY T1 AND T2 AND ADD BASE]
C00015 00007	SOLVE - COMPUTES JOINT ANGLES GIVEN A TRANSFORM
C00019 00008		["SOLVE" - TX,TY,TZ]
C00021 00009		["SOLVE" - JOINT 1]
C00023 00010		["SOLVE" - JOINT 3]
C00025 00011		["SOLVE" - JOINT 2]
C00027 00012		["SOLVE" - JOINT 5]
C00030 00013		["SOLVE" - DEGENERATE CASE AND JOINT 4]
C00033 00014		["SOLVE" - JOINT 6]
C00035 00015		["SOLVE" - NEED TO FLIP?, EXIT]
C00037 00016		["SOLVE" - SUBROUTINES]
C00040 00017	FLAGS  - INITIALIZES THE ARM CONFIGURATION FLAGS AN ERROR BITS
C00043 00018	LOCAL STORAGE
C00045 ENDMK
C⊗;
.TITLE ARMSOL

;PROGRAMS FOR CONVERTING TABLE COORDINATES TO/FROM JOINT ANGLES

;INDICES TO TRANFORM ELEMENT, STORED BY COLUMNS

T11	=0
T21	=2
T31	=4
T12	=6
T22	=10
T32	=12
T13	=14
T23	=16
T33	=20
T14	=22
T24	=24
T34	=26
;UPDATE - COMPUTES THE ARM TRANSFORM GIVEN THE JOINT ANGLES

;GIVEN THE JOINT ANGLES, THE RESULTING HAND POSITION AND ORIENTATION
;ARE DETERMINED AND STORED IN A GIVEN TRANSFORM "T".  THE TRANSFORM
;IS A 3 BY 4 MATRIX STORED BY COLUMNS WITH EACH VALUE REPRESENTED IN
;TABLE COORDINATES.  A SAMPLE CALLING SEQUENCE FOLLOWS:
;
;		MOV	#T,R0		;LOAD TRANSFORM ADDRESS IN R0
;		MOV	#THETA,R1	;PTR TO JOINT ANGLE ARRAY
;		JSR	PC,UPDATE	
;
;THE TRANSFORM WILL BE OF THE FOLLOWING FORM:
;
;		|  T1   T5   T9   T13  |
;		|  T2   T6   T10  T14  |
;		|  T3   T7   T11  T15  |
;		|   0    0    0    1   |
;
;THE PROCEDURE CONSISTS OF GENERATION OF TWO MATRICES T1 AND T2, THE
;TRANSFORM FROM SHOULDER TO WRIST AND FROM WRIST TO HAND
;RESPECTIVELY,THEN MULTIPLYING THE TWO TO GIVE THE DESIRED TRANSFORM.
;ONLY THE FIRST THREE ROWS OF THE TRANSFORM ARE STORED BY THIS
;ROUTINE.  ALL NUMBERS SHOULD BE IN SCALED INTEGER FORMAT.

;RELATIVE STACK DEFINITIONS

ST1=12		;SIN/COS THETA 1
CT1=10
ST2=6		;SIN/COS THETA 2
CT2=4
ST3=2		;SIN/COS THETA 3
CT3=0

ST4=12		;SIN/COS THETA 4
CT4=10
ST5=6		;SIN/COS THETA 5
CT5=4
ST6=2		;SIN/COS THETA 6
CT6=0

;REGISTERS USED:
;	R0, R1 PASS ARGUMENTS AND ARE ALTERED


UPDATE:	MOV	R2,-(SP)	;SAVE REGISTERS
	MOV	R3,-(SP)
	MOV	R4,-(SP)
	MOV	R5,-(SP)
	MOV	R0,R4		;SAVE POINTERS
	MOV	R1,R5
;	[T1: TRANFORMATION FOR JOINTS 1,2,3]

	MOV	(R5)+,R0	;COMPUTE SIN/COS THETA 1
	JSR	PC,SNCOS
	MOV	R0,-(SP)	;SAVE ON STACK
	MOV	R1,-(SP)
	MOV	(R5)+,R0	;COMPUTE SIN/COS THETA 2
	JSR	PC,SNCOS
	MOV	R0,-(SP)	;SAVE ON STACK
	MOV	R1,-(SP)
	MOV	(R5)+,R0	;COMPUTE SIN/COS THETA 3
	JSR	PC,SNCOS
	MOV	R0,-(SP)	;SAVE ON STACK
	MOV	R1,-(SP)
	MOV	CT2(SP),R0	;T1(3,3) =  - ST2*ST3 + CT2*CT3
	MUL	(SP),R0
	MOV	ST2(SP),R2
	MUL	ST3(SP),R2
	SUB	R3,R1
	SBC	R0
	SUB	R2,R0
	ASHC	#2,R0
	TST	R1		;ROUND OFF
	BPL	.+4
	INC	R0
	MOV	R0,@#T133
	MOV	R0,R2		;T1(1,1) = CT1*( - ST2*ST3 + CT2*CT3)
	MUL	CT1(SP),R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,@#T111
	MUL	ST1(SP),R2	;T1(2,1) = ST1*( - ST2*ST3 + CT2*CT3)
	ASHC	#2,R2
	TST	R3	
	BPL	.+4
	INC	R2
	MOV	R2,@#T121
	MOV	(SP)+,R0	;T1(3,1) =  - (ST2*CT3 + CT2*ST3)
	MUL	ST2-2(SP),R0
	MOV	(SP)+,R2
	MUL	CT2-4(SP),R2
	ADD	R3,R1
	ADC	R0
	ADD	R2,R0
	ASHC	#2,R0
	TST	R1	
	BPL	.+4
	INC	R0
	MOV	R0,@#T131
	NEG	@#T131
	MOV	R0,R2		;T1(1,3) = CT1*(ST2*CT3 + CT2*ST3)
	MUL	CT1-4(SP),R2
	ASHC	#2,R2
	TST	R3
	BPL	.+4
	INC	R2
	MOV	R2,@#T113
	MUL	ST1-4(SP),R0	;T1(2,3) = ST1*(ST2*CT3 + CT2*ST3)
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,@#T123
	MOV	CT1-4(SP),R0	;T1(1,4)=- ST1*(S2 + S3) + CT1*CT2*a2
	MUL	CT2-4(SP),R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MUL	@#A2,R0
	MOV	@#S2S3,R2
	MUL	ST1-4(SP),R2
	SUB	R3,R1
	SBC	R0
	SUB	R2,R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,@#T114
	MOV	@#S2S3,R0	;T1(2,4) = ST1*CT2*a2 + CT1*(S2 + S3)
	MUL	CT1-4(SP),R0
	MOV	@#A2,R2
	MUL	ST1-4(SP),R2
	ASHC	#2,R2
	TST	R3
	BPL	.+4
	INC	R2
	MUL	(SP)+,R2
	ADD	R3,R1
	ADC	R0
	ADD	R2,R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,@#T124
	MOV	(SP)+,R2	;T1(3,4) =  - ST2*a2 + S1
	MUL	@#A2,R2
	ASHC	#2,R2
	TST	R3
	BPL	.+4
	INC	R2
	SUB	@#S1,R2
	NEG	R2
	MOV	R2,@#T134
	MOV	(SP)+,@#T122	;T1(2,2) = CT1
	NEG	(SP)		;T1(1,2) =  - ST1
	MOV	(SP)+,@#T112
	CLR	@#T132		;T1(3,2) = 0

;FINISHED WITH T1
;	[T2: TRANFORMATION FOR JOINTS 4,5,6]

	MOV	(R5)+,R0	;COMPUTE SIN/COS THETA 4
	JSR	PC,SNCOS
	MOV	R0,-(SP)	;SAVE ON STACK
	MOV	R1,-(SP)
	MOV	(R5)+,R0	;COMPUTE SIN/COS THETA 5
	JSR	PC,SNCOS
	MOV	R0,-(SP)	;SAVE ON STACK
	MOV	R1,-(SP)
	MOV	(R5),R0		;COMPUTE SIN/COS THETA 6
	JSR	PC,SNCOS
	MOV	R0,-(SP)	;SAVE ON STACK
	MOV	R1,-(SP)
	MOV	ST4(SP),R2  	;T2(2,2) =  - ST4*CT5*ST6 + CT4*CT6
	MUL	CT5(SP),R2
	ASHC	#2,R2
	TST	R3		;ROUND OFF
	BPL	.+4
	INC	R2
	MUL	ST6(SP),R2
	MOV	CT4(SP),R0
	MUL	CT6(SP),R0
	SUB	R3,R1
	SBC	R0
	SUB	R2,R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,@#T222
	MOV	CT4(SP),R0	;T2(1,2) =  - (ST4*CT6 + CT4*CT5*ST6)
	MUL	CT5(SP),R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	ST4(SP),R2
	MUL	(SP)+,R2
	MUL	(SP),R0
	ADD	R3,R1
	ADC	R0
	ADD	R2,R0
	ASHC	#2,R0
	NEG	R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,@#T212
	MOV	(SP)+,R0	;T2(3,2) = ST5*ST6
	MUL	ST5-4(SP),R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,@#T232
	MOV	(SP),@#T233	;T2(3,3) = CT5
	MOV	(SP)+,R0	;T2(3,4) = CT5*S6 + S4
	MUL	@#S6,R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	ADD	@#S4,R0
	MOV	R0,@#T234
	MOV	(SP),R2		;SAVE ST5
	MOV	(SP)+,R0	;T2(1,3) = CT4*ST5
	MUL	(SP)+,R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,@#T213
	MUL	@#S6,R0		;T2(1,4) = CT4*ST5*S6
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,@#T214
	MUL	(SP)+,R2	;T2(2,3) = ST4*ST5
	ASHC	#2,R2
	TST	R3
	BPL	.+4
	INC	R2
	MOV	R2,@#T223
	MUL	@#S6,R2		;T2(2,4) = ST4*ST5*S6
	ASHC	#2,R2
	TST	R3
	BPL	.+4
	INC	R2
	MOV	R2,@#T224

;FINISHED COMPUTING LAST THREE COLUMNS OF T2
;	[MULTIPLY T1 AND T2 AND ADD BASE]

	MOV	R4,R0		;COMPUTE T ← T1 X T2
	MOV	#T111,R1
	MOV	#T212-6,R2
	JSR	PC,MATMUL
	ADD	@#BASEX,T14(R4)	;ADJUST FOR COORDINATES OF BASE
	ADD	@#BASEY,T24(R4)

;EXIT CLEANLY

	MOV	(SP)+,R5	;RESTORE REGISTERS
	MOV	(SP)+,R4
	MOV	(SP)+,R3
	MOV	(SP)+,R2
	RTS	PC

;END OF "UPDATE"
;SOLVE - COMPUTES JOINT ANGLES GIVEN A TRANSFORM

;GIVEN A TRANSFORM "T", THE REQUIRED JOINT ANGLES ARE DETERMINED IN
;SCALED DEGREES. IF ANY JOINT ANGLE IS OUTSIDE OF ITS PERMITTED RANGE
;OF MOVEMENT, THE STOP LIMIT CLOSEST TO THE PREVIOUS JOINT ANGLE IS
;RETURNED. ON COMPLETION OF EXECUTION, R0 CONTAINS BITS INDICATING
;THE JOINT(S) WHICH WERE COMPUTED TO BE OUT OF THEIR STOP LIMITS.  A
;SAMPLE CALLING SEQUENCE TO "SOLVE" FOLLOWS:
;
;		MOV	#T,R0		;LOAD ADDRESS OF TRANSFORM 
;		MOV	#THETA,R1	;LOAD POINTER TO JOINT ANGLES
;		MOV	FLAGS,R2	;CONFIGURATION BITS
;		JSR	PC,SOLVE
;		TST	R0		;EXACT SOLUTION?
;
;IN ADDITION TO THE PTR TO THE REQUIRED TRANSFORM AND THE JOINT ANGLE
;ARRAY, THIS ROUTINE REQUIRES R2 TO BE FILLED WITH FLAG BITS WHICH
;INDICATE ANY CHANGE IN ARM CONFIGURATION THAT IS ASSERTED.  IF NO
;NEW ARM CONFIGURATION IS ASSERTED, THE CONFIGURATION CURRENTLY
;INDICATED BY THE BITS IN "ARMFLG" WILL BE USED.THE ARM CONFIGURATION
;BITS ARE GIVEN BELOW. IF EITHER JOINT 4 OR 6 IS OUT OF RANGE FOR THE
;CURRENT CONFIGURATION AND NEITHER A "FLIP/NOFLIP" NOR A "ONPATH" 
;ASSERTION IS MADE, THE COMPLEMENTARY SOLUTION FOR JOINTS 4,5,6 WILL
;BE TRIED IN AN ATTEMPT TO FIND A VALID SOLUTION.

;REGISTERS USED:
;
;	R0,R1,R2 PASS ARGUMENTS AND R0,R1 ARE ALTERED

;CONFIGURATION SPECIFICATION BITS

LFRT	=1	;REQUEST CHANGE IN SHOULDER 
ART	=2	;ASSERT RIGHT SHOULDER

ABBL	=4	;REQUEST CHANGE IN ABOVE/BELOW APPROACH
ABELOW	=10	;ASSERT BELOW

FNOF	=20	;REQUEST CHANGE IN FLIP/NOFLIP
AFLIP	=40	;ASSERT FLIP

ONPATH	=100	;ON A STRAIGHT LINE PATH, CAN'T CHANGE CONFIGURATION

;CURRENT CONFIGURATION OF THE ARM

ISRGHT	=1	;1 = RIGHT SHOULDER, 0 = LEFT
ISBELW	=2	;1 = BELOW APPROACH, 0 = ABOVE
ISFLIP	=4	;1 = FLIPPED, 0 = NOT FLIPPED

;THE OUT OF RANGE BITS THAT ARE RETURNED IN R0 ARE DEFINED AS
;FOLLOWS:

JT1	=1	;JOINT 1
JT2	=2	;  "   2
JT3	=4	;  "   3
JT4	=10	;  "   4
JT5	=20	;  "   5
JT6	=40	;  "   6
TOCLSE 	=200	;POSITION TOO CLOSE TO  ARM
TOOFAR	=100	;    "     "  FAR  FROM  "
;	["SOLVE" - TX,TY,TZ]

SOLVE:	MOV	R5,-(SP)	;SAVE REGISTERS
	MOV	R4,-(SP)
	MOV	R3,-(SP)
	MOV	R2,-(SP)	;FLAG BITS
	MOV	R0,R4		;T
	MOV	R1,R5		;ANGLES

;COMPUTE POSITION OF THE END OF THE JT 3: TX,TY,TZ.  ALSO COMPUTE
;(TX**2+TY**2-(S2+S3)**2) FOR LATER

	MOV	T34(R4),R2	;TZ ← T34 - T33*S6
	MOV	T33(R4),R0
	MUL	@#S6S,R0
	TST	R1		;ROUND UP
	BPL	.+4
	INC	R0
	SUB	R0,R2
	SUB	@#S1,R2		;TZS1 ← TZ - S1
	MOV	R2,@#TZS1	;SAVE TZS1
	MOV	T14(R4),R2	;TX ← T14 - T13*S6 - X BASE POS.
	MOV	T13(R4),R0
	MUL	@#S6S,R0
	TST	R1
	BPL	.+4
	INC	R0
	SUB	R0,R2
	SUB	@#BASEX,R2
	MOV	R2,@#TX		;SAVE TX
	MUL	R2,R2		;R2 ← TX**2
	MOV	T23(R4),R0	;TY ← T24 - T23*S6 - Y BASE COORD.
	MUL	@#S6S,R0
	TST	R1
	BPL	.+4
	INC	R0
	ADD	@#BASEY,R0
	NEG	R0
	ADD	T24(R4),R0
	MOV	R0,@#TY		;SAVE TY
	MUL	R0,R0		;R0 ← TX**2 + TY**2 - (S2 + S3)**2
	ADD	R3,R1
	ADC	R0
	ADD	R2,R0
	SUB	@#S2S3S+2,R1
	SBC	R0
	SUB	@#S2S3S,R0
	MOV	R1,@#TXTYS+2	;SAVE IT
	MOV	R0,@#TXTYS
	BGE	SQRTOK		;TOO CLOSE?
	INC	R0		;MAYBE, (ERROR TOL = .05 IN)
	BNE	ISTOCL
	TST	R1
	BPL	ISTOCL
	CMP	#-2500.,R1	;.05**2
	BLT	.+10		;LET THIS PASS
ISTOCL:	BIS	#TOCLSE,@#EXACTS ;INDICATE ERROR
	CLR	R0
	BR	.+6
SQRTOK:	JSR	PC,SQRT		;SQRT(TX**2+TY**2-(S2+S3)**2)
;	["SOLVE" - JOINT 1]

	BIT	#LFRT,(SP)	;ASSERT LEFT OR RIGHT SHOULDER?
	BEQ	ISCONT		;NO
	BIC	#ISRGHT,@#ARMFLG	;ASSUME LEFTY
	BIT	#ART,(SP)	;RIGHTY?
	BEQ	NOTRGT
	BIS	#ISRGHT,@#ARMFLG	;RIGHTY IT IS
ISCONT:	BIT	#ISRGHT,@#ARMFLG	;-SQRT FOR RIGHT ARMS
	BEQ	.+4
	NEG	R0
NOTRGT:	MOV	R0,-(SP)
	MUL	@#TX,R0		;COS TH1 = (+-TX*SQRT(TX↑2+TY↑2-
	MOV	@#TY,R2		; (S2+S3)↑2))+TY*(S2+S3))/(TX↑2+TY↑2)
	MUL	@#S2S3,R2
	ADD	R3,R1
	ADC	R0
	ADD	R2,R0
	ASHC	#2,R0
	MOV	R0,@#CTT1
	MOV	(SP)+,R0	;SIN TH1 = (+-TY*SQRT(TX↑2+TY↑2-
	MUL	@#TY,R0		; (S2+S3)↑2))-TX*(S2+S3))/(TX↑2+TY↑2)
	MOV	@#TX,R2
	MUL	@#S2S3,R2
	SUB	R3,R1
	SBC	R0
	SUB	R2,R0
	ASHC	#2,R0
	MOV	@#CTT1,R1
	JSR	PC,ATAN2	;COMPUTE TH1
	CLR	R1		;JOINT 1 STOP LIMITS
	MOV	#JT1,R2
	JSR	PC,SAVJTL	;ADJUST IF OUT OF RANGE AND SAVE
	JSR	PC,SNCOS	;COMPUTE SIN/COS FOR LATER
	MOV	R0,@#STT1
	MOV	R1,@#CTT1
;	["SOLVE" - JOINT 3]

	MOV	@#TXTYS,R0	;SIN TH3=(TX↑2+TY↑2-(S2+S3)↑2+
	MOV	@#TXTYS+2,R1	;   (TZ-S1)↑2-(S4↑2+A2↑2))/(2*A2*S4)
	MOV	@#TZS1,R2
	MUL 	R2,R2
	ADD	R3,R1
	ADC	R0
	ADD	R2,R0
	MOV	R0,R2		;TXYZ=TX↑2+TY↑2-(S2+S3)↑2+(TZ-S1)↑2
	MOV	R1,R3
	SUB	@#S4A2S+2,R1
	SBC	R0
	SUB	@#S4A2S,R0
	ASHC	#3,R0
	MOV	R0,@#STT3	;SAVE SIN TH3
	MOV	@#A224,R0	;COS TH3=SQRT((4*A2↑2-TXYZ)*TXYZ)
	MOV	@#A224+2,R1
	SUB	R3,R1
	SBC	R0
	SUB	R2,R0
	BGE	NOTTOF		;BRANCH IF NOT TOO FAR TO REACH
	BIS	#TOOFAR,@#EXACTS	;INDICATE ERROR
	CLR	R0
	CLR	R1
NOTTOF:	ASHC	#3,R0
	ASHC	#3,R2
	MUL	R2,R0
	JSR	PC,SQRT		;NOW GET COS TH3
	BIT	#ABBL,(SP)	;ASSERT ABOVE OR BELOW APPROACH?
	BEQ	NOABBL		;NO
	BIC	#ISBELW,@#ARMFLG	;ASSUME ABOVE
	BIT	#ABELOW,(SP)	;BELOW?
	BEQ	ISABVE
	BIS	#ISBELW,@#ARMFLG	;ITS BELOW
NOABBL:	BIT	#ISBELW,@#ARMFLG	;-COS TH3 FOR ABOVE
	BNE	.+4
ISABVE:	NEG	R0
	BIT	#ISRGHT,@#ARMFLG	;RIGHT SHOULDERED ARM?
	BEQ	.+4
	NEG	R0		;IF RIGHT  -COS TH3
	MOV	R0,R1
	MOV	@#STT3,R0
	JSR	PC,ATAN2	;COMPUTE THETA 3
	MOV	#4,R1		;CHECK STOP LIMITS AND SAVE THETA 3
	MOV	#JT3,R2
	TST	(R5)+
	JSR	PC,SAVJTL
	JSR	PC,SNCOS	;COMPUTE SIN/COS THETA 3
	MOV	R0,@#STT3
	MOV	R1,@#CTT3
;	["SOLVE" - JOINT 2]

	MOV	@#TX,R0		;SIN(TH2)=((TX*CT1+TY*ST1)*CT3 - 
	MUL	@#CTT1,R0	;       (TZ-S1)*(ST3+(A2/S4)))/FACTOR
	MOV	@#TY,R2
	MUL	@#STT1,R2
	ADD	R3,R1
	ADC	R0
	ADD	R2,R0
	ASHC	#2,R0		;NORMALIZE AND ROUND
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,@#TX1Y1	;SAVE FOR LATER
	MUL	@#CTT3,R0
	MOV	@#STT3,R2
	ADD	@#A2DS4,R2
	CLC			;CAN BE AS MUCH AS 2
	ROR	R2
	MOV	R2,@#STA2S4
	MUL	@#TZS1,R2
	ASHC	#1,R2
	SUB	R3,R1
	SBC	R0
	SUB	R2,R0
	ASHC	#1,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,@#STT2
	MOV	@#TX1Y1,R0	;COS(TH2)=((TX*CT1+TY*ST1)*
	MUL	@#STA2S4,R0	;     (ST3+(A2/S4)) + (TZ-S1)*CT3
	ASHC	#1,R0
	MOV	@#TZS1,R2
	MUL	@#CTT3,R2
	ADD	R3,R1
	ADC	R0
	ADD	R2,R0
	ASHC	#1,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,R1
	MOV	@#STT2,R0
	JSR	PC,ATAN2	;COMPUTE THETA 2
	MOV	#2,R1		;CHECK STOP LIMITS AND SAVE
	MOV	#JT2,R2
	CMP	-(R5),-(R5)
	JSR	PC,SAVJTG
	ADD	(R5)+,R0	;COMPUTE SIN/COS (TH 2 + TH 3)
	JSR	PC,SNCOS
	MOV	R0,@#S23
	MOV	R1,@#C23
;	["SOLVE" - JOINT 5]

	MOV	T13(R4),R0	;COS TH5= (T13*CT1+T23*ST1)*S23
	MUL	@#CTT1,R0	;	  + T33*C23
	MOV	T23(R4),R2
	MUL	@#STT1,R2
	ADD	R3,R1
	ADC	R0
	ADD	R2,R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,@#T1323	;SAVE INTERMEDIATE TERM
	MUL	@#S23,R0
	MOV	T33(R4),R2
	MUL	@#C23,R2
	ADD	R3,R1
	ADC	R0
	ADD	R2,R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,@#CTT5
	MOV	@#T1323,R0	;SIN TH5=SQRT((T13*CT1+T23*ST1)*C23 
	MUL	@#C23,R0	;    -T33*S23)↑2+(T23*CT1-T13*ST1)↑2)
	MOV	T33(R4),R2
	MUL	@#S23,R2
	SUB	R3,R1
	SBC	R0
	SUB	R2,R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,@#CTT4	;THIS IS (COS TH4)*FACTOR
        MOV	T23(R4),R0	;NOW DO T23*CT1-T13*ST1
	MUL	@#CTT1,R0
	MOV	T13(R4),R2
	MUL	@#STT1,R2
	SUB	R3,R1
	SBC	R0
	SUB	R2,R0
	ASHC	#2,R0	
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,@#STT4	;THIS IS (SIN TH4)*FACTOR
	MUL	R0,R0		;SQUARE AND ADD BOTH TERMS
	MOV	@#CTT4,R2
	MUL	R2,R2
	ADD	R3,R1
	ADC	R0
	ADD	R2,R0
	JSR	PC,SQRT		;NOW HAVE SIN(THETA 5)
	MOV	@#CTT5,R1	;AND COS(THETA 5)
	BIT	#FNOF,(SP)	;ASSERT FLIP/NOFLIP?
	BEQ	NOFNOF		;NO
	BIC	#ISFLIP,@#ARMFLG	;ASSUME NOT FLIPPED
	BIT	#AFLIP,(SP)	;FLIP?
	BEQ	NOTFLP
	BIS	#ISFLIP,@#ARMFLG	;ITS FLIPPED
NOFNOF:	BIT	#ISFLIP,@#ARMFLG	;-SIN TH5 IF FLIPPED
	BEQ	.+4
	NEG	R0
NOTFLP:	JSR	PC,ATAN2	;COMPUTE THETA 5
	MOV	R0,@#THETA5
	MOV	#10,R1		;CORRECT FOR STOP LIMITS AND SAVE
	MOV	#JT5,R2
	TST	(R5)+
	JSR	PC,SAVJTB
;	["SOLVE" - DEGENERATE CASE AND JOINT 4]

	TST	R0		;ABS(THETA 5);
	BGE	.+4
	NEG	R0
	CMP	#46.,R0		;THETA 5 =0 (.5 DEGREES)
	BLT	NODEGN		;BRANCH IF NOT DEGENERATE
	MOV	T22(R4),R0	;COS TH4+TH6 = T22*CT1-T12*ST1
	MUL	@#CTT1,R0
	MOV	T12(R4),R2
	MUL	@#STT1,R2
	SUB	R3,R1
	SBC	R0
	SUB	R2,R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	R0,@#CTT6	;SAVE IT TEMPORARILY
	MOV	T21(R4),R0	;SIN TH4+TH6= T21*CT1-T11*ST1
	MUL	@#CTT1,R0
	MOV	T11(R4),R2
	MUL	@#STT1,R2
	SUB	R3,R1
	SBC	R0
	SUB	R2,R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	@#CTT6,R1
	JSR	PC,ATAN2	;COMPUTE THETA 4+6
	SUB	-4(R5),R0	;LEAVE TH4 THE SAME, CHANGE TH6
	JSR	PC,FIX180
	MOV	R0,R3		;SAVE JT 6
	MOV	#12,R1		;CHECK JT 6 STOP LIMITS
	MOV	#JT6,R2
	JSR	PC,SAVJTB
	BIT	#JT6,@#EXACTS	;JT 6 IN RANGE?
	BEQ	FINDGN		;YES
	MOV	R3,R0		;CORRECT TH4 BY JT6-STOP LIMIT
	SUB	-(R5),R0
	CMP	-(R5),-(R5)
	ADD	(R5),R0		;NEW TH4
	JSR	PC,FIX180
	MOV	R0,R3		;CHECK STOP LIMITS
	MOV	#6,R1
	MOV	#JT4,R2
	JSR	PC,SAVJTG
	BIT	#JT4,@#EXACTS	;JT 4 STILL IN RANGE?
	BEQ	FINDGN		;YES
	MOV	R3,R0		;NOW BOTH OUT OF RANGE
	JSR	PC,ADD180	;ADD 180 TO JT 4 AND 6
	MOV	R0,-(R5)
	CMP	(R5)+,(R5)+
	MOV	(R5),R0
	JSR	PC,ADD180
	MOV	R0,(R5)
FINDGN:	BIC	#JT4+JT6,@#EXACTS ;A SOLUTION IS ALWAYS POSSIBLE
	JMP	SOLDNE		;ALL DONE NOW

;NON-DEGENERATE CASE, JOINT 4

NODEGN:	MOV	@#CTT4,R1	;COS TH4=((T13*CT1+T23*ST1)*C23 
				;    -T33*S23)/ST5
        MOV	@#STT4,R0	;SIN TH4=(T23*CT1-T13*ST1)/ST5
	BIT	#ISFLIP,@#ARMFLG	;CORRECT FOR SIGN OF ST5
	BEQ	.+6
	NEG	R0
	NEG	R1
	JSR	PC,ATAN2	;COMPUTE THETA 4
	MOV	R0,@#THETA4
	MOV	#6,R1		;CORRECT FOR STOP LIMITS AND SAVE
	MOV	#JT4,R2
	CMP	-(R5),-(R5)
	JSR	PC,SAVJTG
;	["SOLVE" - JOINT 6]

	MOV	T11(R4),R0	;COS TH6=-((T11*CT1+T21*ST1)*S23
	MUL	@#CTT1,R0	;      +T31*C23)/ST5
	MOV	T21(R4),R2
	MUL	@#STT1,R2
	ADD	R3,R1
	ADC	R0
	ADD	R2,R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MUL	@#S23,R0
	MOV	T31(R4),R2
	MUL	@#C23,R2
	ADD	R3,R1
	ADC	R0
	ADD	R2,R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	NEG	R0
	MOV	R0,@#CTT6	;SAVE COS TH6*FACTOR
	MOV	T12(R4),R0	;SIN TH6=((T12*CT1+T22*ST1)*S23
	MUL	@#CTT1,R0	;      +T32*C23)/ST5
	MOV	T22(R4),R2
	MUL	@#STT1,R2
	ADD	R3,R1
	ADC	R0
	ADD	R2,R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MUL	@#S23,R0
	MOV	T32(R4),R2
	MUL	@#C23,R2
	ADD	R3,R1
	ADC	R0
	ADD	R2,R0
	ASHC	#2,R0
	TST	R1
	BPL	.+4
	INC	R0
	MOV	@#CTT6,R1
	BIT	#ISFLIP,@#ARMFLG	;CORRECT FOR SIGN OF ST5
	BEQ	.+6
	NEG	R0
	NEG	R1
	JSR	PC,ATAN2	;COMPUTE THETA 6
	MOV	R0,R3
	MOV	#12,R1		;CORRECT FOR STOP LIMITS AND SAVE
	MOV	#JT6,R2
	TST	(R5)+
	JSR	PC,SAVJTB
;	["SOLVE" - NEED TO FLIP?, EXIT]

	BIT	#JT4+JT6,@#EXACTS  ;JT 4 AND 6 IN RANGE?
	BEQ	SOLDNE		;YES
	BIT	#ONPATH+FNOF,(SP)  ;FREE TO CHANGE FLIP/NF?
	BNE	SOLDNE		;NO, WE LOSE
	BIC	#JT4+JT5+JT6,@#EXACTS ;TRY FLIPPING
	MOV	#ISFLIP,R0	;CHANGE SENSE OF FLIP/NF
	XOR	R0,@#ARMFLG
	MOV	@#THETA4,R0	;ADD 180 DEG TO THETA 4
	JSR	PC,ADD180
	MOV	#6,R1		;ADJUST FOR STOP LIMITS
	MOV	#JT4,R2
	SUB	#6,R5
	JSR	PC,SAVJTG
	MOV	@#THETA5,R0	;FLIP THETA 5
	NEG	R0
	MOV	#10,R1		;ADJUST FOR STOP LIMITS
	ASL	R2
	JSR	PC,SAVJTB
	MOV	R3,R0		;ADD 180 DEG TO THETA 6
	JSR	PC,ADD180
	MOV	#12,R1		;ADJUST FOR STOP LIMITS
	ASL	R2
	JSR	PC,SAVJTB

SOLDNE:	MOV	@#EXACTS,R0	;INDICATE IF ANY JOINT OUT OF RANGE
	BIC	#TOCLSE+TOOFAR,@#EXACTS
	MOV	(SP)+,R2
	MOV	(SP)+,R3
	MOV	(SP)+,R4
	MOV	(SP)+,R5
	RTS	PC

;END OF "SOLVE"
;	["SOLVE" - SUBROUTINES]

;SUBROUTINES FOR CHECKING STOP LIMITS AND SAVING NEW JOINT ANGLE

SAVJTG:	CMP	USTOP(R1),R0	;MORE THAN MAX?
	BGE	JTINRG		;BRANCH IF OK
	BIS	#100000,R0	;NO, SUBT 360 DEG
	CMP	LSTOP(R1),R0	;LESS THAN MIN?
	BLE	JTINRG
	BR	ISOUT		;OUT OF RANGES

SAVJTL:	CMP	LSTOP(R1),R0	;OPPOSITE FOR JOINTS WITH
	BLE	JTINRG		;    ABS(MIN)<ABS(MAX)
	BIC	#100000,R0	;NO, ADD 360 DEG
	CMP	USTOP(R1),R0	;MORE THAN MAX?
	BGE	JTINRG		;OK
	BR	ISOUT		;OUT OF RANGES

SAVJTB:	CMP	USTOP(R1),R0	;CHECK BOTH HIGH AND LOW LIMITS
	BLT	ISOUT  		;BRANCH IF OUT OF RANGE
	CMP	LSTOP(R1),R0	;LESS THAN MIN?
	BLE	JTINRG		;OK

ISOUT:	BIS	R2,@#EXACTS	;INDICATE NO EXACT SOLUTION
	MOV	(R5),R0		;SUBSTITUTE HIGH OR LOW STOP LIMIT?
	CMP	MIDANG(R1),R0
	BGT	USELOW
	MOV	USTOP(R1),R0	;USE MAX
	BR	SAVANG
USELOW:	MOV	LSTOP(R1),R0	;USE MIN
	BR	SAVANG

JTINRG:	BIT	R2,@#EXACTS	;OUT OF RANGE LAST TIME?
	BEQ	SAVANG		;NO
	BIC	R2,@#EXACTS	;ASSUME COMING IN RANGE
	MOV	(R5),R1		;OLD ANGLE
	XOR	R0,R1
	BPL	SAVANG		;BRANCH IF COMING IN
	MOV	(R5),R0		;ELSE STILL OUT
	BIS	R2,@#EXACTS
SAVANG:	MOV	R0,(R5)+	;SAVE NEW ANGLE
	RTS	PC

;SUBROUTINE FOR SHIFTING AN ANGLE TO BETWEEN -180 AND +180

ADD180:	ADD	#40000,R0	;ADD 180 AND FIX

FIX180:	ASL	R0
	CLC
	BPL	.+4
	SEC
	ASR	R0
	RTS	PC
;FLAGS  - INITIALIZES THE ARM CONFIGURATION FLAGS AN ERROR BITS

;THIS ROUTINE CAN BE CALLED TO INITIALIZE THE ARM CONFIGURATION FLAGS
;WHICH ARE STORED IN "ARMFLG" TO COINCIDE WITH THE CURRENT STATE OF
;THE ARM.  THE ONLY ARGUMENT REQUIRED BY THIS ROUTINE IS A POINTER TO
;A ARRAY OF JOINT ANGLES.  A SAMPLE CALLING SEQUENCE FOLLOWS:
;
;			MOV	#THPTR,R0
;			JSR	PC,FLAGS
;
;AS A SIDE AFFECT, ALL ARM OUT OF RANGE BITS ARE CLEARED BY A CALL TO
;THIS ROUTINE.

;REGISTERS USED:
;	R0 PASSES ARGUMENT AND R0,R1 ARE GARBAGED

FLAGS:	MOV	R2,-(SP)
	CLR	@#ARMFLG	;DEFAULT CONFIGURATION
	MOV	2(R0),R1	;SIN(TH2+TH3)+SIN(TH2+90) => SHOULDER
	ADD	4(R0),R1
	ASL	R1		;SHIFT TH2+TH3 TO QUADRANT 1 OR 4
	ADD	#40000,R1
	BPL	.+4
	NEG	R1
	SUB	#40000,R1
	ASR	R1
	MOV	2(R0),R2	;SHIFT TH2+90 TO QUADRANT 1 OR 4
	ASL	R2
	ADD	#100000,R2
	BPL	.+4
	NEG	R2
	SUB	#40000,R2
	ASR	R2
	ADD	R2,R1		;HAVE SIGN(SIN(TH2+TH3)+SIN(TH2+90))
 	BPL	.+10
	BIS	#ISRGHT,@#ARMFLG	;ITS A RIGHTY
	MOV	4(R0),R1	;TH3+SHOULDER DETERMINES ABOVE/BELOW
	ADD	#20000,R1	;+90
	ASL	R1
	BMI	.+10
	BIS	#ISBELW,@#ARMFLG	;TH3 SAYS IT BELOW
	MOV	#ISBELW,R1
	BIT	#ISRGHT,@#ARMFLG	;WHICH SHOULDER?
	BEQ	.+6
	XOR	R1,@#ARMFLG	;RIGHTY'S SWITCH SENSE OF ABOVE/BELOW
	TST	10(R0)		;TH5 DETERMINES FLIP/NOFLIP
	BPL	.+10
	BIS	#ISFLIP,@#ARMFLG	;TH5<0 MEANS FLIPPED
	CLR	@#EXACTS	;INDICATE NO JOINTS OUT OF RANGE
	MOV	(SP)+,R2
	RTS	PC

;END OF "FLAGS"
;LOCAL STORAGE

EXACTS:	.WORD	0		;BITS OF JT WITH NO EXACT SOL

ARMFLG:	.WORD	0		;PREVIOUS ARM CONFIGURATION


;STORAGE AREA FOR T1 AND T2 TRANSFORMS

T111:	.WORD	0
T121:	.WORD	0
T131:	.WORD	0
T112:	.WORD	0
T122:	.WORD	0
T132:	.WORD	0
T113:	.WORD	0
T123:	.WORD	0
T133:	.WORD	0
T114:	.WORD	0
T124:	.WORD	0
T134:	.WORD	0

T212:	.WORD	0
T222:	.WORD	0
T232:	.WORD	0
T213:	.WORD	0
T223:	.WORD	0
T233:	.WORD	0
T214:	.WORD	0
T224:	.WORD	0
T234:	.WORD	0

;INTERMEDIATE VARIABLES FOR "SOLVE"

TX:	.WORD	0		;X,Y,Z FOR END OF JOINT 3
TY:	.WORD	0
TZS1:	.WORD	0		;TZ-S1
TXTYS:	.WORD	0		;TX**2+TY**2-S2**2-S3**2
	.WORD	0
TX1Y1:	.WORD	0		;TX*CT1+TY*ST1
T1323:	.WORD	0		;T13*CT1+T23*ST1
STA2S4:	.WORD	0		;ST3+(A2/S4)

STT1:	.WORD	0	;SIN/COS THETA 1
CTT1:	.WORD	0
STT2:	.WORD	0	;SIN THETA 2
STT3:	.WORD	0	;SIN/COS THETA 3
CTT3:	.WORD	0
S23:	.WORD	0	;SIN/COS (TH2 + TH3)
C23:	.WORD	0
STT4:	.WORD	0	;SIN/COS THETA 4 (ALMOST)
CTT4:	.WORD	0
CTT5:	.WORD	0	;COS THETA 5
CTT6:	.WORD	0	;COS THETA 6
THETA4:	.WORD	0
THETA5:	.WORD	0

;END OF "ARMSOL"