diff --git a/Makefile b/Makefile
index 29837d74..bf608b37 100644
--- a/Makefile
+++ b/Makefile
@@ -44,8 +44,8 @@ OBJSL = $(BINARY).o hwinit.o stm32scheduler.o params.o terminal.o terminal_prj.
chademo.o amperaheater.o amperacharger.o subaruvehicle.o iomatrix.o bmw_sbox.o NissanPDM.o teslaCharger.o extCharger.o vag_sbox.o \
daisychainbms.o simpbms.o outlanderCharger.o Can_OBD2.o cansdo.o TeslaDCDC.o BMW_E31.o F30_Lever.o \
CPC.o ElconCharger.o RearOutlanderinverter.o linbus.o VWCoolantHeater.o JLR_G1.o JLR_G2.o Foccci.o digipot.o\
- OutlanderHeartBeat.o E65_Lever.o leafbms.o V_Classic.o kangoobms.o OutlanderCanHeater.o VWAirHeater.o\
- MGCoolantHeater.o NissLeafMng.o preheater.o MGgen2V2Lcharger.o
+ OutlanderHeartBeat.o E65_Lever.o leafbms.o V_Classic.o kangoobms.o OutlanderCanHeater.o VWAirHeater.o\
+ MGCoolantHeater.o NissLeafMng.o preheater.o MGgen2V2Lcharger.o Gear_9x1.o vw_mlb_charger.o vag_utils.o\
OBJS = $(patsubst %.o,$(OUT_DIR)/%.o, $(OBJSL))
diff --git a/include/Gear_9x1.h b/include/Gear_9x1.h
new file mode 100644
index 00000000..5cd4bc1f
--- /dev/null
+++ b/include/Gear_9x1.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the Zombieverter project.
+ *
+ * Copyright (C) 2024 Mitch Elliott
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef Gear_9x1_h
+#define Gear_9x1_h
+
+#include "shifter.h"
+
+class Gear_9x1: public Shifter
+{
+public:
+
+ void Task10Ms();
+ void Task100Ms();
+ void DecodeCAN(int, uint32_t*);
+ bool GetGear(Shifter::Sgear& outGear);//if shifter class knows gear return true and set dir
+ void SetCanInterface(CanHardware* c);
+
+private:
+ Shifter::Sgear gear;
+};
+
+
+#endif // Gear_9x1_INCLUDED
+
+
diff --git a/include/param_prj.h b/include/param_prj.h
index d68b7a8e..11311202 100644
--- a/include/param_prj.h
+++ b/include/param_prj.h
@@ -32,10 +32,10 @@
#define PARAM_LIST \
PARAM_ENTRY(CAT_SETUP, Inverter, INVMODES, 0, 8, 0, 5 ) \
PARAM_ENTRY(CAT_SETUP, Vehicle, VEHMODES, 0, 8, 0, 6 ) \
- PARAM_ENTRY(CAT_SETUP, GearLvr, SHIFTERS, 0, 4, 0, 108 ) \
+ PARAM_ENTRY(CAT_SETUP, GearLvr, SHIFTERS, 0, 5, 0, 108 ) \
PARAM_ENTRY(CAT_SETUP, Transmission, TRNMODES, 0, 1, 0, 78 ) \
PARAM_ENTRY(CAT_SETUP, interface, CHGINT, 0, 4, 0, 39 ) \
- PARAM_ENTRY(CAT_SETUP, chargemodes, CHGMODS, 0, 7, 0, 37 ) \
+ PARAM_ENTRY(CAT_SETUP, chargemodes, CHGMODS, 0, 8, 0, 37 ) \
PARAM_ENTRY(CAT_SETUP, BMS_Mode, BMSMODES, 0, 5, 0, 90 ) \
PARAM_ENTRY(CAT_SETUP, ShuntType, SHNTYPE, 0, 4, 0, 88 ) \
PARAM_ENTRY(CAT_SETUP, InverterCan, CAN_DEV, 0, 1, 0, 70 ) \
@@ -270,7 +270,7 @@
"12=DCFCRequest, 13=BrakeVacPump, 14=CoolingFan, 15=HvActive, 16=ShiftLockNO, 17=PreHeatOut, 18=PwmTim3, 19=CpSpoof,"\
"20=GS450pump, 21=PwmTempGauge, 22=PwmSocGauge"
#define APINFUNCS "0=None, 1=ProxPilot, 2=BrakeVacSensor, 3=HeaterPot"
-#define SHIFTERS "0=None, 1=BMW_F30, 2=JLR_G1, 3=JLR_G2, 4=BMW_E65"
+#define SHIFTERS "0=None, 1=BMW_F30, 2=JLR_G1, 3=JLR_G2, 4=BMW_E65, 5=Porsche_PDK"
#define SHNTYPE "0=None, 1=ISA, 2=SBOX, 3=VAG. 4=ISA_udcsw"
#define DMODES "0=CLOSED, 1=OPEN, 2=ERROR, 3=INVALID"
#define POTMODES "0=SingleChannel, 1=DualChannel"
@@ -298,7 +298,7 @@
#define CDMSTAT "1=Charging, 2=Malfunction, 4=ConnLock, 8=BatIncomp, 16=SystemMalfunction, 32=Stop"
#define HTTYPE "0=None, 1=Ampera, 2=VWCoolant, 3=VWAir, 4=OutlanderCan, 5=MGCoolant"
#define HTCTRL "0=Disable, 1=Enable, 2=Timer"
-#define CHGMODS "0=Off, 1=EXT_DIGI, 2=Volt_Ampera, 3=Leaf_PDM, 4=TeslaOI, 5=Out_lander, 6=Elcon, 7=MGgen2"
+#define CHGMODS "0=Off, 1=EXT_DIGI, 2=Volt_Ampera, 3=Leaf_PDM, 4=TeslaOI, 5=Out_lander, 6=Elcon, 7=MGgen2, 8=MLBEvo"
#define CHGCTRL "0=Enable, 1=Disable, 2=Timer"
#define CHGINT "0=Unused, 1=i3LIM, 2=Chademo, 3=CPC, 4=Foccci"
#define CAN3SPD "0=k33.3, 1=k500, 2=k100"
@@ -388,7 +388,8 @@ enum ChargeModes
TeslaOI = 4,
Out_lander = 5,
Elcon = 6,
- MGgen2=7
+ MGgen2 = 7,
+ MLBevo = 8
};
enum ChargeInterfaces
@@ -433,7 +434,8 @@ enum ShifterModes
BMWF30 = 1,
JLRG1 = 2,
JLRG2 =3,
- BMWE65 =4
+ BMWE65 =4,
+ PorschePDK =5
};
diff --git a/include/vag_utils.h b/include/vag_utils.h
new file mode 100644
index 00000000..4407d9f5
--- /dev/null
+++ b/include/vag_utils.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the ZombieVeter project.
+ *
+ * Copyright (C) 2020 Johannes Huebner
+ * 2021-2022 Damien Maguire
+ * 2024 Mitch Elliott
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+ #ifndef VAG_UTILS_H
+ #define VAG_UTILS_H
+
+ #include
+ #include "my_fp.h"
+ #include "my_math.h"
+
+ namespace vag_utils
+ {
+ uint8_t vw_crc_calc(uint8_t* inputBytes, uint8_t length, uint16_t address);
+ uint8_t vw_crc_calc_MQB(uint8_t* inputBytes, uint8_t length, uint16_t address);
+ }
+
+ #endif
+
\ No newline at end of file
diff --git a/include/vw_mlb_charger.h b/include/vw_mlb_charger.h
new file mode 100644
index 00000000..e61fb245
--- /dev/null
+++ b/include/vw_mlb_charger.h
@@ -0,0 +1,151 @@
+
+/*
+ * This file is part of the ZombieVerter project.
+ *
+ * Copyright (C) 2024 Mitch Elliott
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#ifndef vw_mlb_charger_h
+#define vw_mlb_charger_h
+
+#include "chargerhw.h"
+#include "chargerint.h"
+#include "canhardware.h"
+#include
+#include "my_fp.h"
+#include "params.h"
+#include "my_math.h"
+#include "stm32_can.h"
+#include "CANSPI.h"
+#include "vag_utils.h"
+
+class VWMLBClass: public Chargerhw
+{
+public:
+ bool ControlCharge(bool RunCh, bool ACReq);
+ void SetCanInterface(CanHardware*);
+ void DecodeCAN(int id, uint32_t data[2]);
+ void Task1Ms();
+ void Task10Ms();
+ void Task100Ms();
+ void Task200Ms();
+
+
+private:
+ //void CommandStates();
+ void Simulate();
+ void TagParams();
+ void CalcValues100ms();
+ void msg3C0();
+ void msg1A1(); // BMS_02 0x1A1
+ void msg2B1(); // MSG_TME_02 0x2B1
+ void msg39D(); // BMS_03 0x39D
+ void msg485(); // NavData_02 0x485
+ void msg509(); // BMS_10 0x509
+ void msg552(); // HVEM_05 0x552
+ void msg583(); // ZV_02 0x583
+ void msg59E(); // BMS_06 0x59E
+ void msg5AC(); // HVEM_02 0x5AC
+ void msg64F(); // BCM1_04 0x64F
+ void msg663(); // NVEM_02 0x663
+ void msg1A555548(); // ORU_01 0x1A555548
+ void msg1A5555AD(); // Authentic_Time_01 0x1A5555AD
+ void msg96A955EB(); // BMS_09 0x96A955EB
+ void msg96A954A6(); // BMS_11 0x96A954A6
+ void msg9A555539(); // BMS_16 0x9A555539
+ void msg9A555552(); // BMS_27 0x9A555552
+ void msg040(); // Airbag_01 0x40
+ void msg184(); // ZV_01 0x184
+ void msg191(); // BMS_01 0x191
+ void msg1A2(); // ESP_15 0x1A2
+ void msg2AE(); // DCDC_01 0x2AE
+ void msg37C(); // EM1_HYB_11 0x37C
+ void msg503(); // HVK_01 0x503
+ void msg578(); // BMS_DC_01 0x578
+ void msg5A2(); // BMS_04 0x5A2
+ void msg5CA(); // BMS_07 0x5CA
+ void msg5CD(); // DCDC_03 0x5CD
+ uint8_t Airbag_01[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t Authentic_Time_01[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t BCM1_04[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t BMS_01[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t BMS_02[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t BMS_03[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t BMS_04[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t BMS_06[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t BMS_07[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t BMS_09[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t BMS_10[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t BMS_11[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t BMS_16[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t BMS_27[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t BMS_DC_01[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t EM_HYB_11[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t ESP_15[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t Dimmung_01[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t DCDC_01[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t DCDC_02[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t DCDC_03[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t HVK_01[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t HVEM_02[8] = {0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t HVEM_05[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t Klemmen_Status_01[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t MSG_TME_02[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t NVEM_02[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t ORU_01[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t ZV_02[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t HVLM_06[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t HVLM_04[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t LAD_01[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t HVLM_03[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t LAD_02[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t HVLM_10[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t HVLM_11[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t HVLM_08[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t HVLM_15[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t LAD_06[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t ZV_01[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint8_t vag_cnt3C0 = 0x00;
+ uint8_t vag_cnt040 = 0x00;
+ uint8_t vag_cnt184 = 0x00;
+ uint8_t vag_cnt191 = 0x00;
+ uint8_t vag_cnt1A2 = 0x00;
+ uint8_t vag_cnt37C = 0x00;
+ uint8_t vag_cnt2AE = 0x00;
+ uint8_t vag_cnt503 = 0x00;
+ uint8_t vag_cnt578 = 0x00;
+ uint8_t vag_cnt5A2 = 0x00;
+ uint8_t vag_cnt5CA = 0x00;
+ uint8_t vag_cnt5CD = 0x00;
+};
+
+class VWMLBintClass: public Chargerint
+{
+public:
+ // void SetCanInterface(CanHardware* c);
+ // void DecodeCAN(int id, uint32_t data[2]);
+ // void Task10Ms();
+ // void Task100Ms();
+ // void Task200Ms();
+ // bool DCFCRequest(bool RunCh);
+ // bool ACRequest(bool RunCh);
+
+
+protected:
+ // CanHardware* can;
+
+};
+
+#endif /* vw_mlb_charger_h */
diff --git a/src/Gear_9x1.cpp b/src/Gear_9x1.cpp
new file mode 100644
index 00000000..8105e28f
--- /dev/null
+++ b/src/Gear_9x1.cpp
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the Zombieverter project.
+ *
+ * Copyright (C) 2024 Mitch Elliott
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "Gear_9x1.h"
+
+uint8_t Gear9x1LeverPos = 0x78; // Gear Lever Position on Init
+uint8_t Gear9x1TipSport = 0; // Tip +/- Sport Postion
+uint8_t Gear9x1Checksum = 0; // Checksum Value for Plausibilty
+uint8_t Gear9x1Counter = 0; // Counter Value
+
+void Gear_9x1::SetCanInterface(CanHardware* c)
+{
+ can = c;
+ can->RegisterUserMessage(0x133);// 9x1 based shifter CAN message: WHL_01
+}
+
+
+void Gear_9x1::DecodeCAN(int id, uint32_t* data)
+{
+ uint8_t *bytes = (uint8_t *)data;
+ if (id == 0x133)
+ {
+ Gear9x1LeverPos = bytes[0];
+ Gear9x1Counter = (bytes[1] >> 4); // Mapping for later to determine signal validity
+ Gear9x1TipSport = (bytes[1] & (0x0FU)); // +/- sport movement
+ Gear9x1Checksum = bytes[6]; // Mapping for later to determine signal validity
+
+ switch (Gear9x1LeverPos)
+ {
+ case 0x78: // Park
+ {
+ this->gear = PARK;
+ }
+ break;
+ case 0x87: // Reverse
+ {
+ this->gear = REVERSE;
+ }
+ break;
+ case 0x96: // Neutral
+ {
+ this->gear = NEUTRAL;
+ }
+ break;
+ case 0xA5: // Drive
+ {
+ this->gear = DRIVE;
+ }
+ break;
+ case 0x1E: // Manual/ Tip
+ {
+ this->gear = DRIVE;
+ }
+ break;
+ }
+ }
+}
+
+ void Gear_9x1::Task10Ms()
+ {
+
+ }
+
+ void Gear_9x1::Task100Ms()
+ {
+
+ }
+
+ bool Gear_9x1::GetGear(Shifter::Sgear& outGear)
+{
+ outGear = gear; //send the shifter pos
+ return true; //Let caller know we set a valid gear
+}
diff --git a/src/stm32_vcu.cpp b/src/stm32_vcu.cpp
index 5065c46d..e9191ea2 100644
--- a/src/stm32_vcu.cpp
+++ b/src/stm32_vcu.cpp
@@ -91,8 +91,10 @@
#include "JLR_G1.h"
#include "JLR_G2.h"
#include "no_Lever.h"
+#include "Gear_9x1.h"
#include "CPC.h"
#include "Foccci.h"
+#include "vw_mlb_charger.h"
#include "NoInverter.h"
#include "linbus.h"
#include "VWCoolantHeater.h"
@@ -168,6 +170,7 @@ static FCChademo chademoFC;
static i3LIMClass LIMFC;
static CPCClass CPCcan;
static FoccciClass Focccican;
+static VWMLBClass MLBcharger;
static Can_OI openInv;
static NoInverterClass NoInverter;
static OutlanderInverter outlanderInv;
@@ -179,6 +182,7 @@ static F30_Lever F30GearLever;
static E65_Lever E65GearLever;
static JLR_G1 JLRG1shift;
static JLR_G2 JLRG2shift;
+static Gear_9x1 PorschePDKshift;
static vwCoolantHeater heaterCoolantVW;
static mgCoolantHeater heaterCoolantMG;
static vwAirHeater heaterAirVW;
@@ -959,6 +963,9 @@ static void UpdateCharger()
case ChargeModes::MGgen2:
selectedCharger = &MGgen2v2l;
break;
+ case ChargeModes::MLBevo:
+ selectedCharger = &MLBcharger;
+ break;
}
@@ -1101,6 +1108,10 @@ static void UpdateShifter()
case ShifterModes::BMWE65:
selectedShifter = &E65GearLever;
break;
+
+ case ShifterModes::PorschePDK:
+ selectedShifter = &PorschePDKshift;
+ break;
default:
// Default to no shifter
diff --git a/src/vag_utils.cpp b/src/vag_utils.cpp
new file mode 100644
index 00000000..57b0bd7d
--- /dev/null
+++ b/src/vag_utils.cpp
@@ -0,0 +1,278 @@
+/*
+ * This file is part of the ZombieVeter project.
+ *
+ * Copyright (C) 2020 Johannes Huebner
+ * 2021-2022 Damien Maguire
+ * 2024 Mitch Elliott
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+
+#include "vag_utils.h"
+
+namespace vag_utils {
+
+uint8_t vw_crc_calc(uint8_t* inputBytes, uint8_t length, uint16_t address)
+{
+ const uint8_t poly = 0x2F;
+ const uint8_t xor_output = 0xFF;
+ // VAG Magic Bytes
+ const uint8_t MB0040[16] = { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 };
+ const uint8_t MB0073[16] = { 0xdb, 0x71, 0x31, 0xf9, 0x26, 0x43, 0x6d, 0x22, 0x52, 0xe4, 0xe8, 0xa9, 0x73, 0x1c, 0xc5, 0x67 };
+ const uint8_t MB0074[16] = { 0xb7, 0x6e, 0x93, 0xf5, 0xdc, 0x38, 0xe2, 0x40, 0x06, 0xfb, 0x80, 0x1c, 0x0e, 0xe3, 0xd5, 0xe5 };
+ const uint8_t MB0075[16] = { 0x63, 0x04, 0xb4, 0x32, 0x56, 0xc1, 0xfa, 0x97, 0x1f, 0xa6, 0xae, 0xd7, 0x64, 0xc3, 0xbe, 0x42 };
+ const uint8_t MB0080[16] = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
+ const uint8_t MB0081[16] = { 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81 };
+ const uint8_t MB0082[16] = { 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82 };
+ const uint8_t MB0083[16] = { 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83 };
+ const uint8_t MB0087[16] = { 0x14, 0x40, 0x8b, 0x7a, 0x78, 0x23, 0xc6, 0x13, 0x1c, 0x03, 0xed, 0xf4, 0xcb, 0xf8, 0xf0, 0xe5 };
+ const uint8_t MB0097[16] = { 0x3C, 0x54, 0xCF, 0xA3, 0x81, 0x93, 0x0B, 0xC7, 0x3E, 0xDF, 0x1C, 0xB0, 0xA7, 0x25, 0xD3, 0xD8 };
+ const uint8_t MB009D[16] = { 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D };
+ const uint8_t MB00A0[16] = { 0x4a, 0xb4, 0xe8, 0x24, 0x99, 0x5a, 0x59, 0x8b, 0x1e, 0xaa, 0x94, 0xb6, 0x09, 0xd5, 0xaf, 0x97 };
+ const uint8_t MB00A8[16] = { 0x52, 0x8c, 0x50, 0xee, 0x4f, 0xa6, 0xcc, 0xcf, 0x7d, 0x2f, 0x98, 0x6b, 0x27, 0x41, 0x9f, 0x93 };
+ const uint8_t MB00AA[16] = { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA };
+ const uint8_t MB00AB[16] = { 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB };
+ const uint8_t MB00B1[16] = { 0xe1, 0x9e, 0xc2, 0xe9, 0x48, 0x98, 0xf5, 0xb6, 0x47, 0x83, 0x26, 0x45, 0x9a, 0x10, 0x7b, 0x1c };
+ const uint8_t MB00B3[16] = { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 };
+ const uint8_t MB0102[16] = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
+ const uint8_t MB0105[16] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+ const uint8_t MB0108[16] = { 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09 };
+ const uint8_t MB010E[16] = { 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F };
+ const uint8_t MB0111[16] = { 0xb3, 0xeb, 0xe1, 0xf7, 0xba, 0x9e, 0x5f, 0xd9, 0xc2, 0xec, 0xf6, 0xe9, 0x24, 0x18, 0x48, 0xed };
+ const uint8_t MB0114[16] = { 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15 };
+ const uint8_t MB0116[16] = { 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac };
+ const uint8_t MB0121[16] = { 0xe9, 0x65, 0xae, 0x6b, 0x7b, 0x35, 0xe5, 0x5f, 0x4e, 0xc7, 0x86, 0xa2, 0xbb, 0xdd, 0xeb, 0xb4 };
+ const uint8_t MB0124[16] = { 0x12, 0x7E, 0x34, 0x16, 0x25, 0x8F, 0x8E, 0x35, 0xBA, 0x7F, 0xEA, 0x59, 0x4C, 0xF0, 0x88, 0x15 };
+ const uint8_t MB0136[16] = { 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37 };
+ const uint8_t MB0153[16] = { 0x03, 0x13, 0x23, 0x7a, 0x40, 0x51, 0x68, 0xba, 0xa8, 0xbe, 0x55, 0x02, 0x11, 0x31, 0x76, 0xec };
+ const uint8_t MB0154[16] = { 0x21, 0x93, 0x4a, 0x04, 0x5c, 0x18, 0xe0, 0x69, 0x14, 0xce, 0x26, 0x8f, 0x5e, 0xb1, 0xdf, 0x53 };
+ const uint8_t MB0184[16] = { 0xe3, 0xe8, 0xc4, 0x7f, 0xf1, 0x95, 0xd8, 0xb0, 0xc7, 0xa3, 0xf4, 0x6c, 0xe7, 0xc3, 0x5a, 0xf7 };
+ const uint8_t MB0187[16] = { 0x7F, 0xED, 0x17, 0xC2, 0x7C, 0xEB, 0x44, 0x21, 0x01, 0xFA, 0xDB, 0x15, 0x4A, 0x6B, 0x23, 0x05 };
+ const uint8_t MB018D[16] = { 0x9c, 0xcc, 0xe1, 0x4c, 0xc9, 0x39, 0xe3, 0x53, 0x78, 0x33, 0x15, 0x49, 0x55, 0x0a, 0x62, 0x83 };
+ const uint8_t MB0191[16] = { 0x7d, 0x0e, 0xaf, 0x0b, 0x24, 0x58, 0x88, 0x9e, 0x89, 0x3a, 0x81, 0x61, 0x4e, 0xe3, 0x04, 0x1f };
+ const uint8_t MB01A2[16] = { 0xcb, 0x47, 0xd7, 0xd2, 0x56, 0x3e, 0x20, 0xea, 0x6e, 0x6d, 0x8c, 0x1b, 0xdf, 0x49, 0xaa, 0xab };
+ const uint8_t MB01A3[16] = { 0x4a, 0x06, 0x0a, 0x36, 0xf8, 0xd3, 0x60, 0x79, 0xaa, 0xd2, 0x2e, 0x89, 0xa3, 0x76, 0x5f, 0x45 };
+ const uint8_t MB01F3[16] = { 0xc4, 0x1e, 0x9c, 0xae, 0x59, 0xcc, 0x66, 0x99, 0xe1, 0x87, 0xe8, 0x4c, 0x65, 0x4a, 0xc9, 0xde };
+ const uint8_t MB01F9[16] = { 0x14, 0xf8, 0xf6, 0x94, 0x2a, 0x12, 0x39, 0x3d, 0x98, 0x3f, 0xfb, 0x9d, 0x36, 0xca, 0x1d, 0xe0 };
+ const uint8_t MB020F[16] = { 0xd4, 0x22, 0xad, 0x3f, 0x25, 0xaa, 0x62, 0x5b, 0xdc, 0x73, 0xed, 0xc3, 0x9a, 0x14, 0x2f, 0x3e };
+ const uint8_t MB02AD[16] = { 0x7b, 0xed, 0xa6, 0xd1, 0x57, 0x4b, 0x69, 0x9f, 0x13, 0x82, 0x9e, 0x19, 0x3e, 0x08, 0x5e, 0x78 };
+ const uint8_t MB02AE[16] = { 0x83, 0x50, 0xbf, 0x5d, 0x67, 0x68, 0x2f, 0x4b, 0x32, 0x4e, 0x1a, 0xba, 0xc4, 0x39, 0xf5, 0xdb };
+ const uint8_t MB030E[16] = { 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D };
+ const uint8_t MB0312[16] = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 };
+ const uint8_t MB031B[16] = { 0x67, 0x8a, 0xae, 0x22, 0x4d, 0xd0, 0x51, 0x80, 0x5c, 0xb9, 0xce, 0x1e, 0xdf, 0x02, 0x2d, 0xd4 };
+ const uint8_t MB0365[16] = { 0xe3, 0x0a, 0x29, 0xd3, 0x96, 0xaa, 0xeb, 0x89, 0xe6, 0x5f, 0x14, 0xc4, 0xe9, 0x27, 0x0b, 0x2d };
+ const uint8_t MB0367[16] = { 0xa1, 0xb0, 0xdb, 0x69, 0x9c, 0xef, 0xbd, 0x08, 0xdd, 0xcc, 0x1b, 0x05, 0xce, 0x20, 0xe1, 0x48 };
+ const uint8_t MB037C[16] = { 0xed, 0x03, 0x1c, 0x13, 0xc6, 0x23, 0x78, 0x7a, 0x8b, 0x40, 0x14, 0x51, 0xbf, 0x68, 0x32, 0xba };
+ const uint8_t MB0393[16] = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 };
+ const uint8_t MB0394[16] = { 0x47, 0x94, 0x92, 0x6a, 0x67, 0xb5, 0x0d, 0x38, 0xe3, 0x8a, 0x5d, 0xb4, 0x54, 0xab, 0xae, 0x27 };
+ const uint8_t MB03A6[16] = { 0xB6, 0x1C, 0xC1, 0x23, 0x6D, 0x8B, 0x0C, 0x51, 0x38, 0x32, 0x24, 0xA8, 0x3F, 0x3A, 0xA4, 0x02 };
+ const uint8_t MB03AF[16] = { 0x94, 0x6A, 0xB5, 0x38, 0x8A, 0xB4, 0xAB, 0x27, 0xCB, 0x22, 0x88, 0xEF, 0xA3, 0xE1, 0xD0, 0xBB };
+ const uint8_t MB03BE[16] = { 0x1f, 0x28, 0xc6, 0x85, 0xe6, 0xf8, 0xb0, 0x19, 0x5b, 0x64, 0x35, 0x21, 0xe4, 0xf7, 0x9c, 0x24 };
+ const uint8_t MB03C0[16] = { 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3 };
+ const uint8_t MB03F4[16] = { 0x26, 0xe4, 0xc5, 0x16, 0xcf, 0x20, 0x65, 0xad, 0xed, 0x6a, 0xa3, 0x49, 0x02, 0x6b, 0xb2, 0xbd };
+ const uint8_t MB03FA[16] = { 0x26, 0xe3, 0x43, 0x0a, 0x6d, 0x29, 0x22, 0xd3, 0x52, 0x96, 0xe4, 0xaa, 0xe8, 0xeb, 0xa9, 0x89 };
+ const uint8_t MB0450[16] = { 0x30, 0x25, 0xc2, 0x1f, 0x02, 0xb1, 0x9e, 0xe0, 0x73, 0x51, 0xe1, 0xa5, 0xab, 0x0d, 0xf4, 0x2f };
+ const uint8_t MB0451[16] = { 0x19, 0xc1, 0x1a, 0xf6, 0x7d, 0x28, 0x7b, 0x12, 0xcb, 0x29, 0x59, 0x98, 0xd2, 0xbf, 0x53, 0x9d };
+ const uint8_t MB0452[16] = { 0x74, 0x4a, 0x84, 0x18, 0xb9, 0x14, 0x9e, 0x8f, 0x0c, 0xdf, 0x29, 0x40, 0x63, 0x1f, 0xd4, 0xca };
+ const uint8_t MB0457[16] = { 0x82, 0x79, 0xee, 0xb9, 0xf9, 0x67, 0x97, 0xad, 0xb1, 0xd5, 0xcb, 0xf7, 0xb6, 0x70, 0x13, 0xaa };
+ const uint8_t MB0489[16] = { 0x7A, 0x13, 0xF4, 0xE5, 0xC9, 0x07, 0x21, 0xDD, 0x6F, 0x94, 0x63, 0x9B, 0xD2, 0x93, 0x42, 0x33 };
+ const uint8_t MB0503[16] = { 0xed, 0xd6, 0x96, 0x63, 0xa5, 0x12, 0xd5, 0x9a, 0x1e, 0x0d, 0x24, 0xcd, 0x8c, 0xa6, 0x2f, 0x41 };
+ const uint8_t MB0504[16] = { 0x03, 0x63, 0x3e, 0x04, 0xf9, 0xb4, 0x4f, 0x32, 0x25, 0x56, 0x1e, 0xc1, 0x83, 0xfa, 0x31, 0x97 };
+ const uint8_t MB053C[16] = { 0x8e, 0xf9, 0xe1, 0x2e, 0x83, 0x34, 0xd0, 0xf1, 0xaa, 0x2c, 0xbb, 0x81, 0x17, 0x60, 0x11, 0x37 };
+ const uint8_t MB0560[16] = { 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65 };
+ const uint8_t MB0564[16] = { 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24 };
+ const uint8_t MB0578[16] = { 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48 };
+ const uint8_t MB05A2[16] = { 0xeb, 0x4c, 0x44, 0xaf, 0x21, 0x8d, 0x01, 0x58, 0xfa, 0x93, 0xdb, 0x89, 0x15, 0x10, 0x4a, 0x61 };
+ const uint8_t MB05A3[16] = { 0x0a, 0xd3, 0xaa, 0x89, 0x5f, 0xc4, 0x27, 0x2d, 0xfb, 0xa0, 0x47, 0x1e, 0x28, 0xa8, 0x44, 0x5c };
+ const uint8_t MB05CA[16] = { 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43 };
+ const uint8_t MB05CC[16] = { 0x92, 0x9d, 0xb8, 0x71, 0xc4, 0x40, 0x3d, 0x49, 0x5b, 0x4d, 0xfa, 0x94, 0x6d, 0x72, 0xb3, 0x46 };
+ const uint8_t MB05CD[16] = { 0x93, 0x04, 0x18, 0x69, 0xce, 0x8f, 0xb1, 0x53, 0x40, 0x2d, 0xe4, 0xca, 0x90, 0x25, 0x79, 0x8c };
+ const uint8_t MB0641[16] = { 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47 };
+ const uint8_t MB065D[16] = { 0xac, 0xb3, 0xab, 0xeb, 0x7a, 0xe1, 0x3b, 0xf7, 0x73, 0xba, 0x7c, 0x9e, 0x06, 0x5f, 0x02, 0xd9 };
+ const uint8_t MB067E[16] = { 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25 };
+ const uint8_t MB06A3[16] = { 0xC1, 0x8B, 0x38, 0xA8, 0xA4, 0x27, 0xEB, 0xC8, 0xEF, 0x05, 0x9A, 0xBB, 0x39, 0xF7, 0x80, 0xA7 };
+ const uint8_t MB06A4[16] = { 0xC7, 0xD8, 0xF1, 0xC4, 0xE3, 0x5E, 0x9A, 0xE2, 0xA1, 0xCB, 0x02, 0x4F, 0x57, 0x4E, 0x8E, 0xE4 };
+ const uint8_t MB092DD5477[16] = { 0x41, 0x5e, 0x7f, 0xc7, 0xc3, 0x04, 0x0a, 0x11, 0x34, 0x4d, 0x9b, 0x27, 0xaf, 0x0d, 0x0f, 0x31 };
+ const uint8_t MB092DD5478[16] = { 0xe0, 0x2f, 0x8d, 0x3c, 0x70, 0x22, 0x03, 0x60, 0x0e, 0x18, 0xd9, 0xeb, 0x95, 0x63, 0xcb, 0x76 };
+ const uint8_t MB092DD5490[16] = { 0x48, 0x52, 0xa7, 0xe6, 0x83, 0x2b, 0x8c, 0xfb, 0x7b, 0x64, 0x58, 0x50, 0xbc, 0xb3, 0x0f, 0x9c };
+ const uint8_t MB092DD5491[16] = { 0xb1, 0x44, 0x37, 0xca, 0xb5, 0xd6, 0x0e, 0xa3, 0x3b, 0x16, 0xa6, 0x1a, 0x23, 0x1d, 0x91, 0x9c };
+ const uint8_t MB092DD5493[16] = { 0x74, 0x7e, 0x45, 0xe8, 0x3c, 0xd0, 0x13, 0x1f, 0x4e, 0x3a, 0x88, 0x0b, 0x7d, 0xd2, 0x6d, 0xab };
+ const uint8_t MB092DD54AB[16] = { 0xab, 0xe1, 0x73, 0x9e, 0x02, 0xc2, 0x30, 0xe9, 0x75, 0x48, 0x2e, 0x98, 0x7f, 0xf5, 0xa7, 0xb6 };
+ const uint8_t MB092DD54AD[16] = { 0x02, 0xf4, 0x6f, 0x42, 0x4a, 0x62, 0xcd, 0x1b, 0xb4, 0xa0, 0x16, 0x14, 0xe8, 0x0a, 0x71, 0xef };
+ const uint8_t MB092DD54E0[16] = { 0xd0, 0x4d, 0x22, 0xae, 0x8a, 0x67, 0xf4, 0x35, 0x15, 0x2a, 0xb8, 0x4e, 0xcc, 0x07, 0xad, 0xa2 };
+ const uint8_t MB092DD550B[16] = { 0x67, 0xf7, 0x44, 0xdc, 0xd2, 0xca, 0xe7, 0x2b, 0xd6, 0x5c, 0xc6, 0xa3, 0xbe, 0x0d, 0x16, 0x58 };
+ const uint8_t MB096A95414[16] = { 0xa3, 0xed, 0x65, 0xcf, 0xc5, 0x26, 0x54, 0x1a, 0x99, 0x3c, 0x01, 0x84, 0xf4, 0x46, 0x9c, 0x28 };
+ const uint8_t MB096A95415[16] = { 0x01, 0x40, 0xf0, 0x21, 0x22, 0x92, 0x44, 0x1a, 0x85, 0xeb, 0x7b, 0xcd, 0x7c, 0x59, 0xc5, 0xc2 };
+ const uint8_t MB096A954A6[16] = { 0x79, 0xb9, 0x67, 0xad, 0xd5, 0xf7, 0x70, 0xaa, 0x44, 0x61, 0x5a, 0xdc, 0x26, 0xb4, 0xd2, 0xc3 };
+ const uint8_t MB09A555517[16] = { 0xfb, 0xee, 0x5d, 0x2d, 0xfa, 0x85, 0x27, 0xd4, 0xc9, 0xc4, 0xa5, 0x45, 0x5f, 0x76, 0xa3, 0x89 };
+ const uint8_t MB09A555545[16] = { 0xc2, 0xe1, 0xd3, 0x20, 0x42, 0xce, 0x68, 0x05, 0xa9, 0x1b, 0xa3, 0xcc, 0xe2, 0xdd, 0x14, 0x08 };
+
+ uint8_t crc = 0xFF;
+ uint8_t magicByte = 0x00;
+ uint8_t counter = inputBytes[1] & 0x0F; // only the low byte of the counter is relevant
+
+ switch (address)
+ {
+ case 0x03C0: // ??
+ magicByte = MB03C0[counter];
+ break;
+ case 0x0040: // ??
+ magicByte = MB0040[counter];
+ break;
+ case 0x0184: // ??
+ magicByte = MB0184[counter];
+ break;
+ case 0x0191: // ??
+ magicByte = MB0191[counter];
+ break;
+ case 0x01A2: // ??
+ magicByte = MB01A2[counter];
+ break;
+ case 0x02AE: // ??
+ magicByte = MB02AE[counter];
+ break;
+ case 0x037C: // ??
+ magicByte = MB037C[counter];
+ break;
+ case 0x0503: // ??
+ magicByte = MB0503[counter];
+ break;
+ case 0x0578: // ??
+ magicByte = MB0578[counter];
+ break;
+ case 0x05A2: // ??
+ magicByte = MB05A2[counter];
+ break;
+ case 0x05CA: // ??
+ magicByte = MB05CA[counter];
+ break;
+ case 0x05CD: // ??
+ magicByte = MB05CD[counter];
+ break;
+ default: // this won't lead to correct CRC checksums
+ magicByte = 0x00;
+ break;
+ }
+
+ for (uint8_t i = 1; i < length + 1; i++)
+ {
+ // We skip the empty CRC position and start at the timer
+ // The last element is the VAG magic byte for address 0x187 depending on the counter value.
+ if (i < length)
+ crc ^= inputBytes[i];
+ else
+ crc ^= magicByte;
+
+ for (uint8_t j = 0; j < 8; j++)
+ {
+ if (crc & 0x80)
+ crc = (crc << 1) ^ poly;
+ else
+ crc = (crc << 1);
+ }
+ }
+
+ crc ^= xor_output;
+
+ inputBytes[0] = crc; // set the CRC checksum directly in the output bytes
+ return crc;
+}
+
+uint8_t vw_crc_calc_MQB(uint8_t* inputBytes, uint8_t length, uint16_t address)
+{
+
+ // const uint8_t poly = 0x2F;
+ const uint8_t xor_output = 0xFF;
+
+ uint8_t crc = 0xFF;
+ uint8_t magicByte = 0x00;
+ uint8_t counter = inputBytes[1] & 0x0F; // only the low byte of the counter is relevant
+
+ switch (address)
+ {
+ case 0x0080: // Motor1
+ magicByte = 0x80;
+ break;
+ case 0x0081: // Motor2
+ magicByte = 0x81;
+ break;
+ case 0x0082: // Gearbox1
+ magicByte = 0x82;
+ break;
+ case 0x0083: // Gearbox2
+ magicByte = 0x83;
+ break;
+ case 0x00AA: // Motor13
+ magicByte = 0xAA;
+ break;
+ case 0x00AB: // Gearbox7
+ magicByte = 0xAB;
+ break;
+ case 0x0102: // Gearbox3
+ magicByte = 0x03;
+ break;
+ case 0x0105: // Motor3
+ magicByte = 0x04;
+ break;
+ case 0x010E: // TSK4
+ magicByte = 0x0F;
+ break;
+ case 0x0111: // TSK5
+ magicByte = 0x10;
+ break;
+ case 0x0114: // Motor10
+ magicByte = 0x15;
+ break;
+ case 0x030E: // Motor5
+ magicByte = 0x0D;
+ break;
+ case 0x0312: // TSK3
+ magicByte = 0x11;
+ break;
+ case 0x0393: // WBA2
+ magicByte = 0x90;
+ break;
+ case 0x0641: // Motorcode
+ magicByte = 0x47;
+ break;
+ default: // this won't lead to correct CRC checksums
+ magicByte = 0x00;
+ break;
+ }
+
+ for (uint8_t i = 1; i < length + 1; i++)
+ {
+ // We skip the empty CRC position and start at the timer
+ // The last element is the VAG magic byte for address 0x187 depending on the counter value.
+ if (i < length)
+ crc ^= inputBytes[i];
+ else
+ crc ^= magicByte;
+
+ for (uint8_t j = 0; j < 8; j++)
+ {
+ // if (crc & 0x80)
+ // crc = (crc << 1) ^ poly;
+ // else
+ // crc = (crc << 1);
+ }
+ }
+
+ crc ^= xor_output;
+
+ inputBytes[0] = crc; // set the CRC checksum directly in the output bytes
+ return crc;
+}
+}
\ No newline at end of file
diff --git a/src/vw_mlb_charger.cpp b/src/vw_mlb_charger.cpp
new file mode 100644
index 00000000..bb5ba933
--- /dev/null
+++ b/src/vw_mlb_charger.cpp
@@ -0,0 +1,1002 @@
+/*
+ * This file is part of the ZombieVerter project.
+ *
+ * Copyright (C) 2024 Mitch Elliott
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+
+
+#include
+
+uCAN_MSG txMsg;
+uint8_t CanMsgBuf[8];
+
+struct VehicleStatus{
+ bool locked = false;
+ bool CANQuiet = false;
+} vehicle_status;
+
+struct ChargerStatus {
+ uint16_t ACvoltage ;
+ uint16_t HVVoltage ;
+ int8_t temperature ;
+ uint8_t mode;
+ uint16_t current;
+ uint8_t MaxACAmps;
+ uint8_t PPLim;
+ uint32_t HVLM_MaxDC_ChargePower; // maximum DC charging power
+ uint16_t HVLM_Max_DC_Voltage_DCLS; // maximum DC charging voltage
+ uint16_t HVLM_Actual_DC_Current_DCLS; // actual DC charging current
+ uint16_t HVLM_Max_DC_Current_DCLS; // maximum DC charging current
+ uint16_t HVLM_Min_DC_Voltage_DCLS; // minimum DC charging voltage
+ uint16_t HVLM_Min_DC_Current_DCLS; // minimum DC charging current
+ uint8_t HVLM_Status_Grid; // Information as to whether the vehicle is connected to a power grid.
+ uint8_t HVLM_EnergyFlowType; // Display of whether electricity flows into the vehicle and what it is used for.
+ uint8_t HVLM_OperationalMode; // Current Mode: 0=Inactive, 1=Active, 2=Init, 3=Error
+ uint8_t HVLM_HV_ActivationRequest; // HV activation request and reason for the request: 0=No Request, 1=Charging, 2=Battery Balancing, 3=AC/Climate
+ uint8_t HVLM_ChargerErrorStatus; // Current error status of the charger: 0=No Error, 1=DC-NotOK, 2=AC-NotOK, 3=Interlock, 4=Reserved, 5=Reserved, 6=No Component Function, 7=Init
+ uint8_t HVLM_Park_Request; // Request to lock the drive train
+ uint8_t HVLM_Park_Request_Maintain; // Request to keep the drive train locked
+ uint8_t HVLM_Plug_Status; // Plug detection status independent of charging mode (AC or DC): 0=Init, 1=No Plug Inserted, 2=Connector Inserted, Not Locked, 3=Connector Inserted & Locked
+ uint8_t HVLM_LoadRequest; // Charger Status: 0=No Request, 1=AC Charge, 2=DC Charge, 3=Recharge 12V, 4=AC AWC Charge, 5=Reserved, 6=Init, 7=Error
+ uint8_t HVLM_MaxBattChargeCurrent; // Recommended HV battery charging current for a planned charge
+ uint8_t LAD_Mode; // Operating mode of the charger
+ uint16_t LAD_AC_Volt_RMS; // Actual value AC grid voltage (RMS)
+ uint16_t LAD_VoltageOut_HV; // Output voltage of the charger
+ uint16_t LAD_CurrentOut_HV; // Output current charger
+ uint8_t LAD_Status_Voltage; //
+ uint16_t LAD_Temperature; // Instantaneous value: Charger temperature
+ uint16_t LAD_PowerLossVal; // Instantaneous value: power loss charger
+ uint16_t HVLM_HV_StaleTime; // Period between HV deactivated and HV activated
+ uint8_t HVLM_ChargeSystemState; // Displaying status about the charging system. 0=No issue, 1=System Defective, 2=System Incompatable 3=DC Charge not possible
+ uint8_t HVLM_Status_LED; // Status of the charging LED: 0=Colour1-off, 1=Colour2-White, 2=Colour3-Yellow, 3=Colour4-Green, 4=Colour5-Red, 5=Yellow Pulsing, 6=Green Pulsing, 7=Red Pulsing, 8=Green/Red Pulsing, 9=Green Flashing, 14=Init, 15=Error
+ uint8_t HVLM_MaxCurrent_AC; // Maximum permissible current on the primary side (AC)
+ bool HVLM_LG_ChargerTargetMode; // AC charger target mode: 0=Standby, 1=Mains Charging
+ uint8_t HVLM_TankCapReleaseRequest; // Fuel Cap Release: 0=No Release, 1=Release, 2=Init, 3=Error
+ uint8_t HVLM_RequestConnectorLock; // Request connector lock: 0=Unlock, 1=lock, 2=Init, 3=No Request
+ uint8_t HVLM_Start_VoltageMeasure_DCLS; // Message to the BMS that a measurement voltage is being applied to the DC charging station: 0=Inactive, 1=DCLS With Diode, 2=DCLS without Diode, 3=Reserve
+ uint8_t HVLM_ChargeReadyStatus; // Display whether AC or DC charging is not possible: 0=No Error, 1=AC Charge Not Possible, 2=DC Charge Not Possible, 3=AC & DC Charge Not Possible
+ uint16_t HVLM_Output_Voltage_HV; // Output voltage of the charger and DC voltage of the charging station. Measurement between the DC HV lines.
+ bool LAD_Reduction_ChargerTemp; // Reduction due to internal overtemperature in the charger
+ bool LAD_Reduction_Current; // Regulation due to current or voltage at the input or output
+ bool LAD_Reduction_SocketTemp; // Reduction due to excessive charging socket temperature
+ uint16_t LAD_MaxChargerPower_HV; // Maximum power charger in relation to the maximum power infrastructure (cable, charging station) and taking into account the charger efficiency
+ uint8_t LAD_PRX_CableCurrentLimit; // AC current limit due to PRX cable coding
+ bool LAD_ControlPilotStatus; // Status control pilot monitoring (detection of the control pilot duty cycle)
+ bool LAD_LockFeedback; // Status of connector lock (feedback contact of the locking actuator)
+ uint8_t LAD_ChargerCoolingDemand; // Cooling demand of the charger
+ bool LAD_ChargerWarning; // Collective warning charger: 0=Normal, 1=Warning
+ bool LAD_ChargerFault; // Collective error charger: 0=Normal, 1=No Charging Possible
+} charger_status;
+
+struct ChargerControl {
+ uint16_t HVDCSetpnt;
+ uint16_t IDCSetpnt;
+ uint16_t HVpwr=0;
+ uint16_t HVcur=0;
+ uint16_t calcpwr=0;
+ uint8_t modeSet;
+ bool activate;
+} charger_params;
+
+struct BatteryStatus {
+ uint16_t SOCx10; // SOC of battery, With implied decimal place
+ uint16_t SOC_Targetx10; // Target SOC of battery, With implied decimal place
+ uint16_t CapkWhx10; // Usable energy content of the HV battery
+ uint16_t BattkWhx10; // Current energy content of the HV battery
+ uint16_t BMSVoltx10; // BMS Voltage of battery
+ uint16_t BMSCurrx10; // BMS Current of battery, With implied decimal place
+ uint16_t BMSMaxVolt; // BMS Max Voltage of Battery
+ uint16_t BMSMinVolt; // BMS Min Voltage of Battery
+ uint16_t BMSMaxChargeCurr; // BMS Max Charge Curr
+ uint16_t BMSBattCellSumx10;
+ uint16_t BMSCellAhx10 = 1080;
+ uint8_t HV_Status; // 0=Init (no function), 1=BMS intermediate circuit voltage-free (U_Zwkr < 20V), 2=BMS intermediate circuit not free of voltage (U_Zwkr >/= 25V, hysteresis), 3=Error (e.g. error in the sensors)
+ uint8_t BMS_Status; // 0 "Component_OK" 1 "Limited_CompFct_Isoerror_I" 2 "Limited_CompFct_Isoerror_II" 3 "Limited_CompFct_Interlock" 4 "Limited_CompFct_SD" 5 "Limited_CompFct_Powerred" 6 "No_component_function" 7 "Init" ;
+ uint8_t BMS_Mode; //0 "HV_Off" 1 "Driving HV Active" 2 "Balancing" 3 "External Charger" 4 "AC Charging" 5 "Battery Fault" 6 "DC Charging" 7 "Init" ;
+ uint16_t BMS_Battery_Tempx10 = 242;
+ uint16_t BMS_Coolant_Tempx10 = 201;
+ uint16_t BMS_Cell_H_Tempx10 = 290;
+ uint16_t BMS_Cell_L_Tempx10 = 220;
+ uint16_t BMS_Cell_H_mV = 3850;
+ uint16_t BMS_Cell_L_mV = 3750;
+ bool HVIL_Open = false;
+
+} battery_status;
+
+uint32_t UnixTime;
+
+//BMS CAN Messages
+ uint16_t BMS_Batt_Curr;
+ uint16_t BMS_Batt_Volt;
+ uint16_t BMS_Batt_Volt_HVterm;
+ uint16_t BMS_SOC_HiRes;
+ uint16_t BMS_MaxDischarge_Curr;
+ uint16_t BMS_Min_Batt_Volt;
+ uint16_t BMS_Min_Batt_Volt_Discharge;
+ uint16_t BMS_MaxCharge_Curr;
+ uint16_t BMS_MaxCharge_Curr_Offset;
+ uint16_t BMS_Batt_Max_Volt;
+ uint16_t BMS_Min_Batt_Volt_Charge;
+ uint16_t BMS_OpenCircuit_Volts;
+ bool BMS_Status_ServiceDisconnect;
+ uint8_t BMS_HV_Status;
+ bool BMS_Faultstatus;
+ uint8_t BMS_IstModus;
+ uint16_t BMS_Batt_Ah;
+ uint16_t BMS_Target_SOC_HiRes;
+ uint16_t BMS_Batt_Temp;
+ uint16_t BMS_CurrBatt_Temp;
+ uint16_t BMS_CoolantTemp_Act;
+ uint16_t BMS_Batt_Energy;
+ uint16_t BMS_Max_Wh;
+ uint16_t BMS_BattEnergy_Wh_HiRes;
+ uint16_t BMS_MaxBattEnergy_Wh_HiRes;
+ uint16_t BMS_SOC;
+ uint16_t BMS_ResidualEnergy_Wh;
+ uint16_t BMS_SOC_ChargeLim;
+ uint16_t BMS_EnergyCount;
+ uint16_t BMS_EnergyReq_Full;
+ uint16_t BMS_ChargePowerMax;
+ uint16_t BMS_ChargeEnergyCount;
+ uint16_t BMS_BattCell_Temp_Max;
+ uint16_t BMS_BattCell_Temp_Min;
+ uint16_t BMS_BattCell_MV_Max;
+ uint16_t BMS_BattCell_MV_Min;
+ bool HVEM_Nachladen_Anf;
+ uint16_t HVEM_SollStrom_HV;
+ uint16_t HVEM_MaxSpannung_HV;
+ uint8_t HMS_Systemstatus;
+ uint8_t HMS_aktives_System;
+ bool HMS_Fehlerstatus;
+ uint8_t HVK_HVLM_Sollmodus; // Requested target mode of the charging manager: 0=Not Enabled, 1=Enabled
+ bool HV_Bordnetz_aktiv; // Indicates an active high-voltage vehicle electrical system: 0 = Not Active, 1 = Active
+ uint8_t HVK_MO_EmSollzustand; // 0 "HvOff" 1 "HvStbyReq" 2 "HvStbyWait" 3 "HvBattOnReq" 4 "HvBattOnWait" 10 "HvOnIdle" 20 "HvOnDrvRdy" 46 "HvAcChPreReq" 47 "HvAcChPreWait" 48 "HvAcChReq" 49 "HvAcChWait" 50 "HvAcCh" 56 "HvDcChPreReq" 57 "HvDcChPreWait" 58 "HvDcChReq" 59 "HvDcChWait" 60 "HvDcCh" 67 "HvChOffReq" 68 "HvChOffWait" 69 "HvOnIdleReq" 70 "HvOnIdleWait" 96 "HvCpntOffReq" 97 "HvCpntOffWait" 98 "HvBattOffReq" 99 "HvBattOffWait" 119 "HvElmOffReq" 120 "HvElmOff"
+ uint8_t HVK_BMS_Sollmodus; // 0 "HV_Off" 1 "HV_On" 3 "AC_Charging_ext" 4 "AC_Charging" 6 "DC_Charging" 7 "Init" ;
+ uint8_t HVK_DCDC_Sollmodus; //0 "Standby" 1 "HV_On_Precharging" 2 "Step down" 3 "Step up" 4 "Test pulse_12V" 7 "Initialization" ;
+ bool ZV_FT_verriegeln;
+ bool ZV_FT_entriegeln;
+ bool ZV_BT_verriegeln;
+ bool ZV_BT_entriegeln;
+ bool ZV_entriegeln_Anf;
+ bool ZV_verriegelt_intern_ist;
+ bool ZV_verriegelt_extern_ist;
+ bool ZV_verriegelt_intern_soll;
+ bool ZV_verriegelt_extern_soll;
+ uint8_t ZV_verriegelt_soll;
+ bool BMS_Charger_Active;
+ uint16_t BMS_RIso_Ext = 4090;
+ uint8_t HVK_Gesamtst_Spgfreiheit;
+ uint8_t BMS_Balancing_Active=2;
+ uint8_t BMS_Freig_max_Perf =1;
+ uint8_t BMS_Battdiag =1; // Battery Display Diagnostics: 1 = Display Battery, 4 = Display Battery OK, 5 = Charging, 6 = Check Battery
+ uint8_t DC_IstModus_02 = 2;
+ uint8_t BMS_HV_Auszeit_Status = 1; // Status HV timeout.
+ uint16_t BMS_HV_Auszeit = 25; // Time since last HV Activity
+ uint16_t BMS_Kapazitaet = 1000; // Total Energy Capacity (aged)
+ uint16_t BMS_SOC_Kaltstart = 0; // SOC Cold
+ uint8_t BMS_max_Grenz_SOC = 30; // Upper limit of SOC operating strategy (70 offset, so 30 = 100)
+ uint8_t BMS_min_Grenz_SOC = 15; // Lower limit of SOC Operating strategy
+ uint8_t EM1_Istmodus2; // EM1 Status, 0=standby
+ uint8_t EM1_Status_Spgfreiheit; // Voltage Status: 0=Init, 1=NoVoltage, 2=Voltage, 3=Fault & Voltage
+ bool ZAS_Kl_S; // KeySwitch Inserted
+ bool ZAS_Kl_15; // Acc position
+ bool ZAS_Kl_X; // Run position
+ bool ZAS_Kl_50_Startanforderung; // Start
+ uint8_t HVActiveDelayOff;
+ uint8_t HVEM_NVNachladen_Energie = 200;
+ uint8_t LockState;
+
+void VWMLBClass::SetCanInterface(CanHardware* c)
+{
+ can = c;
+ can->RegisterUserMessage(0x488); // HVLM_06
+ can->RegisterUserMessage(0x53C); // HVLM_04
+ can->RegisterUserMessage(0x564); // LAD_01
+ can->RegisterUserMessage(0x565); // HVLM_03
+ can->RegisterUserMessage(0x67E); // LAD_02
+}
+
+bool VWMLBClass::ControlCharge(bool RunCh, bool ACReq)
+{
+ if (charger_status.HVLM_Plug_Status > 1 && RunCh)
+ {
+ charger_params.activate = 1;
+ return true;
+ }
+ else
+ {
+ charger_params.activate = 0;
+ return false;
+ }
+}
+
+void VWMLBClass::Simulate()
+{
+}
+
+void VWMLBClass::Task1Ms()
+{ static uint8_t counter1ms = 0;
+ counter1ms++; // Increments every 10ms
+ if(vehicle_status.CANQuiet == 1){ counter1ms = 0; } // Quick way of silencing the canbus -- NOT IMPLEMENTED
+// - Do 10ms Tasks:
+ if (counter1ms % 10 == 0) { // Every 100ms (10ms * 1)
+ msg191(); // BMS_01 0x191 CRC
+ }
+// - Do 20ms, 40ms, 50ms tasks:
+ if (counter1ms % 20 == 0) { // Every 20ms (10ms * 2)
+ }
+ if (counter1ms % 40 == 0) { // Every 40ms (10ms * 4)
+ //msg040(); // Airbag_01 - 0x40 CRC
+ can->Send(0x2B1, MSG_TME_02, 8); // MSG_TME_02 0x2B1
+ }
+ if (counter1ms % 50 == 0) { // Every 50ms (10ms * 5)
+ msg2AE(); // DCDC_01 0x2AE CRC
+ counter1ms = 1;
+ }
+}
+
+void VWMLBClass::Task10Ms()
+{
+
+}
+
+void VWMLBClass::Task100Ms()
+{
+//Simulate();
+static uint8_t counter100ms = 0;
+TagParams();
+CalcValues100ms();
+counter100ms++; // Increments every 100ms
+if(vehicle_status.CANQuiet == 1){ counter100ms = 0; } // Quick way of silencing the canbus -- NOT IMPLEMENTED
+// - Do 100ms Tasks:
+if (counter100ms % 1 == 0) { // Every 100ms (100ms * 2)
+ msg3C0(); // Klemmen_Status_01 CRC
+ msg503(); // HVK_01 0x503 CRC
+ msg184(); // ZV_01 0x184 CRC
+ msg578(); // BMS_DC_01 0x578 CRC
+ can->Send(0x1A1, BMS_02, 8); // BMS_02 0x1A1
+ can->Send(0x39D, BMS_03, 8); // BMS_03 0x39D
+ can->Send(0x509, BMS_10, 8); // BMS_10 0x509
+ can->Send(0x552, HVEM_05, 8); // HVEM_05 0x552 Fun items relating to Max Voltage and Plug Release
+ can->Send(0x5AC, HVEM_02, 8); // HVEM_02 0x5AC
+}
+// - Do 200ms, 500ms, 1000ms and 2000ms tasks:
+if (counter100ms % 2 == 0) { // Every 200ms (100ms * 2)
+ msg1A2(); // ESP_15 0x1A2 CRC
+ can->Send(0x583, ZV_02, 8); // ZV_02 - 0x583
+}
+if (counter100ms % 5 == 0) { // Every 500ms (100ms * 5)
+ msg5A2(); // BMS_04 0x5A2 CRC
+ msg5CA(); // BMS_07 0x5CA CRC
+ msg5CD(); // DCDC_03 0x5CD CRC
+ can->Send(0x59E, BMS_06, 8); // BMS_06 0x59E
+}
+if (counter100ms % 10 == 0) { // Every 1000ms (100ms * 10)
+ can->Send(0x485, Authentic_Time_01, 8); // NavData_02 - 0x485
+ can->Send(0x1A555548, ORU_01, 8); // ORU_01 0x1A555548
+ can->Send(0x1A5555AD, Authentic_Time_01, 8); // Authentic_Time_01 0x1A5555AD
+ can->Send(0x96A955EB, BMS_09, 8); // BMS_09 0x96A955EB
+ can->Send(0x9A555539, BMS_16, 8); // BMS_16 0x9A555539 Just contains IDs for cells with low/high charge or temps
+ can->Send(0x9A555552, BMS_27, 8); // BMS_27 0x9A555552
+}
+if (counter100ms % 20 == 0) { // Every 2000ms (100ms * 20)
+ can->Send(0x96A954A6, BMS_11, 8); // BMS_11 0x96A954A6
+ counter100ms = 1;
+}
+}
+
+void VWMLBClass::Task200Ms()
+{
+}
+
+// Msgs with CRC & Counters:
+
+void VWMLBClass::msg040() // Airbag_01 - 0x40
+{
+ // CanMsgBuf[0] = 0x00 ;
+ // CanMsgBuf[1] = (0x00 | vag_cnt040) ;
+ // CanMsgBuf[2] = 0x00 ;
+ // CanMsgBuf[3] = 0x00 ;
+ // CanMsgBuf[4] = 0x00 ;
+ // CanMsgBuf[5] = 0x00 ;
+ // CanMsgBuf[6] = 0x00 ;
+ // CanMsgBuf[7] = 0x00 ;
+ // CanMsgBuf[0] = vag_utils::vw_crc_calc(CanMsgBuf, 8, 0x40);
+ // can->Send(0x040, CanMsgBuf, 8);
+ // vag_cnt040++;
+ // if(vag_cnt040>0x0f) vag_cnt040=0x00;
+}
+
+void VWMLBClass::msg184() // ZV_01 0x184
+{
+ CanMsgBuf[0] = 0x00 ;
+ CanMsgBuf[1] = (ZV_01[1]|vag_cnt184) ;
+ CanMsgBuf[2] = ZV_01[2] ;
+ CanMsgBuf[3] = ZV_01[3] ;
+ CanMsgBuf[4] = ZV_01[4] ;
+ CanMsgBuf[5] = ZV_01[5] ;
+ CanMsgBuf[6] = ZV_01[6] ;
+ CanMsgBuf[7] = ZV_01[7] ;
+ CanMsgBuf[0] = vag_utils::vw_crc_calc(CanMsgBuf, 8, 0x184);
+ can->Send(0x184, CanMsgBuf, 8);
+ vag_cnt184++;
+ if(vag_cnt184>0x0f) vag_cnt184=0x00;
+}
+
+void VWMLBClass::msg191() // BMS_01 0x191
+{
+ CanMsgBuf[0] = 0x00 ;
+ CanMsgBuf[1] = (BMS_01[1]|vag_cnt191) ;
+ CanMsgBuf[2] = BMS_01[2] ;
+ CanMsgBuf[3] = BMS_01[3] ;
+ CanMsgBuf[4] = BMS_01[4] ;
+ CanMsgBuf[5] = BMS_01[5] ;
+ CanMsgBuf[6] = BMS_01[6] ;
+ CanMsgBuf[7] = BMS_01[7] ;
+ CanMsgBuf[0] = vag_utils::vw_crc_calc(CanMsgBuf, 8, 0x191);
+ can->Send(0x191, CanMsgBuf, 8);
+ vag_cnt191++;
+ if(vag_cnt191>0x0f) vag_cnt191=0x00;
+}
+
+void VWMLBClass::msg1A2() // ESP_15 0x1A2
+{
+ CanMsgBuf[0] = 0x00 ;
+ CanMsgBuf[1] = (ESP_15[1]|vag_cnt1A2) ;
+ CanMsgBuf[2] = ESP_15[2] ;
+ CanMsgBuf[3] = ESP_15[3] ;
+ CanMsgBuf[4] = ESP_15[4] ;
+ CanMsgBuf[5] = ESP_15[5] ;
+ CanMsgBuf[6] = ESP_15[6] ;
+ CanMsgBuf[7] = ESP_15[7] ;
+ CanMsgBuf[0] = vag_utils::vw_crc_calc(CanMsgBuf, 8, 0x1A2);
+ can->Send(0x1A2, CanMsgBuf, 8);
+ vag_cnt1A2++;
+ if(vag_cnt1A2>0x0f) vag_cnt1A2=0x00;
+}
+
+void VWMLBClass::msg2AE() // DCDC_01 0x2AE
+{
+ CanMsgBuf[0] = 0x00 ;
+ CanMsgBuf[1] = (DCDC_01[1]|vag_cnt2AE) ;
+ CanMsgBuf[2] = DCDC_01[2] ;
+ CanMsgBuf[3] = DCDC_01[3] ;
+ CanMsgBuf[4] = DCDC_01[4] ;
+ CanMsgBuf[5] = DCDC_01[5] ;
+ CanMsgBuf[6] = DCDC_01[6] ;
+ CanMsgBuf[7] = 0xA8 ; // Sets static 13.8V as DC output voltage
+ CanMsgBuf[0] = vag_utils::vw_crc_calc(CanMsgBuf, 8, 0x2AE);
+ can->Send(0x2AE, CanMsgBuf, 8);
+ vag_cnt2AE++;
+ if(vag_cnt2AE>0x0f) vag_cnt2AE=0x00;
+}
+
+void VWMLBClass::msg503() // HVK_01 0x503
+{
+ CanMsgBuf[0] = 0x00 ;
+ CanMsgBuf[1] = (HVK_01[1]|vag_cnt503) ;
+ CanMsgBuf[2] = HVK_01[2] ;
+ CanMsgBuf[3] = HVK_01[3] ;
+ CanMsgBuf[4] = HVK_01[4] ;
+ CanMsgBuf[5] = HVK_01[5] ;
+ CanMsgBuf[6] = HVK_01[6] ;
+ CanMsgBuf[7] = HVK_01[7] ;
+ CanMsgBuf[0] = vag_utils::vw_crc_calc(CanMsgBuf, 8, 0x503);
+ can->Send(0x503, CanMsgBuf, 8);
+ vag_cnt503++;
+ if(vag_cnt503>0x0f) vag_cnt503=0x00;
+}
+
+void VWMLBClass::msg578() // BMS_DC_01 0x578
+{
+ CanMsgBuf[0] = 0x00 ;
+ CanMsgBuf[1] = (BMS_DC_01[1]|vag_cnt578) ;
+ CanMsgBuf[2] = BMS_DC_01[2] ;
+ CanMsgBuf[3] = BMS_DC_01[3] ;
+ CanMsgBuf[4] = BMS_DC_01[4] ;
+ CanMsgBuf[5] = BMS_DC_01[5] ;
+ CanMsgBuf[6] = BMS_DC_01[6] ;
+ CanMsgBuf[7] = BMS_DC_01[7] ;
+ CanMsgBuf[0] = vag_utils::vw_crc_calc(CanMsgBuf, 8, 0x578);
+ can->Send(0x578, CanMsgBuf, 8);
+ vag_cnt578++;
+ if(vag_cnt578>0x0f) vag_cnt578=0x00;
+}
+void VWMLBClass::msg5A2() // BMS_04 0x5A2
+{
+ CanMsgBuf[0] = 0x00 ;
+ CanMsgBuf[1] = (BMS_04[1]|vag_cnt5A2) ;
+ CanMsgBuf[2] = BMS_04[2] ;
+ CanMsgBuf[3] = BMS_04[3] ;
+ CanMsgBuf[4] = BMS_04[4] ;
+ CanMsgBuf[5] = BMS_04[5] ;
+ CanMsgBuf[6] = BMS_04[6] ;
+ CanMsgBuf[7] = BMS_04[7] ;
+ CanMsgBuf[0] = vag_utils::vw_crc_calc(CanMsgBuf, 8, 0x5A2);
+ can->Send(0x5A2, CanMsgBuf, 8);
+ vag_cnt5A2++;
+ if(vag_cnt5A2>0x0f) vag_cnt5A2=0x00;
+}
+void VWMLBClass::msg5CA() // BMS_07 0x5CA
+{
+ CanMsgBuf[0] = 0x00 ;
+ CanMsgBuf[1] = (BMS_07[1]|vag_cnt5CA) ;
+ CanMsgBuf[2] = BMS_07[2] ;
+ CanMsgBuf[3] = BMS_07[3] ;
+ CanMsgBuf[4] = BMS_07[4] ;
+ CanMsgBuf[5] = BMS_07[5] ;
+ CanMsgBuf[6] = BMS_07[6] ;
+ CanMsgBuf[7] = BMS_07[7] ;
+ CanMsgBuf[0] = vag_utils::vw_crc_calc(CanMsgBuf, 8, 0x5CA);
+ can->Send(0x5CA, CanMsgBuf, 8);
+ vag_cnt5CA++;
+ if(vag_cnt5CA>0x0f) vag_cnt5CA=0x00;
+}
+void VWMLBClass::msg5CD() // DCDC_03 0x5CD
+{
+ CanMsgBuf[0] = 0x00 ;
+ CanMsgBuf[1] = (DCDC_03[1]|vag_cnt5CD) ;
+ CanMsgBuf[2] = DCDC_03[2] ;
+ CanMsgBuf[3] = DCDC_03[3] ;
+ CanMsgBuf[4] = DCDC_03[4] ;
+ CanMsgBuf[5] = DCDC_03[5] ;
+ CanMsgBuf[6] = DCDC_03[6] ;
+ CanMsgBuf[7] = DCDC_03[7] ;
+ CanMsgBuf[0] = vag_utils::vw_crc_calc(CanMsgBuf, 8, 0x5CD);
+ can->Send(0x5CD, CanMsgBuf, 8);
+ vag_cnt5CD++;
+ if(vag_cnt5CD>0x0f) vag_cnt5CD=0x00;
+}
+
+void VWMLBClass::msg3C0() // Klemmen_Status_01
+{
+ CanMsgBuf[0] = 0x00 ;
+ CanMsgBuf[1] = (Klemmen_Status_01[1] |vag_cnt3C0) ;
+ CanMsgBuf[2] = Klemmen_Status_01[2] ;
+ CanMsgBuf[3] = Klemmen_Status_01[3] ;
+ CanMsgBuf[4] = Klemmen_Status_01[4] ;
+ CanMsgBuf[5] = Klemmen_Status_01[5] ;
+ CanMsgBuf[6] = Klemmen_Status_01[6] ;
+ CanMsgBuf[7] = Klemmen_Status_01[7] ;
+ CanMsgBuf[0] = vag_utils::vw_crc_calc(CanMsgBuf, 8, 0x3C0);
+ can->Send(0x3C0, CanMsgBuf, 8);
+ vag_cnt3C0++;
+ if(vag_cnt3C0>0x0f) vag_cnt3C0=0x00;
+}
+
+void VWMLBClass::DecodeCAN(int id, uint32_t data[2])
+{
+uint8_t* bytes = (uint8_t*)data;// arrgghhh this converts the two 32bit array into bytes. See comments are useful:) ... Stolen from Zombie, Left comments as they're now famous.
+switch (id)
+{
+ case 0x488: // HVLM_06
+ charger_status.HVLM_MaxDC_ChargePower = (((bytes[2] & (0x3FU)) << 4) | ((bytes[1] >> 4) & (0x0FU)))*250;
+ charger_status.HVLM_Max_DC_Voltage_DCLS = ((bytes[3] & (0xFFU)) << 2) | ((bytes[2] >> 6) & (0x03U));
+ charger_status.HVLM_Actual_DC_Current_DCLS = ((bytes[5] & (0x01U)) << 8) | (bytes[4] & (0xFFU));
+ charger_status.HVLM_Max_DC_Current_DCLS = ((bytes[6] & (0x03U)) << 7) | ((bytes[5] >> 1) & (0x7FU));
+ charger_status.HVLM_Min_DC_Voltage_DCLS = ((bytes[7] & (0x07U)) << 6) | ((bytes[6] >> 2) & (0x3FU));
+ charger_status.HVLM_Min_DC_Current_DCLS = ((bytes[7] >> 3) & (0x1FU));
+ break;
+
+
+ case 0x53C: // HVLM_04
+ // HVLM_ParkingHeater_Mode = ((HVLM_04[1] >> 4) & (0x07U));
+ // HVLM_StationaryClimat_Timer_Stat = ((HVLM_04[1] >> 7) & (0x01U));
+ // HVLM_HVEM_MaxPower = ((HVLM_04[3] & (0x01U)) << 8) | (HVLM_04[2] & (0xFFU));
+ charger_status.HVLM_Status_Grid = ((bytes[3] >> 1) & (0x01U));
+ // HVLM_BEV_LoadingScreen = ((HVLM_04[3] >> 2) & (0x01U));
+ charger_status.HVLM_EnergyFlowType = ((bytes[3] >> 3) & (0x03U));
+ // HVLM_VK_ParkingHeaterStatus = ((HVLM_04[3] >> 5) & (0x07U));
+ // HVLM_VK_ClimateConditioningStat = (HVLM_04[4] & (0x03U));
+ charger_status.HVLM_OperationalMode = ((bytes[4] >> 2) & (0x03U));
+ charger_status.HVLM_HV_ActivationRequest = ((bytes[4] >> 4) & (0x03U));
+ charger_status.HVLM_ChargerErrorStatus = ((bytes[5] & (0x01U)) << 2) | ((bytes[4] >> 6) & (0x03U));
+ charger_status.HVLM_Park_Request = ((bytes[5] >> 1) & (0x07U));
+ charger_status.HVLM_Park_Request_Maintain = ((bytes[5] >> 4) & (0x03U));
+ // HVLM_AWC_Mode = (HVLM_04[6] & (0x07U));
+ charger_status.HVLM_Plug_Status = ((bytes[6] >> 3) & (0x03U));
+ charger_status.HVLM_LoadRequest = ((bytes[6] >> 5) & (0x07U));
+ charger_status.HVLM_MaxBattChargeCurrent = (bytes[7] & (0xFFU));
+ break;
+
+ case 0X564: // LAD_01
+ charger_status.mode = ((bytes[1] >> 4) & (0x07U));
+ charger_status.ACvoltage = ((bytes[2] & (0xFFU)) << 1) | ((bytes[1] >> 7) & (0x01U));
+ charger_status.HVVoltage = (((bytes[4] & (0x03U)) << 8) | (bytes[3] & (0xFFU)));
+ charger_status.current = ((((bytes[5] & (0x0FU)) << 6) | ((bytes[4] >> 2) & (0x3FU))) * 0.2) - 102;
+ charger_status.LAD_Status_Voltage = ((bytes[5] >> 4) & (0x03U));
+ charger_status.temperature = bytes[6] - 40;
+ charger_status.LAD_PowerLossVal = ((bytes[7] & (0xFFU)))*20;
+ break;
+
+ case 0x565: // HVLM_03
+ charger_status.HVLM_HV_StaleTime = ((bytes[0] & (0xFFU)))*4;
+ charger_status.HVLM_ChargeSystemState = (bytes[1] & (0x03U));
+ // HVLM_KESSY_KeySearch = ((HVLM_03[1] >> 2) & (0x03U));
+ charger_status.HVLM_Status_LED = ((bytes[1] >> 4) & (0x0FU));
+ charger_status.MaxACAmps = ((bytes[3] & (0x7FU)))/2;
+ charger_status.HVLM_LG_ChargerTargetMode = ((bytes[3] >> 7) & (0x01U));
+ charger_status.HVLM_TankCapReleaseRequest = (bytes[4] & (0x03U));
+ charger_status.HVLM_RequestConnectorLock = ((bytes[4] >> 2) & (0x03U));
+ charger_status.HVLM_Start_VoltageMeasure_DCLS = ((bytes[4] >> 4) & (0x03U));
+ // PnC_Trigger_OBC_cGW = ((HVLM_03[5] & (0x03U)) << 2) | ((HVLM_03[4] >> 6) & (0x03U));
+ // HVLM_ReleaseAirConditioning = ((HVLM_03[5] >> 2) & (0x03U));
+ charger_status.HVLM_ChargeReadyStatus = ((bytes[6] >> 1) & (0x07U));
+ // HVLM_IsolationRequest = ((HVLM_03[6] >> 5) & (0x01U));
+ charger_status.HVLM_Output_Voltage_HV = ((bytes[7] & (0xFFU)) << 2) | ((bytes[6] >> 6) & (0x03U));
+ break;
+
+ case 0x67E: // LAD_02
+ charger_status.LAD_Reduction_ChargerTemp = ((bytes[1] >> 4) & (0x01U));
+ charger_status.LAD_Reduction_Current = ((bytes[1] >> 5) & (0x01U));
+ charger_status.LAD_Reduction_SocketTemp = ((bytes[1] >> 6) & (0x01U));
+ charger_status.LAD_MaxChargerPower_HV = (((bytes[3] & (0x01U)) << 8) | (bytes[2] & (0xFFU)))*100;
+ charger_status.PPLim = (bytes[4] & (0x07U));
+ charger_status.LAD_ControlPilotStatus = ((bytes[4] >> 3) & (0x01U));
+ charger_status.LAD_LockFeedback = ((bytes[4] >> 4) & (0x01U));
+ charger_status.LAD_ChargerCoolingDemand = ((bytes[4] >> 6) & (0x03U));
+ // LAD_MaxLadLeistung_HV_Offset = ((LAD_02[7] >> 1) & (0x03U));
+ charger_status.LAD_ChargerWarning = ((bytes[7] >> 6) & (0x01U));
+ charger_status.LAD_ChargerFault = ((bytes[7] >> 7) & (0x01U));
+ break;
+}
+}
+
+
+void VWMLBClass::TagParams() // To make code portable between standalone (more params) vs Zombie (basic params) - This code executed 100ms, uncomment or delete un-needed params
+{
+ //Common Params (Shared same param names as zombie vs standalone)
+
+ battery_status.SOCx10 = int(Param::GetFloat(Param::SOC)*10);
+ battery_status.SOC_Targetx10 = 1000; //Param::GetInt(Param::VCU_SOC_Limit);
+ battery_status.CapkWhx10 = int(Param::GetFloat(Param::BattCap)*10);
+ battery_status.BMSMinVolt = Param::GetInt(Param::udcmin);
+ charger_params.HVpwr=Param::GetInt(Param::Pwrspnt);
+ charger_params.HVcur = Param::GetInt(Param::BMS_ChargeLim);
+ charger_params.HVDCSetpnt = Param::GetInt(Param::Voltspnt);
+ battery_status.BMSVoltx10 = Param::GetInt(Param::udc);
+ battery_status.BMSBattCellSumx10 = Param::GetInt(Param::udc2);
+ battery_status.BMSMaxVolt = Param::GetInt(Param::udclim);
+ battery_status.BMS_Cell_H_Tempx10 = int(Param::GetFloat(Param::BMS_Tmax)*10);
+ battery_status.BMS_Cell_L_Tempx10 = int(Param::GetFloat(Param::BMS_Tmin)*10);
+ battery_status.BMS_Cell_H_mV = int(Param::GetFloat(Param::BMS_Vmax)*100);
+ battery_status.BMS_Cell_L_mV = int(Param::GetFloat(Param::BMS_Vmin)*100);
+ vehicle_status.locked = Param::GetInt(Param::VehLockSt);
+
+ Param::SetInt(Param::CableLim,charger_status.MaxACAmps);
+ Param::SetInt(Param::AC_Volts,charger_status.ACvoltage);
+ Param::SetInt(Param::ChgTemp,charger_status.temperature);
+ switch (charger_status.HVLM_Plug_Status)
+ {
+ case 0:
+ Param::SetInt(Param::PlugDet,0);
+ break;
+ case 1:
+ Param::SetInt(Param::PlugDet,0);
+ break;
+ case 2:
+ Param::SetInt(Param::PlugDet,1);
+ break;
+ case 3:
+ Param::SetInt(Param::PlugDet,1);
+ break;
+ }
+
+ switch (charger_status.PPLim)
+ {
+ case 0:
+ Param::SetInt(Param::PilotLim,13);
+ break;
+ case 1:
+ Param::SetInt(Param::PilotLim,20);
+ break;
+ case 2:
+ Param::SetInt(Param::PilotLim,32);
+ break;
+ case 3:
+ Param::SetInt(Param::PilotLim,63);
+ break;
+ }
+ // Standalone additional params:
+
+ // Param::SetInt(Param::DC_Max_ChargePower,charger_status.HVLM_MaxDC_ChargePower);
+ // Param::SetInt(Param::DC_Max_ChargeVoltage,charger_status.HVLM_Max_DC_Voltage_DCLS);
+ // Param::SetInt(Param::DC_Actual_Current,charger_status.HVLM_Actual_DC_Current_DCLS);
+ // Param::SetInt(Param::DC_Max_ChargeCurrent,charger_status.HVLM_Max_DC_Current_DCLS);
+ // Param::SetInt(Param::DC_Min_ChargeVoltage,charger_status.HVLM_Min_DC_Voltage_DCLS);
+ // Param::SetInt(Param::DC_Min_ChargeCurrent,charger_status.HVLM_Min_DC_Current_DCLS);
+ // Param::SetInt(Param::Status_Grid,charger_status.HVLM_EnergyFlowType);
+ // Param::SetInt(Param::ChargeManagerMode,charger_status.HVLM_OperationalMode);
+ // Param::SetInt(Param::ChargerRequestingHV,charger_status.HVLM_HV_ActivationRequest);
+ // Param::SetInt(Param::ChargerErrorStatus,charger_status.HVLM_ChargerErrorStatus);
+ // Param::SetInt(Param::PlugStatus,charger_status.HVLM_Plug_Status);
+ // Param::SetInt(Param::LoadRequest,charger_status.HVLM_LoadRequest);
+ // Param::SetInt(Param::ChargerState,charger_status.mode);
+ // Param::SetInt(Param::Charger_AC_Volt_RMS,charger_status.ACvoltage);
+ // Param::SetInt(Param::Charger_VoltageOut_HV,charger_status.HVVoltage);
+ // Param::SetInt(Param::Charger_CurrentOut_HV,charger_status.current);
+ // Param::SetInt(Param::Charger_Temperature,charger_status.temperature);
+ // Param::SetInt(Param::ChargerSystemState,charger_status.HVLM_ChargeSystemState);
+ // Param::SetInt(Param::Status_LED,charger_status.HVLM_Status_LED);
+ // Param::SetInt(Param::MaxCurrent_AC,charger_status.MaxACAmps);
+ // Param::SetInt(Param::LockRequest,charger_status.HVLM_RequestConnectorLock);
+ // Param::SetInt(Param::Charger_Ready,charger_status.HVLM_ChargeReadyStatus);
+ // Param::SetInt(Param::ChargerTemp_Reduction,charger_status.LAD_Reduction_ChargerTemp);
+ // Param::SetInt(Param::ChargerCurrent_Reduction,charger_status.LAD_Reduction_Current);
+ // Param::SetInt(Param::SocketTemp_Reduction,charger_status.LAD_Reduction_SocketTemp);
+ // Param::SetInt(Param::MaxChargerOutput,charger_status.LAD_MaxChargerPower_HV);
+ // Param::SetInt(Param::CableCurrentLimit,charger_status.PPLim);
+ // Param::SetInt(Param::ControlPilotStatus,charger_status.LAD_ControlPilotStatus);
+ // Param::SetInt(Param::LockState,charger_status.LAD_LockFeedback);
+ // Param::SetInt(Param::ChargerWarning,charger_status.LAD_ChargerWarning);
+ // Param::SetInt(Param::ChargerFault,charger_status.LAD_ChargerFault);
+ // Param::SetInt(Param::OutputVolts,charger_status.HVLM_Output_Voltage_HV);
+
+ // Param::SetFloat(Param::VCU_SOC, (Param::GetInt(Param::SOCx10)));
+ // Param::SetFloat(Param::VCU_SOC_Limit, Param::GetInt(Param::SOC_Targetx10));
+ // Param::SetInt(Param::VCU_UDCmin, Param::GetInt(Param::BMSMinVolt));
+ // Param::SetInt(Param::VCU_Current_SP, Param::GetInt(Param::IDCSetpnt));
+ // Param::SetInt(Param::VCU_Volt_SP, Param::GetInt(Param::HVDCSetpnt));
+ // Param::SetFloat(Param::BMS_Pack_Voltage, (Param::GetInt(Param::BMSBattCellSumx10)/10));
+ // Param::SetInt(Param::VCU_UDCmax, Param::GetInt(Param::BMSMaxVolt));
+ // Param::SetFloat(Param::BMS_Highest_Cell_Temp, (Param::GetInt(Param::BMS_Cell_H_Tempx10))/10);
+ // Param::SetFloat(Param::BMS_Lowest_Cell_Temp, (Param::GetInt(Param::BMS_Cell_L_Tempx10))/10);
+ // Param::SetInt(Param::BMS_Highest_Cell_Volt, Param::GetInt(Param::BMS_Cell_H_mV));
+ // Param::SetInt(Param::BMS_Lowest_Cell_Volt, Param::GetInt(Param::BMS_Cell_L_mV));
+ // Param::SetInt(Param::VCUChargeRequest, Param::Ge|tInt(Param::Activation_Crg));
+ // Param::SetInt(Param::VehicleLockState, Param::GetInt(Param::LockSim));
+
+ // battery_status.SOCx10 = (Param::GetInt(Param::VCU_SOC));
+ // battery_status.SOC_Targetx10 = Param::GetInt(Param::VCU_SOC_Limit);
+ // battery_status.BMSMinVolt = Param::GetInt(Param::VCU_UDCmin);
+ // charger_params.IDCSetpnt = Param::GetInt(Param::VCU_Current_SP);
+ // charger_params.HVDCSetpnt = Param::GetInt(Param::VCU_Volt_SP);
+ // battery_status.BMSBattCellSumx10 = Param::GetInt(Param::BMS_Pack_Voltage);
+ // battery_status.BMSMaxVolt = Param::GetInt(Param::VCU_UDCmax);
+ // battery_status.BMS_Cell_H_Tempx10 = Param::GetInt(Param::BMS_Highest_Cell_Temp)*10;
+ // battery_status.BMS_Cell_L_Tempx10 = Param::GetInt(Param::BMS_Lowest_Cell_Temp)*10;
+ // battery_status.BMS_Cell_H_mV = Param::GetInt(Param::BMS_Highest_Cell_Volt);
+ // battery_status.BMS_Cell_L_mV = Param::GetInt(Param::BMS_Lowest_Cell_Volt);
+ // ZV_verriegelt_extern_ist = Param::GetInt(Param::VehicleLockState);
+
+}
+
+void VWMLBClass::CalcValues100ms() // Run to calculate values every 100 ms
+{
+// Static Set Values - TODO: Roll these up into the CAN msg and eliminate useless variables
+ BMS_MaxDischarge_Curr = 1500;
+ BMS_MaxCharge_Curr_Offset = 0;
+ BMS_Status_ServiceDisconnect = 0;
+ BMS_Battdiag = 0;
+ BMS_BattEnergy_Wh_HiRes = 0;
+ BMS_MaxBattEnergy_Wh_HiRes = 0;
+ BMS_ResidualEnergy_Wh = 0;
+ BMS_ChargePowerMax = 625;
+ BMS_ChargeEnergyCount = 0;
+ BMS_EnergyCount = 0;
+
+//BMS charge current limit but needs to be power for most AC charger types.
+ if(charger_params.HVcur > 1000)
+ {
+ charger_params.calcpwr = 12000;
+ }
+ else
+ {
+ charger_params.calcpwr = charger_params.HVcur*(battery_status.BMSVoltx10/10);
+ }
+
+ charger_params.HVpwr=MIN(charger_params.HVpwr,charger_params.calcpwr);
+
+ charger_params.IDCSetpnt = charger_params.HVpwr / (battery_status.BMSVoltx10/10);
+
+// BMS SOC:
+ BMS_Batt_Curr = charger_status.current + 2047;
+ BMS_SOC = battery_status.SOCx10 * .05;
+ BMS_SOC_HiRes = battery_status.SOCx10 * 2;
+ BMS_SOC_Kaltstart = battery_status.SOCx10 * 2;
+ BMS_Batt_Energy = battery_status.CapkWhx10 * 2;
+
+
+// BMS Current:
+
+// BMS Voltages:
+ BMS_Batt_Volt = battery_status.BMSVoltx10 * 4;
+ BMS_Batt_Volt_HVterm = battery_status.BMSVoltx10 * 2;
+ BMS_BattCell_MV_Max = battery_status.BMS_Cell_H_mV - 1000;
+ BMS_BattCell_MV_Min = battery_status.BMS_Cell_L_mV - 1000;
+
+// BMS Temps:
+ BMS_Batt_Temp = (battery_status.BMS_Battery_Tempx10 + 400) / 5;
+ BMS_CurrBatt_Temp = (battery_status.BMS_Battery_Tempx10 + 400) / 5;
+ BMS_CoolantTemp_Act = (battery_status.BMS_Coolant_Tempx10 + 400) / 5;
+ BMS_BattCell_Temp_Max = (battery_status.BMS_Cell_H_Tempx10 + 400) / 5;
+ BMS_BattCell_Temp_Min = (battery_status.BMS_Cell_L_Tempx10 + 400) / 5;
+
+// BMS SOC Limits:
+ BMS_Max_Wh = battery_status.CapkWhx10*2;
+ BMS_SOC_ChargeLim = battery_status.SOC_Targetx10/10;
+ BMS_max_Grenz_SOC = (battery_status.SOC_Targetx10 - 700)/10;
+ BMS_EnergyReq_Full =((battery_status.SOC_Targetx10 - battery_status.SOCx10)*battery_status.CapkWhx10)/2500;
+
+// BMS Limits Discharge:
+ BMS_Min_Batt_Volt = battery_status.BMSMinVolt;
+ BMS_Min_Batt_Volt_Discharge = battery_status.BMSMinVolt;
+
+// BMS Limits Charge:
+ BMS_MaxCharge_Curr = 1500;
+ HVEM_SollStrom_HV = (charger_params.IDCSetpnt+205)*5;
+ BMS_Batt_Max_Volt = charger_params.HVDCSetpnt;
+ BMS_Min_Batt_Volt_Charge = battery_status.BMSMinVolt;;
+ BMS_OpenCircuit_Volts = battery_status.BMSBattCellSumx10;
+ HVEM_MaxSpannung_HV = battery_status.BMSMaxVolt;
+ BMS_Faultstatus = battery_status.BMS_Status;
+ BMS_Batt_Ah = (battery_status.CapkWhx10*100)/350;
+ BMS_Target_SOC_HiRes = battery_status.SOC_Targetx10*2;
+
+ // ESP15
+ HMS_Systemstatus = 3 ; //0 "No_function_active" 1 "Hold_active" 2 "Parking_requested" 3 "Parking_active" 4 "Keep parking_active" 5 "Start_active" 6 "Release_request_active" 7 "Release_request_by_driver" 8 "Slipping_detected" 9 "Hold_standby_active" 10 "Start_standby_active" 14 "Init" 15 "Error " ;
+ HMS_aktives_System = 6; //0 "No_System__Init_Error" 1 "Driver request_active" 2 "HMS_internal_active" 3 "ACC_active" 4 "Autohold_active" 5 "HHC_active" 6 "HVLM_active" 7 "Getriebe_aktiv" 8 "EBKV_aktiv" 9 "ParkAssist_aktiv" 10 "ARA_aktiv" 12 "Autonomous_Hold_aktiv" 13 "STA_aktiv " 14 "Motor_aktiv" 15 "EA_aktiv" 16 "VLK_aktiv" ;
+
+ // Lock Status:
+ if (vehicle_status.locked == 0)
+ {
+ ZV_verriegelt_soll = 1;
+ }
+ if (vehicle_status.locked == 1)
+ {
+ ZV_verriegelt_soll = 2;
+ }
+
+
+ // Charger Activation State Logic:
+ if( charger_status.HVLM_HV_ActivationRequest == 1)
+ {
+ HV_Bordnetz_aktiv = true; // Indicates an active high-voltage vehicle electrical system: 0 = Not Active, 1 = Active
+ //HVK_BMS_Sollmodus = 4;
+ BMS_IstModus = 4; // 0=Standby, 1=HV Active (Driving) 2=Balancing 4=AC charge, 6=DC charge, 7=init
+ BMS_HV_Status = 2; // HV System Voltage Detected // Voltage Status: 0=Init, 1=NoVoltage, 2=Voltage, 3=Fault & Voltage
+ HVK_MO_EmSollzustand = 50;
+ BMS_Charger_Active = 1;
+ HVActiveDelayOff = 20;
+ }
+
+ if( charger_status.HVLM_HV_ActivationRequest == 0)
+ {
+ BMS_Charger_Active = 0;
+ if (HVActiveDelayOff >= 1)
+ {
+ BMS_HV_Status = 2; // HV No Voltage // Voltage Status: 0=Init, 1=NoVoltage, 2=Voltage, 3=Fault & Voltage
+ BMS_IstModus = 1; // 0=Standby, 1=HV Active (Driving) 2=Balancing 4=AC charge, 6=DC charge, 7=init
+ HVK_BMS_Sollmodus = 1;
+ HVK_MO_EmSollzustand = 67;
+ HVActiveDelayOff = HVActiveDelayOff - 1;
+ }
+
+ if (HVActiveDelayOff == 0)
+ {
+ // HV_Bordnetz_aktiv = false; // Indicates an active high-voltage vehicle electrical system: 0 = Not Active, 1 = Active
+ // BMS_HV_Status = 1; // HV No Voltage // Voltage Status: 0=Init, 1=NoVoltage, 2=Voltage, 3=Fault & Voltage
+ // BMS_IstModus = 0; // 0=Standby, 1=HV Active (Driving) 2=Balancing 4=AC charge, 6=DC charge, 7=init
+ // HVK_BMS_Sollmodus = 0;
+ // HVK_MO_EmSollzustand = 0;
+ // BMS_Batt_Volt = charger_status.HVVoltage*4; // Modify after testing to actual values from BMS/VCU
+ // BMS_Batt_Volt_HVterm = charger_status.HVVoltage*2; // Modify after testing to actual values from BMS/VCU
+
+ BMS_HV_Status = 2; // Voltage Applied // Voltage Status: 0=Init, 1=NoVoltage, 2=Voltage, 3=Fault & Voltage
+ BMS_IstModus = 1; // 0=Standby, 1=HV Active (Driving) 2=Balancing 4=AC charge, 6=DC charge, 7=init
+ HVK_BMS_Sollmodus = 1;
+ HVK_MO_EmSollzustand = 67;
+ }
+ }
+
+ if(BMS_HV_Status == 2)
+ {
+ HVK_DCDC_Sollmodus = 2; // Voltage Status: 0=Init, 1=NoVoltage, 2=Voltage, 3=Fault & Voltage
+ EM1_Status_Spgfreiheit = 2; // Voltage Status: 0=Init, 1=NoVoltage, 2=Voltage, 3=Fault & Voltage
+ HVK_Gesamtst_Spgfreiheit = 2; // Voltage Status: 0=Init, 1=NoVoltage, 2=Voltage, 3=Fault & Voltage
+ }
+ if(BMS_HV_Status == 1)
+ {
+ HVK_DCDC_Sollmodus = 1; // Voltage Status: 0=Init, 1=NoVoltage, 2=Voltage, 3=Fault & Voltage
+ EM1_Status_Spgfreiheit = 1; // Voltage Status: 0=Init, 1=NoVoltage, 2=Voltage, 3=Fault & Voltage
+ HVK_Gesamtst_Spgfreiheit = 1; // Voltage Status: 0=Init, 1=NoVoltage, 2=Voltage, 3=Fault & Voltage
+ }
+
+ switch (charger_params.activate)
+ {
+ case 0: // Charger Standby
+ HVK_HVLM_Sollmodus = false; // Requested target mode of the charging manager: 0=Not Enabled, 1=Enabled
+ HVEM_Nachladen_Anf = false; // Request for HV charging with plugged in connector and deactivated charging request
+ BMS_Charger_Active = 0;
+ break;
+
+ case 1: // HV Active - Charger Active
+ HVEM_Nachladen_Anf = true; // Request for HV charging with plugged in connector and deactivated charging request
+ HVK_HVLM_Sollmodus = true; // Requested target mode of the charging manager: 0=Not Enabled, 1=Enabled
+ BMS_Charger_Active = 1;
+ HVK_BMS_Sollmodus = 4;
+
+ break;
+ }
+
+ // BMS_01
+ BMS_01[0] = 0x00;
+ BMS_01[1] = (0x00 & (0x0FU)) | ((BMS_Batt_Curr & (0x0FU)) << 4);
+ BMS_01[2] = ((BMS_Batt_Curr >> 4) & (0xFFU));
+ BMS_01[3] = (BMS_Batt_Volt& (0xFFU));
+ BMS_01[4] = ((BMS_Batt_Volt >> 8) & (0x0FU)) | ((BMS_Batt_Volt_HVterm & (0x0FU)) << 4);
+ BMS_01[5] = ((BMS_Batt_Volt_HVterm >> 4) & (0x7FU)) | ((BMS_SOC_HiRes & (0x01U)) << 7);
+ BMS_01[6] = ((BMS_SOC_HiRes >> 1) & (0xFFU));
+ BMS_01[7] = ((BMS_SOC_HiRes >> 9) & (0x03U)) | ((0x00 & (0x01U)) << 2) | ((0x00 & (0x0FU)) << 4);
+
+ // BMS_02
+ BMS_02[0] = 0x00;
+ BMS_02[1] = (BMS_MaxCharge_Curr_Offset & (0x0FU)) | ((BMS_MaxDischarge_Curr & (0x0FU)) << 4);
+ BMS_02[2] = ((BMS_MaxDischarge_Curr >> 4) & (0x7FU)) | ((BMS_MaxCharge_Curr & (0x01U)) << 7);
+ BMS_02[3] = ((BMS_MaxCharge_Curr >> 1) & (0xFFU));
+ BMS_02[4] = ((BMS_MaxCharge_Curr >> 9) & (0x03U)) | ((BMS_Min_Batt_Volt & (0x3FU)) << 2);
+ BMS_02[5] = ((BMS_Min_Batt_Volt >> 6) & (0x0FU)) | ((BMS_Min_Batt_Volt_Discharge & (0x0FU)) << 4);
+ BMS_02[6] = ((BMS_Min_Batt_Volt_Discharge >> 4) & (0x3FU)) | ((BMS_Min_Batt_Volt_Charge & (0x03U)) << 6);
+ BMS_02[7] = ((BMS_Min_Batt_Volt_Charge >> 2) & (0xFFU));
+
+ // BMS_03
+ BMS_03[0] = (BMS_OpenCircuit_Volts & (0xFFU));
+ BMS_03[1] = ((BMS_OpenCircuit_Volts >> 8) & (0x03U)) | ((BMS_Batt_Max_Volt & (0x0FU)) << 4);
+ BMS_03[2] = ((BMS_Batt_Max_Volt >> 4) & (0x3FU)) | ((BMS_MaxDischarge_Curr & (0x03U)) << 6);
+ BMS_03[3] = ((BMS_MaxDischarge_Curr >> 2) & (0xFFU));
+ BMS_03[4] = ((BMS_MaxDischarge_Curr >> 10) & (0x01U)) | ((BMS_MaxCharge_Curr & (0x7FU)) << 1);
+ BMS_03[5] = ((BMS_MaxCharge_Curr >> 7) & (0x0FU)) | ((BMS_Min_Batt_Volt_Discharge & (0x0FU)) << 4);
+ BMS_03[6] = ((BMS_Min_Batt_Volt_Discharge >> 4) & (0x3FU)) | ((BMS_Min_Batt_Volt_Charge & (0x03U)) << 6);
+ BMS_03[7] = ((BMS_Min_Batt_Volt_Charge >> 2) & (0xFFU));
+
+ // BMS_04
+ BMS_04[0] = 0x00;
+ BMS_04[1] = (0x00 & (0x0FU)) | ((BMS_Status_ServiceDisconnect & (0x01U)) << 5) | ((BMS_HV_Status & (0x03U)) << 6);
+ BMS_04[2] = 0x00 | ((BMS_IstModus & (0x07U)) << 1) | ((BMS_Faultstatus & (0x07U)) << 4) | ((BMS_Batt_Ah & (0x01U)) << 7);
+ BMS_04[3] = ((BMS_Batt_Ah >> 1) & (0xFFU));
+ BMS_04[4] = ((BMS_Batt_Ah >> 9) & (0x03U));
+ BMS_04[6] = ((BMS_Target_SOC_HiRes & (0x07U)) << 5);
+ BMS_04[7] = ((BMS_Target_SOC_HiRes >> 3) & (0xFFU));
+
+ // BMS_06
+ BMS_06[2] = (BMS_Batt_Temp & (0xFFU));
+ BMS_06[3] = (BMS_CurrBatt_Temp & (0xFFU));
+ BMS_06[7] = (BMS_CoolantTemp_Act & (0xFFU));
+ // BMS_07
+ BMS_07[0] = 0x00;
+ BMS_07[1] = (0x00 & (0x0FU)) | ((BMS_Batt_Energy & (0x0FU)) << 4);
+ BMS_07[2] = ((BMS_Batt_Energy >> 4) & (0x7FU)) | ((BMS_Charger_Active & (0x01U)) << 7); //BMS_07[2] = ((BMS_Batt_Energy >> 4) & (0x7FU)) | ((BMS_Charger_Active & (0x01U)) << 7);
+ BMS_07[3] = (BMS_Battdiag & (0x07U)) | ((BMS_Freig_max_Perf & (0x03U)) << 3) | ((BMS_Balancing_Active & (0x03U)) << 6);
+ BMS_07[4] = (BMS_Max_Wh & (0xFFU));
+ BMS_07[5] = ((BMS_Max_Wh >> 8) & (0x07U)) | ((0x0 & (0x01U)) << 3) | ((0x00 & (0x03U)) << 4) | ((0x00& (0x03U)) << 6); //BMS_07[5] = ((BMS_Max_Wh >> 8) & (0x07U)) | ((0x0 & (0x01U)) << 3) | ((BMS_Gesamtst_Spgfreiheit & (0x03U)) << 4) | ((BMS_RIso_Ext & (0x03U)) << 6);
+ BMS_07[6] = ((BMS_RIso_Ext >> 2) & (0xFFU));
+ BMS_07[7] = ((BMS_RIso_Ext >> 10) & (0x03U)) | ((0x00 & (0x03U)) << 2) | ((0x00 & (0x03U)) << 4);
+ // BMS_09
+ BMS_09[2] = ((BMS_HV_Auszeit_Status & (0x03U)) << 5) | ((BMS_HV_Auszeit & (0x01U)) << 7);
+ BMS_09[3] = ((BMS_HV_Auszeit >> 1) & (0xFFU));
+ BMS_09[4] = (BMS_Kapazitaet & (0xFFU));
+ BMS_09[5] = ((BMS_Kapazitaet >> 8) & (0x07U)) | ((BMS_SOC_Kaltstart & (0x1FU)) << 3);
+ BMS_09[6] = ((BMS_SOC_Kaltstart >> 5) & (0x3FU)) | ((BMS_max_Grenz_SOC & (0x03U)) << 6);
+ BMS_09[7] = ((BMS_max_Grenz_SOC >> 2) & (0x07U)) | ((BMS_min_Grenz_SOC & (0x1FU)) << 3);
+ // BMS_10
+ BMS_10[0] = (BMS_BattEnergy_Wh_HiRes & (0xFFU));
+ BMS_10[1] = ((BMS_BattEnergy_Wh_HiRes >> 8) & (0x7FU)) | ((BMS_MaxBattEnergy_Wh_HiRes & (0x01U)) << 7);
+ BMS_10[2] = ((BMS_MaxBattEnergy_Wh_HiRes >> 1) & (0xFFU));
+ BMS_10[3] = ((BMS_MaxBattEnergy_Wh_HiRes >> 9) & (0x3FU)) | ((BMS_SOC & (0x03U)) << 6);
+ BMS_10[4] = ((BMS_SOC >> 2) & (0x3FU)) | ((BMS_ResidualEnergy_Wh & (0x03U)) << 6);
+ BMS_10[5] = ((BMS_ResidualEnergy_Wh >> 2) & (0xFFU));
+ BMS_10[6] = ((BMS_ResidualEnergy_Wh >> 10) & (0x03U)) | ((0x64 & (0x3FU)) << 2);
+ BMS_10[7] = ((0x64 >> 6) & (0x01U)) | ((0x64 & (0x7FU)) << 1);
+ // BMS_11
+ BMS_11[0] = 0x00;
+ BMS_11[1] = 0x00;
+ BMS_11[2] = ((0x02 & (0x0FU)) << 1) | ((0x01 & (0x07U)) << 5);
+ BMS_11[3] = (BMS_BattCell_Temp_Max & (0xFFU));
+ BMS_11[4] = (BMS_BattCell_Temp_Min & (0xFFU));
+ BMS_11[5] = (BMS_BattCell_MV_Max & (0xFFU));
+ BMS_11[6] = ((BMS_BattCell_MV_Max >> 8) & (0x0FU)) | ((BMS_BattCell_MV_Min & (0x0FU)) << 4);
+ BMS_11[7] = ((BMS_BattCell_MV_Min >> 4) & (0xFFU));
+ // BMS_27
+ BMS_27[0] = 0x00;
+ BMS_27[1] = 0x00;
+ BMS_27[2] = 0x00;
+ BMS_27[3] = ((BMS_SOC_ChargeLim & (0x3FU)) << 2);
+ BMS_27[4] = ((BMS_SOC_ChargeLim >> 6) & (0x01U)) | ((BMS_EnergyCount & (0x0FU)) << 1) | ((BMS_EnergyReq_Full & (0x07U)) << 5);
+ BMS_27[5] = ((BMS_EnergyReq_Full >> 3) & (0xFFU));
+ BMS_27[6] = (BMS_ChargePowerMax & (0xFFU));
+ BMS_27[7] = ((BMS_ChargePowerMax >> 8) & (0x0FU)) | ((BMS_ChargeEnergyCount & (0x0FU)) << 4);
+ // BMS_DC_01
+
+ // BMS_Status_DCLS = Status of the voltage monitoring at the DC charging interface | 0=inactive, 1= i.O, 2= n.i.O, 3= Active
+ // BMS_DCLS_Spannung = DC voltage of the charging station. Measurement between the DC HV lines.
+ // BMS_DCLS_MaxLadeStrom = maximum permissible DC charging current
+
+ // BMS_DC_01[0] = (BMS_DC_01_CRC & (0xFFU));
+ // BMS_DC_01[1] = (BMS_DC_01_BZ & (0x0FU)) | ((BMS_Status_DCLS & (0x03U)) << 4) | ((BMS_DCLS_Spannung & (0x03U)) << 6);
+ // BMS_DC_01[2] = ((BMS_DCLS_Spannung >> 2) & (0xFFU));
+ // BMS_DC_01[3] = (BMS_DCLS_MaxLadeStrom & (0xFFU));
+ // BMS_DC_01[4] = ((BMS_DCLS_MaxLadeStrom >> 8) & (0x01U));
+ // BMS_DC_01[5] = 0x00;
+ // BMS_DC_01[6] = 0x00;
+ // BMS_DC_01[7] = 0x00;
+
+ // DCDC_01 - For DC/DC 12V Converter
+ // Intend to mirror HV voltage from main bus (unless found elsewhere)
+ // Charger only seems interested in the 12V output Current & Voltage from module?
+ // DCDC_01[0] = 0x00;
+ // DCDC_01[1] = (0x00 & (0x0FU)) | ((DC_IstSpannung_HV & (0x0FU)) << 4);
+ // DCDC_01[2] = ((DC_IstSpannung_HV >> 4) & (0xFFU));
+ // DCDC_01[3] = (DC_IstStrom_HV_02 & (0xFFU));
+ // DCDC_01[4] = ((DC_IstStrom_HV_02 >> 8) & (0x03U)) | ((DC_IstStrom_NV & (0x3FU)) << 2);
+ // DCDC_01[5] = ((DC_IstStrom_NV >> 6) & (0x0FU));
+ // DCDC_01[7] = (DC_IstSpannung_NV & (0xFFU));
+
+ // DCDC_03 - For DC/DC 12V Converter
+ DCDC_03[2] = (0x00 & (0x07U)) | ((0x00 & (0x01U)) << 3) | ((0x00 & (0x01U)) << 4) | ((DC_IstModus_02 & (0x07U)) << 5);
+
+
+ // Dimmung_01
+ // Dimmung_01[0] = (DI_KL_58xd & (0xFFU));
+ // Dimmung_01[1] = (DI_KL_58xs & (0x7FU)) | ((DI_Display_Nachtdesign & (0x01U)) << 7);
+ // Dimmung_01[2] = (DI_KL_58xt & (0x7FU));
+ // Dimmung_01[3] = (DI_Fotosensor & (0xFFU));
+ // Dimmung_01[4] = ((DI_Fotosensor >> 8) & (0xFFU));
+ // Dimmung_01[5] = (BCM1_Stellgroesse_Kl_58s & (0x7FU));
+ // Dimmung_01[6] = 0x00;
+ // Dimmung_01[7] = 0x00;
+
+ // HVEM_05
+ HVEM_05[0] = 0x00;
+ HVEM_05[1] = ((HVEM_NVNachladen_Energie & (0x0FU)) << 4);
+ HVEM_05[2] = (HVEM_NVNachladen_Energie >> 4) & (0x0FU);
+ HVEM_05[3] = 0x00;
+ HVEM_05[4] = (HVEM_Nachladen_Anf & (0x01U)) | ((HVEM_SollStrom_HV & (0x7FU)) << 1);
+ HVEM_05[5] = ((HVEM_SollStrom_HV >> 7) & (0x0FU)) | ((HVEM_MaxSpannung_HV & (0x0FU)) << 4);
+ HVEM_05[6] = ((HVEM_MaxSpannung_HV >> 4) & (0x3FU)) | ((0x00& (0x03U)) << 6);
+ HVEM_05[7] = 0x00;
+
+ // Authentic_Time_01 & NavData_02
+ Authentic_Time_01[4] = (UnixTime & (0xFFU));
+ Authentic_Time_01[5] = ((UnixTime >> 8) & (0xFFU));
+ Authentic_Time_01[6] = ((UnixTime >> 16) & (0xFFU));
+ Authentic_Time_01[7] = ((UnixTime >> 24) & (0xFFU));
+
+ ESP_15[4] = (0x00 & (0x01U)) | ((0x00 & (0x07U)) << 1) | ((HMS_Systemstatus & (0x0FU)) << 4);
+ ESP_15[5] = (0x00 & (0x07U)) | ((HMS_aktives_System & (0x1FU)) << 3);
+ ESP_15[6] = (0x00 & (0x01U)) | ((0x00 & (0x01U)) << 1) | ((HMS_Fehlerstatus & (0x07U)) << 2) | ((0x00 & (0x01U)) << 5) | ((0x00 & (0x03U)) << 6);
+
+ Klemmen_Status_01[2] = (ZAS_Kl_S & (0x01U)) | ((ZAS_Kl_15 & (0x01U)) << 1) | ((ZAS_Kl_X & (0x01U)) << 2) | ((ZAS_Kl_50_Startanforderung & (0x01U)) << 3) | ((0x00 & (0x01U)) << 4) | ((0x00 & (0x01U)) << 5) | ((0x00 & (0x01U)) << 6) | ((0x00 & (0x01U)) << 7);
+
+ HVK_01[1] = (0x00 & (0x0FU)) | ((0x00 & (0x01U)) << 4) | ((0x00 & (0x03U)) << 5);
+ HVK_01[2] = (HVK_MO_EmSollzustand & (0xFFU));
+ HVK_01[3] = (HVK_BMS_Sollmodus & (0x07U)) | ((HVK_DCDC_Sollmodus & (0x07U)) << 3) | ((0x00 & (0x03U)) << 6);
+ HVK_01[4] = ((0x00 >> 2) & (0x01U)) | ((0x00 & (0x07U)) << 1) | ((HVK_HVLM_Sollmodus & (0x07U)) << 4) | ((0x00 & (0x01U)) << 7);
+ HVK_01[5] = ((0x00 >> 1) & (0x01U)) | ((HV_Bordnetz_aktiv & (0x01U)) << 1) | ((0x00 & (0x01U)) << 2) | ((HVK_Gesamtst_Spgfreiheit & (0x03U)) << 3) | ((0x00 & (0x01U)) << 5);
+
+
+ ZV_01[1] = (0x00 & (0x0FU)) | ((ZV_FT_verriegeln & (0x01U)) << 4) | ((ZV_FT_entriegeln & (0x01U)) << 5) | ((ZV_BT_verriegeln & (0x01U)) << 6) | ((ZV_BT_entriegeln & (0x01U)) << 7);
+ ZV_01[7] = ((0x00 >> 5) & (0x3FU)) | ((ZV_entriegeln_Anf & (0x01U)) << 6) | ((0x00 & (0x01U)) << 7);
+
+ ZV_02[2] = (ZV_verriegelt_intern_ist & (0x01U)) | ((ZV_verriegelt_extern_ist & (0x01U)) << 1) | ((ZV_verriegelt_intern_soll & (0x01U)) << 2) | ((ZV_verriegelt_extern_soll & (0x01U)) << 3) | ((0x00 & (0x01U)) << 4) | ((0x00 & (0x01U)) << 5) | ((0x00 & (0x01U)) << 6) | ((0x00 & (0x01U)) << 7);
+ ZV_02[7] = (0x00 & (0x01U)) | ((0x00 & (0x01U)) << 1) | ((0x00 & (0x01U)) << 2) | ((0x00 & (0x01U)) << 3) | ((0x00 & (0x01U)) << 4) | ((0x00 & (0x01U)) << 5) | ((ZV_verriegelt_soll & (0x03U)) << 6);
+
+
+
+ EM_HYB_11[1] = (0x00 & (0x0FU)) | ((EM1_Istmodus2 & (0x0FU)) << 4);
+ EM_HYB_11[2] = (0x00 & (0x07U)) | ((EM1_Status_Spgfreiheit & (0x03U)) << 3) | ((0x00 & (0x01U)) << 5);
+
+}