Shop OBEX P1 Docs P2 Docs Learn Events
Help with include files — Parallax Forums

Help with include files

mynet43mynet43 Posts: 644
edited 2008-08-07 12:51 in Propeller 1
I have a program that includes two files, like this example:

OBJ
  fp  : "Float32"
  cal : "Calc"




Both the main program and the included program (Calc) need to use the Float32 routines for their processing.

I haven't been able to figure out how to make Float32 available for use by the Calc routine.

If I 'include' it in Calc, the program gets too big because it loads two copies of it [noparse]:([/noparse]

I tried to pass the address as a calling parameter like: cal.init(@fp). But this didn't work either.

Can someone please give me an example of how to solve this problem?

Thanks for your help.

Jim

Comments

  • hippyhippy Posts: 1,981
    edited 2007-10-01 17:49
    mynet43 said...
    If I 'include' it in Calc, the program gets too big because it loads two copies of it [noparse]:([/noparse]

    It shouldn't. There may be a slight increase in size but an entire copy of the object is not included.
  • mynet43mynet43 Posts: 644
    edited 2007-10-01 18:02
    Hippy, you were right, I got it to load without a problem.

    But, I still have a problem [noparse]:)[/noparse]

    Note the 'return' in the code shown below:

    VAR
    ' variables for Kalman Filter calculations
      long estp
      long phi[noparse][[/noparse]9]
    
    OBJ
      fp  : "Float32"
    
    PUB init_Kalman(altitude, delta_t, est_ptr, gain_ptr) | i
    
      repeat i from 0 to 2
        long[noparse][[/noparse]est_ptr+i]  := 0.0  ' zero out estimate vectors
        estp[i] := 0.0
    
      repeat i from 0 to 8
          phi[i]   := 0.0
    
      long[noparse][[/noparse]gain_ptr]   := 0.65            ' Jim's values
      long[noparse][[/noparse]gain_ptr+1] := 0.70            ' these seem to work for powered flight
      long[noparse][[/noparse]gain_ptr+2] := 0.75            ' try with other data sets
    
      long[noparse][[/noparse]gain_ptr+3] := 0.03090014      ' calculated values
      long[noparse][[/noparse]gain_ptr+4] := 0.03080442      ' use for unpowered flight
      long[noparse][[/noparse]gain_ptr+5] := 0.01536372
    
      long[noparse][[/noparse]est_ptr]  := altitude ' initialize the altitide part of solution vector
    
      phi[noparse][[/noparse]0]  := phi  := phi[noparse][[/noparse]8]  := 1.0
    
      phi  := phi := delta_t                      ' init phi[noparse][[/noparse] ] 1 & 5 = dt
    return
      phi  := fp.FMul(fp.FMul(0.5,delta_t),delta_t)  ' 2 = dt*dt/2 floating
    [/i][/i]
    



    If I move the return statement to after the last line, it never returns. This indicates that it's getting lost in the fp module.

    The same line of code works perfectly if I put it in the main program.

    Any thoughts?
  • mynet43mynet43 Posts: 644
    edited 2007-10-01 18:07
    Never mind [noparse]:([/noparse]

    I figured it out...

    You have to call fp.start in the second one too, duh...

    Thanks
  • deSilvadeSilva Posts: 2,967
    edited 2007-10-01 18:23
    mynet43 said...
    You have to call fp.start in the second one too, duh...
    No, you don't "have to"...
    But it would be the simple solution, however it costs you another COG!
    You have now 2 COGs loaded with the Float32 machine code, NOT working in parallel.

    There are some threads discussing this situation in detail, and I posted a modification for Float32 somewhere, shifting some variables from VAR to DAT... Maybe I can find it.

    Note that this a proplem of many driver authors: Shall they prepare their drivers for multiple use in parallel COGs, or shall they support the more frequent need of use from different objects....
  • Ken PetersonKen Peterson Posts: 806
    edited 2007-10-01 18:33
    This trade-off is made often enough that a tutorial about VAR vs. DAT would be helpful to many in our forum. I myself have modified a few objects to move everything to DAT so they can be shared. I think the TV object should be that way by default as it would be more common to access the display from many points within your code than it would be to have multiple displays.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    The more I know, the more I know I don't know.· Is this what they call Wisdom?
  • mynet43mynet43 Posts: 644
    edited 2007-10-01 18:39
    deSilva,

    Thanks for the reply. Very good point! I really don't want to start another COG here, I know there's a better way!

    If you can find the method for doing this, I'd really appreciate it!

    If we can fix this, I'd like to coordinate it with Cam Thompson, the author, so we can fix the basic module.

    Thanks again,

    Jim
  • mynet43mynet43 Posts: 644
    edited 2007-10-01 18:57
    deSilva,

    I came across one of your posts from a while back:

    [noparse][[/noparse]quote]
    I complained some months ago about the tricky co-operation between Float32 (1.3) and FloatString.
    Using Float32 from your main program and from Float32 needs patching Float32 (put the VAR cells into DAT) and you have to know what you are doing!) It is nonsense to start another Float32-COG just for the needs of FloatString.

    This seems still to be an issue.

    It's not Cam's fault; it's a design flaw with SPIN.

    P.S.: Efficient multi COG Math32 is in fact very tricky as it needs so much overhead within a SPIN programm that the speed-up is mainly lost; there seems to be little interest in Floating Point Math here in the forum. Should it be otherwise, I am interested in disussing improvements there (e.g. chain computations avoiding the intermediate packing and unpacking, complex operations or matrix multiplication,... ) See also Micromega's FPU which for twice the price is not faster than a COG but has much more program space in its ROM....


    This seems to refer to a way to do it, but no details.

    Also, I'd be very interested in discussing the improvements you mentioned to the floating point routines. I'm familiar with the assembly code and I'd like to see a better way than constantly packing and unpacking the numbers. I'd also like to see matrix math. These changes shouldn't be difficult. Let me know what you think.

    Jim
  • deSilvadeSilva Posts: 2,967
    edited 2007-10-01 19:01
    I should not call it a "Fix" smile.gif
    There is a "communication block" near the beginning; just change the VAR into a DAT
    'Original
    VAR
      long  cog
      long  command, cmdReturn
    
    ' for "Single COG action":
    DAT
      long  cog
      long  command, cmdReturn
    



    I explained at another place that I used 6 COGs loaded with FLOAT32 to work in parallel.
    It was not that easy, as a call to FLOAT32 blocks the calling routine.
    So although I tried to utilize the Multi-COG feature, it was not possible without some further modifications (removing the wait) which made this modified Float32deSILVA quite tricky to use.....
  • mynet43mynet43 Posts: 644
    edited 2007-10-01 20:00
    deSilva,

    I tried your change but it didn't work.

    I loaded Float32 and made the change you suggested: change VAR to DAT. And then saved it.

    When I compiled the main program, I got the error message: "Undefined symbol." and the word "cog" was highlighted in the new DAT block.

    What am I doing wrong?

    Jim

    Also, when this works, do I still call fp.start in the second object? If I do this, won't it still load another cog?
  • deSilvadeSilva Posts: 2,967
    edited 2007-10-01 20:04
    So stupid of me !!!

    DAT has a different syntax..It should read:
    DAT
      cog  LONG 0
      command LONG 0
      cmdReturn  LONG 0
    



    To your question. No you need not but it won't do any harm... Have a look at the Float32 code:
    PUB start : okay
    
    '' start floating point engine in a new cog
    '' returns false if no cog available
    
      stop
      okay := cog := cognew(@getCommand, @command) + 1
    
    PUB stop
    
    '' stop floating point engine and release the cog
    
      if cog
        cogstop(cog~ - 1)
      command~
    



    You understand?
  • mynet43mynet43 Posts: 644
    edited 2007-10-01 20:13
    I knew that [noparse]:([/noparse] I should have spotted it.

    It works fine now.

    Is there an easy way to tell that I've loaded fewer cogs than I had before?
  • deSilvadeSilva Posts: 2,967
    edited 2007-10-01 20:19
    You can measure the current the Prop draws? Just kidding!

    I THINK, the COG logic will always allocated the COG with the lowest ID...

    So you could check:
    
    .....
    id := COGNEW(@aCheck,0)
    
    
    DAT
    ORG 0
    aCheck  cogid   :id
            cogstop :id
    :id     res    1
    

    Post Edited (deSilva) : 10/1/2007 8:23:59 PM GMT
  • mynet43mynet43 Posts: 644
    edited 2007-10-01 21:39
    That's a great idea!

    Let's see, I cut the power trace to the prop, insert a 1 ohm resistor, measure the voltage at each end of the resistor with two of my adc ports, take the difference and that's my current, right? Then all I have to do is run the program both ways to prove that I've saved a cog. Ingenious!

    Just kidding!

    Thanks,

    Jim
  • mynet43mynet43 Posts: 644
    edited 2007-10-01 22:43
    Final confirmation:

    I opened a new cog after opening Float32 in the second object.

    I printed out the new cog number.

    With the original Float32, the new cog was 5.

    With the modified Fload32 (DAT instead of VAR), the new cog was 4.

    It works!
  • Fred HawkinsFred Hawkins Posts: 997
    edited 2007-10-01 23:34
    Maybe you should rename this thread to highlight this fix. (Is that possible?)
  • mynet43mynet43 Posts: 644
    edited 2007-10-02 02:10
    Fred,

    This isn't really the fix I'd like to see. I'd rather have it controlled.

    Tomorrow I'll send an email to Cam, the author, to see if he'll agree to incorporate these changes into a permanent version upgrade. Then we can all track any other changes he makes.

    I'll try to post progress...

    Jim
  • camtcamt Posts: 45
    edited 2007-10-02 16:01
    I'm not sure if changing the Float32 communication block from VAR to DAT is the right 'general' solution for the Float32 library object.

    The Float32 cog waits for the command variable to be non-zero, then executes the code for the operation specified, returns the result in the cmdReturn variable, and clears the command variable. If command is defined by DAT, and multiple COGs are calling the Float32 routines, and they're running simultaneously, there will be collisions with the shared command variable. I'm guessing that in the multiple cog examples discussed above, one cog was calling another, which did its thing before returning to the caller, so the contention was avoided. But if the cogs were operating independently, things could fall apart. Putting mutual exclusion protection in the calling mechanism would add excessive overhead. It would be better to put it around blocks of code in the application (e.g. a complete calculation) rather than at the Float32 call level.

    I'm not sure what the right solution is. As it sits now, multiple cog access works for the casual user, at the expense of extra cogs. Power users can change VAR to DAT if they know their application doesn't have a problem with simultaneous access, or they can change it and also add some mutual exclusion code. By making the changes, the power user is acknowledging responsibility for the mutual exclusion issues.

    Cam

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cam Thompson
    Micromega Corporation
  • deSilvadeSilva Posts: 2,967
    edited 2007-10-02 16:38
    As there is no general work-around of this shortcoming of SPIN - I pointed this clearly out! - I accept Cam's statement.

    As I also said, there were more changes necessary to use 6 COGs with Float32 smile.gif

    The main application wil lremain to call Float32 from different objects from ONE COG.
    This is already the case when you use FloatString and ask yourself: Why should I load all the code for FloatMath when I have a fast COG with Float32 waiting eagerly for any operation?

    You edit the OBJ in FloatString, and - bingo!

    Maybe a short piece of explanation will already help?
  • mynet43mynet43 Posts: 644
    edited 2007-10-02 17:09
    There's been a lot of good information in this post.

    Does anyone know how to summarize the results and post them somewhere that will save other people from this same problem?

    I agree with Cam (and deSilva).

    For now, I'll continue to use a modified, uncontrolled version of Float32[noparse]:([/noparse]

    I wish there were a better way...

    Jim
  • Ken PetersonKen Peterson Posts: 806
    edited 2007-10-03 02:27
    @mynet43: One of the disadvantages of this forum is that the knowledge can not be easily boiled down to a quick reference. It has to be searched and the process can be painstaking.

    if someone were dedicated to compiling such information into a reference, we could request that a particular thread by summarized in the reference. There are stickies, but even that can get out of hand.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    The more I know, the more I know I don't know.· Is this what they call Wisdom?
  • Paul BakerPaul Baker Posts: 6,351
    edited 2007-10-03 05:07
    Graham has done a good job with his good thread index. If someone wants to compile a FAQ and post it, I will gladly include a link to the thread in the stickies.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Paul Baker
    Propeller Applications Engineer

    Parallax, Inc.
  • mynet43mynet43 Posts: 644
    edited 2007-10-03 13:53
    I'll try to write up something. I'll run it by deSilva and then submit is.

    Thanks
  • Fred HawkinsFred Hawkins Posts: 997
    edited 2007-10-03 18:33
    I'd like to see a monthly summary -- sort of a newsletter. That seems to be a managable task. Spelunkers could even go back to the beginning and piecemeal build up the prop's forum history, a month at a time.
  • deSilvadeSilva Posts: 2,967
    edited 2007-10-03 22:24
    Something like "The Monthly Observer"...
    September: deSilva posted his 1,000th article smile.gif
  • mynet43mynet43 Posts: 644
    edited 2007-10-10 00:45
    I've prepared two FAQ's that summarize the issues discussed and proposed solutions in this thread.

    They're included as attachments below.


    The first FAQ is:

    How do I use an included object in more than one object?

    The second is:

    How do I prevent an included object from using multiple COGs for the same code?

    Phil said he would include a link to this thread in Graham's thread index.

    Thanks for all the help and great ideas.

    Jim
  • Paul BakerPaul Baker Posts: 6,351
    edited 2007-10-10 17:28
    This thread has been linked to in the stickies under FAQ, once a critical mass of FAQ has been assembled they should be coalated into a single document and placed in a new and seperate thread. When that occurs I will switch the link to the new thread.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Paul Baker
    Propeller Applications Engineer

    Parallax, Inc.
  • jazzedjazzed Posts: 11,803
    edited 2008-08-07 02:44
    FAQ: Why doesn't Propeller use interrupts ?

    Among other answers: The Propeller design doesn't use interrupts because they expect you to use polling via a COG to get events. If you need low latency, you can use the waitpne or waitpeq commands within a COG to monitor the designated interrupt input (kind of a waste of a COG). If you don't need low latency, your interrupt COG could do other things and periodically run the pin monitor. The other reason to use an interrupt for multi-tasking ticks is not of much interest in the Propeller community, but this can be done too with some special coding ....

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • hippyhippy Posts: 1,981
    edited 2008-08-07 12:51
    I added a page on the Wiki to detail Interrupts. Everyone is welcome to edit and add to that ...

    propeller.wikispaces.com/Interrupts
Sign In or Register to comment.