Using repeat loops with coginit/cognew and cogstop
GUFF
Posts: 8
I recently used a prop for a custom piece of test equipment. I am generating a custom dropout pulse used to control another piece of test equipment. Layout is fairly simple: pulse start/stop switch and pulse selector switch (switch between two choices). I can get the pulse generator to work and control things but would like to improve the code. Currently when one pulse runs and I switch to the next i have to wait until the former pulse finishes before the new one begins. So as you can see I am only using one cog to control and call methods. This is not a deal killer but something I would like to tweak. I want to set it up so I get instant change from one pulse to the next.
My first idea was to start and stop different cogs for each pulse. I was doing this inside repeat loops that look at both switches current state. When I do it this way I cannot get any pulse output. Maybe I am getting stack space problems? I did a sanity check and decoupled the start cog commands from the repeat loop(s) and it works fine with code similar to what can be found in PE kit. Attached is a test version of the code where i changed pulse output to blink LEDs instead.
My first idea was to start and stop different cogs for each pulse. I was doing this inside repeat loops that look at both switches current state. When I do it this way I cannot get any pulse output. Maybe I am getting stack space problems? I did a sanity check and decoupled the start cog commands from the repeat loop(s) and it works fine with code similar to what can be found in PE kit. Attached is a test version of the code where i changed pulse output to blink LEDs instead.
Comments
When starting up a separate cog, remember that the COGINIT or COGNEW takes time to start up the cog. COGINIT and COGNEW return (and the initiating cog continues execution) almost immediately (as soon as an idle cog is found). The Spin interpreter is copied into the new cog and initialized in parallel with the execution of the initiating cog. This takes a bit over 100us to do.
Consider this -- it does the same thing, is easy to call, and only uses one cog. (Update) The pulse loop is broken into units of 1/64s so that early exit is possible
Also, you still won't get "instant" response to a change in the pulse generator because it takes a significant amount of time to load code into a COG.
You normally use some hub variables to control a cog - set a start-flag to set it going, cancel it to stop, use a separate variable to
report status back from the cog in question. Locks can be used as a semaphore directly for each cog too.
Killing and restarting a cog costs about 8200 cycles, and killing a cog risks leaving things in a broken state (there is no
cleanup done, the cog stops and all its special registers reset to zero.)
Agreed, I am making it more complicated than it needs to be. But then again, what you do expect from a hardware guy (EMC Engineer)? Attached is a visual for what I am doing.
I think you are right, no need for multiple cogs.
There are two pulses I need to output. Both would be considered "slow" due to the timing parameters:
Pulse 1
10% duty cycle @.2Hz (500ms on/4.5soff)
Pulse 2
24 segments ranging from 50ms to 350ms as follows:
Segment/High/Low/Time (s)
0/Low/0.050
1/High/0.050
2/Low/0.350
3/High/0.250
4/Low/0.050
5/High/0.050
6/Low/0.250
7/High/0.100
8/Low/0.050
9/High/0.350
10/Low/0.050
11/High/0.050
12/Low/0.150
13/High/0.350
14/Low/0.050
15/High/0.050
16/Low/0.350
17/High/0.150
18/Low/0.050
19/High/0.050
20/Low/0.250
21/High/0.050
22/Low/0.050
23/High/0.050
@JonnyMac
I used the idea you presented of breaking up the delays into smaller chunks and then looking for switch changes. That seemed to do the trick nicely. I updated the code and verified on the scope the pulses still work and the pulses change quickly when switches are toggled. Code Attached.
I know I can optimize the code more and plan to as I continue gaining more prop experience. Thanks for helping me learn a thing or two.