; Low level I2C Routines.
;
; Revised on April 24, '98 to slow clocking.
;
; Requires declaration of O_BYTE, I_BYTE and INDEX
;;;;;;
IN_BYTE:			; read byte on i2c bus
				; result returned in I_BYTE
	CLRF I_BYTE
	MOVLW .8
	MOVWF INDEX		; set index to 8	
	CALL HIGH_SDA		; be sure SDA is configured as input
IN_BIT:
	CALL HIGH_SCL		; clock high
	MOVLW .1
	CALL LCD_DELAY
	BTFSS PORTA, SDA	; test SDA bit
	BCF STATUS, C
	BTFSC PORTA, SDA
	BSF STATUS, C
	RLF I_BYTE, F		
	CALL LOW_SCL		; bring clock low
	DECFSZ INDEX, F		; decrement index
	GOTO IN_BIT
	RETURN

;;;;;;

OUT_BYTE:			; send O_BYTE on I2C bus
	MOVLW .8
	MOVWF INDEX
OUT_BIT:
	BCF STATUS,C		; clear carry
	RLF O_BYTE, F		; left shift, most sig bit is now in carry
	BTFSS STATUS, C		; if one, send a one
	GOTO OUT_ZERO
	GOTO OUT_ONE

OUT_ZERO:
	CALL LOW_SDA		; SDA at zero
	CALL CLOCK_PULSE	
	CALL HIGH_SDA
	GOTO OUT_CONT

OUT_ONE:
	CALL HIGH_SDA		; SDA at logic one
	CALL CLOCK_PULSE
	GOTO OUT_CONT

OUT_CONT:
	DECFSZ INDEX, F		; decrement index
	GOTO OUT_BIT
	RETURN	

;;;;;;
		
NACK:				; bring SDA high and clock
	CALL HIGH_SDA
	CALL CLOCK_PULSE
	RETURN

ACK:
	CALL LOW_SDA
	CALL CLOCK_PULSE
	CALL HIGH_SDA
	RETURN

START:				
	CALL LOW_SCL
	CALL HIGH_SDA
	CALL HIGH_SCL
	CALL LOW_SDA		; bring SDA low while SCL is high
	CALL LOW_SCL
	RETURN

STOP:
	CALL LOW_SCL
	CALL LOW_SDA
	CALL HIGH_SCL
	CALL HIGH_SDA		; bring SDA high while SCL is high
	CALL LOW_SCL
	RETURN

CLOCK_PULSE:			; SCL momentarily to logic one
	CALL HIGH_SCL
	CALL LOW_SCL
	RETURN		

HIGH_SDA:			; high impedance by making SDA an input
	BSF STATUS, RP0		; bank 1
	BSF TRISA, SDA		; make SDA pin an input
	BCF STATUS, RP0		; back to bank 0
	CALL SHORT_DELAY
	RETURN

LOW_SDA:
	BCF PORTA, SDA	
	BSF STATUS, RP0		; bank 1
	BCF TRISA, SDA		; make SDA pin an output
	BCF STATUS, RP0		; back to bank 0
	CALL SHORT_DELAY	
	RETURN

HIGH_SCL:
	BSF STATUS, RP0		; bank 1
	BSF TRISA, SCL		; make SCL pin an input
	BCF STATUS, RP0		; back to bank 0
	CALL SHORT_DELAY	
	RETURN

LOW_SCL:
	BCF PORTA, SCL
	BSF STATUS, RP0		; bank 1
	BCF TRISA, SCL		; make SCL pin an output
	BCF STATUS, RP0		; back to bank 0
	CALL SHORT_DELAY	
	RETURN
	
SHORT_DELAY:
	MOVLW .1
	CALL LCD_DELAY
	RETURN