;IIC ROUTINES FOR COMUNICATING TO AN EEPROM
;IIC EQUATES
ACK EQU .1
#DEFINE    SDA PORTB,1         ;DATA LINE
#DEFINE    SCL PORTB,0         ;CLOCK LINE
#DEFINE    SDA_TRIS TRISB,1    ;DATA LINE TRIS
#DEFINE    SCL_TRIS TRISB,0    ;CLOCK LINE TRIS
GENERAL	   EQU 0x21	       ;general equate
COUNTER    EQU 0X5A
TX_BUFFER  EQU 0X5B
RX_BUFFER  EQU 0X5C
EEPROMWR   EQU B'10100000'     ;WRITE INFO TO THE EEPROM
EEPROMRE   EQU B'10100001'     ;READ FROM THE EEPROM
HADD       EQU 0X5D            ;HIGH BYTE ADDRESS
LADDRESS   EQU 0X58            ;LOW BYTE ADDRESS
DATA_IN    EQU 0X5F            ;DATA IN
DATA_OUT   EQU 0X59            ;DATA OUT
SDAUP:
BSF STATUS,RP0                 ;BANK ONE
BSF SDA_TRIS                   ;UP
BCF STATUS,RP0                 ;BANK ZERO
NOP
RETURN
SDADOWN:
BSF STATUS,RP0                 ;BANK ONE
BCF SDA_TRIS                   ;DOWN
BCF STATUS,RP0                 ;BANK ZERO
NOP
RETURN
SCLUP:
BSF STATUS,RP0                 ;BANK ONE
BSF SCL_TRIS                   ;UP
BCF STATUS,RP0                 ;BANK ZERO
NOP
RETURN
SCLDOWN:
BSF STATUS,RP0                 ;BANK ONE
BCF SCL_TRIS                   ;DOWN
BCF STATUS,RP0                 ;BANK ZERO
NOP
RETURN

INIT_IIC:
	BSF	STATUS,RP0	;BANK 1
	BCF	SCL_TRIS	;ALL AS OUTPUT
	BCF	SDA_TRIS	;ALL AS OUTPUT
	BCF	STATUS,RP0	;BANK 0
	BCF	SDA		;STEADY STATE FOR DATA LINE
	BCF	SCL		;STEADY STATE FOR CLOCK
	CALL    SDAUP		;DATA LINE UP
	CALL    SCLUP		;CLOCK LINE UP
	MOVLW	.2
	CALL	MDELAY	;
RETURN
OUTPUT:
	MOVLW	01H
	MOVWF	COUNTER		;SET THE POINTER/COUNTER
LOOP:
	BTFSC	TX_BUFFER,7	;CHECK THE DATA
	GOTO	SET_IT		;GOTO SET THE DATA HIGH
	CALL    SDADOWN		;DATA LOW
CONT:	CALL    SCLUP		;CLOCK GOES HIGH
	CALL    SCLDOWN		;CLOCK GOES LOW AGAIN
	BCF	STATUS,C	;CLEAR THE CARRY
	RLF	TX_BUFFER,F	;ROTATE THE DATA
	BCF	STATUS,C	;CLEAR THE CARRY
	RLF	COUNTER,F	;ROTATE THE COUNTER
	BTFSC	STATUS,C	;TEST FOR END
	RETURN			;GOTO	FINNISH			;
	GOTO	LOOP		;CARRY ON IF NOT FINNISHED
	
SET_IT:	CALL    SDAUP		;DATA HIGH
	GOTO	CONT		;continue
	


INPUT:				;GET THE BYTE!
	MOVLW	01H
	MOVWF	COUNTER		;SET THE POINTER/COUNTER
IPLOOP:
	CALL    SDAUP		;MAKE THE SDA LINE AN INPUT
	CALL    SCLUP		;CLOCK BACK UP
	BTFSC	SDA		;TEST SDA
	GOTO	SET_RXBUF	;SET THE DATA BIT
	BCF	RX_BUFFER,0	;CLEAR THE DATA BIT
IPCONT:
	CALL    SCLDOWN		;RETURN CLOCK DOWN
	RLF	COUNTER,F	;ROTATE THE COUNTER
	BTFSC	STATUS,C	;TEST FOR END
	RETURN			;END OF ROUTINE		;
	BCF	STATUS,C	;CLEAR THE CARRY
	RLF	RX_BUFFER,F	;ROTATE THE DATA
	BCF	STATUS,C	;CLEAR THE CARRY
	GOTO	IPLOOP		;CARRY ON IF NOT FINNISHED
	
SET_RXBUF:	
	BSF	RX_BUFFER,0	;SET THE INFO
GOTO	IPCONT			;CARRY ON

START_BIT:
	CALL    SDAUP		;MAKE SURE THE SDA LINE IS UP
	CALL    SCLUP		;SET THE CLOCK UP
	CALL    SDADOWN		;DATA LINE ADD LOW WHILE CLOCK HIGH
	CALL    SCLDOWN		;START THE CLOCK TRAIN
RETURN
STOP_BIT:
	CALL    SDADOWN		;MAKE SURE THE SDA LINE IS DOWN
	CALL    SCLUP		;MAKE SURE THE SCL LINE IS UP
	CALL    SDAUP		;SDA LINE GOES HIGH WHEN SCL IS HIGH
RETURN


GET_ACK:			;ACKNOWLEDGE
	CALL  SDAUP		;MAKE THE SDA LINE AN INPUT
	CALL  SCLUP		;CLOCK BACK UP
	BTFSC	SDA		;TEST FOR LOW ACK
	GOTO	SET_FLAG	;SET THE ACK FLAG
	BCF	GENERAL,ACK	;CLEAR THE FLAG
FLAG_SET:
	CALL  SCLDOWN			;RETURN CLOCK ADDLOW
RETURN
SET_FLAG:
	BSF	GENERAL,ACK	;SET THE FLAG
	GOTO	FLAG_SET	;CARRY ON
SEND_ACK:			;WHEN READING, THE MASTER HAS TO
				;GIVE THE ACKS/NO ACKS.
	CALL  SDADOWN		;DATA LINE DOWN
	CALL  SCLUP		;CLOCK GOES HIGH
	CALL  SCLDOWN		;CLOCK GOES DOWN
RETURN
NO_ACK:				;WHEN READING, THE MASTER HAS TO
				;GIVE THE ACKS/NO ACKS.
	CALL  SDAUP		;DATA HIGH
	CALL  SCLUP		;CLOCK GOES HIGH
	CALL  SCLDOWN		;CLOCK GOES DOWN
RETURN
;****************************************************************
;	INPUTS TO THIS ROUTINE ARE... HIGH (HIGH BYTE ADDRESS)
;	ADDLOW (ADDLOW BYTE ADDRESS) AND DATA_OUT (THE DATA OUT!)
;****************************************************************
EEWRITE_BYTE:			;WRITE A BYTE TO THE EEPROM
	CALL	START_BIT	;OUTPUT THE START BIT
	MOVLW	EEPROMWR	;CALL THE EEPROM TO WRITE
	MOVWF	TX_BUFFER	;TO OUTPUT BUFFER
	CALL	OUTPUT		;OUTPUT THE DATA ON PORTE
	CALL	GET_ACK		;GET ACK BIT
	MOVFW	HADD		;GET THE HIGH BYTE ADDRESS
	MOVWF	TX_BUFFER	;SEND TO THE BUFFER
	CALL	OUTPUT		;OUTPUT THE DATA ON PORT
	CALL	GET_ACK		;GET ACK BIT
	MOVFW	LADDRESS	;GET THE ADDLOW BYTE ADDRESS
	MOVWF	TX_BUFFER	;SEND TO THE BUFFER
	CALL	OUTPUT		;OUTPUT THE DATA ON PORT
	CALL	GET_ACK		;GET ACK BIT
	MOVFW	DATA_OUT	;GET THE DATA TO BE SENT
	MOVWF	TX_BUFFER	;SEND TO THE BUFFER
	CALL	OUTPUT		;OUTPUT THE DATA ON PORT
	CALL	GET_ACK		;GET ACK BIT
	CALL	STOP_BIT	;OUTPUT THE STOP BIT
RETURN				;RETURN TO MAIN PROGRAM
;*********************************************************************
;	INPUTS TO THIS ROUTINE ARE... HIGH (HIGH BYTE ADDRESS)
;	ADDLOW (ADDLOW BYTE ADDRESS).  OUTPUT FROM THIS ROUTINE IS DATA_IN
;*********************************************************************
EEREAD_BYTE:			;WRITE A BYTE TO THE EEPROM
	CALL	START_BIT	;OUTPUT THE START BIT
	MOVLW	EEPROMWR	;CALL THE EEPROM TO WRITE
	MOVWF	TX_BUFFER	;TO OUTPUT BUFFER
	CALL	OUTPUT		;OUTPUT THE DATA ON PORTE
	CALL	GET_ACK		;GET ACK BIT
	MOVFW	HADD		;GET THE HIGH BYTE ADDRESS
	MOVWF	TX_BUFFER	;SEND TO THE BUFFER
	CALL	OUTPUT		;OUTPUT THE DATA ON PORT
	CALL	GET_ACK		;GET ACK BIT
	MOVFW	LADDRESS	;GET THE ADDLOW BYTE ADDRESS
	MOVWF	TX_BUFFER	;SEND TO THE BUFFER
	CALL	OUTPUT		;OUTPUT THE DATA ON PORT
	CALL	GET_ACK		;GET ACK BIT
	CALL	START_BIT	;START BIT
	MOVLW	EEPROMRE	;READ OPERATION
	MOVWF	TX_BUFFER	;TRANSMIT IT
	CALL	OUTPUT		;OUTPUT THE CODE
	CALL	GET_ACK		;GET THE ACK
	CALL	INPUT		;GET THE DATA BYTE. STORE IN DATA_IN
	CALL	NO_ACK		;SEND A NOT ACK
	CALL	STOP_BIT	;OUTPUT THE STOP BIT
	MOVFW	RX_BUFFER	;GET THE DATA OUT
	MOVWF	DATA_IN		;AN MOVE IT TO DATA IN
RETURN				;RETURN TO MAIN PROGRAM