Skip to content

Commit

Permalink
Manually rebasing
Browse files Browse the repository at this point in the history
  • Loading branch information
A3sanjay committed Nov 11, 2023
1 parent 83a8c05 commit 998ef1a
Showing 1 changed file with 243 additions and 0 deletions.
243 changes: 243 additions & 0 deletions projects/bms_carrier/src/cell_sense.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
#include "cell_sense.h"

#include <string.h>

#include "current_sense.h"
#include "exported_enums.h"
#include "fault_bps.h"
#include "log.h"
#include "ltc_afe_impl.h"
#include "soft_timer.h"
#include "status.h"

// For now, transition to IDLE
// TODO: Create some kind of fault mechanism if driver function fails
bool raise_fault = false;

FSM(ltc_afe_fsm, NUM_LTC_AFE_FSM_STATES);

static CellSenseStorage s_storage = { 0 };

static void prv_extract_cell_result(uint16_t *result_arr, size_t len, void *context) {
memcpy(s_storage.readings->voltages, result_arr, sizeof(s_storage.readings->voltages));

bool fault = false;
for (size_t i = 0; i < len; i++) {
// s_storage.total_voltage += s_storage.readings->voltages[i];
if (s_storage.readings->voltages[i] < s_storage.settings.undervoltage_dmv ||
s_storage.readings->voltages[i] > s_storage.settings.overvoltage_dmv) {
fault = true;
}
}

// TODO: Find what we should do when encountering faulty results
if (fault) {
fault_bps_set(EE_BPS_STATE_FAULT_AFE_CELL);
} else {
fault_bps_clear(EE_BPS_STATE_FAULT_AFE_CELL);
}
}

static void prv_extract_aux_result(uint16_t *result_arr, size_t len, void *context) {
memcpy(s_storage.readings->temps, result_arr, sizeof(s_storage.readings->temps));

uint16_t threshold = s_storage.settings.discharge_overtemp_dmv;
if (current_sense_is_charging()) threshold = s_storage.settings.charge_overtemp_dmv;

for (size_t i = 0; i < len; ++i) {
if (s_storage.readings->temps[i] > threshold) {
// TODO: Find what we should do when encountering faulty results
fault_bps_set(EE_BPS_STATE_FAULT_AFE_TEMP);
return;
}
}

fault_bps_clear(EE_BPS_STATE_FAULT_AFE_TEMP);
}

static void prv_afe_idle_output(void *context) {
if (raise_fault) {
// TODO: Implement some kind of error handling
}
LOG_DEBUG("Transitioned to IDLE state.\n");
}

static void prv_afe_idle_input(Fsm *fsm, void *context) {
LtcAfeStorage *afe = context;
// Always transition to trigger_aux. Might remove this state tbh
if (!raise_fault) {
fsm_transition(fsm, LTC_AFE_TRIGGER_CELL_CONV);
}
}

static void prv_afe_trigger_cell_conv_output(void *context) {
LtcAfeStorage *afe = context;
StatusCode ret = ltc_afe_impl_trigger_cell_conv(afe);
if (ret != STATUS_CODE_OK) {
raise_fault = true;
}
afe->time_elapsed = 1000 * (xTaskGetTickCount() / 1024);
LOG_DEBUG("Transitioned to TRIGGER CELLS CONVERSION state.\n");
}

static void prv_afe_trigger_cell_conv_input(Fsm *fsm, void *context) {
// Transition to read_cells or idle state
LtcAfeStorage *afe = context;
if (raise_fault) {
fsm_transition(fsm, LTC_AFE_IDLE);
}

uint16_t current_time = 1000 * (xTaskGetTickCount() / 1024);
if (current_time - afe->time_elapsed > LTC_AFE_FSM_CELL_CONV_DELAY_MS) {
afe->retry_count = 0;
fsm_transition(fsm, LTC_AFE_READ_CELLS);
}
}

static void prv_afe_read_cells_output(void *context) {
LtcAfeStorage *afe = context;

StatusCode ret = ltc_afe_impl_read_cells(afe);

if (ret != STATUS_CODE_OK) {
raise_fault = true;
}
LOG_DEBUG("Transitioned to READ CELLS state.\n");
}

static void prv_afe_read_cells_input(Fsm *fsm, void *context) {
// Transition to trigger_aux if no faults have occurred
LtcAfeStorage *afe = context;
if (raise_fault) {
if (afe->retry_count < LTC_AFE_FSM_MAX_RETRY_COUNT) {
afe->retry_count++;
fsm_transition(fsm, LTC_AFE_READ_CELLS);
} else {
fsm_transition(fsm, LTC_AFE_IDLE);
}
}
prv_extract_cell_result(afe->cell_voltages, afe->settings.num_cells,
afe->settings.result_context);
fsm_transition(fsm, LTC_AFE_TRIGGER_AUX_CONV);
}

static void prv_afe_trigger_aux_conv_output(void *context) {
LtcAfeStorage *afe = context;
uint32_t device_cell = afe->device_cell;
StatusCode ret = ltc_afe_impl_trigger_aux_conv(afe, device_cell);
if (ret == STATUS_CODE_OK) {
afe->aux_index = device_cell;
} else {
raise_fault = true;
}
afe->time_elapsed = 1000 * (xTaskGetTickCount() / 1024);
LOG_DEBUG("Transitioned to TRIGGER AUX CONVERSION state.");
}

static void prv_afe_trigger_aux_conv_input(Fsm *fsm, void *context) {
// Transition to read_aux or idle state
LtcAfeStorage *afe = context;
if (raise_fault) {
fsm_transition(fsm, LTC_AFE_IDLE);
}

uint16_t current_time = 1000 * (xTaskGetTickCount() / 1024);
if (current_time - afe->time_elapsed > LTC_AFE_FSM_AUX_CONV_DELAY_MS) {
afe->retry_count = 0;
fsm_transition(fsm, LTC_AFE_READ_AUX);
}
}

static void prv_afe_read_aux_output(void *context) {
LtcAfeStorage *afe = context;
StatusCode ret = ltc_afe_impl_read_aux(afe, afe->device_cell);
if (ret == STATUS_CODE_OK) {
afe->device_cell++;
} else {
raise_fault = true;
}
LOG_DEBUG("Transitioned to READ AUX OUTPUT state.");
}

static void prv_afe_read_aux_input(Fsm *fsm, void *context) {
// Transition to aux_complete, read_aux, trigger_aux_conv, or idle state
LtcAfeStorage *afe = context;
if (raise_fault) {
if (afe->retry_count < LTC_AFE_FSM_MAX_RETRY_COUNT) {
afe->retry_count++;
fsm_transition(fsm, LTC_AFE_READ_AUX);
} else {
fsm_transition(fsm, LTC_AFE_IDLE);
}
}
if (afe->device_cell == afe->settings.num_thermistors) {
afe->device_cell = 0;
fsm_transition(fsm, LTC_AFE_AUX_COMPLETE);
} else {
fsm_transition(fsm, LTC_AFE_TRIGGER_AUX_CONV);
}
}

static void prv_afe_aux_complete_output(void *context) {
LOG_DEBUG("Transitioned to AUX COMPLETE state.");
}

static void prv_afe_aux_complete_input(Fsm *fsm, void *context) {
// We can add broadcasting functionality here later (MVP for now)
LtcAfeStorage *afe = context;
// 12 aux conversions complete - the array should be fully populated
prv_extract_aux_result(afe->aux_voltages, afe->settings.num_cells, afe->settings.result_context);
}

// Declare states
static FsmState s_ltc_afe_state_list[NUM_LTC_AFE_FSM_STATES] = {
STATE(LTC_AFE_IDLE, prv_afe_idle_input, prv_afe_idle_output),
STATE(LTC_AFE_TRIGGER_CELL_CONV, prv_afe_trigger_cell_conv_input,
prv_afe_trigger_cell_conv_output),
STATE(LTC_AFE_READ_CELLS, prv_afe_read_cells_input, prv_afe_read_cells_output),
STATE(LTC_AFE_TRIGGER_AUX_CONV, prv_afe_trigger_aux_conv_input, prv_afe_trigger_aux_conv_output),
STATE(LTC_AFE_READ_AUX, prv_afe_read_aux_input, prv_afe_read_aux_output),
STATE(LTC_AFE_AUX_COMPLETE, prv_afe_aux_complete_input, prv_afe_aux_complete_output),
};

// Declare transitions
static FsmTransition s_ltc_afe_transitions[NUM_LTC_AFE_FSM_TRANSITIONS] = {
TRANSITION(LTC_AFE_IDLE, LTC_AFE_TRIGGER_CELL_CONV),
TRANSITION(LTC_AFE_TRIGGER_CELL_CONV, LTC_AFE_READ_CELLS),
TRANSITION(LTC_AFE_TRIGGER_CELL_CONV, LTC_AFE_IDLE),
TRANSITION(LTC_AFE_READ_CELLS, LTC_AFE_IDLE),
TRANSITION(LTC_AFE_READ_CELLS, LTC_AFE_TRIGGER_AUX_CONV),
TRANSITION(LTC_AFE_READ_CELLS, LTC_AFE_READ_CELLS),
TRANSITION(LTC_AFE_TRIGGER_AUX_CONV, LTC_AFE_READ_AUX),
TRANSITION(LTC_AFE_TRIGGER_AUX_CONV, LTC_AFE_IDLE),
TRANSITION(LTC_AFE_READ_AUX, LTC_AFE_AUX_COMPLETE),
TRANSITION(LTC_AFE_READ_AUX, LTC_AFE_READ_AUX),
TRANSITION(LTC_AFE_READ_AUX, LTC_AFE_TRIGGER_AUX_CONV),
TRANSITION(LTC_AFE_READ_AUX, LTC_AFE_IDLE),
TRANSITION(LTC_AFE_AUX_COMPLETE, LTC_AFE_TRIGGER_CELL_CONV),
};

StatusCode prv_init_ltc_afe_fsm(LtcAfeStorage *afe) {
FsmSettings settings = {
.state_list = s_ltc_afe_state_list,
.transitions = s_ltc_afe_transitions,
.num_transitions = NUM_LTC_AFE_FSM_TRANSITIONS,
.initial_state = LTC_AFE_IDLE,
};
fsm_init(ltc_afe_fsm, settings, afe);
return STATUS_CODE_OK;
}

StatusCode cell_sense_init(const CellSenseSettings *settings, AfeReadings *afe_readings,
LtcAfeStorage *afe, LtcAfeSettings *ltc_settings) {
s_storage.afe = afe;
s_storage.readings = afe_readings;
memset(afe_readings, 0, sizeof(AfeReadings));
memcpy(&s_storage.settings, settings, sizeof(CellSenseSettings));
status_ok_or_return(ltc_afe_init(afe, ltc_settings));
return prv_init_ltc_afe_fsm(afe);
}

StatusCode ltc_afe_toggle_cell_discharge(LtcAfeStorage *afe, uint16_t cell, bool discharge) {
return ltc_afe_impl_toggle_cell_discharge(afe, cell, discharge);
}

0 comments on commit 998ef1a

Please sign in to comment.