#include "global.h" #include "sensor.h" #include "efilib.h" #include "loggingcentral.h" static const char* s_sensorNames[] = { "Invalid", "CLT", "IAT", "RPM", "MAP", "MAF", "Oil Pressure", "Fuel Pressure (LP)", "Fuel Pressure (HP)", "Fuel Pressure (injector)", "TPS 1", "TPS 1 Primary", "TPS 1 Secondary", "TPS 2", "TPS 2 Primary", "TPS 2 Secondary", "Acc Pedal", "Acc Pedal Primary", "Acc Pedal Secondary", "Driver Acc Intent", "Aux Temp 1", "Aux Temp 2", "Lambda 1", "Lambda 2", "Wastegate Position", "Idle Valve Position", }; // This struct represents one sensor in the registry. // It stores whether the sensor should use a mock value, // the value to use, and if not a pointer to the sensor that // can provide a real value. class SensorRegistryEntry { public: const Sensor* getSensor() { return m_sensor; } void setMockValue(float value, bool mockRedundant) { m_mockValue = value; m_useMock = true; m_mockRedundant = mockRedundant; } void resetMock() { m_useMock = false; m_mockValue = 0.0f; } void reset() { m_sensor = nullptr; resetMock(); } bool Register(Sensor* sensor) { // If there's somebody already here - a consumer tried to double-register a sensor if (m_sensor) { // This sensor has already been registered. Don't re-register it. firmwareError(CUSTOM_OBD_26, "Duplicate registration for sensor \"%s\"", sensor->getSensorName()); return false; } else { // Put the sensor in the registry m_sensor = sensor; return true; } } SensorResult get() const { // Check if mock if (m_useMock) { return m_mockValue; } // Get the sensor out of the entry const Sensor *s = m_sensor; if (s) { // If we found the sensor, ask it for a result. return s->get(); } // We've exhausted all valid ways to return something - sensor not found. return unexpected; } void showInfo(Logging* logger, const char* sensorName) const { if (m_useMock) { scheduleMsg(logger, "Sensor \"%s\" mocked with value %.2f", sensorName, m_mockValue); } else { const auto sensor = m_sensor; if (sensor) { sensor->showInfo(logger, sensorName); } else { scheduleMsg(logger, "Sensor \"%s\" is not configured.", sensorName); } } } bool hasSensor() const { return m_useMock || m_sensor; } float getRaw() const { const auto sensor = m_sensor; if (sensor) { return sensor->getRaw(); } // We've exhausted all valid ways to return something - sensor not found. return 0; } bool isRedundant() const { const auto sensor = m_sensor; if (sensor) { return sensor->isRedundant(); } if (m_useMock) { return m_mockRedundant; } return false; } private: bool m_useMock = false; bool m_mockRedundant = false; float m_mockValue; Sensor* m_sensor = nullptr; }; static SensorRegistryEntry s_sensorRegistry[static_cast(SensorType::PlaceholderLast)] = {}; static_assert(efi::size(s_sensorNames) == efi::size(s_sensorRegistry)); bool Sensor::Register() { return s_sensorRegistry[getIndex()].Register(this); } /*static*/ void Sensor::resetRegistry() { // Clear all entries for (size_t i = 0; i < efi::size(s_sensorRegistry); i++) { auto &entry = s_sensorRegistry[i]; entry.reset(); } } /*static*/ SensorRegistryEntry *Sensor::getEntryForType(SensorType type) { size_t index = getIndex(type); // Check that we didn't get garbage if (index >= getIndex(SensorType::PlaceholderLast)) { return nullptr; } return &s_sensorRegistry[index]; } /*static*/ const Sensor *Sensor::getSensorOfType(SensorType type) { auto entry = getEntryForType(type); return entry ? entry->getSensor() : nullptr; } /*static*/ SensorResult Sensor::get(SensorType type) { const auto entry = getEntryForType(type); // Check if this is a valid sensor entry if (!entry) { return unexpected; } return entry->get(); } /*static*/ float Sensor::getRaw(SensorType type) { const auto entry = getEntryForType(type); return entry ? entry->getRaw() : 0; } /*static*/ bool Sensor::isRedundant(SensorType type) { const auto entry = getEntryForType(type); return entry ? entry->isRedundant() : false; } /*static*/ bool Sensor::hasSensor(SensorType type) { const auto entry = getEntryForType(type); return entry ? entry->hasSensor() : false; } /*static*/ void Sensor::setMockValue(SensorType type, float value, bool mockRedundant) { auto entry = getEntryForType(type); if (entry) { entry->setMockValue(value, mockRedundant); } } /*static*/ void Sensor::setMockValue(int type, float value) { // bounds check if (type <= 0 || type >= static_cast(SensorType::PlaceholderLast)) { return; } setMockValue(static_cast(type), value); } /*static*/ void Sensor::resetMockValue(SensorType type) { auto entry = getEntryForType(type); if (entry) { entry->resetMock(); } } /*static*/ void Sensor::resetAllMocks() { // Reset all mocks for (size_t i = 0; i < efi::size(s_sensorRegistry); i++) { s_sensorRegistry[i].resetMock(); } } /*static*/ const char* Sensor::getSensorName(SensorType type) { return s_sensorNames[static_cast(type)]; } // Print information about all sensors /*static*/ void Sensor::showAllSensorInfo(Logging* logger) { for (size_t i = 1; i < efi::size(s_sensorRegistry); i++) { auto& entry = s_sensorRegistry[i]; const char* name = s_sensorNames[i]; entry.showInfo(logger, name); } } // Print information about a particular sensor /*static*/ void Sensor::showInfo(Logging* logger, SensorType type) { auto entry = getEntryForType(type); if (entry) { entry->showInfo(logger, getSensorName(type)); } }