Shop OBEX P1 Docs P2 Docs Learn Events
Propeller Chip runs a mostly unmodified Arduino program (video) - Page 3 — Parallax Forums

Propeller Chip runs a mostly unmodified Arduino program (video)

13

Comments

  • Martin_HMartin_H Posts: 4,051
    edited 2013-06-21 19:57
    I just noticed on the front page that this is listed as project of the week. That's flattering, although I wonder how did that happen?

    Is there a secret meeting of Parallax Illuminati in an undisclosed location in Rocklin?
  • jazzedjazzed Posts: 11,803
    edited 2013-06-22 09:21
    Martin_H wrote: »
    I just noticed on the front page that this is listed as project of the week. That's flattering, although I wonder how did that happen?

    Is there a secret meeting of Parallax Illuminati in an undisclosed location in Rocklin?
    Maybe Parallax is proud of what you have done with their products?
  • Martin_HMartin_H Posts: 4,051
    edited 2013-06-22 11:51
    jazzed wrote: »
    Maybe Parallax is proud of what you have done with their products?

    Probably so, but cloak and dagger intrigue sounds more dramatic.
  • jazzedjazzed Posts: 11,803
    edited 2013-06-22 13:56
    LOL maybe someone hacked the forum web page.
  • cavelambcavelamb Posts: 720
    edited 2013-06-24 22:58
    Do you think you might be able to do a presentation on the stat of the art?

    And how to set up GCC for this project?
  • Martin_HMartin_H Posts: 4,051
    edited 2013-06-25 05:14
    I'm glad you are interested and documentation for the project is coming. My current project timetable is to work on the Arduino Wire library this week. I will then use the I2C support to implement analogRead on the Propeller ASC and Prop BOE. At that point I'll have enough working that I'll deal with the packaging issue (single lib or several). I'm thinking that around mid-July I'll be far enough along to create a repository on code.google.com. That would be a natural point to start documenting the project. This is a fairly large project and unfortunately a leisure time activity (I have a strange definition of leisure).

    In the meantime if you want to play around with this code I would suggest downloading my servo sample above. You can adapt it to your project and learn how simple libraries are used with propgcc and SimpleIDE. Either Jazzed or I can answer any questions. Also, if there's a particular library you are looking for I can possibly move that ahead of some of the others.

    BTW the Arduino Wire library has been a challenging piece of code. I've used the I2C protocol, but never dove this deeply into it. I'm having to learn a fair bit about how it's implemented and used, so progress is slower than on areas where I'm more familiar.
  • David BetzDavid Betz Posts: 14,511
    edited 2013-06-25 05:54
    Martin_H wrote: »
    I'm glad you are interested and documentation for the project is coming. My current project timetable is to work on the Arduino Wire library this week. I will then use the I2C support to implement analogRead on the Propeller ASC and Prop BOE. At that point I'll have enough working that I'll deal with the packaging issue (single lib or several). I'm thinking that around mid-July I'll be far enough along to create a repository on code.google.com. That would be a natural point to start documenting the project. This is a fairly large project and unfortunately a leisure time activity (I have a strange definition of leisure).

    In the meantime if you want to play around with this code I would suggest downloading my servo sample above. You can adapt it to your project and learn how simple libraries are used with propgcc and SimpleIDE. Either Jazzed or I can answer any questions. Also, if there's a particular library you are looking for I can possibly move that ahead of some of the others.

    BTW the Arduino Wire library has been a challenging piece of code. I've used the I2C protocol, but never dove this deeply into it. I'm having to learn a fair bit about how it's implemented and used, so progress is slower than on areas where I'm more familiar.
    There is an i2c driver in PropGCC already although it doesn't handle clock stretching. It has the option of using either LMM code running in the same COG as the main program or a separate COG driver.
  • Martin_HMartin_H Posts: 4,051
    edited 2013-06-25 06:40
    David Betz wrote: »
    There is an i2c driver in PropGCC already although it doesn't handle clock stretching. It has the option of using either LMM code running in the same COG as the main program or a separate COG driver.

    Thanks for the heads up. I was using an I2C driver I cross compiled from Spin using spin2cpp, so I'll swap out to the native propgcc one. The Arduino Wire library uses something called the twi utility, so I'm trying to slip a prop class in to replace twi. The terminology and programming model used by Wire and twi doesn't quite line up with I2C as I've used it before. Most I2C libraries I've used are byte oriented, but Wire is buffer oriented and makes the I2C device look like an I/O stream.
  • David BetzDavid Betz Posts: 14,511
    edited 2013-06-25 06:44
    Martin_H wrote: »
    Thanks for the heads up. I was using an I2C driver I cross compiled from Spin using spin2cpp, so I'll swap out to the native propgcc one. The Arduino Wire library uses something called the twi utility, so I'm trying to slip a prop class in to replace twi. The terminology and programming model used by Wire and twi doesn't quite line up with I2C as I've used it before. Most I2C libraries I've used are byte oriented, but Wire is buffer oriented and makes the I2C device look like an I/O stream.
    Yes, that's true. I implemented a Wire-like API for PropGCC a while back but changed to the current API because it doesn't require a buffer in the i2c object. Also, at one point Parallax asked that I not try to pattern the PropGCC functions after Arduino functions. The Wire API is kind of nice in that you can do multiple writes to build up a single i2c command. I may add that support to the PropGCC i2c driver as well.
  • Invent-O-DocInvent-O-Doc Posts: 768
    edited 2013-06-25 09:58
    Prop2 could handle this task easily. There is plenty of RAM and you could use one COG for IO objects and an 'interrupt handler'. This software would fit well with a P2 Shield Compatible Scheme.
  • jazzedjazzed Posts: 11,803
    edited 2013-06-25 11:34
    So the Wire interface let's the device behave as an I2C slave? This is already possible with P8x32a ... Hippy wrote some PASM to do this a few years ago. The input transfer rates are pretty slow though (no SERDES ugh). Maybe a fast I2C slave challenge would be appropriate.

    We need the current simple_i2c PropellerGCC I2C master offering to expose the start, stop, and byte read/write functions. I'll be happy to liberate them.
  • David BetzDavid Betz Posts: 14,511
    edited 2013-06-25 12:05
    jazzed wrote: »
    So the Wire interface let's the device behave as an I2C slave? This is already possible with P8x32a ... Hippy wrote some PASM to do this a few years ago. The input transfer rates are pretty slow though (no SERDES ugh). Maybe a fast I2C slave challenge would be appropriate.

    We need the current simple_i2c PropellerGCC I2C master offering to expose the start, stop, and byte read/write functions. I'll be happy to liberate them.
    As I said in our private discussion, the simple and the COG driver are supposed to have the same interface. Please don't change one without changing the other. Also, having each of those functions as a separate driver call is likely to be too slow. I think it would be better to generalize the current interface a bit. The only thing really missing for master mode is to allow a command to be sent with two separate writes. This would allow one write for the address and the other for the data in an EEPROM write command for example. Otherwise, you have to copy the EEPROM data into a buffer to combine it with the address in order to build a command.
  • PublisonPublison Posts: 12,366
    edited 2013-06-25 14:14
    mindrobots wrote: »
    Wow! Well done!

    Yup, you got pictures, so it happened!!

    Rick,

    Thought I gave you a high 5 for making 3000 posts before. Guess it didn't take.

    Congrats.!

    Jim
  • Martin_HMartin_H Posts: 4,051
    edited 2013-07-09 18:36
    I've been trying to get analogRead working using the Propeller ASC. To do this I read through the Propeller ASC's data sheet and it said that it is using the MCP3208 ADC. So I got the object out of the OBEX and ran it through spin2cpp which resulted in these files:

    MCP3208.cpp
    MCP3208.h

    I then try to read the ADC as follow:
    // Assume Propeller ASC for now.
    static int cpin = 25;
    static int dpin = 26;
    static int spin = 27;
    
    static boolean adcStarted = false;
    static MCP3208 adc;
    
    int analogRead(uint8_t adcChannel)
    {
      if(!adcStarted)   
       adc.Start(dpin, cpin, spin, 255);
    
      return adc.In(adcChannel); \\ called with 0.
    }
    

    I'm using the AnalogInput Arduino sample but I keep getting the same value back from analogRead. Does anyone have a Spin sample using the on board ADC for the Propeller ASC? I figure that would help me verify as well as serve as a model for my C++ port.
  • Martin HodgeMartin Hodge Posts: 1,246
    edited 2013-07-10 11:40
    Martin H. Here's a package that I use to test each ASC. It should show you how to call the MCP3208 driver and use it. test.spin is the top-level file.
  • TinkersALotTinkersALot Posts: 535
    edited 2013-07-10 12:42
    Martin_H wrote: »
    I've been trying to get analogRead working using the Propeller ASC.

    @Martin_H -- I have been trying to get a reliable code set for the same purpose. I was going to study this one next:

    (by Jon McPhalen)
    http://obexclassic.parallax.com/objects/625/
  • Martin_HMartin_H Posts: 4,051
    edited 2013-07-10 13:17
    Martin H. Here's a package that I use to test each ASC. It should show you how to call the MCP3208 driver and use it. test.spin is the top-level file.

    Thanks, I will study this tonight.
  • laser-vectorlaser-vector Posts: 118
    edited 2013-07-10 13:33
    Can this fully utilize the 32bit multi-core architecture? or are there limitations??
  • Martin_HMartin_H Posts: 4,051
    edited 2013-07-10 15:15
    Can this fully utilize the 32bit multi-core architecture? or are there limitations??

    Yes it can. If you read the source of the servo library you'll see that I use a cog to tend the servos while the primary cog runs the main loop. I'm also writing code library to tend the ADC in the background. The challenge will be using too many cogs for library functions and not leaving enough for end users. At some point I may see if I can multiplex one cog for several functions. But I'm still fairly early in development.
  • Martin_HMartin_H Posts: 4,051
    edited 2013-07-11 19:36
    Good news, bad news.

    The good news is that I can use Martin's Spin ADC sample with the Propeller ASC to read the ADC. His code also matches what I was already doing, so I didn't have any major problems in my code.

    The bad news is that if I translate his code from Spin to C++using spin2cpp, the code runs, but doesn't work.

    Since it is such a small test program with all the meat in the MCP3208 class, the translation of that class from Spin to C++ must have failed. Most of that classes innards are in the block of hex that is the assembler, so lots of luck debugging it.
  • TinkersALotTinkersALot Posts: 535
    edited 2013-07-14 12:09
    #include "simpletools.h"                     // Include simpletools header
    
    
    const char   SE_0  = 0x08;              // ch0  single ended  
    const char   SE_1  = 0x09;
    const char   SE_2  = 0x0A;
    const char   SE_3  = 0x0B;
    const char   SE_4  = 0x0C;
    const char   SE_5  = 0x0D;
    const char   SE_6  = 0x0E;
    const char   SE_7  = 0x0F;
    
    const char   D_01  = 0x00;             // 0+/1-  differential 
    const char   D_10  = 0x01;             // 1+/0-
    const char   D_23  = 0x02;             // 2+/3-
    const char   D_32  = 0x03;             // 3+/2- 
    const char   D_45  = 0x04;             // 4+/5-
    const char   D_54  = 0x05;             // 5+/4-
    const char   D_67  = 0x06;             // 6+/7-
    const char   D_76  = 0x07;             // 7+/6-  
      
    volatile int  cs;
    volatile int  clk;
    volatile int  dio;
    
    
    void make_pin_output( int pin )
    {
      DIRA |= ( 1 << pin );
    }
    
    
    void make_pin_input( int pin )
    {
      DIRA &= ~( 1 << pin );
    }
    
    
    void make_pin_high( int pin )
    {
      DIRA |= ( 1 << pin );
      OUTA |= ( 1 << pin );
    }
    
    
    void make_pin_low( int pin )
    {
      DIRA |=  ( 1 << pin );
      OUTA &= ~( 1 << pin );
    }
    
    
    int read_pin_value( int pin )
    {
      DIRA &= ~( 1 << pin );
      return( INA & ( 1 << pin ) ) ? 1 : 0;
    }
    
    
    int write_state_to_pin( int pin, int state )
    {
      DIRA |= ( 1 << pin );
    
      if ( state )
        OUTA |= ( 1 << pin );
      else
        OUTA &= ~( 1 << pin );
    
      return( ( OUTA & ( 1 << pin ) ) != 0 );
    }
    
    void delay( int us )
    {
      int count = us * ( CLKFREQ / 1000000 );
      if ( count < 400 )
        count = 400;
    
      waitcnt( count + CNT );
    }
    
    
    void init( int cspin, int clkpin, int diopin )
    {
      cs  = cspin;
      clk = clkpin;
      dio = diopin;
    
      make_pin_output( cspin );
      make_pin_high( cspin );
    
      make_pin_output( clkpin );
      make_pin_low( clkpin );
    }
    
    
    void finalize()
    {
      make_pin_input( cs );
      make_pin_input( clk );
      make_pin_input( dio );
    }
    
    
    int do_adc_cmd( int mux ) 
    {
      int level = 0;
      int counter;
    
      // Read MCP3208 channel
      // -- mux is encoded mux bits for channel/mode
    
      make_pin_low( cs );                                           // activate adc
      make_pin_output( dio );                                       // dio is output
    
      // output mux bits, MSBFIRST
      
      for ( counter = 0; counter < 5; counter++ )
      { // send mux bits
        write_state_to_pin( dio, mux & 0x10 );
        delay( 10 );
        mux <<= 1;
        make_pin_high( clk );                                       // clock the bit
        delay( 10 );
        make_pin_low( clk );
      }
    
      // input data bits, MSBPOST
      
      make_pin_input( dio );                                        // dio is input
    
      level = 0;                                                    // clear work var  
    
      for ( counter = 0; counter < 13; counter++ )
      { // null + 12 data bits
        make_pin_high( clk );                                       // clock the bit
        delay( 10 );
        make_pin_low( clk );
    
        delay( 10 );
        level = ( level << 1 ) | read_pin_value( dio );             // input data bit
      }
    
      make_pin_high( cs );                                          // de-activate adc
      
      return( level & 0x0fff );
    }
    
    // -- ch is channel, 0 to 7
    // -- mode is 0 for single-ended, 1 for differential
    int read_adc_channel( int ch_mode )
    {
      long adc_cmd;
    
      adc_cmd = 0x10 | ch_mode ;  // create mux bits
    
      return do_adc_cmd( adc_cmd ); 
    }
    
    
    int scale_adc_value( int raw, int minOut, int maxOut )
    {
      if ( ( raw > maxOut ) || ( raw < minOut ) )
        raw = 0;
    
      if ( minOut < maxOut )
      {
        return ( ( raw * ( maxOut - minOut ) ) / 4095 ) + minOut;
      }
      else
        return raw;    
    }
    
    
    int main()                                    // main function
    {
      delay( 2000 );
    
      int buttonVoltage;
    
      printf( "starting\n" );
    
      init( 27, 25, 26 );
    
      do
      {
        pause( 1000 ); 
    
        buttonVoltage = read_adc_channel( SE_0 );
        buttonVoltage = scale_adc_value( buttonVoltage, 0, 4096 );
    
        printf( "button = %d\n", buttonVoltage );
      }
      while( 1 );
    }
    
    
    

    I get this to work with the Prop ASC board to read channel zero
  • Martin_HMartin_H Posts: 4,051
    edited 2013-07-14 12:45
    Thanks so much. I'll try integrate that tonight.
  • TinkersALotTinkersALot Posts: 535
    edited 2013-07-14 13:17
    I have been trying to get an DF Robots LCD Keypad Shield to work with the Prop ASC board. (this is supposed to be compatible with the arduino LCD driver). Here is what I have found out : If I try to use the LCD class I run out of memory in the prop. So, I have a "stripped down" version of the LCD class that "fits" -- but I have not seen it work yet -- I am wondering if the ASC board voltages on the arduino bus is capable of driving the pins on the LCD (?). So far the LCD board is just jibberish (if anything). But it is encouraging that the buttons on the LCD Keypad can be read using the snip above.

    As I have been following your efforts here, I am glad to try to help out some too.

    cheers!
  • whickerwhicker Posts: 749
    edited 2013-07-14 14:10
    TinkersALot:

    why is this part this way?
      if ( ( raw > maxOut ) || ( raw < minOut ) )
        raw = 0;
    

    wouldn't it be,
    if (raw > 4095) raw=4095;
    if (raw < 0) raw=0;
    

    or is this some weird behavior you're trying to duplicate?
  • TinkersALotTinkersALot Posts: 535
    edited 2013-07-14 23:20
    the thinking behind that logic is that if the value is outside of the defined bounds, then set it to a known (safe?) value.
  • whickerwhicker Posts: 749
    edited 2013-07-15 00:42
    the thinking behind that logic is that if the value is outside of the defined bounds, then set it to a known (safe?) value.
    Well, connect up a potentiometer, and make it so that the scaling is between 10 and 20, and see how it performs. probably not what you want.
    with the present code you'll have a very sensitive tiny section with which the value goes from 10 to 20, otherwise it'll be stuck at 10 for most of the range (99.7% of it).
  • LawsonLawson Posts: 870
    edited 2013-07-15 18:07
    There's an Arduino contest running over at Instructables right now. I think this would apply :) (Though with 123 entries already, this might get lost in the crush.)

    Lawson
  • Martin_HMartin_H Posts: 4,051
    edited 2013-07-20 10:37
    Here's a new version of my libPropelleruino being used with the Arduino knob sample. To do that I'm using Martin Hodge's Propeller ASC coupled with TinkersALot ADC code and my Servo library. I took TinkersALot's code and Arduino-fied it to use pinMode, digitalRead, digitalWrite, and delayMicroseconds. In the process I introduced a rather insidious bug that broke his code. It turns out his delay function has a floor of 400 microseconds, while my Arduino version does not. But when I added that floor I broke my Servo library.

    I'm embarrassed to say it took me all morning to figure out the conflict because the symptom wasn't obvious. Everything sort of worked but for certain values pulseOut (which uses delayMicroseconds) would freeze and lock the cog. Anyway here's the new code:

    AnalogInput.zip

    Here's a video of it in action:
  • WhitWhit Posts: 4,191
    edited 2013-07-20 20:05
    Martin - Amazing work on this. I am looking to pick up a Propeller ASC+ and start playing too.
  • TorTor Posts: 2,010
    edited 2013-07-21 06:23
    Re. the necessity of adding #include for the header that Arduino includes automatically
    This may or may not be useful, but gcc (and I assume propggc, but hasn't tested this) has an option '-include' for including a file which hasn't been included with an explicit #include directive in the source code. Example (Hello World with missing stdio.h):
    $ gcc -Wall -o hello hello.c
    hello.c: In function 'main':
    hello.c:4:2: warning: implicit declaration of function 'printf' [-Wimplicit-function-declaration]
    hello.c:4:2: warning: incompatible implicit declaration of built-in function 'printf' [enabled by default]
    $ gcc -include stdio.h -Wall -o hello hello.c
    $ ./hello
     Hello, World
    

    -Tor
Sign In or Register to comment.