How can I share data in between cogs in PASM?
Scenario: Two pasm cogs doing different things, I want to have a third that compares a few pieces of data from each and does some calculations
In trying to figure this out on my own, I would imagine I have to pass a hub ram address to the 3rd comparative cog or call a get command that returns a result. Can I call method.getResult inside of PASM and bypass spin? I'd like to bypass SPIN altogether for speed purposes. Do I have to go through hub ram to share cog data between cogs? I would think there is a way I could obtain the hub address and pass that as PAR, but how do I handle doing that with more than one cog? I'll have no idea how far the second address is from the first in hub ram? All cogs are in their own separate objects.
Can I call the object and get an array of variable address that I can store in hub ram?
I'm a PASM newb, so dumb it down if possible
In trying to figure this out on my own, I would imagine I have to pass a hub ram address to the 3rd comparative cog or call a get command that returns a result. Can I call method.getResult inside of PASM and bypass spin? I'd like to bypass SPIN altogether for speed purposes. Do I have to go through hub ram to share cog data between cogs? I would think there is a way I could obtain the hub address and pass that as PAR, but how do I handle doing that with more than one cog? I'll have no idea how far the second address is from the first in hub ram? All cogs are in their own separate objects.
Can I call the object and get an array of variable address that I can store in hub ram?
I'm a PASM newb, so dumb it down if possible

Comments
As far as I know, you can reserve some bytes in hub ram space, then cogs #1 and #2 can write to them, (wrbyte/wrword/wrlong) and cog3 can read them (rdbyte/rdword/rdlong). You can also reserve 2 bytes for flags, where cogs 1 and 2 can write a "magic" value which means "data ready". Cog 3 can read these bytes in loop and if it detects "data ready", get out of this loop and read and process results from hub ram. I don't know how to reserve these bytes and get their addresses, I think it can be done in spin. (I started Propeller programming learning from pasm, not spin)
Something like:
From pub main in my parent object, I call methods from the two independent pubs that return addresses, and then passes those address to the third comparative method to read from?
object1 VAR long long1 long long2 long long3 PUB Main pub getAddressLong1 result := long[@long1]object2 VAR long long1 long long2 long long3 PUB Main pub getAddressLong1 result := long[@long1]I tested it and it returned a static "10016", which I guess is hex for 65558 . I should be able to pass the address into the comparative cog (@obj1L1 ) and the assign that address or save it to a long that is local to that object so that I can then pass it into the DAT section and read it. Does this sound ok?
Does anyone see anything wrong with my code?
Below are the results when I use comp.init with and without the @ symbol, either way I'm still not getting the values I should inside of the code
CON BULK_NUM_OF_LONGS = 5 var long cog long crTAddr long caTAddr long calcDiff pub init(cr, ca) : okay waitcnt((clkfreq*2) + cnt) ' let screen initialize crTAddr := cr caTAddr := ca okay := cog := cognew(@diffcntr, @crTAddr) + 1 pub cleanup '' Stop frequency counter cog if running if cog cogstop(cog~ - 1) pub getCrTAddr result := crTAddr pub getCaTAddr result := caTAddr pub getCalculatedDiff result := calcDiff pub getPst result := crTAddr pub getPst2 result := caTAddr pub getPst3 result := calcDiff pub getPst4 result := 0 pub getPst5 result := 0 pub getPst6 result := 0 pub getPst7 result := 0 pub getPst8 result := 0 pub getPst9 result := 0 pub getPst10 result := 0 pub getPst11 result := 0 pub getPst12 result := 0 pub getPst13 result := 0 pub getPst14 result := 0 DAT org 0 diffcntr mov tmp1, par ' start of structure rdlong tmp2, tmp1 ' get pin#, store it in tmp2 ' save addresses of hub storage add crTPtr, tmp1 add caTPtr, tmp1 add calcDiffPtr, tmp1 restart rdlong lastCrGapTime, crTptr rdlong lastCaGapTime, caTptr mov lastCrGapTimeT, lastCrGapTime sub lastCrGapTimeT, lastCaGapTime wrlong lastCrGapTimeT, calcDiffPtr jmp #restart nopinstr mov 0, 0 NR ' -------------------------------------------------------------------------------------------------- crTPtr long 0 caTPtr long 4 calcDiffPtr long 8 averageptr long 12 maxptr long 16 minptr long 20 pstptr long 24 pstptr2 long 28 pstptr3 long 32 pstptr4 long 36 pstptr5 long 40 pstptr6 long 44 pstptr7 long 48 pstptr8 long 52 pstptr9 long 56 pstptr10 long 60 pstptr11 long 64 pstptr12 long 68 pstptr13 long 72 pstptr14 long 76 ' Standard variable initialization here lastCrGapTime long 0 lastCrGapTimeT long 0 lastCaGapTime long 0 ' Reserved variables here tmp1 res 1 tmp2 res 1 fit 492Only use a "@" if you want to take a variable name and convert that to the address of the variable. I'm hedging a little because there are sometimes circumstances where you might want to take the address of a parameter containing an address, but that would be unusual and you should understand what you're doing in that case.
You probably want to do: comp.init(fcrank.getTimingAddress,fcam.getTimingAddress)
Then you'll want to do:
mov tmp1, par rdlong address1, tmp1 add tmp1, #4 rdlong address2, tmp1At this point, address1 and address2 have the addresses returned by .getTimingAddress for each of the objects. You can use those with RDLONG to look at long1 in object1 and object2 respectively. If you add 4 or 8 to those, you can look at long2 or long3 in those objects.Even the first code block below is giving me info I can't use, and I have this in the parent spin object inside of a com method just calling the child object.method, so it appears my problem is maybe with the "result := @pst9" ? What should the address actually look like, maybe I can get it for a baseline and hard code it and work backwards from there?
pst.str(string("addresses: ")) pst.dec(fcrank.getTimingAddress) pst.str(string(" : ")) pst.dec(fcam.getTimingAddress) pst.char(13)I get the same value very time and when I do pst.hex I see
pst.str(string("addresses: ")) pst.hex(fcrank.getTimingAddress, strsize(fcrank.getTimingAddress)) pst.str(string(" : ")) pst.hex(fcam.getTimingAddress, strsize(fcam.getTimingAddress)) pst.char(13)If I don't make any code changes, I keep getting the same exact values printed out to the pst when I flash the uC
pst.str(string("addresses: ")) pst.hex(fcrank.getTimingAddress, strsize(fcrank.getTimingAddress)) pst.str(string(" : ")) pst.hex(fcam.getTimingAddress, strsize(fcam.getTimingAddress)) pst.char(13) pst.str(string("addresses: ")) pst.dec(addr1) pst.str(string(" : ")) pst.dec(addr2) pst.char(13) pst.str(string("values: ")) pst.dec(@addr1) pst.str(string(" : ")) pst.dec(@addr2) pst.char(13)Here are parts of the object, the var section and the return of the address in which the information I want is being stored. I can't put it the init result unfortunately, because that is already returning the cog number that it calls.
object fcrank
CON BULK_NUM_OF_LONGS = 5 var long cog long fcPin ' frequency counter pin long fcCycles ' frequency counter cycles long fcToothcount long fcMax long fcMin long fcAverage long pst long pst2 long pst3 long pst4 long pst5 long pst6 long pst7 long pst8 long pst9 long pst10 long pst11 long pst12 long pst13 long pst14 long l_prevCycle9 long l_prevCycle8 long l_prevCycle7 long l_prevCycle6 long l_prevCycle5 long l_prevCycle4 long l_prevCycle3 long l_prevCycle2 long fcToothCntMax long fcGapCnt long fcGapCntPeak pub getTimingAddress result := @pst9object fcam
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 _clkHz = 80_000_000 _byteLimit = 100 CLK_FREQ = ((_clkmode - xtal1) >> 6) * _xinfreq VAR long cog, fcPin, fcCycles{, frcntr, frPin long l_previousCam6, l_previousCam5, l_previousCam4, l_previousCam3, l_previousCam2, l_currentCam, l_CamToothAverage, { } l_trigger1, l_trigger2, l_trigger3, l_calculatedCamRpm} long fcToothcount long fcMax long fcMin long fcAverage long pst long pst2 long pst3 long pst4 long pst5 long pst6 long pst7 long pst8 long pst9 long pst10 long pst11 long pst12 long pst13 long pst14 long l_prevCycle9 long l_prevCycle8 long l_prevCycle7 long l_prevCycle6 long l_prevCycle5 long l_prevCycle4 long l_prevCycle3 long l_prevCycle2 pub getTimingAddress result := @pst9pst.str(string("addresses: ")) pst.hex(fcrank.getTimingAddress, strsize(fcrank.getTimingAddress)) pst.str(string(" : ")) pst.hex(fcam.getTimingAddress, strsize(fcam.getTimingAddress)) pst.char(13)The getTimingAddress methods return address values. Judging from the child objects these addresses don't refer to strings so get rid of the strsize stuff. Simply use pst.hex({base :=}fcrank.getTimingAddress, 8). This is your base address, access it with long[base][idx].pst.str(string("addresses: ")) pst.hex(fcrank.getTimingAddress, 8) pst.str(string(" : ")) pst.hex(fcam.getTimingAddress, 8) pst.char(13)This output was from the code below addresses: 00002B5C : 00002C24
pst.str(string("addresses: ")) pst.hex({base :=}fcrank.getTimingAddress, 8) pst.str(string(" : ")) pst.hex({base :=}fcam.getTimingAddress, 8) pst.char(13)Those look more along the lines of what I was expecting.
I can get the numeric address now, so I'm successfully passing that via the comp.init command. I cannot get rdlong to work properly. I've copied the necessary parts of my code to show what I'm doing, I feel like I've tried every possible angle, but I'm probably just going in circles and don't realize it.
I believe I have the shortest, simplest program one could write and I cannot get it to spit out the value of either address. I can by the parent method call getCrTAddr from the child methods code below and it will return the address to the parent method that I've sent it through the code above, but that is about it. I have to be missing something obvious, because I can't even pass the variable via PAR or tmp1 and then write it back out, so that the program can acknowledge it has received the value in the PASM portion of the code. I believe this will be even more complex when I have to pass addresses that are not consecutive, like crankTimingAddr and camTimingAddr .
comp method code
var long cog long crTAddr long pst pub init(cr, ca) : okay waitcnt((clkfreq*2) + cnt) ' let screen initialize crTAddr := cr 'caTAddr := (crTAddr + 200) okay := cog := cognew(@diffcntr, crTAddr) + 1 pub cleanup '' Stop frequency counter cog if running if cog cogstop(cog~ - 1) pub getCrTAddr result := crTAddr pub getPst result := pst DAT org 0 diffcntr mov tmp1, par ' start of structure ' save addresses of hub storage add crtptr, tmp1 add pstptr, tmp1 restart wrlong par, pstptr jmp #restart nopinstr mov 0, 0 NR ' -------------------------------------------------------------------------------------------------- crtptr long 0 pstptr long 4 ' Standard variable initialization here lastCrGapTime long 0 lastCrGapTimeT long 0 lastCaGapTime long 0 ' Reserved variables here tmp1 res 1 tmp2 res 1 fit 492var long cog long crTAddr long caTAddr long pst PUB selftest | r, a init(@r, @a) r := 0 a := 0 dira[16..23]~~ repeat r? ?a waitcnt(clkfreq + cnt) outa[16..23] := getPst pub init(cr, ca) waitcnt((clkfreq*2) + cnt) ' let screen initialize crTAddr := cr caTAddr := ca return cog := cognew(@diffcntr, [COLOR="red"]@[/COLOR]crTAddr) + 1 pub cleanup '' Stop frequency counter cog if running if cog cogstop(cog~ - 1) pub getCrTAddr result := crTAddr pub getPst result := pst DAT org 0 diffcntr add crtptr, par ' @crTAddr add catptr, par ' @caTAddr add pstptr, par ' @pst rdlong crtptr, crtptr ' cr rdlong catptr, catptr ' ca restart rdlong tmp1, crtptr ' long[cr] rdlong tmp2, catptr ' long[ca] sub tmp1, tmp2 wrlong tmp1, pstptr jmp #restart ' -------------------------------------------------------------------------------------------------- crtptr long 0 catptr long 4 pstptr long 8 ' Standard variable initialization here lastCrGapTime long 0 lastCrGapTimeT long 0 lastCaGapTime long 0 ' Reserved variables here tmp1 res 1 tmp2 res 1 fit DATI'm having a timing problem now with the reads, any tips on how to handle that? I've never used this before, but do I need to use lockset?
Maybe this helps: Imagine someone gives you 2 books (cr/ca) and you have one of your own (pst). You have to send them somewhere (PASM) but you can only send one thing. So you simply put them in a box (VAR section, crTAddr ...) and send it. All you have to do in PASM is unpack (+0/+4/+8/rdlong). If that doesn't make sense then I blame not enough coffee, yet.
You'll have to give us some more info on this one ...
and then passed as a variable storing an address with
What you are saying is that when it gets to init it wants the symbol again?
pub init(cr, ca) waitcnt((clkfreq*2) + cnt) ' let screen initialize crTAddr := cr caTAddr := ca return cog := cognew(@diffcntr, @crTAddr) + 1I believe my lock issue was not a lock issue after all.
Everything I've done so far has led up to the info below, if you have time could you tell me if you agree with the logic. I need to tell the difference between channel 1's tooth 23 (I believe leading edge) and channel 2's tooth 3 underneath it, which will sometimes trail channel 1's tooth 23 and sometimes lead channel 1's tooth 23. What makes it a little more complicated is that channel 2 is moving at half the speed of channel 1.
So each time channel 2 has tooth 3 pass by I grab a cnt, then I check for the most recent channel 1 tooth 23 cnt and do some math. Does that sound reasonable?
location value [COLOR="#020FC0"]pst9{crank} $5000 -1 pst9{cam} $5004 -2 crankTimingAddr $5008 0 camTimingAddr $500C 0 crTAddr $5010 0 caTAddr $5014 0 pst $5018 0[/COLOR] crankTimingAddr := fcrank.getTimingAddress pub getTimingAddress [COLOR="#FFA500"]result stack 0[/COLOR] result := @pst9 [COLOR="#FFA500"][B]result stack $5000[/B][/COLOR] [COLOR="#020FC0"]pst9{crank} $5000 -1 pst9{cam} $5004 -2 [B]crankTimingAddr $5008 $5000[/B] camTimingAddr $500C 0 crTAddr $5010 0 caTAddr $5014 0 pst $5018 0[/COLOR] camTimingAddr := fcam.getTimingAddress pub getTimingAddress [COLOR="#FFA500"]result stack 0[/COLOR] result := @pst9 [COLOR="#FFA500"][B]result stack $5004[/B][/COLOR] [COLOR="#020FC0"]pst9{crank} $5000 -1 pst9{cam} $5004 -2 crankTimingAddr $5008 $5000 [B]camTimingAddr $500C $5004[/B] crTAddr $5010 0 caTAddr $5014 0 pst $5018 0[/COLOR] comp.init(crankTimingAddr, camTimingAddr) pub init(cr, ca) [COLOR="#FFA500"]cr stack $5000 ca stack $5004[/COLOR] crTAddr := cr caTAddr := ca [COLOR="#020FC0"]pst9{crank} $5000 -1 pst9{cam} $5004 -2 crankTimingAddr $5008 $5000 camTimingAddr $500C $5004 [B]crTAddr $5010 $5000 caTAddr $5014 $5004[/B] pst $5018 0[/COLOR] return cog := cognew(@diffcntr, @crTAddr) + 1 PASM: [B]par == $5010[/B] diffcntr add crtptr, par ' @crTAddr $5010+0 == $5010 add catptr, par ' @caTAddr $5010+4 == $5014 add pstptr, par ' @pst $5010+8 == $5018 rdlong crtptr, crtptr ' cr long[$5010] == $5000 == @pst9{crank} rdlong catptr, catptr ' ca long[$5014] == $5004 == @pst9{cam} restart rdlong tmp1, crtptr ' long[cr] long[$5000] == -1 == pst9{crank} rdlong tmp2, catptr ' long[ca] long[$5004] == -2 == pst9{cam} sub tmp1, tmp2 ' tmp1 := 1 wrlong tmp1, pstptr ' long[$5018] := 1 [COLOR="#020FC0"]pst9{crank} $5000 -1 pst9{cam} $5004 -2 crankTimingAddr $5008 $5000 camTimingAddr $500C $5004 crTAddr $5010 $5000 caTAddr $5014 $5004 [B]pst $5018 1[/B][/COLOR]Ok, so the address to the variable holding the address in the value portion is passed here
add crtptr, par ' @crTAddr $5010+0 == $5010
and then this command reads the value saved at that address?
rdlong crtptr, crtptr ' cr long[$5010] == $5000 == @pst9{crank}
If that is correct, excellent explanation!
I'm having trouble and need the advice of someone with more experience then myself because I'm having strange problems and I can't figure out why, I spent hours trying to troubleshoot this tonight.
I'm seeing any of the 3 below, as well as a few other random values that I don't have screen captures of and I can't come up with a theory as to what is causing this.
Pst9/a should always match comPst3 and it is not
caPst9/a should always match comPst2 which it seems to do
comPst should always be (comPst3-comPst2) and comPst3 should always be a greater number. I watch it on the scope and comPst3/Pst9 is always after (greater) comPst2/caPst9. The code I'm using is below, crTAddr reads the value at the address for pst9 and caTAddr reads the value at the address for caPst9.
As you can see from my screen captures, something is wrong. I don't know if it is a lock issue, because I've never experienced that? Maybe it is a timing issue? I'm really confused, I did this in PASM so I wouldn't have timing issues. I minimized the serial data as you can see in the second picture to make sure the slowness of the pst wasn't causing this and that didn't change things.
(The forum is making the pictures a little to small to read, so I posted the link to see the full sized version as well)
http://img24.imageshack.us/img24/4182/goodcompst4a.jpg
http://img855.imageshack.us/img855/6355/badcompst4a.jpg
http://img442.imageshack.us/img442/4540/badcompst4b.jpg
var long cog long crTAddr long caTAddr long pst long pst2 long pst3 PUB selftest | r, a init(@r, @a) r := 0 a := 0 dira[16..23]~~ repeat r? ?a waitcnt(clkfreq + cnt) outa[16..23] := getPst pub init(cr, ca) waitcnt((clkfreq*2) + cnt) ' let screen initialize crTAddr := cr caTAddr := ca return cog := cognew(@diffcntr, @crTAddr) + 1 pub cleanup '' Stop frequency counter cog if running if cog cogstop(cog~ - 1) pub getCrTAddr result := crTAddr pub getPst result := pst pub getPst2 result := pst2 pub getPst3 result := pst3 DAT org 0 diffcntr add crtptr, par ' @crTAddr add catptr, par ' @caTAddr add pstptr, par ' @pst add pstptr2, par ' @pst add pstptr3, par ' @pst rdlong crtptr, crtptr ' cr rdlong catptr, catptr ' ca restart mov prevCaGapTime, lastCaGapTime mov prevCrGapTime, lastCrGapTime rdlong lastCrGapTime, crtptr ' long[cr] rdlong lastCaGapTime, catptr ' long[ca] cmp lastCrGapTime, lastCaGapTime WZ, WC ' if crank time is greater if_nz_and_nc cmp prevCaGapTime, lastCaGapTime WZ, WC ' make sure cam has rotated once to give a different value, before updating if_nz wrlong lastCrGapTime, pstptr3 if_nz sub lastCrGapTime, lastCaGapTime if_nz wrlong lastCaGapTime, pstptr2 if_nz wrlong lastCrGapTime, pstptr jmp #restart ' -------------------------------------------------------------------------------------------------- crtptr long 0 catptr long 4 pstptr long 8 pstptr2 long 12 pstptr3 long 16 ' Standard variable initialization here lastCrGapTime long 0 lastCrGapTimeT long 0 lastCaGapTime long 0 prevCrGapTime long 0 prevCaGapTime long 0 ' Reserved variables here tmp1 res 1 tmp2 res 1 fitI can fix the filter, but any guesses as to why I have to make sure it is greater in the first place? I trust the scope over my code and it is always greater on the scope.
I attempted a nested if in another location that is only crucial upon initialization, which might be why I thought it was "legal" and that it worked, I gather it is no good here either?
'wrlong totalCycles, pstptr8 ' for pst wrlong zero, pstptr14 cmp avgCycles, #0 WZ, WC ' verify avgCycles is not empty if_nz mov avgCyclesDoubled, avgCycles ' copy avgCycles to temp location if_nz shl avgCyclesDoubled, #1 ' double avgCycles if_nz cmp avgCyclesDoubled, totalCycles WZ, WC ' compare current totalCycles to doubled avgCycles if_nz_and_c mov gapTimingLogPrev, gapTimingLog if_nz_and_c mov gapTimingLog, cnt if_nz_and_c wrlong one, pstptr14 if_nz_and_c mov toothNumber, #1 if_nz_and_c jmp #restart ' jump back to restart and ignore if it is more than double the avgCycles