/*********************************************************************
 *                  Flowcode CAL UART File
 *
 * File: PIC_CAL_UART.c
 *
 * (c) 2011 Matrix Multimedia Ltd.
 * http://www.matrixmultimedia.com
 *
 * Software License Agreement
 *
 * The software supplied herewith by Matrix Multimedia Ltd (the
 * “Company”) for its Flowcode graphical programming language is
 * intended and supplied to you, the Company’s customer, for use
 * solely and exclusively on the Company's products. The software
 * is owned by the Company, and is protected under applicable
 * copyright laws. All rights are reserved. Any use in violation
 * of the foregoing restrictions may subject the user to criminal
 * sanctions under applicable laws, as well as to civil liability
 * for the breach of the terms and conditions of this licence.
 *
 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 * Changelog:
 *
 *  date  | by | description
 * -------+----+-----------------------------------------------------
 * 010911 | BR | Created
 * 020911 | BR | Updated variables with typedef alternatives
 * 011211 | BR | Converted to new dynamic defines mechanism
 * 160112 | BR | Fixed issues with rx return type and low bauds on fast devices
 * 020212 | ST | Added <MX_UART_2_PIE4> routing to account for differences in 16F and 18F devices with 2 UARTs
 * 270212 | BR | Fixed a bug in the receive functionality
 * 280212 | BR | Sorted out auto echo functionality
 * 160412 | BR | Addition of HW change baud function
 * 100912 | BR | Minor bug fix for UART 2 where pir3 was referenced instead of definition
 * 240413 | LM | Fixed typo re PORT_1 -> PORT_X for Software UART
 * 030713 | LM | Standard API calls
 * 220713 | LM | Remappable registers to lower case (for @ defs)
 * 300914 | BR | Tried to make the baud calculation a bit more reliable for higher speed bauds at odd crystal frequencies
 * 161014 | LM | Register redefinitions (for PIC18F24K50)
 * 120815 | LM | Changed MX_UART_2_PIE4 switch re 16F1946 compile error
 * 250815 | LM | SPBRG defined as SPBRGL (16F1508 issue)
 
 */


#if (!defined(BAUDCON) && defined(BAUDCON1))
	#define baudcon baudcon1
#endif
#if (!defined(RCSTA) && defined(RCSTA1))
	#define rcsta rcsta1
#endif
#if (!defined(SPBRG) && defined(SPBRG1))
	#define spbrg spbrg1
#endif
#if (!defined(SPBRG) && defined(SPBRGL))
	#define spbrg spbrgl
#endif
#if (!defined(SPBRGH) && defined(SPBRGH1))
	#define spbrgh spbrgh1
#endif
#if (!defined(TXREG) && defined(TXREG1))
	#define txreg txreg1
#endif
#if (!defined(RCREG) && defined(RCREG1))
	#define rcreg rcreg1
#endif
#if (!defined(TXSTA) && defined(TXSTA1))
	#define txsta txsta1
#endif

#ifndef MX_UART_SW_DEFS
	#define MX_UART_SW_DEFS

	#ifdef _BOOSTC
		#define INST_COUNT	45	//65 for lower speeds or 40 for higher speeds.
	#endif
	#ifdef HI_TECH_C
		#define INST_COUNT	315
	#endif

	//Work out number of nops for software baud rate
	#define MX_INSTRUCTION_SPEED 	(MX_CLK_SPEED / 4)
	#define MX_OVERHEAD				(MX_INSTRUCTION_SPEED / INST_COUNT)
	#define SW_OFFSET				(1000000 / MX_OVERHEAD)

#endif

 #if defined(MX_UART_CHANNEL_1) && (MX_UART_NUM==1)
	#if (MX_UART_CHANNEL_1 == 0)

		#define MX_SOFT_BAUD_1 (1000000 / MX_UART_BAUD_1) - SW_OFFSET

		#if (MX_SOFT_BAUD_1 < 1)
			#error "Software UART Baud Rate Not Available At This Clock Speed"
		#endif

	#else
		#define MX_SOFT_BAUD_1	1
		#define MX_HARD_BAUD_1	(((MX_CLK_SPEED / MX_UART_BAUD_1) - 8) / 16)		//Was - 16 but had issues with rounding down
		#define MX_HARD_SLOW_1	0

		#if (MX_HARD_BAUD_1 > 255)
			#undef MX_HARD_BAUD_1
			#undef MX_HARD_SLOW_1
			#define MX_HARD_BAUD_1	(((MX_CLK_SPEED / MX_UART_BAUD_1) - 8)	/ 64)		//Was - 16 but had issues with rounding down
			#define MX_HARD_SLOW_1	1

			#if (MX_HARD_BAUD_1 > 255)
				#warning "The baud rate you have entered cannot be reached (too slow for crystal speed)"
			#endif

		#endif

	#endif
 #endif
 #if defined(MX_UART_CHANNEL_2) && (MX_UART_NUM==2)
	#if (MX_UART_CHANNEL_2 == 0)

		#define MX_SOFT_BAUD_2 (1000000 / MX_UART_BAUD_2) - SW_OFFSET

		#if (MX_SOFT_BAUD_2 < 1)
			#error "Software UART Baud Rate Not Available At This Clock Speed"
		#endif

	#else
		#define MX_SOFT_BAUD_2	1
		#define MX_HARD_BAUD_2	(((MX_CLK_SPEED / MX_UART_BAUD_2) - 8) / 16)		//Was - 16 but had issues with rounding down
		#define MX_HARD_SLOW_2	0

		#if (MX_HARD_BAUD_2 > 255)
			#undef MX_HARD_BAUD_2
			#undef MX_HARD_SLOW_2
			#define MX_HARD_BAUD_2	(((MX_CLK_SPEED / MX_UART_BAUD_2) - 8)	/ 64)		//Was - 16 but had issues with rounding down
			#define MX_HARD_SLOW_2	1

			#if (MX_HARD_BAUD_2 > 255)
				#warning "The baud rate you have entered cannot be reached (too slow for crystal speed)"
			#endif
		#endif
 	#endif
 #endif
 #if defined(MX_UART_CHANNEL_3) && (MX_UART_NUM==3)
	#if (MX_UART_CHANNEL_3 == 0)

		#define MX_SOFT_BAUD_3 (1000000 / MX_UART_BAUD_3) - SW_OFFSET

		#if (MX_SOFT_BAUD_3 < 1)
			#error "Software UART Baud Rate Not Available At This Clock Speed"
		#endif

	#else
		#define MX_SOFT_BAUD_3	1
		#define MX_HARD_BAUD_3	(((MX_CLK_SPEED / MX_UART_BAUD_3) - 8) / 16)		//Was - 16 but had issues with rounding down
		#define MX_HARD_SLOW_3	0

		#if (MX_HARD_BAUD_3 > 255)
			#undef MX_HARD_BAUD_3
			#undef MX_HARD_SLOW_3
			#define MX_HARD_BAUD_3	(((MX_CLK_SPEED / MX_UART_BAUD_3) - 8)	/ 64)		//Was - 16 but had issues with rounding down
			#define MX_HARD_SLOW_3	1

			#if (MX_HARD_BAUD_3 > 255)
				#warning "The baud rate you have entered cannot be reached (too slow for crystal speed)"
			#endif

		#endif
	#endif
 #endif
 #if defined(MX_UART_CHANNEL_4) && (MX_UART_NUM==4)
	#if (MX_UART_CHANNEL_4 == 0)

		#define MX_SOFT_BAUD_4 (1000000 / MX_UART_BAUD_4) - SW_OFFSET

		#if (MX_SOFT_BAUD_4 < 1)
			#error "Software UART Baud Rate Not Available At This Clock Speed"
		#endif

	#else
		#define MX_SOFT_BAUD_4	1
		#define MX_HARD_BAUD_4	(((MX_CLK_SPEED / MX_UART_BAUD_4) - 8) / 16)		//Was - 16 but had issues with rounding down
		#define MX_HARD_SLOW_4	0

		#if (MX_HARD_BAUD_4 > 255)
			#undef MX_HARD_BAUD_4
			#undef MX_HARD_SLOW_4
			#define MX_HARD_BAUD_4	(((MX_CLK_SPEED / MX_UART_BAUD_4) - 8)	/ 64)		//Was - 16 but had issues with rounding down
			#define MX_HARD_SLOW_4	1

			#if (MX_HARD_BAUD_4 > 255)
				#warning "The baud rate you have entered cannot be reached (too slow for crystal speed)"
			#endif

		#endif
	#endif
 #endif


//Hardware Baud update definitions
#ifndef MX_HARD_BAUD_CHANGE_DEFS
	#define MX_HARD_BAUD_CHANGE_DEFS

	#define MX_HARD_BAUD_1200	(((MX_CLK_SPEED / 1200) - 8) / 16)		//Was - 16 but had issues with rounding down
	#if (MX_HARD_BAUD_1200 > 255)
		#undef MX_HARD_BAUD_1200
		#define MX_HARD_BAUD_1200	(((MX_CLK_SPEED / 1200) - 8) / 64)		//Was - 16 but had issues with rounding down
		#define MX_HARD_SLOW_1200	1
	#else
		#define MX_HARD_SLOW_1200	0
	#endif

	#define MX_HARD_BAUD_2400	(((MX_CLK_SPEED / 2400) - 8) / 16)		//Was - 16 but had issues with rounding down
	#if (MX_HARD_BAUD_2400 > 255)
		#undef MX_HARD_BAUD_2400
		#define MX_HARD_BAUD_2400	(((MX_CLK_SPEED / 2400) - 8) / 64)		//Was - 16 but had issues with rounding down
		#define MX_HARD_SLOW_2400	1
	#else
		#define MX_HARD_SLOW_2400	0
	#endif

	#define MX_HARD_BAUD_4800	(((MX_CLK_SPEED / 4800) - 8) / 16)		//Was - 16 but had issues with rounding down
	#if (MX_HARD_BAUD_4800 > 255)
		#undef MX_HARD_BAUD_4800
		#define MX_HARD_BAUD_4800	(((MX_CLK_SPEED / 4800) - 8) / 64)		//Was - 16 but had issues with rounding down
		#define MX_HARD_SLOW_4800	1
	#else
		#define MX_HARD_SLOW_4800	0
	#endif

	#define MX_HARD_BAUD_9600	(((MX_CLK_SPEED / 9600) - 8) / 16)		//Was - 16 but had issues with rounding down
	#if (MX_HARD_BAUD_9600 > 255)
		#undef MX_HARD_BAUD_9600
		#define MX_HARD_BAUD_9600	(((MX_CLK_SPEED / 9600) - 8) / 64)		//Was - 16 but had issues with rounding down
		#define MX_HARD_SLOW_9600	1
	#else
		#define MX_HARD_SLOW_9600	0
	#endif

	#define MX_HARD_BAUD_19200	(((MX_CLK_SPEED / 19200) - 8) / 16)		//Was - 16 but had issues with rounding down
	#if (MX_HARD_BAUD_19200 > 255)
		#undef MX_HARD_BAUD_19200
		#define MX_HARD_BAUD_19200	(((MX_CLK_SPEED / 19200) - 8) / 64)		//Was - 16 but had issues with rounding down
		#define MX_HARD_SLOW_19200	1
	#else
		#define MX_HARD_SLOW_19200	0
	#endif

	#define MX_HARD_BAUD_38400	(((MX_CLK_SPEED / 38400) - 8) / 16)		//Was - 16 but had issues with rounding down
	#if (MX_HARD_BAUD_38400 > 255)
		#undef MX_HARD_BAUD_38400
		#define MX_HARD_BAUD_38400	(((MX_CLK_SPEED / 38400) - 8) / 64)		//Was - 16 but had issues with rounding down
		#define MX_HARD_SLOW_38400	1
	#else
		#define MX_HARD_SLOW_38400	0
	#endif

	#define MX_HARD_BAUD_57600	(((MX_CLK_SPEED / 57600) - 8) / 16)		//Was - 16 but had issues with rounding down
	#if (MX_HARD_BAUD_57600 > 255)
		#undef MX_HARD_BAUD_57600
		#define MX_HARD_BAUD_57600	(((MX_CLK_SPEED / 57600) - 8) / 64)		//Was - 16 but had issues with rounding down
		#define MX_HARD_SLOW_57600	1
	#else
		#define MX_HARD_SLOW_57600	0
	#endif

	#define MX_HARD_BAUD_115200	(((MX_CLK_SPEED / 115200) - 8) / 16)		//Was - 16 but had issues with rounding down
	#if (MX_HARD_BAUD_115200 > 255)
		#undef MX_HARD_BAUD_115200
		#define MX_HARD_BAUD_115200	(((MX_CLK_SPEED / 115200) - 8) / 64)		//Was - 16 but had issues with rounding down
		#define MX_HARD_SLOW_115200	1
	#else
		#define MX_HARD_SLOW_115200	0
	#endif
#endif

#define MX_RECEIVE_DELAY 	(MX_CLK_SPEED / 400000)


//Dynamic function naming based on defines and index number
#define MX_UART_CHANNEL_X	CAL_APPEND(MX_UART_CHANNEL_, MX_UART_NUM)
#define MX_UART_TX_PIN_X	CAL_APPEND(MX_UART_TX_PIN_, MX_UART_NUM)
#define MX_UART_TX_PORT_X	CAL_APPEND(MX_UART_TX_PORT_, MX_UART_NUM)
#define MX_UART_TX_TRIS_X	CAL_APPEND(MX_UART_TX_TRIS_, MX_UART_NUM)
#define MX_UART_RX_PIN_X	CAL_APPEND(MX_UART_RX_PIN_, MX_UART_NUM)
#define MX_UART_RX_PORT_X	CAL_APPEND(MX_UART_RX_PORT_, MX_UART_NUM)
#define MX_UART_RX_TRIS_X	CAL_APPEND(MX_UART_RX_TRIS_, MX_UART_NUM)
#define MX_UART_FLOWEN_X	CAL_APPEND(MX_UART_FLOWEN_, MX_UART_NUM)
#define MX_UART_CTS_PIN_X	CAL_APPEND(MX_UART_CTS_PIN_, MX_UART_NUM)
#define MX_UART_CTS_PORT_X	CAL_APPEND(MX_UART_CTS_PORT_, MX_UART_NUM)
#define MX_UART_CTS_TRIS_X	CAL_APPEND(MX_UART_CTS_TRIS_, MX_UART_NUM)
#define MX_UART_RTS_PIN_X	CAL_APPEND(MX_UART_RTS_PIN_, MX_UART_NUM)
#define MX_UART_RTS_PORT_X	CAL_APPEND(MX_UART_RTS_PORT_, MX_UART_NUM)
#define MX_UART_RTS_TRIS_X	CAL_APPEND(MX_UART_RTS_TRIS_, MX_UART_NUM)
#define MX_UART_DBITS_X		CAL_APPEND(MX_UART_DBITS_, MX_UART_NUM)
#define MX_UART_RETURN_X	CAL_APPEND(MX_UART_RETURN_, MX_UART_NUM)
#define MX_UART_ECHO_X		CAL_APPEND(MX_UART_ECHO_, MX_UART_NUM)
#define MX_UART_INT_X		CAL_APPEND(MX_UART_INT_, MX_UART_NUM)
#define MX_UART_BAUD_X		CAL_APPEND(MX_HARD_BAUD_, MX_UART_NUM)
#define MX_SOFT_BAUD_X		CAL_APPEND(MX_SOFT_BAUD_, MX_UART_NUM)
#define MX_HARD_SLOW_X		CAL_APPEND(MX_HARD_SLOW_, MX_UART_NUM)

#define UART_Delay_CAL		CAL_APPEND(FC_CAL_UART_Delay_, MX_UART_NUM)
#define UART_Send			CAL_APPEND(FC_CAL_UART_Send_, MX_UART_NUM)
#define UART_Uninit			CAL_APPEND(FC_CAL_UART_Uninit_, MX_UART_NUM)


//Component Definitions
#define UART_STATUS_LOOP	0
#define UART_STATUS_TIMEOUT	1
#define UART_STATUS_RXBYTE	2


//Interrupt Definitions
#ifdef TX2STA
  #define MX_UART2_PIE pie4
  #define MX_UART2_PIR pir4
  #define MX_UART2_TXSTA tx2sta
  #define MX_UART2_RCSTA rc2sta
  #define MX_UART2_TXREG tx2reg
  #define MX_UART2_RCREG rc2reg
#else
  #define MX_UART2_PIE pie3
  #define MX_UART2_PIR pir3
  #define MX_UART2_TXSTA txsta2
  #define MX_UART2_RCSTA rcsta2
  #define MX_UART2_TXREG txreg2
  #define MX_UART2_RCREG rcreg2
#endif

#if (MX_UART_INT_X == 1)

	#ifndef MX_UART_INT_DEFS
	#define MX_UART_INT_DEFS

		#define MX_UART_INT_CH1_FUNC
		#define MX_UART_INT_CH2_FUNC
		#define MX_UART_INT_FUNC_END

		#define MX_UART_INT_CH1_DET		ts_bit(pir1, RCIF) && ts_bit(pie1, RCIE)
		#define MX_UART_INT_CH2_DET		ts_bit(MX_UART2_PIR, RC2IF) && ts_bit(MX_UART2_PIE, RC2IE)

		#define MX_UART_INT_CH1_EN		st_bit (pie1, RCIE)
		#define MX_UART_INT_CH2_EN		st_bit (MX_UART2_PIE, RC2IE)

		#define MX_UART_INT_CH1_DIS		cr_bit (pie1, RCIE)
		#define MX_UART_INT_CH2_DIS		cr_bit (MX_UART2_PIE, RC2IE)

		#define MX_UART_INT_CH1_CLR		cr_bit (pir1, RCIF)
		#define MX_UART_INT_CH2_CLR		cr_bit (MX_UART2_PIR, RC2IF)

	#endif
#endif


//Function Prototypes
CALFUNCTION(void, FC_CAL_UART_Init_, (void));
CALFUNCTION(void, FC_CAL_UART_Uninit_, (void));
CALFUNCTION(void, FC_CAL_UART_Send_, (MX_UINT16 nChar));
CALFUNCTION(MX_SINT16, FC_CAL_UART_Receive_, (MX_UINT8 nTimeout));
CALFUNCTION(void, FC_CAL_UART_Delay_, (void));
CALFUNCTION(void, FC_CAL_UART_UpdateBaud_, (MX_UINT8 new_baud));


//Peripheral Functions
CALFUNCTION(void, FC_CAL_UART_Init_, (void))
{

	#if (MX_UART_CHANNEL_X == 0)
		FC_CAL_Bit_In_DDR 	(MX_UART_RX_PORT_X, MX_UART_RX_TRIS_X, MX_UART_RX_PIN_X);		// Receive pin is a input
		FC_CAL_Bit_High_DDR (MX_UART_TX_PORT_X, MX_UART_TX_TRIS_X, MX_UART_TX_PIN_X);		// Transmit pin is default high
	#endif

	#if (MX_UART_CHANNEL_X == 1)

		  #ifdef MX_UART_1_REMAPPABLE
			MX_UART_1_TX_RPOR = MX_UART_1_TX_UTX;
			MX_UART_1_RX_RPINR = MX_UART_1_RX_RP;
		  #endif

		  #if (MX_HARD_SLOW_X == 1)
			cr_bit(txsta, BRGH);						//Low Speed
		  #else
			st_bit(txsta, BRGH);						//High Speed
		  #endif
			spbrg = MX_UART_BAUD_X;   					// set the baud rate
			rcsta = 0;                    				// 8-bit, disabled

			#if(MX_UART_DBITS_X == 9)
				st_bit(txsta, TX9);   					// 9-bit TX
				st_bit(rcsta, RX9);                    	// 9-bit RX
			#endif

			st_bit(rcsta, SPEN);         				// turn on serial interface
			st_bit(txsta, TXEN);
			st_bit(rcsta, CREN);

			#if (MX_UART_INT_X == 1)
				MX_UART_INT_CH1_EN;
				st_bit(intcon, PEIE);
				st_bit(intcon, GIE);
			#else
				cr_bit (pie1, RCIE);
			#endif

	#endif


	#if (MX_UART_CHANNEL_X == 2)

		  #ifdef MX_UART_2_REMAPPABLE
			MX_UART_2_TX_RPOR = MX_UART_2_TX_UTX;
			MX_UART_2_RX_RPINR = MX_UART_2_RX_RP;
		  #endif

		  #if (MX_HARD_SLOW_X == 1)
			cr_bit(MX_UART2_TXSTA, BRGH);				//Low Speed
		  #else
			st_bit(MX_UART2_TXSTA, BRGH);				//High Speed
		  #endif

			spbrg2 = MX_UART_BAUD_X;   					// set the baud rate
			MX_UART2_RCSTA = 0;                    		// 8-bit, disabled

			#if(MX_UART_DBITS_X == 9)
				st_bit(MX_UART2_TXSTA, TX9);   			// 9-bit TX
				st_bit(MX_UART2_RCSTA, RX9);            // 9-bit RX
			#endif

			st_bit(MX_UART2_RCSTA, SPEN);         		// turn on serial interface
			st_bit(MX_UART2_TXSTA, TXEN);
			st_bit(MX_UART2_RCSTA, CREN);

			#if (MX_UART_INT_X == 1)
				MX_UART_INT_CH2_EN;
				st_bit(intcon, PEIE);
				st_bit(intcon, GIE);
			#else
				cr_bit (MX_UART2_PIE, RC2IE);
			#endif

	#endif

	#if (MX_UART_FLOWEN_X == 1)						//Flowcontrol enabled?
		FC_CAL_Bit_In_DDR (MX_UART_CTS_PORT_X, MX_UART_CTS_TRIS_X, MX_UART_CTS_PIN_X);	// CTS pin is a input
		FC_CAL_Bit_High_DDR (MX_UART_RTS_PORT_X, MX_UART_RTS_TRIS_X, MX_UART_RTS_PIN_X);	// RTS not ready to accept data
	#endif

}



CALFUNCTION(void, FC_CAL_UART_Uninit_, (void))
{

	#if (MX_UART_CHANNEL_X == 0)
		FC_CAL_Bit_In_DDR (MX_UART_RX_PORT_X, MX_UART_RX_TRIS_X, MX_UART_RX_PIN_X);		// Receive pin is a input
		FC_CAL_Bit_In_DDR (MX_UART_TX_PORT_X, MX_UART_TX_TRIS_X, MX_UART_TX_PIN_X);		// Transmit pin is default high
	#endif

	#if (MX_UART_CHANNEL_X == 1)
			rcsta = 0;                    								// 8-bit, disabled
			txsta = 0;
		  #ifdef MX_UART_RXINT
			MX_UART_INT_CH1_DIS;
		  #endif
	#endif

	#if (MX_UART_CHANNEL_X == 2)
			MX_UART2_RCSTA = 0;                    								// 8-bit, disabled
			MX_UART2_TXSTA = 0;
		  #ifdef MX_UART_RXINT
			MX_UART_INT_CH2_DIS;
		  #endif
	#endif

	#if (MX_UART_FLOWEN_X == 1)										//Flowcontrol enabled?
		FC_CAL_Bit_In_DDR (MX_UART_CTS_PORT_X, MX_UART_CTS_TRIS_X, MX_UART_CTS_PIN_X);		// CTS pin is a input
		FC_CAL_Bit_In_DDR (MX_UART_RTS_PORT_X, MX_UART_RTS_TRIS_X, MX_UART_RTS_PIN_X);		// RTS not ready to accept data
	#endif
}



CALFUNCTION(void, FC_CAL_UART_Send_, (MX_UINT16 nChar))
{
	#if (MX_UART_FLOWEN_X == 1)
		while (FC_CAL_Bit_In(MX_UART_CTS_PORT_X, MX_UART_CTS_PIN_X) != 0);	// Wait until CTS is low
	#endif

	#if (MX_UART_CHANNEL_X == 0)													// Software UART TX
		MX_UINT8 idx;
		FC_CAL_Bit_Low(MX_UART_TX_PORT_X, MX_UART_TX_PIN_X);					// Send Start bit
		UART_Delay_CAL();
		for (idx = 0; idx < MX_UART_DBITS_X; idx++)
		{
			if (nChar & 0x01)														// Mask off data bit
				FC_CAL_Bit_High(MX_UART_TX_PORT_X, MX_UART_TX_PIN_X);
			else
				FC_CAL_Bit_Low(MX_UART_TX_PORT_X, MX_UART_TX_PIN_X);
			UART_Delay_CAL();
			nChar = nChar >> 1;														// Move to next data bit
		}
		FC_CAL_Bit_High(MX_UART_TX_PORT_X, MX_UART_TX_PIN_X);					// Send Stop bit
		UART_Delay_CAL();
	#endif

	#if (MX_UART_CHANNEL_X == 1)
		while (ts_bit(pir1, TXIF) == 0);

		#if (MX_UART_DBITS_X == 9)
			if (test_bit(nChar, 8))
				st_bit(txsta, TX9D);
			else
				cr_bit(txsta, TX9D);
	  	#endif
		txreg = nChar;
	#endif

	#if (MX_UART_CHANNEL_X == 2)
		while (ts_bit(MX_UART2_PIR, TX2IF) == 0);

		#if (MX_UART_DBITS_X == 9)
			if (test_bit(nChar, 8))
				st_bit(MX_UART2_TXSTA, TX9D);
			else
				cr_bit(MX_UART2_TXSTA, TX9D);
		#endif
		MX_UART2_TXREG = nChar;
	#endif
}


CALFUNCTION(MX_SINT16, FC_CAL_UART_Receive_, (MX_UINT8 nTimeout))
{
  #if (MX_UART_RETURN_X == 1)
	MX_UINT16 retVal = 512;
  #else
  	MX_UINT8 retVal = 255;
  #endif

	MX_UINT8 delay1 = 0;
	MX_UINT8 regcheck = 0;
	MX_UINT8 bWaitForever = 0;
	MX_UINT8 rxStatus = UART_STATUS_LOOP;
	MX_UINT16 delaycnt;

  #if (MX_UART_CHANNEL_X == 0)
  	MX_UINT8 idx;
  #else
  	MX_UINT8 dummy = 0;
  #endif

	if (nTimeout == 255)
		bWaitForever = 1;

	#if (MX_UART_FLOWEN_X == 1)
		FC_CAL_Bit_Low (MX_UART_RTS_PORT_X, MX_UART_RTS_PIN_X);			// Ready to accept data
	#endif

	while (rxStatus == UART_STATUS_LOOP)
	{
		if (bWaitForever == 0)
		{
			if (nTimeout == 0)							//don't wait forever, so do timeout thing...
			{
				rxStatus = UART_STATUS_TIMEOUT;
			}
			else
			{
				for (delaycnt = 0; delaycnt < MX_RECEIVE_DELAY; delaycnt++);	//Delay without calling delay function
				delay1 = delay1 + 1;
				if(delay1 == 100)
				{
					nTimeout = nTimeout - 1;
					MX_CLEAR_WATCHDOG;
					delay1 = 0;
				}
			}
		}

		#if (MX_UART_CHANNEL_X == 0)
			regcheck = FC_CAL_Bit_In(MX_UART_RX_PORT_X, MX_UART_RX_PIN_X);	//Test for start bit
			if (regcheck == 0)
				rxStatus = UART_STATUS_RXBYTE;
		#endif

		#if (MX_UART_CHANNEL_X == 1)
			regcheck = ts_bit(pir1, RCIF);
			if (regcheck != 0)
				rxStatus = UART_STATUS_RXBYTE;
		#endif

		#if (MX_UART_CHANNEL_X == 2)
			regcheck = ts_bit(MX_UART2_PIR, RC2IF);
			if (regcheck != 0)
				rxStatus = UART_STATUS_RXBYTE;
		#endif

	}

	if (rxStatus == UART_STATUS_RXBYTE)
	{
		#if (MX_UART_CHANNEL_X == 0)

			retVal = 0;
			UART_Delay_CAL();

			for (idx = 0; idx < MX_UART_DBITS_X; idx++)
			{
				if (FC_CAL_Bit_In(MX_UART_RX_PORT_X, MX_UART_RX_PIN_X))
					retVal = retVal | (0x01 << idx);

				UART_Delay_CAL();
			}
		#endif

		#if (MX_UART_CHANNEL_X == 1)
			regcheck = ts_bit(rcsta, FERR);
			if (regcheck != 0)
			{
				dummy = rcreg;						//need to read the rcreg to clear FERR
				#if (MX_UART_RETURN_X == 1)
					retVal = 0x400;					//Framing Error Flag
				#endif
			}
			else
			{
				regcheck = ts_bit(rcsta, OERR);
				if (regcheck != 0)
				{
					cr_bit(rcsta, CREN);			//Reset receiver to clear error
					st_bit(rcsta, CREN);

					#if (MX_UART_RETURN_X == 1)
						retVal = 0x800;				//Overrun Error Flag
					#endif
				}
				else
				{
					retVal = 0;

					#if (MX_UART_DBITS_X == 9)
						if(ts_bit(rcsta, RX9D))
							retVal = 0x100;
					#endif

					retVal = retVal | rcreg; 			//no error, so rx byte is valid
				}
			}
		#endif

		#if (MX_UART_CHANNEL_X == 2)
			regcheck = ts_bit(MX_UART2_RCSTA, FERR);
			if (regcheck != 0)
			{
				dummy = MX_UART2_RCREG;			//need to read the rcreg to clear FERR
				#if (MX_UART_RETURN_X == 1)
					retVal = 0x400;					//Framing Error Flag
				#endif
			}
			else
			{
				regcheck = ts_bit(MX_UART2_RCSTA, OERR);
				if (regcheck != 0)
				{
					cr_bit(MX_UART2_RCSTA, CREN);	//Reset receiver to clear error
					st_bit(MX_UART2_RCSTA, CREN);
					#if (MX_UART_RETURN_X == 1)
						retVal = 0x800;				//Overrun Error Flag
					#endif
				}
				else
				{
					retVal = 0;

					#if (MX_UART_DBITS_X == 9)
						if(ts_bit(MX_UART2_RCSTA, RX9D))
							retVal = 0x100;
					#endif

					retVal = retVal | MX_UART2_RCREG; 			//no error, so rx byte is valid
				}
			}

		#endif

		#if (MX_UART_ECHO_X == 1)
			UART_Send(retVal);
		#endif
	}

	#if (MX_UART_FLOWEN_X == 1)
		FC_CAL_Bit_High(MX_UART_RTS_PORT_X, MX_UART_RTS_PIN_X);		//not ready to accept data
	#endif

	return (retVal);
}


CALFUNCTION(void, FC_CAL_UART_Delay_, (void))
{
  #if (MX_UART_CHANNEL_X == 0)

	MX_UINT16 delay = MX_SOFT_BAUD_X;

	while (delay > 255)
	{
		delay_us(255);
		delay = delay - 255;
		MX_CLEAR_WATCHDOG;
	}
	delay_us(delay);
	MX_CLEAR_WATCHDOG;

  #endif
}


CALFUNCTION(void, FC_CAL_UART_UpdateBaud_, (MX_UINT8 new_baud))
{
	//Baud Rates - Function compatible with hardware mode only
	/*
	0 - 1200
	1 - 2400
	2 - 4800
	3 - 9600
	4 - 19200
	5 - 38400
	6 - 57600
	7 - 115200
	*/

	MX_UINT8 baudrate, baudmode;

	if (new_baud > 7)
		return;

	if (new_baud == 0)
	{
		baudrate = MX_HARD_BAUD_1200;
		baudmode = MX_HARD_SLOW_1200;
	}
	else if (new_baud == 1)
	{
		baudrate = MX_HARD_BAUD_2400;
		baudmode = MX_HARD_SLOW_2400;
	}
	else if (new_baud == 2)
	{
		baudrate = MX_HARD_BAUD_4800;
		baudmode = MX_HARD_SLOW_4800;
	}
	else if (new_baud == 3)
	{
		baudrate = MX_HARD_BAUD_9600;
		baudmode = MX_HARD_SLOW_9600;
	}
	else if (new_baud == 4)
	{
		baudrate = MX_HARD_BAUD_19200;
		baudmode = MX_HARD_SLOW_19200;
	}
	else if (new_baud == 5)
	{
		baudrate = MX_HARD_BAUD_38400;
		baudmode = MX_HARD_SLOW_38400;
	}
	else if (new_baud == 6)
	{
		baudrate = MX_HARD_BAUD_57600;
		baudmode = MX_HARD_SLOW_57600;
	}
	else if (new_baud == 7)
	{
		baudrate = MX_HARD_BAUD_115200;
		baudmode = MX_HARD_SLOW_115200;
	}

	UART_Uninit();

	#if (MX_UART_CHANNEL_X == 1)

	    if (baudmode == 1)
			cr_bit(txsta, BRGH);					//Low Speed
	    else
			st_bit(txsta, BRGH);					//High Speed

		spbrg = baudrate;   						// set the baud rate
		rcsta = 0;                    				// 8-bit, disabled

		#if(MX_UART_DBITS_X == 9)
			st_bit(txsta, TX9);   					// 9-bit TX
			st_bit(rcsta, RX9);                    	// 9-bit RX
		#endif

		st_bit(rcsta, SPEN);         				// turn on serial interface
		st_bit(txsta, TXEN);
		st_bit(rcsta, CREN);

		#if (MX_UART_INT_X == 1)
			MX_UART_INT_CH1_EN;
			st_bit(intcon, PEIE);
			st_bit(intcon, GIE);
		#else
			cr_bit (pie1, RCIE);
		#endif
	#endif

	#if (MX_UART_CHANNEL_X == 2)

	  	if (baudmode == 1)
			cr_bit(MX_UART2_TXSTA, BRGH);			//Low Speed
	  	else
			st_bit(MX_UART2_TXSTA, BRGH);			//High Speed

		spbrg2 = baudrate;   						// set the baud rate
		MX_UART2_RCSTA = 0;                    		// 8-bit, disabled

		#if(MX_UART_DBITS_X == 9)
			st_bit(MX_UART2_TXSTA, TX9);   			// 9-bit TX
			st_bit(MX_UART2_RCSTA, RX9);            // 9-bit RX
		#endif

		st_bit(MX_UART2_RCSTA, SPEN);         		// turn on serial interface
		st_bit(MX_UART2_TXSTA, TXEN);
		st_bit(MX_UART2_RCSTA, CREN);

		#if (MX_UART_INT_X == 1)
			MX_UART_INT_CH2_EN;
			st_bit(intcon, PEIE);
			st_bit(intcon, GIE);
		#else
			cr_bit (MX_UART2_PIE, RC2IE);
		#endif
	#endif

	#if (MX_UART_FLOWEN_X == 1)						//Flowcontrol enabled?
		FC_CAL_Bit_In_DDR (MX_UART_CTS_PORT_X, MX_UART_CTS_TRIS_X, MX_UART_CTS_PIN_X);	// CTS pin is a input
		FC_CAL_Bit_High_DDR (MX_UART_RTS_PORT_X, MX_UART_RTS_TRIS_X, MX_UART_RTS_PIN_X);	// RTS not ready to accept data
	#endif

}
