firmware/controllers/can/can_dash_ms.cpp
| Line | Branch | Decision | Exec | Source |
|---|---|---|---|---|
| 1 | /** | |||
| 2 | * @file can_dash_ms.cpp | |||
| 3 | * | |||
| 4 | * This file implements MegaSquirt CAN realtime data broadcasting format | |||
| 5 | * | |||
| 6 | * @date May 8, 2023 | |||
| 7 | * @author AndreyGusakov, (c) 2023 | |||
| 8 | */ | |||
| 9 | ||||
| 10 | #include "pch.h" | |||
| 11 | ||||
| 12 | #if EFI_CAN_SUPPORT || EFI_UNIT_TEST | |||
| 13 | #include "can.h" | |||
| 14 | #include "can_msg_tx.h" | |||
| 15 | ||||
| 16 | #include "rusefi_types.h" | |||
| 17 | #include "rtc_helper.h" | |||
| 18 | #include "fuel_math.h" | |||
| 19 | ||||
| 20 | /* TODO: | |||
| 21 | * use engine->outputChannels instead of Sensor::getOrZero as it cheaper */ | |||
| 22 | ||||
| 23 | struct ms1512 { | |||
| 24 | /* kPa */ | |||
| 25 | scaled_channel<int16_t, 10> Map; | |||
| 26 | /* RPM */ | |||
| 27 | scaled_channel<uint16_t, 1> Rpm; | |||
| 28 | /* Fahrenheit! */ | |||
| 29 | scaled_channel<int16_t, 10> Clt; | |||
| 30 | /* % */ | |||
| 31 | scaled_channel<int16_t, 10> Tps; | |||
| 32 | }; | |||
| 33 | ||||
| 34 | ✗ | void populateFrame(ms1512& msg) | ||
| 35 | { | |||
| 36 | ✗ | msg.Map = Sensor::getOrZero(SensorType::Map); | ||
| 37 | ✗ | msg.Rpm = Sensor::getOrZero(SensorType::Rpm); | ||
| 38 | /* Celsius to Fahrenheit */ | |||
| 39 | ✗ | msg.Clt = Sensor::getOrZero(SensorType::Clt) * 9 / 5 + 32; | ||
| 40 | ✗ | msg.Tps = Sensor::getOrZero(SensorType::Tps1); | ||
| 41 | ✗ | } | ||
| 42 | ||||
| 43 | struct ms1513 { | |||
| 44 | /* mS */ | |||
| 45 | scaled_channel<uint16_t, 1000> pw1; | |||
| 46 | scaled_channel<uint16_t, 1000> pw2; | |||
| 47 | scaled_channel<int16_t, 10> mat; | |||
| 48 | scaled_channel<int16_t, 10> adv_deg; | |||
| 49 | }; | |||
| 50 | ||||
| 51 | ✗ | void populateFrame(ms1513& msg) | ||
| 52 | { | |||
| 53 | /* TODO: per-bank */ | |||
| 54 | ✗ | msg.pw1 = msg.pw2 = engine->engineState.injectionDuration; | ||
| 55 | /* Celsius to Fahrenheit */ | |||
| 56 | ✗ | msg.mat = Sensor::getOrZero(SensorType::Iat) * 9 / 5 + 32; | ||
| 57 | ✗ | float timing = engine->engineState.timingAdvance[0]; | ||
| 58 | ✗ | msg.adv_deg = timing > 360 ? timing - 720 : timing; | ||
| 59 | ✗ | } | ||
| 60 | ||||
| 61 | struct ms1514 { | |||
| 62 | scaled_channel<uint8_t, 10> afrtgt1; | |||
| 63 | scaled_channel<uint8_t, 10> AFR1; | |||
| 64 | scaled_channel<int16_t, 10> EGOcor1; | |||
| 65 | scaled_channel<int16_t, 10> egt1; | |||
| 66 | scaled_channel<int16_t, 10> pwseq1; | |||
| 67 | }; | |||
| 68 | ||||
| 69 | ✗ | void populateFrame(ms1514& msg) | ||
| 70 | { | |||
| 71 | #if EFI_ENGINE_CONTROL | |||
| 72 | ✗ | msg.afrtgt1 = (float)engine->fuelComputer.targetLambda * STOICH_RATIO; | ||
| 73 | ✗ | msg.AFR1 = Sensor::getOrZero(SensorType::Lambda1) * STOICH_RATIO; | ||
| 74 | /* TODO: banks? */ | |||
| 75 | ✗ | msg.EGOcor1 = engine->engineState.stftCorrection[0]; | ||
| 76 | /* TODO */ | |||
| 77 | ✗ | msg.egt1 = 0; | ||
| 78 | ✗ | msg.pwseq1 = engine->engineState.injectionDuration; | ||
| 79 | #endif // EFI_ENGINE_CONTROL | |||
| 80 | ✗ | } | ||
| 81 | ||||
| 82 | struct ms1515 { | |||
| 83 | scaled_channel<uint16_t, 10> Vbat; | |||
| 84 | scaled_channel<uint16_t, 10> sensor1; | |||
| 85 | scaled_channel<uint16_t, 10> sensor2; | |||
| 86 | scaled_channel<uint8_t, 10> knk_rtd; | |||
| 87 | uint8_t unused; /* do we need this? */ | |||
| 88 | }; | |||
| 89 | ||||
| 90 | ✗ | void populateFrame(ms1515& msg) | ||
| 91 | { | |||
| 92 | ✗ | msg.Vbat = Sensor::getOrZero(SensorType::BatteryVoltage); | ||
| 93 | /* TODO */ | |||
| 94 | ✗ | msg.sensor1 = 0; | ||
| 95 | ✗ | msg.sensor2 = 0; | ||
| 96 | ✗ | msg.knk_rtd = engine->module<KnockController>()->m_knockLevel; | ||
| 97 | ✗ | msg.unused = 0; | ||
| 98 | ✗ | } | ||
| 99 | ||||
| 100 | struct ms1516 { | |||
| 101 | scaled_channel<uint16_t, 10> VSS1; | |||
| 102 | scaled_channel<uint16_t, 10> tc_retard; | |||
| 103 | scaled_channel<uint16_t, 10> launch_timing; | |||
| 104 | uint16_t unsused; | |||
| 105 | }; | |||
| 106 | ||||
| 107 | ✗ | void populateFrame(ms1516& msg) | ||
| 108 | { | |||
| 109 | /* ms-1 ??? */ | |||
| 110 | ✗ | msg.VSS1 = Sensor::getOrZero(SensorType::VehicleSpeed); | ||
| 111 | /* TODO */ | |||
| 112 | ✗ | msg.tc_retard = 0; | ||
| 113 | ✗ | msg.launch_timing = 0; | ||
| 114 | ✗ | msg.unsused = 0; | ||
| 115 | ✗ | } | ||
| 116 | ||||
| 117 | ✗ | void canDashboardTS(CanCycle cycle) { | ||
| 118 | /* TODO: get from settings */ | |||
| 119 | ✗ | uint32_t baseId = 1512; /* 0x5e8 */ | ||
| 120 | ||||
| 121 | ✗ | if (!cycle.isInterval(CI::_10ms)) { | ||
| 122 | ✗ | return; | ||
| 123 | } | |||
| 124 | ||||
| 125 | ✗ | bool busIndex = 0; | ||
| 126 | ✗ | transmitStruct<ms1512>(CanCategory::NBC, baseId + 0, false, busIndex); | ||
| 127 | ✗ | transmitStruct<ms1513>(CanCategory::NBC, baseId + 1, false, busIndex); | ||
| 128 | ✗ | transmitStruct<ms1514>(CanCategory::NBC, baseId + 2, false, busIndex); | ||
| 129 | ✗ | transmitStruct<ms1515>(CanCategory::NBC, baseId + 3, false, busIndex); | ||
| 130 | ✗ | transmitStruct<ms1516>(CanCategory::NBC, baseId + 4, false, busIndex); | ||
| 131 | } | |||
| 132 | ||||
| 133 | #endif /* EFI_CAN_SUPPORT */ | |||
| 134 |