File: I2CLib.asm - Tab length: 1 2 4 8 - Lines: on off - No wrap: on offsection ".data"
include "OS.H"
xdef i2clib@0000
xdef i2clib@0001
xdef i2clib@0002
xdef i2clib@0003
xdef i2clib@0004
xdef i2clib@0005
;****************************************************
;* SDA is mapped to bit 1 and SCL to bit 0 *
;* D1 and D2 are volatile, D0 is parameter *
;****************************************************
;****************************************************
; Macro definitions
Rel_SDA MACRO
bclr.b #1,$60000E
ENDM
Rel_SCL MACRO
bclr.b #0,$60000E
ENDM
Pull_SDA MACRO
bset.b #1,$60000E
ENDM
Pull_SCL MACRO
bset.b #0,$60000E
ENDM
Get_SDA MACRO
move.b $60000E,D2
not D2
btst.b #3,D2
ENDM
Get_SCL MACRO ; Not used
move.b $60000E,D2
not D2
btst.b #2,D2
ENDM
Wait_2us: ; Small delay
; move.w #1,D2 ; I think these loops aren't needed : the
; bra loopw5us ; tests i made with rts only showed a speed of
Wait_5us: ; ~45kbps, while the specifications are 100kbps max.
; move.w #2,D2 ; the delay should be around 5�s between the
; edges of the SCL signal.
loopw5us: ; for more info about timing, see i2clib.txt
; dbra D2,loopw5us
rts
;*****************************************************
; Generate a START condition
i2clib@0000:
Start:
; move.w #$700,D0 ; Disable (maskable) interrupts
; trap #1 ; Beware if you use keyboard or auto-ints (used for greyscale)!
bclr.b #6,$60000E ; Enable direct link port access
move.w $60000C,D0 ; (dunno exactly what these bits are for, but
move.b #$E0,$60000C ; strange things happen if they're not set ...)
Rel_SDA ; Start condition definition :
Rel_SCL
bsr Wait_5us ; __
; SDA : \__
Pull_SDA ; _____
bsr Wait_5us ; SCL :
Pull_SCL
bsr Wait_5us
rts
;*****************************************************
; Generate a STOP condition
i2clib@0001:
Stop:
Pull_SDA ; Stop condition definition :
Rel_SCL
bsr Wait_5us ; __
; SDA : __/
Rel_SDA ; _____
bsr Wait_5us ; SCL :
bset.b #6,$60000E ; Disable direct link access
jsr OSLinkReset ; To be sure everything's in order
; move.w #0,D0 ; Enable interrupts
; trap #1
rts
;*****************************************************
; Send ADRESS or DATA Byte
i2clib@0002:
Adress:
i2clib@0003:
Send_byte:
move.w #7,D1 ; MSB first
loopsd:
btst.b D1,D0
beq sd0
Rel_SDA
bra sd1
sd0:
Pull_SDA
sd1:
bsr Wait_2us
Rel_SCL
bsr Wait_5us
Pull_SCL
bsr Wait_2us
dbra D1,loopsd
Rel_SDA ; Get the Acknowledge bit
bsr Wait_2us
Rel_SCL
bsr Wait_2us
Get_SDA
bne sdak0
move.l #1,D0 ; D0=1 : Ack not set (byte not received)
bra sdak1
sdak0:
move.l #0,D0 ; D0=0 : Ack Set (OK)
sdak1:
bsr Wait_2us
Pull_SCL
; Pull_SDA
bsr Wait_2us
rts
;*****************************************************
; Get DATA Byte and acknowledge
i2clib@0004:
Get_byte_a:
bsr Get_b
Pull_SDA ; Send an Acknowledge bit
bsr Wait_2us
Rel_SCL
bsr Wait_5us
Pull_SCL
bsr Wait_2us
Rel_SDA
rts
;*****************************************************
; Get DATA Byte and do not acknowledge
i2clib@0005:
Get_byte_na:
bsr Get_b
Rel_SDA ; Send a Not Acknowledge bit
bsr Wait_2us
Rel_SCL
bsr Wait_5us
Pull_SCL
bsr Wait_2us
rts
;*****************************************************
; Get byte subroutine
Get_b:
clr.l D0
move.w #7,D1 ; MSB first
loopgt:
bsr Wait_2us
Rel_SCL
bsr Wait_2us
Get_SDA
beq gt0
bset.b D1,D0
gt0:
bsr Wait_2us
Pull_SCL
bsr Wait_2us
dbra D1,loopgt
rts
;*****************************************************
end