;Slave address of I2C device to whom we are talking
#DEFINE SLAVEID 0x90		; Set this for your device

;	*********************************************************************
;	MACRO DEFINITIONS
; Generic PIC Assembly macro definitions
; Copywrite (c) 2004 Randy Gamage
;
ifpos	macro arg1
	btfss arg1,7			;Test if argument is positive (high bit clear)
	endm
ifneg	macro arg1
	btfsc arg1,7			;Test if argument is negative (high bit set)
	endm
	
bank0 	macro
	bcf STATUS,RP1
	bcf STATUS,RP0
	endm
	
bank1	macro
	bcf STATUS,RP1
	bsf STATUS,RP0
	endm
	
bank2 	macro
	bsf STATUS,RP1
	bcf STATUS,RP0
	endm
	
bank3 	macro
	bsf STATUS,RP1
	bsf STATUS,RP0
	endm
;
;==============================================
; I2C Routines (using H/W I2C Peripheral
;==============================================	
I2CInit:
			;NOTE: I2C Pins must already be set to be INPUTS
	movlw 0x28			; Set mode to I2C Master, enable I2C
	movwf SSPCON
	bank1
	clrf SSPCON2^0x80		; Clear status flags
	movlw 49			; Set speed to 100kHz w/20MHz clock
	movwf SSPADD^0x80
	bsf SSPSTAT^0x80,SMP	; Disable slew rate control, set for 100kHz
	bcf SSPSTAT^0x80,CKE	; Set levels to I2C (set if you want SMBus levels)
	bank0
	bcf PIR1,SSPIF		; Clear SSPIF interrupt flag 
	bcf PIR2,BCLIF		; Clear bus collision flag
	return

I2CWaitForIdle:
	bank1
I2C_WFI:
	movf SSPCON2^0x80,W		; Check all busy bits
	andlw 0x1F
	skipz
	goto I2C_WFI
	ifset SSPSTAT^0x80,R_W
	goto $ - 1
	bank0
	return
	
I2CStart:
	call I2CWaitForIdle
	bank1
	bsf SSPCON2^0x80,SEN		; Initiate Start
	bank0
	return

I2CRepStart:
	call I2CWaitForIdle
	bank1
	bsf SSPCON2^0x80,RSEN		; Initiate Repeated Start
	bank0
	return

I2CStop:
	call I2CWaitForIdle
	bank1
	bsf SSPCON2^0x80,PEN		; Initiate stop
	bank0
	return
	
I2CRead:
	call I2CWaitForIdle
	bank1
	bsf SSPCON2^0x80,RCEN		; Initiate receive
	bank0
	call I2CWaitForIdle
	movf SSPBUF,W
	movwf I2CData
	call I2CWaitForIdle
	bank1
	bsf SSPCON2^0x80,ACKDT		; Don't send an ACK (EEPROM doesn't require it)
	bsf SSPCON2^0x80,ACKEN		; Initiate ACK sequence
	bank0	
	return

I2CReadwAck:
	; Same as I2CRead, but we send an ACK this time
	call I2CWaitForIdle
	bank1
	bsf SSPCON2^0x80,RCEN		; Initiate receive
	bank0
	call I2CWaitForIdle
	movf SSPBUF,W
	movwf I2CData
	call I2CWaitForIdle
	bank1
	bcf SSPCON2^0x80,ACKDT		; Send an ACK this time
	bsf SSPCON2^0x80,ACKEN		; Initiate ACK sequence
	bank0	
	return

I2CWrite:
	movwf I2CData		; Save input value
	call I2CWaitForIdle
	movf I2CData,W
	movwf SSPBUF
	call I2CWaitForIdle
	; Can capture ACK return value here (in SSPCON2, ACKSTAT) if desired
	return