#include <stm32f7xx.h>

const signed char __pll_main_div_q_val[] = {-1, -1, 2, 3, 4, 5, 6, 7, 8 ,9, 10, 11, 12, 13, 14, 15};
const signed char __pll_main_div_p_val[] = {-1, -1, 0, -1, 1, -1, 2, -1, 3};
const signed char __mco_div_val[] = {-1, 0, 4, 5, 6, 7};
const signed char __apb_presc_val[] = {-1, 0, 4, -1, 5, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, 7};
const signed char *__pll_i2s_div_p_val = __pll_main_div_p_val;
#define SYSINIT_MAIN_I2S_PLL_DIV_M_MIN (2)
#define SYSINIT_MAIN_I2S_PLL_DIV_M_MAX (63)
#define SYSINIT_MAIN_I2S_PLL_MULT_N_MIN (2)
#define SYSINIT_MAIN_I2S_PLL_MULT_N_MAX (432)
#define SYSINIT_MAIN_I2S_PLL_SRC_HSE (1)
#define SYSINIT_MAIN_I2S_PLL_SRC_HSI (0)

#define SYSINIT_MCO2_SRC_SYSCLK (0)
#define SYSINIT_MCO2_SRC_PLLI2S (1)
#define SYSINIT_MCO2_SRC_HSE (2)
#define SYSINIT_MCO2_SRC_PLL (3)

#define SYSINIT_MCO1_SRC_HSI (0)
#define SYSINIT_MCO1_SRC_LSE (1)
#define SYSINIT_MCO1_SRC_HSE (2)
#define SYSINIT_MCO1_SRC_PLL (3)

#define SYSINIT_I2S_SRC_PLLI2S (0)
#define SYSINIT_I2S_SRC_CKIN (1)

#define SYSINIT_SYSCLK_SRC_HSI (0)
#define SYSINIT_SYSCLK_SRC_HSE (1)
#define SYSINIT_SYSCLK_SRC_PLL (2)

enum sysinit_ahb_presc {DIV1 = 0, DIV2 = 8, DIV4 = 9, DIV8 = 10, DIV16 = 11, DIV64 =12, DIV128 = 13, DIV256 = 14, DIV512 = 15};

struct clock_config {
	uint32_t hsi_enable : 1;
	uint32_t hse_enable : 1;
	uint32_t lsi_enable : 1;
	uint32_t lse_enable : 1;
	uint32_t pll_sai_on : 1;
	uint32_t pll_i2s_on : 1;
	uint32_t pll_main_on : 1;
	uint32_t css_on	: 1;
	uint32_t hse_bypass : 1;
    uint32_t lse_bypass : 1;
	uint32_t hsi_trim : 5;
	/* Main PLL Conf */
	uint32_t pll_main_i2s_src : 1;
	uint32_t pll_main_div_q : 4; /* true value */
	uint32_t pll_main_div_p : 3; /* true value */
	uint32_t pll_main_mult_n : 9;
    uint32_t pll_div_m : 6;
	/* MCO Outputs */
	uint32_t mco2_sel : 2;
	uint32_t mco2_presc : 3;
	uint32_t mco1_sel : 2;
	/* I2S clock selection */
	uint32_t i2s_src : 1;
	/* RTC */
	uint32_t rtc_hse_div_1_meg : 5;
    uint32_t rtc_clock_en : 1;
	/* APB */
	uint32_t apb1_presc : 5;
	uint32_t apb2_presc : 5;
	/* Systemclock */
	uint32_t sysclk_src : 2;
    /* PLLI2S */
    uint32_t pll_i2s_r : 3;
    uint32_t pll_i2s_q : 4;
    uint32_t pll_i2s_p : 4; /* true value */
    uint32_t pll_i2s_mult : 9;
    /* PLLSAI */

	/* AHB */
	enum sysinit_ahb_presc ahb_presc;
};


#define VECT_TAB_OFFSET (0x0)

static void __init_default_clocks(void)
{
	 /* Reset the RCC clock configuration to the default reset state ------------*/
  /* Set HSION bit */
  RCC->CR |= (uint32_t)0x00000001;

  /* Reset CFGR register */
  RCC->CFGR = 0x00000000;

  /* Reset HSEON, CSSON and PLLON bits */
  RCC->CR &= (uint32_t)0xFEF6FFFF;

  /* Reset PLLCFGR register */
  RCC->PLLCFGR = 0x24003010;

  /* Reset HSEBYP bit */
  RCC->CR &= (uint32_t)0xFFFBFFFF;

  /* Disable all interrupts */
  RCC->CIR = 0x00000000;

  /* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
  SCB->VTOR = RAMDTCM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
}


void __system_init(void)
{
	/* FPU settings ------------------------------------------------------------*/
  #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
    SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
  #endif

 __init_default_clocks();
 
}
