Small I2C driver
I have looked through the current I2C drivers and found them all - well - quite corpulent...
So I decided to post my "small footprint driver" - including a test program exercising the well known PCF8574A port expander. (Note the PCF8574 has a different device address; I have A-types as they were a bargain....)
It is still "version 1", so I should be grateful for problem reports..
Post Edited (deSilva) : 1/22/2008 12:46:14 AM GMT
So I decided to post my "small footprint driver" - including a test program exercising the well known PCF8574A port expander. (Note the PCF8574 has a different device address; I have A-types as they were a bargain....)
It is still "version 1", so I should be grateful for problem reports..
'' MPE_I2C_001 (mod)
'' Minimal I2C driver 2008-01 by deSilva
' ----- The following section is a test routine
_clkmode = xtal1 + pll8x
_xinfreq = 10_000_000
EEPROM = $A0
DEVICE = $70
LEDPIN = 25
PUB checkOut | x , status
{
This checks my minimal I2C driver, using a PCF8574A port expander
When an LED is connected from LEDPIN to Vcc it will indicate a device error.
+───A───────┐
+───B─────┐ │
+───C───┐ │ │
+─  ─┐ │ │ │
│ │ │ │
+ D C I │ │ │ │
┌┴─┴─┴─┴─┴─┴─┴─┴┐
│(8574) 7 6 5 4│
│ 0 1 2 3 │
└┬─┬─┬─┬─┬─┬─┬─┬┘
- - -     -
C B A
I/O 4,5,6,7 of the PCF will be configured as OUTPUT (0)
I/O 0,1,2,3 as INPUT / active low
Connect LEDs to 4,5,6 (resistors to high, as this is a kind of open drain chip)
Each of them will light when I/O 1,2,3 resp. are set LOW
As those pins are just opposite, I reversed the bits to make it look better
I/O 0 is special: As long as it's low a 1.5 kHz signal is output at I/O 7
and I/O 4,5,6 are all three on.
Note that inputs are HIGH by default as with the old TTLs
}
REPEAT
REPEAT
engage
status := snd(DEVICE)
status |= snd(%0000_1111|(x><8)) ' 8 I/O pins:
' 0: output (driven low)
' 1: input (tri-state)
'release
engage
status |= snd(DEVICE+1)
x := rcv
'release
DIRA[noparse][[/noparse]LEDPIN]:=status
WHILE x&1
engage
snd(DEVICE)
REPEAT 1500
snd(%1000_1111)
snd(%0000_1111)
release
' ===========Here starts deSilva's small I2C driver
CON
SCL = 28
SDA = 29
PUB engage
' Pulls SDA to LOW whilst CLK is HIGH
dira[noparse][[/noparse]SCL]~~
outa[noparse][[/noparse]SDA]~
'The former two instructions need be done only once, if all is o.k.
outa[noparse][[/noparse]SCL]~~
dira[noparse][[/noparse]SDA]~ ' Pulse SDA; HIGH by pullup (default)
dira[noparse][[/noparse]SDA]~~ ' Enable = LOW
outa[noparse][[/noparse]SCL]~ ' Keep SCL LOW
PUB snd(by) : status
' Send a byte (and get status: 0: ACK 1: NAK)
by := (!by) >< 8 ' Reverse bits and invert pattern
REPEAT 8
dira[noparse][[/noparse]SDA] := by
outa[noparse][[/noparse]SCL]~~ ' Transfer on rising edge
by >>= 1
outa[noparse][[/noparse]SCL]~
' Returns "acknowledge bit": 0 = ACK, 1 = NAK.
dira[noparse][[/noparse]SDA]~ ' release SDA
outa[noparse][[/noparse]SCL]~~ ' puls-in ACK
status := ina[noparse][[/noparse]SDA]
outa[noparse][[/noparse]SCL]~ ' keep CLK low
PUB release
' Assert stop condition.
' SDA transits from LOW to HIGH whilst SCL is HIGH
dira[noparse][[/noparse]SDA]~~ ' LOW
outa[noparse][[/noparse]SCL]~~
dira[noparse][[/noparse]SDA]~ ' release SDA (HIGH)
PUB rcv : val
' Get a byte
REPEAT 8
outa[noparse][[/noparse]SCL]~~ ' Request bit
val <<= 1
val |= ina[noparse][[/noparse]SDA]
outa[noparse][[/noparse]SCL]~ ' Keep CLK low
PUB nak
' Send ackbit
dira[noparse][[/noparse]SDA]~~ ' LOW
outa[noparse][[/noparse]SCL]~~ ' Pulse SCL
outa[noparse][[/noparse]SCL]~ ' keep CLK low
dira[noparse][[/noparse]SDA]~ ' release SDA
PUB ack
' Send ackbit
dira[noparse][[/noparse]SDA]~ ' HIGH
outa[noparse][[/noparse]SCL]~~ ' Pulse SCL
outa[noparse][[/noparse]SCL]~ ' keep CLK low
dira[noparse][[/noparse]SDA]~ ' release SDA
Post Edited (deSilva) : 1/22/2008 12:46:14 AM GMT

Comments
http://www.rayslogic.com/propeller/Programming/i2c/i2c.htm
PS:· The PCA9554·is a newer device with the same pinout but better in several ways...
Post Edited (Rayman) : 1/22/2008 1:21:22 AM GMT
I am aware that the PCA9554 is newer, but I miss its true advantages. The 8574 is extremely versatile and most simple to program... And as I said, I got a lot of them for little money
You have an INA, giving you all the pin states, and a DIRA, allowing you to select either high impedance, or driving an external resistor low @15 mA.
For some projects it could be a problem not being able to drive from high.. Also 100 kHz might be slow. As seen I can generate 1.5 kHz square waves at the moment. Even with machine code this will not exceed 5 kHz (100kHz clock /10 clocks /2). The 9554 on the other hand could sample 40 kHz.