/**************************************************************************
Данный файл содержит объявления всякого для симуляции таймеров STM32F407xx.

**************************************************************************/
#ifndef _MATLAB_TIM_H_
#define _MATLAB_TIM_H_

#include "stm32_matlab_conf.h"
//#include "mcu_wrapper_conf.h"



/////////////////////////////---DEFINES---/////////////////////////////
/* дефайн для сдвига между первой и второй половиной CCMRx регистров */
#define TIM_OCMODE_SECOND_SHIFT                 TIM_CCMR1_OC2M_Pos - TIM_CCMR1_OC1M_Pos

///* дефайны для проверки выводить ли канал на GPIO (настроен ли GPIO на альтернативную функцию) */
//#define READ_GPIO_CRL_CNF(_reg_, _pos_)         ((_pos_ < 8)?                                                                                           \
//                                                ((((_reg_->CRL) & (GPIO_CRL_CNF0   << (_pos_       << 2u)))     >> ( _pos_      << 2u))     >> 2):      \
//                                                ((((_reg_->CRH) & (GPIO_CRL_CNF0   << ((_pos_ - 8) << 2u)))     >> ((_pos_ - 8) << 2u))     >> 2)       )

#define Check_OC1_GPIO_Output(_tims_)           (GPIO_MODE_AF_PP == GET_GPIO_CONF(_tims_->Channels.OC1_GPIOx, _tims_->Channels.OC1_PIN_SHIFT))
#define Check_OC2_GPIO_Output(_tims_)           (GPIO_MODE_AF_PP == GET_GPIO_CONF(_tims_->Channels.OC2_GPIOx, _tims_->Channels.OC2_PIN_SHIFT))
#define Check_OC3_GPIO_Output(_tims_)           (GPIO_MODE_AF_PP == GET_GPIO_CONF(_tims_->Channels.OC3_GPIOx, _tims_->Channels.OC3_PIN_SHIFT))
#define Check_OC4_GPIO_Output(_tims_)           (GPIO_MODE_AF_PP == GET_GPIO_CONF(_tims_->Channels.OC4_GPIOx, _tims_->Channels.OC4_PIN_SHIFT))

/////////////////////////////////////////////////////////////////////



///////////////////////////---STRUCTURES---//////////////////////////
/* Структура для управления Слейв Таймерами */
struct SlaveChannels
{
    unsigned TIM1_TRGO : 1;
    unsigned TIM2_TRGO : 1;
    unsigned TIM3_TRGO : 1;
    unsigned TIM4_TRGO : 1;
    unsigned TIM5_TRGO : 1;
    unsigned TIM6_TRGO : 1;
    unsigned TIM7_TRGO : 1;
    unsigned TIM8_TRGO : 1;    

};
extern struct SlaveChannels Slave_Channels; // структура для связи и синхронизации таймеров
/* Структура для моделирования каналов таймера */
struct Channels_Sim
{
    // связанные с каналами GPIO порты и пины
    GPIO_TypeDef *OC1_GPIOx;
    uint32_t OC1_PIN_SHIFT;

    GPIO_TypeDef *OC2_GPIOx;
    uint32_t OC2_PIN_SHIFT;

    GPIO_TypeDef *OC3_GPIOx;
    uint32_t OC3_PIN_SHIFT;

    GPIO_TypeDef *OC4_GPIOx;
    uint32_t OC4_PIN_SHIFT;

    // Каналы таймера
    unsigned OC1REF:1;
    unsigned OC2REF:1;
    unsigned OC3REF:1;
    unsigned OC4REF:1;
};

/* Структура для моделирования таймера */
struct TIM_Sim
{
    int Updated; // счетчик таймера
    double tx_cnt; // счетчик таймера
    double tx_step; // шаг счета за один шаг симуляции
    long long RELOAD;     // буфер, если PRELOAD = 1
    long long RepititiveCnt;     // буфер, если PRELOAD = 1
    struct Channels_Sim Channels; // структура для симуляции каналов
};
/////////////////////////////////////////////////////////////////////



///////////////////////////---FUNCTIONS---///////////////////////////

//----------------------TIMER BASE FUNCTIONS-----------------------//
/* Базовая функция для симуляции таймера: она вызывается каждый шаг симуляции */
void TIM_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS);
/* Счет таймера за один такт */
void TIMx_Count(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
/* Проверка на переполнение и дальнейшая его обработка */
void Overflow_Check(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
//-----------------------------------------------------------------//


//------------------------CHANNELS FUNCTIONS-----------------------//
/* Симуляция каналов таймера */
void Channels_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS);
/*---------------- - CAPTURE COPMARE & PWM FUNCTIONS------------------*/
/* Выбор режима CaptureCompare или PWM и симуляция для каждого канала */
void CC_PWM_Ch1_Simulation(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
void CC_PWM_Ch2_Simulation(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
void CC_PWM_Ch3_Simulation(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
void CC_PWM_Ch4_Simulation(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
/* Запись каналов таймера в порты GPIO */
void Write_OC_to_GPIO(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
/* Запись результата compare в глабальную структуру с TRIGGER OUTPUT */
void Write_TRGO(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
//------------------------------------------------------------------//


//--------------------MISC (temporary) FUNCTIONS--------------------//

void TIM_Call_IRQHandller(TIM_TypeDef* TIMx);
/* Определение источника для запуска таймера в SLAVE MODE */
void Slave_Mode_Check_Source(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
//------------------------------------------------------------------//


//------------------------SIMULINK FUNCTIONS------------------------//
// Симулирование выбранных таймеров
void Simulate_TIMs(void);
// Деинициализирование выбранных таймеров (вызывается в конце симуляции)
void TIM_SIM_DEINIT(void);
//------------------------------------------------------------------//
#endif // _MATLAB_TIM_H_
