/*
 * UART_LinkLayer_V10.h
 *
 * Created: 30.8.2015 19:06:44
 *  Author: Chenda
 */ 

#ifndef UART_LINKLAYER_V10_H_
	#define UART_LINKLAYER_V10_H_
	
	#include <stdbool.h>
	
	/************************************************************************/
	/* Link layer protocol version                                          */
	/************************************************************************/
	#define UART_LINK_LAYER_VER		101			// V1.00
	
	/************************************************************************/
	/* Link layer definitions                                               */
	/************************************************************************/
	#define UART_FRAME_START_MARK	0xAB
	#define UART_FRAME_STOP_MARK	0xBA
	#define UART_FRAME_SUBST_MARK	0x80
	#define UART_FRAME_SUBST_0X80	0x80
	#define UART_FRAME_SUBST_0XAB	0x81
	#define UART_FRAME_SUBST_0XBA	0x82
	
	/************************************************************************/
	/* Link layer error number                                              */
	/************************************************************************/
	#define UART_E_NO_ERROR			1
	#define UART_E_FRAME			2
	#define UART_E_FRAME_OVF		3
	#define UART_E_RX_TIMEOUT		4
	#define UART_E_RX_UNEXP_DATA	5			// UnExpected data receiving (missing start mark)
	#define UART_E_RX_START_MARK	6
	#define UART_E_RX_STOP_MARK		7
	#define UART_E_TX_LOW_PAC_LEN	8			// low length of packet (data before encoding and sending to bus)
	#define UART_E_TX_HIG_PAC_LEN	9			// high length of packet (data before encoding and sending to bus)
	#define UART_E_RX_LOW_FRM_LEN	10			// low length of frame (encoded data coming from bus)
	#define UART_E_RX_HIG_FRM_LEN	11			// high length of frame (encoded data coming from bus)
	#define UART_E_RX_DECODING		12
	#define UART_E_RX_EVEN_LEN		13
	#define UART_E_RX_CHKSUM		14
	#define UART_E_RX_MSG_TOUT		15
	
	/************************************************************************/
	/* Frame size max 254 bytes                                             */
	/************************************************************************/
	#define UART_PACKET_LEN_MIN		3
	#define UART_PACKET_LEN_MAX		120
	#define UART_FRAME_LEN_MIN		7
	#define UART_FRAME_LEN_MAX		(UART_PACKET_LEN_MAX*2+3)	// max povolena velikost 253 - ne 255 kvuli pretikani indexu bufferu
	#define UART_DEC_DATA_SIZE		(UART_PACKET_LEN_MAX+2)

	/************************************************************************/
	/* Link layer structure                                                 */
	/************************************************************************/
	
	struct stLL_UARTx
	{
		// Link layer - access only for LinkLayer functions
		// - RX
		struct LinkLayer
		{
			bool IsMasterPeriphery;
			bool DisTxWhileIdle;			// disabling TX if slave bus
			bool DisRxWhileTxOperate;
			bool RS485;					// Set dir before TX and clear after TX finished
										// optionally disable RX while TX operate
			struct LL_Receiver
			{
				volatile uint8_t MissedRxWhileException;
				volatile uint8_t Buff[UART_FRAME_LEN_MAX];
				volatile uint8_t Index;
				volatile bool FrameReceived;
				volatile bool FrameReceiving;
				bool DisableIt;
				// Message timeout
				volatile uint8_t TickForToutError;
				volatile uint8_t CurrentTicks;
				volatile bool ExpectRespondMsg;
				// error handling
				volatile bool E;
				volatile uint8_t E_Nr;
			}RX;
			struct LL_Transmitter
			{
				volatile uint8_t Buff[UART_FRAME_LEN_MAX];
				volatile uint8_t Index;
				volatile bool FrameTransmitted;
				volatile bool FrameTransmitting;
				bool LaunchIt;
				bool DisableIt;
			}TX;	
		}LL;			
		
		// Interface
		struct LinkLayerInterface
		{
			struct Interface_Receiver
			{
				bool Busy;		// informativni hodnota
				uint8_t MissedRx;
				uint8_t Buff[UART_DEC_DATA_SIZE];
				uint16_t PacketLength;
				bool PacketReceived;
				// error handling
				uint8_t E_Nr;
			}RX;
			struct Interface_Transmitter
			{
				bool Busy;						// higher layer - read only 
				uint8_t Buff[UART_DEC_DATA_SIZE];
				uint16_t PacketLength;
				bool PacketTransmitted;
				bool InitiateTransmition;
				// Respond message timeout
				bool ExpectRespond;
				// error handling
				uint8_t E_Nr;
			}TX;
		}LL_Int;		
	};
	

	/************************************************************************/
	/* Link layer functions                                                 */
	/************************************************************************/
	struct stLL_UARTx* UART_LL_U1_INT (void);
	void UART_LL_U1 (void);

#endif /* UART_LINKLAYER_V10_H_ */

/************************************************************************/
/* main.c file ISR & setup template                                     */
/************************************************************************/

/*
// SETUP
// link layer - physical layer
mMaBusRs485Dir_Enab();
mMaBusRs485Dir_In();
spLL_UART_MasterBus->LL.DisTxWhileIdle = false;
spLL_UART_MasterBus->LL.RS485 = false;
spLL_UART_MasterBus->LL.DisRxWhileTxOperate = false;
// link layer
spLL_UART_MasterBus->LL.IsMasterPeriphery = false;
// network layer
spNL_UART_MasterBus->NL.PeriphAddress = 0x01;
// periphery setup
ui16Tmp = UART_CalculateBaudRate(DEF_UART_MASTERBUS_BR);
uiBrLow = (uint8_t)ui16Tmp;
uiBrHigh = (uint8_t)(ui16Tmp>>8);
mUart0BaudRate(uiBrLow,uiBrHigh);
mUart0NoBit_8();
mUart0Rx_Enab();
mUart0Tx_Enab();
mUart0IntRx_Enab();

// PeripheryLauncher()
void PeripheryLauncher(void)
{
	if (sLL_UART_MasterBus.LL.TX.LaunchIt) {
		sLL_UART_MasterBus.LL.TX.LaunchIt = false;
		if(sLL_UART_MasterBus.LL.DisTxWhileIdle) {
			mUart0Tx_Enab();
		}
		if(sLL_UART_MasterBus.LL.RS485) {
			mMaBusRs485Dir_Out();
		}
		if(sLL_UART_MasterBus.LL.DisRxWhileTxOperate) {
			mUart0Rx_Dis();
		}
		mUart0IntUdrEmp_Enab();
	}
	if (sLL_UART_SlaveBus.LL.TX.LaunchIt) {
		sLL_UART_SlaveBus.LL.TX.LaunchIt = false;
		if(sLL_UART_SlaveBus.LL.DisTxWhileIdle) {
			mUart2Tx_Enab();
		}
		if(sLL_UART_SlaveBus.LL.RS485) {
			mSlBusRs485Dir_Out();
		}
		if(sLL_UART_SlaveBus.LL.DisRxWhileTxOperate) {
			mUart2Rx_Dis();
		}
		mUart2IntUdrEmp_Enab();
	}
}

// interruption
ISR(TIMER1_COMPA_vect) 
- for RX timeout, can be not used, but needs to be edited impacted code
{
	sLL_UART_MasterBus.LL.RX.E = true;
	sLL_UART_MasterBus.LL.RX.E_Nr = UART_E_RX_TIMEOUT;
	mTimer1Stop();
}

ISR(USART0_RX_vect)
{
	uiTmpInterrupt = UDR0;
	if (!sLL_UART_MasterBus.LL.RX.E && !sLL_UART_MasterBus.LL.RX.FrameReceived) {
		switch (uiTmpInterrupt) {
			case UART_FRAME_START_MARK:
			if (!sLL_UART_MasterBus.LL.RX.FrameReceiving) {
				sLL_UART_MasterBus.LL.RX.FrameReceiving = true;
				sLL_UART_MasterBus.LL.RX.Index = 0;
				sLL_UART_MasterBus.LL.RX.Buff[sLL_UART_MasterBus.LL.RX.Index++] = uiTmpInterrupt;
				mTimer1Clear();
				mTimer1Run_Clk_64();
			}
			else {
				sLL_UART_MasterBus.LL.RX.E = true;
				sLL_UART_MasterBus.LL.RX.E_Nr = UART_E_RX_START_MARK;
				mTimer1Stop();
			}
			break;
			case UART_FRAME_STOP_MARK:
			if (sLL_UART_MasterBus.LL.RX.FrameReceiving) {
				sLL_UART_MasterBus.LL.RX.Buff[sLL_UART_MasterBus.LL.RX.Index++] = uiTmpInterrupt;
				sLL_UART_MasterBus.LL.RX.FrameReceived = true;
				sLL_UART_MasterBus.LL.RX.FrameReceiving = false;
			}
			else {
				sLL_UART_MasterBus.LL.RX.E = true;
				sLL_UART_MasterBus.LL.RX.E_Nr = UART_E_RX_STOP_MARK;
			}
			mTimer1Stop();
			break;
			default:
			if (sLL_UART_MasterBus.LL.RX.FrameReceiving) {
				sLL_UART_MasterBus.LL.RX.Buff[sLL_UART_MasterBus.LL.RX.Index++] = uiTmpInterrupt;
				mTimer1Clear();
			}
			else {
				sLL_UART_MasterBus.LL.RX.E = true;
				sLL_UART_MasterBus.LL.RX.E_Nr = UART_E_RX_UNEXP_DATA;
				mTimer1Stop();
			}
		}
		if (sLL_UART_MasterBus.LL.RX.Index > UART_FRAME_LEN_MAX) {
			sLL_UART_MasterBus.LL.RX.E = true;
			sLL_UART_MasterBus.LL.RX.E_Nr = UART_E_RX_HIG_FRM_LEN;
			mTimer1Stop();
		}
	}
	else {
		sLL_UART_MasterBus.LL.RX.MissedRxWhileException++;
	}
}

ISR(USART0_TX_vect)
{
	mUart0IntTx_Dis();
	if(sLL_UART_MasterBus.LL.RS485) {
		mMaBusRs485Dir_In();
	}
	if(sLL_UART_MasterBus.LL.DisTxWhileIdle) {
		mUart0Tx_Dis();
	}
	if(sLL_UART_MasterBus.LL.DisRxWhileTxOperate) {
		mUart0Rx_Enab();
	}
	sLL_UART_MasterBus.LL.TX.FrameTransmitted = true;
	sLL_UART_MasterBus.LL.TX.Index = 0;
	sLL_UART_MasterBus.LL.TX.FrameTransmitting = false;
}

ISR(USART0_UDRE_vect)
{
	uiTmpInterrupt = sLL_UART_MasterBus.LL.TX.Buff[sLL_UART_MasterBus.LL.TX.Index++];
	UDR0 = uiTmpInterrupt;
	sLL_UART_MasterBus.LL.TX.FrameTransmitting = true;
	if (uiTmpInterrupt == UART_FRAME_STOP_MARK) {
		mUart0IntUdrEmp_Dis();
		mUart0TxFlag_Clr();
		mUart0IntTx_Enab();
	}
}
*/