/* Project L476_ats_blink for STM32L476 mounted on Nucleo board:
 * the user LED (mounted on pin PA-5) is flashed every second for 50 ms.
 * The time base is provided by Systick (1000 ticks per second).
 * The clock configuration is the default one (Sysclk = 80 MHz, derived from MSI and PLL).
 */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
// #if defined(USE_FULL_ASSERT)
// #include "stm32_assert.h"
// #endif /* USE_FULL_ASSERT */

#include "gpio.h"

// systick interrupt handler
volatile uint32_t msTicks = 0;
volatile uint8_t expe = 2;
volatile uint8_t blue_mode = 0;

void SysTick_Handler()
{
  if	( BLUE_BUTTON() ){
			blue_mode = 1 ;
  }

  msTicks++;                                                /* See startup file startup_LPC17xx.s for SysTick vector */
  if (msTicks == 5 * expe){
	  LED_GREEN(0);
  }else if(msTicks >= 200){
	  msTicks = 0;
	  LED_GREEN(1);
  }
 if(expe == 2){
	 CLK_TOGGLE();
 }
}




int main(void)
{
//	if (RCC->BDCR & RCC_BDCR_LSEON) {
//			LL_APB1_GRP1_EnableClock( LL_APB1_GRP1_PERIPH_PWR );
//			LL_PWR_EnableBkUpAccess();
//
//			//expe = register RTC
//			expe = RTC->BKP0R;
//			if (expe == 0){
//				expe = 1;
//				RTC->BKP0R = expe;
//			}else if (expe != 0 && BLUE_BUTTON()){
//				expe ++;
//				RTC->BKP0R = expe;
//			}
//	}else{
//		SystemClock_Config_24M_LSE();
//		expe = 1;
//		LL_APB1_GRP1_EnableClock( LL_APB1_GRP1_PERIPH_PWR );
//		LL_PWR_EnableBkUpAccess();
//		RTC->BKP0R = expe;
//	}
//	LL_PWR_DisableBkUpAccess();
	switch(expe){
			case 1:
				/* Configure the system clock */
				SystemClock_Config_80M();
				break;
			case 2:
				/* Configure the system clock */
				SystemClock_Config_24M_LSE();
				break;
			}




// config GPIO
GPIO_init();

// init systick timer (tick period at 1 ms)
LL_Init1msTick( SystemCoreClock );
LL_SYSTICK_EnableIT();

//Setup Sleep mode
LL_LPM_EnableSleep();
//LL_LPM_EnableSleepOnExit();

while (1)  {
	if (blue_mode){
		switch(expe){
					case 1:
						__WFI();
						break;
					case 2:
						LL_RCC_MSI_EnablePLLMode();
						break;
					}

		}
	}
}

/**
  * @brief System Clock Configuration
  * @retval None
  * 24Mhz + RTC + LSE
  */
void SystemClock_Config_24M_LSE(void)
{
  LL_FLASH_SetLatency(LL_FLASH_LATENCY_1);
  while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_1)
  {
  }
  LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
  LL_RCC_MSI_Enable();

   /* Wait till MSI is ready */
  while(LL_RCC_MSI_IsReady() != 1)
  {

  }

  LL_RCC_LSE_Enable();

    /* Wait till LSE is ready */
   while(LL_RCC_LSE_IsReady() != 1)
   {

   }
  LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
  LL_RCC_EnableRTC();

  LL_RCC_MSI_EnableRangeSelection();
  LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_6);
  LL_RCC_MSI_SetCalibTrimming(0);
//  LL_RCC_MSI_EnablePLLMode();
  LL_PWR_EnableBkUpAccess();
  LL_RCC_ForceBackupDomainReset();
  LL_RCC_ReleaseBackupDomainReset();
  LL_RCC_LSE_SetDriveCapability(LL_RCC_LSEDRIVE_LOW);

  LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_MSI, LL_RCC_PLLM_DIV_1, 24, LL_RCC_PLLR_DIV_4);
  LL_RCC_PLL_EnableDomain_SYS();
  LL_RCC_PLL_Enable();

   /* Wait till PLL is ready */
  while(LL_RCC_PLL_IsReady() != 1)
  {

  }
  LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);

   /* Wait till System clock is ready */
  while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
  {

  }
  LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
  LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
  LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
  LL_SetSystemCoreClock(24000000);

   /* Update the time base */
  if (HAL_InitTick (TICK_INT_PRIORITY) != HAL_OK)
  {
//    Error_Handler();
  }
}


void SystemClock_Config_80M(void)
{
  LL_FLASH_SetLatency(LL_FLASH_LATENCY_4);
  while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_4)
  {
  }
  LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
  LL_RCC_MSI_Enable();

   /* Wait till MSI is ready */
  while(LL_RCC_MSI_IsReady() != 1)
  {

  }
  LL_RCC_MSI_EnableRangeSelection();
  LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_6);
  LL_RCC_MSI_SetCalibTrimming(0);
  LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_MSI, LL_RCC_PLLM_DIV_1, 40, LL_RCC_PLLR_DIV_2);
  LL_RCC_PLL_EnableDomain_SYS();
  LL_RCC_PLL_Enable();

   /* Wait till PLL is ready */
  while(LL_RCC_PLL_IsReady() != 1)
  {

  }
  LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);

   /* Wait till System clock is ready */
  while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
  {

  }
  LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
  LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
  LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
  LL_SetSystemCoreClock(80000000);

   /* Update the time base */
  if (HAL_InitTick (TICK_INT_PRIORITY) != HAL_OK)
  {
//    Error_Handler();
  }
}
