Passing Values between objects with Cogs.
bambino69
Posts: 126
in Propeller 2
The fact that all serial objects pass data to AND from the top objects that called them, tells me this is possible.
But even in my brief P1 Days I wasn't able to fully understand it. Passing data to the child objects was easy enough, but navigating the address space to get data back to the top was frustrating.
The Top object here calls three instances of the child object. Sending each a time value to stay lit.
What is the process that would enable the child to tell the top how long it took to complete is program?
top Object:
Child Object:
But even in my brief P1 Days I wasn't able to fully understand it. Passing data to the child objects was easy enough, but navigating the address space to get data back to the top was frustrating.
The Top object here calls three instances of the child object. Sending each a time value to stay lit.
What is the process that would enable the child to tell the top how long it took to complete is program?
top Object:
{Cog usage with child control via shared register"sync".} {pin 0----------(gLed)------\ pin 1----------(yLed)------|---(330 ohm res)--gnd pin 2----------(rLed)------/ } CON CLK_FREQ = 5_000_000 _clkfreq = CLK_FREQ sec = 1000 VAR long sync long cognum long StkAddr[100] long StkAddr1[100] long StkAddr2[100] OBJ rLed : "ContolledChild" gLed : "ContolledChild" yLed : "ContolledChild" pub main()| okay,c cognum:=COGSPIN(newcog, gLed.On(0,sec,@sync) , @StkAddr) cognum:=COGSPIN(newcog, yLed.On(1,sec,@sync) , @StkAddr1) cognum:=COGSPIN(newcog, rLed.On(2,sec,@sync) , @StkAddr2) repeat repeat c from 0 to 2 sync:=c waitms(sec)
Child Object:
{Basic child with parent variable used for pin synchronization} VAR long pin long duration long sync long syncAddr PUB On(num,d,s) pin:=num 'Save passed parems duration:=d syncAddr:=s 'Save passed parent control variable address to local var repeat LONGMOVE(@sync, syncAddr, 1) ' Move value at parent address to local var toggle() pri Light() pinhigh(pin) PRI delay() waitms(duration) pinclear(pin) PRI toggle()| t t:=getct() if sync==pin Light() delay() t:=getct()-t-48 return
Comments
If the expected run time is more than 10 seconds, you can use the latest version of PNut and the getms() function. This is not as fine as using the cnt register, but for durations that long, 1ms resolution is probably okay.
A few minutes later... I see you have something like my suggestion in your child object. I guess I don't understand the question.
Suggestion: Use one resistor per LED. Differences in the LED forward voltage can create problems with Parallel LEDs (the one with the lowest Vf will light, the others will not).
But I digress!
For this lesson the value is irrelevant. Any none 0 value could let top know when to change the red light!
How to get it back to the top object. I've tried get statements(The cog throws that off)
I've tried longmoves(but where from and where to)
Not even considering wasting a couple pins for cog cog comms.
But the timing of each cog was done trial and error.
If the child object cog could say to the top object "Hey I'm red and I just turned off" then the top would know he could safely turn on the green light.
ps. By trial and error I mean at the speed where running the light looks like a functioning red light, But technically the top object is assuming each child finishes in the allotted second
Top object........child object.......cog in child object........data
data<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<data
The process of getting data from a cog in a child up to the top object.
In my code above.
I would wont to send time back to the top object. I'm using time here but a boolean would work too.
Would like to write it this way though, with the cog started in the child object, But the sync value wouldn't make it to the cog.
You can always have the slave process write 0 back to the shared location so that the foreground process can see that it's done and send control to another process.
Child object
Green light fires and stays lit.
code is stuck here. [/code]
I would expect to see the red light come on after the green goes out.
So how would I make the top object see sync as 10
I showed you. Pass the address of your sync variable to the background cog. Have the background cog wait for a trigger value in the sync location to run its process. When that process is done it writes a "finished" value back to the sync address.
Easy-peasy. JonnyMac out!!!
How is this: Different from this: Or this: From this:
I looked at your code and saw where you declared p_baton and in my code its "s" in the "On" routine.
Something more in your code I not implementing.
In going back thru the discussion I noticed your zip file. I did not know you had posted that.
Thanks, That code works as good as mine.
Both led routines are in their own cogs.
However, yours are in the same file with the top object, Yes, that would be as you say... But I did not ask how to do that.
Imagine your flasher routine in its own object, and its cog being started in said object. How would it pipe data back to the Top Object?
My code passes the baton, but cant get it back.
Hopefully I can get back on it tonight!
No, according to your complaints, my code works better because it can tell when the external process is done.
Yeah, yeah, I know you want an external file -- but that's a Smile argument here because the mechanism is the same: the cogs simply need to what location in memory they're using as a mailbox. Want proof? Run the attached demo. I took my internal object code and moved it to an external object -- that is, a proper object with start() and stop() methods. I also added the ability to pass the timing to the external object from the master -- again, this has to do with an agreement. In this case, the mailbox is a long defined in the top object, and the timing is the next long in memory. The external process knows this so it can pick up the timing. This can be extended to as many values as you like -- there just has to be agreement on both sides.
You probably missed my presentation on Propeller programming. One of the most important things I said is that you should build to things incrementally. I've been programming the Propeller for 15 years (since before the P1 release) and I've had a lot of time to develop working strategies.
Did you ever see the movie "The Karate Kid"? In that movie, Daniel didn't ask to be taught how to wax cars, but Mr. Miyagi made him do it as it would provide a foundation for what was to come. If I or one of the other forum old-timers give you information, you can -- and should -- assume it's for good reason.
Parent object:
Child Object "bambinoChild": It's remarkable that you can start methodes in objects from the parent object in Spin2, that was not possible with Spin1, you needed a start routine that started the cog in the child object.
Andy
It's important to me to be able to compartmentalize my learning in child objects, for a library, if you will, of coding strategies.
My personal strategy is to write spin, then try to do it in asm.
Thanks to you Andy.
Indeed that was one of my reasons for it. Don't remember much of my code from 2008-2009, but I do remember not being able to do this in P1. That memory is what caused me to wonder if it had changed in P2. I can remember blowing up my file size by putting serial objects every where to get my debug statements out of the chip.