#ifndef __SPI_TO_DUAL_USARTS_BRIDGE_H_
#define __SPI_TO_DUAL_USARTS_BRIDGE_H_

#include "fsl_common.h"

/************************register count***********************/
//General register count
#define GEN_REG_COUNT           16
//Special register and Enhanced register count
#define SPEC_EN_REG_COUNT       8     
/************************register count***********************/

/************************Fifo max deepth**************************/
#define FIFO_MAX_LEN            64
/************************Fifo max deepth**************************/

//SPI to dual USARTs bridge register address type
typedef enum reg_addr
{
/************************general register address********************************************/
	THR_RHR_ADDR                  = 0x00,
	IER_ADDR                      = 0x01,
	FCR_IIR_ADDR                  = 0x02,
	LCR_ADDR                      = 0x03,
	MCR_ADDR                      = 0x04,
	LSR_ADDR                      = 0x05,
	TCR_MSR_ADDR                  = 0x06,
	TLR_SPR_ADDR                  = 0x07,
	TXLVL_ADDR                    = 0x08,
	RXLVL_ADDR                    = 0x09,
	IODir_ADDR                    = 0x0A,
	IOState_ADDR                  = 0x0B,
	IOIntEna_ADDR                 = 0x0C,
	reserved_ADDR                 = 0x0D,
	IOControl_ADDR                = 0x0E,
	EFCR_ADDR                     = 0x0F,
/************************general register address********************************************/

/************************special register and enhanced register address**********************/
	DLL_ADDR                      = 0x00,
	DLH_ADDR                      = 0x01,
	EFR_ADDR                      = 0x02,
	XON1_ADDR                     = 0x04,
	XON2_ADDR                     = 0x05,
	XOFF1_ADDR                    = 0x06,
	XOFF2_ADDR                    = 0x07,
/************************special register and enhanced register address**********************/
}Reg_Addr_Type;

//SPI to dual USARTs bridge register set type
typedef enum reg_set
{
	GEN_REG_SET = 0,//general register set type
	SPEC_EN_REG_SET = 1//special register and enhanced register set type
}Reg_Set_Type;

/*
 * In SC16IS752/SC16IS762, there are three register types:
 * 1. read-only register-> register can only be read, can not be written, such as LSR, MSR, TXLVL, RXLVL, IOState
 * 2. read-write split register-> read mode and write mode correspond to different register entities,such as RHR/THR, IIR/FCR
 * 3. read-write identical register->read mode and write mode correspond to same register entity
*/
//SPI to dual USARTs bridge register type
typedef struct reg_type
{
	uint8_t  r_reg_val;//buffer for read-only register or read-write split register in read mode
	uint8_t  w_reg_val;//buffer for read-write split register in write mode
	uint8_t  rw_reg_val;//buffer for read-write identical register
}Reg_Type;

//register information
typedef struct reg_info
{
	Reg_Set_Type reg_set_type;//SPI to dual USARTs bridge register set type
	uint32_t     reg_addr;//register address
}Reg_Update_Info_Type;

/*!
 * brief  initalize bridge register
 * param  void
 * return void
 */
extern void initalizeBridgeRegister(void);
	
/*!
 * brief  update data transmission parameter
 * param  void
 * return void
 */
extern void updateDataTransferParameter(void);

/*
 * According to SC16IS752/SC16IS762 datasheet, SPI transmission format is as following:
 * discription      direction bit    register address  usart channel  unknown    data byte  data byte  data byte ......
 *     bit               7           6   5   4   3       2      1       0          7 - 0      7 - 0      7 - 0   ......
 *                      R/~W         A3  A2  A1  A0      CH1   CH0    don't care   D7 - D0    D7 - D0    D7 - D0 ......
 * Frame Header includes R/~W + A3A2A1A0 + CH1CH0 + don't care bit
 * Frame Data includes data bytes following Frame Header
*/
//data frame header for SPI to dual USARTs bridge
typedef struct data_frame_header
{
	bool    isSPIHostToUSART;//data transmission direction 
	uint8_t regAddr;//bridge register address
  uint8_t USART_channel;//USART channel number
}Bridge_Data_Frame_Header;

/*
 * According to SC16IS752/SC16IS762 datasheet, SPI transmission format is as following:
 * discription      direction bit    register address  usart channel  unknown    data byte  data byte  data byte ......
 *     bit               7           6   5   4   3       2      1       0          7 - 0      7 - 0      7 - 0   ......
 *                      R/~W         A3  A2  A1  A0      CH1   CH0    don't care   D7 - D0    D7 - D0    D7 - D0 ......
 * Frame Header includes R/~W + A3A2A1A0 + CH1CH0 + don't care bit
 * Frame Data includes data bytes following Frame Header
*/
//data frame phase for SPI to dual USARTs bridge
typedef enum data_frame_phase
{
	Frame_Header = 0,
	Frame_Data = 1
}Bridge_Data_Frame_Phase;

/*!
 * brief set SPI_2USARTs_bridge register
 * param Reg_Set_Type reg_set->register set:General register set or Special register and Enhanced register set
 * param uint8_t reg_addr->register address
 * param uint8_t reg_value->setting value for register
 * return void
 */
extern void setBridgeReg(Reg_Set_Type reg_set, uint8_t reg_addr, uint8_t reg_value);

/*!
 * brief get SPI_2USARTs_bridge register
 * param Reg_Set_Type reg_set->register set:General register set or Special register and Enhanced register set
 * param uint8_t reg_addr->register address
 * return uint8_t->register value
 */
extern uint8_t getBridgeReg(Reg_Set_Type reg_set, uint8_t reg_addr);

/*!
 * brief generate an IRQ signal to SPI host
 * param void
 * return void
 */
extern void emitIRQToSPIHost(void);

/*!
 * brief set transfer timeout flag
 * param void
 * return void
 */
extern void setTransferTimeOutFlag(void);

/*!
 * brief process time out
 * param void
 * return void
 */
extern void processTimeOut(void);

/*!
 * brief preprocess data from SPI host
 * param uint8_t sourceData->data received from SPI host
 * return void
 */
extern void preprocessDataFromSPIHost(uint8_t sourceData);

/*!
 * brief save data received from USART peripheral to rx fifo in bridge
 * param uint8_t sourceData->data received from USART peripheral
 * return void
 */
extern void saveUSARTDataToRxFifo(uint8_t sourceData);

/*!
 * brief process data from SPI host
 * param void
 * return void
 */
extern void processDataFromSPIHost(void);

/*!
 * brief send data from USART peripheral to SPI host
 * param void
 * return void
 */
extern void sendDataFromUSARTToSPIHost(void);

#endif
