From bdddc49dab14a9c3145f124308f7b86f1f76cf70 Mon Sep 17 00:00:00 2001
From: Kilian Bracher <k.bracher@fasttube.de>
Date: Sun, 13 Apr 2025 15:42:53 +0200
Subject: [PATCH] add battery error handling

---
 AMS_Master_Code/Core/Src/battery.c | 31 +++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/AMS_Master_Code/Core/Src/battery.c b/AMS_Master_Code/Core/Src/battery.c
index 16c16db..7766d44 100644
--- a/AMS_Master_Code/Core/Src/battery.c
+++ b/AMS_Master_Code/Core/Src/battery.c
@@ -1,11 +1,16 @@
 #include "battery.h"
 #include "ADBMS_Driver.h"
 #include "NTC.h"
+#include "can.h"
 #include "config_ADBMS6830.h"
+#include "ts_state_machine.h"
 #include <string.h>
 
 #define SWO_LOG_PREFIX "[BATTERY] "
 #include "swo_log.h"
+
+#define MAX_ERRORS                4 // max number of errors in window before panic
+#define MAX_ERRORS_WINDOW_SIZE   16 // size of the error window for error detection
  
 uint16_t min_voltage = 0xFFFF;
 uint16_t max_voltage = 0;
@@ -16,6 +21,26 @@ typeof(module_temps) module_temps = {[0 ... N_BMS - 1] = {INT16_MAX, INT16_MIN}}
 
 int16_t cellTemps[N_BMS][N_CELLS];
 
+static bool error_window[MAX_ERRORS_WINDOW_SIZE] = {};
+static size_t error_window_index = 0;
+static size_t error_count = 0;
+
+static inline void update_error_window(bool error, int id) {
+  error_count -= error_window[error_window_index] ? 1 : 0; 
+  error_count += error ? 1 : 0;
+
+  if (error_count >= MAX_ERRORS) {
+    can_send_error(TS_ERRORKIND_SLAVE_PANIC, id);
+    ts_sm_set_error_source(TS_ERROR_SOURCE_SLAVES, TS_ERRORKIND_SLAVE_PANIC, true);
+  } else {
+    ts_sm_set_error_source(TS_ERROR_SOURCE_SLAVES, TS_ERRORKIND_SLAVE_PANIC, false);
+  }
+
+  error_window[error_window_index] = error;
+  error_window_index += 1;
+  error_window_index %= MAX_ERRORS_WINDOW_SIZE;
+}
+
 HAL_StatusTypeDef battery_init(SPI_HandleTypeDef *hspi) { 
     auto ret = AMS_Init(hspi);
     if (ret.status != ADBMS_NO_ERROR) {
@@ -33,14 +58,18 @@ HAL_StatusTypeDef battery_init(SPI_HandleTypeDef *hspi) {
 HAL_StatusTypeDef battery_update() {
   auto ret = AMS_Idle_Loop();
   if (ret.status != ADBMS_NO_ERROR) {
-    debug_log(LOG_LEVEL_ERROR, "Failed to update battery data: %s",
+    debug_log(LOG_LEVEL_ERROR, "Error while updating battery data: %s",
               ADBMS_Status_ToString(ret.status));
     if (ret.bms_id != -1) {
       debug_log_cont(LOG_LEVEL_ERROR, " (on BMS ID: %hd)", ret.bms_id);
     }
+    
+    update_error_window(true, ret.bms_id);
     return HAL_ERROR;
   }
 
+  update_error_window(false, ret.bms_id);
+
   min_voltage = 0xFFFF;
   max_voltage = 0;
   min_temp = INT16_MAX;