From 1c000fef961926b99eb15d421474a49ccbd83d94 Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Tue, 23 Jan 2001 07:17:47 +0000
Subject: [PATCH] Tweaks to add an altitude indicator adjustment.

---
 src/Cockpit/steam.cxx | 66 ++++++++++++++++++++++++++++++++++---------
 src/Cockpit/steam.hxx |  5 ++++
 src/Main/main.cxx     | 14 ++++-----
 3 files changed, 65 insertions(+), 20 deletions(-)

diff --git a/src/Cockpit/steam.cxx b/src/Cockpit/steam.cxx
index 3d01ff43f..bd58a1bc5 100644
--- a/src/Cockpit/steam.cxx
+++ b/src/Cockpit/steam.cxx
@@ -53,9 +53,16 @@ static bool isTied = false;
 
 
 double FGSteam::the_STATIC_inhg = 29.92;
-double FGSteam::the_ALT_ft = 0.0;
+double FGSteam::the_ALT_ft = 0.0;  // Indicated altitude
 double FGSteam::get_ALT_ft() { _CatchUp(); return the_ALT_ft; }
 
+double FGSteam::the_ALT_datum_mb = 1013.0;
+double FGSteam::get_ALT_datum_mb() { return the_ALT_datum_mb; }
+
+void FGSteam::set_ALT_datum_mb ( double datum_mb ) {
+    the_ALT_datum_mb = datum_mb;
+}
+
 double FGSteam::get_ASI_kias() { return FGBFI::getAirspeed(); }
 
 double FGSteam::the_VSI_case = 29.92;
@@ -104,6 +111,9 @@ void FGSteam::update ( int timesteps )
 	  isTied = true;
 	  fgTie("/steam/airspeed", FGSteam::get_ASI_kias);
 	  fgTie("/steam/altitude", FGSteam::get_ALT_ft);
+	  fgTie("/steam/altimeter-datum-mb",
+		FGSteam::get_ALT_datum_mb, FGSteam::set_ALT_datum_mb,
+		false);  /* don't modify the value */
 	  fgTie("/steam/turn-rate", FGSteam::get_TC_std);
 	  fgTie("/steam/slip-skid", FGSteam::get_TC_rad);
 	  fgTie("/steam/vertical-speed", FGSteam::get_VSI_fps);
@@ -124,6 +134,7 @@ void FGSteam::update ( int timesteps )
 #undef DF2
 
 
+/* tc should be (elapsed_time_between_updates / desired_smoothing_time) */
 void FGSteam::set_lowpass ( double *outthe, double inthe, double tc )
 {
 	if ( tc < 0.0 )
@@ -135,7 +146,7 @@ void FGSteam::set_lowpass ( double *outthe, double inthe, double tc )
 		}
 	} else
 	if ( tc < 0.2 )
-	{	/* Normal mode of operation */
+	{	/* Normal mode of operation; fast approximation to exp(-tc) */
 		(*outthe) = (*outthe) * ( 1.0 - tc )
 			  +    inthe  * tc;
 	} else
@@ -152,6 +163,24 @@ void FGSteam::set_lowpass ( double *outthe, double inthe, double tc )
 }
 
 
+#define INHG_TO_MB 33.86388  /* Inches_of_mercury * INHG_TO_MB == millibars. */
+
+// Convert air pressure to altitude by ICAO Standard Atmosphere
+double pressInHgToAltFt(double p_inhg)
+{
+    // Ref. Aviation Formulary, Ed Williams, www.best.com/~williams/avform.htm
+    const double P_0 = 29.92126;  // Std. MSL pressure, inHg. (=10135.25 mb)
+    const double p_Tr = 0.2233609 * P_0;  // Pressure at tropopause, same units.
+    const double h_Tr = 36089.24;  // Alt of tropopause, ft. (=11.0 km)
+
+    // return (P_0 - p_inhg) * 1000.0;  // ### crude approx. for low alt's
+    if (p_inhg > p_Tr)  // 0.0 to 11.0 km
+	return (1.0 - pow((p_inhg / P_0), 1.0 / 5.2558797)) / 6.8755856e-6;
+    return h_Tr + log10(p_inhg / p_Tr) / -4.806346e-5;  // 11.0 to 20.0 km
+    // We could put more code for higher altitudes here.
+}
+
+
 
 ////////////////////////////////////////////////////////////////////////
 // Here the fun really begins
@@ -287,24 +316,20 @@ void FGSteam::_CatchUp()
 	*/
 	the_ENGINE_rpm = controls.get_throttle(0) * 26.0;
 
-	/**************************
-	This is just temporary, until the static source works,
-	so we just filter the actual value by one second to
-	account for the line impedance of the plumbing.
-	*/
-	set_lowpass ( & the_ALT_ft, FGBFI::getAltitude(), dt );
-
 	/**************************
 	First, we need to know what the static line is reporting,
 	which is a whole simulation area in itself.  For now, we cheat.
+	We filter the actual value by one second to
+	account for the line impedance of the plumbing.
 	*/
-	the_STATIC_inhg = 29.92; 
-	i = (int) the_ALT_ft;
+	double static_inhg = 29.92; 
+	i = (int) FGBFI::getAltitude();
 	while ( i > 9000 )
-	{	the_STATIC_inhg *= 0.707;
+	{	static_inhg *= 0.707;
 		i -= 9000;
 	}
-	the_STATIC_inhg *= ( 1.0 - 0.293 * i / 9000.0 );
+	static_inhg *= ( 1.0 - 0.293 * i / 9000.0 );
+	set_lowpass ( & the_STATIC_inhg, static_inhg, dt ); 
 
 	/*
 	NO alternate static source error (student feature), 
@@ -312,6 +337,21 @@ void FGSteam::_CatchUp()
 	NO slip-induced error, important for C172 for example.
 	*/
 
+	/**************************
+	Altimeter.
+	ICAO standard atmosphere MSL pressure is 1013.25 mb, and pressure
+	gradient is about 28 ft per mb at MSL increasing to about 32 at
+	5000 and 38 at 10000 ft.
+	Standard altimeters apply the subscale offset to the output altitude,
+	not to the input pressure; I don't know exactly what pressure gradient
+	they assume for this.  I choose to make it accurate at low altitudes.
+	Remember, we are trying to simulate a real altimeter, not an ideal one.
+	*/
+	set_lowpass ( & the_ALT_ft,
+	    pressInHgToAltFt(the_STATIC_inhg) +
+	    (the_ALT_datum_mb - 1013.25) * 28.0, /* accurate at low alt. */
+	    dt * 10 ); /* smoothing time 0.1 s */
+
 	/**************************
 	The VSI case is a low-pass filter of the static line pressure.
 	The instrument reports the difference, scaled to approx ft.
diff --git a/src/Cockpit/steam.hxx b/src/Cockpit/steam.hxx
index 69911e1ae..ed31f803b 100644
--- a/src/Cockpit/steam.hxx
+++ b/src/Cockpit/steam.hxx
@@ -72,6 +72,10 @@ public:
 				// Engine Gauges
   static double get_VACUUM_inhg ();
 
+				// Atmosphere
+  static double get_ALT_datum_mb ();
+  static void set_ALT_datum_mb(double datum_mb);
+
 				// Hacks ... temporary stuff
   static double get_HackVOR1_deg ();
   static double get_HackOBS1_deg ();
@@ -83,6 +87,7 @@ public:
 
 private:
 	static double	the_ALT_ft;
+        static double	the_ALT_datum_mb;
         static double   the_TC_rad, the_TC_std;
 	static double	the_STATIC_inhg, the_VACUUM_inhg;
 	static double	the_VSI_fps, the_VSI_case;
diff --git a/src/Main/main.cxx b/src/Main/main.cxx
index 1d4b266f6..0cddd59dc 100644
--- a/src/Main/main.cxx
+++ b/src/Main/main.cxx
@@ -1058,18 +1058,18 @@ static void fgMainLoop( void ) {
 	    double mp_factor;
 	    if ( cur_fdm_state->get_engine(0) != NULL ) {
 		mp_factor = 
-		    cur_fdm_state->get_engine(0)->get_Manifold_Pressure() / 28;
+		    cur_fdm_state->get_engine(0)->get_Manifold_Pressure() / 100;
 	    } else {
-		mp_factor = 1.0;
+		mp_factor = 0.3;
 	    }
-	    // cout << "mp = " 
-	    //      << cur_fdm_state->get_engine(0)->get_Manifold_Pressure()
-	    //      << endl;
+	    /* cout << "mp = " 
+	         << cur_fdm_state->get_engine(0)->get_Manifold_Pressure()
+	         << endl; */
 
-	    double volume = mp_factor;
+	    double volume = 0.3 + mp_factor;
 
 	    if ( volume < 0.3 ) { volume = 0.3; }
-	    if ( volume > 2.0 ) { volume = 2.0; }
+	    if ( volume > 1.0 ) { volume = 1.0; }
 	    // cout << "volume = " << volume << endl;
 
 	    pitch_envelope.setStep  ( 0, 0.01, pitch );