2025-05-07 23:44:38 +02:00

179 lines
5.6 KiB
C

#include "can.h"
#include "ADBMS_Driver.h"
#include "imd_monitoring.h"
#include "isotp.h"
#include "isotp_user_defs.h"
#include "isotp_log_backend.h"
#include "log.h"
#include "main.h"
#include "shunt_monitoring.h"
#include "battery.h"
#include "soc_estimation.h"
#include "ts_state_machine.h"
#include "can-halal.h"
#include <math.h>
#include <stdint.h>
#include <string.h>
static isotp_conn_id_t isotp_connection_id = 0;
bool isotp_transmit(uint16_t id, const uint8_t *data, size_t datalen) {
return ftcan_transmit(id, data, datalen) == HAL_OK;
}
uint32_t isotp_get_time() {
return HAL_GetTick();
}
void can_init(FDCAN_HandleTypeDef *handle) {
ftcan_init(handle);
ftcan_add_filter(CAN_ID_SHUNT_BASE, 0xFF0);
ftcan_add_filter(CAN_ID_AMS_IN, 0xFFF);
ftcan_add_filter(CAN_ID_AMS_DETAILS_FC, 0xFFF);
ftcan_add_filter(ISOTP_LOG_FC_CAN_ID, 0xFFF);
const auto status = isotp_add_connection(CAN_ID_AMS_DETAILS_FC, CAN_ID_AMS_DETAILS, ISOTP_FLAGS_NONE);
if (status < 0) {
log_warning("Failed to add ISO-TP connection: %s", isotp_status_to_string((isotp_status_t)status));
}
isotp_connection_id = (isotp_conn_id_t)status;
// ftcan_add_filter(CAN_ID_SLAVE_PANIC, 0xFFF);
// ftcan_add_filter(CAN_ID_SLAVE_STATUS_BASE, 0xFF0);
// ftcan_add_filter(CAN_ID_SLAVE_LOG, 0xFFF);
}
HAL_StatusTypeDef can_send_status() {
uint8_t data[8];
data[0] = ts_state.current_state | (sdc_closed << 7);
data[1] = roundf(current_soc);
ftcan_marshal_unsigned(&data[2], min_voltage, 2);
ftcan_marshal_signed(&data[4], max_temp, 2);
data[6] = imd_data.state | (imd_data.ok << 7);
if (imd_data.r_iso < 0xFFF) {
data[7] = imd_data.r_iso >> 4;
} else {
data[7] = 0xFF;
}
const HAL_StatusTypeDef ret = ftcan_transmit(CAN_ID_AMS_STATUS, data, sizeof(data));
if (ret != HAL_OK) {
return ret;
}
data[0] = (sdc_closed_nodelay << 0) | (ts_error << 1) | (hv_active << 2) |
(neg_air_closed << 3) | (pos_air_closed << 4) |
(precharge_closed << 5) | (pre_and_air_open << 6);
return ftcan_transmit(CAN_ID_AMS_SIGNALS, data, 1);
}
HAL_StatusTypeDef can_send_details() {
static uint8_t module_index = 0;
static uint8_t data[103] = {}; //sizeof(Cell_Module) + 10 + 1
const auto module = &modules[module_index];
auto data_ptr = &data[1];
isotp_status_t status = isotp_try_add_message(isotp_connection_id, data, sizeof(data));
switch (status) {
case ISOTP_OK:
break;
case ISOTP_MESSAGE_ALREADY_IN_FLIGHT:
return HAL_BUSY;
default:
log_warning("isotp_try_add_message failed: %s", isotp_status_to_string(status));
return HAL_ERROR;
}
data[0] = module_index;
data_ptr = ftcan_marshal_unsigned(data_ptr, module->bmsID, 8);
data_ptr = ftcan_marshal_unsigned(data_ptr, module->status.CS_FLT, 2);
data_ptr = ftcan_marshal_unsigned(data_ptr, module->status.CCTS, 2);
// Marshal status bits into a single byte
uint8_t status_bits = 0;
status_bits |= module->status.SMED << 0;
status_bits |= module->status.SED << 1;
status_bits |= module->status.CMED << 2;
status_bits |= module->status.CED << 3;
status_bits |= module->status.VD_UV << 4;
status_bits |= module->status.VD_OV << 5;
status_bits |= module->status.VA_UV << 6;
status_bits |= module->status.VA_OV << 7;
*(data_ptr++) = status_bits;
// Marshal the rest of the status bits
status_bits = 0;
status_bits |= module->status.OSCCHK << 0;
status_bits |= module->status.TMODCHK << 1;
status_bits |= module->status.THSD << 2;
status_bits |= module->status.SLEEP << 3;
status_bits |= module->status.SPIFLT << 4;
status_bits |= module->status.COMPARE << 5;
status_bits |= module->status.VDE << 6;
status_bits |= module->status.VDEL << 7;
*(data_ptr++) = status_bits;
// Marshal voltage flags
data_ptr = ftcan_marshal_unsigned(data_ptr, module->overVoltage, 4);
data_ptr = ftcan_marshal_unsigned(data_ptr, module->underVoltage, 4);
// Marshal temperature and voltages
data_ptr = ftcan_marshal_signed(data_ptr, module->internalDieTemp, 2);
data_ptr = ftcan_marshal_unsigned(data_ptr, module->analogSupplyVoltage, 2);
data_ptr = ftcan_marshal_unsigned(data_ptr, module->digitalSupplyVoltage, 2);
data_ptr = ftcan_marshal_unsigned(data_ptr, module->refVoltage, 2);
// Marshal cell voltages
for (int i = 0; i < 16; i++) {
data_ptr = ftcan_marshal_signed(data_ptr, module->cellVoltages[i], 2);
}
// Marshal auxiliary voltages
for (int i = 0; i < 10; i++) {
data_ptr = ftcan_marshal_signed(data_ptr, module->auxVoltages[i], 2);
}
// Marshal temperature data
for (int i = 0; i < 10; i++) {
data_ptr = ftcan_marshal_signed(data_ptr, cellTemps[module_index][i], 2);
}
if ((status = isotp_add_message(isotp_connection_id, data, sizeof(data))) != ISOTP_OK) {
log_warning("isotp_add_message failed unexpectedly: %s", isotp_status_to_string(status));
return HAL_ERROR;
}
module_index = (module_index + 1) % N_BMS;
return HAL_OK;
}
HAL_StatusTypeDef can_send_error(TSErrorKind kind, uint8_t arg) {
uint8_t data[2];
data[0] = kind;
data[1] = arg;
return ftcan_transmit(CAN_ID_AMS_ERROR, data, sizeof(data));
}
void ftcan_msg_received_cb(uint16_t id, size_t len, const uint8_t *data) {
if ((id & 0xFF0) == CAN_ID_SHUNT_BASE) {
shunt_handle_can_msg(id, data);
return;
}
switch (id) {
case ISOTP_LOG_FC_CAN_ID:
case CAN_ID_AMS_DETAILS_FC:
const auto status = isotp_handle_incoming(id, data, len);
if (status != ISOTP_OK) {
log_debug("Error when handling flow control: %s", isotp_status_to_string(status));
}
break;
case CAN_ID_AMS_IN:
ts_sm_handle_ams_in(data);
break;
default:
break;
}
}