Program Listing for File bms_fsm.c

Return to documentation for file (mainboard/Src/bms_fsm.c)

#include "bms_fsm.h"

#include "cli_bms.h"
#include "error.h"
#include "main.h"
#include "mainboard_config.h"
#include "pack/pack.h"
#include "pack/voltage.h"
#include "peripherals/can_comm.h"
#include "tim.h"

#include <inttypes.h>
#include <stdio.h>
#include <string.h>

//------------------------------Declarations------------------------------------------
void bms_set_led_blinker();
void bms_blink_led();

void _idle_entry(fsm FSM);
void _idle_handler(fsm FSM, uint8_t event);
void _idle_exit(fsm FSM);
void _precharge_entry(fsm FSM);
void _precharge_handler(fsm FSM, uint8_t event);
void _precharge_exit(fsm FSM);
void _on_entry(fsm FSM);
void _on_handler(fsm FSM, uint8_t event);
void _on_exit(fsm FSM);
void _halt_entry(fsm FSM);
void _halt_run(fsm FSM);
void _halt_handler(fsm FSM, uint8_t event);

bms_fsm bms;

void bms_fsm_init() {
    bms.fsm = fsm_init(BMS_NUM_STATES, BMS_EV_NUM, &bms_blink_led, &bms_set_led_blinker);

    fsm_state state;
    state.run     = NULL;
    state.handler = _idle_handler;
    state.entry   = _idle_entry;
    state.exit    = _idle_exit;
    fsm_set_state(bms.fsm, BMS_IDLE, &state);

    state.handler = _precharge_handler;
    state.entry   = _precharge_entry;
    state.exit    = _precharge_exit;
    fsm_set_state(bms.fsm, BMS_PRECHARGE, &state);

    state.handler = _on_handler;
    state.entry   = _on_entry;
    state.exit    = _on_exit;
    fsm_set_state(bms.fsm, BMS_ON, &state);

    state.handler = _halt_handler;
    state.entry   = _halt_entry;
    state.run     = _halt_run;
    state.exit    = NULL;
    fsm_set_state(bms.fsm, BMS_HALT, &state);

    HAL_TIM_Base_Start_IT(&HTIM_BMS);
    fsm_start(bms.fsm);

    bms.led.port = STATE_LED_GPIO;
    bms.led.pin  = STATE_LED_PIN;
    bms.led.time = HAL_GetTick();

    bms_set_led_blinker();
}

void bms_set_led_blinker() {
    uint8_t pattern_count                    = 0;
    uint8_t state_count                      = 0;
    uint32_t state                           = fsm_get_state(bms.fsm);
    uint16_t pattern[(BMS_NUM_STATES)*2 + 1] = {0};

    pattern[pattern_count++] = 200;  // Off
    while (state_count < state) {
        pattern[pattern_count++] = 200;  // On
        pattern[pattern_count++] = 200;  // Off
        state_count++;
    }
    pattern[pattern_count++] = 1000;  // Big off

    BLINK_SET_PATTERN(bms.led, pattern, pattern_count);
    BLINK_SET_ENABLE(bms.led, true);
    BLINK_SET_REPEAT(bms.led, true);

    blink_reset(&(bms.led));
    HAL_GPIO_WritePin(bms.led.port, bms.led.pin, GPIO_PIN_SET);
}
void bms_blink_led() {
    blink_run(&bms.led);
}

void _idle_entry(fsm FSM) {
    can_send(ID_TS_STATUS);
}

void _idle_handler(fsm FSM, uint8_t event) {
    switch (event) {
        case BMS_EV_TS_ON:
            fsm_transition(FSM, BMS_PRECHARGE);
            break;
        case BMS_EV_HALT:
            fsm_transition(FSM, BMS_HALT);
            break;
    }
}

void _idle_exit(fsm FSM) {
}

void _precharge_entry(fsm FSM) {
    // Precharge
    pack_set_pc_start();

    uint32_t cnt = __HAL_TIM_GET_COUNTER(&HTIM_BMS);
    __HAL_TIM_SET_COMPARE(&HTIM_BMS, TIM_CHANNEL_1, (cnt + PRECHARGE_CHECK_INTERVAL * 10));
    __HAL_TIM_SET_COMPARE(&HTIM_BMS, TIM_CHANNEL_2, (cnt + PRECHARGE_TIMEOUT * 10));

    HAL_TIM_OC_Start_IT(&HTIM_BMS, TIM_CHANNEL_1);
    HAL_TIM_OC_Start_IT(&HTIM_BMS, TIM_CHANNEL_2);

    cli_bms_debug("Entered precharge", 18);
}

void _precharge_handler(fsm FSM, uint8_t event) {
    switch (event) {
        case BMS_EV_PRECHARGE_TIMEOUT:
            cli_bms_debug("Precharge timeout", 18);
            // send timeout warning
        case BMS_EV_TS_OFF:
            fsm_transition(FSM, BMS_IDLE);
            break;

        case BMS_EV_PRECHARGE_CHECK:
            char c[5] = {'\0'};
            itoa(voltage_get_bus() / voltage_get_internal() * PRECHARGE_VOLTAGE_THRESHOLD, c, 10);
            cli_bms_debug(c, 5);

            if (voltage_get_bus() >= voltage_get_internal() * PRECHARGE_VOLTAGE_THRESHOLD) {
                fsm_transition(bms.fsm, BMS_ON);
                cli_bms_debug("Precharge ok", 18);
            }
            break;
        case BMS_EV_HALT:
            fsm_transition(FSM, BMS_HALT);
            break;
    }
}

void _precharge_exit(fsm FSM) {
    HAL_TIM_OC_Stop_IT(&HTIM_BMS, TIM_CHANNEL_1);
    HAL_TIM_OC_Stop_IT(&HTIM_BMS, TIM_CHANNEL_2);
}

void _on_entry(fsm FSM) {
    pack_set_precharge_end();
}

void _on_handler(fsm FSM, uint8_t event) {
    switch (event) {
        case BMS_EV_TS_OFF:
            fsm_transition(FSM, BMS_IDLE);
            break;
        case BMS_EV_HALT:
            fsm_transition(FSM, BMS_HALT);
            break;
    }
}

void _on_exit(fsm FSM) {
    pack_set_ts_off();
}

void _halt_entry(fsm FSM) {
    // bms_set_fault(&data->bms);
    HAL_GPIO_WritePin(BMS_FAULT_GPIO_Port, BMS_FAULT_Pin, GPIO_PIN_RESET);

    HAL_GPIO_WritePin(GPIO4_GPIO_Port, GPIO4_Pin, GPIO_PIN_SET);
    //can_send_error(&hcan, data->error, data->error_index, &data->pack);
    //cli_bms_debug("HALT", 5);
}

void _halt_run(fsm FSM) {
    if (error_get_fatal() == 0) {
        fsm_trigger_event(FSM, BMS_EV_NO_ERRORS);
    }
}

void _halt_handler(fsm FSM, uint8_t event) {
    switch (event) {
        case BMS_EV_NO_ERRORS:
            fsm_transition(FSM, BMS_IDLE);
            break;
    }
}