How to return multiple values resulting from multiple cogs?
ElectricAye
Posts: 4,561
Greetings, I'm terribly new at this so please pardon my ignorance, but I'm trying to use a Propeller to count 5 different frequencies on 5 different pins simultaneously.· My concept is to launch 5 different cogs that will all count the frequencies during a specified time window, then write the results to a data aquisition system about once every 10 seconds.· I got started on this only to find myself lost in the woods when it came to getting the final count values out of the cogs.· Calling a method will return a value, but cognew only returns the ID of the cog.· I'm guessing I have to use some kind of global RAM addressing and reading technique, but I'm not familiar with how that works·in general and I can't find anything on the website that spells out exactly how to plug·cog results into one place and pull them out with the Main program.· Is there a "RAM Useage For Dummies"·hidden somewhere on the website?· And when I say for Dummies, I mean to say for Mechanical Engineers, like me.· I'm not sure which is more blind to computerease.
At the risk of·embarrassment, I'm pasting the bit of code I started on just to make it clear what I'm trying to do.· I'm sure it's fraught with all kinds of·mistakes and inefficiences, and although I eagerly welcome advice on any of its parts, I'm mainly concerned with the issue of getting·the counts up out of the cogs.
many thanks,
Mark
At the risk of·embarrassment, I'm pasting the bit of code I started on just to make it clear what I'm trying to do.· I'm sure it's fraught with all kinds of·mistakes and inefficiences, and although I eagerly welcome advice on any of its parts, I'm mainly concerned with the issue of getting·the counts up out of the cogs.
many thanks,
Mark
''*************************************** ''* Pulse Counter * ''* PulseCounter1f.spin * ''*************************************** {{This Pulse Counter will launch 5 cogs to count 5 different channels of pulses.}} CON _CLKMODE = XTAL1 + PLL16X _XINFREQ = 5_000_000 VAR long stack[noparse][[/noparse]50] 'create a stack array of 10 longs for each counter cog. Long enough??? {FreqChannel refers to the frequency finally measured on the chosen pin} {Make an array of five channels. Note their IDs will start at zero.} {The first element of this array will be FreqChannel[noparse][[/noparse]0]...} long FreqChannel[noparse][[/noparse]5] {SynchStart is the system clock count at which all the cogs will be told to start counting pulses on their assigned pins. SynchStop is the system clock count at which all the cogs will stop counting. } long SynchStart, SynchStop {TimeWindow is how many clock cycles the count is allowed to last. } long TimeWindow PUB MainPHA {Main of the Pulse Height Analyzer} {Make pins 10 thru 14 read inputs} dira[noparse][[/noparse]14..10]~ {Set TimeWindow to equal 1 second, which is 80 million clock cycles.} TimeWindow := 80_000_000 {****** some sort of repeat block is needed to read about every 10 seconds and write into the data aquisition system.} {Set SynchStart to order the cogs to start counting 1 second from now.} {This gives all the cogs plenty of time to get on the starting line.} SynchStart := (80_000_000 + cnt) {Set SynchStop to happen at the close of the TimeWindow.} SynchStop := (SynchStart + TimeWindow) {Launch the cogs with LaunchCog... } {Somehow each launched cog must provide to MainPHA the value of that cog's phsa register when it reaches the close of the TimeWindow.} cognew (LaunchCog(10,SynchStart,SynchStop),@stack[noparse][[/noparse]0]) cognew (LaunchCog(11,SynchStart,SynchStop),@stack[noparse][[/noparse]10]) cognew (LaunchCog(12,SynchStart,SynchStop),@stack[noparse][[/noparse]20]) cognew (LaunchCog(13,SynchStart,SynchStop),@stack[noparse][[/noparse]30]) cognew (LaunchCog(14,SynchStart,SynchStop),@stack[noparse][[/noparse]40]) PUB LaunchCog(PinA,SynchStart,SynchStop) {PinA refers to the pin number upon which ctra of a cog will count.} {LaunchCog is a method that configures a cog so it will measure pulse counts on its counter module A, using pin PinA. LaunchCog allows a cog to run independently but it requires the cog to start and end its counting in synch with other cogs, thanks to the waitcnt commands. SynchStart is the system clock count at which all the cogs will be told to start counting pulses on their assigned pins. TimeWindow is how many clock cycles the count is allowed to last. SynchStop is the system clock count at which all the cogs will be told to stop counting pulses on their assigned pins.} {Configure the cog's counter module A} ctra[noparse][[/noparse]5..0] := PinA 'assign what pin to look at. ctra[noparse][[/noparse]30..26] := %01010 'configure for positive edge detection. frqa := 0 'no counts are yet allowed to accumulate. phsa~ 'clear the register, set the count to zero. waitcnt(SynchStart) 'wait for the synchstart... then... frqa := 1 'allow counts to start accumulating. waitcnt(SynchStop) 'keep accumulating until the time window is closed. {Note another way to wait for this is waitcnt(SynchStart += TimeWindow)...} frqa := 0 'stop the count. {The result will be the number of pulses counted on PinA during the TimeWindow.} result := phsa {But, uh, how to return this value to the MainPHA??? Ohmagod, don't tell me I have to learn about RAM addresses and pointers and other suchstuff from which insanity itself is inescapably woven...}
Comments
You can extend that to arrays ...
You should be able to adapt that to pass the required variable address into each of your separate Cog programs, eg ...
cognew (LaunchCog( @myVar[noparse][[/noparse] 0 ], 10, SynchStart, SynchStop), @stack[noparse][[/noparse] 0 ] )
I can tell there is great wisdom within your words. It will take me some time to feel my way through it.
Okay, I can see how this would pass variables into a cog but how does it work getting values out of a cog?
the array myVar is already defined in your code.
The programming-language SPIN uses the HUB-RAM. This RAM is shared about ALL cogs.
So you just add another parameter to your LaunchCogMethod
PUB LaunchCog(PinA,SynchStart,SynchStop,PointerToMyVar)
cognew (LaunchCog(10,SynchStart,SynchStop,@MyVar[noparse][[/noparse]0]),@stack[noparse][[/noparse]0])
and at the end of LaunchCog
instead of
result := phsa
you write long[noparse][[/noparse]PointerToMyVar] := phsa
You don't have to know the REAL number of the RAM-adresses
The "@"-operator in "@MyVar[noparse][[/noparse]0]" does the calculations for you
So the "@"-operator could be seen just as a function like on a pocketcalculator sinus(angle).
You get back a result and use the result without caring about the details how the result is calculated
The "@"-operator gives back the RAM-adress
The construction long[noparse][[/noparse]"RAM-adress] writes the result to a certain adress in RAM
and with the adress @MyVar[noparse][[/noparse]0] you write exact at that place in RAM where MyVar[noparse][[/noparse]0] is located
You "give in" the ABSOLUTE-RAM-Adress to the cog. The cog is writing to this ABSOLUTE-RAM-Adress
and by writing to this ABSOLUTE-RAM-Adress the result is already "given OUT"
best regards
Stefan
Okay, now things are beginning to make sense to me. Your explanation of how the @ operator works to store values shared by ALL the cogs helps tremendously. I seem to have some kind of phobia when it comes to RAM address operations, and your example has helped me to face my fears.
a thousand thanks,
Mark
Like asking a secretary to post a leaflet to someone whose address is written on a piece of card. You pass the card over which indicates who to send to. In the example code 'ptr' plays the part of the card.
Is there a better way to keep it straight for us that don't use it much?
J
I agree. I couldn't find anything in the labs, etc. that walked me through this. How about a lab that deals directly with using addresses, RAM and multiple cogs, etc.?
Speaking as a newbie, I would, of course, like to see more examples of everything with lots and lots of comments, too. But because the Propeller has so much capability that stems from its multiple cogs, it seems to me that a lab concerning how to really work the RAM, etc. would be essential to promoting this product.
Mark