//#############################################################################################################################################################################################################
#ifndef _IDIBUS_SERIAL_H_
#define _IDIBUS_SERIAL_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "IdiBusSystem.h"
#include "IdiBusSerialDefs.h"
#include "IdiBusInterruptsList.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
enum IDIBUS_SERIAL_USARTN_NUMBER {
	IDIBUS_SERIAL_USART0,
	IDIBUS_SERIAL_USART1,
	IDIBUS_SERIAL_USART2,
	IDIBUS_SERIAL_USART3
	};
enum IDIBUS_SERIAL_TIMER_NUMBER {
	IDIBUS_TIMER_1 = 1,
	IDIBUS_TIMER_3 = 3,
	IDIBUS_TIMER_4,
	IDIBUS_TIMER_5
	};
enum IDIBUS_SERIAL_USARTN_CONFIG {
	IDIBUS_SERIAL_8N1,
	IDIBUS_SERIAL_8N2,
	IDIBUS_SERIAL_8E1,
	IDIBUS_SERIAL_8E2,
	IDIBUS_SERIAL_8O1,
	IDIBUS_SERIAL_8O2
	};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct {
	enum IDIBUS_SERIAL_USARTN_NUMBER   USART_NUMBER;
	enum IDIBUS_SERIAL_TIMER_NUMBER    TIMER_NUMBER;
	enum IDIBUS_SERIAL_USARTN_CONFIG   CONFIG;
	uint8_t							   RS485_DIR_PIN;
	uint8_t							   BAUDRATE_DIPSW_S0_PIN;
	uint8_t							   BAUDRATE_DIPSW_S1_PIN;
	uint8_t							   BAUDRATE_DIPSW_S2_PIN;
	} IDIBUS_SERIAL_INIT_TYPEDEF;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct {
	enum IDIBUS_SERIAL_USARTN_NUMBER   USART_NUMBER;
	enum IDIBUS_SERIAL_TIMER_NUMBER    TIMER_NUMBER;
	enum IDIBUS_SERIAL_USARTN_CONFIG   CONFIG;
	IDIBUS_SERIAL_GPIO_INIT			   RS485_DIR_GPIO;
	struct {
		IDIBUS_SERIAL_GPIO_INIT		   S0;
		IDIBUS_SERIAL_GPIO_INIT		   S1;
		IDIBUS_SERIAL_GPIO_INIT		   S2;
		}							   BAUDRATE_DIPSW;
	} IDIBUS_SERIAL_ALTERNATIVE_INIT_TYPEDEF;	
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusSerial : public IdiBusCallbackInterface {
	
	public :
		IdiBusSerial(void);
		
		uint8_t								Init(IDIBUS_SERIAL_INIT_TYPEDEF *InitT);
		uint8_t								Init(IDIBUS_SERIAL_ALTERNATIVE_INIT_TYPEDEF *InitT);
		void								SetBaudrate(enum IDIBUS_SERIAL_BAUDRATE Baudrate);
		void								UpdateBaudrateFromDipSwitch(void);
		
		void								Start (void);				// Hold Line
		void								Stop (void);				// TX/RX disable, Release Line
		
		uint8_t								SendRequestAsync(uint8_t *_TxBuf_, uint16_t _TxBufLength_);
		uint8_t								SendRequestSync (uint8_t *_TxBuf_, uint16_t _TxBufLength_);

		uint8_t								WriteSync (uint8_t *_TxBuf_, uint16_t _TxBufLength_);
		uint8_t								WriteAsync(uint8_t *_TxBuf_, uint16_t _TxBufLength_);
		
		uint8_t								IsTransferComplete(void);
		uint16_t							GetRxBufCounter(void);
		IDIBUS_SERIAL_ERROR_STATUS_TYPE		GetErrorStatus(void);
		uint32_t							GetBaudrate(void);
		
	private :
		IDIBUS_SERIAL_USART_HW_TYPE			USARTN;
		IDIBUS_SERIAL_USARTN_16BIT_TIMER	TIMN;
		
		IDIBUS_SERIAL_GPIO					RS485_DIR_GPIO;
		IDIBUS_SERIAL_BAUDRATE_DIPSW_TYPE	BAUDRATE_DIPSW;
		uint32_t							BAUDRATE;
		
		uint8_t								TxBuf[IDIBUS_SERIAL_TX_BUF_SIZE];
		uint16_t							TxBufLength;
		uint16_t							TxBufCounter;
		
		uint8_t								RxBuf[IDIBUS_SERIAL_RX_BUF_SIZE];
		uint16_t							RxBufCounter;
		IDIBUS_SERIAL_ERROR_STATUS_TYPE		ERROR_STATUS;

		uint16_t							TimerInterFrameCompValue;
		uint16_t                            TimerTimeoutCompValue;
		uint16_t							TimerTimeoutOverflow;
		
		enum IDIBUS_SERIAL_REQUEST_TYPE		RequestType;
		volatile uint8_t					TransferComplete;
		uint16_t						    InitProtectionVar;
		uint8_t  						    InitState;
		
		// Interrupt Vectors Pointers
		virtual void USART_RxInterruptFunc(void)   override;
		virtual void USART_TxInterruptFunc(void)   override;
		virtual void TIM_COMPA_InterruptFunc(void) override;
		virtual void TIM_COMPB_InterruptFunc(void) override;
		
		// Routine
		uint8_t BaseInit(enum IDIBUS_SERIAL_USARTN_NUMBER USART_NUM, enum IDIBUS_SERIAL_TIMER_NUMBER TIMER_NUM, enum IDIBUS_SERIAL_USARTN_CONFIG CONF);
		uint8_t GetGpioParams(IDIBUS_SERIAL_GPIO_INIT *InitSTR, IDIBUS_SERIAL_GPIO *gpio);
		uint8_t GetGpioParamsArduino(uint8_t PinNum, IDIBUS_SERIAL_GPIO *gpio);
		void    SetBaudrateLL(uint32_t Baudrate);
	
	protected :
		uint8_t *getTxBufPointer (void);
		uint8_t *getRxBufPointer (void);
		uint8_t  SendRequestAsync(uint16_t DataLength);
		uint8_t  SendRequestSync(uint16_t DataLength);
		uint8_t  WriteAsync(uint16_t DataLength);
		uint8_t  WriteSync(uint16_t DataLength);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //_IDIBUS_SERIAL_H_
//#############################################################################################################################################################################################################
