swh:1:snp:92f3f585b9ae79620ad8c41a332d6329b31fd381
Raw File
Tip revision: 078c79d8734a9ed2860303a7c1662004284fe853 authored by Ron Burkey on 07 August 2022, 15:04:04 UTC
Fixed a potential string-overflow bug in yaASM. Removed timestamps from
Tip revision: 078c79d
ASCENT_STEERING.agc
### FILE="Main.annotation"
## Copyright:	Public domain.
## Filename:	ASCENT_STEERING.agc
## Purpose:	A module for revision 0 of BURST120 (Sunburst). It 
##		is part of the source code for the Lunar Module's
##		(LM) Apollo Guidance Computer (AGC) for Apollo 5.
## Assembler:	yaYUL
## Contact:	Ron Burkey <info@sandroid.org>.
## Website:	www.ibiblio.org/apollo/index.html
## Mod history:	2016-09-30 RSB	Created draft version.
##		2016-10-24 RSB	Transcribed.
##		2016-10-31 RSB	Typos.
##		2016-11-01 RSB	More typos.
##		2016-12-06 RSB	Comment proofing via octopus/ProoferComments
##				performed, and changes made.

## Page 913
#    PROGRAM NAME--ASCENT        BY--BERMAN
#     ASCENT IS AN E-GUIDANCE SCHEME WHICH PRODUCES A DESIRED UNIT THRUST VECTOR DURING ASCENT BURNS, WITH THE
# CURRENT STATE AND ESTIMATED TGO,AND ESTIMATED VCO (VELOCITIES IN ASCENT ARE DEFINED IN LOCAL VERTICAL SYSTEMS),
# RCO IS ESTIMATED. THIS ENABLES THE LAMBERT SUBROUTINE TO SOLVE FOR A BETTER VCO. THIS AND V ALLOW US TO IMPROVE
# THE ESTIMATE OF TGO. FINALLY, TGO AND THE DESIRED CHANGES IN R AND V ARE USED TO COMPUTE UT.
#    MODING SWITCHES
#       HC--IF 0, ABVAL(RCO) IS CONSTRAINED TO A SPECIFIED VALUE-- IF 1, ABVAL(RCO) IS NOT CONSTRAINED, BUT IS
#           ESTIMATED.
#       PASS-- IF 0, USE LAMBERT TO UPDATE VCO-- IF 1, SKIP LAMBERT. PASS IS INVERTED EVERY ENTRY TO ASCENT, THUS
#           LAMBERT IS USED EVERY OTHER ENTRY.
#       DIRECT-- IF 0, SPECIFIED INJECTION CONDITIONS ARE USED AND PASS IS SET PERMANENTLY TO 1 AFTER THE FIRST
#           ENTRY-- IF 1, LAMBERT IS USED FOR TARGETING UNDER CONTROL OF            PASS.

# CALLING SEQUENCE
#    ASCENT IS ENTERED IN INTERPRETIVE BY
#                                                  GOTO
#                                                         ASCENT

# NORMAL EXIT
#    NORMAL EXIT FROM ASCENT IS BY
#                                                  GOTO
#                                                         ASCRET

# WHERE THE PREAPS PROGRAM PUTS A RETURN ADDRESS IN ASCRET FOR THE FIRST (PRE-IGNITION) ENTRY, AND THEN STORES
# FINDCDUD IN ASCRET SO THAT SUBSEQUENT EXITS WILL BE TO FINDCDUD.

# DEBRIS
#    USES 118 ERASABLE LOCATIONS CURRENTLY ASSIGNES TO  AMEMORY  THRU  AMEMORY +117. (SEE PG. 32 OF SUNBURST FOR
# VARIABLE NAMES.

# RESERVED LOCATIONS
#    THE FOLLOWING 44 LOCATIONS MUST NOT BE DISTURBED DURING MP13 OR MP4 -- PAXIS1,QAXIS,SAXIS,ATMEAS,RDOTD,YDOTD,
# ZDOTD,RCO,TGO,PCONS,PRATE,TINT,TREF,YCONS,ASCRET. THE REMAINING 74 LOCATIONS MAY BE USED BETWEEN EXIT FROM
# ASCENT AND RE-ENTRY INTO THE THRUST MAGNITUDE FILTER, ATMAG.
		BANK	32
		EBANK=	TCO
ASCENT		VLOAD	V/SC		# FORM GRAVITY SCALED 2(10)M/CS/CS FROM
			GDT1/2		# GDT1/2 SCALED 2(-7)M/CS
			2SEC(18)
		AXC,1	DOT		# LOAD X1 WITH -5   (OLD NSHIFT CONTENTS)
			5
			UNITR		# G,URX2(9)=GRX2(9)
		PDVL	VXV		# STORE IN PDL(0)			 2
			UNITR		# LOAD UNITR*2(-1)
			VN		# UR*2(-1) X VN*2(-7)=H/R*2(-8)
		VSQ	DDV		# H(2)/R(2)*2(-16)
			RMAG		# H(2)/R(3)*2(9)
		SL1	DAD
		BON
			BAKTO4
## Page 914
			GFKNOWN		# DURING PROCO1, GO BACK TO MP4
		STOVL	GEFF		# STORE GEFFX2(9) (POS UP)
			UNITR		# LOAD URX2(-1)
		VXV	UNIT		# URX2(-1)XQX2(-1)=ZAXISXSIN
			QAXIS		# ZAXISX2(-1)
		STORE	ZAXIS		# STORE ZAXIS
		VXV	VCOMP		# ZAXISX2(-1)XQAXISX2(-1)=-MAXISX2(-2)
			QAXIS		# MAXISX2(-2)
		VSL1	PDVL		# MAXISX2(-1) IN PDL(0)                  6
			UNITR		# LOAD URX2(-1)
		DOT	SL1		# URX2(-1).VX2(-7)=VRX2(-8)
			VN		# SHIFT TO VRX2(-7)
		STOVL	RDOT		# STORE IN RDOT
			ZAXIS		# LOAD ZAXISX2(-1)
		DOT	SL1		# ZAXISX2(-1).VX2(-7)=ZDOTX2(-8)	(6
			VN		# SHIFT TO ZDOTX2(-7)
		STOVL	ZDOT		# STORE IN ZDOT
			ZAXIS		# LOAD ZAXISX2(-1)
		VXV	VSL1		# Z*2(-1)XUR*2(-1)=LAXIS*2(-2)
			UNITR		# SHIFT TO LAXIS*2(-1)
		STORE	LAXIS		# STORE
		DOT	SL1		# LAXIS.VN=YDOT*2(-8)
			VN		# SHIFT TO YDOT*2(-7)
		STOVL	YDOT		# STORE IN YDOT
			00D		# LOAD MAXISX2(-1)
		DOT	SL2		# MAXISX2(-1).SX2(-1)=RZX2(-2)
			SAXIS		# SHIFT TO RZ
		PUSH	DSQ		# STORE RZ IN PDL(6)			 8
		PUSH	DMP		# STORE RZ(2) IN PDL(8)			10
			DP3/80		# 3/8ORZ(2)
		DAD	DMP		# 1/12+3/8ORZ(2)
			1/12TH		# RZ(2)/12+3/8ORZ(4)			 8
		DAD	DMP		# 1/2+RZ(2)/12+3/8ORZ(4)
			DP.5		# RZ(...)				 6
		DMP	SR2		# Z*2(-26)
			RCO		# SHIFT TO Z*2(-28)
		PDVL	DOT		# STORE Z IN PDL(6)			 8
			UNITR		# LOAD URX2(-1)
			QAXIS		# URX2(-1).QX2(-1)=RYX2(-2)
		STORE	RY		# STORE IN RY
		DSQ	DMP		# RY(2)X2(-4)				(8
			DP2/3H		# RY(2)/24
		DAD	DMP
			DP.25		# 1/4+RY(2)/24
			RY		# RY(1+RY(2)/6)/16
		DMP	SL4		# RCORY(1+RY(2)/6)X2(N-34)=YX2(N-34)
			RCO		# YX2(N-30)
		PDDL	DSU		# STORE IN PDL(8)		       (10
			TGO		# LOAD TGO*2(-17)
			DTASC		# (TGO-DT)*2(-17)
## Page 915
		STORE	TGO		# REPLACE IN TGO
		BOFF	DLOAD		# IF HC=0, GO TO HOLDR
			HC
			HOLDR
			RDOT		# LOAD RDOT*2(-7)
		DAD	DMP		# (RDOT+RDOTD)*2(-7)
			RDOTD
			TGO		# TGO(RDOT+RDOTD)*2(-24)
		SR1	DAD		# SHIFT TO RGO*2(-24)
			RMAG		# FORM RCO*2(-24)
		SR1			# SHIFT TO RCO*2(-24)
		STORE	RCO		# STORE IN RCO
		
HOLDR		BOFF
			DIRECT
			GAIN
LAMPREP		BOFF	DLOAD		# IF LAMB NOT DONE, GO TO GAIN+1
			DONESW
			GAIN
			YDOT		# LOAD YDOT*2(-7)
		DMP	PDDL		# YDOT TGO*2(-24)
			TGO		# PUSH DOWN				12
			YDOTD		# LOAD YDOTD*2(-7)
		DMP	DAD		# YDOTD TGO*2(-24)
			TGO		# TGO(YDOT+YDOTD)*2(-24)		10
		SL*	DAD		# YGO/2*2(N-30)
			0	-7,1	#					 8
		STADR			# YCO*2(N-30)
		STODL	32D		# STORE IN PDL(32)
			ZDOT		# LOAD ZDOTX2(-7)
		DAD	DMP		# (ZDOT+ZDOTD)X2(-7)
			ZDOTD		# TGO(ZDOT+ZDOTD)X2(-24)
			TGO
		SL*	DAD		# SHIFT TO TGO(ZDOT+ZDOTD)X2(N-34)
			0	-10D,1	# ZCOX2(N-33)				 6
		DDV	DDV		# ZRADCO/8
			RCO
			PI/4		# ZRADCO/2PI
		PUSH	COS		# STORE IN PDL(6),TAKE 1/2COS		 8
		PDDL	SIN		# EXCH.ZRADCO/2PI WITH .5COS,TAKE .5SIN  8
		PUSH	VXSC		# STORE 1/2SIN IN PDL(8)		10
			SAXIS		# S/4SIN
		PDDL	VXSC		# STORE IN PDL(10),LOAD1/2COS		16
			06D		# P/4COS
			PAXIS1
		VAD			# S/4SIN+P/4COS,			10
		PDDL			# STORE IN PDL(10)			16
			32D		# LOAD YCOX2(N-30)
		DSQ	PDDL		# YCO(2)X2(2N-60),STORE IN PDL(16)	18
			RCO		# LOAD RCOX2(N-30)
## Page 916
		DSQ	DSU		# (RCO(2)-YCO(2))X2(2N-60)		16
		SQRT	VXSC		# (RCO(2)-YCO(2))(1/2)X2(N-30)XPDL(10)	10
		VSL1	PDDL		# SHIFT TO ROOT*(SSIN+PCOS)*2(N-31)
			32D		# STORE PS TERMS IN PDL(10),LOAD YCO	16
		VXSC	VAD		# QYCOX2(N-31)
			QAXIS		# ADD PS TERMS,GET RCOX2(N-31)		10
		VSL1			# SHIFT TO RCOV*2(N-30)
		BOFF
			PASS
			OLDRCO
		STORE	RCOV		# STORE CUTOFF POSITION
OLDRCO		STORE	RCOTEMPV
		VXV	UNIT
			R1VEC
		SIGN	GOTO
			TAG5		# PATCH IN THRUST MAGNITUDE FILTER LOG
			ASCPATCH	# SECTION SO IT IS AT END OF BANK.
			
ENDPATCH	STORE	URCO
		VXV	UNIT		# GET LOCAL Z-AXIS
			QAXIS
		SETPD			# CLEAR PDC
			00D		# RESET PDC TO 0			 0
		STODL	H1		# STORE H1
			TINT		# LOAD TINT*2(-28)
		DSU	BON
			TCO		# IF PASS=1, USE RAW TFL
			PASS
			USEIT		# IF PASS=0, AVERAGE TFL
		DAD	SR1
			TFL
USEIT		STORE	TFL
		CLEAR
			DONESW
		BONCLR
			CONVSW		# LAMBERT'S ITERATING PROCESS IS NOT
			ASCALARM	# CONVERGING WELL TO VOVEC - HENCE ALARM
		EXIT
ALARMRET	CA	LAMPRIO
		INHINT
		TC	FINDVAC		# SET UP LAMBERT JOB
		EBANK=	SPLOC
		2CADR	LAMBSET
		
		RELINT
		CCS	NEWJOB		# CHECK FOR LAMBERT INTERRUPT
		TC	CHANG1
DUMPLOC		TC	INTPRET		# HIGH PRIO FOR LAMB DURING PREBURN PASS
		VLOAD	PUSH		# WILL CAUSE INTERRUPT HERE.
			V0VEC		# LOAD V0VEC, RESCALE FOR ASCENT
## Page 917
		DOT	SL1		# V1*2(-7) IN PDL(0)
			URCO		# V1.URCO=RDOTD*2(-8)
		STOVL	RDOTD		# STORE IN RDOTD
			00D		# LOAD V1*2(-7)
		DOT	SL1		# V1.N1*2(-8)=ZDOTD*2(-8)
			H1		# SHIFT TO 2(-7)
		STOVL	ZDOTD		# STORE IN ZDOTD,LOAD URCO*2(-1)
			URCO
		VXV	DOT		# URCOXH1*2(-2)=-UYCO*2(-2)
			H1		# -UYCO.V1*2(-9)=-YDOTD*2(-9)		 0
		SL2	DCOMP		# +YDOTD*2(-7)
		STOVL	YDOTD
			RCOTEMPV
		STORE	RCOV
GAIN		DLOAD	SETPD		# LOAD YDOTD
			YDOTD
			02D		# SET PDC AT 2				 2
		DSU	PUSH		# (YDOTD-YDOT)X2(-7)=DYDOTX2(-7)
			YDOT		# STORE IN PDL(2)			 4
		STODL	32D		# STORE DYDOT IN 32			(2
			ZDOTD		# LOAD ZDOT
		DSU
			ZDOT
		STORE	00D		# STORE IN PDL(0)
		STODL	30D		# ALSO IN 30
			GEFF		# LOAD GEFF
		DMP	SL1		# GEFF TGOX2(-8)
			TGO		# SHIFT TO 2(-7)
		PDDL	DSU		# STORE IN PDL(4)			 6
			RDOTD		# LOAD RDOTD
			RDOT		# DRDOTX2(-7)
		STORE	28D		# STORE IN 28
		DSU	VDEF		# DRDOT-TGOGEFF,DEFINE VGX2(-7)	       0,4
		STADR
		STORE	VGVECT		# FOR DOWNLINK
		ABVAL	DSU		# GET VG(SCALAR)
			VTO		# SUBTRACT TAILOFF
		DDV	PUSH		# VG*2(-7)/V3*2(-7)=VG/VE
			VE		# STORE IN PDL(0)7)=VG/VE		 2
		DMP	BDSU		# KTVG/VE
			KT		# 1/2-KTVG/VE
			DP.5
		DAD	DMP		# 1-KTVG/VE
			DP.5		# VG/VE(1-KTVG/VE)=TGO/TBUP		 0
		PUSH	DMP		# STORE TGO/TBUP IN PDL(0)		 2
			TBUP		# TGOX2(-17)
		STORE	TGO		# STORE
		DSU	BMN		# IF TGO SMTHAN 4SEC,GO TO SET UP ENGOFF
			2SEC(16)	# 2*2(-16)=4*2(-17)
			ENGOFF

## Page 918
KEEPGOIN	BONCLR	RTB		# DURING PRECOI, GO BACK TO MP4
			BAKTO4
			TKNOWN
			LOADTIME
		STORE	TIME
		DLOAD	SR
			TGO		# TGO*2(-17)
			11D		# TGO*2(-28)
		STORE	TTGO		# FOR DOWNLINK
		BONCLR	DAD		# IF PASS ON, DO NOT COMPUTE TCO.
			PASS		# CLEAR PASS ,GO TO AFTTCO
			AFTTCO
			TIME		# T+TGO=TCO*2(-28)
		STODL	TCO		# STORE TCO				(2
			T2		# LOAD T2X2(-17)
		DSU	BPL		# T2-TGO
			TGO
			AIMER		# IF T2-TGO POS,GO TO AIMER
			
AFTTCO		DLOAD	DSU		# LOAD TGO*2(-28)
			TIME		# SUBTRACT 100 CS, 1/2DT
			100CS		# (T-.5DT)*2(-28)
		STODL	TREF		# *2(-28)
			TGO		# LOAD TGOX2(-17)
		DMP	DAD		# RDOT TGO*2(-24)
			RDOT		# (R+RDOT TGO)*2(-24)
			RMAG
		SR1	BDSU		# *2(-25)
			RCO		# RCO-R-RDOT TGO=DR*2(-25)
		STODL	26D		# STORE DR IN 26,LOAD TGO/TBUP
		BDSU	DAD		# 1/2-TGO/TBUP
			DP.5
			DP.5		# 1-TGO/TBUP
		CALL
			LOGSUB		# CALL LOG SUBROUTINE
			
		SL	PUSH		# SHIFT TO -L,STORE IN PDL(0)		 2
			5
		BDDV	BDSU		# -TGO/L*2(-17)
			TGO
			TBUP		# (TBUP+TGO/L)*2(-17)=D12*2(-17)
		PDDL	DSU		# D12 IN PDL(2)				 4
			TGO
			T3		# TGO-T3
		BPL	DLOAD		# IF TGO-T3 POS,GO TO RATE
			RATER
			DP0		# SET B=0
		STORE	PRATE
		SETGO			# SET HC=1,GO TO CONST
			HC		
## Page 919
			CONST
			
RATER		DLOAD	DSU		# TGO
			TGO
			02D		# TGO-D12=D21X2(-17)
		PDDL	SR1		# D21 IN PDL(4)				 6
			TGO		# LOAD TGOX2(-17),SHIFT TO 1/2
		DSU	SL		# .5TGO-D21=D*2(-17)
			04D		# SHIFT TO D*2(-12)
			05D		
		PDDL	DMP		# STORE D IN PDL(6),LOADDRDOT*2(-7)	 8
			28D		# D21 DRDOT*2(-24)
			04D
		SR1	DSU		# SHIFT TO 2(-25)
			26D		# (D21 DRDOT-DR)*2(-25)
		DDV	DDV		# DIVIDE BY TGO*2(-17)
			TGO		# DIVIDE BY D*2(-12),GET B*2(4)		 6
		SETPD			# REDUCE PDC TO 4			 4
			04D
		STORE	PRATE		# STORE B*2(4)
CONST		DLOAD	DDV		# LOAD DRDOTX2(-7)
			28D		# DRDOT/-LX2(-7)
			00D
		SR1	PDDL		# EXCH DRDOT/-L*2(-8) WITH D12 IN PDL(2) 4
		DMP	SL		# D12 PRATE*2(-16)
			PRATE		# SHIFT TO 2(-8)
			5
		BDSU			# PULL DRDOT/-L,GET A*2(-8)		 2
		STADR
		STODL	PCONS		# STORE A*2(-8) IN PCONS
			32D		# LOAD DYDOTX2(-7)
		DDV	SR1		# DYDOT/-L*2(-7)=C*2(-7)
			00D		# SHIFT TO 2(-8)
		STORE	YCONS		# STORE C*2(-8) IN YCONS
		
AIMER		SETPD
			00D		#					 0
		DLOAD	DSU
			TIME
			TREF		# (T-TO)X2(-28)
		DMP	SL		# B(T-TO)*2(-24)
			PRATE		# SHIFT TO 2(-8)
			16D
		DAD	DDV		# (A+B(T-TO))*2(-8)
			PCONS		# DIVIDE BY TBUP*2(-17)
			TBUP
		DSU	VXSC		# SUBTRACT GEFF, GET ATR*2(9)
			GEFF
			UNITR		# ATR UR*2(8)
		PDDL	DDV		# STORE IN PDL(0),LOAD C*2(-8)		 6	
## Page 920
			YCONS
			TBUP		# C/TBUP*2(9)=ATY*2(9)
		VXSC	VAD		# ATY LAXIS*2(8)
			LAXIS		# (ATY LAXIS+ATR UR)*2(8)=AH*2(8)	 0
		VSL1	PUSH		# SHIFT TO AH*2(9),STORE IN PDL(0)	 6
		ABVAL	PDDL		# AH2X2(18) IN PDL(34),AHMAG IN MPAC
			AT		# STORE AHMAG IN PDL( 6),LOAD AT	 8
		DSQ	DSU		# AT(2)X2(18)
			34D		# (AT(2)-AH2)X2(18)=ATP2X2(18)
		PDDL	DMP		# STORE IN PDL( 8)			10
			AT		# LOAD AT X2(9)
			KR		# AT KRX2(8)
		SL1	PUSH		# 2(9),STORE IN PDL(10)			12
		DSQ	DSU		# AT(2)KR(2)X2(18)
			34D		#  -AH2X2(18) =ATP3X2(18)
		BMN	DLOAD		# IF ATP3 NEG,GO TO AIMING
			AIMING
			8D		# LOAD ATP2X2(18)
		SQRT			# ATPX2(9)
		GOTO
			AIMED

AIMING		DLOAD	BDDV		# KR AT/AH=KH FROMPDL(10,6)		 8
			06D
		VXSC			# KH AH*2(9)
			00D
		STODL	00D		# STORE NEW AH IN PDL(0)
			AT		# LOAD ATX2(9)
		DMP			# AT(1-KR(2))(1/2)X2(9)=ATPX2(9)
			KR1
			
AIMED		SIGN	VXSC		# GIVE SIGN TO ATP
			30D
			ZAXIS		# ATP ZAXISX2(8)
		VSL1	VAD		# ATP ZAXISX2(9)
			00D		# (ATPZAXIS+AH)X2(9)
		UNIT			# GET UT*2(-1)
		STORE	AXISD
		SETPD	CALL
			0
			ASCRET
		EXIT
ASCTERM		TC	PHASCHNG	# THE SERVEXIT PHASE CHANGE
		OCT	00035
		TCF	ENDOFJOB
		
100CS		2DEC	100

		2DEC	0.34		# KT WAS HERE, BUT NOW IS IN ERASABLE.	
## Page 921
DP3/80		2DEC	0.0375

2SEC(18)	2DEC	200	B-18

2SEC(16)	2DEC	200	B-16

T3		2DEC	1000	B-17

1/12TH		2DEC	0.083333333

DP.25		2DEC	0.25

DP2/3H		2DEC	.666666667

DTASC		2DEC	200	B-17

T2		2DEC	200	B-17

LAMBSET		TC	INTPRET		# CALL FOR LAMBERT SUBR.
		CALL
			LAMBERT
ENGOFF		BON	DLOAD
			ENGOFFSW
			KEEPGOIN
			TGO
		SL3	EXIT
		INHINT
		CAF	EBANK4		# INSURE THAT THE EBANK IS SET PROPERLY
		TS	EBANK
		EBANK=	TGO
		CA	MPAC
		TS	ENGOFFDT
		EXTEND	
		BZMF	ENGOFF2
		TC	WAITLIST
		EBANK=	TGO
		2CADR	ENGOFF3
		
		CS	FLAGWRD4	# BYPASS PHASCHNG WHEN IN MP 13.
		MASK	BIT8
		EXTEND
		BZF	ENGOFF1
		
		TC	PHASCHNG	# RESTART PROTECTION FOR ENGINOFF CALL
		OCT	47012
	       -GENADR	ENGOFFDT
	       	EBANK=	TGO
	       	2CADR	ENGOFF3

ENGOFF1		RELINT
## Page 922
		TC	INTPRET
		SET	GOTO
			ENGOFFSW
			KEEPGOIN
ENGOFF2		TC	EXEUNT
		TC	BANKCALL
		CADR	ENGINOFF
		TC	BANKCALL
		CADR	STOPRATE
		TCF	ASCTERM
ENGOFF3		TC	EXEUNT
		TC	IBNKCALL
		CADR	ENGINOFF
		TC	IBNKCALL
		CADR	STOPRATE
		CS	FLAGWRD4	# BYPASS PHASCHNG WHEN IN MP 13.
		MASK	BIT8
		EXTEND
		BZF	TASKOVER
		
		TC	PHASCHNG	# DEACTIVATE GROUP 2 AFTER SUCCESSFUL CALL
		OCT	00002
		
		TC	TASKOVER
EXEUNT		EXTEND			# DISENGAGE THE GUIDANCE EQUATIONS
		DCA	SERVEXAD
		DXCH	AVGEXIT
		TC	Q
		
		EBANK=	DVCNTR
SERVEXAD	2CADR	SERVEXIT

ASCALARM	EXIT
		TC	ALARM
		OCT	00405		# LAMBERT ITERATIONS NOT CONVERGING
		TCF	ALARMRET
		
# ************************************************************************
back to top