Shop OBEX P1 Docs P2 Docs Learn Events
Spin and C interacting? — Parallax Forums

Spin and C interacting?

seanpaulseanpaul Posts: 5
edited 2011-04-13 18:49 in Propeller 1
I have a robot that is controlled by the propellor chip. I have the location algorithm written in C and the movements of the robot are written in the spin language. Is it possible to call C functions in the spin language or is it necessary to write the entire program in either spin or C?

Comments

  • Heater.Heater. Posts: 21,230
    edited 2011-04-09 20:41
    There is no C compiler available that allows calling from Spin to C or vice versa as far as I know.

    What one would do is have, for example, a Spin program running on one COG. Meanwhile a C program is being run by another COG. All communications between these two happen through a shared space in HUB RAM. Perhaps with a LONG indicating some command and a buffer to hold parameters and return values. The C code would be polling the command LONG until a valid command is set there by the Spin. The C code would then perform the work indicated by the command and write the results back to the shared HUB space.

    This is basically how Spin and PASM code interacts on the Prop anyway.

    This is easy to do with GCC and the Zog interpreter. No idea how easy it is with Catalina C.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-04-10 02:25
    You might be on to something really clever here. This is all new and cutting-edge, of course. But I have spend a day coding in C on the propeller, and one thing I have been doing is taking Catalina and shutting down cogs one at a time and replacing them with my own cog drivers. Shut down the serial port, shut down the keyboard, shut down the two video cogs, and the mouse. Then load in Kye's single cog video driver - 160x120 in 64 colors. Then unload that and reload with a grayscale 320x240.

    That is fairly minimalist, but it is C running in two cogs.

    Spin can run in another cog. So you are only using 3 cogs here. More can be added of course.

    What you could do is define a parameter array in Spin. Find the location of that parameter array, and put that location right at the top of memory in $7FFC. Now you can use C to read this pointer, and get all the parameters from Spin. The parameter list could be as long as you like.

    No-one has done this yet, but I think it is entirely possible, and it would be a cool hybrid system!
  • Heater.Heater. Posts: 21,230
    edited 2011-04-10 02:39
    Dr_A,
    No-one has done this yet, but I think it is entirely possible, and it would be a cool hybrid system!

    Yes they have. Ever since the beginning Zog has been running Spin and GCC compiled C code at the same time passing data between the two as described.

    Now David and Jazzed have carried forward.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-04-10 04:03
    Really?

    I must say, that is pretty cool! Chalk one up for Zog.
  • Dave HeinDave Hein Posts: 6,347
    edited 2011-04-10 04:48
    seanpaul,

    I have a utility called cspin that converts C code into Spin. I prefer writing in C, so I write code in C first and then convert it to Spin to run on the Prop. cspin has quite a few limitations, but I find it useful for me. Let me know if you want to convert your C code to Spin.

    Dave
  • seanpaulseanpaul Posts: 5
    edited 2011-04-13 01:30
    Thanks for the info everyone. I'm going to first try to free up a cog and then get the two to interact with how Heater suggested. Dave how would I get access to cspin? I would love to try that out, too.
  • RossHRossH Posts: 5,547
    edited 2011-04-13 02:38
    Hi seanpaul,

    Sorry not to reply sooner. You can easily use the Catalina RESERVE_COG capability to run any SPIN function in parallel with a Catalina C program. Just put your SPIN function inside a Catalina_Reserved_Cog.spin wrapper (you'll find this wrapper in the Catalina\target directory).

    Below is a working example of running a Spin function that toggles the VGA LED on the C3 at 1Hz. To compile it to run alongside a C program, I used the following command:
    catalina -lc hello_world.c -D RESERVE_COG -D C3
    
    Here is the actual SPIN program:
    {{
    ''=============================================================================
    '' Catalina_Reserved_Cog - Reserve a cog during the load process.
    ''
    '' This code is intended just as an example - it is used to show how a cog
    '' can be reserved during the process of loading and starting a Catalina C
    '' program. In this example, we start a SPIN interpreter in the reserved
    '' cog and use it to execute a SPIN function.
    ''
    ''=============================================================================
    }}
    CON
    
    TOGGLE_PIN  = 15                 ' I/O Pin to toggle (VGA LED on C3)
    
    TOGGLE_TIME = common#CLOCKFREQ/2 ' set/reset the pin at 1Hz
    
    BYTE_SIZE   = 100                ' Size (bytes) to reserve for the SPIN stack
    
    OBJ
       Common : "Catalina_Common"    ' need this to identify the RESERVED_COG
    
    '
    ' This demo SPIN function just toggles a pin forever.
    '
    PUB Spin_Function(Pin, Time)
    
       dira[Pin]~~
    
       repeat
         outa[Pin]~
         waitcnt(cnt + Time)
         outa[Pin]~~
         waitcnt(cnt + Time)
    
    '
    ' This function is called during Catalina startup. 
    ' In this example we use it to start a SPIN interpreter.
    '
    PUB Start (Block_Ptr) : ok | cog
    
      ' start the SPIN function in the RESERVED Cog
      coginit (Common#RESERVED_COG, Spin_Function(TOGGLE_PIN, TOGGLE_TIME), Block_Ptr)
    
      ok := TRUE
    
    Note that you can pass parameters to the SPIN function on startup, or you can communicate via Hub variables (as described by Heater).

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-04-13 03:53
    Hi Ross,

    That could open up some interesting possibilities. Can you explain a bit more how memory is allocated? I think Catalina starts from the top and works down, with the stack taking up whatever is needed.

    Would Spin start from the bottom up?
  • Heater.Heater. Posts: 21,230
    edited 2011-04-13 04:02
    By some, possibly lucky, happenstance the Spin stack grows from bottom to top. Contrary to most other stacks in the world. This was quite convenient for running Spin and C under Zog.
  • RossHRossH Posts: 5,547
    edited 2011-04-13 04:28
    Dr_Acula wrote: »
    Hi Ross,

    That could open up some interesting possibilities. Can you explain a bit more how memory is allocated? I think Catalina starts from the top and works down, with the stack taking up whatever is needed.

    Would Spin start from the bottom up?

    Hi Dr_A,

    The reason this works is that the SPIN function is started with its own dedicated stack space (the Block_Ptr parameter, which is initialied by the Catalina startup code to point to a block of BYTE_SIZE bytes). This space is allocated above (and separate to) the Catalina stack space.

    I don't really care how SPIN uses this space - up down or sideways! But in fact, since you only pass a pointer to the start of it, it must use it bottom-up. And, in the words of the SPIN reference manual, this pointer ...
    ... is a pointer to memory, such as a long array, reserved for stack space for the affected cog. The affected cog uses this space to store temporary data during further calls and expression evaluations. If insufficient space is allocated, either the application will fail to run or it will run with strange results.
    So make sure your BYTE_SIZE is large enough for the SPIN function (and divisible by 4)!

    Oh - and be aware that this technique will only work for Catalina LMM programs (i.e. not XMM programs) - PASM programs can be easily started by a Catalina XMM program (as you are doing with your cogjects) but a bit more frigging about is required to invoke SPIN programs. This is because XMM programs normally assume they can use all of the Hub space for local variables and stack, leaving no space for SPIN code (which must reside in Hub RAM to be executed by the SPIN interpreter). If there were a demand for it I could make this work as well, but we are really getting into the realms where the total number of potential users of such functionality is in the single digits - and I'm talking binary digits here!

    Ross.
  • Dave HeinDave Hein Posts: 6,347
    edited 2011-04-13 09:28
    seanpaul wrote: »
    Dave how would I get access to cspin? I would love to try that out, too.
    seanpaul,

    The latest version of cspin is available at http://forums.parallax.com/showthread.php?119342-CSPIN-A-C-to-Spin-Converter&p=991970#post991970 . Let me know if you have any problems using it. I would be happy to do the conversion if you want to send me your C code.

    Dave
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-04-13 16:27
    Thanks Ross. Lots of cunning things going on in the background, but I agree, no point in coding something more that is really clever if hardly anyone is going to use it.

    Having got all the essential stuff working for the GUI (keyboard, video), I'm finding the actual coding in C is so much easier than in Spin. Never have to worry about running out of ram, it is easy to put data either in hub or external and to move it back and forth, and any time I want to do something a bit clever, I do a quick search on Google and up comes some useful C code from somewhere.

    I guess I'm a convert to C now, and as such, see less need for such interaction, so no need to try to get it working in XMM for like you say, a binary number of potential users :)

    Looks like there are already several very good solutions to this problem as posted above - kudos to all the authors involved!
  • David BetzDavid Betz Posts: 14,519
    edited 2011-04-13 18:49
    Heater. wrote: »
    Dr_A,



    Yes they have. Ever since the beginning Zog has been running Spin and GCC compiled C code at the same time passing data between the two as described.

    Now David and Jazzed have carried forward.

    Well, I'm not sure how far forward we've gotten. I have runtime code that allows a COG to be loaded from an array of C initialized data. That could just as easily have been data read from an SD card. It all works pretty well and results in an environment that is fairly easy to work with. The C startup code doesn't load any drivers at all. It relies on the C code to load them itself. One advantage on the C3 though is that the driver that handles the cache also handles the SD card so it is already loaded when the C code starts. The C code only has to load serial, keyboard, or TV/VGA drivers as needed.

    Unfortunately, I'm pretty much at a dead end with ZOG. I've come to the conclusion that it can't be made to work well with data in hub memory without switching to little-endian mode and the ZPU GCC compiler doesn't really support that yet. It's not clear it will ever support that. :-(
Sign In or Register to comment.