-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
There are no files selected for viewing
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# flybywire-a32nx-fadec-v2 CMakeLists.txt | ||
|
||
# add additional compiler definitions for the a32nx fadec-v2 build | ||
add_definitions() | ||
|
||
# add the local include directories | ||
include_directories( | ||
${CMAKE_CURRENT_SOURCE_DIR}/src | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec | ||
${FBW_COMMON}/cpp-msfs-framework/ | ||
${FBW_COMMON}/fadec_common/src/ | ||
) | ||
|
||
# define the source files | ||
set(SOURCE_FILES | ||
${FBW_COMMON}/fadec_common/src/Fadec.cpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Gauge_Fadec_v2.cpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/Fadec_A32NX.cpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/EngineControlA32NX.cpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/FuelConfiguration_A32NX.cpp | ||
) | ||
|
||
set(INCLUDE_FILES | ||
${FBW_COMMON}/fadec_common/src/Fadec.h | ||
${FBW_COMMON}/fadec_common/src/EngineRatios.hpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/Fadec_A32NX.h | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/FadecSimData_A32NX.hpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/EngineControlA32NX.h | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/FuelConfiguration_A32NX.h | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/ThrustLimits_A32NX.hpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/Polynomials_A32NX.hpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/Tables1502_A32NX.hpp | ||
) | ||
|
||
# create the targets | ||
add_library(fadec-a32nx OBJECT ${SOURCE_FILES} ${INCLUDE_FILES}) | ||
add_wasm_library( | ||
NAME fadec-a32nx | ||
DEPENDENCIES fadec-a32nx cpp-msfs-framework-a32nx | ||
) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# A32NX FADEC | ||
|
||
This is a new version of the FADEC system for the A32NX. | ||
It is a migration and cleanup of the original FADEC system, | ||
and is designed to be more modular and easier to maintain. |
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// Copyright (c) 2023-2024 FlyByWire Simulations | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
#include "Fadec_A32NX.h" | ||
|
||
bool Fadec_A32NX::initialize() { | ||
engineControl.initialize(&msfsHandler); | ||
|
||
_isInitialized = true; | ||
LOG_INFO("Fadec_A32NX initialized"); | ||
return true; | ||
} | ||
|
||
bool Fadec_A32NX::update(sGaugeDrawData* pData) { | ||
if (!_isInitialized) { | ||
std::cerr << "Fadec_A32NX::update() - not initialized" << std::endl; | ||
return false; | ||
} | ||
|
||
engineControl.update(pData); | ||
|
||
return true; | ||
} | ||
|
||
bool Fadec_A32NX::shutdown() { | ||
_isInitialized = false; | ||
LOG_INFO("Fadec_A32NX::shutdown()"); | ||
return true; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Copyright (c) 2023-2024 FlyByWire Simulations | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
#ifndef FLYBYWIRE_AIRCRAFT_FADEC_A32NX_H | ||
#define FLYBYWIRE_AIRCRAFT_FADEC_A32NX_H | ||
|
||
#include "EngineControlA32NX.h" | ||
#include "Fadec.h" | ||
|
||
/** | ||
* @brief: The Fadec_A32NX class is responsible for managing the FADEC system for the A32NX aircraft. | ||
* | ||
* In this current implementation is only holding the EngineControl_A32NX instance and is | ||
* responsible for calling its initialize, update and shutdown methods. | ||
* The actual fadec logic is implemented in the EngineControl_A32NX class. | ||
*/ | ||
class Fadec_A32NX : public Fadec { | ||
private: | ||
// Engine control instance | ||
EngineControl_A32NX engineControl{}; | ||
|
||
public: | ||
/** | ||
* Creates a new Fadec_A32NX instance and takes a reference to the MsfsHandler instance. | ||
* @param msfsHandler The MsfsHandler instance that is used to communicate with the simulator. | ||
*/ | ||
explicit Fadec_A32NX(MsfsHandler& msfsHandler) : Fadec(msfsHandler) {} | ||
|
||
bool initialize() override; | ||
bool preUpdate(sGaugeDrawData*) override { return true; } | ||
bool update(sGaugeDrawData* pData) override; | ||
bool postUpdate(sGaugeDrawData*) override { return true; } | ||
bool shutdown() override; | ||
}; | ||
|
||
#endif // FLYBYWIRE_AIRCRAFT_FADEC_A32NX_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// Copyright (c) 2023-2024 FlyByWire Simulations | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
#include <iostream> | ||
#include <string> | ||
|
||
#include "inih/ini.h" | ||
#include "inih/ini_type_conversion.h" | ||
|
||
#include "logging.h" | ||
|
||
#include "FuelConfiguration_A32NX.h" | ||
|
||
void FuelConfiguration_A32NX::loadConfigurationFromIni() { | ||
if (configFilename.empty()) { | ||
LOG_ERROR("Fadec::FuelConfiguration_A32NX: no configuration file specified -> using default fuel" | ||
" quantities. Use setConfigFilename() to set the configuration file)"); | ||
return; | ||
} | ||
|
||
LOG_INFO("Fadec::FuelConfiguration_A32NX: loading configuration file " + configFilename); | ||
|
||
mINI::INIStructure ini; | ||
mINI::INIFile iniFile(configFilename); | ||
|
||
if (!iniFile.read(ini)) { | ||
LOG_ERROR("Fadec::FuelConfiguration_A32NX: failed to read configuration file \"" + configFilename + "\" due to error \"" + | ||
strerror(errno) + "\" -> using default fuel quantities."); | ||
return; | ||
} | ||
|
||
fuelCenter = mINI::INITypeConversion::getDouble(ini, INI_SECTION_FUEL, INI_SECTION_FUEL_CENTER_QUANTITY, fuelCenterDefault); | ||
fuelLeft = mINI::INITypeConversion::getDouble(ini, INI_SECTION_FUEL, INI_SECTION_FUEL_LEFT_QUANTITY, fuelLeftDefault); | ||
fuelRight = mINI::INITypeConversion::getDouble(ini, INI_SECTION_FUEL, INI_SECTION_FUEL_RIGHT_QUANTITY, fuelRightDefault); | ||
fuelLeftAux = mINI::INITypeConversion::getDouble(ini, INI_SECTION_FUEL, INI_SECTION_FUEL_LEFT_AUX_QUANTITY, fuelLeftAuxDefault); | ||
fuelRightAux = mINI::INITypeConversion::getDouble(ini, INI_SECTION_FUEL, INI_SECTION_FUEL_RIGHT_AUX_QUANTITY, fuelRightAuxDefault); | ||
|
||
LOG_DEBUG("Fadec::FuelConfiguration_A32NX: loaded fuel configuration from " + configFilename + " with the following values:"); | ||
LOG_DEBUG("Fadec::FuelConfiguration_A32NX: " + this->toString()); | ||
} | ||
|
||
void FuelConfiguration_A32NX::saveConfigurationToIni() { | ||
LOG_DEBUG("Fadec::FuelConfiguration_A32NX: saving configuration file " + configFilename); | ||
|
||
mINI::INIStructure ini; | ||
mINI::INIFile iniFile(configFilename); | ||
|
||
// Do not check a possible error since the file may not exist yet | ||
iniFile.read(ini); | ||
|
||
ini[INI_SECTION_FUEL][INI_SECTION_FUEL_CENTER_QUANTITY] = std::to_string(this->fuelCenter); | ||
ini[INI_SECTION_FUEL][INI_SECTION_FUEL_LEFT_QUANTITY] = std::to_string(this->fuelLeft); | ||
ini[INI_SECTION_FUEL][INI_SECTION_FUEL_RIGHT_QUANTITY] = std::to_string(this->fuelRight); | ||
ini[INI_SECTION_FUEL][INI_SECTION_FUEL_LEFT_AUX_QUANTITY] = std::to_string(this->fuelLeftAux); | ||
ini[INI_SECTION_FUEL][INI_SECTION_FUEL_RIGHT_AUX_QUANTITY] = std::to_string(this->fuelRightAux); | ||
|
||
if (!iniFile.write(ini, true)) { | ||
LOG_ERROR("Fadec::FuelConfiguration_A32NX: failed to write engine conf " + configFilename + " due to error \"" + strerror(errno) + | ||
"\""); | ||
return; | ||
} | ||
|
||
LOG_DEBUG("Fadec::FuelConfiguration_A32NX: saved fuel configuration to " + configFilename + " with the following values:"); | ||
LOG_DEBUG("Fadec::FuelConfiguration_A32NX: " + this->toString()); | ||
} | ||
|
||
std::string FuelConfiguration_A32NX::toString() const { | ||
std::ostringstream oss; | ||
oss << "FuelConfiguration_A32NX: { " | ||
<< "fuelCenter: " << fuelCenter // | ||
<< ", fuelLeft: " << fuelLeft // | ||
<< ", fuelRight: " << fuelRight // | ||
<< ", fuelLeftAux: " << fuelLeftAux // | ||
<< ", fuelRightAux: " << fuelRightAux // | ||
<< " }"; | ||
return oss.str(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// Copyright (c) 2023-2024 FlyByWire Simulations | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
#ifndef FLYBYWIRE_AIRCRAFT_FUELCONFIGURATION_A32NX_H | ||
#define FLYBYWIRE_AIRCRAFT_FUELCONFIGURATION_A32NX_H | ||
|
||
#include <string> | ||
|
||
// Define constants for the INI file sections and keys | ||
#define INI_SECTION_FUEL "FUEL" | ||
#define INI_SECTION_FUEL_CENTER_QUANTITY "FUEL_CENTER_QUANTITY" | ||
#define INI_SECTION_FUEL_LEFT_QUANTITY "FUEL_LEFT_QUANTITY" | ||
#define INI_SECTION_FUEL_RIGHT_QUANTITY "FUEL_RIGHT_QUANTITY" | ||
#define INI_SECTION_FUEL_LEFT_AUX_QUANTITY "FUEL_LEFT_AUX_QUANTITY" | ||
#define INI_SECTION_FUEL_RIGHT_AUX_QUANTITY "FUEL_RIGHT_AUX_QUANTITY" | ||
|
||
/** | ||
* @class FuelConfiguration_A32NX | ||
* @brief Class to manage the fuel configuration for the A32NX aircraft. | ||
* | ||
* This class provides methods to load and save the fuel configuration from/to an INI file. | ||
* It also provides getter and setter methods for each fuel tank quantity. | ||
*/ | ||
class FuelConfiguration_A32NX { | ||
private: | ||
// Fuel tank default quantities in gallons | ||
static constexpr double fuelCenterDefault = 0; | ||
static constexpr double fuelLeftDefault = 411.34; | ||
static constexpr double fuelRightDefault = fuelLeftDefault; | ||
static constexpr double fuelLeftAuxDefault = 0; | ||
static constexpr double fuelRightAuxDefault = fuelLeftAuxDefault; | ||
|
||
// Actual fuel tank quantities in gallons | ||
double fuelCenter = fuelCenterDefault; | ||
double fuelLeft = fuelLeftDefault; | ||
double fuelRight = fuelRightDefault; | ||
double fuelLeftAux = fuelLeftAuxDefault; | ||
double fuelRightAux = fuelRightAuxDefault; | ||
|
||
std::string configFilename{"A32NX-default-fuel-config.ini"}; | ||
|
||
public: | ||
/** | ||
* @brief Returns the filename of the INI file to use for loading and saving the fuel configuration. | ||
*/ | ||
std::string getConfigFilename() const { return configFilename; } | ||
|
||
/** | ||
* @brief Sets the filename of the INI file to use for loading and saving the fuel configuration. | ||
* | ||
* This must be called before calling loadConfigurationFromIni or saveConfigurationToIni otherwise the default | ||
* filename will be used. | ||
* | ||
* @param configFilename The filename of the INI file to use for loading and saving the fuel configuration. | ||
*/ | ||
void setConfigFilename(const std::string& configFilename) { this->configFilename = configFilename; } | ||
|
||
/** | ||
* @brief Loads the fuel configuration from an INI file. | ||
* | ||
* This method reads the INI file specified in the configFilename member variable and updates the fuel quantities accordingly. | ||
* If the INI file cannot be read, an error message is logged and the method returns without making any changes. | ||
*/ | ||
void loadConfigurationFromIni(); | ||
|
||
/** | ||
* @brief Saves the current fuel configuration to an INI file. | ||
* | ||
* This method writes the current fuel quantities to the INI file specified in the configFilename member variable. | ||
* If the INI file cannot be written, an error message is logged. | ||
*/ | ||
void saveConfigurationToIni(); | ||
|
||
/** | ||
* @brief Converts the current fuel configuration to a string. | ||
* | ||
* This method is used to convert the current state of the fuel configuration into a string format. | ||
* The string includes the quantities of fuel in each tank. | ||
* | ||
* @return A string representation of the current fuel configuration. | ||
*/ | ||
std::string toString() const; | ||
|
||
// === Getters and setters === | ||
|
||
double getFuelCenter() const { return fuelCenter; } | ||
double getFuelLeft() const { return fuelLeft; } | ||
double getFuelRight() const { return fuelRight; } | ||
double getFuelLeftAux() const { return fuelLeftAux; } | ||
double getFuelRightAux() const { return fuelRightAux; } | ||
|
||
void setFuelCenter(double fuelCenter) { this->fuelCenter = fuelCenter; } | ||
void setFuelLeft(double fuelLeft) { this->fuelLeft = fuelLeft; } | ||
void setFuelRight(double fuelRight) { this->fuelRight = fuelRight; } | ||
void setFuelLeftAux(double fuelLeftAux) { this->fuelLeftAux = fuelLeftAux; } | ||
void setFuelRightAux(double fuelRightAux) { this->fuelRightAux = fuelRightAux; } | ||
}; | ||
|
||
#endif // FLYBYWIRE_AIRCRAFT_FUELCONFIGURATION_A32NX_H |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// Copyright (c) 2023-2024 FlyByWire Simulations | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
#ifndef FLYBYWIRE_AIRCRAFT_TABLES1502_A32NX_HPP | ||
#define FLYBYWIRE_AIRCRAFT_TABLES1502_A32NX_HPP | ||
|
||
#include <cmath> | ||
|
||
#include "Fadec.h" | ||
|
||
/** | ||
* @class Table1502_A32NX | ||
* | ||
* This class contains methods and data used in the calculation of the corrected fan speed (CN1 and CN2). | ||
* The class has a 2D array `table` that contains values used in the calculation of the corrected fan speed. | ||
* Each row in the `table` represents a set of values. The columns represent different parameters used in the calculation. | ||
* The class also has two static methods `iCN3` and `iCN1` that calculate the corrected fan speed (CN2 and CN1) respectively. | ||
* | ||
* TODO: extract the reusable code to a common library | ||
*/ | ||
class Tables1502_A32NX { | ||
/** | ||
* @brief Table 1502 (CN2 vs correctedN1) representations with FSX nomenclature. | ||
* | ||
* This table represents the relationship between CN2 and correctedN1 in the FSX nomenclature. | ||
* Each row in the table represents a different state of the engine, with the first column being the CN2 value, | ||
* the second and third columns being the lower and upper bounds of the correctedN1 value at Mach 0.2, | ||
* and the fourth column being the correctedN1 value at Mach 0.9. | ||
* | ||
* @return A 2D array representing the CN2 - correctedN1 pairs. | ||
*/ | ||
static constexpr double table1502[13][4] = { | ||
{18.20, 0.00, 0.00, 17.00}, // CN2 = 18.20, correctedN1 = [0.00, 0.00] at Mach 0.2, correctedN1 = 17.00 at Mach 0.9 | ||
{22.00, 1.90, 1.90, 17.40}, // CN2 = 22.00, correctedN1 = [1.90, 1.90] at Mach 0.2, correctedN1 = 17.40 at Mach 0.9 | ||
{26.00, 2.50, 2.50, 18.20}, // CN2 = 26.00, correctedN1 = [2.50, 2.50] at Mach 0.2, correctedN1 = 18.20 at Mach 0.9 | ||
{57.00, 12.80, 12.80, 27.00}, // CN2 = 57.00, correctedN1 = [12.80, 12.80] at Mach 0.2, correctedN1 = 27.00 at Mach 0.9 | ||
{68.20, 19.60, 19.60, 34.83}, // CN2 = 68.20, correctedN1 = [19.60, 19.60] at Mach 0.2, correctedN1 = 34.83 at Mach 0.9 | ||
{77.00, 26.00, 26.00, 40.84}, // CN2 = 77.00, correctedN1 = [26.00, 26.00] at Mach 0.2, correctedN1 = 40.84 at Mach 0.9 | ||
{83.00, 31.42, 31.42, 44.77}, // CN2 = 83.00, correctedN1 = [31.42, 31.42] at Mach 0.2, correctedN1 = 44.77 at Mach 0.9 | ||
{89.00, 40.97, 40.97, 50.09}, // CN2 = 89.00, correctedN1 = [40.97, 40.97] at Mach 0.2, correctedN1 = 50.09 at Mach 0.9 | ||
{92.80, 51.00, 51.00, 55.04}, // CN2 = 92.80, correctedN1 = [51.00, 51.00] at Mach 0.2, correctedN1 = 55.04 at Mach 0.9 | ||
{97.00, 65.00, 65.00, 65.00}, // CN2 = 97.00, correctedN1 = [65.00, 65.00] at Mach 0.2, correctedN1 = 65.00 at Mach 0.9 | ||
{100.00, 77.00, 77.00, 77.00}, // CN2 = 100.00, correctedN1 = [77.00, 77.00] at Mach 0.2, correctedN1 = 77.00 at Mach 0.9 | ||
{104.00, 85.00, 85.00, 85.50}, // CN2 = 104.00, correctedN1 = [85.00, 85.00] at Mach 0.2, correctedN1 = 85.50 at Mach 0.9 | ||
{116.50, 101.00, 101.00, 101.00} // CN2 = 116.50, correctedN1 = [101.00, 101.00] at Mach 0.2, correctedN1 = 101.00 at Mach 0.9 | ||
}; | ||
|
||
public: | ||
|
||
/** | ||
* @brief Calculates the expected CN2 at idle. | ||
* | ||
* @param pressureAltitude The pressure altitude in feet. | ||
* @param mach The Mach number. | ||
* @return The expected CN2 value at idle in percent. | ||
*/ | ||
static double iCN2(double pressureAltitude, double mach) { | ||
// The specific values are likely derived from empirical data or a mathematical model of the engine's behavior. | ||
// The original source code does not provide any information on the origin of these values. | ||
return 68.2 / ((std::sqrt)((288.15 - (1.98 * pressureAltitude / 1000)) / 288.15) * (std::sqrt)(1 + (0.2 * (std::pow)(mach, 2)))); | ||
} | ||
|
||
/** | ||
* @brief Calculates the expected CN1 at idle. | ||
* | ||
* @param pressureAltitude The pressure altitude in feet. | ||
* @param mach The Mach number. | ||
* @param ambientTemp The ambient temperature in Kelvin. | ||
* @return The expected CN1 value at idle. | ||
*/ | ||
static double iCN1(double pressureAltitude, double mach, [[maybe_unused]] double ambientTemp) { | ||
// Calculate the expected CN2 value | ||
const double cn2 = iCN2(pressureAltitude, mach); | ||
|
||
// Find the row in the table that contains the CN2 value and store the index in i | ||
int i = 0; | ||
while (table1502[i][0] <= cn2 && i < 13) { | ||
i++; | ||
} | ||
|
||
// Retrieve the lower and upper bounds of the CN2 value and the correctedN1 value at Mach 0.2 and Mach 0.9 | ||
const double cn2lo = table1502[i - 1][0]; | ||
const double cn2hi = table1502[i][0]; | ||
const double cn1lolo = table1502[i - 1][1]; | ||
const double cn1hilo = table1502[i][1]; | ||
const double cn1lohi = table1502[i - 1][3]; | ||
const double cn1hihi = table1502[i][3]; | ||
|
||
// Interpolate the correctedN1 value based on the CN2 value and the Mach number | ||
const double cn1_lo = Fadec::interpolate(cn2, cn2lo, cn2hi, cn1lolo, cn1hilo); | ||
const double cn1_hi = Fadec::interpolate(cn2, cn2lo, cn2hi, cn1lohi, cn1hihi); | ||
|
||
return Fadec::interpolate(mach, 0.2, 0.9, cn1_lo, cn1_hi); | ||
} | ||
}; | ||
|
||
#endif // FLYBYWIRE_AIRCRAFT_TABLES1502_A32NX_HPP |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,329 @@ | ||
// Copyright (c) 2023-2024 FlyByWire Simulations | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
#ifndef FLYBYWIRE_AIRCRAFT_THRUSTLIMITS_A32NX_HPP | ||
#define FLYBYWIRE_AIRCRAFT_THRUSTLIMITS_A32NX_HPP | ||
|
||
#include <algorithm> | ||
#include <cmath> | ||
|
||
#include "EngineRatios.hpp" | ||
#include "Fadec.h" | ||
|
||
/** | ||
* @class ThrustLimits_A32NX | ||
* @brief A static class that provides methods for calculating various engine thrust limits for the A33NX aircraft. | ||
* | ||
* TODO: extract the reusable code to a common library | ||
*/ | ||
class ThrustLimits_A32NX { | ||
/** | ||
* @brief A 2D array representing various engine thrust limits. | ||
* | ||
* This 2D array contains 72 rows, each with 6 columns. Each row represents a different altitude | ||
* level and the corresponding engine thrust | ||
* limits. The columns in each row represent the following parameters: | ||
* 1. Altitude (in feet) | ||
* 2. Corner Point (CP) - the temperature below which the engine can operate at full thrust without any restrictions. | ||
* 3. Limit Point (LP) - the temperature above which the engine thrust starts to be limited. | ||
* 4. CN1 Flat - the engine's N1 fan speed limit at the CP temperature. | ||
* 5. CN1 Last - the engine's N1 fan speed limit at the LP temperature. | ||
* 6. CN1 Flex - the engine's N1 fan speed limit at a temperature of 100 degrees Celsius. | ||
* | ||
* The array is divided into sections for different flight phases: Takeoff (TO), Go-Around (GA), | ||
* Climb (CLB), and Maximum Continuous Thrust (MCT). | ||
*/ | ||
static constexpr double limits[72][6] = { | ||
// TO | ||
{-2000, 48.000, 55.000, 81.351, 79.370, 61.535}, // row 0 | ||
{-1000, 46.000, 55.000, 82.605, 80.120, 62.105}, // | ||
{0, 44.000, 55.000, 83.832, 80.776, 62.655}, // | ||
{500, 42.000, 52.000, 84.210, 81.618, 62.655}, // | ||
{1000, 42.000, 52.000, 84.579, 81.712, 62.655}, // | ||
{2000, 40.000, 50.000, 85.594, 82.720, 62.655}, // | ||
{3000, 36.000, 48.000, 86.657, 83.167, 61.960}, // | ||
{4000, 32.000, 46.000, 87.452, 83.332, 61.206}, // | ||
{5000, 29.000, 44.000, 88.833, 84.166, 61.206}, // | ||
{6000, 25.000, 42.000, 90.232, 84.815, 61.206}, // | ||
{7000, 21.000, 40.000, 91.711, 85.565, 61.258}, // | ||
{8000, 17.000, 38.000, 93.247, 86.225, 61.777}, // | ||
{9000, 15.000, 36.000, 94.031, 86.889, 60.968}, // | ||
{10000, 13.000, 34.000, 94.957, 88.044, 60.935}, // | ||
{11000, 12.000, 32.000, 95.295, 88.526, 59.955}, // | ||
{12000, 11.000, 30.000, 95.568, 88.818, 58.677}, // | ||
{13000, 10.000, 28.000, 95.355, 88.819, 59.323}, // | ||
{14000, 10.000, 26.000, 95.372, 89.311, 59.965}, // | ||
{15000, 8.000, 24.000, 95.686, 89.907, 58.723}, // | ||
{16000, 5.000, 22.000, 96.160, 89.816, 57.189}, // | ||
{16600, 5.000, 22.000, 96.560, 89.816, 57.189}, // row 20 | ||
// GA | ||
{-2000, 47.751, 54.681, 84.117, 81.901, 63.498}, // row 21 | ||
{-1000, 45.771, 54.681, 85.255, 82.461, 63.920}, // | ||
{0, 43.791, 54.681, 86.411, 83.021, 64.397}, // | ||
{500, 42.801, 52.701, 86.978, 83.740, 64.401}, // | ||
{1000, 41.811, 52.701, 87.568, 83.928, 64.525}, // | ||
{2000, 38.841, 50.721, 88.753, 84.935, 64.489}, // | ||
{3000, 36.861, 48.741, 89.930, 85.290, 63.364}, // | ||
{4000, 32.901, 46.761, 91.004, 85.836, 62.875}, // | ||
{5000, 28.941, 44.781, 92.198, 86.293, 62.614}, // | ||
{6000, 24.981, 42.801, 93.253, 86.563, 62.290}, // | ||
{7000, 21.022, 40.821, 94.273, 86.835, 61.952}, // | ||
{8000, 17.062, 38.841, 94.919, 87.301, 62.714}, // | ||
{9000, 15.082, 36.861, 95.365, 87.676, 61.692}, // | ||
{10000, 13.102, 34.881, 95.914, 88.150, 60.906}, // | ||
{11000, 12.112, 32.901, 96.392, 88.627, 59.770}, // | ||
{12000, 11.122, 30.921, 96.640, 89.206, 58.933}, // | ||
{13000, 10.132, 28.941, 96.516, 89.789, 60.503}, // | ||
{14000, 9.142, 26.961, 96.516, 90.475, 62.072}, // | ||
{15000, 9.142, 24.981, 96.623, 90.677, 59.333}, // | ||
{16000, 7.162, 23.001, 96.845, 90.783, 58.045}, // | ||
{16600, 5.182, 21.022, 97.366, 91.384, 58.642}, // row 41 | ||
// CLB | ||
{-2000, 30.800, 56.870, 80.280, 72.000, 0.000}, // row 42 | ||
{2000, 20.990, 48.157, 82.580, 74.159, 0.000}, // | ||
{5000, 16.139, 43.216, 84.642, 75.737, 0.000}, // | ||
{8000, 7.342, 38.170, 86.835, 77.338, 0.000}, // | ||
{10000, 4.051, 34.518, 88.183, 77.999, 0.000}, // | ||
{10000.1, 4.051, 34.518, 87.453, 77.353, 0.000}, // | ||
{12000, 0.760, 30.865, 88.303, 78.660, 0.000}, // | ||
{15000, -4.859, 25.039, 89.748, 79.816, 0.000}, // | ||
{17000, -9.934, 19.813, 90.668, 80.895, 0.000}, // | ||
{20000, -15.822, 13.676, 92.106, 81.894, 0.000}, // | ||
{24000, -22.750, 6.371, 93.651, 82.716, 0.000}, // | ||
{27000, -29.105, -0.304, 93.838, 83.260, 0.000}, // | ||
{29314, -32.049, -3.377, 93.502, 82.962, 0.000}, // | ||
{31000, -34.980, -6.452, 95.392, 84.110, 0.000}, // | ||
{35000, -45.679, -17.150, 96.104, 85.248, 0.000}, // | ||
{39000, -45.679, -17.150, 96.205, 84.346, 0.000}, // | ||
{41500, -45.679, -17.150, 95.676, 83.745, 0.000}, // row 58 | ||
// MCT | ||
{-1000, 26.995, 54.356, 82.465, 74.086, 0.000}, // row 59 | ||
{3000, 18.170, 45.437, 86.271, 77.802, 0.000}, // | ||
{7000, 9.230, 40.266, 89.128, 79.604, 0.000}, // | ||
{11000, 4.019, 31.046, 92.194, 82.712, 0.000}, // | ||
{15000, -5.226, 21.649, 95.954, 85.622, 0.000}, // | ||
{17000, -9.913, 20.702, 97.520, 85.816, 0.000}, // | ||
{20000, -15.129, 15.321, 99.263, 86.770, 0.000}, // | ||
{22000, -19.947, 10.382, 98.977, 86.661, 0.000}, // | ||
{25000, -25.397, 4.731, 98.440, 85.765, 0.000}, // | ||
{27000, -30.369, -0.391, 97.279, 85.556, 0.000}, // | ||
{31000, -36.806, -7.165, 98.674, 86.650, 0.000}, // | ||
{35000, -43.628, -14.384, 98.386, 85.747, 0.000}, // | ||
{39000, -47.286, -18.508, 97.278, 85.545, 0.000} // row 71 | ||
}; | ||
|
||
public: | ||
/** | ||
* @brief Finds the top-row boundary in the limits array. | ||
* | ||
* @param altitude The altitude to find the top-row boundary for. | ||
* @param index The index to start the search from. | ||
* @return The index of the top-row boundary in the limits array. | ||
*/ | ||
static int finder(double altitude, int index) { | ||
while (altitude >= limits[index][0]) { | ||
index++; | ||
} | ||
return index; | ||
} | ||
|
||
/** | ||
* @brief Structure to store the bleed values for different types of limits. | ||
* | ||
* This structure contains three members, each representing a specific bleed value: | ||
* - `n1Packs`: A double representing the bleed value for the packs. | ||
* - `n1Nai`: A double representing the bleed value for the nacelle anti-ice. | ||
* - `n1Wai`: A double representing the bleed value for the wing anti-ice. | ||
*/ | ||
struct BleedValues { | ||
double n1Packs; | ||
double n1Nai; | ||
double n1Wai; | ||
}; | ||
|
||
/** | ||
* @brief Lookup table for bleed values based on limit type. | ||
* | ||
* This map stores the bleed values for different types of limits. The key is an integer | ||
* representing the type of limit (0-TO, 1-GA, 2-CLB, 3-MCT), | ||
* and the value is a `BleedValues` structure containing the values for `n1Packs`, `n1Nai`, and `n1Wai`. | ||
*/ | ||
static std::map<int, BleedValues> bleedValuesLookup; // see below for initialization | ||
|
||
/** | ||
* @brief Calculates the total bleed for the engine. | ||
* | ||
* @param type The type of operation (0-TO, 1-GA, 2-CLB, 3-MCT). | ||
* @param altitude The current altitude of the aircraft in feet. | ||
* @param oat The outside air temperature in degrees Celsius. | ||
* @param cp The corner point - the temperature below which the engine can operate at full thrust without any restrictions (in degrees Celsius). | ||
* @param lp The limit point - the temperature above which the engine thrust starts to be limited (in degrees Celsius). | ||
* @param flexTemp The flex temperature in degrees Celsius. | ||
* @param packs The status of the air conditioning (0 for off, 1 for on). | ||
* @param nacelle The status of the nacelle anti-ice (0 for off, 1 for on). | ||
* @param wing The status of the wing anti-ice (0 for off, 1 for on). | ||
* @return The total bleed for the engine | ||
*/ | ||
static double bleedTotal(int type, // | ||
double altitude, // | ||
double oat, // | ||
double cp, // | ||
double lp, // | ||
double flexTemp, // | ||
int packs, // | ||
int nacelle, // | ||
int wing // | ||
) { | ||
if (flexTemp > lp && type <= 1) { | ||
return packs * -0.6 + nacelle * -0.7 + wing * -0.7; | ||
} | ||
|
||
// Define a map to store the bleed values for different conditions | ||
// Keys: | ||
// int - Represents the type of operation (0-TO, 1-GA, 2-CLB, 3-MCT). | ||
// bool - Represents whether the altitude is less than 8000. | ||
// bool - Represents whether the outside air temperature is less than the corner point. | ||
// Values: | ||
// double - Represents the bleed value for the packs. | ||
// double - Represents the bleed value for the nacelle anti-ice. | ||
// double - Represents the bleed value for the wing anti-ice. | ||
std::map<std::tuple<int, bool, bool>, std::tuple<double, double, double>> bleedValues = { | ||
{{0, true, true}, {-0.4, -0.6, -0.7}}, // | ||
{{0, true, false}, {-0.5, -0.6, -0.7}}, // | ||
{{0, false, true}, {-0.6, -0.8, -0.8}}, // | ||
{{0, false, false}, {-0.7, -0.8, -0.8}}, // | ||
{{1, true, true}, {-0.4, -0.6, -0.6}}, // | ||
{{1, true, false}, {-0.4, -0.6, -0.6}}, // | ||
{{1, false, true}, {-0.6, -0.7, -0.8}}, // | ||
{{1, false, false}, {-0.6, -0.7, -0.8}}, // | ||
{{2, true, false}, {-0.2, -0.8, -0.4}}, // | ||
{{2, false, false}, {-0.3, -0.8, -0.4}}, // | ||
{{3, true, false}, {-0.6, -0.9, -1.2}}, // | ||
{{3, false, false}, {-0.6, -0.9, -1.2}} // | ||
}; | ||
|
||
double n1Packs = 0; | ||
double n1Nai = 0; | ||
double n1Wai = 0; | ||
|
||
// Use the map to get the bleed values | ||
std::tie(n1Packs, n1Nai, n1Wai) = bleedValues[{type, altitude < 8000, oat < cp}]; | ||
|
||
return packs * n1Packs + nacelle * n1Nai + wing * n1Wai; | ||
} | ||
|
||
/** | ||
* @brief Calculates the N1 limit for the engine. | ||
* | ||
* This function calculates the N1 limit for the engine based on various parameters such as the | ||
* type of operation, altitude, ambient temperature, ambient pressure, flex temperature, and the | ||
* status of the air conditioning (AC), nacelle anti-ice (nacelle), and wing anti-ice (wing). | ||
* | ||
* @param type The type of operation (0-TO, 1-GA, 2-CLB, 3-MCT). | ||
* @param altitude The current altitude of the aircraft. | ||
* @param ambientTemp The ambient temperature. | ||
* @param ambientPressure The ambient pressure. | ||
* @param flexTemp The flex temperature. | ||
* @param packs The status of the air conditioning (0 for off, 1 for on). | ||
* @param nacelle The status of the nacelle anti-ice (0 for off, 1 for on). | ||
* @param wing The status of the wing anti-ice (0 for off, 1 for on). | ||
* @return The N1 limit for the engine. | ||
*/ | ||
static double limitN1(int type, // | ||
double altitude, // | ||
double ambientTemp, // | ||
double ambientPressure, // | ||
double flexTemp, // | ||
int packs, // | ||
int nacelle, // | ||
int wing // | ||
) { | ||
int rowMin = 0; | ||
int rowMax = 0; | ||
int loAltRow = 0; | ||
int hiAltRow = 0; | ||
double mach = 0; | ||
|
||
// Set main variables per Limit Type | ||
switch (type) { | ||
case 0: // TO | ||
rowMin = 0; | ||
rowMax = 20; | ||
mach = 0; | ||
break; | ||
case 1: // GA | ||
rowMin = 21; | ||
rowMax = 41; | ||
mach = 0.225; | ||
break; | ||
case 2: // CLB | ||
rowMin = 42; | ||
rowMax = 58; | ||
if (altitude <= 10000) { | ||
mach = Fadec::cas2mach(250, ambientPressure); | ||
} else { | ||
mach = Fadec::cas2mach(300, ambientPressure); | ||
if (mach > 0.78) | ||
mach = 0.78; | ||
} | ||
break; | ||
case 3: // MCT | ||
rowMin = 59; | ||
rowMax = 71; | ||
mach = Fadec::cas2mach(230, ambientPressure); | ||
break; | ||
} | ||
|
||
// Check for over/under flows. Else, find top row value | ||
if (altitude <= limits[rowMin][0]) { | ||
hiAltRow = rowMin; | ||
loAltRow = rowMin; | ||
} else if (altitude >= limits[rowMax][0]) { | ||
hiAltRow = rowMax; | ||
loAltRow = rowMax; | ||
} else { | ||
hiAltRow = finder(altitude, rowMin); | ||
loAltRow = hiAltRow - 1; | ||
} | ||
|
||
// Define key table variables and interpolation | ||
const double cp = Fadec::interpolate(altitude, limits[loAltRow][0], limits[hiAltRow][0], limits[loAltRow][1], limits[hiAltRow][1]); | ||
const double lp = Fadec::interpolate(altitude, limits[loAltRow][0], limits[hiAltRow][0], limits[loAltRow][2], limits[hiAltRow][2]); | ||
const double cn1Flat = Fadec::interpolate(altitude, limits[loAltRow][0], limits[hiAltRow][0], limits[loAltRow][3], limits[hiAltRow][3]); | ||
const double cn1Last = Fadec::interpolate(altitude, limits[loAltRow][0], limits[hiAltRow][0], limits[loAltRow][4], limits[hiAltRow][4]); | ||
const double cn1Flex = Fadec::interpolate(altitude, limits[loAltRow][0], limits[hiAltRow][0], limits[loAltRow][5], limits[hiAltRow][5]); | ||
|
||
double cn1 = 0; | ||
double m = 0; | ||
double b = 0; | ||
if (flexTemp > 0 && type <= 1) { // CN1 for Flex Case | ||
if (flexTemp <= cp) { | ||
cn1 = cn1Flat; | ||
} else if (flexTemp > lp) { | ||
m = (cn1Flex - cn1Last) / (100 - lp); | ||
b = cn1Flex - m * 100; | ||
cn1 = (m * flexTemp) + b; | ||
} else { | ||
m = (cn1Last - cn1Flat) / (lp - cp); | ||
b = cn1Last - m * lp; | ||
cn1 = (m * flexTemp) + b; | ||
} | ||
} | ||
else { // CN1 for All other cases | ||
if (ambientTemp <= cp) { | ||
cn1 = cn1Flat; | ||
} else { | ||
m = (cn1Last - cn1Flat) / (lp - cp); | ||
b = cn1Last - m * lp; | ||
cn1 = (m * ambientTemp) + b; | ||
} | ||
} | ||
|
||
// Define bleed rating/ de-rating | ||
const double bleed = bleedTotal(type, altitude, ambientTemp, cp, lp, flexTemp, packs, nacelle, wing); | ||
|
||
return (cn1 * (std::sqrt)(EngineRatios::theta2(mach, ambientTemp))) + bleed; | ||
} | ||
}; | ||
|
||
#endif // FLYBYWIRE_AIRCRAFT_THRUSTLIMITS_A32NX_HPP |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// Copyright (c) 2023 FlyByWire Simulations | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
#ifndef __INTELLISENSE__ | ||
#define MODULE_EXPORT __attribute__((visibility("default"))) | ||
#define MODULE_WASM_MODNAME(mod) __attribute__((import_module(mod))) | ||
#else | ||
#define MODULE_EXPORT | ||
#define MODULE_WASM_MODNAME(mod) | ||
#define __attribute__(x) | ||
#define __restrict__ | ||
#endif | ||
|
||
#include <MSFS/Legacy/gauges.h> | ||
#include <MSFS/MSFS.h> | ||
|
||
#include "Fadec/Fadec_A32NX.h" | ||
#include "MsfsHandler.h" | ||
|
||
// Create an instance of the MsfsHandler | ||
// We do not use a prefix and use the full LVar name in the code. | ||
// Prefixes in framework code are not ideal and also prevent the creation | ||
// of an LVar without a prefix | ||
MsfsHandler msfsHandler("Gauge_Fadec_A32NX", ""); | ||
|
||
// ADD ADDITIONAL MODULES HERE | ||
// This is the only place these have to be added - everything else is handled automatically | ||
Fadec_A32NX fadec(msfsHandler); | ||
|
||
/** | ||
* Gauge Callback | ||
* There can by multiple gauges in a single wasm module. Just add another gauge callback function | ||
* and register it in the panel.cfg file. | ||
* | ||
* Avoid putting any logic in the gauge callback function. Instead, create a new class and put | ||
* the logic there. | ||
* | ||
* @see | ||
* https://docs.flightsimulator.com/html/Content_Configuration/SimObjects/Aircraft_SimO/Instruments/C_C++_Gauges.htm?rhhlterm=_gauge_callback&rhsearch=_gauge_callback | ||
*/ | ||
extern "C" { | ||
[[maybe_unused]] MSFS_CALLBACK bool Gauge_Fadec_gauge_callback([[maybe_unused]] FsContext ctx, int svcId, void* pData) { | ||
switch (svcId) { | ||
case PANEL_SERVICE_PRE_INSTALL: { | ||
return msfsHandler.initialize(); | ||
} | ||
case PANEL_SERVICE_PRE_DRAW: { | ||
return msfsHandler.update(static_cast<sGaugeDrawData*>(pData)); | ||
} | ||
case PANEL_SERVICE_PRE_KILL: { | ||
return msfsHandler.shutdown(); | ||
} | ||
default: | ||
break; | ||
} | ||
return false; | ||
} | ||
} |
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# flybywire-a380x-fadec-v2 CMakeLists.txt | ||
|
||
# add additional compiler definitions for the a380x fadec-v2 build | ||
#add_definitions( ) | ||
|
||
# add the local include directories | ||
include_directories( | ||
${CMAKE_CURRENT_SOURCE_DIR}/src | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec | ||
${FBW_COMMON}/cpp-msfs-framework/ | ||
${FBW_COMMON}/fadec_common/src/ | ||
) | ||
|
||
# define the source files | ||
set(SOURCE_FILES | ||
${FBW_COMMON}/fadec_common/src/Fadec.cpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Gauge_Fadec_v2.cpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/Fadec_A380X.cpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/EngineControl_A380X.cpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/FuelConfiguration_A380X.cpp | ||
) | ||
|
||
set(INCLUDE_FILES | ||
${FBW_COMMON}/fadec_common/src/Fadec.h | ||
${FBW_COMMON}/fadec_common/src/EngineRatios.hpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/Fadec_A380X.h | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/EngineControl_A380X.h | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/FuelConfiguration_A380X.h | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/FadecSimData_A380X.hpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/ThrustLimits_A380X.hpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/Polynomials_A380X.hpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fadec/Table1502_A380X.hpp | ||
) | ||
|
||
# create the targets | ||
add_library(fadec-a380x OBJECT ${SOURCE_FILES} ${INCLUDE_FILES}) | ||
add_wasm_library( | ||
NAME fadec-a380x | ||
DEPENDENCIES fadec-a380x cpp-msfs-framework-a380x | ||
) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# A380X FADEC | ||
|
||
This is a new version of the FADEC system for the A380X. | ||
It is a migration and cleanup of the original FADEC system, | ||
and is designed to be more modular and easier to maintain. |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,264 @@ | ||
// Copyright (c) 2023-2024 FlyByWire Simulations | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
#ifndef FLYBYWIRE_AIRCRAFT_ENGINECONTROL_A380X_H | ||
#define FLYBYWIRE_AIRCRAFT_ENGINECONTROL_A380X_H | ||
|
||
#include "MsfsHandler.h" | ||
|
||
#include "FadecSimData_A380X.hpp" | ||
#include "FuelConfiguration_A380X.h" | ||
|
||
#define FILENAME_FADEC_CONF_DIRECTORY "\\work\\AircraftStates\\" | ||
#define FILENAME_FADEC_CONF_FILE_EXTENSION ".ini" | ||
|
||
/** | ||
* @class EngineControl_A380X | ||
* @brief Manages the engine control for the A380XX aircraft, coordinating and synchronising the | ||
* simulator's jet engine simulation with realistic custom values. | ||
* | ||
* Engine control is adding more realistic values and behaviour to the engine simulation of the simulator. | ||
* Esp. for startup, shutdown, fuel consumption, thrust limits, etc. | ||
* | ||
* TODO: The EngineControl_A380X class is still work in progress and might be extended or replaced in the future. | ||
*/ | ||
class EngineControl_A380X { | ||
private: | ||
// Convenience pointer to the msfs handler | ||
MsfsHandler* msfsHandlerPtr = nullptr; | ||
|
||
// Convenience pointer to the data manager | ||
DataManager* dataManagerPtr = nullptr; | ||
|
||
// FADEC simulation data | ||
FadecSimData_A380X simData{}; | ||
|
||
// ATC ID for the aircraft used to load and store the fuel levels | ||
std::string atcId{}; | ||
|
||
// Fuel configuration for loading and storing fuel levels | ||
FuelConfiguration_A380X fuelConfiguration{}; | ||
|
||
// Remember last fuel save time to allow saving fuel only every 5 seconds | ||
FLOAT64 lastFuelSaveTime = 0; | ||
static constexpr double FUEL_SAVE_INTERVAL = 5.0; // seconds | ||
|
||
// thrust limits transition for flex | ||
bool isTransitionActive = false; | ||
static constexpr double TRANSITION_WAIT_TIME = 10; | ||
|
||
// values that need previous state | ||
double prevFlexTemperature = 0.0; | ||
double prevThrustLimitType = 0.0; | ||
|
||
// TODO - might not be required - feeds into stateMachine but really relevant | ||
double prevSimEngineN3[4] = {0.0, 0.0, 0.0, 0.0}; | ||
|
||
// additional constants | ||
static constexpr int MAX_OIL = 200; | ||
static constexpr int MIN_OIL = 140; | ||
static constexpr double FUEL_RATE_THRESHOLD = 661; // lbs/sec for determining fuel ui tampering | ||
|
||
/** | ||
* @enum EngineState | ||
* @brief Enumerates the possible states for the engine state machine. | ||
* | ||
* @var OFF The engine is turned off. This is the initial state of the engine. | ||
* @var ON The engine is turned on and running. | ||
* @var STARTING The engine is in the process of starting up. | ||
* @var RESTARTING The engine is in the process of restarting. | ||
* @var SHUTTING The engine is in the process of shutting down. | ||
*/ | ||
enum EngineState { | ||
OFF = 0, | ||
ON = 1, | ||
STARTING = 2, | ||
RESTARTING = 3, | ||
SHUTTING = 4, | ||
}; | ||
|
||
#ifdef PROFILING | ||
// Profiling for the engine control - can eventually be removed | ||
SimpleProfiler profilerUpdate{"Fadec::EngineControl_A380X::update()", 100}; | ||
SimpleProfiler profilerEngineStateMachine{"Fadec::EngineControl_A380X::engineStateMachine()", 100}; | ||
SimpleProfiler profilerEngineStartProcedure{"Fadec::EngineControl_A380X::engineStartProcedure()", 100}; | ||
SimpleProfiler profilerEngineShutdownProcedure{"Fadec::EngineControl_A380X::engineShutdownProcedure()", 100}; | ||
SimpleProfiler profilerUpdateFF{"Fadec::EngineControl_A380X::updateFF()", 100}; | ||
SimpleProfiler profilerUpdatePrimaryParameters{"Fadec::EngineControl_A380X::updatePrimaryParameters()", 100}; | ||
SimpleProfiler profilerUpdateEGT{"Fadec::EngineControl_A380X::updateEGT()", 100}; | ||
SimpleProfiler profilerUpdateFuel{"Fadec::EngineControl_A380X::updateFuel()", 100}; | ||
SimpleProfiler profilerUpdateThrustLimits{"Fadec::EngineControl_A380X::updateThrustLimits()", 100}; | ||
#endif | ||
|
||
// =========================================================================== | ||
// Public methods | ||
// =========================================================================== | ||
|
||
public: | ||
/** | ||
* @brief Initializes the EngineControl_A32NX class once during the gauge initialization. | ||
* @param msfsHandler | ||
*/ | ||
void initialize(MsfsHandler* msfsHandler); | ||
|
||
/** | ||
* @brief Updates the EngineControl_A32NX class once per frame. | ||
* @param pData | ||
*/ | ||
void update(sGaugeDrawData* pData); | ||
|
||
/** | ||
* @brief Shuts down the EngineControl_A32NX class once during the gauge shutdown. | ||
*/ | ||
void shutdown(); | ||
|
||
// =========================================================================== | ||
// Private methods | ||
// =========================================================================== | ||
|
||
private: | ||
/** | ||
* @brief Initialize the FADEC and Fuel model | ||
* This is done after we have retrieved the ATC ID so we can load the fuel levels | ||
*/ | ||
void initializeEngineControlData(); | ||
|
||
/** | ||
* @brief Generate Idle / Initial Engine Parameters (non-imbalanced) | ||
* | ||
* @param pressureAltitude The current pressure altitude of the aircraft in feet. | ||
* @param mach The current Mach number of the aircraft. | ||
* @param ambientTemperature The current ambient temperature in degrees Celsius. | ||
* @param ambientPressure The current ambient pressure in hPa. | ||
*/ | ||
void generateIdleParameters(FLOAT64 pressureAltitude, FLOAT64 mach, FLOAT64 ambientTemperature, FLOAT64 ambientPressure); | ||
|
||
/** | ||
* @brief Manages the state and state changes of the engine. | ||
* | ||
* @param engine The engine number (1 or 2). | ||
* @param engineIgniter The status of the engine igniter (enum 0=Crank, 1=Norm, 2=Ign). | ||
* @param engineStarter The status of the engine starter as bool. | ||
* @param simN3 The current N2 value from the simulator used as N3 for the A380X in percent. | ||
* @param idleN3 The idle N3 value in percent. | ||
* @param ambientTemperature The current ambient temperature in degrees Celsius. | ||
* @return The current state of the engine as an enum of type EngineState (OFF, ON, STARTING, RESTARTING, SHUTTING). | ||
* @see EngineState | ||
*/ | ||
EngineControl_A380X::EngineState engineStateMachine(int engine, | ||
int engineIgniter, | ||
bool engineStarter, | ||
double simN3, | ||
double idleN3, | ||
double ambientTemperature); | ||
|
||
/** | ||
* @brief This function manages the engine start procedure. | ||
* | ||
* @param engine The engine number (1 or 2). | ||
* @param engineState The current state of the engine as an enum of type EngineState. | ||
* @param deltaTime The time difference since the last update in seconds. | ||
* @param engineTimer A timer used to calculate the elapsed time for various operations. | ||
* @param simN3 The current N3 value from the simulator in percent (actually reading the sim's N2 as the sim does not have an N3. | ||
* @param ambientTemperature The current ambient temperature in degrees Celsius. | ||
* | ||
* @see EngineState | ||
*/ | ||
void engineStartProcedure(int engine, | ||
EngineState engineState, | ||
double deltaTime, | ||
double engineTimer, | ||
double simN3, | ||
double ambientTemperature); | ||
|
||
/** | ||
* @brief This function manages the engine shutdown procedure. | ||
* TODO: Temporary solution as per comment in original code | ||
* | ||
* @param engine The engine number (1 or 2). | ||
* @param ambientTemperature The current ambient temperature in degrees Celsius to calculate the engine's operating temperature. | ||
* @param simN1 The current N1 value from the simulator. | ||
* @param deltaTime The time difference since the last update. This is used to calculate the rate of change of various parameters. | ||
* @param engineTimer A timer used to calculate the elapsed time for various operations. | ||
*/ | ||
void engineShutdownProcedure(int engine, double deltaTime, double engineTimer, double simN1, double ambientTemperature); | ||
|
||
/** | ||
* @brief Updates the fuel flow of the engine. | ||
* | ||
* @param engine The engine number (1 or 2). | ||
* @param simCN1 The current corrected fan speed value from the simulator. | ||
* @param mach The current Mach number of the aircraft. | ||
* @param pressureAltitude The current pressure altitude of the aircraft in feet. | ||
* @param ambientTemperature The current ambient temperature in degrees Celsius to calculate the engine's operating temperature. | ||
* @param ambientPressure The current ambient pressure in hPa. | ||
* @return The updated fuel flow as a double in kg/hour. | ||
*/ | ||
int updateFF(int engine, FLOAT64 simCN1, FLOAT64 mach, FLOAT64 altitude, FLOAT64 temperature, FLOAT64 pressure); | ||
|
||
/** | ||
* @brief Updates the primary custom parameters (LVars) of the engine when not starting or stopping the engine | ||
* and the sim has control. | ||
* | ||
* @param engine The engine number (1 or 2). | ||
* @param imbalance The current encoded imbalance number of the engine. | ||
* @param simN1 The current N1 value from the simulator in percent. | ||
* @param simN3 The current N2 value from the simulator in percent used as N3 input in the A380X. | ||
*/ | ||
void updatePrimaryParameters(int engine, FLOAT64 simN1, FLOAT64 simN3); | ||
|
||
/** | ||
* @brief FBW Exhaust Gas Temperature (in degree Celsius). Updates EGT with realistic values visualized in the ECAM | ||
* | ||
* @param engine The engine number (1 or 2). | ||
* @param deltaTime The time difference since the last update to calculate the rate of change of various parameters. | ||
* @param simOnGround The on ground status of the aircraft (0 or 1). | ||
* @param engineState The current state of the engine. | ||
* @param simCN1 The current corrected fan speed value from the simulator. | ||
* @param correctedFuelFlow The current custom fuel flow of the engine (FBW corrected). | ||
* @param mach The current Mach number of the aircraft. | ||
* @param pressureAltitude The current pressure altitude of the aircraft in feet. | ||
* @param ambientTemperature The current ambient pressure in hPa. | ||
* | ||
* @see EngineState | ||
*/ | ||
void updateEGT(int engine, | ||
double engineState, | ||
double deltaTime, | ||
double simCN1, | ||
int customFuelFlow, | ||
const double mach, | ||
const double pressureAltitude, | ||
const double ambientPressure, | ||
bool simOnGround); | ||
|
||
/** | ||
* @brief FBW Fuel Consumption and Tanking. Updates Fuel Consumption with realistic values | ||
* | ||
* @param deltaTimeSeconds Frame delta time in seconds | ||
*/ | ||
void updateFuel(FLOAT64 deltaTimeSeconds); | ||
|
||
/** | ||
* @brief Updates the thrust limits of the engine. | ||
* | ||
* @param simulationTime The current time in the simulation. | ||
* @param pressureAltitude The current pressure altitude of the aircraft in feet. | ||
* @param ambientTemperature The current ambient temperature in degrees Celsius. | ||
* @param ambientPressure The current ambient pressure in hPa. | ||
* @param mach The current Mach number of the aircraft. | ||
* @param packs The current state of the packs (0 or 1). | ||
* @param nai The current state of the NAI (0 or 1). | ||
* @param wai The current state of the WAI (0 or 1). | ||
*/ | ||
void updateThrustLimits(double simulationTime, | ||
double pressureAltitude, | ||
double ambientTemperature, | ||
double ambientPressure, | ||
double mach, | ||
int packs, | ||
int nai, | ||
int wai); | ||
}; | ||
|
||
#endif // FLYBYWIRE_AIRCRAFT_ENGINECONTROL_A380X_H |