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