/*Author: Alexandre Boyer
 * Date: 14 Aug. 2024
 */
/* Clock configuratio.
 */


#include "stm32l4xx_ll_bus.h"
#include "stm32l4xx_ll_rcc.h"
#include "stm32l4xx_ll_pwr.h"
#include "stm32l4xx_ll_rtc.h"
#include "stm32l4xx_ll_cortex.h"
#include "stm32l4xx_ll_system.h"
#include "stm32l4xx_ll_utils.h"
#include "clock.h"

/**
  * @brief  System Clock Configuration
  *         The system Clock is configured as follows :
  *            System Clock source            = PLL
  *            SYSCLK(Hz)                     = 80000000
  *            HCLK(Hz)                       = 80000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 1
  *            APB2 Prescaler                 = 1
  *            MSI Frequency(Hz)              = 4000000
  *            Flash Latency(WS)              = 4
  * Input  argument Voltrange = 1 (range 1 = max internal voltage) or 2 (range 2 = min internal voltage)
  */
void SystemClock_Config_80M(int VoltRange)
{
	/* MSI activation */
	LL_RCC_MSI_Enable();			// normally, the MSI is already enabled.
	while	(LL_RCC_MSI_IsReady() != 1)
		{ }

	LL_FLASH_SetLatency(LL_FLASH_LATENCY_4);	//latency level 4 for 80MHz

	//Set the internal voltage range
	if (VoltRange == 2) {
		LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE2);
		while (LL_PWR_IsActiveFlag_VOS() ) {
		}
	}
	else {
		LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
		while (LL_PWR_IsActiveFlag_VOS() ) {
		}
	}
	
	/* Configuration of the MSI frequency */
	LL_RCC_MSI_EnableRangeSelection();

	LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_6);
	while	(LL_RCC_MSI_IsReady() != 1)
		{ }

	// Start the main PLL : clock source = MSI : 4MHz --> 80 MHz
	LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_MSI, LL_RCC_PLLM_DIV_1, 40, LL_RCC_PLLR_DIV_2);
	LL_RCC_PLL_Enable();
	LL_RCC_PLL_EnableDomain_SYS();
	while	( LL_RCC_PLL_IsReady() != 1 )
		{ }

	// PLL clock --> system clock Sysclk
	LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
	LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
	while	( LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL )
		{ }

	/* Set APB1 & APB2 prescaler*/
	LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
	LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);

	//update global variable SystemCoreClock = CPU clock frequency.
	//Necessary for the Systick configuration !
	LL_SetSystemCoreClock(80000000);
}


// Configuration of Systick timer with interrupt.
//The input argument periode_en_ticks gives the Systick timer overflow period
//in terms of number of SysClk periods.
void mySystick( unsigned int periode_en_ticks )
{
	// overflow period setting
	SysTick->LOAD  = periode_en_ticks - 1;

	// Interrupt priority
	NVIC_SetPriority( SysTick_IRQn, 7 );
	// init counter
	SysTick->VAL = 0;
	// prescale (0 ===> %8)
	SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk;
	// enable timer, enable interrupt
	SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
}

