Shop OBEX P1 Docs P2 Docs Learn Events
"Generic" I2C operations in Propeller C — Parallax Forums

"Generic" I2C operations in Propeller C

Bald-N-BlueBald-N-Blue Posts: 3
edited 2013-10-31 14:00 in Learn with BlocklyProp
I'm looking for some pointers in setting up an I2C interface using Prop C. I'm comfortable with PBASIC and the Stamp environment, and with the I2C protocol, but I'm new to the Prop, Spin, and Prop C (actually OOL in general). I've been through the Propeller C tutorials on the site, and while I feel like I've learned a lot, I still have a long way to go. For someone like me, that's the fun part :)

As far as the library references, I'm a little over my head with some of the syntax, structures, etc., but I'm starting to figure some of it out by looking at examples where they are listed. Not all of the function documentation have examples, so I'm a little confused by a few things after looking at the simpletools library (i2c_newbus, i2c_out, i2c_in), and the simplei2c library (i2c_open, i2c_start, i2c_stop, etc.). I got even more flustered when I looked at the compass3d library, as that sensor uses i2c and I was hoping for an example of how it all fits together. Unfortunately, it refers to a function called "i2c_init" in the simpletools library, which I can't seem to find . . . :(

I know I am making this WAY HARDER than it needs to be. If someone could point me to a general example of how to set up a generic i2c device in a Prop C function call, it would go a long way toward helping me understand how these libraries work together. I've done some searching and I haven't been able to find anything yet. For the record, I'm putting together a circuit using a PCF8574 8 bit I/O expander, but even an example for a very common DS1307 RTC would be a BIG help.

Thanks in advance for any help!

Comments

  • dgatelydgately Posts: 1,631
    edited 2013-10-30 23:20
    I think you'll find that the documentation for compass3d library is a little old. I'm sure it's intended to be updated. If you look at the actual code for libcompass3d.c (In the Simple Libraries/Sensors/libcompass3d directory), you'll see that it actually uses 12c_newbus(clock,data,drive) to create an i2c bus storage variable:
    In libcompass3d.c
    
      i2c *bus = i2c_newbus(3, 2, 0);             // New I2C bus SCL=P3, SDA=P2
    
    i2c_newbus as documented in the simple tools library documentation:
    
    [INDENT]i2c* i2c_newbus	(
    [INDENT]
    int 	sclpin,
    int 	sdapin,
    int 	scldrive [/INDENT]
    )[/INDENT]
    	
    

    I hope this helps,
    dgately
  • SRLMSRLM Posts: 5,045
    edited 2013-10-30 23:27
    I haven't used the Parallax supplied I2C drivers, but I'll take an opportunity for some self promotion here. I have a generic C++ driver that I've worked extensively on here that might prove useful. It comes with a number of higher level drivers for devices such as the PCF8523 RTC and others.
  • jazzedjazzed Posts: 11,803
    edited 2013-10-31 09:32
    The Learn/Protocol/libsimplei2c was originally designed to work like below.

    A reference for libsimplei2c is on-line here: https://propsideworkspace.googlecode.com/hg/Learn/Simple Libraries/Protocol/libsimplei2c/Documentation simplei2c Library.html
    The same file would be in your "up-to-date" SimpleIDE/Learn folder.

    Andy created wrappers for the simplei2c library and put them in the simpletools library.
    https://propsideworkspace.googlecode.com/hg/Learn/Simple Libraries/Utility/libsimpletools/Documentation simpletools Library.html

    /**
     * This is the main I2Creadbyte program file.
     */
    
    // This include causes libsimplei2c, libsimpletext, and others to be linked in SimpleIDE.
    #include "simpletools.h"
    
    int main(void)
    {
        int bytes[4]; // byte storage
        i2c eebus;    // declare an i2c device variable
    
        pause(1000);  // pause to ensure we can see output
    
        i2c_open(&eebus, 28, 29, 1); // open the device
    
        i2c_start(&eebus); // send the start sequence for addressing
        i2c_writeByte(&eebus, 0xA0); // send the EEPROM device ID as a write
        i2c_writeByte(&eebus, 0); // send the address upper byte
        i2c_writeByte(&eebus, 0); // send the address lower byte
    
        i2c_start(&eebus); // send the start sequence again for a read
        i2c_writeByte(&eebus, 0xA1); // send the ID as a read
        bytes[0] = i2c_readByte(&eebus, 0); // read the byte with ack state
        bytes[1] = i2c_readByte(&eebus, 0); // ackstate should be 0 for continue
        bytes[2] = i2c_readByte(&eebus, 0); // 
        bytes[3] = i2c_readByte(&eebus, 1); // read the byte with no-ack state
        i2c_stop(&eebus); // stop the bus transaction
    
        print("Bytes x x x x\n", bytes[0], bytes[1], bytes[2], bytes[3]);
        // output is typically Bytes 00 b4 c4 04
    
        return 0;
    }
    
    
    
    The difference between what is shown in the code and the diagram below is that we read 4 total bytes.


    attachment.php?attachmentid=104698&d=1383235759
    720 x 213 - 12K
  • dgatelydgately Posts: 1,631
    edited 2013-10-31 10:40
    Thanks Jazzed!

    I updated my notes on i2c, as well!


    dgately
  • Bald-N-BlueBald-N-Blue Posts: 3
    edited 2013-10-31 12:59
    jazzed wrote: »
    The Learn/Protocol/libsimplei2c was originally designed to work like below.

    A reference for libsimplei2c is on-line here: https://propsideworkspace.googlecode.com/hg/Learn/Simple Libraries/Protocol/libsimplei2c/Documentation simplei2c Library.html
    The same file would be in your "up-to-date" SimpleIDE/Learn folder.

    Andy created wrappers for the simplei2c library and put them in the simpletools library.
    https://propsideworkspace.googlecode.com/hg/Learn/Simple Libraries/Utility/libsimpletools/Documentation simpletools Library.html

    /**
     * This is the main I2Creadbyte program file.
     */
    
    // This include causes libsimplei2c, libsimpletext, and others to be linked in SimpleIDE.
    #include "simpletools.h"
    
    int main(void)
    {
        int bytes[4]; // byte storage
        i2c eebus;    // declare an i2c device variable
    
        pause(1000);  // pause to ensure we can see output
    
        i2c_open(&eebus, 28, 29, 1); // open the device
    
        i2c_start(&eebus); // send the start sequence for addressing
        i2c_writeByte(&eebus, 0xA0); // send the EEPROM device ID as a write
        i2c_writeByte(&eebus, 0); // send the address upper byte
        i2c_writeByte(&eebus, 0); // send the address lower byte
    
        i2c_start(&eebus); // send the start sequence again for a read
        i2c_writeByte(&eebus, 0xA1); // send the ID as a read
        bytes[0] = i2c_readByte(&eebus, 0); // read the byte with ack state
        bytes[1] = i2c_readByte(&eebus, 0); // ackstate should be 0 for continue
        bytes[2] = i2c_readByte(&eebus, 0); // 
        bytes[3] = i2c_readByte(&eebus, 1); // read the byte with no-ack state
        i2c_stop(&eebus); // stop the bus transaction
    
        print("Bytes x x x x\n", bytes[0], bytes[1], bytes[2], bytes[3]);
        // output is typically Bytes 00 b4 c4 04
    
        return 0;
    }
    
    
    
    The difference between what is shown in the code and the diagram below is that we read 4 total bytes.


    attachment.php?attachmentid=104698&d=1383235759

    Jazzed, that was EXACTLY what I needed! I was delving into the references you linked, but I was way over-thinking the issue. I need to learn how the documentation on Doxygen works a bit more - what some of the syntax actually refers to. Example; HUBTEXT, i2c*, unsigned char *data, etc. These terms mean loads to those of you who firmly understand the language. For me who still has a lot to learn, well, it can be intimidating.

    But, lesson learned, instead of trying so hard to figure out the details, I should have just started writing some code and let the details come. I was actually on the right track after looking at your example, but you filled in the unknowns for me.

    So THANKS A LOT for the help! I know the whole Prop C tutorial is a work in progress, but they've done a superb job so far as I think Parallax does with all of their education products.

    Cheers!
  • Bald-N-BlueBald-N-Blue Posts: 3
    edited 2013-10-31 13:13
    dgately wrote: »
    I think you'll find that the documentation for compass3d library is a little old. I'm sure it's intended to be updated. If you look at the actual code for libcompass3d.c (In the Simple Libraries/Sensors/libcompass3d directory), you'll see that it actually uses 12c_newbus(clock,data,drive) to create an i2c bus storage variable:
    In libcompass3d.c
    
      i2c *bus = i2c_newbus(3, 2, 0);             // New I2C bus SCL=P3, SDA=P2
    
    i2c_newbus as documented in the simple tools library documentation:[INDENT]i2c* i2c_newbus    ([INDENT]
    int     sclpin,
    int     sdapin,
    int     scldrive [/INDENT]
    )[/INDENT]
        
    

    I hope this helps,
    dgately

    I suspected there were some changes made, I was using it as a way of feeling sorry for myself for not being able to figure out the main problem (sarcasm intended) :) The more I don't understand something, the more obsessed I get with trying to figure it out.

    More deep breaths -- less frustration -- more happiness . . .

    Thanks for the response, it was helpful.
    SRLM wrote: »
    I haven't used the Parallax supplied I2C drivers, but I'll take an opportunity for some self promotion here. I have a generic C++ driver that I've worked extensively on here that might prove useful. It comes with a number of higher level drivers for devices such as the PCF8523 RTC and others.

    Thanks, I looked at your driver quickly but I need to study it more in depth. I understand C++ even less than plain old C but I'm getting there. I can always fall back on spin but C/C++ seem a bit more "elegant" and besides, it's something new to learn.

    This whole "learn a new language" thing was initiated a few months ago when I broke (crushed) my left hand in an accident, and I've had a LOT of time at home looking for things to occupy my time. I'm still a few months away from going back to work so I have plenty of time to kill and lots of programming to master, er . . . ,learn :)

    Thanks for the responses, this is going to be a very educational forum!
  • jazzedjazzed Posts: 11,803
    edited 2013-10-31 14:00
    Jazzed, that was EXACTLY what I needed! I was delving into the references you linked, but I was way over-thinking the issue. I need to learn how the documentation on Doxygen works a bit more - what some of the syntax actually refers to. Example; HUBTEXT, i2c*, unsigned char *data, etc. These terms mean loads to those of you who firmly understand the language. For me who still has a lot to learn, well, it can be intimidating.
    Sorry if it's intimidating.

    HUBTEXT is an attribute applied to propeller-gcc functions that force code to be loaded into Propeller HUB RAM in case the program is built with an XMM model. HUB RAM code is faster.

    i2c is a type that is short hand for "struct i2c..." (i usually add _t to types, but parallax didn't think that simplified anything :)

    C is a heavily typed language that allows for building large programs with compile time error/warning checking, and "unsigned char *" is just one of several types.
Sign In or Register to comment.