// CRC: DAF3BBFBC218194DDD01FE695DEEF1A59F856AD91E1BBFBBEBB54541E166299460962A53099133EF9CCA8FC4F709DA08B770B8B5A4760B27E3EBE58434688A5216F1807400ECC625575200A5E9845AC3F7D883A9EE77903C610ED2ADF4B5FDFC002543F9B49157D0A76C508C585E6A3D3542B439FB62A1905AD630387EE0F5E7A61894EC5669941CB380304E2D518B2820857F6A0FB1062EF7DB906F01FEFA9063725AA1B1D49695B2E0A3F108D13B8354A16AE436F337788DCFF29235443E5C1F13BD2751FCFB0C0DCBF07F91B3D369D3DBAFBF94C6532E4D971B26A51C902B626428E61595AF20
// REVISION: 6.0
// GUID: 1ABE1988-D184-40C0-932D-C3D1319151B2
// DATE: 11\03\2020
// DIR: CAL\STARM\STARM_CAL_I2C.c
/*********************************************************************
 *                  Flowcode CAL I2C File
 *
 * File: ARM_CAL_I2C.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
 * -------+----+-----------------------------------------------------
 * 230911 | BR | Created
 * 050312 | BR | Updated to v5.1 CAL Schema
 * 030713 | LM | Standard API calls
 * 260914 | LM | Changes to Slave macro API
 * 220118 | LM | Add transaction functions
 * 060219 | LM | Add hardware support
 */

/****
This needs checking ...
//When using hardware I2C channels override port and pin conns with FCD conn definitions
#ifdef MX_I2C_REF1
	#if MX_I2C_CHANNEL_1 > 0
		#undef MX_I2C_SDA_PIN_1
		#undef MX_I2C_SDA_PORT_1
		#undef MX_I2C_SDA_TRIS_1
		#undef MX_I2C_SCL_PIN_1
		#undef MX_I2C_SCL_PORT_1
		#undef MX_I2C_SCL_TRIS_1
	#endif
	#if MX_I2C_CHANNEL_1 == 1
		#define MX_I2C_SDA_PIN_1		MX_I2C_1_SDA_PIN
		#define MX_I2C_SDA_PORT_1		MX_I2C_1_SDA_PORT
		#define MX_I2C_SDA_TRIS_1		MX_I2C_1_SDA_TRIS
		#define MX_I2C_SCL_PIN_1		MX_I2C_1_SCL_PIN
		#define MX_I2C_SCL_PORT_1		MX_I2C_1_SCL_PORT
		#define MX_I2C_SCL_TRIS_1		MX_I2C_1_SCL_TRIS
	#endif
	#if MX_I2C_CHANNEL_1 == 2
		#define MX_I2C_SDA_PIN_1		MX_I2C_2_SDA_PIN
		#define MX_I2C_SDA_PORT_1		MX_I2C_2_SDA_PORT
		#define MX_I2C_SDA_TRIS_1		MX_I2C_2_SDA_TRIS
		#define MX_I2C_SCL_PIN_1		MX_I2C_2_SCL_PIN
		#define MX_I2C_SCL_PORT_1		MX_I2C_2_SCL_PORT
		#define MX_I2C_SCL_TRIS_1		MX_I2C_2_SCL_TRIS
	#endif
	#if MX_I2C_CHANNEL_1 == 3
		#define MX_I2C_SDA_PIN_1		MX_I2C_3_SDA_PIN
		#define MX_I2C_SDA_PORT_1		MX_I2C_3_SDA_PORT
		#define MX_I2C_SDA_TRIS_1		MX_I2C_3_SDA_TRIS
		#define MX_I2C_SCL_PIN_1		MX_I2C_3_SCL_PIN
		#define MX_I2C_SCL_PORT_1		MX_I2C_3_SCL_PORT
		#define MX_I2C_SCL_TRIS_1		MX_I2C_3_SCL_TRIS
	#endif
	#if MX_I2C_CHANNEL_1 == 4
		#define MX_I2C_SDA_PIN_1		MX_I2C_4_SDA_PIN
		#define MX_I2C_SDA_PORT_1		MX_I2C_4_SDA_PORT
		#define MX_I2C_SDA_TRIS_1		MX_I2C_4_SDA_TRIS
		#define MX_I2C_SCL_PIN_1		MX_I2C_4_SCL_PIN
		#define MX_I2C_SCL_PORT_1		MX_I2C_4_SCL_PORT
		#define MX_I2C_SCL_TRIS_1		MX_I2C_4_SCL_TRIS
	#endif
#endif
#ifdef MX_I2C_REF2
	#if MX_I2C_CHANNEL_2 > 0
		#undef MX_I2C_SDA_PIN_2
		#undef MX_I2C_SDA_PORT_2
		#undef MX_I2C_SDA_TRIS_2
		#undef MX_I2C_SCL_PIN_2
		#undef MX_I2C_SCL_PORT_2
		#undef MX_I2C_SCL_TRIS_2
	#endif
	#if MX_I2C_CHANNEL_2 == 1
		#define MX_I2C_SDA_PIN_2		MX_I2C_1_SDA_PIN
		#define MX_I2C_SDA_PORT_2		MX_I2C_1_SDA_PORT
		#define MX_I2C_SDA_TRIS_2		MX_I2C_1_SDA_TRIS
		#define MX_I2C_SCL_PIN_2		MX_I2C_1_SCL_PIN
		#define MX_I2C_SCL_PORT_2		MX_I2C_1_SCL_PORT
		#define MX_I2C_SCL_TRIS_2		MX_I2C_1_SCL_TRIS
	#endif
	#if MX_I2C_CHANNEL_2 == 2
		#define MX_I2C_SDA_PIN_2		MX_I2C_2_SDA_PIN
		#define MX_I2C_SDA_PORT_2		MX_I2C_2_SDA_PORT
		#define MX_I2C_SDA_TRIS_2		MX_I2C_2_SDA_TRIS
		#define MX_I2C_SCL_PIN_2		MX_I2C_2_SCL_PIN
		#define MX_I2C_SCL_PORT_2		MX_I2C_2_SCL_PORT
		#define MX_I2C_SCL_TRIS_2		MX_I2C_2_SCL_TRIS
	#endif
	#if MX_I2C_CHANNEL_2 == 3
		#define MX_I2C_SDA_PIN_2		MX_I2C_3_SDA_PIN
		#define MX_I2C_SDA_PORT_2		MX_I2C_3_SDA_PORT
		#define MX_I2C_SDA_TRIS_2		MX_I2C_3_SDA_TRIS
		#define MX_I2C_SCL_PIN_2		MX_I2C_3_SCL_PIN
		#define MX_I2C_SCL_PORT_2		MX_I2C_3_SCL_PORT
		#define MX_I2C_SCL_TRIS_2		MX_I2C_3_SCL_TRIS
	#endif
	#if MX_I2C_CHANNEL_2 == 4
		#define MX_I2C_SDA_PIN_2		MX_I2C_4_SDA_PIN
		#define MX_I2C_SDA_PORT_2		MX_I2C_4_SDA_PORT
		#define MX_I2C_SDA_TRIS_2		MX_I2C_4_SDA_TRIS
		#define MX_I2C_SCL_PIN_2		MX_I2C_4_SCL_PIN
		#define MX_I2C_SCL_PORT_2		MX_I2C_4_SCL_PORT
		#define MX_I2C_SCL_TRIS_2		MX_I2C_4_SCL_TRIS
	#endif
#endif
#ifdef MX_I2C_REF3
	#if MX_I2C_CHANNEL_3 > 0
		#undef MX_I2C_SDA_PIN_3
		#undef MX_I2C_SDA_PORT_3
		#undef MX_I2C_SDA_TRIS_3
		#undef MX_I2C_SCL_PIN_3
		#undef MX_I2C_SCL_PORT_3
		#undef MX_I2C_SCL_TRIS_3
	#endif
	#if MX_I2C_CHANNEL_3 == 1
		#define MX_I2C_SDA_PIN_3		MX_I2C_1_SDA_PIN
		#define MX_I2C_SDA_PORT_3		MX_I2C_1_SDA_PORT
		#define MX_I2C_SDA_TRIS_3		MX_I2C_1_SDA_TRIS
		#define MX_I2C_SCL_PIN_3		MX_I2C_1_SCL_PIN
		#define MX_I2C_SCL_PORT_3		MX_I2C_1_SCL_PORT
		#define MX_I2C_SCL_TRIS_3		MX_I2C_1_SCL_TRIS
	#endif
	#if MX_I2C_CHANNEL_3 == 2
		#define MX_I2C_SDA_PIN_3		MX_I2C_2_SDA_PIN
		#define MX_I2C_SDA_PORT_3		MX_I2C_2_SDA_PORT
		#define MX_I2C_SDA_TRIS_3		MX_I2C_2_SDA_TRIS
		#define MX_I2C_SCL_PIN_3		MX_I2C_2_SCL_PIN
		#define MX_I2C_SCL_PORT_3		MX_I2C_2_SCL_PORT
		#define MX_I2C_SCL_TRIS_3		MX_I2C_2_SCL_TRIS
	#endif
	#if MX_I2C_CHANNEL_3 == 3
		#define MX_I2C_SDA_PIN_3		MX_I2C_3_SDA_PIN
		#define MX_I2C_SDA_PORT_3		MX_I2C_3_SDA_PORT
		#define MX_I2C_SDA_TRIS_3		MX_I2C_3_SDA_TRIS
		#define MX_I2C_SCL_PIN_3		MX_I2C_3_SCL_PIN
		#define MX_I2C_SCL_PORT_3		MX_I2C_3_SCL_PORT
		#define MX_I2C_SCL_TRIS_3		MX_I2C_3_SCL_TRIS
	#endif
	#if MX_I2C_CHANNEL_3 == 4
		#define MX_I2C_SDA_PIN_3		MX_I2C_4_SDA_PIN
		#define MX_I2C_SDA_PORT_3		MX_I2C_4_SDA_PORT
		#define MX_I2C_SDA_TRIS_3		MX_I2C_4_SDA_TRIS
		#define MX_I2C_SCL_PIN_3		MX_I2C_4_SCL_PIN
		#define MX_I2C_SCL_PORT_3		MX_I2C_4_SCL_PORT
		#define MX_I2C_SCL_TRIS_3		MX_I2C_4_SCL_TRIS
	#endif
#endif
#ifdef MX_I2C_REF4
	#if MX_I2C_CHANNEL_4 > 0
		#undef MX_I2C_SDA_PIN_4
		#undef MX_I2C_SDA_PORT_4
		#undef MX_I2C_SDA_TRIS_4
		#undef MX_I2C_SCL_PIN_4
		#undef MX_I2C_SCL_PORT_4
		#undef MX_I2C_SCL_TRIS_4
	#endif
	#if MX_I2C_CHANNEL_4 == 1
		#define MX_I2C_SDA_PIN_4		MX_I2C_1_SDA_PIN
		#define MX_I2C_SDA_PORT_4		MX_I2C_1_SDA_PORT
		#define MX_I2C_SDA_TRIS_4		MX_I2C_1_SDA_TRIS
		#define MX_I2C_SCL_PIN_4		MX_I2C_1_SCL_PIN
		#define MX_I2C_SCL_PORT_4		MX_I2C_1_SCL_PORT
		#define MX_I2C_SCL_TRIS_4		MX_I2C_1_SCL_TRIS
	#endif
	#if MX_I2C_CHANNEL_4 == 2
		#define MX_I2C_SDA_PIN_4		MX_I2C_2_SDA_PIN
		#define MX_I2C_SDA_PORT_4		MX_I2C_2_SDA_PORT
		#define MX_I2C_SDA_TRIS_4		MX_I2C_2_SDA_TRIS
		#define MX_I2C_SCL_PIN_4		MX_I2C_2_SCL_PIN
		#define MX_I2C_SCL_PORT_4		MX_I2C_2_SCL_PORT
		#define MX_I2C_SCL_TRIS_4		MX_I2C_2_SCL_TRIS
	#endif
	#if MX_I2C_CHANNEL_4 == 3
		#define MX_I2C_SDA_PIN_4		MX_I2C_3_SDA_PIN
		#define MX_I2C_SDA_PORT_4		MX_I2C_3_SDA_PORT
		#define MX_I2C_SDA_TRIS_4		MX_I2C_3_SDA_TRIS
		#define MX_I2C_SCL_PIN_4		MX_I2C_3_SCL_PIN
		#define MX_I2C_SCL_PORT_4		MX_I2C_3_SCL_PORT
		#define MX_I2C_SCL_TRIS_4		MX_I2C_3_SCL_TRIS
	#endif
	#if MX_I2C_CHANNEL_4 == 4
		#define MX_I2C_SDA_PIN_4		MX_I2C_4_SDA_PIN
		#define MX_I2C_SDA_PORT_4		MX_I2C_4_SDA_PORT
		#define MX_I2C_SDA_TRIS_4		MX_I2C_4_SDA_TRIS
		#define MX_I2C_SCL_PIN_4		MX_I2C_4_SCL_PIN
		#define MX_I2C_SCL_PORT_4		MX_I2C_4_SCL_PORT
		#define MX_I2C_SCL_TRIS_4		MX_I2C_4_SCL_TRIS
	#endif
#endif
*****/

#define MX_I2C_CHANNEL_X		CAL_APPEND(MX_I2C_CHANNEL_, MX_I2C_NUM)
#define MX_I2C_SDA_PIN_X		CAL_APPEND(MX_I2C_SDA_PIN_, MX_I2C_NUM)
#define MX_I2C_SDA_PORT_X		CAL_APPEND(MX_I2C_SDA_PORT_, MX_I2C_NUM)
#define MX_I2C_SDA_TRIS_X		CAL_APPEND(MX_I2C_SDA_TRIS_, MX_I2C_NUM)
#define MX_I2C_SCL_PIN_X		CAL_APPEND(MX_I2C_SCL_PIN_, MX_I2C_NUM)
#define MX_I2C_SCL_PORT_X		CAL_APPEND(MX_I2C_SCL_PORT_, MX_I2C_NUM)
#define MX_I2C_SCL_TRIS_X		CAL_APPEND(MX_I2C_SCL_TRIS_, MX_I2C_NUM)
#define MX_I2C_BMODE_X			CAL_APPEND(MX_I2C_BMODE_, MX_I2C_NUM)
#define MX_I2C_BAUD_X			CAL_APPEND(MX_I2C_BAUD_, MX_I2C_NUM)
#define MX_I2C_INT_X			CAL_APPEND(MX_I2C_INT_, MX_I2C_NUM)
#define MX_I2C_STOPDEL_X		CAL_APPEND(MX_I2C_STOPDEL_, MX_I2C_NUM)
#define MX_I2C_CLKSTRCH_X		CAL_APPEND(MX_I2C_CLOCKSTRETCHING_, MX_I2C_NUM)

#if (MX_I2C_CHANNEL_X > 0)
	#define MX_I2C_X				CAL_APPEND(I2C, MX_I2C_NUM)					// I2C Name - eg I2C1
	#define MX_I2C_CLOCK_X     		CAL_APPEND(MX_I2C_CLOCK_, MX_I2C_NUM)		// I2C Clock Config - eg __HAL_RCC_SPI1_CLK_ENABLE
	#define MX_I2C_HANDLE_X			CAL_APPEND(MX_I2C_HANDLE_, MX_I2C_NUM)		// I2C instance structure handle
	#define MX_I2C_SCL_AF_X			CAL_APPEND(MX_I2C_SCL_AF_, MX_I2C_NUM)		// I2C SCL Alt
	#define MX_I2C_SDA_AF_X			CAL_APPEND(MX_I2C_SDA_AF_, MX_I2C_NUM)		// I2C SDA Alt
	I2C_HandleTypeDef MX_I2C_HANDLE_X;											// Create I2C Structure
#endif

//Function Prototypes
CALFUNCTION(void, FC_CAL_I2C_Master_Init_, (void));
CALFUNCTION(void, FC_CAL_I2C_Master_Uninit_, (void));
CALFUNCTION(void, FC_CAL_I2C_Master_Start_, (void));
CALFUNCTION(void, FC_CAL_I2C_Master_Restart_, (void));
CALFUNCTION(void, FC_CAL_I2C_Master_Stop_, (void));
CALFUNCTION(MX_UINT8, FC_CAL_I2C_Master_TxByte_, (MX_UINT8 Data));
CALFUNCTION(MX_UINT8, FC_CAL_I2C_Master_RxByte_, (MX_UINT8 Last));

CALFUNCTION(void, FC_CAL_I2C_Slave_Init_, (MX_UINT8 Address, MX_UINT8 Mask));
CALFUNCTION(void, FC_CAL_I2C_Slave_Uninit_, (void));
CALFUNCTION(MX_UINT8, FC_CAL_I2C_Slave_TxByte_, (MX_UINT8 Data));
CALFUNCTION(MX_UINT8, FC_CAL_I2C_Slave_RxByte_, (MX_UINT8 Last));
CALFUNCTION(MX_UINT8, FC_CAL_I2C_Slave_Status_, (void));

CALFUNCTION(MX_UINT8, FC_CAL_I2C_Transaction_Init_,   (MX_UINT8 SlaveAddress));
CALFUNCTION(MX_UINT16, FC_CAL_I2C_Transaction_Read_,   (MX_UINT8* Buffer, MX_UINT16 Size, MX_UINT16 Length));
CALFUNCTION(MX_UINT16, FC_CAL_I2C_Transaction_Write_,  (MX_UINT8* Buffer, MX_UINT16 Size, MX_UINT16 Length));
CALFUNCTION(void,     FC_CAL_I2C_Transaction_Uninit_, (void));



//If software channel is enabled then define bit delay.
#if (MX_I2C_CHANNEL_X == 0)
  #ifndef MX_I2C_SW_DEL
	#define MX_I2C_SW_BAUD	((500000 / MX_I2C_BAUD_X)-1)

	#if (MX_I2C_SW_BAUD < 1)
		#define MX_I2C_DELAY	delay_us(1);
	#else
		#define MX_I2C_DELAY	delay_us(MX_I2C_SW_BAUD);
	#endif

  #endif
#endif


CALFUNCTION(void, FC_CAL_I2C_Master_Init_, (void))
{

	#if (MX_I2C_CHANNEL_X == 0)															//Use Master I2C Software
		FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X);		//Configure SDA as Input
		FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X);		//Configure SCL as Input
	#endif

}

CALFUNCTION(void, FC_CAL_I2C_Master_Uninit_, (void))
{
	#if (MX_I2C_CHANNEL_X == 0)															//Use Master I2C Software
		FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X);		//Configure SDA as Input
		FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X);		//Configure SCL as Input
	#endif

	#if (MX_I2C_CHANNEL_X == 1)															//Use Master I2C Hardware 1
		//ARM does not support I2C in this mode - SW only
	#endif
}

CALFUNCTION(void, FC_CAL_I2C_Master_Start_, (void))
{
	#if (MX_I2C_CHANNEL_X == 0)															//Use Master I2C Software
		FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X);		//Make Sure SCL is Set
		FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X);		//Make Sure SDA is Set
		MX_I2C_DELAY;																	//Small Delay
		FC_CAL_Bit_Low_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X);		//Clear SDA
		MX_I2C_DELAY;																	//Small Delay
		FC_CAL_Bit_Low_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X);		//Clear SCL
		//MX_I2C_DELAY;																	//Small Delay //Removed 050613 - BR
	#endif

	#if (MX_I2C_CHANNEL_X == 1)															//Use Master I2C Hardware 1
		//ARM does not support I2C in this mode - SW only
  	#endif
}

CALFUNCTION(void, FC_CAL_I2C_Master_Restart_, (void))
{
	#if (MX_I2C_CHANNEL_X == 0)															//Use Master I2C Software
		FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X);		//Set SDA High
		MX_I2C_DELAY;
		FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X);		//Set SCL High
		MX_I2C_DELAY;
		FC_CAL_Bit_Low_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X);		//Set SDA Low
		MX_I2C_DELAY;
		FC_CAL_Bit_Low_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X);		//Set SCL Low
		//MX_I2C_DELAY;																	//Small Delay //Removed 050613 - BR
	#endif

	#if (MX_I2C_CHANNEL_X == 1)															//Use Master I2C Hardware 1
		//ARM does not support I2C in this mode - SW only
	#endif
}

CALFUNCTION(void, FC_CAL_I2C_Master_Stop_, (void))
{
	#if (MX_I2C_CHANNEL_X == 0)															//Use Master I2C Software
		FC_CAL_Bit_Low_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X);		//Set SCL Low
		FC_CAL_Bit_Low_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X);		//Set SDA Low
		MX_I2C_DELAY;
		FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X);		//Set SCL High
		MX_I2C_DELAY;
		FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X);		//Set SDA High
	#endif

	#if (MX_I2C_CHANNEL_X == 1)															//Use Master I2C Hardware 1
		//ARM does not support I2C in this mode - SW only
	#endif

	#if (MX_I2C_STOPDEL_X == 1)
  	  delay_ms(10);		//Wait before reusing the I2C BUS -  avoids lockup problem exibited on some PICs
	#endif
}

CALFUNCTION(MX_UINT8, FC_CAL_I2C_Master_TxByte_, (MX_UINT8 Data))
{
	#if (MX_I2C_CHANNEL_X == 0)															//Use Master I2C Software
		MX_UINT8 bit_mask;
		MX_UINT8 local_ack = 0;
		for(bit_mask=0x80;bit_mask;bit_mask=bit_mask>>1)
		{
			if(Data & bit_mask)
			{
				FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X);	//Set SDA High
			}
			else
			{
				FC_CAL_Bit_Low_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X);	//Set SDA Low
			}
			MX_I2C_DELAY;
			FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X);		//Set SCL High
			MX_I2C_DELAY;

			#if (MX_I2C_CLKSTRCH_X == 1)
				while (FC_CAL_Bit_In(MX_I2C_SCL_PORT_X, MX_I2C_SCL_PIN_X) == 0);		//Wait for the clock to go high - Clock stretching.
			#endif

			FC_CAL_Bit_Low_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X);		//Set SCL Low
			//MX_I2C_DELAY;																	//Small Delay //Removed 050613 - BR
		}
		FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X);			//Set SDA High
		MX_I2C_DELAY;
		FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X);			//Set SCL High
		MX_I2C_DELAY;
		FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X);
		if (FC_CAL_Bit_In(MX_I2C_SDA_PORT_X, MX_I2C_SDA_PIN_X))		//Get the Status Bit
			local_ack = 1;
		//MX_I2C_DELAY;																	//Small Delay //Removed 050613 - BR
		FC_CAL_Bit_Low_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X);			//Set SCL Low
		//MX_I2C_DELAY;																	//Small Delay //Removed 050613 - BR
		return (local_ack);													//0 = Ack received : 1 = Ack not received
	#endif

	#if (MX_I2C_CHANNEL_X == 1)												//Use Master I2C Hardware 1
		//ARM does not support I2C in this mode - SW only
	#endif
}

CALFUNCTION(MX_UINT8, FC_CAL_I2C_Master_RxByte_, (MX_UINT8 Last))
{
	#if (MX_I2C_CHANNEL_X == 0)												//Use Master I2C Software
		MX_UINT8 bit_mask;
		MX_UINT8 Data = 0;
		FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X);			//Set SDA High
		MX_I2C_DELAY;
		for(bit_mask=0x80;bit_mask;bit_mask=bit_mask>>1)
		{
			FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X);		//Set SCL High
			MX_I2C_DELAY;

			#if (MX_I2C_CLKSTRCH_X == 1)
				while (FC_CAL_Bit_In(MX_I2C_SCL_PORT_X, MX_I2C_SCL_PIN_X) == 0);		//Wait for the clock to go high - Clock stretching.
			#endif

			FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X);
			if(FC_CAL_Bit_In(MX_I2C_SDA_PORT_X, MX_I2C_SDA_PIN_X))	//Read Incoming Bit
				Data = Data | bit_mask;														//Add data to variable
			FC_CAL_Bit_Low_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X);		//Set SCL Low
			MX_I2C_DELAY;
		}
		if (Last)																		//Acknowledge?
		{
			FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X);	//Send Nack
		}
		else
		{
			FC_CAL_Bit_Low_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X);	//Send Ack
		}
		MX_I2C_DELAY;
		FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X);		//Set SCL High
		MX_I2C_DELAY;
		FC_CAL_Bit_Low_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X);		//Set SCL Low
		//MX_I2C_DELAY;																	//Small Delay //Removed 050613 - BR
		return (Data);
	#endif

	#if (MX_I2C_CHANNEL_X == 1)						//Use Master I2C Hardware 1
		//ARM does not support I2C in this mode - SW only
	#endif
}




//Slave functions currently not implemented
CALFUNCTION(void, FC_CAL_I2C_Slave_Init_, (MX_UINT8 Address, MX_UINT8 Mask))
{

}

CALFUNCTION(void, FC_CAL_I2C_Slave_Uninit_, (void))
{

}

CALFUNCTION(MX_UINT8, FC_CAL_I2C_Slave_TxByte_, (MX_UINT8 Data))
{
	return (0);
}

CALFUNCTION(MX_UINT8, FC_CAL_I2C_Slave_RxByte_, (MX_UINT8 Last))
{
	return (0);
}

CALFUNCTION(MX_UINT8, FC_CAL_I2C_Slave_Status_, (void))
{
	return (0);
}



/**************************************************
	Master Transaction functions
**************************************************/

#define MX_I2C_ADDRESS_X		CAL_APPEND(MX_I2C_ADDRESS_, MX_I2C_NUM)
MX_UINT8 MX_I2C_ADDRESS_X;


CALFUNCTION(MX_UINT8, FC_CAL_I2C_Transaction_Init_,   (MX_UINT8 SlaveAddress))
{
	MX_I2C_ADDRESS_X = SlaveAddress;
	#if (MX_I2C_CHANNEL_X == 0)
		CALFUNCTION(, FC_CAL_I2C_Master_Init_, ());
		return 1;	// Success
	#else
		GPIO_InitTypeDef  GPIO_InitStruct;
		
		#if (MX_I2C_CHANNEL_X == 1)
			__HAL_RCC_I2C1_CLK_ENABLE();
		#elif (MX_I2C_CHANNEL_X == 2)
			__HAL_RCC_I2C2_CLK_ENABLE();
		#endif

		#if defined (__STM32F0xx_HAL_I2C_H)
			#if (MX_I2C_CHANNEL_X == 1)
				RCC_PeriphCLKInitTypeDef PeriphClkInit;
				PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C1;
				PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_HSI;
				HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
			#elif (MX_I2C_CHANNEL_X == 2)
				RCC_PeriphCLKInitTypeDef PeriphClkInit;
				PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C2;
				PeriphClkInit.I2c1ClockSelection = RCC_I2C2CLKSOURCE_HSI;
				HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
			#endif
		#endif

		/* I2C SCL GPIO pin configuration  */
		GPIO_InitStruct.Pin       = 1 << MX_I2C_SCL_PIN_X;
		GPIO_InitStruct.Mode      = GPIO_MODE_AF_OD;
		GPIO_InitStruct.Pull      = GPIO_PULLUP;
		GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
		GPIO_InitStruct.Alternate = MX_I2C_SCL_AF_X;
		HAL_GPIO_Init(MX_I2C_SCL_PORT_X, &GPIO_InitStruct);

		/* I2C SDA GPIO pin configuration  */
		GPIO_InitStruct.Pin 	  = 1 << MX_I2C_SDA_PIN_X;
		GPIO_InitStruct.Alternate = MX_I2C_SDA_AF_X;
		HAL_GPIO_Init(MX_I2C_SDA_PORT_X, &GPIO_InitStruct);

		MX_I2C_HANDLE_X.Instance = MX_I2C_X;

		#if defined (__STM32F0xx_HAL_I2C_H)
			// This code currently assumes fI2CCLK is HSI (the default)
			#if (MX_I2C_BAUD_X < 300000)
				// 100K
				MX_I2C_HANDLE_X.Init.Timing = (0x01U << I2C_TIMINGR_PRESC_Pos)
												|(0x04U << I2C_TIMINGR_SCLDEL_Pos)
												|(0x02U << I2C_TIMINGR_SDADEL_Pos)
												|(0x0FU << I2C_TIMINGR_SCLH_Pos)
												|(0x13U << I2C_TIMINGR_SCLL_Pos);
			#elif (MX_I2C_BAUD_X < 500000)
				// 400K
				MX_I2C_HANDLE_X.Init.Timing = (0 << I2C_TIMINGR_PRESC_Pos)
												|(0x01U << I2C_TIMINGR_SCLDEL_Pos)
												|(0x01U << I2C_TIMINGR_SDADEL_Pos)
												|(0x03U << I2C_TIMINGR_SCLH_Pos)
												|(0x09U << I2C_TIMINGR_SCLL_Pos);
			#else
				// 500K (max at HSI)
				MX_I2C_HANDLE_X.Init.Timing = (0x00U << I2C_TIMINGR_PRESC_Pos)
												|(0x00U << I2C_TIMINGR_SCLDEL_Pos)
												|(0x00U << I2C_TIMINGR_SDADEL_Pos)
												|(0x03U << I2C_TIMINGR_SCLH_Pos)
												|(0x06U << I2C_TIMINGR_SCLL_Pos);
			#endif
			
		#elif defined (__STM32F4xx_HAL_I2C_H)
			MX_I2C_HANDLE_X.Init.ClockSpeed = MX_I2C_BAUD_X;
			MX_I2C_HANDLE_X.Init.DutyCycle = I2C_DUTYCYCLE_2;
			
		#else
			// This needs further work ...
			MX_I2C_HANDLE_X.Init.Timing = 0x70777F7F;
		#endif

		MX_I2C_HANDLE_X.Init.OwnAddress1 = 0;
		MX_I2C_HANDLE_X.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
		MX_I2C_HANDLE_X.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
		MX_I2C_HANDLE_X.Init.OwnAddress2 = 0;
		MX_I2C_HANDLE_X.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
		MX_I2C_HANDLE_X.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
		MX_I2C_HANDLE_X.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
		if (HAL_I2C_Init(&MX_I2C_HANDLE_X) == HAL_OK)
			return 1;	// Success
		else
			return 0;	// Fail
	#endif
}

CALFUNCTION(MX_UINT16, FC_CAL_I2C_Transaction_Read_,   (MX_UINT8* Buffer, MX_UINT16 Size, MX_UINT16 Length))
{
	if (Length > Size) return 0;
	MX_UINT16 n = 0;
	#if (MX_I2C_CHANNEL_X == 0)
		CALFUNCTION( , FC_CAL_I2C_Master_Start_, ());
		if ( CALFUNCTION( , FC_CAL_I2C_Master_TxByte_, ((MX_I2C_ADDRESS_X<<1)|1)))
			return 0;
		while (n < Length)
		{
			Buffer[n] = CALFUNCTION(, FC_CAL_I2C_Master_RxByte_, ((n+1==Length)?1:0));
			++n;
		}
		CALFUNCTION( , FC_CAL_I2C_Master_Stop_, ());
		return n;
	#else
		if (HAL_I2C_Master_Receive(&MX_I2C_HANDLE_X, (MX_I2C_ADDRESS_X<<1), Buffer, Length, 200) == HAL_OK)
			return Length;
		else
			return 0;
	#endif

}

CALFUNCTION(MX_UINT16, FC_CAL_I2C_Transaction_Write_,  (MX_UINT8* Buffer, MX_UINT16 Size, MX_UINT16 Length))
{
	if (Length > Size) return 0;
	MX_UINT16 n = 0;
	#if (MX_I2C_CHANNEL_X == 0)
		CALFUNCTION( , FC_CAL_I2C_Master_Start_, ());
		if ( CALFUNCTION( , FC_CAL_I2C_Master_TxByte_, (MX_I2C_ADDRESS_X<<1)))
			return 0;
		while (n < Length)
		{
			if ( CALFUNCTION( , FC_CAL_I2C_Master_TxByte_, (Buffer[n])))
				break;
			++n;
		}
		CALFUNCTION( , FC_CAL_I2C_Master_Stop_, ());
	#else
		HAL_StatusTypeDef ErrorCode = HAL_I2C_Master_Transmit(&MX_I2C_HANDLE_X, (MX_I2C_ADDRESS_X<<1), Buffer, Length, 2000);
		if (ErrorCode == HAL_OK)
			return Length;
		else
			return 0;
	#endif
	return n;
}

CALFUNCTION(void,     FC_CAL_I2C_Transaction_Uninit_, (void))
{
	#if (MX_I2C_CHANNEL_X == 0)
		CALFUNCTION(, FC_CAL_I2C_Master_Uninit_, ());
	#else
		HAL_I2C_DeInit(&MX_I2C_HANDLE_X);
	#endif
}
