Κώδικας:
;---------- I2C PCA9665 ROUTINES -----------------
I2C_RDSTAT_WT: IN A,(DI2C_CON) ;READ CONTROL REGISTER BIT 3 IS SI
BIT 3,A ;CHECK BIT 3 SI
JR Z,I2C_RDSTAT_WT ;BIT 3 SHOULD BE SET IF VALID STATUS
IN A,(DI2C_STA) ;VALID HERE
RET
I2C_RDSTAT_NW: IN A,(DI2C_CON) ;READ CONTROL REGISTER BIT 3 IS SI
BIT 3,A ;CHECK BIT 3 SI
LD A,$FF ;$FF=INVALID STATUS
RET Z ;BIT 3 SHOULD BE SET IF VALID STATUS
IN A,(DI2C_STA) ;VALID HERE
RET
I2C_INIT: LD A,I2CADR
OUT (DI2C_INDPTR),A
LD A,$E0
OUT (DI2C_INDIR),A ;SET MY SLAVE ADDR
LD A,$40 ;INIT
OUT (DI2C_CON),A ;
LD B,250
CALL DELAYMICRO
LD B,250
CALL DELAYMICRO ;DELAY 500 MICROSECS
;SET SPEED MODE
;MODE 0x00, 0x9D, 0x86 STANDARD
; 0x01, 0x2C, 0x14 FAST
; 0x02, 0x011, 0x09 FAST+
LD A,I2CMODE
OUT (DI2C_INDPTR),A ;SELECT I2CMODE REGISTER
LD A,0 ;SELECT MODE 0
OUT (DI2C_INDIR),A
LD A,I2CSCLL
OUT (DI2C_INDPTR),A ;SELECT I2CMODE REGISTER
LD A,$9D ;SELECT CLK L
OUT (DI2C_INDIR),A
LD A,I2CSCLH
OUT (DI2C_INDPTR),A ;SELECT I2CMODE REGISTER
LD A,$86 ;SELECT CLK H
OUT (DI2C_INDIR),A
RET
;D = ADDR OF DEVICE
;HL BUFFER ADDRESS
;BC BYTE COUNT
I2C_WRITE:
I2C_WR_BYTE: LD A,$60 ;START
OUT (DI2C_CON),A
WRB_LP1: CALL I2C_RDSTAT_WT ;WAIT FOR INTERRUPT SI=1
LD E,A ;SAVE STATUS
CP MASTER_START_TXed ;A HAS THE STATUS
JR Z,WRB_S1
CP MASTER_RESTART_TXed
JR Z,WRB_S1
CP MASTER_DATA_W_ACK
JR Z,WRB_S2
CP MASTER_SLA_W_ACK
JR Z,WRB_S3
CP MASTER_SLA_W_NAK
JR Z,WRB_EXIT
CP MASTER_DATA_W_NAK
JR Z,WRB_EXIT
CP MASTER_ARB_LOST
RET Z
CP SLAVE_AL_ADDRESSED_R
RET Z
CP SLAVE_AL_ADDRESSED_W
RET Z
CP SLAVE_GENERALCALL_AL
RET Z
RET
WRB_S1: LD A,D ;DEVICE ADDR
SLA A
AND $FE ;ADDR+WRITE ON D0=0
OUT (DI2C_DAT),A
LD A,$40
OUT (DI2C_CON),A
JR WRB_LP1
WRB_S2: DEC BC
WRB_S3: LD A,B
OR C
JR Z,WRB_EXIT
LD A,(HL)
INC HL
OUT (DI2C_DAT),A
LD A,$40
OUT (DI2C_CON),A
JR WRB_LP1
WRB_EXIT: LD A,$50 ;STOP
OUT (DI2C_CON),A
LD A,B
OR C
RET ;IF A NOT ZERO THEN ERROR
;D DEVICE ADDR
;HL BYTE BUFFER
;BC BYTE COUNT
I2C_READ:
I2C_RD_BYTE: LD A,B
OR C
RET Z ;RETURN IF ZERO BYTE COUNT
LD A,$60
OUT (DI2C_CON),A
RDB_LP1: CALL I2C_RDSTAT_WT ;WAIT FOR INTERRUPT SI=1
LD E,0
CP MASTER_START_TXed
JR Z,RDB_S1
MASTER_RESTART_TXed
JR Z,RDB_S1
CP MASTER_DATA_R_NAK
JR Z,RDB_S2
CP MASTER_DATA_R_ACK
JR Z,RDB_S3
CP MASTER_SLA_R_ACK
JR Z,RDB_S4
CP MASTER_SLA_R_NAK
JR Z,RDB_EXIT
CP MASTER_ARB_LOST
RET Z
CP SLAVE_AL_ADDRESSED_R
RET Z
CP SLAVE_AL_ADDRESSED_W
RET Z
CP SLAVE_GENERALCALL_AL
RET Z
RET
RDB_S1: LD A,D ;DEVICE ADDR
SLA A
OR $01 ;ADDR + READ COMMAND
OUT (DI2C_DAT),A
LD A,$40
OUT (DI2C_CON),A
JR RDB_LP1
RDB_S2: LD E,1 ;MEANS WE EXIT
RDB_S3: IN A,(DI2C_DAT) ;READ DATA
LD (HL),A
INC HL
DEC BC
RDB_S4: LD A,B ; IS LENGTH 0
OR C
JR Z,RDB_EXIT
LD A,E
CP 1
JR Z,RDB_EXIT
LD A,B
ADD C
CP 1
LD A,$40
JR Z,RDB_NXT1
LD A,$C0
RDB_NXT1: OUT (DI2C_CON),A ;WRITE $40 IF BYTE COUNT BC=1 ELSE WRITE $C0
JR RDB_LP1
RDB_EXIT: LD A,$50
OUT (DI2C_CON),A
LD A,B
OR C
RET ;IF A NOT ZERO THEN ERROR
;---------- I2C PCA9665 ROUTINES END-----------------