

/* ----------------------------------------------------------------------------
	David Hladký 2016
	Program pro zpracování a modulovaní vstuppního singálu pro parametrický reproduktro.
	- Implementovány tři typy modulace - SSB-C AM, Improve (Vylepšená) AM a klasická AM.
*/

#include <stdio.h>
#include <stdlib.h>
#include "diag/Trace.h"
#include "stm32f4xx_hal.h"
#include "SPI_peripherals.h"
#include "fir_filter.h"


// Global variables and definitions of functions

//--------------Definition of functions---------------//
void bar_graph_0_10 (uint16_t data);
void HAL_TIM1_PWM_CH1_init();
void HAL_TIM2_PWM_CH1_init();
void SystemClock_Config(void);

//-------------- Definice a globální proměnné ---------------//
#define NUM_SAMPLE 15 // Počet vzorků na jednu periodu (600/40 = 15), 600kHz vzorkovací frekvence DAC, 40kHz vzorkovací frekvence ADC

#define SPI1_CS 	GPIO_PIN_8 	// GPIOA
#define SPI2_CS 	GPIO_PIN_0 	// GPIOA
#define AM_SW		GPIO_PIN_13 // GPIOA
#define SSB_SW		GPIO_PIN_14 // GPIOA
#define IMP_AM_SW	GPIO_PIN_15 // GPIOA
#define TLAC_DEC	GPIO_PIN_10	// GPIOC
#define TLAC_INC	GPIO_PIN_11	// GPIOC
#define STROBE 		GPIO_PIN_2	//GPIOD

FIR_XN_BUFFER fir_buff;
LINE_HILB_APPROX line_aprox_hilb;
LINE_APPROX line_aprox;

uint16_t output_buffer_1[NUM_SAMPLE],output_buffer_2[NUM_SAMPLE];

uint16_t type_of_modulation = 1; // Výběr typu modulace - Defaultně AM

float Modulation_index = 0; // Defaultní hodnota hloubky modulace 0

float modulation_index_2 = 0; // Samostatný výpočet hloubky modulace pro vylepšenou AM
float modulation_index_4 = 0;

float sin_tab[] =
{
    0,0.4067366431,0.7431448255,0.9510565163,0.9945218954,0.8660254038,0.5877852523,0.2079116908,-0.2079116908,-0.5877852523,
    -0.8660254038,-0.9945218954,-0.9510565163,-0.7431448255,-0.4067366431
}; // Tabulka hodnot funkce sinus

float cos_tab[] =
{
    1,0.9135454576,0.6691306064,0.3090169944,-0.1045284633,-0.5,-0.8090169944,-0.9781476007,-0.9781476007,-0.8090169944,
    -0.5,-0.1045284633,0.3090169944,0.6691306064,0.9135454576
}; // Tabulka hodnot funkce kosinus

float fir_coefficients[] = {-2.078634572e-005,-0,-3.497203231e-005,-0,-5.385448384e-005,-0,-7.835883632e-005,-0,-0.0001095155431,-0,-0.0001484648007,-0,-0.0001964606893,-0,-0.0002548750715,-0,
							-0.0003252013245,-0,-0.0004090580144,-0,-0.000508192665,-0,-0.0006244858201,-0,-0.0007599556601,-0,-0.0009167635032,-0,-0.001097220607,-0,-0.001303796789,-0,
							-0.001539131521,-0,-0.0018060483,-0,-0.002107573314,-0,-0.00244695968,-0,-0.002827718858,-0,-0.003253661309,-0,-0.003728949025,-0,-0.004258163385,-0,-0.004846392837,
							-0,-0.00549934641,-0,-0.006223501146,-0,-0.007026294462,-0,-0.007916376728,-0,-0.008903945506,-0,-0.01000119214,-0,-0.01122290531,-0,-0.01258729773,-0,-0.01411715633,
							-0,-0.01584147133,-0,-0.01779779201,-0,-0.02003571516,-0,-0.02262219469,-0,-0.02564988563,-0,-0.0292507569,-0,-0.03361931074,-0,-0.03905437327,-0,-0.04603945445,-0,
							-0.05541076345,-0,-0.06874923061,-0,-0.08944454624,-0,-0.1263128605,-0,-0.2116852246,-0,-0.6365571437,0,0.6360563086,0,0.2111857691,0,0.1258161539,0,0.08895193824,0,
							0.06826204107,0,0.05493027327,0,0.04556689651,0,0.038590924,0,0.03316608224,0,0.02880878977,0,0.02522014248,0,0.02220555455,0,0.01963296862,0,0.0174096374,0,0.01546851167,
							0,0.01375989734,0,0.0122461467,0,0.01089817093,0,0.009693085263,0,0.008612580765,0,0.007641775009,0,0.006768386176,0,0.005982130234,0,0.005274275026,0,0.004637306627,0,
							0.004064677289,0,0.003550613522,0,0.003089969018,0,0.002678111406,0,0.002310834755,0,0.001984291812,0,0.001694941482,0,0.001439508105,0,0.001214949882,0,0.001018434429,0,
							0.0008473198133,0,0.0006991398347,0,0.0005715925327,0,0.000462531115,0,0.000369956671,0,0.000292012155,0,0.0002269772336,0,0.0001732636735,0,0.0001294110186,0,
							9.408236467e-005,0,6.606008524e-005,0,4.424140919e-005,0,2.763377957e-005,0,0
                           }; // Hodnoty koeficientů FIR filtru pro Hilbertovu transforamci

//-------------- Inicializační struktury periferií MCU ---------------//

TIM_OC_InitTypeDef TIM_1_CH1,TIM_2_CH1;

TIM_MasterConfigTypeDef TIM_1_MASTER,TIM_2_MASTER;

TIM_SlaveConfigTypeDef TIM_2_SLAVE;

TIM_HandleTypeDef TIM_1_setup,TIM_2_setup;

GPIO_InitTypeDef PWM1_GPIO_Config, PWM2_GPIO_Config, AM_GPIO, STROBE_GPIO, INC_DEC_GPIO;

SPI_HandleTypeDef SPI1_HANDLE, SPI2_HANDLE, SPI3_HANDLE;

DMA_HandleTypeDef TIM_1_SPI_DMA;

//--------------------------- Funkce MAIN ----------------------------//
int main(void)
{

    //----------------------------------------------- Inicialiazce systému a periferií -------------------------------------------------------//
    HAL_Init();
    SystemClock_Config(); // Incilaizace hodin systému

    __GPIOA_CLK_ENABLE(); // Povolení hodin CLK pro port GPIOA
    __GPIOB_CLK_ENABLE(); // Povolení hodin CLK pro port GPIOB
    __GPIOC_CLK_ENABLE(); // Povolení hodin CLK pro port GPIOC
    __GPIOD_CLK_ENABLE(); // Povolení hodin CLK pro port GPIOD
    __GPIOH_CLK_ENABLE(); // Povolení hodin CLK pro port GPIOH

    __TIM1_CLK_ENABLE(); // Povolení hodin CLK pro Timer 1
    __TIM2_CLK_ENABLE(); // Povolení hodin CLK pro Timer 2
    __DMA2_CLK_ENABLE(); // Povolení hodin CLK pro DMA 2

    HAL_SPI_peripehrals_Init(&SPI1_HANDLE,1); // Inicializace sběrnice SPI 1
    HAL_SPI_peripehrals_Init(&SPI2_HANDLE,2); // Inicializace sběrnice SPI 2
    HAL_SPI_peripehrals_Init(&SPI3_HANDLE,3); // Inicializace sběrnice SPI 3

    HAL_TIM1_PWM_CH1_init(); // Inicialiazce Timeru 1 v PWM módu, s výstupem na CH1 - Timer 1 je nadřazen Timeru 2
    HAL_TIM2_PWM_CH1_init(); // Inicialiazce Timeru 2 v PWM módu, s výstupem na CH1


    //----------------------------------------------- Nastavení portů GPIO -------------------------------------------------------//

    AM_GPIO.Pin = IMP_AM_SW|AM_SW|SSB_SW; // Nastavení tlačítek pro výběr tehniky AM
    AM_GPIO.Mode = GPIO_MODE_INPUT;
    AM_GPIO.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOA, &AM_GPIO);

    STROBE_GPIO.Pin = STROBE; 		   // Pin PD2 slouží pro nahrání nové hodnoty na výstup posuvného registru 74HC595
    STROBE_GPIO.Mode = GPIO_MODE_OUTPUT_PP;
    STROBE_GPIO.Speed = GPIO_SPEED_FAST;
    STROBE_GPIO.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOD, &STROBE_GPIO);

    INC_DEC_GPIO.Pin = TLAC_INC|TLAC_DEC;	// Piny PC10 a PC11 slouží pro inkrementování nebo dekrementování hodnoty hlouby modulace
    INC_DEC_GPIO.Pull = GPIO_PULLUP;
    INC_DEC_GPIO.Mode = GPIO_MODE_IT_FALLING; // Nastaveny pro přerušení - reagují při sestupné hraně
    INC_DEC_GPIO.Speed = GPIO_SPEED_LOW;
    HAL_GPIO_Init(GPIOC, &INC_DEC_GPIO);

    HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0x02, 0); // Nastavení priority přerušení od PC10 a PC11
    HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

    //-------------------------------------- Start programu -> START DMA2, TIM1, TIM2 ------------------------------------------------//

    init_fir_buffer(&fir_buff,fir_coefficients); // Inicialiazce bufferu pro FIR filtr

    HAL_DMAEx_MultiBufferStart(&TIM_1_SPI_DMA, (uint32_t)output_buffer_1, (uint32_t)((&SPI1->DR)), (uint32_t)output_buffer_2, NUM_SAMPLE); // Nastavení DMA 2 do režimu dvojítého bufferu, kdy při naplnění jednoho automaticky dochází k plnění následujícího

    HAL_TIM_PWM_Start(&TIM_1_setup,TIM_CHANNEL_1); // Povolení činnosti Timru 1 a výstupu na CH1
    HAL_TIM_PWM_Start(&TIM_2_setup,TIM_CHANNEL_1); // Povolení činnosti Timru 2 a výstupu na CH1

    SPI2->DR = 0xFFFF; // Měření první hodnoty ADC MCP3201

    bar_graph_0_10 ((uint16_t)((Modulation_index + 0.01)*10)); // Zobrazení aktuální hodnoty hloubk modulace na bargraf

    while(1) // Smyčka pro kontrolu výběru Am techniky
    {
        if(HAL_GPIO_ReadPin(GPIOA, AM_SW) == GPIO_PIN_RESET)
        {
            type_of_modulation = 1; // Use AM
        }
        else if(HAL_GPIO_ReadPin(GPIOA, SSB_SW) == GPIO_PIN_RESET)
        {
            type_of_modulation = 2; // Use SSB-AM
        }
        else if(HAL_GPIO_ReadPin(GPIOA, IMP_AM_SW) == GPIO_PIN_RESET)
        {
            type_of_modulation = 3; // Use Improve AM
        }
    }

    return 0;

}

//---------------------------------------------------- Obsluha přerušení od Timer 2 a externího přerušení ------------------------------//
void TIM2_IRQHandler(void) // Obsluha přerušení od přetečíní časovače Timmer 2
{

    // Lokální proměné
    float line_approx_buffer_y[NUM_SAMPLE],line_approx_buffer_hilb[NUM_SAMPLE]; // Buffery pro vypočítané hodnoty  lineární aproximace
    float output_data_AM = 0;
    float input_data, output_data_y, output_data_y_hilb; // Proměnné pro výpočet nových hodnot z FIR filtru
    uint16_t *ptr_buffer; // Pointer to DAC buffer
    uint16_t mcp3201_data, DR_SPI2;
    float *ptr_cos_tab, *ptr_sin_tab, *ptr_y, *ptr_hilb; // Ukazatele na tabulky funkcí sin a cos a ukazatele na výstupní buffery, které obsahují výsledky z lineární interpolace

    ptr_cos_tab = cos_tab;
    ptr_sin_tab = sin_tab;
    ptr_y = line_approx_buffer_y;
    ptr_hilb = line_approx_buffer_hilb;

    if(__HAL_TIM_GET_IT_SOURCE(&TIM_2_setup, TIM_IT_UPDATE) !=RESET) // Jestliže byl vyvolán příznak TIM2_IT_UPDATE - došlo k přetečení Timeru 2
    {
        __HAL_TIM_CLEAR_IT(&TIM_2_setup, TIM_IT_UPDATE); // Vymazání příznaku přerušení

        // Přečtení přijatých dat z periférie SPI2
        DR_SPI2 = SPI2->DR; // Přečtení dat z MCP3201
        mcp3201_data = (DR_SPI2 & 0x1FFF)>>1; // Upravení přijatých dat do požadované formy, viz data sheet
        // Po přečtení předchozích hodnoty, která byla naměřena začíná nové měření dat ADC převodníkem
        SPI2->DR = 0x0000; // začátek nového měření ADC převodníkem

        input_data = ((mcp3201_data - 2048) * 2) / 4096.0; // Konverze změřených dat z int16 na float (rozmezí konverze je od -1 do 1, avšak vstup je od -1,25 do 1,25); ((ADRC_reg-2048)*2) / 2^12

        if(type_of_modulation == 2) // Jestliže je vybrán typ modulace 2 - SSB-AM, je nutné provést výpočet Hilbertovy transforamce
        {
            fir_Hilbert_filter_float(&fir_buff, &input_data, &output_data_y_hilb, &output_data_y); // Výpočet Hilbertovy transforamce
            line_Hilbert_interpolation(&line_aprox_hilb, &output_data_y, &output_data_y_hilb, ptr_y, ptr_hilb, NUM_SAMPLE); // Linerání interpolace změřených dat - jakoby byl vstupní signál navzorkován 600 kHz
        }
        else
        {
        	line_interpolation(&line_aprox, &input_data, ptr_y, NUM_SAMPLE);
        }

        // Kontrola toho, který buffer je právě využíván
        if((DMA2_Stream5->CR & DMA_SxCR_CT) == 0) // Nyní je používán výstupní buffer 1 - output_buffer_1,data jsou ukládány do output_buffer_2
        {
            ptr_buffer = output_buffer_2;

            switch (type_of_modulation)
            {
            case 1: // Výpočet klasické AM
                while(ptr_buffer < (output_buffer_2 + NUM_SAMPLE)) // Velikostu bufferu je 15 - počet vzorků na jednu periodu
                {
                    output_data_AM = (1 + Modulation_index * *(ptr_y++))* *(ptr_sin_tab++);

                    if(output_data_AM > 2) output_data_AM = 2.0; // Omezení minimální a maximální výstupní hodnoty
                    else if (output_data_AM < -2) output_data_AM = -2.0;
                    *(ptr_buffer++) = (uint16_t)((output_data_AM * 4095 / 4) + 2048)| 0x3000; // Uložení dat do bufferu, ze kterého jsou následně vyslána data do DAC
                }
                break;

            case 2: // Výpočet jednostranné AM
                while(ptr_buffer < (output_buffer_2 + NUM_SAMPLE))
                {
                    output_data_AM = Modulation_index * (*(ptr_y++) *  *(ptr_cos_tab) - *(ptr_hilb++) * *(ptr_sin_tab++)) + *ptr_cos_tab; // Calculate SSB-C AM
                    ptr_cos_tab++;

                    if(output_data_AM > 2) output_data_AM = 2.0;
                    else if (output_data_AM < -2) output_data_AM = -2.0;
                    *(ptr_buffer++) = (uint16_t)((output_data_AM * 4095 / 4) + 2048)| 0x3000;
                }
                break;

            case 3: // Výpočet vylepšené AM
                while(ptr_buffer < (output_buffer_2 + NUM_SAMPLE))
                {
                    output_data_AM = (1 - modulation_index_2 * *(ptr_y) * *(ptr_y) - modulation_index_4 * *(ptr_y) * *(ptr_y)* *(ptr_y) * *(ptr_y)) * *(ptr_sin_tab++);
                    output_data_AM += (1 + Modulation_index * *(ptr_y++))* *(ptr_cos_tab++);

                    if(output_data_AM > 2) output_data_AM = 2.0;
                    else if (output_data_AM < -2) output_data_AM = -2.0;
                    *(ptr_buffer++) = (uint16_t)((output_data_AM * 4095 / 4) + 2048)| 0x3000;
                }
                break;
            }
        }

        else if((DMA2_Stream5->CR & DMA_SxCR_CT) != 0) // Nyní je používán výstupní buffer 2 - output_buffer_2, data jsou ukládány do output_buffer_1
        {
            ptr_buffer = output_buffer_1;

            switch (type_of_modulation)
            {
            case 1: // Výpočet klasické AM
                while(ptr_buffer < (output_buffer_1 + NUM_SAMPLE)) // Velikostu bufferu je 15 - počet vzorků na jednu periodu
                {
                    output_data_AM = (1 + Modulation_index * *(ptr_y++))* *(ptr_sin_tab++);

                    if(output_data_AM > 2) output_data_AM = 2.0; // Omezení minimální a maximální výstupní hodnoty
                    else if (output_data_AM < -2) output_data_AM = -2.0;
                    *(ptr_buffer++) = (uint16_t)((output_data_AM * 4095 / 4) + 2048)| 0x3000; // Uložení dat do bufferu, ze kterého jsou následně vyslána data do DAC
                }
                break;

            case 2: // Výpočet jednostranné AM
                while(ptr_buffer < (output_buffer_1 + NUM_SAMPLE))
                {
                    output_data_AM = Modulation_index * (*(ptr_y++) *  *(ptr_cos_tab) - *(ptr_hilb++) * *(ptr_sin_tab++)) + *ptr_cos_tab;
                    ptr_cos_tab++;

                    if(output_data_AM > 2) output_data_AM = 2.0;
                    else if (output_data_AM < -2) output_data_AM = -2.0;
                    *(ptr_buffer++) = (uint16_t)((output_data_AM * 4095 / 4) + 2048)| 0x3000;
                }
                break;

            case 3: // Výpočet vylepšené AM
                while(ptr_buffer < (output_buffer_1 + NUM_SAMPLE))
                {
                    output_data_AM = (1 - modulation_index_2 * *(ptr_y) * *(ptr_y) - modulation_index_4 * *(ptr_y) * *(ptr_y)* *(ptr_y) * *(ptr_y)) * *(ptr_sin_tab++);
                    output_data_AM += (1 + Modulation_index * *(ptr_y++))* *(ptr_cos_tab++);

                    if(output_data_AM > 2) output_data_AM = 2.0;
                    else if (output_data_AM < -2) output_data_AM = -2.0;
                    *(ptr_buffer++) = (uint16_t)((output_data_AM * 4095 / 4) + 2048)| 0x3000;
                }
                break;
            }
        }
    }

}


void EXTI15_10_IRQHandler(void) // Přerušení od PC10 nebo PC11 - inrementace nebo dekrementace hloubky modulace v rozsahu 0.1 - 1
{
	HAL_Delay(100); // Debouncování tlačítka prodleva 100ms
	while(HAL_GPIO_ReadPin(GPIOC,TLAC_DEC) == GPIO_PIN_RESET); // Debouncování tlačítek pokud je některé stlačeno počká
	while(HAL_GPIO_ReadPin(GPIOC,TLAC_INC) == GPIO_PIN_RESET);

    if(__HAL_GPIO_EXTI_GET_IT(TLAC_DEC) != RESET)
    {
        Modulation_index -= 0.1; // Dekrementace hloubky modulace
        if (Modulation_index < 0) Modulation_index = 0; // Omezení minima
    }
    else if(__HAL_GPIO_EXTI_GET_IT(TLAC_INC) != RESET)
    {
        Modulation_index += 0.1; // Inkrementace hloubky modulace
        if (Modulation_index > 1) Modulation_index = 1; // Omezení maxima
    }

    if(type_of_modulation == 3) // Vypočítání nové hloubky modulace pro vylepšenou AM
    {
        modulation_index_2 = 0.5* Modulation_index * Modulation_index;
        modulation_index_4 = 0.25* Modulation_index * Modulation_index * Modulation_index * Modulation_index;
    }

    bar_graph_0_10 ((uint16_t)((Modulation_index + 0.01)*10)); // Zobrazení aktuální hodnoty hloubk modulace na bargraf


    __HAL_GPIO_EXTI_CLEAR_IT(TLAC_INC);// Vymazání příznaku přerušení
    __HAL_GPIO_EXTI_CLEAR_IT(TLAC_DEC); // Vymazání příznaku přerušení

}



//------------------------------------------------- Funkce pro zobrazení hloubky modulace na bragrafu ----------------------------------------------------//
void bar_graph_0_10 (uint16_t data) // Zobrazení hloubky modulace na bargrafu
{
    switch (data)
    {
    case 0:
        spi_send_data(&SPI3_HANDLE, 0x000); // 0
        break;
    case 1:
        spi_send_data(&SPI3_HANDLE, 0x200); // 0.1
        break;
    case 2:
        spi_send_data(&SPI3_HANDLE, 0x300); // 0.2
        break;
    case 3:
        spi_send_data(&SPI3_HANDLE, 0x380); // 0.3
        break;
    case 4:
        spi_send_data(&SPI3_HANDLE, 0x3C0); // 0.4
        break;
    case 5:
        spi_send_data(&SPI3_HANDLE, 0x3E0); // 0.5
        break;
    case 6:
        spi_send_data(&SPI3_HANDLE, 0x3F0); // 0.6
        break;
    case 7:
        spi_send_data(&SPI3_HANDLE, 0x3F8); // 0.7
        break;
    case 8:
        spi_send_data(&SPI3_HANDLE, 0x3FC); // 0.8
        break;
    case 9:
        spi_send_data(&SPI3_HANDLE, 0x3FE); // 0.9
        break;
    case 10:
        spi_send_data(&SPI3_HANDLE, 0x3FF); // 1
        break;
    }

    HAL_GPIO_WritePin(GPIOD,STROBE,GPIO_PIN_SET); // Nahrání dat do posuvného registru
    HAL_GPIO_WritePin(GPIOD,STROBE,GPIO_PIN_RESET);
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------//
//-------------------------------------------------- Nastavení Timeru 1 jako hlavního timeru ------------------------------------------------//
void HAL_TIM1_PWM_CH1_init()
{
    // Nastavení výstupního pinu PWM1_CH1, výstup PWM zároveň slouží jako CS pin pro MCP4921
    PWM1_GPIO_Config.Pin = SPI1_CS;
    PWM1_GPIO_Config.Mode = GPIO_MODE_AF_PP;
    PWM1_GPIO_Config.Speed = GPIO_SPEED_FAST;
    PWM1_GPIO_Config.Alternate = GPIO_AF1_TIM1;
    PWM1_GPIO_Config.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOA, &PWM1_GPIO_Config); // Inicializace portu

    //Základní nastavení Timeru 1
    TIM_1_setup.Instance = TIM1; // Timer 1
    TIM_1_setup.Init.Prescaler = 1; // Delička - čítá hodinový signál 50MHz
    TIM_1_setup.Init.CounterMode = TIM_COUNTERMODE_UP;
    TIM_1_setup.Init.Period = 82; // Nastavení periody čítání -  50MHz / 600 kHz = 83 - 1 = 82
    TIM_1_setup.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // Bez děličky
    HAL_TIM_Base_Init(&TIM_1_setup); //Incializace Timeru 1


    TIM_1_CH1.OCMode = TIM_OCMODE_PWM1; // Nastavení shody PWM
    TIM_1_CH1.Pulse = 75; // Nastavení střídy
    TIM_1_CH1.OCPolarity = TIM_OCPOLARITY_LOW;
    TIM_1_CH1.OCFastMode = TIM_OCFAST_DISABLE;
    HAL_TIM_PWM_ConfigChannel(&TIM_1_setup, &TIM_1_CH1, TIM_CHANNEL_1); //Incialiazce výstupu Timeru 1

    // konfigurace Timeru 1 jako imeru časovače, který řídí Timer 2
    TIM_1_MASTER.MasterOutputTrigger = TIM_TRGO_UPDATE;
    TIM_1_MASTER.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
    HAL_TIMEx_MasterConfigSynchronization(&TIM_1_setup, &TIM_1_MASTER);

    // Nastavení DMA pro přenos dat z paměti do registru SPI1, data jsou přenášena vždy, když přeteče Timer 1
    TIM_1_SPI_DMA.Instance = DMA2_Stream5;
    TIM_1_SPI_DMA.Init.Channel = DMA_CHANNEL_6;
    TIM_1_SPI_DMA.Init.Direction = DMA_MEMORY_TO_PERIPH;
    TIM_1_SPI_DMA.Init.PeriphInc = DMA_PINC_DISABLE;
    TIM_1_SPI_DMA.Init.MemInc = DMA_MINC_ENABLE;
    TIM_1_SPI_DMA.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    TIM_1_SPI_DMA.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    TIM_1_SPI_DMA.Init.Mode = DMA_CIRCULAR;
    TIM_1_SPI_DMA.Init.Priority = DMA_PRIORITY_HIGH;
    TIM_1_SPI_DMA.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    HAL_DMA_Init(&TIM_1_SPI_DMA);

    __HAL_LINKDMA(&TIM_1_setup,hdma[TIM_DMA_ID_UPDATE],TIM_1_SPI_DMA); // Spouštení přenosu při přetečení timeru 1

    __HAL_TIM_ENABLE_DMA(&TIM_1_setup, TIM_DMA_UPDATE); // Povolení DMA 2
}
//-------------------------------------------------- Nastavení Timeru 2 jako podřízený timer -------------------------------------------------//
void HAL_TIM2_PWM_CH1_init()
{
    // Nastavení výstupního pinu PWM2_CH1, výstup PWM zároveň slouží jako CS pin pro MCP3201
    PWM2_GPIO_Config.Pin = SPI2_CS;
    PWM2_GPIO_Config.Mode = GPIO_MODE_AF_PP;
    PWM2_GPIO_Config.Pull = GPIO_NOPULL;
    PWM2_GPIO_Config.Speed = GPIO_SPEED_LOW;
    PWM2_GPIO_Config.Alternate = GPIO_AF1_TIM2;
    HAL_GPIO_Init(GPIOA, &PWM2_GPIO_Config);

    //Základní nastavení Timeru 2
    TIM_2_setup.Instance = TIM2; // Timer 2
    TIM_2_setup.Init.Prescaler = 0; //Bez děličky kmitočtu - vstupní clock je odvozen od TIM 1 - tudíž 600kHz
    TIM_2_setup.Init.CounterMode = TIM_COUNTERMODE_UP;
    TIM_2_setup.Init.Period = 14; // Nastavení periody čítání = 600 kHz / 40 kHz = 15 - 1 = 14
    TIM_2_setup.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    HAL_TIM_Base_Init(&TIM_2_setup); // Inicializace Timeru 2

    TIM_2_CH1.OCMode = TIM_OCMODE_PWM1; // Nastavení shody PWM
    TIM_2_CH1.Pulse = 14; // Nastavení střídy
    TIM_2_CH1.OCPolarity = TIM_OCPOLARITY_LOW;
    TIM_2_CH1.OCFastMode = TIM_OCFAST_DISABLE;
    HAL_TIM_PWM_ConfigChannel(&TIM_2_setup, &TIM_2_CH1, TIM_CHANNEL_1); // Initialization TIM2_PWM_output_channel_1

    // Konfigurace Timeru 2 jako podřízeného timeru, podřízen je přímo Timeru 1
    TIM_2_SLAVE.SlaveMode = TIM_SLAVEMODE_GATED;
    TIM_2_SLAVE.InputTrigger = TIM_TS_ITR0;
    HAL_TIM_SlaveConfigSynchronization(&TIM_2_setup, &TIM_2_SLAVE);

    HAL_NVIC_SetPriority(TIM2_IRQn,0,0); // Nastavení přerušení s nejvyšší prioritou
    HAL_NVIC_EnableIRQ(TIM2_IRQn);

    __HAL_TIM_ENABLE_IT(&TIM_2_setup,TIM_IT_UPDATE); // Vyvolání přerušení po přetečí Timeru 2
}
