;=======================================================================
; 	INTER - INTEGRATED CIRCUIT (I2C) SERIAL INTERFACE 
;			VIRTUAL PERIPHERAL
;	I2CSDO1.SRC -- I2CS (Authentic I2C Slave) VP Demo #1
;	Revision X1.01, 08.14.98
;	Developed by Authentic Engineering for Scenix Semiconductor, Inc.
;	Authentic Engineering // www.authenticeng.com // ak@silcom.com
;
;	We consider this revision as a Beta version, and would appreciate
;	any feedback and recommendation on the improvements of this VP.	
;=======================================================================
;=======================================================================
;
;	Authentic I2CS (I2CS Slave) Virtual Peripheral
;
;	I2CS is a part of the Authentic SPI virtual peripherals for SX micro.
;	This VP provides the means to connect the SX microcontroller to the 
;	I2C Bus. It supports data transfer in 10-bit address mode at clock 
;	rates up to 1.8MHz. It supports transfer of only one byte at a time.	
;
;	------ Communication Protocol -----
;
;	I2C Bus protocol was introduced more than ten years ago. Original 
;	I2CS protocol (with seven bit address and clock frequency up to 
;	0.2 MHz) is widely used by the industry. However, some extensions 
;	of this protocol were developed in order to provide wider address 
;	space and faster transfer rate. For more details please refer to 
;	I2C Peripherals for Microcontrollers Data Handbook, published by
;	Philips Semiconductors in 1992.
;
;	I2CS complies with extension of the I2C protocol - 10 bit address
;	and fast clock rate of 400 KHz (in fact data transfer rate may
;	be as high as 1.8 Mb/s). I2CS does not support GENERAL CALL 
;	command on the I2C Bus. I2CS does not support CBUS protocol.
;	I2CS also does not support original 7-bit address protocol,
;	however it can be easily modified to work in 7-bit address mode.
;
;	Authentic I2CS VP supports I2C Bus communication protocol, 
;	recommended by Philips for software implementations of I2C 
;	Slaves.	According to this protocol data transfer cycle includes 
;	next steps:
;
;	1. I2C Bus Master generates S (start condition) and then generates
;	Start Byte - special byte used only to establish communication
;	with slow responding, software driven I2C devices. Start Byte is -
;	01h.
; 
;	I2C Slave monitors the SDA line often enough to detect the 
;	long SDA line LOW state associated with 01h byte. When this event 
;	on the Bus is detected the Slave starts to monitor the SDA line 
;	often enough to detect Sr (start repeat) condition. Slave  
;	should not generate ACK signal in response to Start Byte.
;
;	2. Master generates Sr (start repeat) condition. Sr condition
;	is detected by Slave and Slave starts to receive the address from 
;	the Master.
;
;	3. Master sends to Slave two byte of address information. If the
;	address information matches Slave address, the Slave must 
;	generate ACK signals for each of two bytes.
;	
;	First byte is 1111 0SS(r/w), where SS are two MSBs of 10-bit Slave 
;	address, R/W is the transfer direction bit. R/W=1 corresponds to 
;	data transfer from Slave to Master.
;
;	Second Byte contains simply eight bits of Slave Bus address
;
;	4. Data are transferred to/from Master. When the data are transferred
;	to Slave the Slave generates the ACK signal.
;
;	5. Master generates P (Stop) condition.
;	
;	6. Transfer can be interrupted at any time by Sr or P (Stop) signals
;	generated by Master. To detect these situations Slave monitors SDA line
;	during each SCL HIGH state.
;
;	It is worth mentioning that the I2CS protocol was developed having
;	in mind easy hardware implementation. The software implementation
;	of this protocol is relatively complicated. Specifically - the software 
;	must assure correct response on Start and Stop conditions on the bus.
;	It may contradict with other software functions. In this case we recommend
;	to develop relatively simple hardware extension to support this protocol.
;
;	----- Timing considerations ------
;
;	I2CS must sample the SDA line often enough to assure detection of Start Byte.
;	The minimum sampling depends on Bus Clock frequency. For the clock
;	frequency of 400 KHz the sampling period should not be more than 18 usec.
;	I2CS must be called by MAIN program at least every 18 usec. The I2CS will 
;	exit within 180 nsec in the case when SDA LOW state is not detected.
;	So, the sampling of the SDA Bus occupies only 1% of CPU time.
;
;	When the SDA LOW state is detected, the I2CS will wait for 30 usec or until
;	the Sr condition is detected. This waiting time is controlled by 
;
;		I2CS_START_TIMEOUT. 
;		F0h value corresponds to 30 usec waiting time. 
;	
;	In order to prevent I2CS locking in case of I2C Bus faults (like absents of 
;	Clock signal), the I2CS VP make use of timeout timer. This timer is initiated 
;	whenever the I2CS comes into some wait state. When the timeout timer expires
;	data transfer will be terminated by Slave. The waiting time is always the 
;	same and is controlled by
;
;		I2CS_CLK_TIMEOUT. 50 (decimal) value corresponds to 6 usec.
;	 
;	------ Address ------
;
;	I2CS provides direct memory access for the Master. The RAM space, 
;	accessible from the Master is limited to one bank - 16 bytes. This 
;	IO_RAM Bank can be randomly addressed by the Master and is used as a 
;	mail box between Bus Master and user application program, running on
;	the Slave. 
;
;	The I2C Bus address of I2CS consists of 10 bits, four LSbits are
;	used to address corresponding bytes in the IO_RAM bank. Upper six bits 
;	are user defined and represent the I2CS Bus address - (we call it Bus ID). 
;	I2CS 10-bit Bus ID consists of two parts. One is the address of the
;	The IO_RAM bank itself is defined by Slave MAIN program.
;	The address of I2CS is defined by next bytes:
;
;	I2CS_IO_RAM	
;	Defines the base address of the BANK. Must be one of 10h, 30h....
;					
;	I2CS_ID_MASK_MSB
;
;	Must be 1111 0SS0. Five MSBs are pointing that it is 10-bit address mode
;	two bits SS are  first two bits of 10-bit bus address. Last bit is zero.
;
;	I2CS_ID_MASK_LSB
;
;	Four MSBs define the Slave I2C Bus address. Four LSBs, must be zero.
;	
;	Example:
;	Two address bytes send by Master:  1  1  1  1  0  s10  s9  1
;				 	  s8 s7 s6 s5 r4 r3   r2 r1
;	will address location r4 r3 r2 r1 of the Slave IO_RAM in the case when
;	Slave MASK_MSB and MASK_LSB will contain bits S10-S5 on corresponding 
;	positions:
;		I2CS_ID_MASK_MSB	  1  1  1  1  0  s10  s9  0
;		I2CS_ID_MASK_LSB	  s8 s7 s6 s5 0  0    0   0
;
;	
;	------- I/O pin configuration -------
;
;	I2CS makes use of three pins. 
;	SCL line pin in always configured as an input. 
;	SDA input pin is always configured as input.
;	SDA output pin is dynamically reconfigured from input to output state.
;	I2CS make use of PortB only, However, it is relatively easy to change the
;	the program so that it will work with any other port. The port configuration 
;	is controlled by next data:
;
;	I2CS_SCL_PIN		pointer to SCL pin
;	I2CS_SDA_IN_PIN		pointer to SDA input pin
;	I2CS_SDA_OUT_PIN	pointer to SDA output pin
;	I2CS_PORT_RX_MASK	image of PortB direction register
;				in receive mode
;	I2CS_PORT_TX_MASK	image of port direction register
;				in transmit mode
;
;	------- Entry points ------
;
;	I2CS VP has two entry points:
;
;	I2CS_INIT - an entry point of the subroutine, which will provide
;	correct configuration of the PortB.
;
;	I2CS_EXECUTE - an entry point of the I2CS VP.
;
;	------ Control and status data ------
;
;	The following is a list of all I2CS control parameters (described above)
;
;	I2CS_START_TIMEOUT. F0h value corresponds to 30 usec waiting time. 
;
;	I2CS_CLK_TIMEOUT. 50 (decimal) value corresponds to 6 usec.
;
;	I2CS_IO_RAM	
;	Defines the base address of the BANK. Must be one of 10h, 30h....
;					
;	I2CS_ID_MASK_MSB
;	I2CS_ID_MASK_LSB	Two byte mask of I2CS Bus ID.
;
;	I2CS_SCL_PIN		pointer to SCL pin
;	I2CS_SDA_IN_PIN		pointer to SDA input pin
;	I2CS_SDA_OUT_PIN	pointer to SDA output pin
;	I2CS_PORT_RX_MASK	image of PortB direction register
;				in receive mode
;	I2CS_PORT_TX_MASK	image of port direction register
;				in transmit mode
;
;	I2CS provides the feed back to the user program with a help of two bytes
;	- I2CS_STATUS and I2CS_FSR.
;
;	I2CS_FSR contains the image of FSR register for the last byte transferred
;  
;	I2CS_STATUS/Bit.0 -	I2CS_READY
;	Set by I2CS when data reception was accomplished. Should be cleared by MAIN 
;	program. Acts as a flag indicating that byte was written by Master.
;
;	I2CS_STATUS/Bit.1 -	I2CS_OVERFLOW
;	Warning, set by I2CS when the data were written by I2C Bus Master 
;	before the previous data have been processed by MAIN (before 
;	I2CS_READY flag was cleared).
;
;	I2CS_STATUS/Bit.3 -	I2CS_STOP_EVENT
;	Set when transfer was aborted because of Stop event.
;
;	I2CS_STATUS/Bit.4 -	I2CS_START_REPEAT_EVENT
;	Set when Sr event occurred during the data transfer.
;
;	I2CS_STATUS/Bit.5 -	I2CS_TIMEOUT
;	Set when transfer was aborted because of expiration of TIMEOUT TIMER.
;
;	I2CS_STATUS/Bit.6 -	I2CS_RECEIVE_TRANSMIT
;	Set when last transfer was transmission to Master.
;
;	I2CS_STATUS/Bit.7 -	I2CS_TRANSFER_ERROR
;	Set when transfer was aborted by either timeout or P events.
;
;	------ How to use I@CS from the user program ------
;
;	1. Initialize all control data
;	2. Call I2CS_INIT to initialize the Port (optional)
;	3. Disable interrupts and call I2CS_EXECUTE
;	4. Check the content of I2CS_STATUS, clear I2CS_READY bit, if necessary.
;	5. Make sure that steps 3 and 4 repeated often enough to support correct
;	   operation of I2CS Bus.	 
;
;=======================================================================

;================= Recommended system configuration ====================
;**************************** Code start *******************************

			device	pins28, pages4, banks8, oschs, turbo, stackx, optionx 
			id	'I2CS_D1'

reset			reset_entry

;****************** I/O PINS and RAM configuration **********************

i2cs_port		=	rb		;SX port assigned for I2CS communication

i2cs_scl_pin		=	rb.0		;I2CS clock line
i2cs_sda_in_pin		=	rb.1		;I2CS data input pin
i2cs_sda_out_pin	=	rb.2		;I2CS data output pin
sys_bank		=	10h		;MAIN program RAM
i2cs_ram_bank		=	30h		;I2CS RAM bank
i2cs_io_ram		=	50h		;I2CS I/O RAM bank


;=======================================================================

;========================== Authentic I2C SLAVE VP =====================

;******************************** I2CS RAM *****************************

			org	i2cs_ram_bank

;I2CS control data

i2cs_port_rx_mask	ds	1		;PortB direction register image for receive mode
i2cs_port_tx_mask	ds	1		;PortB direction register image for transmit mode

i2cs_id_mask_msb	ds	1		;I2CS ID MSbyte, correct MSB value should be 1111 0SS(r/w)
						;Bit sero is data transfer direction (r=1/W=0)
						;Bits 1,2 (SS) are the MSBits of the 10 bit 
						;I2CS Bus ID. 
						;Bits 3 to 7 must be 1111 0XXX
i2cs_id_mask_lsb	ds	1		;LSByte of the ID. Bits from 0 to 3 address 
						;the RAM (r) within the selected bank, bits 4 to 7
						;are the LSBits of I2CS Bus ID:	SSSS rrrr

						;So the two address mask bytes will look like
						; 1111 0SS0  SSSS 0000

i2cs_fsr		ds	1		;FSR image for the last byte transferred (read/written)
i2cs_clk_timeout	ds	1		;Clock detection timeout
i2cs_start_timeout	ds	1		;Start detection timeout

;I2CS status data

i2cs_status		ds	1		;I2CS Status word
i2cs_ready		equ	i2cs_status.0	;Set when data reception was accomplished.
						;Should be cleared by MAIN program. Acts as 
						;as a flag indicating that byte was written by Master
i2cs_overflow		equ	i2cs_status.1	;Warning, set when the data are written
						;by I2C Bus Master before the previous data
						;were processed by MAIN (before I2CS_READY flag was cleared)
i2cs_stop_event		equ	i2cs_status.3	;Set when the transfer was aborted
						;because of detection of Stop event on the BUS
i2cs_start_repeat_event	equ	i2cs_status.4	;Set when the Sr (Start Repetition) was detected
i2cs_timeout		equ	i2cs_status.5	;Set when watchdog timeout occurred
i2cs_receive_transmit	equ	i2cs_status.6	;Set when the last operation was transmission to Master
i2cs_transfer_error	equ	i2cs_status.7	;Error - transfer aborted by I2CS timeout or P

i2cs_io_buffer		ds	1		;Data shift register for I2CS

;I2CS private data

i2cs_state		ds	1		;Internal state of the I2CS
i2cs_start_ok		equ	i2cs_state.0	;Set when start condition was detected
i2cs_id_ok		equ	i2cs_state.1	;Set when I2CS address was detected
i2cs_byte_ok		equ	i2cs_state.2	;Set when data byte was transferred
i2cs_stop_ok		equ	i2cs_state.3	;Set when Stop condition was detected
i2cs_start_repeat	equ	i2cs_state.4	;Set when repetition start condition was detected
i2cs_timeout_exp	equ	i2cs_state.5	;Set when I2CS timeout expires

i2cs_shift_counter	ds	1		;number of bits to transfer
i2cs_timeout_counter	ds	1		;I2CL timeout counter

			org	main_end

;********************** I2CS subroutines *******************************

;******************** Send acknowledgement *****************************
;
;	This subroutine generates the ACK signal on I2CS_OUT_PIN. 
;	It first configures the PortB direction register with the
;	I@CS_PORT_TX_MASK. Then sets the SDA pin LOW until the Clock
;	signal occurs, or the timeout timer expires.

i2cs_send_ack		mov	i2cs_timeout_counter,i2cs_clk_timeout	
								;Initialize Clock timeout counter
			mov	m,#$0f
			mov	!rb,i2cs_port_tx_mask		;Configure the pin as an output 
			clrb	i2cs_sda_out_pin		;Set ACK - SDA LOW

:i2cs_send_ack_1	jb	i2cs_scl_pin,:i2cs_send_ack_2	;Wait for SCL LOW to HIGH transition
			djnz	i2cs_timeout_counter,:i2cs_send_ack_1
			setb	i2cs_timeout_exp		;Exit when timeout expires
			jmp	:i2cs_send_ack_exit

			mov	i2cs_timeout_counter,i2cs_clk_timeout	
								;Initialize clock timeout counter
:i2cs_send_ack_2	jnb	i2cs_scl_pin,:i2cs_send_ack_exit	
								;Wait for the end of ACK clock pulse
								;(HIGH to LOW transition of SCL line)
			djnz	i2cs_timeout_counter,:i2cs_send_ack_2
			setb	i2cs_timeout_exp		;Exit when timeout expires

:i2cs_send_ack_exit	mov	!rb,i2cs_port_rx_mask		;Disactivate output pin and exit
			setb	i2cs_sda_out_pin
			ret
;**************** End of Send Acknowledgement subroutine ***************

;************************* Get byte subroutine *************************
;
;	This subroutine receives the byte from I2C Master and stores it
;	in I2CS_IO_BUFFER. The Subrotine aborts data reception in cases
;	when:
;		- the clock frequency will be too low
;		- the Sr (Start repetition) will occur
;		- the P (Stop) will occur 

i2cs_get_byte		mov	i2cs_shift_counter,#$08		;Set the number of bits to receive

:i2cs_get_byte_loop	mov	i2cs_timeout_counter,i2cs_clk_timeout
								;Set the timeout counter
:i2cs_get_0		jnb	i2cs_scl_pin,:i2cs_get_1	;Wait for SCL LOW state	
			djnz	i2cs_timeout_counter,:i2cs_get_0
			setb	i2cs_timeout_exp		;Exit when timeout expires
			ret
			
:i2cs_get_1		movb	rc.1,i2cs_scl_pin		;XXXX TEST PIN TO MONITOR THE CLOCK	
			mov	i2cs_timeout_counter,i2cs_clk_timeout
								;Set the timeout counter
:i2cs_get_2		jb	i2cs_scl_pin,:i2cs_get_bit_in	;Wait for SCL LOW to HIGH transition
			djnz	i2cs_timeout_counter,:i2cs_get_2
			setb	i2cs_timeout_exp		;Exit when timeout expires
			ret

:i2cs_get_bit_in	rl	i2cs_io_buffer			;Shift the data in
			movb	i2cs_io_buffer.0,i2cs_sda_in_pin
			movb	rc.0,i2cs_sda_in_pin		;XXXX TEST PIN TO MONITOR THE DATA
			movb	rc.1,i2cs_scl_pin		;XXXX TEST PIN TO MONITOR THE CLOCK	
			mov	i2cs_timeout_counter,i2cs_clk_timeout
								;Set the timeout counter
:i2cs_get_wait		jnb	i2cs_scl_pin,:i2cs_get_3	;Wait for SCL HIGH to LOW step
			djnz	i2cs_timeout_counter,:i2cs_get_wait
			setb	i2cs_timeout_exp		;Exit when timeout expires
			ret

:i2cs_get_3		movb	rc.1,i2cs_scl_pin		;XXXX TEST PIN TO MONITOR THE CLOCK

			jb	i2cs_io_buffer.0,:i2cs_get_4	;Compare SDA line state right after 
			sb	i2cs_sda_in_pin			;the HIGH to LOW clock transission
			jmp	:i2cs_get_continue		;to the SDA line state right after
								;LOW to HIGH clock transmission
			setb	i2cs_stop_ok			;they should be identical, otherwise
			ret					;it is either Sr or P event

:i2cs_get_4		snb	i2cs_sda_in_pin			;In both cases - exit
			jmp	:i2cs_get_continue
			setb	i2cs_start_repeat
			ret
			
:i2cs_get_continue	djnz	i2cs_shift_counter,:i2cs_get_byte_loop
			ret

;******************* End of Get byte subroutine ************************

;*********************** Send byte subroutine **************************
;
;	This subroutine sends the byte of data from I2CS_IO_BUFFER to the Master. 
;	The Subroutine aborts data reception in cases when:
;		the clock frequency will be too low
;		the Sr (Start repetition) will occur

i2cs_send_byte		mov	!rb,i2cs_port_tx_mask		;Set the direction of SDA pin as an output
			mov	i2cs_shift_counter,#$8		;Set the shift counter
:i2cs_send_byte_loop
			mov	i2cs_timeout_counter,i2cs_clk_timeout
								;Set the timeout counter
								;to wait for SCL LOW state
:i2cs_send_0		jnb	i2cs_scl_pin,:i2cs_shift_bit_out	;Wait for SCL LOW
			djnz	i2cs_timeout_counter,:i2cs_send_0
			setb	i2cs_timeout_exp		;Exit when timeout expires
			jmp	:i2cs_send_byte_exit

			mov	i2cs_timeout_counter,i2cs_clk_timeout
								;Initialize clock timeout counter
								;to wait for SCL LOW to HIGH step
:I2cs_shift_bit_out	movb	i2cs_sda_out_pin,i2cs_io_buffer.7	
								;Shift bit out
:i2cs_send_1		jb	i2cs_scl_pin,:i2cs_send_2	;Wait for SCL LOW to HIGH transition
			djnz	i2cs_timeout_counter,:i2cs_send_1
			setb	i2cs_timeout_exp		;Exit when timeout expires
			jmp	:i2cs_send_byte_exit

			mov	i2cs_timeout_counter,i2cs_clk_timeout
								;Initialize clock timeout counter
								;to wait for SCL HIGH to LOW step
:i2cs_send_2		jnb	i2cs_scl_pin,:i2cs_send_3	;Wait for SCL HIGH to LOW transition
			djnz	i2cs_timeout_counter,:i2cs_send_2
			setb	i2cs_timeout_exp		;Exit when timeout expires
			jmp	:i2cs_send_byte_exit

:i2cs_send_3		mov	i2cs_timeout_counter,#3		;Hold the data for about 0.4 usec
:i2cs_send_4		djnz	i2cs_timeout_counter,:i2cs_send_4
	
			jnb	i2cs_io_buffer.7,:i2cs_send_continue	
								;if the current bit was HIGH, then
								;there is a chance of Sr condition
								;generated by Master								
			jb	i2cs_sda_in_pin,:i2cs_send_continue
								;Current SDA line state is HIGH - continue
			setb	i2cs_start_repeat		;SDA line is LOW - Sr occurred, exit
			jmp	:i2cs_send_byte_exit

:i2cs_send_continue	rl	i2cs_io_buffer
			djnz	i2cs_shift_counter,:i2cs_send_byte_loop
								;decrement bit counter and exit
:i2cs_send_byte_exit	mov	!rb,i2cs_port_rx_mask		;restore the direction register for DSA pin
			ret
;******************* End of Send byte subroutine ***********************

;****************** I2CS initialization subroutine *********************

i2cs_init		bank	i2cs_ram_bank
			mov	m,#$0f			;set data direction registers
			mov	!rb,i2cs_port_rx_mask	;configure ports
			setb	i2cs_sda_out_pin
			ret

;******************* End of initialization subroutine ******************

;************************* I2CS DATA TRANSFER **************************

i2cs_execute		bank	i2cs_ram_bank		;set I2CS RAM bank

;************** Detection of Start condition on the BUS ****************

			snb	i2cs_sda_in_pin		;Test if SDA line is LOW
			ret				;SDA pin is HIGH - no Start Byte
							;Exit
;SDA line LOW detected, wait for Sr (Start repetition)

i2cs_sr_detect		mov 	i2cs_timeout_counter,i2cs_start_timeout

;Wait for SDA LOW to HIGH transition
			clr	i2cs_state		;Begin detection of the Sr,
							;wait for SDA HIGH
:i2cs_sda_test		jb	i2cs_sda_in_pin,:i2cs_sda_high
							;when SDA is HIGH - go to next step
			djnz	i2cs_timeout_counter,:i2cs_sda_test
							;One wait cycle is 120 nsec		
			jmp	:i2cs_false_start	;Timeout - exit

;Wait for first SDA HIGH to LOW transition

:i2cs_sda_high		jnb	i2cs_sda_in_pin,:i2cs_sda_low
							;When SDA goes LOW - test the SCL
			djnz	i2cs_timeout_counter,:i2cs_sda_high
			jmp	:i2cs_false_start	;Timeout - exit

;Test the SCL line - it must be HIGH, if it is LOW - false start

:i2cs_sda_low		snb	i2cs_scl_pin		;It was LOW to HIGH step on SDA							
							;line, when the SCL was LOW - false start
			jmp	i2cs_start

:i2cs_false_start	ret				;Exit I2CS, no Start detected

;************** Decode the first byte in transfer **********************
;	Start condition detected; next step - decode the address
;	First byte contains R/W bit, and two bits of 10-bit address

i2cs_start		clr	i2cs_state		;Reset the state machine
			setb	i2cs_start_ok		;Start  detected
			and	i2cs_status,#$01	;Clear all bits of Status byte but READY bit
							;Ready bit may be cleared only by MAIN program
:get_transfer		call	i2cs_get_byte		;Get 1st address byte

;Test if the transfer was interrupted either by Sr, P signals or by timeout timer 
			mov	w,i2cs_state			
			and	w,#$38			;Select three state bits
			sz				;Continue if ZERO
			jmp	i2cs_exit

;Test if the byte was the Start Byte
			mov	w,i2cs_io_buffer
			xor	w,#$01			;Is it the "START BYTE" (01h) ?	
			snz
			jmp	i2cs_sr_detect		;Yes, it was the Start Byte
							;Go back and wait for Sr condition
;Check if this is I2CS  ID
			mov	w,i2cs_io_buffer	;Is it 10-bit address ?
			and	w,#$fe			;Mask the r/w bit
			xor	w,i2cs_id_mask_msb	;Test ten bit address (must be1111 0SSX)
			sz
			jmp	i2cs_exit		;This is not I2CS ID - exit			
;Decode R/W bit	
			clrb	i2cs_receive_transmit
			snb	i2cs_io_buffer.0	;Test the r/w bit
			setb	i2cs_receive_transmit	;Zero indicates transmission from master
;Send ack 
			call 	I2cs_send_ack		;Generate ACK signal
			snb	i2cs_timeout_exp	;Was the timeout OK ?
			jmp	i2cs_exit		;No

;************************ Decode the second byte ***********************
;	Second byte contains last eight bit of 10-bit address

			call	i2cs_get_byte

;Test if the transfer was interrupted by either Sr or P signal or timeout timer
			mov	w,i2cs_state			
			and	w,#$38			;Select three state bits
			sz				;Continue if ZERO
			jmp	i2cs_exit

;Decode the LSB of Bus ID
			mov	w,i2cs_io_buffer
			and	w,#$f0			;Test the ID
			xor	w,i2cs_id_mask_lsb	;Is it the I2CS bus ID ?
			sz
			jmp	i2cs_exit		;This is not I2CS Bus ID
;Decode ram address	
			mov	w,i2cs_io_buffer
			and	w,#$0f
			or	w,i2cs_io_ram		;Combine the last 4 bits of BUS ID
							;with the defined I/O_RAM bank address
			mov	i2cs_fsr,w		;Save the FSR image

			setb	i2cs_id_ok
			call 	i2cs_send_ack		;Generate the ACK
			snb	i2cs_timeout_exp	;Was the timeout OK ?
			jmp	i2cs_exit		;No

;*********************** Transfer the byte *****************************
			
			jb	i2cs_receive_transmit,:i2cs_transmit_byte
;Receive the byte	
			call	i2cs_get_byte

;Test if the transfer was interrupted by either Sr or P signal 
			mov	w,i2cs_state			
			and	w,#$38			;Select three state bits
			sz				;Continue if ZERO
			jmp	i2cs_exit

			mov	08h,i2cs_io_buffer	;Move the data to I2CS I/O RAM location
			mov	fsr,i2cs_fsr		;using FSR as I/O data pointer
			mov	indf,08h

			bank	i2cs_ram_bank
			call	i2cs_send_ack		;Generate the ACK signal
			snb	i2cs_timeout_exp	;Was the timeout OK ?
			jmp	i2cs_exit		;No

			setb	i2cs_byte_ok
			jmp	i2cs_exit		;Data transfer finished - exit
;Transmit the byte
:i2cs_transmit_byte	mov	fsr,i2cs_fsr		;Move the data from I2CS RAM Location
			mov	08h,indf		;to I2CS_IO_BUFFER using FSR as pointer
			bank	i2cs_ram_bank
			mov	i2cs_io_buffer,08h
			call	i2cs_send_byte		;Send the data
			jmp	i2cs_exit		;Whatever happened - exit
		
;*********************** Data Transfer Exit ****************************
;
;	This part of I2CS VP may be customized to meet specific needs of
;	the interface to the MAIN program
;
i2cs_exit		jnb	i2cs_start_repeat,:i2cs_exit_1	
							;Was Sr detected ?
			setb	I2cs_start_repeat
			jmp	i2cs_start		;Yes, start all over again

:I2cs_exit_1		jnb	i2cs_stop_ok,:i2cs_exit_2
							;Was stop condition detected ?
			setb	i2cs_stop_event		;Yes, set the flags and exit
			setb	i2cs_transfer_error
			jmp	:i2cs_finish
			
:i2cs_exit_2		jnb	i2cs_timeout_exp,:i2cs_exit_3
							;Was timeout detected ?
			setb	i2cs_timeout		;Yes, set the flags and exit
			setb	i2cs_transfer_error
			jmp	:i2cs_finish

:i2cs_exit_3		jb	i2cs_receive_transmit,:i2cs_finish
							;Was it data transmission from the Master
			snb	i2cs_ready		;Yes, check if the Warning should be set
			setb	i2cs_overflow
			setb	i2cs_ready

:i2cs_finish		ret

;========================== END OF I2CS VP =============================
