Shop OBEX P1 Docs P2 Docs Learn Events
Headbanging: r/w values between Main and Object in another cog — Parallax Forums

Headbanging: r/w values between Main and Object in another cog

ErlendErlend Posts: 612
edited 2013-03-17 18:40 in Propeller 1
I thought I hade sorted out using @pointers by now, but obviously not. Here's a sample code I wrote for you.
{Receive DAT value from Main, and write data data to VAR value in Main}


CON
        _clkmode = xtal1 + pll16x                                               'Standard clock mode * crystal frequency = 80 MHz
        _xinfreq = 5_000_000

VAR
long LocalInputDataPointer
long LocalOutputDataPointer
long cog, stack[32]

  
PUB start(InputDataPointer, OutputDataPointer)                     
    cog:= cognew(r_w(LocalInputDataPointer, LocalOutputDataPointer), @stack[0])
    
    LocalInputDataPointer := InputDataPointer
    LocalOutputDataPointer := OutputDataPointer
    
PUB r_w(indataPointer, outdataPointer)

    IF long[LocalInputDataPointer] [4] == 6
       long[LocalOutputDataPointer] [4] := 3
    ELSE
       long[LocalOutputDataPointer] [4] := 1


-and the Main to test it
CON
        _clkmode = xtal1 + pll16x                                               'Standard clock mode * crystal frequency = 80 MHz
        _xinfreq = 5_000_000
       
VAR
  long  OutputData[9]
   
OBJ
  rw      : "TESTr_w"

PUB Main | i

    rw.start(@InputData, @OutputData)
 
    
DAT
InputData    long  3, 1, 4, 2, 9, 7, 5, 8, 0, 6        
    

Testing with debug to display the return-write gives garbage. What am I doing wrong?

Comments

  • Mike GMike G Posts: 2,702
    edited 2013-03-17 06:45
    LocalInputDataPointer and LocalOutputDataPointer are used before being assigned a value. cognew is called and a cog ID is assigned but the cog stops executing at the end of r_w. This is not a good use of cognew. Plus the main COG exits as well.
    PUB start(InputDataPointer, OutputDataPointer)                     
        cog:= cognew(r_w(LocalInputDataPointer, LocalOutputDataPointer), @stack[0])
        
        LocalInputDataPointer := InputDataPointer
        LocalOutputDataPointer := OutputDataPointer
    
  • Mike GMike G Posts: 2,702
    edited 2013-03-17 07:08
    Try this...

    Top level object
    CON
            _clkmode = xtal1 + pll16x                                               
            _xinfreq = 5_000_000
              
    OBJ
      pst   :       "Parallax Serial Terminal"
           
    VAR
      long  OutputData[10]
       
    OBJ
      rw      : "TESTr_w"
    
    PUB Main | i
        pst.Start(115_200)
        
        rw.start(@InputData, @OutputData)
    
        repeat i from 0 to 9
          pst.str(string("InputData["))
          pst.dec(i)
          pst.str(string("] = "))
          pst.dec(InputData[i])
          pst.char(13)
          
        pst.char(13)
    
        repeat i from 0 to 9
          pst.str(string("OutputData["))
          pst.dec(i)
          pst.str(string("] = "))
          pst.dec(OutputData[i])
          pst.char(13)
        
        repeat
        
    DAT
    InputData    long  3, 1, 4, 2, 9, 7, 5, 8, 0, 6
    

    Child object
    {Receive DAT value from Main, and write data data to VAR value in Main}
    
    VAR
      long LocalInputDataPointer
      long LocalOutputDataPointer
      long cog, stack[32]
    
      
    PUB start(InputDataPointer, OutputDataPointer)
    
        LocalInputDataPointer := InputDataPointer
        LocalOutputDataPointer := OutputDataPointer
                             
        cog:= cognew(r_w(LocalInputDataPointer, LocalOutputDataPointer), @stack[0])
    
        
    PUB r_w(indataPointer, outdataPointer)
        repeat
          IF long[LocalInputDataPointer] [4] == 6
             long[LocalOutputDataPointer] [4] := 3
          ELSE
             long[LocalOutputDataPointer] [4] := 1
    

    This example works and it does demo passing values by reference. It's ok for learning but not a good design pattern.
  • MagIO2MagIO2 Posts: 2,243
    edited 2013-03-17 09:48
    @Mike G:
    You find the "bug" without harming by yourself? First you call r_w with parameters but then you don't use them ;o)

    In general I don't understand what the LocalXXXXDataPointer variables are good for at all! ... well ... at least when the program keeps being as simple as that. Because having the pointers in the r_w-stack is local enough. If your program get's more complex and you need access from more than one function it might make sense to store the values in a VAR, but then you don't have to pass those LocalXXXX addresses to the functions, because all functions in an object have access to the VARs defined in the object.
  • Mike GMike G Posts: 2,702
    edited 2013-03-17 10:14
    @MagIO2, you're right. That probably makes the example even more confusing.

    One way
    {Receive DAT value from Main, and write data data to VAR value in Main}
    
    VAR
      long LocalInputDataPointer
      long LocalOutputDataPointer
      long cog, stack[32]
    
      
    PUB start(InputDataPointer, OutputDataPointer)
    
        LocalInputDataPointer := InputDataPointer
        LocalOutputDataPointer := OutputDataPointer
                             
        cog:= cognew(r_w, @stack[0])
    
        
    PUB r_w
        repeat
          IF long[LocalInputDataPointer] [4] == 6
             long[LocalOutputDataPointer] [4] := 3
          ELSE
             long[LocalOutputDataPointer] [4] := 1
    

    Another way
    {Receive DAT value from Main, and write data data to VAR value in Main}
    
    VAR
      long cog, stack[32]
    
      
    PUB start(InputDataPointer, OutputDataPointer)
        cog:= cognew(r_w(InputDataPointer, OutputDataPointer), @stack[0])
    
        
    PUB r_w(indataPointer, outdataPointer)
        repeat
          IF long[indataPointer] [4] == 6
             long[outdataPointer] [4] := 3
          ELSE
             long[outdataPointer] [4] := 1
    
  • ErlendErlend Posts: 612
    edited 2013-03-17 15:23
    I am feeling my way in the cog&pointer darkness. Thanks for the enlightenment, it moves me one step further towards mastering spin.
  • Mike GMike G Posts: 2,702
    edited 2013-03-17 16:54
    There's a lot of ways to design objects and deal will reference types or pointers. Your initial code posting, IMO, is more a design question.

    This is an example of encapsulation...

    Top Level
    CON
            _clkmode = xtal1 + pll16x                                               
            _xinfreq = 5_000_000
                   
    VAR
      long  OutputData[10]
       
    OBJ
      pst     : "Parallax Serial Terminal" 
      rw      : "TESTr_w"
    
    PUB Main | ptr
        pst.Start(115_200)
        
        ptr := rw.Init
        PrintArray(ptr)
    
        rw.CopyArray(@inputData)
        PrintArray(ptr)
    
        ifnot(rw.SetArray(0, 200))
          pst.str(string("Error: Index out of bounds", pst#NL))
        else
          PrintArray(ptr)
    
        ifnot(rw.SetArray(1000, 200))
          pst.str(string("Error: Index out of bounds", pst#NL))
        else
          PrintArray(ptr)
    
        if(rw.IsNull(rw.GetArray(100)))
          pst.str(string("Error: Index out of bounds", pst#NL))
        else
          pst.str(string("Array["))
          pst.dec(100)
          pst.str(string("] = "))
          pst.dec(long[ptr][100])
          pst.char(pst#NL)
          pst.char(pst#NL)
    
        if(rw.IsNull(rw.GetArray(1)))
          pst.str(string("Error: Index out of bounds", pst#NL))
        else
          pst.str(string("Array["))
          pst.dec(1)
          pst.str(string("] = "))
          pst.dec(long[ptr][1])
          pst.char(pst#NL)
          pst.char(pst#NL)
           
    
    
    PUB PrintArray(ptrArray) | i
      repeat i from 0 to rw#BUFFER_SIZE-1
        pst.str(string("Array["))
        pst.dec(i)
        pst.str(string("] = "))
        pst.dec(long[ptrArray][i])
        pst.char(13)
      pst.char(13)  
        
    DAT
      inputData    long  3, 1, 4, 2, 9, 7, 5, 8, 0, 6
    

    Child Object
    {Receive DAT value from Main, and write data data to VAR value in Main}
    
    CON
      BUFFER_SIZE   = 10
      
    DAT
      array    long  $[BUFFER_SIZE]
      null     long  $0
    
    
    PUB Init | i
      'Initialize the array
      repeat i from 0 to BUFFER_SIZE-1
        array[i] := i
    
      return GetArrayPointer
    
    PUB CopyArray(ArrayToCopy) | i
      repeat i from 0 to BUFFER_SIZE-1
        array[i] := long[ArrayToCopy][i]
      
    PUB GetArray(index)
      'Get an array element value
      if(index > BUFFER_SIZE OR index < 0)
        return @null
      else  
        return array[index]
    
    PUB SetArray(index, value)
      'Set an array element value 
      if(index > BUFFER_SIZE OR index < 0)
        return false
      else
        array[index] := value
        return true
    
    PUB GetArrayPointer
      return @array
    
    PUB IsNull(value)
      return @null == value
    
    
  • kuronekokuroneko Posts: 3,623
    edited 2013-03-17 18:30
    Mike G wrote: »
    PUB GetArray(index)
      'Get an array element value
      if(index > BUFFER_SIZE OR index < 0)
        return @null
      else  
        return array[index]
    
    I assume that's supposed to read index => BUFFER_SIZE? Also, how would you distinguish between @null as an error case and array[index] == @null?
  • Mike GMike G Posts: 2,702
    edited 2013-03-17 18:40
    kuroneko, yep you're right my logic is messed up.
Sign In or Register to comment.