Shop OBEX P1 Docs P2 Docs Learn Events
Looking for a few fresh ideas for switching back and forth between two functions — Parallax Forums

Looking for a few fresh ideas for switching back and forth between two functions

idbruceidbruce Posts: 6,197
edited 2011-01-26 11:19 in Propeller 1
llllllllllllllllllllllllll

Comments

  • HughHugh Posts: 362
    edited 2011-01-26 03:18
    Global variable?

    0 = run 'as is'
    1 = Forced change to Function A
    2 = Forced change to Function B
    3 = run Stop

    ?
  • Mike GMike G Posts: 2,702
    edited 2011-01-26 04:54
    This is where PASM comes in handy. Take a look at Jonny Mac's January Spin Zone article. There is also the LED blink demo code in the Propeller manual. Or you can do what Hugh suggests and write a SPIN dispatch scheme.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-26 08:24
    @Hugh and Mike G

    I was thinking along the lines of the following, but I don't know if it will work:
    VAR
      LONG IncomingNewString  
      LONG IncomingOldString
      LONG OutgoingNewString  
      LONG OutgoingOldString
      LONG Stack[10]
      BYTE StopByte
      BYTE Cog
    PUB Start(Pin1) : Success
      Stop
      Success := (Cog := COGNEW(MainLoop(Pin1), @Stack) + 1)
    PUB Stop
      IF Cog
        COGSTOP(Cog~ - 1)
    PUB MainLoop(Pin1)
      StopByte := FALSE
      DIRA[Pin1]~~
      OUTA[Pin1]~
      REPEAT
        IF OutgoingNewString == OutgoingOldString
          IF NOT \ FunctionA
            Stop
          ELSE
            NEXT
        ELSE
          IF NOT \ FunctionB(OutgoingNewString)
            Stop
          ELSE
            NEXT
    PUB FunctionA  
      REPEAT
     
        IF StopByte == TRUE
          ABORT FALSE
        ELSEIF OutgoingNewString <> OutgoingOldString
          ABORT TRUE 
        ELSE
          IncomingNewString := Some Value
          ### Remaining code goes here ###
    PUB FunctionB(UpdateString)  
      REPEAT 3
     
        IF StopByte == TRUE
          ABORT FALSE
        ELSE
          IF ### Some condition == TRUE
            ABORT TRUE
     
          ### Remaining code goes here ###
    

    The parent object would need to be able to read:
    IncomingNewString
    And the parent object would need to be able to write to:
    StopByte
    OutgoingNewString
    Is this possible?

    Bruce

    P.S. As you can clearly see, I have very little knowledge of working with new cogs, as to what is possible and what is not.
  • MagIO2MagIO2 Posts: 2,243
    edited 2011-01-26 09:10
    I would only use aborts for real problems. These are meant to be used like exceptions in C++.
    PRI mainLoop...
      ' init code here
      stopByte := FALSE
      ' state := "A" or state := "B" - whatever is the initial state
      repeat until stopByte
        if state == "A"
          FunctionA
        if state == "B"
          FunctionB( .. )
    
    PRI FunctionA
       ' This does not need a repeat, as it's repeated by the main
       if OutgoingNewString <> 0
          IncomingNewString := .....
         ' remaining code
       else
          state := "B"
    
    PRI FunctionB
      repeat 3
        ' Your code
        state := "A"
    

    For stopping the whole thing you'd add another PUB function which simply sets the stopByte to true.

    If I understand your code correctly OutgoingNewString is a variable which holds the address of a string-buffer, right? Otherwise OutgoingNewString == OutgoingOldString makes no sense, as you can not compare strings directly.
    So, you can do it a different way:
    The code that prepares the string to be send, would set the pointer to the buffer-address (using a PUB function)
    The code that sends the string sets this pointer to 0 if done.
    This way you don't need a New and a Old variable.

    For the IncomingString you can do the same. For your object you have 2 possibilities, either you give it the buffer-address with the start function. In this case the buffer is part of the code using this object.
    Or you have another PUB function called getIncomingString. Then your object has a buffer for the Incoming message.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-26 09:31
    MagIO2

    Thank you very much for your input. Please give me a minute or two to examine what you wrote. I will get back to you.

    Bruce
  • idbruceidbruce Posts: 6,197
    edited 2011-01-26 10:26
    MagIO2

    Overall, I like your ideas and source. I would imagine it would now look something similar to this:
    VAR
      LONG IncomingString  
      LONG OutgoingString  
      LONG Stack[10]
      BYTE StopByte
      BYTE Cog
      BYTE State
    PUB Start(Pin) : Success
      Stop
      Success := (Cog := COGNEW(MainLoop(Pin), @Stack) + 1)
    PUB Stop
      IF Cog
        COGSTOP(Cog~ - 1)
    PRI MainLoop
      DIRA[Pin]~~
      OUTA[Pin]~
     
      StopByte := FALSE
      State := "A"
     
      REPEAT UNTIL StopByte
     
        IF State == "A"
     
          IF NOT \ FunctionA
            Stop
     
        IF State == "B"
     
          IF NOT \ FunctionB(OutgoingString)
            Stop
    PRI FunctionA
       IF OutgoingString <> 0
          IF NoErrors
            ' remaining code
     
            IncomingString := .....
          ELSE
            ABORT FALSE 'Exception
     
       ELSE
     
          State := "B"
    PRI FunctionB(UpdateString)
      REPEAT 3
        ' Do something with UpdateString  
     
        IF NoErrors := TRUE
     
          OutgoingString := 0
        ELSE
          ABORT FALSE 'Exception
     
        State := "A"
    PUB UpdateOutgoingString(OutgoingStringPointer)
      ' Set the value for OutgoingString
    

    However I still have a two remaining questions, which are:
    While the object is running in a loop, can the parent object still call the PUB Stop method and stop the cog, and can the parent call the PUB UpdateOutgoingString?
    It would seem to me that the child object would be wrapped up in the MainLoop, and be unable to accomplish these tasks.

    Bruce
  • Heater.Heater. Posts: 21,230
    edited 2011-01-26 10:32
    Bruce,
    While the object is running in a loop, can the parent object still call the PUB Stop method and stop the cog....

    Yes. That is the normal way things are done.

    Don't forget when the parent calls Start which does a COGNEW, a new instance of the Spin interpreter is started on a new COG just to run MainLoop (In your example).
    After that Start returns back to the parent who can then continue, in its original COG, and do whatever it likes. Including calling Stop.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-26 10:35
    Heater

    Oh I think see the forest now. The whole object is not running in a new cog, it is just the MainLoop. Is this correct?

    Bruce
  • Heater.Heater. Posts: 21,230
    edited 2011-01-26 10:37
    I think the point is not to confuse objects and COGs.

    When a parent object calls a method in a child object the code of that method is run in the same COG as the parent.

    When you do a COGNEW an new COG is started and it only runs the method that was passed to COGNEW. The rest of the methods in that object are still available to be called from a parent.

    In fact if the method started my COGNEW is PUB then it can be called directly by the barent object and then you might have two COGS running the same method. Which makes sense in some cases.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-26 10:42
    Heater

    That was very enlightening. Thank you very much for your input. I was missing that whole concept, now I understand completely, and it makes perfect sense. Just one of those "A DUH" things :)

    Thanks Heater

    Bruce
  • MagIO2MagIO2 Posts: 2,243
    edited 2011-01-26 10:47
    Ok, next iteration:

    1. Simply call the abort whereever an error occurs. So, no NoErrors variable needed. Except you do it for a reason that I don't see here.
    2. The other improvement is mainly beautifying code and maybe saves some bytes.
    PRI Init
      DIRA[Pin]~~
      OUTA[Pin]~
     
      StopByte := FALSE
      State := "A
      If NOT \ MainLoop
        Stop
    
    PRI MainLoop
      REPEAT UNTIL StopByte
     
        IF State == "A"
          FunctionA
     
        IF State == "B"
          FunctionB(OutgoingString)
    
    Of course start would then call Init instead of the MainLoop.
  • idbruceidbruce Posts: 6,197
    edited 2011-01-26 11:19
    MagIO2

    I truly appreciate your input in this matter. And I really like your modifications, which were some very nice suggestions.

    I was just using NoErrors as an example :) I would call the aborts directly.

    OutgoingNewString == OutgoingOldString LOL Sometimes I still tend to think like I am working with a CString object in MFC.

    I would imagine this would be a lot better:
    IF STRCOMP(OutgoingNewString, OutgoingOldString)
    Anyhow, thanks for your input, I definitely appreciate it.

    Bruce
Sign In or Register to comment.