diff --git a/AMS_Master_Code/.vscode/launch.json b/AMS_Master_Code/.vscode/launch.json
index e713b61..4fa138f 100644
--- a/AMS_Master_Code/.vscode/launch.json
+++ b/AMS_Master_Code/.vscode/launch.json
@@ -40,7 +40,6 @@
       "request": "attach",
       "type": "cortex-debug",
       "servertype": "openocd",
-      "preLaunchTask": "Build STM",
       "device": "stm32h7a3xxq.s",
       "configFiles": [
         "openocd.cfg"
diff --git a/AMS_Master_Code/Core/Inc/NTC.h b/AMS_Master_Code/Core/Inc/NTC.h
index 7934f44..6c0d10b 100644
--- a/AMS_Master_Code/Core/Inc/NTC.h
+++ b/AMS_Master_Code/Core/Inc/NTC.h
@@ -1,4 +1,5 @@
 #include <math.h>
+#include <stdint.h>
 
 #define USE_CALC
 
@@ -18,10 +19,10 @@
 // With R_T/R_0 and R_0 = R_T@25C
 // R_T/R_0 = 1 / V_REF / ADC - 1
 
+[[gnu::optimize("fast-math")]]
 static inline uint16_t ntc_mv_to_celsius(int16_t adc) {
-  float log_ohms = logf(1/((VREF/adc)-1));
+  float log_ohms = logf(1 / ((VREF / adc) - 1));
   return (uint16_t) (TEMP_CONV / (NTC_A1 + NTC_B1 * log_ohms + NTC_C1 * log_ohms * log_ohms + NTC_D1 * log_ohms * log_ohms * log_ohms) - CELSIUS_TO_KELVIN_SCALED);
-
 }
 #else
 // Lookup Table coming soon; not really needed but fun?
diff --git a/AMS_Master_Code/Core/Inc/config_ADBMS6830.h b/AMS_Master_Code/Core/Inc/config_ADBMS6830.h
index 4b60e4c..2fdaa6a 100644
--- a/AMS_Master_Code/Core/Inc/config_ADBMS6830.h
+++ b/AMS_Master_Code/Core/Inc/config_ADBMS6830.h
@@ -4,13 +4,17 @@
 #include "main.h"
 
 #define N_BMS 1
-#define ADBMS_SPI_TIMEOUT 100 // Timeout in ms
+#define N_CELLS 16
+#define ADBMS_MAX_CHIP_TEMP 110 // max temperature of ADBMS6830B (not battery) in C
+#define ADBMS_SPI_TIMEOUT    50 // Timeout in ms
 
-[[maybe_unused]] static inline void mcuAdbmsCSLow() {
+[[maybe_unused, gnu::always_inline]]
+static inline void mcuAdbmsCSLow() {
     HAL_GPIO_WritePin(AMS_CS_GPIO_Port, AMS_CS_Pin, GPIO_PIN_RESET);
 }
 
-[[maybe_unused]] static inline void mcuAdbmsCSHigh() {
+[[maybe_unused, gnu::always_inline]]
+static inline void mcuAdbmsCSHigh() {
     HAL_GPIO_WritePin(AMS_CS_GPIO_Port, AMS_CS_Pin, GPIO_PIN_SET);
 }
 
diff --git a/AMS_Master_Code/Core/Inc/swo_log.h b/AMS_Master_Code/Core/Inc/swo_log.h
index 1eb1e68..ed95e66 100644
--- a/AMS_Master_Code/Core/Inc/swo_log.h
+++ b/AMS_Master_Code/Core/Inc/swo_log.h
@@ -93,8 +93,7 @@ static inline void __swo_print(unsigned int channel, const char *str) {
   }
 }
 
-[[maybe_unused]]
-static void debug_clear_console() {
+static inline void debug_clear_console() {
   for (int i = 0; i < LOG_LEVEL_NOISY; i++) {
 #if USE_ANSI_ESCAPE_CODES
     __swo_print(i, "\033[2J\033[;H"); // clear screen
@@ -104,44 +103,58 @@ static void debug_clear_console() {
   }
 }
 
-#define debug_log(level, msg, ...)                                             \
-  do {                                                                         \
-    if (DEBUG_CHANNEL_ENABLED(level)) {                                        \
-      char __swo_buffer[MAX_MESSAGE_LENGTH];                                   \
-      size_t len =                                                             \
-          snprintf(__swo_buffer, sizeof(__swo_buffer), msg, ##__VA_ARGS__);    \
-      __swo_putc('\n', level);                                                 \
-      /* Print timestamp if enabled */                                         \
-      if (PRINT_TIMESTAMP) {                                                   \
-        char __time_buffer[16];                                                \
-        if (USE_ANSI_ESCAPE_CODES) {                                           \
-          snprintf(__time_buffer, sizeof(__time_buffer),                       \
-                   "\033[90m[%lu]\033[0m ", HAL_GetTick());                    \
-        } else {                                                               \
-          snprintf(__time_buffer, sizeof(__time_buffer), "[%lu] ",             \
-                   HAL_GetTick());                                             \
-        }                                                                      \
-        __swo_print(level, __time_buffer);                                     \
-      }                                                                        \
-      __swo_print(level, log_level_names[level]);                              \
-      __swo_print(level, __swo_buffer);                                        \
-      if (len >= sizeof(__swo_buffer)) {                                       \
-        __swo_print(level, " [message length exceeded] ");                     \
-      }                                                                        \
-    }                                                                          \
-  } while (0)
+[[gnu::format(printf, 2, 3)]]
+static inline void debug_log(enum log_level_t level, const char *msg, ...) {
+  if (!DEBUG_CHANNEL_ENABLED(level)) {
+    return;
+  }
+  
+  char __swo_buffer[MAX_MESSAGE_LENGTH];
+  va_list args;
+  va_start(args, msg);
+  size_t len = vsnprintf(__swo_buffer, sizeof(__swo_buffer), msg, args);
+  va_end(args);
+  
+  __swo_putc('\n', level);
+  
+  /* Print timestamp if enabled */
+  if (PRINT_TIMESTAMP) {
+    char __time_buffer[16];
+    if (USE_ANSI_ESCAPE_CODES) {
+      snprintf(__time_buffer, sizeof(__time_buffer),
+               "\033[90m[%lu]\033[0m ", HAL_GetTick());
+    } else {
+      snprintf(__time_buffer, sizeof(__time_buffer), "[%lu] ",
+               HAL_GetTick());
+    }
+    __swo_print(level, __time_buffer);
+  }
+  
+  __swo_print(level, log_level_names[level]);
+  __swo_print(level, __swo_buffer);
+  
+  if (len >= sizeof(__swo_buffer)) {
+    __swo_print(level, " [message length exceeded] ");
+  }
+}
 
-#define debug_log_cont(level, msg, ...)                                        \
-  do {                                                                         \
-    if (DEBUG_CHANNEL_ENABLED(level)) {                                        \
-      char __swo_buffer[MAX_MESSAGE_LENGTH];                                   \
-      size_t len =                                                             \
-          snprintf(__swo_buffer, sizeof(__swo_buffer), msg, ##__VA_ARGS__);    \
-      __swo_print(level, __swo_buffer);                                        \
-      if (len >= sizeof(__swo_buffer)) {                                       \
-        __swo_print(level, " [message length exceeded] ");                     \
-      }                                                                        \
-    }                                                                          \
-  } while (0)
+[[gnu::format(printf, 2, 3)]]
+static inline void debug_log_cont(enum log_level_t level, const char *msg, ...) {
+  if (!DEBUG_CHANNEL_ENABLED(level)) {
+    return;
+  }
+  
+  char __swo_buffer[MAX_MESSAGE_LENGTH];
+  va_list args;
+  va_start(args, msg);
+  size_t len = vsnprintf(__swo_buffer, sizeof(__swo_buffer), msg, args);
+  va_end(args);
+  
+  __swo_print(level, __swo_buffer);
+  
+  if (len >= sizeof(__swo_buffer)) {
+    __swo_print(level, " [message length exceeded] ");
+  }
+}
 
 #endif /* __SWO_LOG_H */
diff --git a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_Abstraction.h b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_Abstraction.h
index 406e92c..8b1fdca 100644
--- a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_Abstraction.h
+++ b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_Abstraction.h
@@ -8,10 +8,7 @@
 #ifndef INC_ADBMS_ABSTRACTION_H_
 #define INC_ADBMS_ABSTRACTION_H_
 
-#include "ADBMS_CMD_MAKROS.h"
 #include "ADBMS_Driver.h"
-#include "ADBMS_LL_Driver.h"
-#include "main.h"
 
 #define mV_from_ADBMS6830(x) (((((int16_t)(x))) * 0.150) + 1500)
 
diff --git a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_Driver.h b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_Driver.h
index 6c8a037..020b3f1 100644
--- a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_Driver.h
+++ b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_Driver.h
@@ -83,7 +83,7 @@ typedef struct {
     uint32_t bmsID;
 
     struct ADBMS6830_Internal_Status status;
-    uint16_t internalDieTemp;
+    int16_t internalDieTemp;
     uint16_t analogSupplyVoltage;
     uint16_t digitalSupplyVoltage;
     uint16_t sumOfCellMeasurements;
diff --git a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_HighLevel.h b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_HighLevel.h
index 2222503..ced8255 100644
--- a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_HighLevel.h
+++ b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_HighLevel.h
@@ -30,6 +30,4 @@ extern Cell_Module modules[N_BMS];
 extern uint32_t balancedCells;
 extern bool BalancingActive;
 
-extern uint8_t numberofCells;
-
 #endif /* INC_AMS_HIGHLEVEL_H_ */
diff --git a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_LL_Driver.h b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_LL_Driver.h
index 73a0156..cb785ce 100644
--- a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_LL_Driver.h
+++ b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Inc/ADBMS_LL_Driver.h
@@ -9,9 +9,7 @@
 #define ADBMS_LL_DRIVER_H_
 
 #include "config_ADBMS6830.h"
-#include "stm32h7xx_hal.h"
 #include <stdint.h>
-#define TARGET_STM32
 
 
 uint8_t adbmsDriverInit(SPI_HandleTypeDef* hspi);
diff --git a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_Abstraction.c b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_Abstraction.c
index 93f794c..9a219cb 100644
--- a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_Abstraction.c
+++ b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_Abstraction.c
@@ -13,8 +13,6 @@
 #include <stddef.h>
 #include "NTC.h"
 
-extern uint8_t numberofCells;
-
 static const char* const HAL_Statuses[] = {"HAL_OK", "HAL_ERROR", "HAL_BUSY", "HAL_TIMEOUT"};
 
 #define CHECK_RETURN(x)                                                                                                \
@@ -91,8 +89,7 @@ HAL_StatusTypeDef initAMS(SPI_HandleTypeDef* hspi) {
 }
 
 HAL_StatusTypeDef amsWakeUp() {
-    uint8_t buffer[CMD_BUFFER_SIZE(CFG_GROUP_A_SIZE)] = {0};
-    return readCMD(RDCFGA, buffer, CFG_GROUP_A_SIZE);
+    return __pollCMD(PLADC, 100); //wake up ADBMS6830, wait for T_wake = 200 us (100 cycles at 500 kHz)
 }
 
 HAL_StatusTypeDef amsCellMeasurement(Cell_Module (*module)[N_BMS]) {
@@ -264,8 +261,7 @@ HAL_StatusTypeDef amsCheckUnderOverVoltage(Cell_Module (*module)[N_BMS]) {
         (*module)[i].overVoltage = 0;
         (*module)[i].underVoltage = 0;
 
-        for (size_t j = 0; j < numberofCells;
-             j++) { // ov/uv flags are 1-bit flags for each cell C0UV, C0OV, C1UV, C1OV, ...
+        for (size_t j = 0; j < N_CELLS; j++) { // ov/uv flags are 1-bit flags for each cell C0UV, C0OV, C1UV, C1OV, ...
             (*module)[i].underVoltage |= (ov_uv_data >> (j * 2)) & 0x01;
             (*module)[i].overVoltage |= (ov_uv_data >> (j * 2 + 1)) & 0x01;
         }
diff --git a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_HighLevel.c b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_HighLevel.c
index e30a1ed..afd150f 100644
--- a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_HighLevel.c
+++ b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_HighLevel.c
@@ -18,8 +18,6 @@ Cell_Module modules[N_BMS] = {};
 uint32_t balancedCells = 0;
 bool balancingActive = false;
 
-uint8_t numberofCells = 16;
-
 uint8_t packetChecksumFails = 0;
 #define MAX_PACKET_CHECKSUM_FAILS 5
 
@@ -37,7 +35,7 @@ static constexpr ADBMS_DetailedStatus NO_ERROR = {ADBMS_NO_ERROR};
 
 ADBMS_DetailedStatus AMS_Init(SPI_HandleTypeDef* hspi) {
     debug_log(LOG_LEVEL_INFO, "ADBMS6830B HAL - configured for %d controllers and %d cells per controller...", N_BMS,
-              numberofCells);
+              N_CELLS);
     if (initAMS(hspi) != HAL_OK) {
         debug_log(LOG_LEVEL_ERROR, "ADBMS6830B HAL - initialization failed");
         return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_FAULT, -1};
@@ -106,8 +104,7 @@ ADBMS_DetailedStatus AMS_Idle_Loop() {
         return (ADBMS_DetailedStatus){ADBMS_UNDERVOLT, match - 1};
     }
 
-    // TODO: replace with the correct threshold for the internal die temperature
-    if ((match = any(module.internalDieTemp > 28000 || module.status.THSD))) { 
+    if ((match = any(module.internalDieTemp > ADBMS_MAX_CHIP_TEMP || module.status.THSD))) { 
         return (ADBMS_DetailedStatus){ADBMS_INTERNAL_BMS_OVERTEMP, match - 1};
     }
 
diff --git a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_LL_Driver.c b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_LL_Driver.c
index a35c61c..f951a04 100644
--- a/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_LL_Driver.c
+++ b/AMS_Master_Code/Core/Lib/ADBMS6830B_Driver/Core/Src/ADBMS_LL_Driver.c
@@ -15,6 +15,13 @@
 #define INITIAL_COMMAND_PEC        0x0010
 #define INITIAL_DATA_PEC           0x0010 
 
+// CRC polynomial constants
+#define CRC15_POLY 0xC599
+#define CRC10_POLY 0x8F
+#define CRC15_REMAINDER_MASK 0x4000
+#define CRC10_REMAINDER_MASK 0x200
+#define CRC10_RESULT_MASK 0x3FF
+
 SPI_HandleTypeDef* adbmsspi;
 
 uint8_t adbmsDriverInit(SPI_HandleTypeDef* hspi) {
@@ -49,8 +56,8 @@ static uint16_t computeCRC15(const uint8_t* data, size_t length) {
     for (size_t i = 0; i < length; i++) {
         remainder ^= (data[i] << 7);
         for (int b = 0; b < 8; b++) {
-            if (remainder & 0x4000) {
-                remainder = (uint16_t)((remainder << 1) ^ 0xC599);
+            if (remainder & CRC15_REMAINDER_MASK) {
+                remainder = (uint16_t)((remainder << 1) ^ CRC15_POLY);
             } else {
                 remainder <<= 1;
             }
@@ -81,13 +88,12 @@ static uint8_t checkCommandPEC(uint8_t* data, uint8_t datalen) {
 
 static uint16_t computeCRC10(const uint8_t* data, size_t length, bool rx_cmd) {
   uint16_t remainder = INITIAL_DATA_PEC;
-  const uint16_t poly = 0x8F;
 
   for (size_t i = 0; i < length; i++) {
       remainder ^= (uint16_t)(data[i] << 2);
       for (int b = 0; b < 8; b++) {
-          if (remainder & 0x200) {
-              remainder = (uint16_t)((remainder << 1) ^ poly);
+          if (remainder & CRC10_REMAINDER_MASK) {
+              remainder = (uint16_t)((remainder << 1) ^ CRC10_POLY);
           } else {
               remainder <<= 1;
           }
@@ -98,14 +104,14 @@ static uint16_t computeCRC10(const uint8_t* data, size_t length, bool rx_cmd) {
   if (rx_cmd) { 
       remainder ^= (uint16_t)((data[length] & 0xFC) << 2);
       for (int b = 0; b < 6; b++) {
-          if (remainder & 0x200) {
-              remainder = (uint16_t)((remainder << 1) ^ poly);
+          if (remainder & CRC10_REMAINDER_MASK) {
+              remainder = (uint16_t)((remainder << 1) ^ CRC10_POLY);
           } else {
               remainder <<= 1;
           }
       }
   }
-  return (uint16_t)(remainder & 0x3FF);
+  return (uint16_t)(remainder & CRC10_RESULT_MASK);
 }
 
 static uint8_t calculateDataPEC(uint8_t* data, uint8_t datalen) {
@@ -242,10 +248,27 @@ HAL_StatusTypeDef ___readCMD(uint16_t command, uint8_t * buffer, size_t arglen)
     }
   }
 
+  if (arglen == 0) {
+    return HAL_OK; //no data to check
+  }
+
   //check data PEC
   for (size_t i = 0; i < N_BMS; i++) {
     size_t offset = BUFFER_BMS_OFFSET(i, arglen);
     if (checkDataPEC(&buffer[offset], arglen + 2) != 0) {
+      debug_log(LOG_LEVEL_ERROR, "Invalid data PEC when reading BMS %d", i);
+      debug_log(LOG_LEVEL_ERROR, "Received: ");
+      for (size_t j = 0; j < arglen + 2; j++) {
+        debug_log_cont(LOG_LEVEL_ERROR, "%02X ", buffer[offset + j]);
+      }
+      debug_log_cont(LOG_LEVEL_ERROR, "| %02X %02X ", buffer[offset + arglen], buffer[offset + arglen + 1]); //print out the DPEC
+      debug_log(LOG_LEVEL_ERROR, "          DATA ^");
+      //print out spaces until start of DPEC
+      for (size_t j = 0; j < arglen - 1; j++) {
+        debug_log_cont(LOG_LEVEL_ERROR, (arglen < 2) ? "" : "^^^");
+      }
+      debug_log_cont(LOG_LEVEL_ERROR, "^^ ");
+      debug_log_cont(LOG_LEVEL_ERROR, "  PEC ^");
       return HAL_ERROR;
     }
   }
@@ -271,5 +294,5 @@ HAL_StatusTypeDef __pollCMD(uint16_t command, uint8_t waitTime) {
     return status;
   }
 
-  return ((buffer[4 + (N_BMS * 2)] & 0x0F) == 0x0) ? HAL_BUSY : HAL_OK; //SDO goes high when data is ready
+  return ((buffer[sizeof buffer] & 0x0F) == 0x0) ? HAL_BUSY : HAL_OK; //SDO goes high when data is ready
 }
\ No newline at end of file