diff --git a/firmware/controllers/can/can_tx.cpp b/firmware/controllers/can/can_tx.cpp index a4dfac4be2..09f6ed0eb7 100644 --- a/firmware/controllers/can/can_tx.cpp +++ b/firmware/controllers/can/can_tx.cpp @@ -26,6 +26,11 @@ CanWrite::CanWrite() void CanWrite::PeriodicTask(efitime_t nowNt) { UNUSED(nowNt); + if (CONFIG(enableVerboseCanTx)) { + void sendCanVerbose(); + sendCanVerbose(); + } + // Transmit dash data, if enabled switch (CONFIG(canNbcType)) { case CAN_BUS_NBC_BMW: diff --git a/firmware/controllers/can/can_verbose.cpp b/firmware/controllers/can/can_verbose.cpp new file mode 100644 index 0000000000..9d3aa852ec --- /dev/null +++ b/firmware/controllers/can/can_verbose.cpp @@ -0,0 +1,146 @@ + +#include "globalaccess.h" +#if EFI_CAN_SUPPORT + +#include "engine.h" + +#include "scaled_channel.h" +#include "can_msg_tx.h" +#include "sensor.h" +#include "allsensors.h" +#include "fuel_math.h" +#include "spark_logic.h" +#include "vehicle_speed.h" + +EXTERN_ENGINE; + +struct Status { + uint16_t warningCounter; + uint16_t lastErrorCode; + + uint8_t revLimit : 1; + uint8_t mainRelay : 1; + uint8_t fuelPump : 1; + uint8_t checkEngine : 1; + uint8_t o2Heater : 1; + + uint8_t pad6 : 1; + uint8_t pad7 : 1; + uint8_t pad8 : 1; + + uint8_t pad[3]; +}; + +static void populateFrame(Status& msg) { + msg.warningCounter = engine->engineState.warnings.warningCounter; + msg.lastErrorCode = engine->engineState.warnings.lastErrorCode; + + msg.revLimit = GET_RPM() > CONFIG(rpmHardLimit); + msg.mainRelay = enginePins.mainRelay.getLogicValue(); + msg.fuelPump = enginePins.fuelPumpRelay.getLogicValue(); + msg.checkEngine = enginePins.checkEnginePin.getLogicValue(); + msg.o2Heater = enginePins.o2heater.getLogicValue(); +} + +struct Speeds { + uint16_t rpm; + scaled_angle timing; + scaled_channel injDuty; + scaled_channel coilDuty; + scaled_channel vssKph; + uint8_t pad[1]; +}; + +static void populateFrame(Speeds& msg) { + auto rpm = GET_RPM(); + msg.rpm = rpm; + + auto timing = engine->engineState.timingAdvance; + msg.timing = timing > 360 ? timing - 720 : timing; + + msg.injDuty = getInjectorDutyCycle(rpm); + msg.coilDuty = getCoilDutyCycle(rpm); + + msg.vssKph = getVehicleSpeed(); +} + +struct PedalAndTps { + scaled_percent pedal; + scaled_percent tps1; + scaled_percent tps2; + uint8_t pad[2]; +}; + +static void populateFrame(PedalAndTps& msg) +{ + msg.pedal = getPedalPosition(); + msg.tps1 = Sensor::get(SensorType::Tps1).value_or(-1); + msg.tps2 = Sensor::get(SensorType::Tps2).value_or(-1); +} + +struct Sensors1 { + scaled_pressure map; + scaled_channel clt; + scaled_channel iat; + scaled_channel aux1; + scaled_channel aux2; + scaled_channel mcuTemp; + scaled_channel fuelLevel; +}; + +static void populateFrame(Sensors1& msg) { + msg.map = getMap(); + + msg.clt = getCoolantTemperature() + 40; + msg.iat = getIntakeAirTemperature() + 40; + + // todo: does aux temp even work? + msg.aux1 = 0 + 40; + msg.aux2 = 0 + 40; + + msg.mcuTemp = getMCUInternalTemperature(); + msg.fuelLevel = engine->sensors.fuelTankLevel; +} + +struct Sensors2 { + scaled_afr afr; + scaled_pressure oilPressure; + scaled_angle vvtPos; + scaled_voltage vbatt; +}; + +static void populateFrame(Sensors2& msg) { + msg.afr = getAfr(); + msg.oilPressure = Sensor::get(SensorType::OilPressure).value_or(-1); + msg.vvtPos = engine->triggerCentral.getVVTPosition(); + msg.vbatt = getVBatt(); +} + +struct Fueling { + scaled_channel cylAirmass; + scaled_channel estAirflow; + scaled_ms fuel_pulse; + scaled_percent stft; +}; + +static void populateFrame(Fueling& msg) { + msg.cylAirmass = engine->engineState.sd.airMassInOneCylinder; + msg.estAirflow = engine->engineState.airFlow; + msg.fuel_pulse = engine->actualLastInjection; + + // todo + msg.stft = 0; +} + +void sendCanVerbose() { + auto base = CONFIG(verboseCanBaseAddress); + + transmitStruct (base + 0); + transmitStruct (base + 1); + transmitStruct (base + 2); + transmitStruct (base + 3); + transmitStruct (base + 4); + transmitStruct (base + 5); +} + +#endif // EFI_CAN_SUPPORT diff --git a/firmware/controllers/controllers.mk b/firmware/controllers/controllers.mk index b2b3bda907..9a4d4ad22e 100644 --- a/firmware/controllers/controllers.mk +++ b/firmware/controllers/controllers.mk @@ -35,6 +35,7 @@ CONTROLLERS_SRC_CPP = \ $(CONTROLLERS_DIR)/flash_main.cpp \ $(CONTROLLERS_DIR)/injector_central.cpp \ $(CONTROLLERS_DIR)/can/obd2.cpp \ + $(CONTROLLERS_DIR)/can/can_verbose.cpp \ $(CONTROLLERS_DIR)/can/can_rx.cpp \ $(CONTROLLERS_DIR)/can/can_tx.cpp \ $(CONTROLLERS_DIR)/can/can_dash.cpp \ diff --git a/firmware/controllers/sensors/sensor.h b/firmware/controllers/sensors/sensor.h index fac4229b33..63c2da2a42 100644 --- a/firmware/controllers/sensors/sensor.h +++ b/firmware/controllers/sensors/sensor.h @@ -59,6 +59,11 @@ struct SensorResult { constexpr explicit operator bool() const { return Valid; } + + // Easy default value handling + constexpr float value_or(float valueIfInvalid) const { + return Valid ? Value : valueIfInvalid; + } }; // Fwd declare - nobody outside of Sensor.cpp needs to see inside this type diff --git a/firmware/hw_layer/drivers/can/can_msg_tx.h b/firmware/hw_layer/drivers/can/can_msg_tx.h index 15e30b37d9..178b1dc9af 100644 --- a/firmware/hw_layer/drivers/can/can_msg_tx.h +++ b/firmware/hw_layer/drivers/can/can_msg_tx.h @@ -83,4 +83,15 @@ public: TData* operator->() { return reinterpret_cast(&m_frame.data8); } + + TData& get() { + return *reinterpret_cast(&m_frame.data8); + } }; + +template +void transmitStruct(uint32_t eid) +{ + CanTxTyped frame(eid); + populateFrame(frame.get()); +}