Shop OBEX P1 Docs P2 Docs Learn Events
Accessing an objects variables from another object? — Parallax Forums

Accessing an objects variables from another object?

Rick_HRick_H Posts: 116
edited 2010-10-02 16:32 in Propeller 1
How do I access an objects variables from another object without making a function to pass them?

Speed is critical but I would like to use objects for readability and ease of modification. I tried obj.var[1] but it expects a method not a variable.

Comments

  • max72max72 Posts: 1,155
    edited 2010-10-02 03:12
    You could create a pub function in the object:
    pub variablereturn
      return variablename
    

    Otherwise you could get a base memory address from the object the first time, and access the memory position from the main object.
    I'm not sure it speeds up things...

    Massimo
  • Rick_HRick_H Posts: 116
    edited 2010-10-02 03:27
    that's what I am doing right now, but I have to pass a 6 element array and then process the data, it takes way to long.

    In the object I have a function that just returns the data based on the index number I pass to it.
    pub GetData(idx) : data
    return Var[idx]
    
  • kuronekokuroneko Posts: 3,623
    edited 2010-10-02 03:49
    In case of the array, why don't you just return its address (return @a[0]) and access it "upstairs" as long[address][index]?
  • Rick_HRick_H Posts: 116
    edited 2010-10-02 04:52
    ya just tried longmove and it works but its still too slow.
  • max72max72 Posts: 1,155
    edited 2010-10-02 05:28
    Kuroneko's solution is probably the best. You can get the base address at startup, and access the array directly (the address will no change).

    Other ideas:

    If you need a little bit more speed use a faster xtal (6 of 6.25 MHz work, just check decoupling capacitor discussions).

    Otherwise check propbasic (it compiles to PASM), or Catalina (C).

    Spinwise, if speed is so important check (with cnt) speed execution and experiment. For instance -variable is faster than variable:=-variable
    You might find bottlenecks in other parts of your code....

    Spin is much slower than pasm. If you need more speed use pasm, alone, or as an embedded code.
    In this case there are at least 2 options. SpinLMM object, and Beau's embedded pasm object.

    Massimo
  • Rick_HRick_H Posts: 116
    edited 2010-10-02 08:05
    ya, I am mostly using asm now, but I found my problem. It wasn't spin moving the data it was my lcd object running on the first cog, made it run in its own cog and whala down to 600 u second sample time.

    I want to try this, how do I start a cog with asm code from another file. so say I have my main object to just start my cogs and have the global variables in just one file. So I have asm code for i2c and some math each in thier own file but have cognew (@i2c,@stack) and cognew (@math,@stack) ?
  • Rick_HRick_H Posts: 116
    edited 2010-10-02 09:25
    ok this is what I came up with and it kinda works

    in each objectfile I added a getaddress method
    pub getAddress
    return @entry
    

    then In my main object I have
    pub start | address
    address := i2c.getaddress 
    coginit(7,address, stack)
    address:= math.getaddress
    coginit(6,address, stack)
    



    I can get one or the other working like this but not both. Any suggestions?
  • Heater.Heater. Posts: 21,230
    edited 2010-10-02 10:31
    You should have a different stack for each COG.
  • Rick_HRick_H Posts: 116
    edited 2010-10-02 10:37
    I want to share the same data from cog to cog.
    the math writes to the array and the i2c reads from it. Can I not do it this way? I added a hart beat on pin 16 for math and pin 18 for i2c and they work independently but with them sharing the stack and a timer between each coginit only the last one starts.
  • Heater.Heater. Posts: 21,230
    edited 2010-10-02 10:52
    Spin uses the stack for return addresses when calling methods, method parameters, return results and local variables. So you see that two COGs running Spin with the same stack is not going to work as they both corrupt each others stack.

    You cannot share a timer between COGs. Or do you mean some variable that is used to count time?

    With the stacks sorted out things should start to run. But...

    How are these two methods using the shared data? If that data contains a bunch of values that must be treated as an "atomic" unit, i.e. all parts updated before the next process reads it, then you will need to be careful about how the two processes access shared the data and may end up needing locks to prevent data corruption.
  • Heater.Heater. Posts: 21,230
    edited 2010-10-02 11:02
    Sorry, you are using ASM in your COGs. So there is no need for a stack as such and I guess "stack" is your shared data area.

    Still, be careful how that shared data is accessed. by each COG.
  • Rick_HRick_H Posts: 116
    edited 2010-10-02 11:04
    its all asm code not spin code, the only spin code I have is to initalize the data from rom and then I start the cogs. its not atomic. and i mean waitcnt in asm for a timer. I'm just togleing a pin on and off every cycle. I think I may have to set my stack like this.
    var
    long ams1, asm2, output[8], data1[5]
    pub start | address
    address := i2c.getaddress 
    coginit(7,address, asm2)
    address:= math.getaddress
    coginit(6,address, asm1)
    

    then I will just add #8 to par to get the output[0] and so on.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2010-10-02 11:45
    Please look up coginit in the manual. You've got your arguments reversed, and you need to pass the addresses of your assembly routines, not their names.

    But I have to ask: why are you using coginit instead of cognew? Such a practice is almost universally frowned upon, since it straitjackets your cog usage and may lead to conflicts down the road with other objects that commit the same faux pas.

    -Phil
  • Heater.Heater. Posts: 21,230
    edited 2010-10-02 12:00
    Actually this is interesting, my prop manual explains that for COGINIT the parameters are:

    For starting a Spin method:

    1) The COG id to be started.
    2) The method name to be started in that COG
    3) The address of some stack space to use.

    For starting PASM:

    1) The COG id to be started.
    2) The address of a PASM routine to start
    3) A value to pass as PAR.

    Somehow the compiler works out how to load a Spin interpreter and run the Spin method in a COG or just load the PASM to a COG.

    BUT what Rick_H has here is an undocumented use of COGINIT.

    His calls just have any old number as the second parameter unrelated to any labels in the calling object. Seems just by chance that Spin does the right thing here.

    Use of COGNEW is preferred.
  • Rick_HRick_H Posts: 116
    edited 2010-10-02 12:04
    no, I am passing the address, its written in the object to the method and passed back via return. just trying coginit because I haven't used it yet and its their. its primaraly how I learn by trying different things. I agree though, useing cognew has way more advantages.
    Where do I have them reversed?

    COGINIT (CogID, AsmAddress, Parameter )

    asm1 and asm2 are the parameters and address is the entry to the asm code.
  • Heater.Heater. Posts: 21,230
    edited 2010-10-02 12:22
    OK but asm1 and asm2 re defined in:
    long ams1, asm2, output[8], data1[5]
    
    and used in:
    coginit(7,address, asm1)
    
    coginit(7,address, asm2)
    

    So the PAR obtained by the PASM contains the uninitialized value of asm1 and asm2. You should pass the address instead by using @:
    coginit(7,address, @asm1)
    
  • Rick_HRick_H Posts: 116
    edited 2010-10-02 12:37
    o wow right, didn't see that. haha wonder how that worked out lmao. its working great at the moment lol.

    na I caught that in my code on compile but didn't change it hear, sorry.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2010-10-02 14:08
    Rick, 'my mistake. Your variable names threw me. I assumed asm1 and asm2 were the assembly routine addresses and that address pointed to a common data area.

    Heater, I would hope that the compiler is smart enough to default to an assembly cog if the first argument is not the name of a Spin routine. But I've been fooled before.

    -Phil
  • Rick_HRick_H Posts: 116
    edited 2010-10-02 15:31
    ya sorry Phil, my var naming conventions could be better but I'm more at home in RSLogics, I try to be as vague as possible so I can pick up service contracts. Just kidding but its been done.

    So can I get an explanation why I can't use the same global var for 2 cogs started in the same object file. I was under the impression that par was just a pointer and nothing was done with it unless wrlong or something was used in asm. Or is it a placeholder that holds some data?
  • Heater.Heater. Posts: 21,230
    edited 2010-10-02 15:50
    Rick_H,
    So can I get an explanation why I can't use the same global var for 2 cogs started in the same object file.
    Who said you can't?

    If you pass the same address (of some shared data) to two calls of COGINIT/NEW that start PASM codes then both of those COGs will get that same address in the PAR register when the start up. So they can both happily access the same data.
    I was under the impression that par was just a pointer and nothing was done with it unless wrlong or something was used in asm
    PAR is a register in the COG address space that holds a thirty two bit value passed to it from COGINIT/NEW.

    Whether PAR contains anything useful or not is entirely up to you. Could be a value, could be bunch of flag bits or bit fields, could be HUB address of some data (a pointer). Could just be unused in which case using zero might be the neat thing to use in the COGINIT/NEW parameter.
  • kuronekokuroneko Posts: 3,623
    edited 2010-10-02 16:13
    ... I would hope that the compiler is smart enough to default to an assembly cog if the first argument is not the name of a Spin routine.
    I checked about a couple of weeks ago, everything which cannot be found/matched as a method is treated as an address to PASM.
  • Rick_HRick_H Posts: 116
    edited 2010-10-02 16:22
    oddly enough I passed the same var to the 2 cogs and they would work but only the last one would stay running, I'll try it again tonight probably had a typo somewhere as I have been rewriting the whole shebang today trying to get a few more clock cycles out of my assembly code. I eliminated all of my jmp's in my I2C and am just doing it all inline. its small enough to fit and way faster without sub routines.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2010-10-02 16:32
    kuroneko wrote: »
    I checked about a couple of weeks ago, everything which cannot be found/matched as a method is treated as an address to PASM.
    Where this becomes ambiguous, of course, is when you call a Spin method to return the address of an assembly routine. :) IIRC, this can be gotten around by enclosing the method call in parens, or by adding zero to the result; but I'd have to test that to make sure.

    -Phil
Sign In or Register to comment.