

#include "stm32f10x.h"

/*-------------------------------------------------------*/
/*--- Eloforditoi utasitasok ----------------------------*/
/*-------------------------------------------------------*/

//#define SKALAZAS

#define LED_GREEN       0x00000200 
#define LED_BLUE     	0x00000100
#define USER_BUTTON  	0x00000001

#define ON				1
#define OFF				0

#define READY   		1
#define NOT_READY		0

#define DATA_CNT_ON_DMA 30



/*-------------------------------------------------------*/
/*--- Globalis valtozok ---------------------------------*/
/*-------------------------------------------------------*/

unsigned short int usiRawDatas[DATA_CNT_ON_DMA];
volatile unsigned int uiADC_Cal=0;

volatile unsigned char uchSendingIsReadyToGo = NOT_READY;

volatile unsigned char uchRxData=0;

/*-------------------------------------------------------*/
/*--- Fuggveny deklaraciok  -----------------------------*/
/*-------------------------------------------------------*/

void IO_Init(void);
void ADC_Init(void);
void TIM3_ADC_Trig_Init(float flSampleTimeSec);
void TIM3_Enable(void);
void TIM3_Disable(void);
void TIM3_IRQ_Enable(void);
void DMA_ADC2RAM_Init(void);
void DMA1_ADC_IRQ_Init(void);

void UART_Init(void);
void UART1_RX_IRQ_Enable(void);
void myPutUSART_modified(unsigned short int* usiData, unsigned char uchNumber);
void myPutUSART(unsigned short int* usiData, unsigned char uchNumber);

void Switch_LEDs(void);

/*-------------------------------------------------------*/
/*--- USART1 Megszakitas --------------------------------*/
/*-------------------------------------------------------*/
void USART1_IRQHandler (void)
{	
	if( (USART1->SR & USART_SR_RXNE) == USART_SR_RXNE )
	{
		uchRxData = USART1->DR;											// Erkezett bajt kiolvasasa 
		
		USART1->SR &= ~USART_SR_RXNE;									// Flag torlese
	}
}
/*-------------------------------------------------------*/
/*--- TIM3 IRQ Handler ----------------------------------*/
/*-------------------------------------------------------*/

void TIM3_IRQHandler(void)
{
	if( (TIM3->SR & TIM_SR_UIF) == TIM_SR_UIF )
	{		
		TIM3->SR &= ~TIM_SR_UIF;						// Flag torlese
	}
}

/*-------------------------------------------------------*/
/*--- DMA1 Channel1 IRQ Handler -------------------------*/
/*-------------------------------------------------------*/

void DMA1_Channel1_IRQHandler(void)
{
	//--- Ha kesz a transzfer ---
	if( (DMA1->ISR & DMA_ISR_TCIF1) == DMA_ISR_TCIF1  )
	{
		Switch_LEDs();
		
		uchSendingIsReadyToGo=READY;
		
		DMA1->IFCR  |= DMA_IFCR_CTCIF1;				// Flag torlese (1-be allitva torli)
	}
}


/*-------------------------------------------------------*/
/*--- MAIN ----------------------------------------------*/
/*-------------------------------------------------------*/
int main(void)
{
	IO_Init();
	ADC_Init();		
	TIM3_ADC_Trig_Init(0.01);
	
	DMA_ADC2RAM_Init();
	DMA1_ADC_IRQ_Init();
	
	UART_Init();									// 9600-as Baud 
	
	TIM3_IRQ_Enable();	
	UART1_RX_IRQ_Enable();
	
	while(1)
	{
		// Ha lenyomtuk a gombot es nincs aktualis ADC vs. DMA konverzio, akkor ujat inditunk
		if(  (GPIOA->IDR & USER_BUTTON) == USER_BUTTON || (uchRxData == 's') || (uchRxData == 'S') )
		{
			uchSendingIsReadyToGo = NOT_READY;
			uchRxData = 0;
			
			TIM3_Enable();
			
			while( uchSendingIsReadyToGo == NOT_READY );
			
			TIM3_Disable();
			
			#ifdef SKALAZAS
				myPutUSART_modified(&usiRawDatas[0],DATA_CNT_ON_DMA);	
			#else
				 myPutUSART(&usiRawDatas[0],DATA_CNT_ON_DMA);
			#endif	
		}
	}

}

/*-------------------------------------------------------*/
/*--- Fuggveny definiciok -------------------------------*/
/*-------------------------------------------------------*/

void IO_Init(void)
{
	RCC->APB2ENR = RCC_APB2ENR_IOPCEN + RCC_APB2ENR_IOPAEN; 		// GPIOC es GPIOA orajelenek engedelyezese
	GPIOC->CRH = 0x00000011;										// GPIOC 8-9-es laba kimenet
	
	GPIOA->CRL = 0x00000004;										// GPIOA 0 bemenet
}

/*-------------------------------------------------------*/

void ADC_Init(void)
{
	RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;								// ADC1 orajelenek engedelyezese
	
	//RCC->CFGR  |=  ;												// ADC1 orajelet lehet leosztani a APB2-bol. 
																								// Alapbol ez egy 2-esoszto, azaz 12 MHz
	
	GPIOB->CRL &= 0xFFFFFF0F;										// PB1 analog bemenet 
	
	ADC1->CR1 = 0;
																	// AWDEN=0    - Analog watchdog kikapcsolva a sima csatornakon
																	// JAWDEN=0   - Analog watchdog kikapcsolva az injected csatornakon
																	// DISCNUM=0  - Nincs discount mod, szoval a szamlalot sem kell bizergalni
																	// JDISCEN=0  - Nincs discount mod az inflected csatornan
																	// DISCEN=0   - Nincs discount mod a sima csatornakon
																	// JAUTO=0    - Nincs infelcted channel auto konverzio
																	// AWDSGL=0   - Minden csatornan engedelyezett az analog watchdog
																	// SCAN=0     - Nincs scan mod, csak 1 csatornat babralunk
																	// JEOCIE=0   - Injected csatornak interruptja letiltva
																	// AWDIE=0    - Analog watchdog interrupt letiltva
																	// EOCIE=0	  - "Konverzio kesz" nem okoz interruptot
																	// AWDCH=0    - Analog watchdog altal "orzott" csatorna
	
	ADC1->CR2 = 0x00980100;
																	// TSVREFE=1  - Homero szenzor, meg a ref fesz bekapcsolva
																	// SWSART=0   - Szoftveres konverzio start normal csatornan
																	// JSWSART=0  - Szoftveres konverzio start injected csatornan
																	// EXTTRIG=1  - Kulso trigger engedelyezve
																	// EXTSEL=4   - TIM3 TRGO bit triggereli a konverziot
																	// JEXTTRIG=0 - Nincs kulso trigger az injected-en
																	// JEXTSEL=0  - Ganz egal...
																	// ALIGN=0    - Jobbra zart eredmeny
																	// DMA=1      - DMA engedelyezese
																	// RSTCAL=0
																	// CAL=0
																	// CONT=0
																	// ADON=0

	 ADC1->SMPR1= ADC_SMPR1_SMP16_0									// Sampling time maximalis a 16-os csatornan 
							+ ADC_SMPR1_SMP16_1 
							+ ADC_SMPR1_SMP16_2;
	
	ADC1->SQR1 |= ADC_SQR1_L_0;										// Csak 1 konverzio lesz
	ADC1->SQR3 = 0x00000009;										// 1. konverziot a 9. csatornan (PB1) hajtjuk vegre
	
	ADC1->CR2 |= ADC_CR2_ADON;										// ADC bekapcsolasa (ebresztese)

	//--- ADC Kalibracio ---------
	// Elvileg a hardver levonja ezt az offset erteket az eredmenybol
	ADC1->CR2 |= ADC_CR2_CAL;											// Kalibralas inditasa
	while( (ADC1->CR2 & ADC_CR2_CAL) == ADC_CR2_CAL );					// Vegzett?
	uiADC_Cal=ADC1->DR;													// Kalibralt ertek elmentese
}

/*-------------------------------------------------------*/

void DMA_ADC2RAM_Init(void)
{
	RCC->AHBENR |= RCC_AHBENR_DMA1EN ;							// DMA1 orajelenek engedelyezese
	
	DMA1_Channel1->CPAR = (unsigned long)( &(ADC1->DR) );		// ADC11->DR regiszter cime.
	DMA1_Channel1->CMAR = (unsigned long)(&usiRawDatas[0]);   	// Cel memoriacim
	DMA1_Channel1->CNDTR = DATA_CNT_ON_DMA;				  		// Mennyi adat transzfer legyen
	
	DMA1_Channel1->CCR = 0x000035A2;								// PL=3 - Very High Channel priority
																	// 16 bites adatok mind a memorianal, mind a periferianal
																	// MINC=1 - Memoria cimnoveles a transzferek soran
																	// PINC=0 - Periferianal ilyen nincs
																	// CIRC=1 - Korkoros buffer hasznalata
																	// TCIE=1 - Transzfer kesz interrupt
																											
	DMA1_Channel1->CCR |= 0x00000001;								// DMA1 1-es csatorna engedelyezese
}

/*-------------------------------------------------------*/

void TIM3_ADC_Trig_Init(float flSampleTimeSec)
{
	unsigned int uiARR_Value=0;

	uiARR_Value = (unsigned int)( 366.2109375*flSampleTimeSec );	
	
	RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;							// TIM3 orajelenek engedelyezese
		
	TIM3->CR1 = 0x0084;											// ARPE=1 - Auto Reload Register bufferelt=>felulirasa, csak a kov. tulcsordolaskor tortenik meg							
																// DIR=0  - UpCount mode
																// OPM=0  - Nem One Pulse modban megy
																// URS=1  - Csak a tulcsordulasok es a DMA tud megszakitast okozni
																// CEN=0  - Meg nem indditottuk el...
														
	TIM3->DIER =  TIM_DIER_UIE;									// Update Event megszakitas engedelyezese
	
	TIM3->CR2 |= TIM_CR2_MMS_1;									// MMS = 0b010 => "Update event" TRGO-n jelet general  
	
	TIM3->CNT = 0;
	TIM3->PSC = 0xFFFF;											// 65536-os elooszto
	TIM3->ARR = uiARR_Value;									// Meddig szamoljunk
}

/*--------------------------------------------------------*/

void TIM3_Enable(void)
{
	TIM3->CR1 |= TIM_CR1_CEN;					// TIM3 enable
}

/*--------------------------------------------------------*/

void TIM3_Disable(void)
{
	TIM3->CR1 &= ~TIM_CR1_CEN;					// TIM3 disable
}

/*--------------------------------------------------------*/

void TIM3_IRQ_Enable(void)
{
	NVIC_EnableIRQ(TIM3_IRQn);
}

/*--------------------------------------------------------*/

void UART1_RX_IRQ_Enable(void)
{
		NVIC_EnableIRQ(USART1_IRQn);		// USART1 interrupt engedelyezese az NVIC-ben
}

/*--------------------------------------------------------*/

void UART_Init(void)
{
	
	RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
	
	// 28. oldal
	// PA9  - USART1_TX
	// PA10 - USART1_RX
	GPIOA->CRH = 0x444444A0;							// PA9  - USART1_TX: Alternate function output push-pull
														//					    		 Output mode, max 2 MHz
														// PA10 - USART1_RX: Floating input
														//									 Input mode
	
	USART1->CR1 = 0x0000002C;	   						// UE     = 0		!!!!!!
														// RXNEIE = 1
														// TE     = 1
														// RE     = 1
	
	USART1->CR2 = 0;									// 1 STOP bit
	
	USART1->CR3 = 0; 							  		 // Vetel DMA-val bekapcsolva
	
	USART1->BRR = (156<<4)+4;		        			 // 24 M/(16*9600)=156,25
														 // Mantissa: 156
														 // Fraction: 16*0,25=4
														
	USART1->CR1 |= USART_CR1_UE;			  			 // UART Enable 																	
													     // 9600-as Baud rata
}

/*--------------------------------------------------------*/

void myPutUSART_modified(unsigned short int* usiData, unsigned char uchNumber)
{
	 unsigned char i=0;
	 float flData=0.0;
	
	 unsigned char uchEgyes=0, uchTized=0, uchSzazad=0, uchEzred=0;
	
	 for(i=0;i<uchNumber;i++)
	 {
		 flData = 0.0008056640625 * (float)( usiData[i] );			// Konverzio
		 
		 uchEgyes = (unsigned char)(flData/1.0);
		 flData -= (float)uchEgyes * 1.0;
		 
		 uchTized = (unsigned char)(flData/0.1);
		 flData -= (float)uchTized * 0.1;
		 
		 uchSzazad = (unsigned char)(flData/0.01);
		 flData -= (float)uchSzazad * 0.01;
		 
		 uchEzred = (unsigned char)(flData/0.001);
		 
		 uchEgyes += 0x30;
		 uchTized += 0x30;
		 uchSzazad += 0x30;
		 uchEzred += 0x30;
		 
		 USART1->DR = uchEgyes;
		 while( (USART1->SR & USART_SR_TXE) == 0 );
		 
		 USART1->DR = ',';
		 while( (USART1->SR & USART_SR_TXE) == 0 );
		 
		 USART1->DR = uchTized;
		 while( (USART1->SR & USART_SR_TXE) == 0 );
		 
		 USART1->DR = uchSzazad;												
		 while( (USART1->SR & USART_SR_TXE) == 0 );
		 
		 USART1->DR = uchEzred;												
		 while( (USART1->SR & USART_SR_TXE) == 0 );
		 
		 USART1->DR = 0x0A;												// New Line
		 while( (USART1->SR & USART_SR_TXE) == 0 );
		 
		 USART1->DR = 0x0D;														
		 while( (USART1->SR & USART_SR_TXE) == 0 );						// Ha 1, akkor az azt jelzi, hogy ures a regiszter
	 }
}

/*--------------------------------------------------------*/

void myPutUSART(unsigned short int* usiData, unsigned char uchNumber)
{
	unsigned char i=0;
	
	for(i=0;i<uchNumber;i++)
	{
		USART1->DR = (unsigned char)( (usiData[i]>>8) & 0x00FF );		// MSB
		while( (USART1->SR & USART_SR_TXE) == 0 );
		
		USART1->DR = (unsigned char)( usiData[i] & 0x00FF );		    // LSB
		while( (USART1->SR & USART_SR_TXE) == 0 );		
		
		USART1->DR = 0x0A;												// New Line
		while( (USART1->SR & USART_SR_TXE) == 0 );
		 
		USART1->DR = 0x0D;														
		while( (USART1->SR & USART_SR_TXE) == 0 );
	}
}

/*--------------------------------------------------------*/
void DMA1_ADC_IRQ_Init(void)
{
		NVIC_EnableIRQ(DMA1_Channel1_IRQn);							// DMA1 Channel1 interrupt engedelyezese az NVIC-ben
}	

/*--------------------------------------------------------*/

void Switch_LEDs(void)
{
	static unsigned uchState=OFF;
	
	switch(uchState)
	{
		case OFF:
			GPIOC->ODR = LED_GREEN;
			uchState = ON;
			break;
							
		case ON:
			GPIOC->ODR = LED_BLUE;
			uchState = OFF;
			break;
	}
}

