Shop OBEX P1 Docs P2 Docs Learn Events
How to return multiple values resulting from multiple cogs? — Parallax Forums

How to return multiple values resulting from multiple cogs?

ElectricAyeElectricAye Posts: 4,561
edited 2008-08-13 12:02 in Propeller 1
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
''***************************************
''*  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

  • hippyhippy Posts: 1,981
    edited 2008-08-12 17:18
    You can use a pointer to RAM and pass the address of a variable you want to use into a method ...

    VAR
      long myVar
    
    PUB Main
      WriteToMyVar( @myVar, 10 )
    
    PUB WriteToMyVar( ptr, value )
      long[noparse][[/noparse] ptr ] := value
    
    
    



    You can extend that to arrays ...

    VAR
      long myVar[noparse][[/noparse] 3 ]
    
    PUB Main
      WriteToMyVar( @myVar[noparse][[/noparse] 0 ], 10 )
      WriteToMyVar( @myVar[noparse][[/noparse] 1 ], 20 )
      WriteToMyVar( @myVar[noparse][[/noparse] 2 ], 30 )
    
    PUB WriteToMyVar( ptr, value )
      long[noparse][[/noparse] ptr ] := value
    
    
    



    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 ] )
  • ElectricAyeElectricAye Posts: 4,561
    edited 2008-08-12 17:31
    Thanks, Hippy,
    I can tell there is great wisdom within your words. It will take me some time to feel my way through it.
  • ElectricAyeElectricAye Posts: 4,561
    edited 2008-08-12 17:50
    Hippy said...

    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 ] )

    Okay, I can see how this would pass variables into a cog but how does it work getting values out of a cog?
  • StefanL38StefanL38 Posts: 2,292
    edited 2008-08-12 19:28
    hello ElectricAye,

    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
  • ElectricAyeElectricAye Posts: 4,561
    edited 2008-08-12 19:50
    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
  • hippyhippy Posts: 1,981
    edited 2008-08-12 20:05
    I think you're getting there Mark. @ provides the address of where to read or write and then you pass that into the method.

    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.
  • JamesxJamesx Posts: 132
    edited 2008-08-13 11:41
    Seems to me this "@" and "LONG" indirect addressing is relatively undocumented, compared to how important it is. Difficulties with it keep coming up in this forum.

    Is there a better way to keep it straight for us that don't use it much?

    J
  • ElectricAyeElectricAye Posts: 4,561
    edited 2008-08-13 12:02
    Jamesx said...
    Seems to me this "@" and "LONG" indirect addressing is relatively undocumented, compared to how important it is. Difficulties with it keep coming up in this forum. Is there a better way to keep it straight for us that don't use it much?

    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
Sign In or Register to comment.