Starting, Stopping, updating PASM in COGs other than the original caller?
T Chap
Posts: 4,223
PUB Start(StartPin, NumEnc, NumDelta, PosAddr, direction): Pass ' rotary encoder obj Pin := StartPin TotEnc := NumEnc TotDelta := NumDelta Pos := PosAddr Stop longfill(Pos, 0, TotEnc+TotDelta) SetDir(direction) Pass := (Cog := cognew(@Update, Pos) + 1) > 0 'SetDir(direction) ' or here? can instruction be changed after cog is started PUB SetDir(i) 'alter an instruction in DAT from add to sub 'adding this to the Rotary obj if i == 1 'Subtract AMask[-8] |= |< 26 ' sub set bit 26 high for subtract = reverse elseif i == 0 'Add 'bitwise NOT bit 26 of the instruction on line :IPos add 0, Diff AMask[-8] &= !|< 26 ' add 'AMask is in the DAT section of the Rotary objA few questions if someone can make this more clear.
1. Does SetDir belong above the Cognew or below?
2. Main(cog0) starts a COG(1) that starts another COG(2) shown above. I can't test this till tomorrow but am trying to get an understanding. If the object above in COG(2) was launched from COG(1), can the SPIN code in COG(1) call SetDir on the fly anytime to alter the PASM instruction from add to sub? Or would COG(2) require a stop, then a relaunch to select the instruction?
3. Can Main contain the object name for COG(2) also under OBJ, and then allow Main to call COG(2) SetDir. Or must Main call a method in COG(1) that calls a SetDir in COG(2). In other words, can any COG call a method in any other cog.
Comments
hub memory into the cog RAM, zeroes the special registers (except PAR which is loaded from the parameter to cognew or
coginit) and then starts executing PASM from cog address 0. If the cog is running spin code then the memory copied is
the Spin interpreter.
This loading of the cog is asynchronous, in other words the cog calling cognew or coginit will get control back immediately
and run alongside the (re)started cog's loading.
Cog RAM cannot be accessed from outside the cog, so any changes into the hub memory the cog was loaded from
will have no effect on the cog after its copied it. Calling coginit will overwrite the whole of cog memory so all cog-local
variable state is lost - you will need code in the cog to update itself, rather than trying to change it from outside.
Also in Spin you can only call methods in the same cog, the only way to initiate code in another cog is
via cognew or coginit. There is no meaning to calling on another (already running) cog anyway, it doesn't
make any kind of sense. You can communicate with other cogs, but they have to cooperate with you.
One last thing, cogs are pretty lightweight to startup, it takes about 100us with a system clock of
80MHz (for the new cog, the one starting it doesn't lose time), so its quite feasible to spawn and kill them
on demand (just be sure you never try to have more than 8 at one time).
SetDir is run in whichever cog calls it. Only code launched with cognew is assigned to a cog. The Spin code just sits in hub RAM to be used by any cog wanting to call it. Objects don't correspond to cogs.
To answer your other questions we need to know where "AMask" is located and how it is accessed. Does the PASM code use a rdxxxx to access it or is it access from within cog RAM? If the latter, then you need to call "SetDir" before launching the cog.
Okay, I just found what you're talking about.
You'll need to call SetDirection before starting the cog. You'll have to stop and restart the cog if you want to change the direction after the initial start. It would be possible to add a couple of rdlongs to the loop in order to change them on the fly without needing to stop the cog.
I hadn't noticed the "[-8]" after "AMask". I see now you want to modify the PASM code on the fly. You can only do this from within cog running the PASM.
You could add a "direction" variable to be read from hub. You could then set the direction to "1" or "-1" and then the PASM cog would read the value and add whatever the value is to the encoder total.
If you're not sure how to do this let me know. It would only take a few minutes to add.
Edit: I was just looking at the code some more. It's not as simple as I had thought. I think you're idea of changing the plus to a minus is a good one, it's just going to be a bit tricky doing it on the fly.
Ideally you also make sure that the cog is loaded completely before returning but that is less critical in your case I believe.
I tested out your note about how the cog is loaded into memory after the cognew and found that up to a delay of 4600+cnt the code SetDir will work consistently. However, why bother with trying that, I just wanted to see how things worked. I still don't understand how part of the code is moving on towards the loading of the COG with the 2k from hub, while at the same time some part of the code is running the SetDir simultaneously with the COG memory being loaded, so that the SPIN is altering the DAT section at the same time. So, what COG is actually running the code to call up SetDir post cognew if the COG for the Rotary Object is loading itself? I am thinking this is as Duane stated, the cog that holds the SPIN that is doing the call for the new object(cognew) is actually what is running the SetDir. This is why I was asking about the cogs starting and stopping and altering methods within a cog. Even after years of years of this, some of this still is not clear. The beauty of it is I suppose, that I don't really need to know since it just always does what I want reliably even without a deep understanding of the process.
I would also like to know this.
At first I wondered if the new cog got loaded with some code to transfer the data into itself but I don't see how it would fit with the code being load. Maybe the Spin interpreter running in the cog which called cognew does some multitasking and both load the new cog while continuing running the rest of the code but then this also doesn't make sense since one cog can't access another. There must be some sort of hub "processor" which takes care of the round robin access to the cogs and maybe this same "processor" loads cogs?
I have never given any thought to waiting on a cog to load.
I always have a synchronisation mechanism to talk to a cog, so that outside code automatically waits for it to set its ready flag
(or whatever scheme I'm using). You can synchronise with a lock, or a hub variable (the latter involves busy-waiting), or if you
have more than one PASM cog you can synchronize them to the precise clock cycle by passing a value for both to WAITCNT on.
You can also synchronise with a I/O pin.
One thing that is often useful is have to cog load some of its configuration variables from hub ram each time
round its main loop, so that it can be controlled from other cogs - basically the cog is polling for its configuration
rather than just setting it up at start up. This would be a good way to control a PWM cog for instance since
the cog decides when its ready to poll.