View Full Version : Unsolved General purpose I2C driver written in PropForth V5.0 ???

Duane C. Johnson
04-08-2012, 02:30 AM
I'm looking for a general purpose I2C driver written in PropForth V5.0.

1. Single byte writes and reads to the I2C device.
2. Can operate with pins other than P28,P29.( i.e. not using EEPROM words.)
3. Written entirely in PropForth V5.0 words.
4. Bonus, if the I2C clock speed can be slowed down to less than 9KHz.


Duane J

04-08-2012, 08:29 PM
On the propforth downloads page, please nick lordi's contributions for spi and c3. I think these have something on i2c

04-08-2012, 11:06 PM
I wrote code of rtc(DS1337).
This use eeprom word.
But you can modify this code for a general purpose I2C driver.

PropForth 5.0

RTC DS1337 driver
24/03/2012 22:17:10
RTC DS1337 Propeller

scl ---- P28 0x1c
sda ---- P29 0x1d


\ bcd> ( n1 -- n2 ) convert bcd byte n1 to hex byte n2
[ifndef bcd>
: bcd>
dup F and
swap F0 and
1 rshift dup
2 rshift + +

\ >bcd ( n1 -- n2 ) convert hex byte n1 to bcd byte n2
[ifndef >bcd
: >bcd
A u/mod 4 lshift +

\ _rtcflip7 ( n7 n6 n5 n4 n3 n2 n1 -- n1 n2 n3 n4 n5 n6 n7 ) flip the top 7 items on the stack
: _rtcflip7
rot >r rot >r rot >r rot >r rot >r
r> r> r> r> r>
rot >r rot >r rot >r
r> r> r>
swap rot

\ _DS1337_w ( c1 -- )
: _DS1337_w
8007 ERR

\ _DS1337_s ( n1 -- ) I2C Start for DS1337
\ n1:register address c1:wr[0]/rd[1]
: _DS1337_s
D0 _DS1337_w \ slave address + wr[0]
_DS1337_w \ register adress

\ ( -- ) only Data Read
: _DS1337_sr
D1 _DS1337_w \ slave address + rd[1]

\ ( -- n1 n2 n3 n4 n5 n6 n7 ) read 7 bytes from DS1337
\ n1 - second (00 - 59)
\ n2 - minute (00 - 59)
\ n3 - hour (00 - 23)
\ n4 - day of week (1 - 7)
\ n5 - day (01 - 31)
\ n6 - month (01 - 12)
\ n7 - yesr (00 - 99)
: _DS1337_time_r 0 _DS1337_s _DS1337_sr 6 0 do 0 _eeread loop -1 _eeread _eestop ;
\ ( n1 n2 n3 n4 n5 n6 n7 -- ) write 7 bytes to DS1337
: _DS1337_time_w _rtcflip7 0 _DS1337_s 7 0 do _DS1337_w loop 0 _eeread drop _eestop ;

\ Read Hr/Min from Ds1337 ( -- n1 n2 ) n1:Minute n2:Hour
: read_hrmin
3drop drop
bcd> swap bcd> rot drop swap

\ Read&convert all time-data from DS1337
\ ( -- n1 n2 n3 n4 n5 n6 n7 )
\ n1 - second (00 - 59)
\ n2 - minute (00 - 59)
\ n3 - hour (00 - 23)
\ n4 - day of week (1 - 7)
\ n5 - day (01 - 31)
\ n6 - month (01 - 12)
\ n7 - yesr (2000 - 2099)
: read_time
bcd> 7D0 + >r \ Year
bcd> >r \ Month
bcd> >r \ Day
>r \ week
bcd> >r \ Hour
bcd> >r \ Minute
bcd> \ Second
r> r> r> r> r> r>

\ ( n1 n2 n3 n4 n5 -- ) write Input-datas to DS1337
\ n1 - yesr (00 - 99)
\ n2 - month (01 - 12)
\ n3 - day (01 - 31)
\ n4 - hour (00 - 23)
\ n5 - minute (00 - 59)
: set_time
0 rtc_busy W!
>bcd >r \ minute
>bcd >r \ hour
>bcd >r \ day
>bcd >r \ month
7D0 - >bcd \ year
r> r> 0 r> r> 0 _rtcflip7
read_time . . . . . . .


Duane C. Johnson
04-08-2012, 11:59 PM
Hi Professor:

I've searched high and low and can't find this.

There is some reference to SPI, and a bit on I2C but nowhere is there a link to any code? (That I can find)

Where can I find this?

Duane J

04-09-2012, 01:20 AM
From this page http://code.google.com/p/propforth/downloads/list

the links I was referring to are:

You should start with caskaz' example, I think you can just change the pin assignments.
Can you tell us your example I2C device, and what pins you have it on, etc?

We can help you work through it if you want.

Duane C. Johnson
04-09-2012, 03:17 AM
Hi Professor:

My long term project is for use in computation based solar trackers. The plan for this rendition is to use an SD-card to store many years, (maybe 30 years), of pre-computed stepper movements. I use a high accuracy ephemeris program in my PC to make the data files on the SD-card.

Currently I have everything running on a simple plugboard using FemtoBasic. The problem is the slow access reading even 1 month of data on the SD-card.

I have 3 devices in mind to be used on pins 16 & 17.
1. The DS1307 clock with 56 bytes of static ram
Clock_DS1307_Real-Time-Clock_RTC_I2C_DIP-8 (http://www.redrok.com/Clock_DS1307_Real-Time-Clock_RTC_I2C_DIP-8.pdf)
2. PCA9554 or PCA9555 Expander, very easy to use.
Expander_PCA9554_8-bit-I2C-bus-and-SMBus-IO-port_MicroChip_DIP-16 (http://www.redrok.com/Expander_PCA9554_8-bit-I2C-bus-and-SMBus-IO-port_MicroChip_DIP-16.pdf)
3. MCP23017 Expander, A bit more complicated.
Expander_MCP23017_16-Bit-IO-Expander-with-Serial-Interface_MicroChip_DIP-28 (http://www.redrok.com/Expander_MCP23017_16-Bit-IO-Expander-with-Serial-Interface_MicroChip_DIP-28.pdf)

All of these were pretty easy to drive using Mike Greens I2C driver in FemtoBasic.

Or possibly a shift register.
4. 74HCT595 shift register. However, this requires 4 pins to do right.
CMOS_74HCT595_8-bit-serial-in-serial-or-parallel-out-latched-tristate_DIP-16 (http://www.redrok.com/CMOS_74HCT595_8-bit-serial-in-serial-or-parallel-out-latched-tristate_DIP-16.pdf)

The reason I want to run the I2C buss at less than 9KHz is that at that speed shielding and filtering will eliminate any radio interference or emissions. Only the processor would need to be RF tight.

I am an old fan of forth. I started with an Apple ][, then a Z80, 1802, M68HC11, and a number of others over the years. My problem is I'm not a software engineer, I do pretty good when I see examples of how things are done them modify for my needs. I don't do so well when I'm on my own. I specifically choose the Propeller because it had a forth interpreter. I have done a bunch of stuff on V2.0. But I kind of backed off for a while waiting for the SD version of PropForth.

Anyway I would really appreciate all the help I can get on examples of I2C drivers.

Duane J

04-09-2012, 01:54 PM
Hi Duane

I'm not a EE, I'm a SWE, so I generally leave the hardware drivers to the EE's, unless I have the parts in the lab for testing. Other takes are first in the queue, and the only part similar to yours is the DS1302 on my PDB.
http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CIABEBYwAA&url=http%3A%2F%2Fwww.parallax.com%2Ftabid%2F786%2F ProductID%2F515%2FList%2F0%2FDefault.aspx&ei=TuiCT9npNIqQ8wTl6rHZBw&usg=AFQjCNFveye5Y4_38SnwGaXOhsDWt1Quog&sig2=imXvvDONeEaKnKwDQTbKgA

So I might be able to look at that. I actually don't know the difference between SPI and I2C, as I have not had a project that required me to work on these.

Did you have any progress with caskaz' code? He is one of the premier users of propforth, tap his brain as much as possible.

The extensions we are currently working on for propforth v5.1 may also prove to be of interest. These are CSP channels, which should be the stepping stone to execution automation and logging.

Duane C. Johnson
04-10-2012, 03:05 AM
Hi Professor;

I looked at the spec for the DS1302:
Clock_DS1302_Real-Time-Clock_RTC_Serial-Clock_DIP-8 (http://www.redrok.com/Clock_DS1302_Real-Time-Clock_RTC_Serial-Clock_DIP-8.pdf)
And compared it with the DS1307 which uses an I2C interface.
The DS1302 interface is similar to SPI, but not quite. SPI has separate data in and out pins, the DS1302 has bidirectional data.

SPI is a much simpler interface. Basically data is shifted in and out and controlled by the clock. Fairly easy to do.

I2C is similar but the clock has more specific functions.
Take a look at the MCP23017/MCP23S17 spec which describes both.
Expander_MCP23017_16-Bit-IO-Expander-with-Serial-Interface_MicroChip_DIP-28 (http://www.redrok.com/Expander_MCP23017_16-Bit-IO-Expander-with-Serial-Interface_MicroChip_DIP-28.pdf)

I've been thinking about the procedure to implement this. I suspect 1 forth word can be written for each bit type:
1. Start and Restart
2. Out bit
3 In bit
4. W/R bit
5. ACK/NAK bit
6. Stop bit
Some of these are complicated, especially the Start, and ACK bits.
I think this would be a real challenge to get right.
Start with the Prop being the master and transfer a single byte at a time.

The formatting of the data should be fairly easy.
1. 7 bit device op code
2. Read byte
3. Write byte.

I think this would be fun to try to do.
I would like to try. What do you think?

Duane J

04-10-2012, 04:03 PM
Hi Professor;

Some of these are complicated, especially the Start, and ACK bits.
I think this would be a real challenge to get right.
Start with the Prop being the master and transfer a single byte at a time.

If you can dig through the serial material in the tutorials, you might get some ideas. Sal has implemented all this stuff or similar. He pointed out the code where this happens, it very short and simple looking, but over my head. I got the impression its a lot simpler than it seems, we just have to break it down in the simplest thing that gets the job done, and resist the temptation to add the kitchen sink, which is the real trick.

It looks like you are on the right path though.