LCOV - code coverage report
Current view: top level - firmware/controllers/sensors/impl - AemXSeriesLambda.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 42 58 72.4 %
Date: 2024-09-08 11:28:59 Functions: 5 6 83.3 %

          Line data    Source code
       1             : #include "pch.h"
       2             : 
       3             : #if EFI_CAN_SUPPORT || EFI_UNIT_TEST
       4             : #include "AemXSeriesLambda.h"
       5             : #include "wideband_firmware/for_rusefi/wideband_can.h"
       6             : 
       7             : static constexpr uint32_t aem_base    = 0x180;
       8             : static constexpr uint32_t rusefi_base = WB_DATA_BASE_ADDR;
       9             : 
      10             : // "silent" of wboFaultCodeList
      11             : #define HACK_SILENT_VALUE 1
      12             : 
      13           5 : AemXSeriesWideband::AemXSeriesWideband(uint8_t sensorIndex, SensorType type)
      14             :         : CanSensorBase(
      15             :                 0,      // ID passed here doesn't matter since we override acceptFrame
      16             :                 type,
      17             :                 MS2NT(3 * WBO_TX_PERIOD_MS)     // sensor transmits at 100hz, allow a frame to be missed
      18             :         )
      19           5 :         , m_sensorIndex(sensorIndex)
      20             : {
      21           5 :     faultCode = HACK_SILENT_VALUE;// silent, initial state is "no one has spoken to us so far"
      22           5 : }
      23             : 
      24          12 : bool AemXSeriesWideband::acceptFrame(const CANRxFrame& frame) const {
      25          12 :         if (frame.DLC != 8) {
      26           0 :                 return false;
      27             :         }
      28             : 
      29          12 :         uint32_t id = CAN_ID(frame);
      30             : 
      31             :         // 0th sensor is 0x180, 1st sensor is 0x181, etc
      32          12 :         uint32_t aemXSeriesId = aem_base + m_sensorIndex;
      33             : 
      34             :         // 0th sensor is 0x190 and 0x191, 1st sensor is 0x192 and 0x193
      35          12 :         uint32_t rusefiBaseId = rusefi_base + 2 * m_sensorIndex;
      36             : 
      37             :         return
      38           7 :                 id == aemXSeriesId ||
      39          19 :                 id == rusefiBaseId ||
      40          14 :                 id == rusefiBaseId + 1;
      41             : }
      42             : 
      43           6 : void AemXSeriesWideband::decodeFrame(const CANRxFrame& frame, efitick_t nowNt) {
      44           6 :         uint32_t id = CAN_ID(frame);
      45             : 
      46             :         // accept frame has already guaranteed that this message belongs to us
      47             :         // We just have to check if it's AEM or rusEFI
      48           6 :         if (id < rusefi_base) {
      49           3 :                 decodeAemXSeries(frame, nowNt);
      50           3 :                 faultCode = 6;//static_cast<uint8_t>(Fault::LegacyProtocol);
      51             :         } else {
      52             :                 // rusEFI custom format
      53           3 :                 if ((id & 0x1) != 0) {
      54             :                         // low bit is set, this is the "diag" frame
      55           0 :                         decodeRusefiDiag(frame);
      56             :                 } else {
      57             :                         // low bit not set, this is standard frame
      58           3 :                         decodeRusefiStandard(frame, nowNt);
      59             :                 }
      60             :         }
      61           5 : }
      62             : 
      63           3 : void AemXSeriesWideband::decodeAemXSeries(const CANRxFrame& frame, efitick_t nowNt) {
      64             :         // reports in 0.0001 lambda per LSB
      65           3 :         uint16_t lambdaInt = SWAP_UINT16(frame.data16[0]);
      66           3 :         float lambdaFloat = 0.0001f * lambdaInt;
      67             : 
      68             :         // bit 6 indicates sensor fault
      69           3 :         bool sensorFault = frame.data8[7] & 0x40;
      70           3 :         if (sensorFault) {
      71           1 :                 invalidate();
      72           1 :                 return;
      73             :         }
      74             : 
      75             :         // bit 7 indicates valid
      76           2 :         bool valid = frame.data8[6] & 0x80;
      77           2 :         if (!valid) {
      78           1 :                 invalidate();
      79           1 :                 return;
      80             :         }
      81             : 
      82           1 :         setValidValue(lambdaFloat, nowNt);
      83             : }
      84             : 
      85           3 : void AemXSeriesWideband::decodeRusefiStandard(const CANRxFrame& frame, efitick_t nowNt) {
      86           3 :         auto data = reinterpret_cast<const wbo::StandardData*>(&frame.data8[0]);
      87             : 
      88           3 :         if (data->Version != RUSEFI_WIDEBAND_VERSION) {
      89           1 :                 firmwareError(ObdCode::OBD_WB_FW_Mismatch, "Wideband controller index %d has wrong firmware version, please update!", m_sensorIndex);
      90           0 :                 return;
      91             :         }
      92             : 
      93           2 :         tempC = data->TemperatureC;
      94             : 
      95           2 :         float lambda = 0.0001f * data->Lambda;
      96           2 :         bool valid = data->Valid != 0;
      97             : 
      98           2 :         if (valid) {
      99           1 :                 setValidValue(lambda, nowNt);
     100             :         } else {
     101           1 :                 invalidate();
     102             :         }
     103             : }
     104             : 
     105           0 : void AemXSeriesWideband::decodeRusefiDiag(const CANRxFrame& frame) {
     106           0 :         auto data = reinterpret_cast<const wbo::DiagData*>(&frame.data8[0]);
     107             : 
     108             :         // convert to percent
     109           0 :         heaterDuty = data->HeaterDuty / 2.55f;
     110           0 :         pumpDuty = data->PumpDuty / 2.55f;
     111             : 
     112             :         // convert to volts
     113           0 :         nernstVoltage = data->NernstDc * 0.001f;
     114             : 
     115             :         // no conversion, just ohms
     116           0 :         esr = data->Esr;
     117             : 
     118             : // todo: suggest values 1 and 2 into the official WB source fault enum?
     119             : #define HACK_CRANKING_VALUE 2
     120             : 
     121           0 :     if (!engine->engineState.heaterControlEnabled) {
     122           0 :         faultCode = HACK_CRANKING_VALUE;
     123           0 :         return;
     124             :     }
     125           0 :         faultCode = static_cast<uint8_t>(data->Status);
     126             : 
     127           0 :         if (data->Status != wbo::Fault::None) {
     128           0 :                 auto code = m_sensorIndex == 0 ? ObdCode::Wideband_1_Fault : ObdCode::Wideband_2_Fault;
     129           0 :                 warning(code, "Wideband #%d fault: %s", (m_sensorIndex + 1), wbo::describeFault(data->Status));
     130             :         }
     131             : }
     132             : 
     133             : #endif

Generated by: LCOV version 1.14