Shop OBEX P1 Docs P2 Docs Learn Events
Multiple PUB /PRI functions using CogSPIN - How-to — Parallax Forums

Multiple PUB /PRI functions using CogSPIN - How-to

PropGuy2PropGuy2 Posts: 360
edited 2022-02-23 04:29 in Propeller 2

Like most of you I have written numerous SPIN2 programs. But now the programs become longer and more complex. COG0 is the primary working Cog and is a real workhorse, my Cog1 is used for ER Smiths VGA tile drivers. The setup works great.

However, as the main program in Cog0 grows and becomes more complex, I would like to use Cog2, Cog3 as a Utility Function Cog to take the burden and time delays off of Cog0, and let the (new) Utility cog completely and independently, take over some occasional & randomly used functions: PUB Print, PUB i2c, PUB SD card, PUB sounds, PUB math functions, and more.

The COGSPIN command only allows for the initialization for only one PUB or PRI function per Cog, as I understand it. Further the REPEAT commend is used to keep the function "alive" , again as I understand it.
As in : mycog := COGSPIN ( 16, SomeFunction( ), @SomeStack )

It appears that SomeFunction() will run independently on the new Cog, but any other PUB functions share the working Cog0 time slice.

How can I add multiple PUB and PRI functions to the same Cog ??? and have the utility functions all run independently to keep my primary program COG0 from being over worked ???

Comments

  • roglohrogloh Posts: 5,837
    edited 2022-02-23 04:40

    @PropGuy2 said:
    How can I add multiple PUB and PRI functions to the same Cog ??? and have the utility functions all run independently to keep my primary program COG0 from being over worked ???

    This is a confusing question to ask and needs clarification. Do you want to spawn a different COG for each SPIN2 function call? That can be done by just passing different method names into your "SomeFunction" argument in your code above.

    If you want the spawned COG to return values back to the caller which spawned the new COG while freeing up the caller to go to other things in the meantime, you will need to invent some type of data structure to return the parameters into, and have the caller then poll for completion when it desires. This can be achieved with some agreed memory locations that can be cleared initially and checked for returned results afterwards and the spawned COG could shut itself down when it has written the data there. There is also a COGATN mechanism for signalling between COGs or locks which may also be useful that you could look into for inter-process communication which is what I think you might be asking for. Lookup WAITATN, POLLATN, ATN to see what can be done with those commands.

  • roglohrogloh Posts: 5,837
    edited 2022-02-23 04:55

    Here's an (untested) snippet of code that shows the general idea..

    VAR
        long mailbox[2]
        long stack[100]
    
    PUB main()
        demo()
    
    PUB demo() : result | a, b  ' main cog runs this 
    
        ' setup parameters for new cog
        a:=3
        b:=2
        mailbox[0]:=0 ' clear completion flag initially
    
        ' spawn worker cog with parameters
        cogspin(16, newCogStart(@mailbox, a, b), @stack)
    
        repeat
            doSomeWork(100)
        until mailbox[0]<>0 ' wait for result
    
        ' cog results are available now in mailbox[1]
    
        return mailbox[1]
    
    
    PUB doSomeWork(y) | x
        repeat x from 1 to y
            waitms(1)
    
    
    PUB newCogStart(@resultMem, param1, param2) | x
        x := newCogFn(param1, param2)
        long[@resultMem][1]:= x ' copy result here
        long[@resultMem][0]:=-1 ' indicate completion with non-zero value
        ' spawned cog dies here
    
    PUB newCogFn(p1, p2) : result
        result := p1*p2
    
    
  • Following up on Roger's suggestion, remember that all Spin cogs have access to all global variables. I used this fact helping my friend from JonyJib where Cog0 handles joystick interface and RS-485 packet management, and another cog "talks" to the Nextion HMI. Both cogs can use/manipulate global variables.

  • @PropGuy2 said:
    Like most of you I have written numerous SPIN2 programs. But now the programs become longer and more complex. COG0 is the primary working Cog and is a real workhorse, my Cog1 is used for ER Smiths VGA tile drivers. The setup works great.

    However, as the main program in Cog0 grows and becomes more complex, I would like to use Cog2, Cog3 as a Utility Function Cog to take the burden and time delays off of Cog0, and let the (new) Utility cog completely and independently, take over some occasional & randomly used functions: PUB Print, PUB i2c, PUB SD card, PUB sounds, PUB math functions, and more.

    The COGSPIN command only allows for the initialization for only one PUB or PRI function per Cog, as I understand it. Further the REPEAT commend is used to keep the function "alive" , again as I understand it.
    As in : mycog := COGSPIN ( 16, SomeFunction( ), @SomeStack )

    It appears that SomeFunction() will run independently on the new Cog, but any other PUB functions share the working Cog0 time slice.

    How can I add multiple PUB and PRI functions to the same Cog ??? and have the utility functions all run independently to keep my primary program COG0 from being over worked ???

    You only need to keep the utility cogs 'alive' if their job is ongoing, like the VGA driver or a driver for an SD card. If it is a single shot function you can set it going and just let it quietly stop when finished, or alternately alert the calling cog and stop.

    It may help to think of the unallocated cogs as a resource pool, and as long as you don't set too many utility functions going at once you can be uncaring as to which cog is running those functions. It only gets awkward if you run out of cogs.

  • Also keep in mind the ATN mechanism you can use to signal completion to a waiting cog, or even use as IRQ source.

  • pik33pik33 Posts: 2,388

    How can I add multiple PUB and PRI functions to the same Cog ??? and have the utility functions all run independently to keep my primary program COG0 from being over worked ???

    Your cogspin function is a main loop for this cog: you simply call other functions from there. Warning: calling functions from more than 1 cog can have side effects, where more than 1 cog modifies the same variables used by these functions.

Sign In or Register to comment.