/**
  ******************************************************************************
  * @file    main.c
  * @author  Ac6
  * @version V1.0
  * @date    01-December-2013
  * @brief   Default main function.
  ******************************************************************************
*/


#include "stm32f1xx.h"
#include "stm32f1xx_hal_gpio.h"
#include "stm32f1xx_hal_rcc.h"

ADC_HandleTypeDef ADC_HandleStruct;
uint32_t ADC_val;

void setup_led()
{
	GPIO_InitTypeDef GPIO_InitStruct;

	/*Configure GPIO pin : D1_Pin */
	__HAL_AFIO_REMAP_PD01_ENABLE();
	GPIO_InitStruct.Pin = GPIO_PIN_1;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}

void led_on()
{
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_RESET);
}

void led_off()
{
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_SET);
}

void enable_clocks()
{
	// Need ALL the shits
	__HAL_RCC_ADC1_CLK_ENABLE();
	__HAL_RCC_AFIO_CLK_ENABLE();
	__HAL_RCC_GPIOA_CLK_ENABLE();
	__HAL_RCC_GPIOB_CLK_ENABLE();
	__HAL_RCC_GPIOC_CLK_ENABLE();
	__HAL_RCC_GPIOD_CLK_ENABLE();
	__HAL_RCC_ADC1_CLK_ENABLE();
	__HAL_RCC_TIM1_CLK_ENABLE();
	__HAL_RCC_SPI1_CLK_ENABLE();
	__HAL_RCC_USART1_CLK_ENABLE();
	__HAL_RCC_PWR_CLK_ENABLE();
}

void setup_clocks()
{
	RCC_OscInitTypeDef RCC_OscInitStruct;
	RCC_ClkInitTypeDef RCC_ClkInitStruct;
	RCC_PeriphCLKInitTypeDef RCC_PeriphInitStruct;

	/**Initializes the CPU, AHB and APB busses clocks
	*/
	RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
	RCC_OscInitStruct.HSIState = RCC_HSI_ON;
	RCC_OscInitStruct.HSICalibrationValue = 16;
	RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
	RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
	RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
	if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
	{
		asm("bkpt 255");
	}

	/**Initializes the CPU, AHB and APB busses clocks
	*/
	RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
							  |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
	RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
	RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
	RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
	RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

	if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
	{
		asm("bkpt 255");
	}

	/**Configure the Systick interrupt time
	*/
	HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

	/**Configure the Systick
	*/
	HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

	/* SysTick_IRQn interrupt configuration */
	HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

	/* SysTick_IRQn interrupt configuration */
	HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);	__enable_irq();

#if 0 // Uncomment to confirm sysclk freq on PA8
	// SYSCLK output on PA8
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.Pin = GPIO_PIN_8;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

	HAL_RCC_MCOConfig(RCC_MCO, RCC_MCO1SOURCE_SYSCLK, RCC_MCODIV_1);
#endif



	// Initializes ADC peripheral clock
	RCC_PeriphInitStruct.AdcClockSelection = RCC_ADCPCLK2_DIV6; // 64/6 = 16.66666 MHz ADC clock
	RCC_PeriphInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
	if(HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphInitStruct) != HAL_OK)
	{
		asm("bkpt 255");
	}
}

void setup_adc()
{
	GPIO_InitTypeDef GPIO_InitStruct;
	ADC_ChannelConfTypeDef ADC_ChannelStruct;

	/* Configure GPIO pin : PA3 */
	GPIO_InitStruct.Pin = GPIO_PIN_3;
	GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

	/* Configure GPIO pin : PA4 */
	GPIO_InitStruct.Pin = GPIO_PIN_4;
	GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

	/* Configure GPIO pin : PA5 */
	GPIO_InitStruct.Pin = GPIO_PIN_5;
	GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(ADC1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(ADC1_IRQn);

	ADC_HandleStruct.Instance = ADC1;
	ADC_HandleStruct.Init.ContinuousConvMode = ENABLE;
	ADC_HandleStruct.Init.DiscontinuousConvMode = DISABLE;
	ADC_HandleStruct.Init.DataAlign = ADC_DATAALIGN_RIGHT;
	ADC_HandleStruct.Init.ExternalTrigConv = ADC_SOFTWARE_START;
	ADC_HandleStruct.Init.NbrOfConversion = 1;
	ADC_HandleStruct.Init.ScanConvMode = DISABLE;
	if(HAL_ADC_Init(&ADC_HandleStruct) != HAL_OK)
	{
		asm("bkpt 255");
	}

	ADC_ChannelStruct.Channel = ADC_CHANNEL_16;
	ADC_ChannelStruct.Rank = ADC_REGULAR_RANK_1;
	ADC_ChannelStruct.SamplingTime = ADC_SAMPLETIME_13CYCLES_5;
	if(HAL_ADC_ConfigChannel(&ADC_HandleStruct, &ADC_ChannelStruct) != HAL_OK)
	{
		asm("bkpt 255");
	}

	// Enable other channels when one works
#if 0
	ADC_ChannelStruct.Channel = ADC_CHANNEL_4;
	ADC_ChannelStruct.Rank = ADC_REGULAR_RANK_2;
	ADC_ChannelStruct.SamplingTime = ADC_SAMPLETIME_13CYCLES_5;
	if(HAL_ADC_ConfigChannel(&ADC_HandleStruct, &ADC_ChannelStruct) != HAL_OK)
	{
		asm("bkpt 255");
	}

	ADC_ChannelStruct.Channel = ADC_CHANNEL_5;
	ADC_ChannelStruct.Rank = ADC_REGULAR_RANK_3;
	ADC_ChannelStruct.SamplingTime = ADC_SAMPLETIME_13CYCLES_5;
	if(HAL_ADC_ConfigChannel(&ADC_HandleStruct, &ADC_ChannelStruct) != HAL_OK)
	{
		asm("bkpt 255");
	}
#endif
}

int main(void)
{
	HAL_Init();
	enable_clocks();
	setup_led();
	setup_clocks();
	setup_adc();
	led_off();

	while(1)
	{
		// ADC measurment & display value
		HAL_ADC_Start(&ADC_HandleStruct);
		HAL_ADC_PollForConversion(&ADC_HandleStruct, 1000); // 1000 is timeout in miliseconds
		ADC_val = HAL_ADC_GetValue(&ADC_HandleStruct);
		HAL_ADC_Stop(&ADC_HandleStruct);
	}
}
