/*
 * myapp.c
 *
 *  Created on: 26. 10. 2021
 *      Author: student
 */

#include "main.h"
#include "myapp.h"

#include <math.h>

#include "mydsp.h"

#include "dataAcq.h"

// #define BUFFER_SIZE 2
#define DATA_SIZE 2 // Velikost přenášených dat

uint8_t my_index = 0;
uint8_t data[DATA_SIZE]; // Pole pro přijatá data


rawADCData_typedef rawADCData;
analogData_typedef analogData;

fltLoPass_typedef filter1;

uint16_t SMP[N_SMP];
int Arr_Tim2 = 7119;

/*
fltLoPass_typedef menic;
fltLoPass_typedef RLobvod;
float RLobvodRa;
*/
regPI_typedef regI;
regPI_typedef regU;
uint8_t DClink_ON;
float iz, ia, ua, uar, uaz, uz, Uc, d;
uint8_t freq = 50;
uint16_t value = 0;


//uint8_t rxBuffer[BUFFER_SIZE]; // globální proměnná pro buffer na přijatá data

__IO uint32_t     Transfer_Direction = 0;

/*
  *  moje inicializace
  */
void myInit(void)
{
	SinCalc();

	  // Nastavime a povolime DMA
	  LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_1,
			  (uint32_t)&ADC12_COMMON->CDR, // ukazatel pretypovany na uint32  (*ADC12_COMMON).CDR je ekvivalentní k ADC12_COMMON->CDR
			  (uint32_t)&rawADCData,
			  LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
	  LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, rawADCsmpNum); // nastavi pocet prenosu DMA

	  LL_DMA_ClearFlag_TC1(DMA1);                   // preventivni mazani priznaku

	  LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);   // povoleni preruseni na konci davky prenosu DMA

	  LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);


	  // Povolime a spustime ADC
	  LL_ADC_StartCalibration(ADC1, LL_ADC_SINGLE_ENDED);
	  while(LL_ADC_IsCalibrationOnGoing(ADC1))
		  ;
	  LL_ADC_StartCalibration(ADC2, LL_ADC_SINGLE_ENDED);
	  while(LL_ADC_IsCalibrationOnGoing(ADC2))
	      ;
	  LL_ADC_EnableInternalRegulator(ADC1);
	  uint32_t delayCycles = 72000;
	  while(--delayCycles)
	  ;
	  LL_ADC_Enable(ADC1);
	  LL_ADC_Enable(ADC2);
	  LL_ADC_REG_StartConversion(ADC1);
	  LL_ADC_REG_StartConversion(ADC2);

	  // Spustime a povolime vystupy TIM1
	  LL_TIM_EnableCounter(TIM1);
	  LL_TIM_SetRepetitionCounter(TIM1, 1U);
	  // Spustime a povolime vystupy TIM1
	 	  LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH2 | LL_TIM_CHANNEL_CH3 |
	 			                        LL_TIM_CHANNEL_CH2N| LL_TIM_CHANNEL_CH3N);
	 	  LL_TIM_EnableAllOutputs(TIM1);
	 	  LL_TIM_OC_SetCompareCH3(TIM1, 0U);

	 	  // Inicializace pro sinusový měnič

		  LL_TIM_ClearFlag_UPDATE(TIM2);   // Mazat příznak přerušení
		  LL_TIM_EnableIT_UPDATE(TIM2);    // Povolení přerušení (UPDATE)
		  LL_TIM_EnableCounter(TIM2);      // Spuštění timeru
		  // Spustime a povolime vystupy TIM1
		  //LL_TIM_EnableDMAReq_UPDATE(TIM1);
		  /*
		   * Pokud se prvni zadefinuje repetition counter na 1 a pote zapne counter dojde k UPDATE v dolni uvrati
		   * Pokud se prvni zapne counter a pote zadefinuje repetition counter na 1 dojde k UPDATE v horni uvrati
		   */
		  LL_TIM_SetRepetitionCounter(TIM1, 1);
		  LL_TIM_EnableCounter(TIM1);
		  LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH1 |
				                        LL_TIM_CHANNEL_CH1N);
		  LL_TIM_EnableAllOutputs(TIM1);

		 // LL_TIM_EnableDMAReq_UPDATE(TIM1);

		  TIM1->CCR1 = 500;

	  /*
	   * inicializace softwaru
	   */
	 // float fpwm = 10e3f;
	  //vzorkovací perioda
	 // regI.Ts = RLobvod.Ts = menic.Ts = filter1.Ts =  100e-6f;         //
	  regI.Ts = filter1.Ts =  1/240e3f; // 1/2*120e3f;  //(5/4)*100e-6f; // časová konstanta měniče
	  filter1.tau = 0.5f;

	  // filtr pro potenciometr
	  fltLoPass_init(&filter1);

	  /*
	   * Parametry regulovane soustavy
	   *//*
	  menic.tau = menic.Ts*1.5f;
      RLobvod.tau = 4.5e-3f;
      RLobvodRa = 1.0f/0.5f;
      fltLoPass_init(&menic);
      fltLoPass_init(&RLobvod);
      */
      /*
       * Parametry regulatoru proudu
       */
	  float taua =2.29e-3;
	  float R = 0.67;
      regI.Ti = 1/(taua);//RLobvod.tau;
      regI.Kp = R*taua/(2*regI.Ts); //RLobvod.tau/(RLobvodRa * 2.0f * menic.tau);
      regI.lim_h = 10.0f;
      regI.lim_l = -10.0f;
      regPI_init(&regI);
      /*
       * Parametry regulatoru napeti
       */
      float C = 33e-6;
      regU.Ts = 4.8*regI.Ts;
      //regU.Ti = 1/(4*regU.Ts);//RLobvod.tau;
      regU.Ti = 8/(4*regU.Ts);//RLobvod.tau;
      regU.Kp = 5*C/(2*regU.Ts); //RLobvod.tau/(RLobvodRa * 2.0f * menic.tau);
      regU.lim_h = 80.0f;
      regU.lim_l = 0.0f;
      regPI_init(&regU);

      uz = 50; // nastavené napětí



}

/*
 * Obsluha preruseni DMA - synchronni s PWM
 * f_pwm = 10kHz
 */
void myPeriodicISR(void)
{
  analogData.Ia = (float)rawADCData.in.Iph3*0.03168945f; //0.00523f;  // PC2 ADC1 IN 8
  analogData.Vc = (float)rawADCData.in.Vph1*0.03168945f; // změna PA6 ADC2 IN3 // PA4 ADC2 IN 1/// zpětná vazba napětí
  analogData.Vdc1 = (float)rawADCData.in.VDC1*0.006915f; //
  analogData.Vdc2 = (float)rawADCData.in.VDC2*0.006915f;
  analogData.Pot = (float)rawADCData.in.Pot*(1.0f/(1u<<12));
  analogData.Vrefadc = (float)rawADCData.in.Vrefint*(3.3f/(1u<<12));
  //pouziti filtru
  fltLoPass(analogData.Pot, &filter1);
  // TIM1->CCR2 = (int)analogData.Pot*7199;
  // regulator proudu
  //uaz = regPI(iz - ia, &regI);
  ia = analogData.Ia;
  ua = analogData.Vc;
  // výpočet střídy

  //LL_TIM_OC_SetCompareCH2(TIM1, (uint32_t)(d*TIM1->ARR));

  // limitace střídy na rozumný rozsah
  uar = regPI(uz - analogData.Vc, &regU);
  //uar = regPI(iz - ia, &regI);
  d = uar / uz; //Uc
  d = d >= 1.0f ? 1.0f : d <= 0.0f ? 0.0f : d;
  //d = 1-d;
  DAC_SetOutputVoltage(4095*(d)); // 0 až 4095
  LL_TIM_OC_SetCompareCH2(TIM1, (uint32_t)(d*TIM1->ARR));   // PA9 CH2N PB14
/*
  //simulace regulovane soustavy
  fltLoPass(uaz, &menic);
  ua = menic.out;
  fltLoPass(ua, &RLobvod);
  ia = RLobvod.out * RLobvodRa;
*/

  // Rucni ovladani premostovaciho rezistoru
  //if((analogData.Vdc1*0.9) < analogData.Vdc2) SET_BIT(GPIOB->ODR, GPIO_ODR_4);
  //else CLEAR_BIT(GPIOB->ODR, GPIO_ODR_4);
  DumpTrace();

}

// funkce pro sinusový měnič
void NewSMP(void)
{
	static   uint8_t i = 0;
	if(i == N_SMP)
		i = 0;
	TIM1->CCR1 = SMP[i++];

	if(TIM2->ARR != Arr_Tim2 )
	{
		TIM2->CR1 &= ~TIM_CR1_CEN;
		// Nastavení nové hodnoty do autoreload registru
		TIM2->ARR = Arr_Tim2;
		// Spuštění čítače
		TIM2->CR1 |= TIM_CR1_CEN;
     }
}

void SinCalc(void)
{
	float angle;
	for (uint8_t i = 0; i < N_SMP; i++)
	{
	  angle = ASR*(float)i;
	  SMP[i] = (uint16_t) rint(600 + 599*sinf(angle*(PI/180)));
    }

}
/*
// obsluha přerušení pro příjem dat po I2C
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{

  // uložení přijatých dat do bufferu
  for (int i = 0; i < BUFFER_SIZE; i++)
  {

    HAL_I2C_Slave_Receive(hi2c,rxBuffer ,2 , HAL_MAX_DELAY);
   HAL_I2C_Slave_Seq_Receive_IT(hi2c, rxBuffer, 2, I2C_NEXT_FRAME);
  }

  // zpracování dat
  processRxData(rxBuffer);
}

// obsluha chybového přerušení I2C
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
{
  // chyba při příjmu dat po I2C
  if (HAL_I2C_GetError(hi2c) != HAL_I2C_ERROR_NONE)
  {
    Error_Handler();
  }
}*/
void prijem_I2C(void)
{
/* USER CODE BEGIN I2C1_EV_IRQn 0 */
	 // Pokud přišlo ACK pro slave address, připrav se na příjem dat
	    if(LL_I2C_IsActiveFlag_ADDR(I2C1))
	    {
	        // Clear ADDR flag
	        LL_I2C_ClearFlag_ADDR(I2C1);

	        // Zapni interrupt pro RXNE
	        LL_I2C_EnableIT_RX(I2C1);

	        // Reset RX index
	        my_index = 0;
	    }

	    // Pokud je připraveno nové data, přijmi je
	    if(LL_I2C_IsActiveFlag_RXNE(I2C1))
	    {
	        // Přečti přijatá data z I2C a ulož je do pole
	        data[my_index++] = LL_I2C_ReceiveData8(I2C1);

	        // Pokud jsou všechna data přijata, zakaž interrupt pro RXNE
	        if(my_index == DATA_SIZE)
	        {
	            LL_I2C_DisableIT_RX(I2C1);
	            zpracovani_Dat();
	        }
	    }
}
/*
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{
	Transfer_Direction = TransferDirection;
      //##- Put I2C peripheral in reception process ###########################
  if (HAL_I2C_Slave_Seq_Receive_IT(&hi2c, (uint8_t *)rxBuffer, BUFFER_SIZE, I2C_FIRST_AND_LAST_FRAME) != HAL_OK)
    {
    // Transfer error in reception process
    Error_Handler();
  }
}
*/

// funkce pro zpracování přijatých dat
void zpracovani_Dat()
{
 switch(data[0]) {
 case 1:
	 freq = data[1];
	 Arr_Tim2 = 72000000/(freq*N_SMP)-1;  // TIM 2 clock 72 MHz
	 break;
 case 2:
	 uz = data[1]*1.6;
	 break;
 }
}
void DAC_SetOutputVoltage(uint16_t value)
{
    LL_DAC_ConvertData12RightAligned(DAC1, LL_DAC_CHANNEL_1, value);
    LL_DAC_TrigSWConversion(DAC1, LL_DAC_CHANNEL_1);
}

