 /*
U2RX láb= RF4 bemenet
U2TX láb= RF5 kimenet
 */

#include <p24fj128ga010.h>
#include "functions.h"


_CONFIG1 (JTAGEN_OFF & FWDTEN_OFF)
_CONFIG2 (POSCMOD_HS & FNOSC_PRIPLL)	//32 MHz


#define FW_VER	   50					//aktuális firmware verzió
#define COMM_FW	   0b10000000			//firmware verzió utasítás
#define COMM_EN	   0b10000001			//send enable-höz parancs a géptől
#define COMM_FREK  0b10000010			//frekvenciaállítás utasítása
#define COMM_DUTY  0b10000011   		//duty cycle utasítása

void InitPWM(int periodreg, int duty);
void InitUART2(void);
void InitUARTInt(void);
void SendUART2(int c);
void SendUART2_8 (char c);
void SendCD(int command,int data);
int GetUART2 (void);

//globális változók

volatile unsigned int sendenable=0;			//ezzel engedélyezzük a PC hatására az UARTON az adatok küldését
volatile unsigned int incoming=999;			//bejövő adat
volatile unsigned int inCMD=999;				//bejövő utasítás
volatile unsigned int PC_SW=0;				//ebbe tárolja el a PC-s szoftver verziót, ha kell
volatile unsigned int period=100;			//period regiszter segédváltozója
volatile unsigned int dutycycle=50;			//OC1RS regiszter előváltozója

	

int main(void)
{
	
	TRISD=0x0;		//RD0 láb kimenet
	delay_ms(10);
	TRISF=0x0;		//RF5 láb (U2TX) kimenet
	delay_ms(10);
	TRISFbits.TRISF4=1;		//RF4 láb (U2RX) bemenet
	TRISAbits.TRISA0=0;		//RA0 lábon LED van
	TRISAbits.TRISA7=0;		//RA7 lábon LED van
	TRISAbits.TRISA6=0;		//teszthez
	InitPWM(period,dutycycle);		//100 kHz-es frekvencia, 50%-os kitöltési tényező
	InitUART2();
	PMCONbits.PMPEN=0;
	
	InitUARTInt();


	while(1)
	{
		if(sendenable==0)
		{
		}
		else if(sendenable==1)			//kimenő parancsok és adatok
		{
			SendCD(COMM_FREK,period);			//itt az interruptól kapott period és dutycycle értékekkel dolgozik
			LATAbits.LATA7=0;				// 7. LED kikapcsolása
			LATAbits.LATA0=1;				//világítson a 0. LED
			delay_ms(500);
			SendCD(COMM_DUTY,dutycycle);
			LATAbits.LATA0=0;
			LATAbits.LATA7=1;
			delay_ms(500);
		}
			
	}
	return 1;
}


void _ISR _U2RXInterrupt(void)			//beérkező adat esetén interrupt
{
	IFS1bits.U2RXIF=0;	
	incoming=U2RXREG;		//beletöltjük a beérkezett adatot
	LATAbits.LATA6=1;		//teszthez
	if((incoming>>7))			//ha ez igaz, tehát a 8. bit 1 --> utasításról van szó
	{
	
		inCMD=incoming;		//betároljuk az utasításba
		switch (inCMD)
		{
			case COMM_FW: 
							while(U2STAbits.UTXBF);		
							U2TXREG=FW_VER;
						//	SendUART2(FW_VER);		//elküldi a saját firmware verzióját
							break;
			case COMM_EN:
							sendenable=1;			//engedélyezi az adatok küldését a PC felé
							break;
			case COMM_FREK: 
							break;					//mert már úgyis beállítottuk az inCMD értéket, itt nem kell
			case COMM_DUTY:
							break;					//-||-

			default: break;							//majd ide berakhatunk egy sendenable=0 utasítást, ha megy a többi
		}	
	}
	else					//tehát ha adatról van szó, már egyből kezelhető
	{
		switch(inCMD)
		{
			case COMM_FW:
							PC_SW=incoming;			//ekkor a bejövő adat a PC sw verziója
							break;
			case COMM_EN: 
							break;				//ilyen elvileg nem történhet
			case COMM_FREK: 
							period=incoming;	//beletöltjük a period regiszter előváltozójába a kívánt értéket
							break;
			case COMM_DUTY:
							dutycycle=incoming;
							break;

			default: break;
		}
	}



	IFS1bits.U2RXIF=0;		//interrupt flag törlése a végén
}

void _ISR _U2ErrInterrupt(void)
{
	U2STAbits.OERR=0;

	IFS4bits.U2ERIF=0;
}







void InitPWM(int periodreg, int duty)
{
	OC1CON=0x0;		//kikapcsolja előtte az Output COmpare modult, TIMER 2 használata
	OC1R=(unsigned int)(periodreg*duty/100);			//duty cycle által meghatározott kitöltési tényező
	OC1RS=(unsigned int)(periodreg*duty/100);
 //	OC1R=79;		//a compare register beállítása (indítás előtt)
 //	OC1RS=79;		//secondary compare register beállítása
	OC1CONbits.OCM=0b110;	//output compae mód kiválasztása: PWM
	PR2=periodreg;
	//PR2=159;		//számolások alapján 100 kHz-hez 32 MHz fosc mellett
					//prescaler: 1:1
	T2CONbits.TON=1;		//elindítása a fenti beállításokkal
}



void InitUART2(void)
{
	U2BRG=103;		//képlet alapján, 9600bps, BRGH=0, 16 MHz Fcy
	U2MODEbits.UARTEN=1;	//modul aktiválása, 1 Stop bit
	U2MODEbits.UEN=0b00;	//egyelőre hardware handshake lábak nem kellenek
	U2MODEbits.PDSEL=0b00;	//8 bites,nincs paritás
	//mivel többi bitja alapból 0 és az most jó, ezért hagyjuk
	U2STAbits.UTXISEL1=0;		//intterrupt lesz ha legalább egy üres hely van a bufferben
	U2STAbits.UTXISEL0=0;
	U2STAbits.UTXEN=1;		//küldés engedélyezése, a lábat az UART használja
	U2STAbits.URXISEL1=0;		//fogadáskor akkor lesz interrupt, ha adat érkezik a bufferbe
								//mindegy mennyi van benne
	U2STAbits.ADDEN=0;			//address detection nem kell
	U2STAbits.OERR=0;			//overrun error kezdeti letörlése
	//mivel bekapcsoltuk a fogadást, ezért elején le kell trölnünk az ehhez tartozó flaget
//	IFS1bits.U2TXIF=0;			//transmit interrupt flag törlése
}

void InitUARTInt(void)		//UART-hoz tartozó interrupt inicializálása, inkább majd a fogadáshoz kell interruptot írni
{
	//Transzmitternek
	IEC1bits.U2TXIE=0;		//engedélyezés egyelőre nem
	IPC7bits.U2TXIP=4;		//prioritása 4
	IFS1bits.U2TXIF=0;		//interrupt flag törlése
	// vevőnek
	IEC1bits.U2RXIE=1;		//a vevő interruptjának engedélyezése
	IPC7bits.U2RXIP=4;		// prioritása: 4, eggyel nagyobb
	//IFS1bits.U2RXIF=0;		//interrupt flag törlése
	//hibakezelőnek
	IEC4bits.U2ERIE=1;		//egyelőre nem engedélyezzük
	IPC16bits.U2ERIP=5;		//prioritása: 5
	IFS4bits.U2ERIF=0;		//interupt flag törlése
	// processzor prioritási szintje
	SRbits.IPL=0b000;	//processzor prioritás = 0
}

void SendUART2(int c)
{
	while(U2STAbits.UTXBF);		//várjon, amíg a küldő buffer tele van
	U2TXREG=c;					//beletöltjük az adatot, ebből csak annyi bitet használ fel, amennyi be van állítva (8 vagy 9)
}

void SendUART2_8 (char c)		//kifejezetten 8 bit küldésére
{
	while(U2STAbits.UTXBF);		//várjon, amíg a küldő buffer tele van
	U2TXREG=c;					//beletöltjük az adatot
}

int GetUART2 (void)
{
	return U2RXREG;		//kiolvassa a karaktert a vevő bufferből
}

void SendCD(int command,int data)		//utasítás majd utána adat küldése
{
	while(U2STAbits.UTXBF);		//várjon, amíg a küldő buffer tele van
	U2TXREG=command;					//9 bites utasítás elküldése, MSB bit=1
	delay_ms(500);				//ez később ki lesz ölve innen
	while(U2STAbits.UTXBF);
	U2TXREG=data;
}
