Shop OBEX P1 Docs P2 Docs Learn Events
I2C problem — Parallax Forums

I2C problem

ArchiverArchiver Posts: 46,084
edited 2001-10-06 00:19 in General Discussion
Hi all,

I've got a I2C problem that I can't seem to fix.
I have connected an I2C eeprom to port8 (SDA) and port9 (SCL)
of a basic stamp 2SX.
The code that follows operates perfectly. Values written to the
eeprom are later read back correctly. Inside the low level I2C routines
the SDA and SCL lines are sometimes driven high. Instead of driving these
lines high I want to make them inputs and let the 4.7k pullup resistors
pull the lines high. Here start the troubles. Read on after the working
program.

'*** FINE WORKING CODE

'{$STAMP BS2sx}
OUTINIT con %0000000000000000 'init values for output pins
DIRINIT con %0010110000000000 'initial direction of pins
I2C0 con 0 'for use with I2C functions
I2C8 con 8 'for use with I2C functions

'Pin variables

_sda0in var in0
_sda0out var out0
_sda8in var in8
_sda8out var out8

'I2C data transfer variables
'all required during an I2C function call, otherwise free

_I2Ctemp1 var byte 'I2C low level functions
_I2Cbus var _I2Ctemp1.lownib 'I2C bus select, either I2C0 or I2C8
_I2Cbits var _I2Ctemp1.highnib 'I2C bit counter
_I2Ctemp2 var byte 'I2C low level functions storage variable
_I2Cslave var byte 'I2C high level entry slave id
_I2Cword var byte 'I2C high level entry word address
_I2Cdata var byte 'I2C high level entry data byte
n var byte 'counter

begin:
outs = OUTINIT
dirs = DIRINIT
_I2Cbus = I2C8 'we use port8/port9
pause 2000

PCF8582TEST:
debug "Eeprom Test...",cr
_I2Cslave=$A0
for n=0 to 255
_I2Cword = n
_I2Cdata = n
gosub I2C_xwrite
next
for n=0 to 255
_I2Cword = n
gosub I2C_xread
if _I2Cdata = n then pcf8582_1
debug "error; write ", hex2 n, " read ", hex2 _I2Cdata, cr
pcf8582_1:
next
debug "Eeprom test finished",cr

loop:
goto loop

'
---
' System calls for I2C devices
'
---
'note: _I2Cbus determines which ports are used for I2C (P0/P1 or P8/P9)
' and should be set properly before calling these functions

'Name : I2C_xwrite
'Function: write byte to I2C device with internal address
'Inputs : _I2Cslave = slave ID, _I2Cword = internal address, _I2Cdata =
byte to be written
'Returns : none
'Modifies: _I2Ctemp2, _I2Cbits

I2C_xwrite:
gosub I2C_start
_I2Ctemp2 = _I2Cslave
gosub I2C_byteout
_I2Ctemp2 = _I2Cword
gosub I2C_byteout
_I2Ctemp2 = _I2Cdata
gosub I2C_byteout
gosub I2C_stop
pause 20
return

'Name : I2C_xread
'Function: read byte from I2C device with internal address
'Inputs : _I2Cslave = slave ID, _I2Cword = internal address
'Returns : _I2Cdata = byte read
'Modifies: _I2Ctemp2, _I2Cbits

I2C_xread:
gosub I2C_start
_I2Ctemp2 = _I2Cslave
gosub I2C_byteout
_I2Ctemp2 = _I2Cword
gosub I2C_byteout
gosub I2C_start
_I2Ctemp2 = _I2Cslave | $1
gosub I2C_byteout
gosub I2C_bytein
gosub I2C_stop
return

'***** low level routines for I2C bus *****

I2C_byteout:
low _I2Cbus
for _I2Cbits=0 to 7
if _I2Cbus=I2C8 then I2C_bo1
_sda0out = _I2Ctemp2.bit7
goto I2C_bo2
I2C_bo1:
_sda8out = _I2Ctemp2.bit7
I2C_bo2:
high _I2Cbus+1
low _I2Cbus+1
_I2Ctemp2 = _I2Ctemp2<<1
next
input _I2Cbus
high _I2Cbus+1
low _I2Cbus+1
output _I2Cbus
return

I2C_bytein:
input _I2Cbus
_I2Cdata = 0
for _I2Cbits=0 to 7
high _I2Cbus+1
_I2Cdata = (_I2Cdata << 1) | (_sda8in & _I2Cbus.bit3) | (_sda0in &
(1-_I2Cbus.bit3))
low _I2Cbus+1
next
output _I2Cbus
high _I2Cbus+1
low _I2Cbus+1
return

I2C_start:
input _I2Cbus
high _I2Cbus+1
low _I2Cbus
low _I2Cbus+1
return

I2C_stop
low _I2Cbus
high _I2Cbus+1
input _I2Cbus
return

end

Concerned are only the low level routines.
As the stamp output latches hold 0, I make SDA and SCL
low by setting these lines to outputs. To make these
lines high I make them inputs. That's the only difference
between the working low level routines and the not-working
routines.

'*** MAKE INPUTS TO PULL LINES HIGH

'***** low level routines for I2C bus *****

I2C_byteout:
output _I2Cbus
for _I2Cbits=0 to 7
if _I2Ctemp2.bit7=0 then I2C_bo1
input _I2Cbus
goto I2C_bo2
I2C_bo1:
output _I2Cbus
I2C_bo2:
input _I2Cbus+1
output _I2Cbus+1
_I2Ctemp2 = _I2Ctemp2<<1
next
input _I2Cbus
input _I2Cbus+1
output _I2Cbus+1
output _I2Cbus
return

I2C_bytein:
input _I2Cbus
_I2Cdata = 0
for _I2Cbits=0 to 7
input _I2Cbus+1
_I2Cdata = (_I2Cdata << 1) | (_sda8in & _I2Cbus.bit3) | (_sda0in &
(1-_I2Cbus.bit3))
output _I2Cbus+1
next
output _I2Cbus
input _I2Cbus+1
output _I2Cbus+1
return

I2C_start:
input _I2Cbus
input _I2Cbus+1
output _I2Cbus
output _I2Cbus+1
return

I2C_stop
output _I2Cbus
input _I2Cbus+1
input _I2Cbus
return

With these new low level routines the read back test routine gives mostly
errors for data values between 0 and 127, but never for 128-255. So I know
bit7 of the data value is involved. I just can't locate the error.
If anyone can pinpoint the error or perhaps a physical cause (stronger
pullups
perhaps instead of the 4.7k), that would be much appreciated.

greetings peter

Comments

  • ArchiverArchiver Posts: 46,084
    edited 2001-10-05 19:29
    Hi Peter,

    I might be wrong, and you've probably thought of all this, but ...

    You have, of course, tried the combination of NEW writes and OLD reads, and
    vice-versa to determine that the data is written correctly, rather than
    being retrieved incorrectly?

    Since your bit-banging, a bit of a delay after the line-transitions would
    only slow the I2C bitrate, and might shed some light on the differences in
    actively driving (IN/OUT) and passively driving (INPUT/OUTPUT) the line.

    Regards,
    Daniel


    >
    Original Message
    > From: Peter Verkaik [noparse]/noparse]mailto:[url=http://forums.parallaxinc.com/group/basicstamps/post?postID=GynV86B6QOqO9Qfn29vbD4Zn_BjGG7lxCOHBBhvxjv1nmumKrjlAfTZaPSrjGLkwdnx6Fvw7A1HDxNMs2CMBrQ]peterverkaik@b...[/url
    > Sent: Thursday, 04 October 2001 16:29
    > To: basicstamps@yahoogroups.com
    > Subject: [noparse][[/noparse]basicstamps] I2C problem
    >
    >
    > Hi all,
    >
    > I've got a I2C problem that I can't seem to fix.
    > I have connected an I2C eeprom to port8 (SDA) and port9 (SCL)
    > of a basic stamp 2SX.
    > The code that follows operates perfectly. Values written to the
    > eeprom are later read back correctly. Inside the low level I2C routines
    > the SDA and SCL lines are sometimes driven high. Instead of driving these
    > lines high I want to make them inputs and let the 4.7k pullup resistors
    > pull the lines high. Here start the troubles. Read on after the working
    > program.
    >
    > '*** FINE WORKING CODE
    >
    > '{$STAMP BS2sx}
    > OUTINIT con %0000000000000000 'init values for output pins
    > DIRINIT con %0010110000000000 'initial direction of pins
    > I2C0 con 0 'for use with I2C functions
    > I2C8 con 8 'for use with I2C functions
    >
    > 'Pin variables
    >
    > _sda0in var in0
    > _sda0out var out0
    > _sda8in var in8
    > _sda8out var out8
    >
    > 'I2C data transfer variables
    > 'all required during an I2C function call, otherwise free
    >
    > _I2Ctemp1 var byte 'I2C low level functions
    > _I2Cbus var _I2Ctemp1.lownib 'I2C bus select,
    > either I2C0 or I2C8
    > _I2Cbits var _I2Ctemp1.highnib 'I2C bit counter
    > _I2Ctemp2 var byte 'I2C low level
    > functions storage variable
    > _I2Cslave var byte 'I2C high level
    > entry slave id
    > _I2Cword var byte 'I2C high level
    > entry word address
    > _I2Cdata var byte 'I2C high level
    > entry data byte
    > n var byte 'counter
    >
    > begin:
    > outs = OUTINIT
    > dirs = DIRINIT
    > _I2Cbus = I2C8 'we use port8/port9
    > pause 2000
    >
    > PCF8582TEST:
    > debug "Eeprom Test...",cr
    > _I2Cslave=$A0
    > for n=0 to 255
    > _I2Cword = n
    > _I2Cdata = n
    > gosub I2C_xwrite
    > next
    > for n=0 to 255
    > _I2Cword = n
    > gosub I2C_xread
    > if _I2Cdata = n then pcf8582_1
    > debug "error; write ", hex2 n, " read ", hex2 _I2Cdata, cr
    > pcf8582_1:
    > next
    > debug "Eeprom test finished",cr
    >
    > loop:
    > goto loop
    >
    > '
    >
    > ---
    > ' System calls for I2C devices
    > '
    >
    > ---
    > 'note: _I2Cbus determines which ports are used for I2C (P0/P1 or P8/P9)
    > ' and should be set properly before calling these functions
    >
    > 'Name : I2C_xwrite
    > 'Function: write byte to I2C device with internal address
    > 'Inputs : _I2Cslave = slave ID, _I2Cword = internal address, _I2Cdata =
    > byte to be written
    > 'Returns : none
    > 'Modifies: _I2Ctemp2, _I2Cbits
    >
    > I2C_xwrite:
    > gosub I2C_start
    > _I2Ctemp2 = _I2Cslave
    > gosub I2C_byteout
    > _I2Ctemp2 = _I2Cword
    > gosub I2C_byteout
    > _I2Ctemp2 = _I2Cdata
    > gosub I2C_byteout
    > gosub I2C_stop
    > pause 20
    > return
    >
    > 'Name : I2C_xread
    > 'Function: read byte from I2C device with internal address
    > 'Inputs : _I2Cslave = slave ID, _I2Cword = internal address
    > 'Returns : _I2Cdata = byte read
    > 'Modifies: _I2Ctemp2, _I2Cbits
    >
    > I2C_xread:
    > gosub I2C_start
    > _I2Ctemp2 = _I2Cslave
    > gosub I2C_byteout
    > _I2Ctemp2 = _I2Cword
    > gosub I2C_byteout
    > gosub I2C_start
    > _I2Ctemp2 = _I2Cslave | $1
    > gosub I2C_byteout
    > gosub I2C_bytein
    > gosub I2C_stop
    > return
    >
    > '***** low level routines for I2C bus *****
    >
    > I2C_byteout:
    > low _I2Cbus
    > for _I2Cbits=0 to 7
    > if _I2Cbus=I2C8 then I2C_bo1
    > _sda0out = _I2Ctemp2.bit7
    > goto I2C_bo2
    > I2C_bo1:
    > _sda8out = _I2Ctemp2.bit7
    > I2C_bo2:
    > high _I2Cbus+1
    > low _I2Cbus+1
    > _I2Ctemp2 = _I2Ctemp2<<1
    > next
    > input _I2Cbus
    > high _I2Cbus+1
    > low _I2Cbus+1
    > output _I2Cbus
    > return
    >
    > I2C_bytein:
    > input _I2Cbus
    > _I2Cdata = 0
    > for _I2Cbits=0 to 7
    > high _I2Cbus+1
    > _I2Cdata = (_I2Cdata << 1) | (_sda8in & _I2Cbus.bit3) | (_sda0in &
    > (1-_I2Cbus.bit3))
    > low _I2Cbus+1
    > next
    > output _I2Cbus
    > high _I2Cbus+1
    > low _I2Cbus+1
    > return
    >
    > I2C_start:
    > input _I2Cbus
    > high _I2Cbus+1
    > low _I2Cbus
    > low _I2Cbus+1
    > return
    >
    > I2C_stop
    > low _I2Cbus
    > high _I2Cbus+1
    > input _I2Cbus
    > return
    >
    > end
    >
    > Concerned are only the low level routines.
    > As the stamp output latches hold 0, I make SDA and SCL
    > low by setting these lines to outputs. To make these
    > lines high I make them inputs. That's the only difference
    > between the working low level routines and the not-working
    > routines.
    >
    > '*** MAKE INPUTS TO PULL LINES HIGH
    >
    > '***** low level routines for I2C bus *****
    >
    > I2C_byteout:
    > output _I2Cbus
    > for _I2Cbits=0 to 7
    > if _I2Ctemp2.bit7=0 then I2C_bo1
    > input _I2Cbus
    > goto I2C_bo2
    > I2C_bo1:
    > output _I2Cbus
    > I2C_bo2:
    > input _I2Cbus+1
    > output _I2Cbus+1
    > _I2Ctemp2 = _I2Ctemp2<<1
    > next
    > input _I2Cbus
    > input _I2Cbus+1
    > output _I2Cbus+1
    > output _I2Cbus
    > return
    >
    > I2C_bytein:
    > input _I2Cbus
    > _I2Cdata = 0
    > for _I2Cbits=0 to 7
    > input _I2Cbus+1
    > _I2Cdata = (_I2Cdata << 1) | (_sda8in & _I2Cbus.bit3) | (_sda0in &
    > (1-_I2Cbus.bit3))
    > output _I2Cbus+1
    > next
    > output _I2Cbus
    > input _I2Cbus+1
    > output _I2Cbus+1
    > return
    >
    > I2C_start:
    > input _I2Cbus
    > input _I2Cbus+1
    > output _I2Cbus
    > output _I2Cbus+1
    > return
    >
    > I2C_stop
    > output _I2Cbus
    > input _I2Cbus+1
    > input _I2Cbus
    > return
    >
    > With these new low level routines the read back test routine gives mostly
    > errors for data values between 0 and 127, but never for 128-255. So I know
    > bit7 of the data value is involved. I just can't locate the error.
    > If anyone can pinpoint the error or perhaps a physical cause (stronger
    > pullups
    > perhaps instead of the 4.7k), that would be much appreciated.
    >
    > greetings peter
    >
    >
    > To UNSUBSCRIBE, just send mail to:
    > basicstamps-unsubscribe@yahoogroups.com
    > from the same email address that you subscribed. Text in the
    > Subject and Body of the message will be ignored.
    >
    >
    > Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
    >


    _________________________________________________________
    Do You Yahoo!?
    Get your free @yahoo.com address at http://mail.yahoo.com
  • ArchiverArchiver Posts: 46,084
    edited 2001-10-05 22:24
    Hi Daniel,

    Each new run I change the data to write to 255-n or n (inverse it) and
    change
    the read back test accordingly. Always the same result. I also tried delays.
    No effect. I guess that's because of the decoding time the stamp already
    requires
    to interpret the pbasic commands. It looks as if the clock synchronization
    gets out
    of order, I just don't see how. I'll keep working on it. What's bugging me
    is that
    for data values $80-$FF everything looks ok, i.e when bit7 is high.

    reards peter

    Oorspronkelijk bericht
    Van: D. Daniel McGlothin [noparse]/noparse]mailto:[url=http://forums.parallaxinc.com/group/basicstamps/post?postID=cwCKasN7dv8_Y59DQm736AilkE9iD56s1ghAs-6pvRHh7nphh4ieEpvANoKWJd16ATnoLdTGmbqdR8RokC5T]ddm_stamps@y...[/url
    Verzonden: vrijdag 5 oktober 2001 19:29
    Aan: basicstamps@yahoogroups.com
    Onderwerp: RE: [noparse][[/noparse]basicstamps] I2C problem


    Hi Peter,

    I might be wrong, and you've probably thought of all this, but ...

    You have, of course, tried the combination of NEW writes and OLD reads, and
    vice-versa to determine that the data is written correctly, rather than
    being retrieved incorrectly?

    Since your bit-banging, a bit of a delay after the line-transitions would
    only slow the I2C bitrate, and might shed some light on the differences in
    actively driving (IN/OUT) and passively driving (INPUT/OUTPUT) the line.

    Regards,
    Daniel
  • ArchiverArchiver Posts: 46,084
    edited 2001-10-05 22:55
    In a message dated 10/5/01 4:39:58 PM Central Daylight Time,
    peterverkaik@b... writes:


    > Each new run I change the data to write to 255-n or n (inverse it) and
    > change
    > the read back test accordingly. Always the same result. I also tried delays.
    > No effect. I guess that's because of the decoding time the stamp already
    > requires
    > to interpret the pbasic commands. It looks as if the clock synchronization
    > gets out
    > of order, I just don't see how. I'll keep working on it. What's bugging me
    > is that
    >

    Peter Anderson has quite a bit of I2C code for non-BS2p Stamps on his
    web-site. Perhaps a look there will provide some answers.

    Try these links:

    -- http://www.phanderson.com/stamp/i2c/8574.html
    -- http://www.phanderson.com/stamp/i2c/24lc32.html
    -- http://www.phanderson.com/stamp/i2c/ds1621_1.html
    -- http://www.phanderson.com/stamp/i2c/ds1803_1.html


    [noparse][[/noparse]Non-text portions of this message have been removed]
  • ArchiverArchiver Posts: 46,084
    edited 2001-10-06 00:19
    Hi Daniel,

    I found the problem!
    I merged the active and passive routines in one program
    and tried write/read combinations as you suggested.
    I had set the SDA for output to send ACK to slave (byte in routines) but
    forgot
    that the output latch holds a databit at that time. I changed it
    to an input to set SDA high for ACK and all write/read combinations
    are now without error.
    Thanks again for the suggestion.

    regards peter


    I2C0 con 0 'for use with I2C functions
    I2C8 con 8 'for use with I2C functions

    OUTINIT con %0000000000000000 'init values for output pins
    DIRINIT con %0010110000000000 'initial direction of pins

    'Pin variables

    _sda0in var in0
    _sda0out var out0
    _sda8in var in8
    _sda8out var out8

    'I2C data transfer variables
    'all required during an I2C function call, otherwise free

    _I2Ctemp1 var byte 'I2C low level functions
    _I2Cbus var _I2Ctemp1.lownib 'I2C bus select, either I2C0 or I2C8
    _I2Cbits var _I2Ctemp1.highnib 'I2C bit counter
    _I2Ctemp2 var byte 'I2C low level functions storage variable
    _I2Cslave var byte 'I2C high level entry slave id
    _I2Cword var byte 'I2C high level entry word address
    _I2Cdata var byte 'I2C high level entry data byte
    n var byte

    'Code starts here

    begin:
    outs = OUTINIT
    dirs = DIRINIT
    _I2Cbus = I2C8
    pause 2000

    gosub PCF8582TEST
    mainloop:
    goto mainloop

    '***** PCF8582 I2C eeprom test routine

    PCF8582TEST:
    'Test sequence
    'Write 256 bytes (n) using ACTIVE write routine.
    'Read back using ACTIVE read routine
    'Read back using PASSIVE read routine
    'Write 256 complementary bytes (255-n) using PASSIVE write routine
    'Read back using ACTIVE read routine
    'Read back using PASSIVE read routine

    _I2Cslave=$A0
    debug "Eeprom test...ACTIVE write",cr
    for n=0 to 255
    _I2Cword = n
    _I2Cdata = n
    gosub I2C_xwrite
    next
    dirs = DIRINIT 'set startup conditions for testing
    outs = OUTINIT
    pause 1000 'hold debug output for a sec
    debug "Eeprom test...ACTIVE read",cr
    for n=0 to 255
    _I2Cword = n
    gosub I2C_xread
    if _I2Cdata = n then pcf8582_1
    debug "AW-AR error; write ", hex2 n, " read ", hex2 _I2Cdata, cr
    pcf8582_1:
    next
    dirs = DIRINIT
    outs = OUTINIT
    pause 1000
    debug "Eeprom test...PASSIVE read",cr
    for n=0 to 255
    _I2Cword = n
    gosub pasI2C_xread
    if _I2Cdata = n then pcf8582_2
    debug "AW-PR error; write ", hex2 n, " read ", hex2 _I2Cdata, cr
    pcf8582_2:
    next
    dirs = DIRINIT
    outs = OUTINIT
    pause 1000
    debug "Eeprom test...PASSIVE write",cr
    for n=0 to 255
    _I2Cword = n
    _I2Cdata = 255-n
    gosub pasI2C_xwrite
    next
    dirs = DIRINIT
    outs = OUTINIT
    pause 1000
    debug "Eeprom test...ACTIVE read",cr
    for n=0 to 255
    _I2Cword = n
    gosub I2C_xread
    if _I2Cdata = 255-n then pcf8582_3
    debug "PW-AR error; write ", hex2 255-n, " read ", hex2 _I2Cdata, cr
    pcf8582_3:
    next
    dirs = DIRINIT
    outs = OUTINIT
    pause 1000
    debug "Eeprom test...PASSIVE read",cr
    for n=0 to 255
    _I2Cword = n
    gosub pasI2C_xread
    if _I2Cdata = 255-n then pcf8582_4
    debug "PW-PR error; write ", hex2 255-n, " read ", hex2 _I2Cdata, cr
    pcf8582_4:
    next
    dirs = DIRINIT
    outs = OUTINIT
    debug "Eeprom test finished",cr
    return

    '
    ---
    ' System calls for I2C devices
    '
    ---
    'note: _I2Cbus determines which ports are used for I2C (P0/P1 or P8/P9)
    ' and should be set properly before calling these functions

    '***** byte read/write functions for I2C bus *****

    'Name : I2C_xwrite (ACTIVE)
    'Function: write byte to I2C device with internal address
    'Inputs : _I2Cslave = slave ID, _I2Cword = internal address, _I2Cdata =
    byte to be written
    'Returns : none
    'Modifies: _I2Ctemp2, _I2Cbits

    I2C_xwrite:
    gosub I2C_start
    _I2Ctemp2 = _I2Cslave
    gosub I2C_byteout
    _I2Ctemp2 = _I2Cword
    gosub I2C_byteout
    _I2Ctemp2 = _I2Cdata
    gosub I2C_byteout
    gosub I2C_stop
    pause 20
    return

    'Name : I2C_xread (ACTIVE)
    'Function: read byte from I2C device with internal address
    'Inputs : _I2Cslave = slave ID, _I2Cword = internal address
    'Returns : _I2Cdata = byte read
    'Modifies: _I2Ctemp2, _I2Cbits

    I2C_xread:
    gosub I2C_start
    _I2Ctemp2 = _I2Cslave
    gosub I2C_byteout
    _I2Ctemp2 = _I2Cword
    gosub I2C_byteout
    gosub I2C_start
    _I2Ctemp2 = _I2Cslave | $1
    gosub I2C_byteout
    gosub I2C_bytein
    gosub I2C_stop
    return

    'Name : pasI2C_xwrite (PASSIVE)
    'Function: write byte to I2C device with internal address
    'Inputs : _I2Cslave = slave ID, _I2Cword = internal address, _I2Cdata =
    byte to be written
    'Returns : none
    'Modifies: _I2Ctemp2, _I2Cbits

    pasI2C_xwrite:
    gosub pasI2C_start
    _I2Ctemp2 = _I2Cslave
    gosub pasI2C_byteout
    _I2Ctemp2 = _I2Cword
    gosub pasI2C_byteout
    _I2Ctemp2 = _I2Cdata
    gosub pasI2C_byteout
    gosub pasI2C_stop
    pause 20
    return

    'Name : pasI2C_xread (PASSIVE)
    'Function: read byte from I2C device with internal address
    'Inputs : _I2Cslave = slave ID, _I2Cword = internal address
    'Returns : _I2Cdata = byte read
    'Modifies: _I2Ctemp2, _I2Cbits

    pasI2C_xread:
    gosub pasI2C_start
    _I2Ctemp2 = _I2Cslave
    gosub pasI2C_byteout
    _I2Ctemp2 = _I2Cword
    gosub pasI2C_byteout
    gosub pasI2C_start
    _I2Ctemp2 = _I2Cslave | $1
    gosub pasI2C_byteout
    gosub pasI2C_bytein
    gosub pasI2C_stop
    return

    '***** ACTIVE *** low level routines for I2C bus *****

    I2C_byteout:
    low _I2Cbus
    for _I2Cbits=0 to 7
    if _I2Cbus=I2C8 then I2C_bo1
    _sda0out = _I2Ctemp2.bit7
    goto I2C_bo2
    I2C_bo1:
    _sda8out = _I2Ctemp2.bit7
    I2C_bo2:
    high _I2Cbus+1
    low _I2Cbus+1
    _I2Ctemp2 = _I2Ctemp2<<1
    next
    input _I2Cbus 'accept ACK from slave
    high _I2Cbus+1
    low _I2Cbus+1
    return

    I2C_bytein:
    input _I2Cbus
    _I2Cdata = 0
    for _I2Cbits=0 to 7
    high _I2Cbus+1
    _I2Cdata = (_I2Cdata << 1) | (_sda8in & _I2Cbus.bit3) | (_sda0in &
    (1-_I2Cbus.bit3))
    low _I2Cbus+1
    next
    input _I2Cbus 'keep data high for ACK
    high _I2Cbus+1
    low _I2Cbus+1
    return

    I2C_start:
    high _I2Cbus+1
    low _I2Cbus
    low _I2Cbus+1
    return

    I2C_stop
    low _I2Cbus
    high _I2Cbus+1
    input _I2Cbus
    return

    '***** PASSIVE *** low level routines for I2C bus *****

    pasI2C_byteout:
    for _I2Cbits=0 to 7
    if _I2Ctemp2.bit7=0 then pasI2C_bo1
    input _I2Cbus
    goto pasI2C_bo2
    pasI2C_bo1:
    output _I2Cbus
    pasI2C_bo2:
    input _I2Cbus+1
    output _I2Cbus+1
    _I2Ctemp2 = _I2Ctemp2<<1
    next
    input _I2Cbus 'accept ACK from slave
    input _I2Cbus+1 'clock ACK
    output _I2Cbus+1
    return

    pasI2C_bytein:
    input _I2Cbus
    _I2Cdata = 0
    for _I2Cbits=0 to 7
    input _I2Cbus+1
    _I2Cdata = (_I2Cdata << 1) | (_sda8in & _I2Cbus.bit3) | (_sda0in &
    (1-_I2Cbus.bit3))
    output _I2Cbus+1
    next
    input _I2Cbus 'keep data high for ACK
    input _I2Cbus+1
    output _I2Cbus+1
    return

    pasI2C_start:
    input _I2Cbus+1 'clock high
    output _I2Cbus 'data high->low while clock high
    output _I2Cbus+1 'clock low
    return

    pasI2C_stop
    output _I2Cbus 'data low
    input _I2Cbus+1 'clock high
    input _I2Cbus 'data low->high while clock high
    return

    end
Sign In or Register to comment.