HVAC_M7_CAN_SPAM/CanSpamTransmitter.c

511 lines
20 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Created by cfif on 05.12.2025.
//
#include <SystemDelayInterface.h>
#include "CanSpamTransmitter.h"
#include "CmsisRtosThreadUtils.h"
#include "CanPorts.h"
void CanSpamTransmitter_Init(tCanSpamTransmitter *env,
tSerialPortFrameIO *ioCanFrame) {
env->ioCanFrame = ioCanFrame;
env->access = osMutexNew(NULL);
InitThreadAtrStatic(&env->thread.attr, "CanSpamTrans", env->thread.controlBlock, env->thread.stack,
osPriorityNormal);
}
static void CCU_HVC_Req_Msg(tCanSpamTransmitter *env) {
CCU_HVC_Req_Msg_t *_m = &ccu_candb_tx.CCU_HVC_Req_Msg;
// Compressor target speed:
// 0xFF = Fault value
_m->CCU_eCompSpeedReq_Val_ro = 0; // Bits= 8 Factor= 50 Unit:'rpm'
// Request to activate air conditioner compressor
// 1 : "Request"
// 0 : "Stop request"
_m->CCU_eCompReq_Stat = 0; // Bits= 1
// request to EMS for closing the low temperature circuit valve
// 2 : "Open Valve request"
// 1 : "Close Valve request"
// 0 : "No request"
_m->CCU_LowTempValve_Req = 1; // Bits= 2
// Rolling Counter [0 - 15]
if (_m->CCU_HVC_Req_RC > 15) {
_m->CCU_HVC_Req_RC = 0; // Bits= 4
} else {
++_m->CCU_HVC_Req_RC; // Bits= 4
}
// Checksum XOR8 of the data field this message
// Checksum computed as per XOR algorithm:
// Byte 1 XOR byte 2 .... XOR byte n-1. (n = packet length.)
uint8_t d0 = (uint8_t) ((_m->CCU_eCompSpeedReq_Val_ro & (0xFFU)));
uint8_t d1 = (uint8_t) ((_m->CCU_eCompReq_Stat & (0x01U)) |
((_m->CCU_LowTempValve_Req & (0x03U)) << 1U) |
((_m->CCU_HVC_Req_RC & (0x0FU)) << 4U));
_m->CCU_HVC_Req_CS = d0 ^ d1; // Bits= 8
}
static void CCU_Msg1(tCanSpamTransmitter *env) {
CCU_Msg1_t *_m = &ccu_candb_tx.CCU_Msg1;
// Request to activate mirrors heating
// 3 : "Error"
// 2 : "Heating off requested"
// 1 : "Heating on requested"
// 0 : "Unknown"
_m->CCU_MirrorHeating_Req = 0; // Bits= 2
// Air recirculation LED indicator command
// 1 : "On"
// 0 : "Off"
_m->CCU_RecirculationLed_Cmd = 0; // Bits= 1
// Defrost function LED indicator on/off request
// 1 : "On"
// 0 : "Off"
_m->CCU_DefrostLed_Req = 0; // Bits= 1
// Request to activate side windows heating
// 3 : "Error"
// 2 : "Heating off requested"
// 1 : "Heating on requested"
// 0 : "Unknown"
_m->CCU_SideWindowHeating_Req = 0; // Bits= 2
// Request to activate rear window heating
// 3 : "Error"
// 2 : "Heating off requested"
// 1 : "Heating on requested"
// 0 : "Unknown"
_m->CCU_RearWindowHeating_Req = 0; // Bits= 2
// Request to activate front window heating
// 3 : "Error"
// 2 : "Heating off requested"
// 1 : "Heating on requested"
// 0 : "Unknown"
_m->CCU_FrontWindowHeating_Req = 0; // Bits= 2
// Status of emergency air cleaning system
// 1 : "Active"
// 0 : "Incative"
_m->CCU_EmergAirCleaning_Stat = 0; // Bits= 1
// Status of fire extinguishing system
// 1 : "Active"
// 0 : "Inactive"
_m->CCU_FireExtinguishSys_Stat = 0; // Bits= 1
// Automate climate control On/Off LED command
// 1 : "On"
// 0 : "Off"
_m->CCU_FLAutoPsngrLed_Cmd = 0; // Bits= 1
// Automate climate control On/Off LED command
// 1 : "On"
// 0 : "Off"
_m->CCU_FRAutoPsngrLed_Cmd = 0; // Bits= 1
// Automate climate control On/Off LED command
// 1 : "On"
// 0 : "Off"
_m->CCU_RLAutoPsngrLed_Cmd = 0; // Bits= 1
// Automate climate control On/Off LED command
// 1 : "On"
// 0 : "Off"
_m->CCU_RRAutoPsngrLed_Cmd = 0; // Bits= 1
// LED indicator command in CCPF when automatic Coditioner with max power is Active
// 1 : "On"
// 0 : "Off"
_m->CCU_AC_MaxLed_Cmd = 0; // Bits= 1
// Rolling Counter [0 - 15]
if (_m->CCU_MSG1_RC > 15) {
_m->CCU_MSG1_RC = 0; // Bits= 4
} else {
++_m->CCU_MSG1_RC; // Bits= 4
}
// Checksum XOR8 of the data field this message
// Checksum computed as per XOR algorithm:
// Byte 1 XOR byte 2 .... XOR byte n-1. (n = packet length.)
uint8_t d0 = (uint8_t) ((_m->CCU_MirrorHeating_Req & (0x03U)) |
((_m->CCU_RecirculationLed_Cmd & (0x01U)) << 2U) |
((_m->CCU_DefrostLed_Req & (0x01U)) << 3U) |
((_m->CCU_SideWindowHeating_Req & (0x03U)) << 4U) |
((_m->CCU_RearWindowHeating_Req & (0x03U)) << 6U));
uint8_t d1 = (uint8_t) ((_m->CCU_FrontWindowHeating_Req & (0x03U)) |
((_m->CCU_EmergAirCleaning_Stat & (0x01U)) << 2U) |
((_m->CCU_FireExtinguishSys_Stat & (0x01U)) << 3U));
uint8_t d3 = (uint8_t) ((_m->CCU_FLAutoPsngrLed_Cmd & (0x01U)) |
((_m->CCU_FRAutoPsngrLed_Cmd & (0x01U)) << 1U) |
((_m->CCU_RLAutoPsngrLed_Cmd & (0x01U)) << 2U) |
((_m->CCU_RRAutoPsngrLed_Cmd & (0x01U)) << 3U) |
((_m->CCU_AC_MaxLed_Cmd & (0x01U)) << 4U));
uint8_t d6 = (uint8_t) (((_m->CCU_MSG1_RC & (0x0FU)) << 4U));
_m->CCU_MSG1_CS = d0 ^ d1 ^ d3 ^ d6;
}
static void CCU_Msg3(tCanSpamTransmitter *env) {
CCU_Msg3_t *_m = &ccu_candb_tx.CCU_Msg3;
// Indicates the requested FAN speed from CCU system.
// 127 : "Error"
_m->CCU_FAN_Req = 0; // Bits= 7 Unit:'%'
// CCU REST mode status
// 3 : "Inactive"
// 2 : "Active"
// 1 : "Standby"
// 0 : "Not requested"
_m->CCU_RestMode_Stat = 0; // Bits= 2
// Arithmetic mean air temperature inside the car
_m->CCU_IncarTempSum_Val_ro = CANDB_CCU_IncarTempSum_Val_ro_toS(
23); // Bits= 8 Offset= -50.0 Factor= 0.5 Unit:'<27>C'
// Rolling Counter [0 - 15]
if (_m->CCU_MSG3_RC > 15) {
_m->CCU_MSG3_RC = 0; // Bits= 4
} else {
++_m->CCU_MSG3_RC; // Bits= 4
}
// Checksum XOR8 of the data field this message
// Checksum computed as per XOR algorithm:
// Byte 1 XOR byte 2 .... XOR byte n-1. (n = packet length.)
uint8_t d0 = (uint8_t) ((_m->CCU_FAN_Req & (0x7FU)));
uint8_t d1 = (uint8_t) ((_m->CCU_RestMode_Stat & (0x03U)));
uint8_t d2 = (uint8_t) ((_m->CCU_IncarTempSum_Val_ro & (0xFFU)));
uint8_t d3 = (uint8_t) ((_m->CCU_MSG3_RC & (0x0FU)));
_m->CCU_MSG3_CS = d0 ^ d1 ^ d2 ^ d3;
}
static void CCU_Errors(tCanSpamTransmitter *env) {
CCU_Errors_t *_m = &ccu_candb_tx.CCU_Errors;
// Incar temperature sensors for front zone error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_IncarTempErrF_Stat = 0; // Bits= 1
// Incar temperature sensors for rear zone error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_IncarTempErrR_Stat = 0; // Bits= 1
// Duct temperature sensors for front zone error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_DuctTempSenErrF_Stat = 0; // Bits= 1
// Duct temperature sensors for rear zone error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_DuctTempSenErrR_Stat = 0; // Bits= 1
// Evaporator temperature sensor for front zone error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_EvaTempSenErrF_Stat = 0; // Bits= 1
// Evaporator temperature sensor for rear zone error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_EvaTempSenErrR_Stat = 0; // Bits= 1
// Deflectors for front zone error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_DeflectorSwErrF_Stat = 0; // Bits= 1
// Deflectors for rear zone error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_DeflectorSwErrR_Stat = 0; // Bits= 1
// Pressure sensors error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_PressSenErr_Stat = 0; // Bits= 1
// Ambient temperature sensor error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_AmbienTemptSenErr_Stat = 0; // Bits= 1
// Sealing valve error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_SealingValveErr_Stat = 0; // Bits= 1
// ETXV error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_ETXVerr_Stat = 0; // Bits= 1
// HVAC fan or TXV for front zone error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_HVACfanOrTXVerrF_Stat = 0; // Bits= 1
// HVAC fan or TXV for rear zone error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_HVACfanOrTXVerrR_Stat = 0; // Bits= 1
// Actuators for front zone error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_ActuatorErrF_Stat = 0; // Bits= 1
// Actuators for rear zone error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_ActuatorErrR_Stat = 0; // Bits= 1
// Ultraviolet system error status
// 3 : "Component malfunction"
// 2 : "Supply chain short circuit
// 1 : "Supply chain break
// 0 : "No error"
_m->CCU_UltravioletErr_Stat = 0; // Bits= 2
// CCU VIN record error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_VinRecordErr_Stat = 0; // Bits= 1
// Air quality sensor error status
// 4 : "Component malfunction"
// 3 : "Communication error"
// 2 : "Supply chain short circuit"
// 1 : "Supply chain break"
// 0 : "No error"
_m->CCU_AirQualSenErr_Stat = 0; // Bits= 3
// CCU communication error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_CommErr_Stat = 0; // Bits= 1
// Two-way valve error status
// 1 : "Error"
// 0 : "No error"
_m->CCU_TWVerr_Stat = 0; // Bits= 1
// Ionization system error status
// 4 : "Component malfunction"
// 3 : "Communication error
// 2 : "Supply chain short circuit
// 1 : "Supply chain break
// 0 : "No error"
_m->CCU_IonizationErr_Stat = 0; // Bits= 3
// Aromatization system error status
// 4 : "Component malfunction"
// 3 : "Communication error
// 2 : "Supply chain short circuit
// 1 : "Supply chain break
// 0 : "No error"
_m->CCU_AromaErr_Stat = 0; // Bits= 3
}
static void sendEventToCan(tCanSpamTransmitter *env) {
if (env->ide) {
env->canFrame.id_type = FLEXCAN_ID_EXT;
env->canFrame.extended_id = env->can_id;
} else {
env->canFrame.id_type = FLEXCAN_ID_STD;
env->canFrame.standard_id = env->can_id;
}
env->ioCanFrame->transmit(env->ioCanFrame->env, (uint8_t *) &env->canFrame.data, env->canFrame.dlc,
env->can_id, env->canFrame.id_type, 100);
}
static eTimeEventTransmit isEventTransmitter(tCanSpamTransmitter *env) {
if (env->time_CCU_Stat1_CYC < env->timeMs) {
env->time_CCU_Stat1_CYC = env->timeMs + CCU_Stat1_CYC;
env->can_id = Pack_CCU_Stat1_candb(&ccu_candb_tx.CCU_Stat1, env->canFrame.data, &env->canFrame.dlc, &env->ide);
// return event_CCU_Stat1_CYC;
}
if (env->time_CCU_Stat2_CYC < env->timeMs) {
env->time_CCU_Stat2_CYC = env->timeMs + CCU_Stat2_CYC;
env->can_id = Pack_CCU_Stat2_candb(&ccu_candb_tx.CCU_Stat2, env->canFrame.data, &env->canFrame.dlc, &env->ide);
// return event_CCU_Stat2_CYC;
}
if (env->time_CCU_Stat3_CYC < env->timeMs) {
env->time_CCU_Stat3_CYC = env->timeMs + CCU_Stat3_CYC;
env->can_id = Pack_CCU_Stat3_candb(&ccu_candb_tx.CCU_Stat3, env->canFrame.data, &env->canFrame.dlc, &env->ide);
// return event_CCU_Stat3_CYC;
}
if (env->time_CCU_Errors_CYC < env->timeMs) {
env->time_CCU_Errors_CYC = env->timeMs + CCU_Errors_CYC;
CCU_Errors(env);
env->can_id = Pack_CCU_Errors_candb(&ccu_candb_tx.CCU_Errors, env->canFrame.data, &env->canFrame.dlc,
&env->ide);
return event_CCU_Errors_CYC;
}
if (env->time_CCU_Requests < env->timeMs) {
env->time_CCU_Requests = env->timeMs + CCU_Requests_CYC;
env->can_id = Pack_CCU_Requests_candb(&ccu_candb_tx.CCU_Requests, env->canFrame.data, &env->canFrame.dlc,
&env->ide);
// return event_CCU_Requests;
}
// начало--------------------------------------0x310 CCU_HVC_Req_Msg------------------------------------------------
// начало--------------------------------------0x310 CCU_HVC_Req_Msg------------------------------------------------
// начало--------------------------------------0x310 CCU_HVC_Req_Msg------------------------------------------------
if (env->time_CCU_HVC_Req_Msg < env->timeMs) {
env->time_CCU_HVC_Req_Msg = env->timeMs + CCU_HVC_Req_Msg_CYC;
CCU_HVC_Req_Msg(env);
env->can_id = Pack_CCU_HVC_Req_Msg_candb(&ccu_candb_tx.CCU_HVC_Req_Msg, env->canFrame.data, &env->canFrame.dlc,
&env->ide);
return event_CCU_HVC_Req_Msg;
}
// конец ---------------------------------------0x310 CCU_HVC_Req_Msg------------------------------------------------
// конец ---------------------------------------0x310 CCU_HVC_Req_Msg------------------------------------------------
// конец ---------------------------------------0x310 CCU_HVC_Req_Msg------------------------------------------------
// начало РЕЗЕРВ--------------------------------------0x315 CCU_VCU_Msg1---------------------------------------------------
// начало РЕЗЕРВ--------------------------------------0x315 CCU_VCU_Msg1---------------------------------------------------
// начало РЕЗЕРВ--------------------------------------0x315 CCU_VCU_Msg1---------------------------------------------------
// if (env->time_CCU_VCU_Msg1 < env->timeMs) {
// env->time_CCU_VCU_Msg1 = env->timeMs + CCU_VCU_Msg1_CYC;
// env->can_id = Pack_CCU_VCU_Msg1_candb(&ccu_candb_tx.CCU_VCU_Msg1, env->canFrame.data, &env->canFrame.dlc,
// &env->ide);
// return event_CCU_VCU_Msg1;
// }
// конец РЕЗЕРВ---------------------------------------0x315 CCU_VCU_Msg1---------------------------------------------------
// конец РЕЗЕРВ---------------------------------------0x315 CCU_VCU_Msg1---------------------------------------------------
// конец РЕЗЕРВ---------------------------------------0x315 CCU_VCU_Msg1---------------------------------------------------
// начало РЕЗЕРВ--------------------------------------0x316 CCU_VCU_Msg2---------------------------------------------------
// начало РЕЗЕРВ--------------------------------------0x316 CCU_VCU_Msg2---------------------------------------------------
// начало РЕЗЕРВ--------------------------------------0x316 CCU_VCU_Msg2---------------------------------------------------
// if (env->time_CCU_VCU_Msg2 < env->timeMs) {
// env->time_CCU_VCU_Msg2 = env->timeMs + CCU_VCU_Msg2_CYC;
// env->can_id = Pack_CCU_VCU_Msg2_candb(&ccu_candb_tx.CCU_VCU_Msg2, env->canFrame.data, &env->canFrame.dlc,
// &env->ide);
// return event_CCU_VCU_Msg2;
// }
// конец РЕЗЕРВ---------------------------------------0x316 CCU_VCU_Msg2---------------------------------------------------
// конец РЕЗЕРВ---------------------------------------0x316 CCU_VCU_Msg2---------------------------------------------------
// конец РЕЗЕРВ---------------------------------------0x316 CCU_VCU_Msg2---------------------------------------------------
// начало--------------------------------------0x380 CCU_Msg1-------------------------------------------------------
// начало--------------------------------------0x380 CCU_Msg1-------------------------------------------------------
// начало--------------------------------------0x380 CCU_Msg1-------------------------------------------------------
if (env->time_CCU_Msg1 < env->timeMs) {
env->time_CCU_Msg1 = env->timeMs + CCU_Msg1_CYC;
CCU_Msg1(env);
env->can_id = Pack_CCU_Msg1_candb(&ccu_candb_tx.CCU_Msg1, env->canFrame.data, &env->canFrame.dlc, &env->ide);
return event_CCU_Msg1;
}
// начало--------------------------------------0x380 CCU_Msg1-------------------------------------------------------
// начало--------------------------------------0x380 CCU_Msg1-------------------------------------------------------
// начало--------------------------------------0x380 CCU_Msg1-------------------------------------------------------
// начало--------------------------------------0x501 CCU_Msg3-------------------------------------------------------
// начало--------------------------------------0x501 CCU_Msg3-------------------------------------------------------
// начало--------------------------------------0x501 CCU_Msg3-------------------------------------------------------
if (env->time_CCU_Msg3 < env->timeMs) {
env->time_CCU_Msg3 = env->timeMs + CCU_Msg3_CYC;
CCU_Msg3(env);
env->can_id = Pack_CCU_Msg3_candb(&ccu_candb_tx.CCU_Msg3, env->canFrame.data, &env->canFrame.dlc, &env->ide);
return event_CCU_Msg3;
}
// конец--------------------------------------0x501 CCU_Msg3-------------------------------------------------------
// конец--------------------------------------0x501 CCU_Msg3-------------------------------------------------------
// конец--------------------------------------0x501 CCU_Msg3-------------------------------------------------------
// начало РЕЗЕРВ--------------------------------------0x18FFF200 CCU_AC_Ctrl -------------------------------------------------------
// начало РЕЗЕРВ--------------------------------------0x18FFF200 CCU_AC_Ctrl -------------------------------------------------------
// начало РЕЗЕРВ--------------------------------------0x18FFF200 CCU_AC_Ctrl -------------------------------------------------------
// if (env->time_CCU_AC_Ctrl < env->timeMs) {
// env->time_CCU_AC_Ctrl = env->timeMs + CCU_AC_Ctrl_CYC;
// env->can_id = Pack_CCU_AC_Ctrl_candb(&ccu_candb_tx.CCU_AC_Ctrl, env->canFrame.data, &env->canFrame.dlc,
// &env->ide);
// return event_CCU_AC_Ctrl;
// }
// конец РЕЗЕРВ--------------------------------------0x18FFF200 CCU_AC_Ctrl -------------------------------------------------------
// конец РЕЗЕРВ--------------------------------------0x18FFF200 CCU_AC_Ctrl -------------------------------------------------------
// конец РЕЗЕРВ--------------------------------------0x18FFF200 CCU_AC_Ctrl -------------------------------------------------------
return event_CCU_none;
}
static _Noreturn void CanSpamTransmitter_Thread(tCanSpamTransmitter *env) {
for (;;) {
if (osMutexAcquire(env->access, 100) == osOK) {
env->timeMs = GetSystemTick();
while (isEventTransmitter(env) != event_CCU_none) {
sendEventToCan(env);
}
osMutexRelease(env->access);
SystemDelayMs(1);
}
}
}
void CanSpamTransmitter_StartThread(tCanSpamTransmitter *env) {
if (!env->thread.id) {
env->thread.id = osThreadNew((osThreadFunc_t) (CanSpamTransmitter_Thread), (void *) (env), &env->thread.attr);
}
}