;**********************************************************************************************************
;
;                               I2C Master : General Purpose Macros & Subroutines
;
;               High Level Routines, Uses Low level Routines (in I2C_LOW.ASM)                                   
;
;**********************************************************************************************************


	Functions/Macros Implemented :

		MACROS :

			I2C_TEST_DEVICE
			I2C_WRITE
			I2C_WRITE_SUB
			I2C_WR_SUB_SWINC
			I2C_WR_MEM_BYTE
			I2C_WR_MEM_BUF
			I2C_READ
			I2C_READ_SUB
			I2C_READ_STATUS
			I2C_WR_SUB_WR
			I2C_WR_SUB_RD
			I2C_WR_COM_WR


		Functions :

			TxmtStartBit:			Send a Start Bit
			TxmtStopBit:			Send a Stop Bit
			Txmt_Slave_Addr:		Send the Slave Address (8/10) with R/W bit set(from Control Reg)
			SendData:			Sends out a Byte Of Data
			GetData:			Receives a Byte Of Data

			_i2c_block_write:		Writes a block of data starting pointed to by FSR0
			_i2c_block_read:		Reads in a block of data starting at addr pointed to by FSR0



	Control Reg :

		#define	_10BitAddr	Bus_Control,0		; 1 Sets to 10 Bit Addressing
		#define	_Slave_RW	Bus_Control,1		; 1 Sets to  READ Mode 
		#define	_Last_Byte_Rcv	Bus_Control,2		; 1 Sets to last byte, so NACK is sent
	
		#define	_SlaveActive	Bus_Control,6		; Status : 1 indicates if a Slave Is Activeafter a call to IsSlaveActive
		#define	_TIME_OUT_	Bus_Control,7		; Set to 1 if Clock is Stretched for much too long (RTCC is currently set to 1 mSec)


	Status Reg :

		#define	_Bus_Busy	Bus_Status,0		; 1 for Bus busy
		#define	_Abort		Bus_Status,1		; 1 Indicates that comminication was Aborted
		#define	_Txmt_Progress	Bus_Status,2		; 1 for Txmt progress
		#define	_Rcv_Progress	Bus_Status,3		; 1 indicated that Reception is in progress

		#define	_Txmt_Success	Bus_Status,4		; Set to 1 for Txmt Success
		#define	_Rcv_Success	Bus_Status,5		; Set to 1 if Reception was Successful
		#define	_Fatal_Error	Bus_Status,6		; Set to 1 on a Fatal Error condition : Clock Held Low by a slave for much too long
		#define	_ACK_Error	Bus_Status,7		; Slave Acknowledgement Error


	Data Registers :

		SlaveAddr		; Slave Addr must be loader into this 2 Byte Register

		DataByte		; 8 Bit data to be transmitted or received

		SubAddr			; Sub Address of slave (used in I2C_HIGH.ASM : High level routines)


;**********************************************************************************************************
;
;                               I2C_TEST_DEVICE
; MACRO
;
;   If Slave Device is listening, then _SlaveActive bit is set, else is cleared
;
;	Parameter :  NONE
;
;   Sequence Of Operations :
;       S-SlvAW-A-P
;   If A is +ve device is listening, else either busy, not present or error condition
;
;   This test may also be used to check for eample if a Serial EEPROM is in internal programming
;   mode
;
;  NOTE : The address of the slave must be loaded into SlaveAddress Registers, and 10 or 8 bit
;               mode addressing must be set
;**********************************************************************************************************



;**********************************************************************************************************
;                               I2C_WRITE
;
;  A basic macro for writing a block of data to a slave
;
;  Parameters :
;               _BYTES_                 #of bytes starting from RAM pointer _SourcePointer_
;               _SourcePointer_         Data Start Buffer pointer in RAM (file Registers)
;
;   Sequence :
;               S-SlvAW-A-D[0]-A.....A-D[N-1]-A-P
;
;  If an error occurs then the routine simply returns and user should check for
;       flags in Bus_Status Reg (for eg. _Txmt_Success flag)
;
;  NOTE : The address of the slave must be loaded into SlaveAddress Registers, and 10 or 8 bit
;               mode addressing must be set
;**********************************************************************************************************


;**********************************************************************************************************
;                            I2C_WRITE_SUB
;                               
;  Writes a message just like I2C_WRITE, except that the data is preceeded by a sub-address
;  to a slave device.
;               Eg. : A serial EEPROM would need an address of memory location for Random Writes
;
;  Parameters :
;               _BYTES_                 #of bytes starting from RAM pointer _SourcePointer_ (constant)
;               _SourcePointer_         Data Start Buffer pointer in RAM (file Registers)
;               _Sub_Address_           Sub-address of Slave (constant)
;
;   Sequence :
;               S-SlvAW-A-SubA-A-D[0]-A.....A-D[N-1]-A-P
;
;  If an error occurs then the routine simply returns and user should check for
;       flags in Bus_Status Reg (for eg. _Txmt_Success flag
;
;       Returns :       WREG = 1 on success, else WREG = 0
;
;  NOTE : The address of the slave must be loaded into SlaveAddress Registers, and 10 or 8 bit
;               mode addressing must be set
;
;  COMMENTS :
;               I2C_WR may prove to be more efficient than this macro in most situations
;               Advantages will be found for Random Address Block Writes for Slaves with
;               Auto Increment Sub-Addresses (like Microchip's 24CXX series Serial EEPROMS)
;
;**********************************************************************************************************


;**********************************************************************************************************
;                               I2C_WR_SUB_SWINC
;
;  Parameters :
;               _BYTES_                 #of bytes starting from RAM pointer _SourcePointer_ (constant)
;               _SourcePointer_         Data Start Buffer pointer in RAM (file Registers)
;               _Sub_Address_           Sub-address of Slave (constant)
;
;   Sequence :
;               S-SlvAW-A-(SubA+0)-A-D[0]-A-P
;               S-SlvAW-A-(SubA+1)-A-D[1]-A-P
;                       and so on until #of Bytes
;
;  If an error occurs then the routine simply returns and user should check for
;       flags in Bus_Status Reg (for eg. _Txmt_Success flag
;
;       Returns :       WREG = 1 on success, else WREG = 0
;
;  COMMENTS : Very In-efficient, Bus is given up after every Byte Write
;
;               Some I2C devices addresed with a sub-address do not increment automatically
;       after an access of each byte. Thus a block of data sent must have a sub-address
;       followed by a data byte.
;  
;**********************************************************************************************************


;**********************************************************************************************************
;
;                               I2C_WR_MEM_BYTE
;
;  Some I2C devices like a EEPROM need to wait fo some time after every byte write
;  (when entered into internal programming mode). This MACRO is same as I2C_WR_SUB_SWINC,
;  but in addition adds a delay after each byte.
;          Some EERPOM memories (like Microchip's 24Cxx Series have on-chip data buffer), and hence
;               this routine is not efficient in these cases. In such cases use I2C_WR or I2C_WR_SUB
;               for a block of data and then insert a delay until the whole buffer is written.
;
;  Parameters :
;               _BYTES_                 #of bytes starting from RAM pointer _SourcePointer_ (constant)
;               _SourcePointer_         Data Start Buffer pointer in RAM (file Registers)
;               _Sub_Address_           Sub-address of Slave (constant)
;
;   Sequence :
;               S-SlvAW-A-(SubA+0)-A-D[0]-A-P
;                       Delay 1 mSec            ; The user can chnage this value to desired delay
;               S-SlvAW-A-(SubA+1)-A-D[1]-A-P
;                       Delay 1 mSec
;                       and so on until #of Bytes
;
;**********************************************************************************************************


;**********************************************************************************************************
;                    I2C_WR_MEM_BUF
;
;   This Macro/Function write #of _BYTES_ to an I2C memory device. However
;   some devices, esp. EEPROMs must wait while the device enters into programming 
;   mode. But some devices have an onchip temp data hold buffer and is used to 
;  store data before the device actually enters into programming mode.
;               For example, the 24C04 series of Serial EEPROMs from Microchip
;       have an 8 byte data buffer. So one can send 8 bytes of data at a time
;       and then the device enters programming mode. The master can either wait 
;       until a fixed time and then retry to program or can continiously poll
;       for ACK bit and then transmit the next Block of data for programming
;
;  Parameters :
;               _BYTES_         # 0f bytes to write to memory
;               _SourcePointer_ Pointer to the block of data
;               _SubAddress_    Sub-address of the slave
;               _Device__BUF_SIZE_      The on chip buffer size of the i2c slave
;
;  Sequence of operations
;
;**********************************************************************************************************


;**********************************************************************************************************
;
;                               I2C_READ
;
; The basic MACRO/procedure to read a block message from a slave device
;
;   Parameters :
;               _BYTES_         :  constant : #of bytes to receive
;               _DestPointer_   :  destination pointer of RAM (File Registers)
;
;   Sequence :
;               S-SlvAR-A-D[0]-A-.....-A-D[N-1]-N-P
;
;   If last byte, then Master will NOT Acknowledge (send NACK)
;
;  NOTE : The address of the slave must be loaded into SlaveAddress Registers, and 10 or 8 bit
;               mode addressing must be set
;
;**********************************************************************************************************




;**********************************************************************************************************
;
;                               I2C_READ_SUB
;  This MACRO/Subroutine reads a message from a slave device preceeded by a write of the sub-address
;  Between the sub-addrers write & the following reads, a STOP condition is not issued and
;  a "REPEATED START" condition is used so that an other master will not take over the bus,
;  and also that no other master will overwrite the sub-address of the same salve.
;
;   This function is very commonly used in accessing Random/Sequential reads from a
;       memory device (e.g : 24Cxx serial of Serial EEPROMs from Microchip).
;
;  Parameters :
;               _BYTES_         # of bytes to read
;               _DestPointer_   The destination pointer of data to be received.
;               _BubAddress_    The sub-address of the slave 
;
;
;**********************************************************************************************************



;**********************************************************************************************************
;
;                               I2C_READ_STATUS
;
;  This Macro/Function reads a status word (1 byte) from slave. Several I2C devices can
;  send a status byte upon reception of a control byte
;               This is basically same as I2C_READ MACRO for reading a single byte
;
;   For example, in a Serial EEPROM (Microchip's 24Cxx serial EEPROMs) will send the memory
;       data at the current address location
;
;  On success WREG = 1 else = 0
;
;**********************************************************************************************************



;**********************************************************************************************************
;
;                               I2C_WR_SUB_WR
;
;  This Macro write 2 Blocks of Data (variable length) to a slave at a sub-address. This
;  may be useful for devices which need 2 blocks of data in which the first block may be an
;  extended address of a slave device. For example, a large I2C memory device, or a teletext
;  device with an extended addressing scheme, may need multiple bytes of data in the 1st block
;  that represents the actual physical address and is followed by a 2nd block that actually
;  represents the data. 
;
;  Parameters :
;
;               _BYTES1_                1st block #of bytes
;               _SourcePointer1_        Start Pointer of the 1st block
;               _SubAddress_            Sub-Address of slave
;               _BYTES2_                2st block #of bytes
;               _SourcePointer2_        Start Pointer of the 2nd block
;
;  Sequence :
;               S-SlvW-A-SubA-A-D1[0]-A-....-D1[N-1]-A-D2[0]-A-.....A-D2[M-1]-A-P
;   
;  Note : This MACRO is basically same as calling I2C_WR_SUB twice, but
;               a STOP bit is not sent (bus is not given up) in between
;               the two I2C_WR_SUB
;
;  Check Txmt_Success flag for any transmission errors
;
;**********************************************************************************************************



;**********************************************************************************************************
;
;                               I2C_WR_SUB_RD
;
;  This macro writes a block of data from SourcePointer of length _COUNT1_ to a slave
;       at sub-address and then Reads a block of Data of length _COUNT2_ to destination
;       address pointer
;
;
;  Message Structure :
;              S-SlvW-A-SubA-A-D1[0]-A-.....-A-D1[N-1]-A-S-SlvR-A-D2[0]-A-......A-D2[M-1]-N-P
;
;  Parameters :
;		_COUNT1_		Length Of Source Buffer
;		_SourcePointer_		Source Pointer Address
;		_Sub_Address_		The Sub Address Of the slave
;		_COUNT2_		The length of Destination Buffer
;		_DestPointer_		The start address of Destination Pointer                   
;
;**********************************************************************************************************


;**********************************************************************************************************
;
;                               I2C_WR_COM_WR
;
;  This Macro write 2 blocks of data buffers to a slave in one message. This way no need to give up
;  the bus after sending the first block.
;               For example, this kind of transaction is used in an LCD driver where a
;       a block of control & addresss info is needed and then another block of actual data
;       to be displayed is needed. 
;
;
;  Message Structure :
;               S-SlvW-A-D1[0]-A-.....A-D1[N-1]-A-D2[0]-A-......-A-D2[M-1]-A-P
;  NOTE : This message is same as calling two I2C_WR Macros, except that
;       the bus is not given up between the sending of 2 blocks (this is
;       done by not sending a STOP bit inbetween)
;
;
;  Parameters :
;		_COUNT1_		Length Of Source Buffer #1
;		_SourcePointer1_	Source Pointer Address of 1st buffer
;		_COUNT2_		The length of Destination Buffer
;		_SourcePointer2_	Source Pointer Address of 2nd Buffer
;
;**********************************************************************************************************




