/*
 * Slave_Monitoring.c
 *
 *  Created on: Jun 15, 2022
 *      Author: max
 */

#include "Slave_Monitoring.h"

#include "AMS_Errorcodes.h"
#include "main.h"

#include "stm32g4xx_hal.h"
#include "stm32g4xx_hal_gpio.h"

#include <string.h>

SlaveHandler slaves[NUMBEROFSLAVES];

void initSlaves() {
  HAL_GPIO_WritePin(SLAVES_ENABLE_GPIO_Port, SLAVES_ENABLE_Pin, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(BOOT0_FF_DATA_GPIO_Port, BOOT0_FF_DATA_Pin, GPIO_PIN_RESET);

  for (int i = 0; i < NUMBEROFSLAVES + 5; i++) {
    HAL_GPIO_WritePin(BOOT0_FF_CLK_GPIO_Port, BOOT0_FF_CLK_Pin, GPIO_PIN_SET);
    HAL_Delay(1);
    HAL_GPIO_WritePin(BOOT0_FF_CLK_GPIO_Port, BOOT0_FF_CLK_Pin, GPIO_PIN_RESET);
    HAL_Delay(1);
  }

  HAL_Delay(5);
  HAL_GPIO_WritePin(SLAVES_ENABLE_GPIO_Port, SLAVES_ENABLE_Pin, GPIO_PIN_SET);

  for (int n = 0; n < NUMBEROFSLAVES; n++) {
    for (int i = 0; i < NUMBEROFTEMPS; i++)
      slaves[n].cellTemps[i] = 0;

    for (int j = 0; j < NUMBEROFCELLS; j++)
      slaves[n].cellVoltages[j] = 32768;

    slaves[n].error = 0;
    slaves[n].timeout = 0;
    slaves[n].timestamp = HAL_GetTick();
    slaves[n].slaveID = n;
    for (int i = 0; i < SLAVE_HEARTBEAT_FRAMES; i++) {
      slaves[n].frame_timestamps[i] = HAL_GetTick();
    }
  }
}

uint8_t checkSlaveTimeout() {
  if (HAL_GetTick() < 10000) {
    return 0;
  }

  for (int n = 0; n < NUMBEROFSLAVES; n++) {
    if (((int)(HAL_GetTick() - slaves[n].timestamp)) > SLAVETIMEOUT) {
      slaves[n].timeout = 1;

      AMSErrorHandle timeouterror;
      timeouterror.errorcode = SlavesTimeoutError;
      timeouterror.errorarg[0] = n;

      AMS_Error_Handler(&timeouterror);
      return 1;
    }

    if (slaves[n].error) {
      AMSErrorHandle errorframe;
      errorframe.errorcode = SlavesErrorFrameError;
      memcpy(errorframe.errorarg, slaves[n].error_frame, 7);
      AMS_Error_Handler(&errorframe);
      return 1;
    }

    for (int i = 0; i < SLAVE_HEARTBEAT_FRAMES; i++) {
      if ((int)(HAL_GetTick() - slaves[n].frame_timestamps[i]) >
          SLAVETIMEOUT * 2) {
        slaves[n].timeout = 1;
        AMSErrorHandle timeouterror;
        timeouterror.errorcode = SLAVES_FRAME_TIMEOUT_ERROR;
        timeouterror.errorarg[0] = n;
        timeouterror.errorarg[1] = i;
        AMS_Error_Handler(&timeouterror);
        return 1;
      }
    }

    int working_cell_temps = 0;
    for (int i = 0; i < NUMBEROFTEMPS; i++) {
      if (slaves[n].cellTemps[i] != 0) {
        working_cell_temps++;
      }
    }
    if (working_cell_temps < SLAVE_MIN_TEMP_SENSORS) {
      AMSErrorHandle temperror;
      temperror.errorcode = SLAVES_TOO_FEW_TEMPS;
      temperror.errorarg[0] = n;
      AMS_Error_Handler(&temperror);
      return 1;
    }
  }
  return 0;
}
