#include "main.h"
#include <stdio.h>
#include <math.h>

ADC_HandleTypeDef hadc1; 
UART_HandleTypeDef huart2;
void SystemClock_Config(void);
static void MX_GPIO_Init(void); 
static void MX_USART2_UART_Init(void);
static void MX_ADC1_Init(void);

int n=1; //n uchovava hodnotu, na ktere baterii se nachazime
float voltage[4]; //Vektor hodnot napeti
uint32_t adcVal[4]; //Vektor hodnot napeti v bitove podobe

int main(void)
{
  HAL_Init(); //Inicializace ovladani periferii
  SystemClock_Config(); //Inicializace interniho casovace
  MX_GPIO_Init(); //Inicializace vst. a vys. pinu
  MX_USART2_UART_Init(); //Inicializace UART
  MX_ADC1_Init(); //Inicializace AD prevodniku
  while (1) 
  {
  	if(err=1) //Pokud se vyskytuje problem
	{Err_Message(); //Smycka vystrazne zpravy}
	else //Nevyskytuje se problem
	{
	  if (n==1) //BAT1 -> MUX_IN(A4) - S2=1, S1=0, S0=0
	  {
		 Connect_Disconnect_BAT1(); //Pripojeni BAT1
		 Read_And_Balance();  //Vyhodnoceni hodnoty a zapnuti
		 //balancovani (pri potrebe), jinak pokracuje na dalsi
		 Connect_Disconnect_BAT1(); //Odpojeni BAT1
	  }
	  else if(n==2) //BAT2 -> MUX_IN(A6) - S2=1, S1=1, S0=0
	  {
		 Connect_Disconnect_BAT2();
		 Read_And_Balance();
		 Connect_Disconnect_BAT2();
	  }
	  else if(n==3) //BAT3 -> MUX_IN(A7) - S2=1, S1=1, S0=1
	  {
		  Connect_Disconnect_BAT3();
		  Read_And_Balance();
		  Connect_Disconnect_BAT3();
	  }
	  else if(n==4) //BAT4 -> MUX_IN(A5) - S2=1, S1=0, S0=1
	  {
		  Connect_Disconnect_BAT4();
		  Read_And_Balance();
		  Connect_Disconnect_BAT4();
	  }
	  else
	  {
		  n=1;
		  Send_Voltage_Data(); //Odeslani dat napeti a SOC
		  Send_SOC_Data();     //pres UART na konci cyklu
	  }
	}
  }
}
void Read_And_Balance() 
{
	HAL_ADC_Start(&hadc1); //Zacina prevod AD
	if(HAL_ADC_PollForConversion(&hadc1, 50) == HAL_OK)
	{ //Pokud probehl prevod v pruhebu 50 ms v poradku,
	  //lze pokracovat dale v algoritmu
		adcVal[n-1] = HAL_ADC_GetValue(&hadc1);
		voltage[n-1]=(((adcVal[n-1]*3.3)/4095)/0.75);
    //V=(((ADC_Bits*MCU_V)/ADC_resolution)/Correction_V_Ratio)
        if(Terminate(voltage[n-1])==1){return;}
        else{
    		if(voltage[n-1] >= 3.6) //Podminka zapnuti balancovani
    		{
    			 Bal_SWn(); //Turn on balancing, pockat a vypnout
    			 n++; //Inkrementace = pokracovani na dalsi baterii
    		}
    		else{n++;}
    	}
	}
}
void Connect_Disconnect_BAT1(void) //BAT1 -> A4
{                                  //S2=1, S1=0, S0=0
	HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_10); //S2 = 1
}
void Connect_Disconnect_BAT2(void) //BAT2 -> A6
{                                  //S2=1, S1=1, S0=0
	HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_10); //S2 = 1
	HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_3); //S1 = 1
}
void Connect_Disconnect_BAT3(void) //BAT3 -> A7
{                                  //S2=1, S1=1, S0=1
	HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_10); //S2 = 1
	HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_3); //S1 = 1
	HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5); //S0 = 1
}
void Connect_Disconnect_BAT4(void) //BAT4 -> A5
{                                  //S2=1, S1=0, S0=1
	HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_10); //S2 = 1
	HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5); //S0 = 1
}

void Bal_SWn(void)
{
	int Time = 2000; //Cas je zvolen pouze pro dobre zobrazeni
	if(n==1)
	{
		HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_10); //SW1=LED1
		HAL_Delay(Time); //Probiha balancovani
		HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_10); //SW1=LED1
	}
	else if(n==2)
	{
		HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_8); //SW2=LED2
		HAL_Delay(Time);
		HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_8); //SW2=LED2
	}
	else if(n==3)
	{
		HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_9); //SW3=LED3
	    HAL_Delay(Time);
	    HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_9); //SW3=LED3
	}
	else
	{
		HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_7); //SW4=LED4
		HAL_Delay(Time);
		HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_7); //SW4=LED4
	}
}
void Send_Voltage_Data(void)
{
	uint8_t B1V_txt[12] = " B1Voltage  ",
	B2V_txt[12] = " B2Voltage  ", 
	B3V_txt[12] = " B3Voltage  ", 
	B4V_txt[12] = " B4Voltage  ";
	char charVoltage_1[7] = "0000000"; //Deklarace pripravenych
	char charVoltage_2[7] = "0000000"; //promennych
	char charVoltage_3[7] = "0000000";
	char charVoltage_4[9] = "000000000";
	sprintf(charVoltage_1, " %.2f\r\n",voltage[0]);
	//Dojde ke slozeni vybraneho textu a aktualniho napeti,
	//ktere je zaokrouhleno na 2 desetinna mista
	HAL_UART_Transmit(&huart2, B1V_txt, 12, 10);
	//Odeslani oznaceni napeti
	HAL_UART_Transmit(&huart2,(uint8_t *) charVoltage_1, 7, 10);
	//Odeslani napeti, ktere je prevedeno do unsigned int

	sprintf(charVoltage_2, " %.2f\r\n",voltage[1]);
	HAL_UART_Transmit(&huart2, B2V_txt, 12, 10);
	HAL_UART_Transmit(&huart2,(uint8_t *) charVoltage_2, 7, 10);

	sprintf(charVoltage_3, " %.2f\r\n",voltage[2]);
	HAL_UART_Transmit(&huart2, B3V_txt, 12, 10);
	HAL_UART_Transmit(&huart2,(uint8_t *) charVoltage_3, 7, 10);

	sprintf(charVoltage_4, " %.2f\r\n\r\n",voltage[3]);
	HAL_UART_Transmit(&huart2, B4V_txt, 12, 10);
	HAL_UART_Transmit(&huart2,(uint8_t *) charVoltage_4, 9, 10);
}
void Send_SOC_Data(void)
{
	uint8_t SOC1_txt[9] = " B1_SOC  ",
	SOC2_txt[9] = " B2_SOC  ",
	SOC3_txt[9] = " B3_SOC  ",
	SOC4_txt[9] = " B4_SOC  ";
	float SOC1, SOC2, SOC3, SOC4, maxBatVoltage = 4.2;
	char charSOC_1[7] = "0000000";
	char charSOC_2[7] = "0000000";
	char charSOC_3[7] = "0000000";
	char charSOC_4[11] = "00000000000"; //Velikost posledniho je 
	                             //zvolena vetsi pouze pro lepsi
	                          //demonstraci pri vypisovani na PC
	SOC1=(voltage[0]*100)/maxBatVoltage; //Pouze demonstracni
	                                     //vypocet SOC
	...//Dale kod pokracuje obdobnym zpusobem
	   //jako pri "void Send_Voltage_Data()"                  
}
int Terminate(float value)
{
	if(value >= 4.4)
	{
		HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_8);
		err=1;    //Vypnuti hlavniho spinace a tim
		return 1; //odpojeni vsech baterii -> nabijeni
	}
	else{return 0;}
}
void Err_Message()
{
    HAL_UART_Transmit(&huart2, "Critical Voltage!", 17, 10);
    HAL_Delay(500); //Odesilani vystrazne zpravy kazdych 500ms
}