#include "stm32l0xx_hal_conf.h"
#include "stm32l0xx_hal.h"
#include "init.h"

RCC_ClkInitTypeDef      RCC_ClkInitStruct;
RCC_OscInitTypeDef      RCC_OscInitStruct;

GPIO_InitTypeDef        GPIO_InitStructure;

TIM_HandleTypeDef       TIM_InitStructure;
TIM_OC_InitTypeDef      PWM_InitStructure; 

//WWDG_InitTypeDef      WATCH_InitStructure;
IWDG_HandleTypeDef      WATCH_Structure;

ADC_HandleTypeDef       ADC_InitStructure;
ADC_ChannelConfTypeDef  ADC_ChannelInitStructure;
DMA_HandleTypeDef       DMA_InitStructure;

SPI_HandleTypeDef       hspi1;

RTC_TimeTypeDef               RTC_GetTime;
RTC_DateTypeDef               RTC_GetDate;

//RTC
                        RTC_HandleTypeDef               hrtc; 
/*volatile*/            RTC_TimeTypeDef                 RTC_Time; 
/*volatile*/            RTC_DateTypeDef                 RTC_Date; 
                        RCC_PeriphCLKInitTypeDef        PeriphClkInit;

//UART
UART_HandleTypeDef      UART1_InitStructure;
#define MAIN_TX_BUFFER_LENGTH 20
#define MAIN_RX_BUFFER_LENGTH 40
extern /*volatile*/ unsigned char txActiveBuffer [255];
char 	status_txbuffer[20];
uint8_t 	status_rxbuffer[20];

// Merici buffer
volatile 	uint32_t adcArray[150];
extern      uint32_t        ticks;
static uint32_t HALPOM = 0xFF;








// #########################################################################################################
void CLK_1MHz_Init(void)
{
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
	__HAL_RCC_CLEAR_RESET_FLAGS();

    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_MSI|RCC_OSCILLATORTYPE_LSE;

	RCC_OscInitStruct.LSIState = RCC_LSI_ON;
	RCC_OscInitStruct.LSEState = RCC_LSE_ON;                // pridano pro RTC
	RCC_OscInitStruct.MSIState = RCC_MSI_ON;
	RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
    
    RCC_OscInitStruct.MSICalibrationValue = 0;
    RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_4;			//-1Mhz
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
    
	if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
		{
		Error_Handler();
		}
    
   __HAL_RCC_RTC_ENABLE(); 

    PeriphClkInit.PeriphClockSelection         = RCC_PERIPHCLK_RTC; 
    PeriphClkInit.RTCClockSelection         = RCC_RTCCLKSOURCE_LSE; 

    RCC_ClkInitStruct.ClockType       = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;

	if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
		{
		Error_Handler();
		}

	__PWR_CLK_ENABLE();

    __SYSCFG_CLK_ENABLE();
    __TIM2_CLK_ENABLE();
   
    __GPIOA_CLK_ENABLE();
    __GPIOB_CLK_ENABLE();
    
    __ADC1_CLK_ENABLE();
    __DMA1_CLK_ENABLE();
    
    //SystemCoreClockUpdate(); 
    };

// #########################################################################################################
void CLK_32MHz_Init(void)
{
   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); 

   RCC_OscInitStruct.OscillatorType      = RCC_OSCILLATORTYPE_HSI; 
   RCC_OscInitStruct.HSIState            = RCC_HSI_ON; 
   RCC_OscInitStruct.HSICalibrationValue = 16; 
   RCC_OscInitStruct.PLL.PLLState        = RCC_PLL_ON; 
   RCC_OscInitStruct.PLL.PLLSource       = RCC_PLLSOURCE_HSI; 
   RCC_OscInitStruct.PLL.PLLMUL          = RCC_PLLMUL_4; 
   RCC_OscInitStruct.PLL.PLLDIV          = RCC_PLLDIV_2; 
   HAL_RCC_OscConfig(&RCC_OscInitStruct); 

    RCC_ClkInitStruct.ClockType       = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); 
   RCC_ClkInitStruct.SYSCLKSource    = RCC_SYSCLKSOURCE_PLLCLK; 
   RCC_ClkInitStruct.AHBCLKDivider   = RCC_SYSCLK_DIV1; 
   RCC_ClkInitStruct.APB1CLKDivider  = RCC_HCLK_DIV1; 
   RCC_ClkInitStruct.APB2CLKDivider  = RCC_HCLK_DIV1; 
   HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1); 


   PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2; 
   PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1; 
   HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); 
};

// #########################################################################################################
void CLK_Deinit(void)
{
    __SYSCFG_CLK_DISABLE();
    __TIM2_CLK_DISABLE();  
    __GPIOA_CLK_DISABLE();
    __GPIOB_CLK_DISABLE();    
    __ADC1_CLK_DISABLE();
    __DMA1_CLK_DISABLE();
    __SPI1_CLK_ENABLE();
    __USART1_CLK_ENABLE();
};

// #########################################################################################################
void Periph_Deinit(void)
{
    __ADC1_CLK_DISABLE();
    __DMA1_CLK_DISABLE();

    HAL_SPI_DeInit(&hspi1);
    HAL_DMA_DeInit(&DMA_InitStructure);
    HAL_ADC_DeInit(&ADC_InitStructure);
    HAL_UART_DeInit(&UART1_InitStructure);
};

// #########################################################################################################
void GPIO_Init(void )
{
    //OUT - LED_CERVENA
    GPIO_InitStructure.Pin      = LED_CERVENA_PIN;              // císlo pinu
    GPIO_InitStructure.Mode     = GPIO_MODE_OUTPUT_PP;          // nastavit jako výstup Push Pull?  - GPIO_MODE_OUTPUT_OD (open drain)
    GPIO_InitStructure.Speed    = GPIO_SPEED_LOW;               
    GPIO_InitStructure.Pull     = GPIO_NOPULL;                  // žádný pull
    HAL_GPIO_Init(LED_CERVENA_PORT, &GPIO_InitStructure);       // inicializace
  
    //PWM_PULZ - Bzucak
    GPIO_InitStructure.Pin      = PWM_PULZ_PIN;         // cislo pinu
    GPIO_InitStructure.Mode     = GPIO_MODE_AF_PP;      // alternate push pull
    GPIO_InitStructure.Speed    = GPIO_SPEED_HIGH;      // rychlost
    GPIO_InitStructure.Pull     = GPIO_NOPULL;          // žádný pull
    GPIO_InitStructure.Alternate= GPIO_AF2_TIM2;        // alternativní funkce
    HAL_GPIO_Init(PWM_PULZ_PORT, &GPIO_InitStructure);

    //SPI SCLK
    GPIO_InitStructure.Pin      = SCLK_PIN;    
    GPIO_InitStructure.Mode     = GPIO_MODE_AF_PP;      
    GPIO_InitStructure.Speed    = GPIO_SPEED_HIGH;      
    GPIO_InitStructure.Pull     = GPIO_NOPULL;         
    GPIO_InitStructure.Alternate= GPIO_AF0_SPI1;     
    HAL_GPIO_Init(SCLK_PORT, &GPIO_InitStructure);
    
    //SPI MOSI
    GPIO_InitStructure.Pin      = MOSI_PIN;    
    GPIO_InitStructure.Mode     = GPIO_MODE_AF_PP;     
    GPIO_InitStructure.Speed    = GPIO_SPEED_HIGH;      
    GPIO_InitStructure.Pull     = GPIO_NOPULL;        
    GPIO_InitStructure.Alternate= GPIO_AF0_SPI1;        
    HAL_GPIO_Init(MOSI_PORT, &GPIO_InitStructure);
    
    //SPI MISO
    GPIO_InitStructure.Pin      = MISO_PIN;    
    GPIO_InitStructure.Mode     = GPIO_MODE_AF_PP;    
    GPIO_InitStructure.Speed    = GPIO_SPEED_HIGH;      
    GPIO_InitStructure.Pull     = GPIO_NOPULL;          
    GPIO_InitStructure.Alternate= GPIO_AF0_SPI1;        
    HAL_GPIO_Init(MISO_PORT, &GPIO_InitStructure);

    //WAKEUP_IN
    GPIO_InitStructure.Pin      = WAKEUP_IN_PIN;        // cislo pinu
    GPIO_InitStructure.Mode     = GPIO_MODE_INPUT;      // nastavit jako vstup
    GPIO_InitStructure.Speed    = GPIO_SPEED_LOW;       // rychlost low
    GPIO_InitStructure.Pull     = GPIO_NOPULL;          // zadny pull
    HAL_GPIO_Init(WAKEUP_IN_PORT, &GPIO_InitStructure);
    
    //MOT_ONOFF
    GPIO_InitStructure.Pin      = MOT_ONOFF_PIN;         
    GPIO_InitStructure.Mode     = GPIO_MODE_OUTPUT_PP;      
    GPIO_InitStructure.Speed    = GPIO_SPEED_LOW;               
    GPIO_InitStructure.Pull     = GPIO_NOPULL;                
    HAL_GPIO_Init(MOT_ONOFF_PORT, &GPIO_InitStructure);       

    
    //NAPETI_IN
    GPIO_InitStructure.Pin      = NAPETI_IN_PIN;
    GPIO_InitStructure.Mode     = GPIO_MODE_ANALOG;
    GPIO_InitStructure.Speed    = GPIO_SPEED_LOW;
    GPIO_InitStructure.Pull     = GPIO_NOPULL;
    HAL_GPIO_Init(NAPETI_IN_PORT, &GPIO_InitStructure);
    
    //CHARGE_STAT
    GPIO_InitStructure.Pin      = CHARGE_STAT_PIN;         
    GPIO_InitStructure.Mode     = GPIO_MODE_INPUT;      
    GPIO_InitStructure.Speed    = GPIO_SPEED_LOW;               
    GPIO_InitStructure.Pull     = GPIO_NOPULL;                
    HAL_GPIO_Init(CHARGE_STAT_PORT, &GPIO_InitStructure); 

    //USB_CONNECT
    GPIO_InitStructure.Pin      = USB_CONNECT_PIN;         
    GPIO_InitStructure.Mode     = GPIO_MODE_INPUT;      
    GPIO_InitStructure.Speed    = GPIO_SPEED_LOW;               
    GPIO_InitStructure.Pull     = GPIO_NOPULL;                
    HAL_GPIO_Init(USB_CONNECT_PORT, &GPIO_InitStructure); 
    
    //USART TX_Data
    GPIO_InitStructure.Pin      = TX_DATA_PIN;         
    GPIO_InitStructure.Mode     = GPIO_MODE_AF_PP;      
    GPIO_InitStructure.Speed    = GPIO_SPEED_HIGH;               
    //GPIO_InitStructure.Pull     = GPIO_NOPULL;   
    GPIO_InitStructure.Alternate = GPIO_AF0_USART1;    
    HAL_GPIO_Init(TX_DATA_PORT, &GPIO_InitStructure);     
    
    //USART RX_Data
    GPIO_InitStructure.Pin      = RX_DATA_PIN;         
    GPIO_InitStructure.Mode     = GPIO_MODE_AF_PP;      
    GPIO_InitStructure.Speed    = GPIO_SPEED_HIGH;               
    //GPIO_InitStructure.Pull     = GPIO_NOPULL;   
    GPIO_InitStructure.Alternate = GPIO_AF0_USART1;     
    HAL_GPIO_Init(RX_DATA_PORT, &GPIO_InitStructure);    
};

// #########################################################################################################
void GPIO_Deinit(void)
{
    HAL_GPIO_DeInit(LED_CERVENA);
    HAL_GPIO_DeInit(PWM_PULZ);
    HAL_GPIO_DeInit(SCLK);
    HAL_GPIO_DeInit(MOSI);
    HAL_GPIO_DeInit(MISO);
    HAL_GPIO_DeInit(WAKEUP_IN);
    HAL_GPIO_DeInit(MOT_ONOFF);
    HAL_GPIO_DeInit(NAPETI_IN);
    HAL_GPIO_DeInit(CHARGE_STAT);
    HAL_GPIO_DeInit(USB_CONNECT);
    HAL_GPIO_DeInit(TX_DATA);
    HAL_GPIO_DeInit(RX_DATA);
};

// #########################################################################################################
void WATCH_Init(void)
    {
    WATCH_Structure.Instance 		= IWDG;
    WATCH_Structure.Init.Prescaler 	= IWDG_PRESCALER_4;     
    WATCH_Structure.Init.Reload 	= 0xFF0;  
	WATCH_Structure.Init.Window    	= IWDG_WINDOW_DISABLE;	
    
	if (HAL_IWDG_Init(&WATCH_Structure) != HAL_OK)
		{
		Error_Handler();
		}
	
	if (HAL_IWDG_Start(&WATCH_Structure) != HAL_OK)
		{
		Error_Handler();
		}
	};

// #########################################################################################################
void WATCH_Refresh(void)
    {
    HAL_IWDG_Refresh(&WATCH_Structure);
    };

// #########################################################################################################
void PWM_FET_Set(uint32_t F_Delka_periody, uint32_t F_Delka_pulzu)
{
    TIM_InitStructure.Instance = TIM2;  
    TIM_InitStructure.Init.Prescaler = 0;  
    TIM_InitStructure.Init.CounterMode = TIM_COUNTERMODE_UP;  
    TIM_InitStructure.Init.Period = F_Delka_periody;  
    TIM_InitStructure.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;  
    
      
    PWM_InitStructure.OCMode = TIM_OCMODE_PWM1;  
    PWM_InitStructure.Pulse = F_Delka_pulzu;  
    PWM_InitStructure.OCPolarity = TIM_OCPOLARITY_HIGH;  
    PWM_InitStructure.OCFastMode = TIM_OCFAST_DISABLE;  

    HAL_TIM_Base_Init (&TIM_InitStructure);  
    HAL_TIM_PWM_Init (&TIM_InitStructure);  

    HAL_TIM_PWM_ConfigChannel (&TIM_InitStructure, &PWM_InitStructure, TIM_CHANNEL_2);  
    HAL_TIM_PWM_Start (&TIM_InitStructure, TIM_CHANNEL_2);                              
    };

// #########################################################################################################
void PWM_FET_Stop(void)
{
    PWM_InitStructure.Pulse = 0;  
	HAL_TIM_PWM_ConfigChannel (&TIM_InitStructure, &PWM_InitStructure, TIM_CHANNEL_2);  
    HAL_TIM_PWM_Start (&TIM_InitStructure, TIM_CHANNEL_2);                              
    };
    
// #########################################################################################################
void PWM_FET_Start(void)
{
    HAL_TIM_PWM_Start (&TIM_InitStructure, TIM_CHANNEL_2);                              
    };

// #########################################################################################################
void ADC_NAP_Init(void)
{
    __ADC1_CLK_ENABLE();
    __DMA1_CLK_ENABLE();    


    /* A/D prevodnik ------------------------------------------------------------- */
    ADC_InitStructure.Instance = ADC1;
    ADC_InitStructure.Init.OversamplingMode         = DISABLE;
    ADC_InitStructure.Init.ClockPrescaler           = ADC_CLOCKPRESCALER_PCLK_DIV2;
    ADC_InitStructure.Init.LowPowerAutoOff          = DISABLE;
    ADC_InitStructure.Init.LowPowerFrequencyMode    = ENABLE;
    ADC_InitStructure.Init.LowPowerAutoWait         = ENABLE;
    ADC_InitStructure.Init.Resolution               = ADC_RESOLUTION12b;
    ADC_InitStructure.Init.SamplingTime             = ADC_SAMPLETIME_239CYCLES_5;
    ADC_InitStructure.Init.ScanDirection            = ADC_SCAN_DIRECTION_BACKWARD;  
    ADC_InitStructure.Init.DataAlign                = ADC_DATAALIGN_RIGHT;
    ADC_InitStructure.Init.ContinuousConvMode       = ENABLE;
    ADC_InitStructure.Init.DiscontinuousConvMode    = ENABLE;   //DISABLE;
    ADC_InitStructure.Init.ExternalTrigConvEdge     = ADC_EXTERNALTRIG_EDGE_NONE;
    ADC_InitStructure.Init.EOCSelection             = EOC_SINGLE_CONV;
    ADC_InitStructure.Init.DMAContinuousRequests    = ENABLE;
    HAL_ADC_Init(&ADC_InitStructure);
    HAL_ADCEx_Calibration_Start(&ADC_InitStructure, ADC_SINGLE_ENDED);
  
  
    ADC_ChannelInitStructure.Channel = (ADC_CHANNEL_1 | ADC_CHANNEL_17 | ADC_CHANNEL_18); 
    HAL_ADC_ConfigChannel(&ADC_InitStructure, &ADC_ChannelInitStructure);
    
    /* DMA transfer -------------------------------------------------------------- */
    DMA_InitStructure.Instance                      = DMA1_Channel1;
    DMA_InitStructure.Init.Direction                = DMA_PERIPH_TO_MEMORY;
    DMA_InitStructure.Init.PeriphInc                = DMA_PINC_DISABLE;
    DMA_InitStructure.Init.MemInc                   = DMA_MINC_ENABLE;
    DMA_InitStructure.Init.PeriphDataAlignment      = DMA_PDATAALIGN_WORD;
    DMA_InitStructure.Init.MemDataAlignment         = DMA_MDATAALIGN_WORD;
    DMA_InitStructure.Init.Mode                     = DMA_CIRCULAR;
    DMA_InitStructure.Init.Priority                 = DMA_PRIORITY_MEDIUM;
    DMA_InitStructure.Init.Request                  = DMA_REQUEST_0;
    HAL_DMA_DeInit(&DMA_InitStructure);  
    HAL_DMA_Init(&DMA_InitStructure);
  
    /* Associate the DMA handle */
    __HAL_LINKDMA(&ADC_InitStructure, DMA_Handle, DMA_InitStructure);
    HAL_ADC_Start_DMA(&ADC_InitStructure, (uint32_t *)&adcArray, 150);
    };

// #########################################################################################################
void ADC_NAP_Start(void)
    {
    HAL_ADC_Start_DMA(&ADC_InitStructure, (uint32_t *)&adcArray, 150);
};

// #########################################################################################################
void ADC_NAP_Stop(void)
    {
    HAL_ADC_Stop_DMA(&ADC_InitStructure);
};

// #########################################################################################################
void Error_Handler(void)
{
	while(1){}; 
}

// #########################################################################################################
void BAT_MEAS_Start(void)
{
    //BAT_MEASURE_ONOFF - on
    GPIO_InitStructure.Pin      = BAT_MEAS_ONOFF_PIN;              
    GPIO_InitStructure.Mode     = GPIO_MODE_OUTPUT_PP;      
    GPIO_InitStructure.Speed    = GPIO_SPEED_HIGH;                  //GPIO_SPEED_LOW;               
    GPIO_InitStructure.Pull     = GPIO_NOPULL;                
    HAL_GPIO_Init(BAT_MEAS_ONOFF_PORT, &GPIO_InitStructure);        // nastavit jako vystup
    HAL_GPIO_WritePin (BAT_MEAS_ONOFF, BAT_MEAS_ON);                // pripojit k 0

    HAL_ADC_Start_DMA(&ADC_InitStructure, (uint32_t *)&adcArray, 150);
};

// #########################################################################################################
void BAT_MEAS_Stop(void)
{
    HAL_ADC_Stop_DMA(&ADC_InitStructure);

    //BAT_MEASURE_ONOFF - off
    GPIO_InitStructure.Pin      = BAT_MEAS_ONOFF_PIN;              
    GPIO_InitStructure.Mode     = GPIO_MODE_INPUT;      
    GPIO_InitStructure.Speed    = GPIO_SPEED_LOW;               
    GPIO_InitStructure.Pull     = GPIO_NOPULL;                
    HAL_GPIO_Init(BAT_MEAS_ONOFF_PORT, &GPIO_InitStructure);    // nastavit jako vstup
};

// #########################################################################################################
uint32_t BAT_VOLTAGE(uint32_t adcArray2)
{
   //linearni funkce: 0=0V,     4096 = 5V (+doladene)
    return ((0.001215*adcArray2)*1000);
};

// #########################################################################################################
uint32_t BAT_CAPACITY(uint32_t adcArray2)
{
    //linearni funkce: 3.3V = 0%,    4.05 = 90%  - skok po 10% // puvodni
    //linearni funkce: 3,6V = 0%,    4,2  = 99%  - skok po 1%
    int32_t Cap;

    Cap =  0.12*((0.001215*adcArray2)*1000)-396; // puvodni
    if(Cap >99 )  // 99% pokud neni signal z nabijeciho clenu
        Cap = 99;
    if((Cap < 0))                                     // aby nebyl zapor
        Cap = 0;
    return Cap;
};

// #########################################################################################################
void PERIFERIE_ON(void)
{
    GPIO_InitStructure.Pin      = PER_ONOFF_PIN;              
    GPIO_InitStructure.Mode     = GPIO_MODE_OUTPUT_PP; 
    GPIO_InitStructure.Speed    = GPIO_SPEED_LOW;               
    GPIO_InitStructure.Pull     = GPIO_NOPULL;                
    HAL_GPIO_Init(PER_ONOFF_PORT, &GPIO_InitStructure);         // ZAPNE NAPÁJENÍ PERIFERIÍ

    GPIO_InitStructure.Pin      =  CS_FLASH_PIN;
    GPIO_InitStructure.Mode     =  GPIO_MODE_OUTPUT_PP; 
    GPIO_InitStructure.Speed    =  GPIO_SPEED_MEDIUM;               
    GPIO_InitStructure.Pull     =  GPIO_NOPULL;               
    HAL_GPIO_Init(CS_FLASH_PORT, &GPIO_InitStructure);          // CS FLASH - vysoka uroven
    HAL_GPIO_WritePin (CS_FLASH, HIGH);

    GPIO_InitStructure.Pin      =  CS_AKC_PIN;
    GPIO_InitStructure.Mode     =  GPIO_MODE_OUTPUT_PP; 
    GPIO_InitStructure.Speed    =  GPIO_SPEED_MEDIUM;               
    GPIO_InitStructure.Pull     =  GPIO_NOPULL;                  
    HAL_GPIO_Init(CS_AKC_PORT, &GPIO_InitStructure);          // CS AKC - vysoka uroven
    HAL_GPIO_WritePin (CS_AKC, HIGH);
};

// #########################################################################################################
void PERIFERIE_OFF(void)
{
    GPIO_InitStructure.Pin      = PER_ONOFF_PIN;              
    GPIO_InitStructure.Mode     = GPIO_MODE_INPUT;  
    GPIO_InitStructure.Speed    = GPIO_SPEED_LOW;               
    GPIO_InitStructure.Pull     = GPIO_NOPULL;                
    HAL_GPIO_Init(PER_ONOFF_PORT, &GPIO_InitStructure);         // VYPNE NAPÁJENÍ PERIFERIÍ

    GPIO_InitStructure.Pin      =  CS_FLASH_PIN;
    GPIO_InitStructure.Mode     =  GPIO_MODE_INPUT; 
    GPIO_InitStructure.Speed    =  GPIO_SPEED_MEDIUM;               
    GPIO_InitStructure.Pull     =  GPIO_NOPULL;               
    HAL_GPIO_Init(CS_FLASH_PORT, &GPIO_InitStructure);          // CS FLASH - prepnuti na vstup

    GPIO_InitStructure.Pin      =  CS_AKC_PIN;
    GPIO_InitStructure.Mode     =  GPIO_MODE_INPUT; 
    GPIO_InitStructure.Speed    =  GPIO_SPEED_MEDIUM;               
    GPIO_InitStructure.Pull     =  GPIO_NOPULL;               
    HAL_GPIO_Init(CS_AKC_PORT, &GPIO_InitStructure);          // CS AKC - prepnuti na vstup
};

// #########################################################################################################
void SPI_Init(void)
{
  __SPI1_CLK_ENABLE(); 
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;    
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;                            // slave select management SPI_NSS_HARD_INPUT SPI_NSS_HARD_OUTPUT SPI_NSS_SOFT
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  HAL_SPI_Init(&hspi1);
};

// #########################################################################################################
void SPI_Deinit(void)
{
    HAL_SPI_DeInit(&hspi1);
}

// #########################################################################################################
uint8_t SPI_TransmitReceive(uint8_t TxData)
{
uint8_t RxData = 0xF0;
HAL_SPI_TransmitReceive(&hspi1, &TxData, &RxData, 1, 0xFF);
return RxData;
};

// #########################################################################################################
void SPI_TransmitField(uint8_t *Data ,uint16_t number) 
{
    HAL_SPI_Transmit(&hspi1, Data, number, 0xFF);
};

// #########################################################################################################
void SPI_ReceiveField(uint8_t *Data ,uint16_t number) 
{
    HAL_SPI_Receive(&hspi1, Data, number, 0xFF);
};

// #########################################################################################################
void SLEEP(void)
{
         PWR->CR |= PWR_CR_CWUF;       // clear wake up flag
         HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1); 
         HAL_PWR_EnterSTANDBYMode();
};

// #########################################################################################################
void SLEEP_IfBatLow(uint32_t adcValue)
{
        if((((5.07/4096) * adcValue )*1000) <3000)        // pokud napeti mensi nez 3V - vstup do STAND BY rezimu
        {
         PWR->CR |= PWR_CR_CWUF;       // clear wake up flag
         HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1); 
         HAL_PWR_EnterSTANDBYMode();
        };
};

// #########################################################################################################
void UART1_Init(void)
{
    __USART1_CLK_ENABLE();

// Seriová linka - komunikace s PC -------------------------------------------------------------   
  UART1_InitStructure.Instance       = USART1;
  UART1_InitStructure.Init.BaudRate  = 921600; //2000000;//9600;  //57600;  //800 000 pro mgm protool, 2000 000 pro gemini
  UART1_InitStructure.Init.WordLength= UART_WORDLENGTH_8B;
  UART1_InitStructure.Init.StopBits  = UART_STOPBITS_1;
  UART1_InitStructure.Init.Parity    = UART_PARITY_NONE;
  UART1_InitStructure.Init.HwFlowCtl  = UART_HWCONTROL_NONE;
  UART1_InitStructure.Init.Mode      = UART_MODE_TX_RX;

    if (HAL_UART_Init(&UART1_InitStructure) != HAL_OK)
        asm("bkpt 255");

  USART1 -> CR1     &= ~USART_CR1_UE;       // USART DISABLE
  
  // TRANSMIT : /////////////////////////////////////////////////////////////////////////
  
  USART1 -> CR3     |= USART_CR3_DMAT;      // DMAT: DMA enable transmitter 
  
  DMA_InitStructure.Instance                 = DMA1_Channel4;
  DMA_InitStructure.Init.Direction           = DMA_MEMORY_TO_PERIPH;
  DMA_InitStructure.Init.PeriphInc           = DMA_PINC_DISABLE;
  DMA_InitStructure.Init.MemInc              = DMA_MINC_ENABLE;
  DMA_InitStructure.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  DMA_InitStructure.Init.MemDataAlignment    = DMA_PDATAALIGN_BYTE;
  DMA_InitStructure.Init.Mode                = DMA_NORMAL;                //DMA_NORMAL    DMA_CIRCULAR
  DMA_InitStructure.Init.Priority            = DMA_PRIORITY_VERY_HIGH;      // DMA_PRIORITY_LOW     DMA_PRIORITY_VERY_HIGH
  DMA_InitStructure.Init.Request             = DMA_REQUEST_3;
  HAL_DMA_Init(&DMA_InitStructure);  
                
  DMA1_Channel4-> CPAR   = (uint32_t)(0x40013800 + 0x28 );  // PeripheralBaseAddr
  //DMA1_Channel4-> CMAR   = (uint32_t)(&status.txbuffer  );  // MemoryBaseAddr
  DMA1_Channel4-> CMAR   = (uint32_t)(&txActiveBuffer);  // MemoryBaseAddr
  DMA1_Channel4-> CNDTR  = MAIN_TX_BUFFER_LENGTH;           // DMA_BufferSize
  
  
  // RECEIVE : /////////////////////////////////////////////////////////////////////////
  
  USART1 -> CR3     |= USART_CR3_DMAR;      // DMAR: DMA enable receiver
  
  DMA_InitStructure.Instance                 = DMA1_Channel5;
  DMA_InitStructure.Init.Direction           = DMA_PERIPH_TO_MEMORY;
  DMA_InitStructure.Init.PeriphInc           = DMA_PINC_DISABLE;
  DMA_InitStructure.Init.MemInc              = DMA_MINC_ENABLE;
  DMA_InitStructure.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  DMA_InitStructure.Init.MemDataAlignment    = DMA_PDATAALIGN_BYTE;
  DMA_InitStructure.Init.Mode                = DMA_NORMAL;                //DMA_NORMAL    DMA_CIRCULAR
  DMA_InitStructure.Init.Priority            = DMA_PRIORITY_LOW;      // DMA_PRIORITY_LOW     DMA_PRIORITY_VERY_HIGH
  DMA_InitStructure.Init.Request             = DMA_REQUEST_3;
  HAL_DMA_Init(&DMA_InitStructure);  
                
  DMA1_Channel5-> CPAR   = (uint32_t)(0x40013800 + 0x24 );  // PeripheralBaseAddr
  DMA1_Channel5-> CMAR   = (uint32_t)(&status_rxbuffer );  // MemoryBaseAddr
  DMA1_Channel5-> CNDTR  = MAIN_RX_BUFFER_LENGTH;           // DMA_BufferSize
  DMA1_Channel5-> CCR   |=  DMA_CCR_EN;                     // ENABLE chanal

  // receiver timeout : //////////
  USART1 -> RTOR = 60;                      // klid na lince 60 tiku
  USART1 -> CR2 |= USART_CR2_RTOEN;         // Receiver timeout enable
  USART1 -> CR1 |=  USART_CR1_RTOIE;    //Receiver timeout interrupt enable


  // GLOBAL: /////////////////////////////////////////////////////////////////////////
  USART1 -> CR1         |= USART_CR1_UE;    // USART ENABLE
  
  HAL_NVIC_SetPriority(USART1_IRQn, 0, 2);
  HAL_NVIC_EnableIRQ  (USART1_IRQn); 
 
};

// #########################################################################################################
void UART1_Deinit(void)
{
    HAL_UART_DeInit(&UART1_InitStructure);
    HAL_DMA_DeInit(&DMA_InitStructure);
    HAL_DMA_DeInit(&DMA_InitStructure);
}

// #########################################################################################################
void UART1_DMA_SEND (unsigned int delka_dat)
{
    DMA1_Channel4 -> CCR    &= ~DMA_CCR_EN;             // DISABLE chanal
    DMA1_Channel4 -> CNDTR  = delka_dat;
    USART1 -> ICR           =   USART_ICR_TCCF;
	DMA1_Channel4 -> CCR    |=  DMA_CCR_EN;             // ENABLE chanal
};

// #########################################################################################################
void RTC_Init_0(void) 
{
    __PWR_CLK_ENABLE();
    HAL_PWR_EnableBkUpAccess();
    __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE);         //select clock source
    __HAL_RCC_RTC_ENABLE();
    hrtc.Instance = RTC;
    hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
    hrtc.Init.AsynchPrediv = 127;
    hrtc.Init.SynchPrediv = 255;
    HAL_RTC_Init(&hrtc);

    RTC_Time.Seconds = 0;
    RTC_Time.Minutes = 0;
    RTC_Time.Hours = 0;
    RTC_Time.SubSeconds = 0;
    HAL_RTC_SetTime(&hrtc,&RTC_Time, FORMAT_BIN);

    RTC_Date.Date = 0;
    RTC_Date.Month = 0;
    RTC_Date.WeekDay = 0;
    RTC_Date.Year = 0;
    HAL_RTC_SetDate(&hrtc, &RTC_Date, FORMAT_BIN);
    HAL_PWR_DisableBkUpAccess();
};

// #########################################################################################################
void RTC_Init(void)
{
    __PWR_CLK_ENABLE();
    HAL_PWR_EnableBkUpAccess();
    __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE);         //select clock source
    __HAL_RCC_RTC_ENABLE();
    hrtc.Instance = RTC;
    hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
    hrtc.Init.AsynchPrediv = 127;
    hrtc.Init.SynchPrediv = 255;
    HAL_RTC_Init(&hrtc);
}

// #########################################################################################################
void RTC_TellTime(uint8_t *Year, uint8_t *WeekDay, uint8_t *Month, uint8_t * Date, uint8_t * Hr, uint8_t * Min, uint8_t * Sec)
{
    HAL_PWR_EnableBkUpAccess();
    HAL_RTC_GetTime (&hrtc, &RTC_GetTime, FORMAT_BIN);
    HAL_RTC_GetDate(&hrtc, &RTC_GetDate, FORMAT_BIN);
    HAL_PWR_DisableBkUpAccess();
    *Date = RTC_GetDate.Date;
    *Hr = RTC_GetTime.Hours;
    *Min = RTC_GetTime.Minutes;
    *Sec = RTC_GetTime.Seconds;   
    *Year = RTC_GetDate.Year;
    *WeekDay = RTC_GetDate.WeekDay;
    *Month = RTC_GetDate.Month;
};

// #########################################################################################################
uint8_t RTC_TellSec(void)
{
    HAL_PWR_EnableBkUpAccess();
    HAL_RTC_GetTime (&hrtc, &RTC_GetTime, FORMAT_BIN);
    HAL_RTC_GetDate(&hrtc, &RTC_GetDate, FORMAT_BIN);
    HAL_PWR_DisableBkUpAccess();
    return RTC_GetTime.Seconds;  
};

// #########################################################################################################
void RTC_SetTime(uint8_t Year, uint8_t WeekDay, uint8_t Month, uint8_t Date, uint8_t Hr, uint8_t Min, uint8_t Sec)
{
    HAL_PWR_EnableBkUpAccess();
    RTC_Time.Seconds = Sec;
    RTC_Time.Minutes = Min;
    RTC_Time.Hours = Hr;
    RTC_Time.SubSeconds = 0;
    RTC_Date.Date = Date;
    RTC_Date.Month = Month;
    RTC_Date.WeekDay = WeekDay;
    RTC_Date.Year = Year;
    HAL_RTC_SetTime (&hrtc, &RTC_Time, FORMAT_BIN);
    HAL_RTC_SetDate(&hrtc, &RTC_Date, FORMAT_BIN);
};

// #########################################################################################################
void Led_ON(void)
{
    GPIO_InitStructure.Pin      = LED_CERVENA_PIN;              // císlo pinu
    GPIO_InitStructure.Mode     = GPIO_MODE_OUTPUT_PP;          // nastavit jako výstup Push Pull?  - GPIO_MODE_OUTPUT_OD (open drain)
    GPIO_InitStructure.Speed    = GPIO_SPEED_LOW;               
    GPIO_InitStructure.Pull     = GPIO_NOPULL;                  // žádný pull
    HAL_GPIO_Init(LED_CERVENA_PORT, &GPIO_InitStructure);       // inicializace

    HAL_GPIO_WritePin(LED_CERVENA, LED_ON);
};

// #########################################################################################################
void Led_OFF(void)
{
    HAL_GPIO_WritePin(LED_CERVENA, LED_OFF);

    GPIO_InitStructure.Pin      = LED_CERVENA_PIN;              // císlo pinu
    GPIO_InitStructure.Mode     = GPIO_MODE_INPUT;          // nastavit jako výstup Push Pull?  - GPIO_MODE_OUTPUT_OD (open drain)
    GPIO_InitStructure.Speed    = GPIO_SPEED_LOW;               
    GPIO_InitStructure.Pull     = GPIO_NOPULL;                  // žádný pull
    HAL_GPIO_Init(LED_CERVENA_PORT, &GPIO_InitStructure);       // inicializace
};

// #########################################################################################################
int32_t ComputeTemperature(uint32_t measure, uint32_t VDDref)
{
    return((1655*measure)/(VDDref*10)-40);
}

// #########################################################################################################
void SOUND_TurnOn(void)
{
    SystemCoreClockUpdate(); 
    SysTick_Config(System_1ms);

    HAL_Delay(200);
    PWM_FET_Set(3000, 1500);
    HAL_Delay(50);
    PWM_FET_Stop();
    HAL_Delay(50);
    PWM_FET_Set(2000, 1000);
    HAL_Delay(50);
    PWM_FET_Stop();
    HAL_Delay(50);
    PWM_FET_Set(1000, 500);
    HAL_Delay(100);
    PWM_FET_Stop();
    HAL_Delay(200);
    PWM_FET_Set(500, 250);
    HAL_Delay(50);
    PWM_FET_Stop();
};

// #########################################################################################################
void SOUND_TurnOff(void)
{
   // CLK_1MHz_Init();
    SystemCoreClockUpdate(); 
    SysTick_Config(System_1ms);

    HAL_Delay(200);
    PWM_FET_Set(1000, 500);
    HAL_Delay(100);
    PWM_FET_Stop();
    HAL_Delay(100);
    PWM_FET_Set(2000, 1000);
    HAL_Delay(100);
    PWM_FET_Stop();
    HAL_Delay(100);
    PWM_FET_Set(3000, 1500);
    HAL_Delay(550);
    PWM_FET_Stop();
};

// #########################################################################################################
void SOUND_LowBat(void)
{
    SystemCoreClockUpdate(); 
    SysTick_Config(System_1ms);

    HAL_Delay(200);
    for(int i = 0; i<3 ; i++)
    {
        PWM_FET_Set(750, 450);
        HAL_Delay(300);
        PWM_FET_Stop();
        HAL_Delay(300);
    }
};

// #########################################################################################################
void SOUND_USBConnect(void)
{
    SystemCoreClockUpdate(); 
    SysTick_Config(System_1ms);

    HAL_Delay(100);
    PWM_FET_Set(1500, 750);
    HAL_Delay(30);
    PWM_FET_Stop();
    HAL_Delay(100);
    PWM_FET_Set(2000, 1000);
    HAL_Delay(30);
    PWM_FET_Stop();
    HAL_Delay(60);
    PWM_FET_Set(1000, 500);
    HAL_Delay(30);
    PWM_FET_Stop();
};

// #########################################################################################################
void SOUND_USBDisconnect(void)
{
    SystemCoreClockUpdate(); 
    SysTick_Config(System_1ms);

    HAL_Delay(100);
    PWM_FET_Set(1000, 500);
    HAL_Delay(30);
    PWM_FET_Stop();
    HAL_Delay(70);
    PWM_FET_Set(2000, 1000);
    HAL_Delay(30);
    PWM_FET_Stop();
    HAL_Delay(70);
    PWM_FET_Set(2000, 1000);
    HAL_Delay(30);
    PWM_FET_Stop();
};

// #########################################################################################################
void mgmCRC32_Init(void)
{
    __CRC_CLK_ENABLE();
    CRC->CR  = 0x00000000;
    CRC->CR  |= 0b10000000 | 0b00100000;    //reverse output, reverse input, 32bit
    CRC->POL = 0x04C11DB7;                  //set polynom    
}

// #########################################################################################################
uint32_t mgmCRC32(uint8_t pBuffer[], uint32_t startIndex, uint32_t lastIndex)
{
    uint8_t tempCrc8bit;
    uint32_t aux;
    CRC->CR |= CRC_CR_RESET;    //dalsi moznost reset
    for(aux = startIndex; aux <= lastIndex;  aux++)
    {  
         tempCrc8bit = pBuffer[aux];
         *(uint8_t*)(CRC_BASE) = (uint8_t)tempCrc8bit;              
    }
    return ((CRC->DR) ^ 0xFFFFFFFF);
};




