/* Driver pro interni AD prevodnik */

#include "My_ADC.h"
#include "PIN_config.h"
#include "stm32f10x_rcc.h"									// FW pro praci s jadrem mikrokontroleru
#include "stm32f10x_gpio.h"									// FW pro praci s GPIO piny
#include "stm32f10x_adc.h"									// FW pro praci s AD prevodnikem
#include "stm32f10x_dma.h"									// FW pro praci s DMA radicem
#include "misc.h"											// FW pro praci s NVIC radicem

// Globalni promenne
extern uint16_t ADC_Hodnoty[6] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF};					// Promenna kam bude DMA ukladat namerene vysledky ADC
		
void AD_Init(void)
{
	ADC_InitTypeDef  ADC_InitStructure;						// struktura pro ADC
	DMA_InitTypeDef	 DMA_InitStructure;						// struktura pro nastaveni DMA
	NVIC_InitTypeDef NVIC_InitStructure;					// struktura pro nastaveni NVIC jednotky (preruseni od DMA1-Full-Transfer)

  	ADC_IN();												// Nastaveni pinu AD prevodniku jako analogoveho vstupu
	

	RCC_ADCCLKConfig(RCC_PCLK2_Div2);						// Nastaveni hodin pro ADC -> ADCCLK = 24/2 = 12MHz
 	RCC->APB2ENR |= (RCC_APB2Periph_ADC1);					// Povoleni hodin do A/D prevodniku
	RCC->AHBENR |= (RCC_AHBPeriph_DMA1);

	/* ADC1 Configuration -------------------------------------------------- ---*/
	ADC_InitStructure.ADC_Mode                = ADC_Mode_Independent;		// Beh AD prevodniku je nezavysly na ostatnich prevodnicich a periferiich
	ADC_InitStructure.ADC_ScanConvMode        = ENABLE;						// Povoleni Scan modu - kdyz dokonci konverzi na jednom kanalu, pokracuje na dalsi ve vybrane sekvenci
	ADC_InitStructure.ADC_ContinuousConvMode  = ENABLE;						// Po dokonceni sekvence scanu se vrati na zacatek a pokracuje od znova
	ADC_InitStructure.ADC_ExternalTrigConv    = ADC_ExternalTrigConv_None;	// Bez externi synchronizace startu konverze
	ADC_InitStructure.ADC_DataAlign           = ADC_DataAlign_Right;		// Zarovnani dat doprava - platna data v bitech 10:0
	ADC_InitStructure.ADC_NbrOfChannel        = 6;							// Pocet převadenych kanalu pri scan modu
	ADC_Init( ADC1, &ADC_InitStructure );
	
	ADC_TempSensorVrefintCmd(ENABLE);										// Aktivace teplotniho senzoru

	/* Nastaveni sekvence prevadenych kanalu */
	ADC_RegularChannelConfig(ADC1, ADC_CH_LED1, 1, ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1, ADC_CH_LED2, 2, ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1, ADC_CH_LED3, 3, ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1, ADC_CH_LED4, 4, ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1, ADC_CH_LED5, 5, ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1, ADC_CH_TEMP, 6, ADC_SampleTime_239Cycles5);

	ADC1->CR2 |= CR2_DMA_Set;												// Zapnuti DMA zadosti od AD prevodniku
	ADC1->CR2 |= CR2_ADON_Set;												// Zapnuti AD prevodniku

	/* Provedeni kalibrace prevodniku */
	ADC1->CR2 |= CR2_RSTCAL_Set;											// Reset priznaku kalibrace AD prevodniku
	while((ADC1->CR2 & CR2_RSTCAL_Set) != (uint32_t)RESET);					// Cekani na dokonceni resetu kalibrace AD prevodniku
	ADC1->CR2 |= CR2_CAL_Set;												// Start kalibrace AD prevodniku
	while((ADC1->CR2 & CR2_CAL_Set) != (uint32_t)RESET);					// Cekani na dokonceni kalibrace AD prevodniku

	/* Konfigurace DMA aby prevedene hodnoty ADC rovnou ukladal do pole v RAM */
	DMA_InitStructure.DMA_PeripheralBaseAddr = 	(uint32_t)ADC1_DR_Address;			// Nastaveni zdrojove adresy registru periferie ADC ze ktereho bude DMA cist hodnoty
	DMA_InitStructure.DMA_MemoryBaseAddr = 		(uint32_t)&ADC_Hodnoty;				// Nastaveni zdrojove adresy prvniho prvku pole v pameti do ktereho bude DMA ukladat posledni prevedenou hodnotu ADC
	DMA_InitStructure.DMA_DIR = 				DMA_DIR_PeripheralSRC;				// Zdrojem dat pro DMA je periferie, cilem je tedy pamet
	DMA_InitStructure.DMA_BufferSize = 			6;									// Delka bufferu v jednotce DataSize nastavena DMA kanalu
	DMA_InitStructure.DMA_PeripheralInc = 		DMA_PeripheralInc_Disable;			// Adresa registru periferie ze ktere se cte se nebude inkrementovat => zustane porad stejna
	DMA_InitStructure.DMA_MemoryInc = 			DMA_MemoryInc_Enable;				// Adresa v pameti se bude inkrekrementovat
	DMA_InitStructure.DMA_PeripheralDataSize = 	DMA_PeripheralDataSize_HalfWord;	// Sirka dat registru ctene periferie = 16 bitu
	DMA_InitStructure.DMA_MemoryDataSize = 		DMA_MemoryDataSize_HalfWord;		// Sirka dat ukladana do pameti = 16-bitova
	DMA_InitStructure.DMA_Mode = 				DMA_Mode_Circular;					// Ukladani do cilove pameti bude probyhat v kruhu - az se dorazi na posedni adresu, tak se zacne zase prvni
	DMA_InitStructure.DMA_Priority = 			DMA_Mode_Normal;					// Nastavena normalni priorita tohoto DMA kanalu
	DMA_InitStructure.DMA_M2M = 				DMA_M2M_Disable;					// Typ DMA prenosu neni pamet->pamet ale periferie->pamet
	DMA_Init(DMA1_Channel1, &DMA_InitStructure);									// DMA1 Kanal 1 => ADC

	DMA1_Channel1->CCR |= DMA_CCR1_EN;										// Zapnuti DMA kanalu na ktery je pripojen AD prevodnik

	ADC1->CR2 |= CR2_EXTTRIG_SWSTART_Set;									// SW odstartovani AD prevodu

	// Konfigurace DMA preruseni Full-transfer pro realizaci prumerovani namerenych hodnot ADC
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  	NVIC_Init(&NVIC_InitStructure);
	
	DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);
	DMA_ClearFlag(DMA1_FLAG_TC1);											// Vyresetovani flagu Full-transfer
}

/* -------------------------------------------------
 Funkce vrati hodnotu proudu v mA z RAW hodnoty z ADC
 ------------------------------------------------ */
uint16_t ADC_ConvertTomA(uint16_t hodnota)
{
	uint32_t Hodnota32;

	Hodnota32 = (8058*hodnota)/12;											// Vypocet skutecneho ubytku napeti
	Hodnota32 = Hodnota32/1667;												// Vypocet skutecneho proudu
	return((uint16_t)Hodnota32);
}

/* -------------------------------------------------
 Funkce vrati teplotu MCU v desetinach stupne
 ------------------------------------------------ */
uint16_t ADC_GetTempMCU(void)
{
	uint32_t Hodnota32;
	Hodnota32 = ADC_Hodnoty[ADC_VALUE_TEMP];		// 32°C = 1725	
	Hodnota32 = (((uint32_t)100*((uint32_t)3288-(uint32_t)Hodnota32))/(uint32_t)53)+(uint32_t)250;
	return((uint16_t)(Hodnota32/10));

}

/* -------------------------------------------------
 Funkce deaktivuje preruseni od DMA pro prumerovani
 namerenych hodnot ADC
 ------------------------------------------------ */
void ADC_DisableInterupt(void)
{
	DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,DISABLE);
}

/* -------------------------------------------------
 Funkce deaktivuje preruseni od DMA pro prumerovani
 namerenych hodnot ADC
 ------------------------------------------------ */
void ADC_EnableInterupt(void)
{
	DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);
}
// Konec souboru =================================================
