Shop OBEX P1 Docs P2 Docs Learn Events
How can I share data in between cogs in PASM? — Parallax Forums

How can I share data in between cogs in PASM?

turbosupraturbosupra Posts: 1,088
edited 2012-05-02 07:06 in Propeller 1
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 :)
«1

Comments

  • JonnyMacJonnyMac Posts: 9,378
    edited 2012-04-13 08:48
    Sure, you have to do it through the hub. Have your spin code designate the address(es) you want to share and then pass that information to the PASM cogs. If you need to multiple values as a block then you'll want to setup a lock to prevent access by one cog while the other is busy writing values.
  • Mike GreenMike Green Posts: 23,101
    edited 2012-04-13 08:50
    The PASM cogs have to store their results in some variables in hub memory where the Spin cog can get at it. Typically, you pass the address of a block of longs to each of the PASM cogs and access this block using the PAR register. Since the PAR register contains only one address, you have to move PAR to some temporary location and add offsets to it to get other addresses. For examples, look at some of the PASM I/O drivers that come with the Propeller Tool. FullDuplexSerial is one example where the Spin code passes the address of a block of information in PAR and the PASM code uses PAR to access several parameters including the receive and transmit buffers. Look at the .start method there and the PASM initialization routine beginning at the "entry" label.
  • pik33pik33 Posts: 2,413
    edited 2012-04-13 08:50
    I am new in Propeller, too.

    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)
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-13 09:11
    So can I launch the two independent data objects/cogs and have them allocate longs in hub ram for my wrlong commands to write to as part of the initialization. Then have a method inside of each one of those independent objects that I can call, that will return the hub ram address of a variable.

    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?
    OBJ
      object1 : "object1"
      object2 : "object2"
    
    
    PUB Main
    
      object1.init
      object2.init
    
      obj1L1 := object1.getAddressLong1 ' stores address of the first long in object 1
      obj2L1 := object2.getAddressLong1 ' stores address of the first long in object 2
    
      object3.init(obj1L1, obj2L1) ' passes addresses of long 1 in object 1 and long 1 in object 2, then initializes third object
    
    
    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]
    
    
    
  • Mike GreenMike Green Posts: 23,101
    edited 2012-04-13 09:19
    Your "getAddressLong1" routines won't do what you want. They'll return the value stored in "long1". You want:
    PUB getAddressLong1
       return @long1
    
  • Mike GreenMike Green Posts: 23,101
    edited 2012-04-13 09:26
    From a stylistic perspective, I'd suggest returning the address of the work area as the result of the .init method like this:
    VAR long long1, long2, long3
    
    PUB init
    ' do initialization stuff
       return @long1
    
    In your main program you'd do:
    PUB main | workAddr1, workAddr2
    ' initialize lots of stuff
       workAddr1 := object1.init
       workAddr2 := object2.init
       object3.init( workAddr1, workAddr2)
    
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-13 09:30
    Excellent ... thank you, does the rest of my theory sound correct?

    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?

    Mike Green wrote: »
    Your "getAddressLong1" routines won't do what you want. They'll return the value stored in "long1". You want:
    PUB getAddressLong1
       return @long1
    
  • Mike GreenMike Green Posts: 23,101
    edited 2012-04-13 09:55
    You've got the general idea. Do look at objects like FullDuplexSerial for examples of this sort of thing.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-13 10:01
    Will do, thanks for pointing me in the right direction :)
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-13 11:50
    Mike, I've done what you asked and it appears I do the same basic thing that fullduplexserial does except theirs works and mine doesn't : D

    Does anyone see anything wrong with my code?

      crankTimingAddr := fcrank.getTimingAddress
      camTimingAddr := fcam.getTimingAddress
      
    
      comp.init(@crankTimingAddr, @camTimingAddr
    

    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

    using no @ symbol addresses are: 10972 : 11172

    using @ symbol addresses are: 8628 : 8632

    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     492
                             
    
  • Mike GreenMike Green Posts: 23,101
    edited 2012-04-13 12:41
    You've got too many "@" in passing parameters from one routine to another. The first "@" produces the address of some variable. This is a numeric value that should get passed essentially unchanged from one routine to another. If you do another "@", then you're passing the address of the variable that contains the address of the original variable.

    Only 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, tmp1
    
    At 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.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-13 13:51
    You are right, I do need the original hub ram address

    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?
    addresses: 10992 : 11192
        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
    addresses: AF800000AF8 : BC000000BC0
        pst.str(string("addresses: "))
        pst.hex(fcrank.getTimingAddress, strsize(fcrank.getTimingAddress))
        pst.str(string("  :  ")) 
        pst.hex(fcam.getTimingAddress, strsize(fcam.getTimingAddress))  
        pst.char(13)
    
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-13 14:34
    I'm close ... I feel there is probably 1 piece missing that I don't know since this is my first time trying this and it is hosing the whole operation.

    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 wrote:
    addresses: B6000000B60 : C2800000C28
    addresses: 11104 : 11304
    values: 8792 : 8796
        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 := @pst9
                  
    

    object 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 := @pst9
    
  • Mike GreenMike Green Posts: 23,101
    edited 2012-04-13 15:12
    This is all too complicated. How about reducing everything to two source files ... a main program and one object. You could really use only one source file, but you might not believe that it's the same thing as a main program and a separate object file. Eliminate everything but an initialization routine in the object and a PASM routine that takes the address of a table and fills the table with addresses and values of some sort. The main program just displays everything you might want to look at.
  • kuronekokuroneko Posts: 3,623
    edited 2012-04-13 15:52
        pst.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].
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-13 16:18
    This output was from the code below addresses: 00002B5C : 00002C24
        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.

    kuroneko wrote: »
        pst.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].
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-13 16:20
    Thanks Mike, that's actually what I'm doing now, just trying to at this point display the address and then the value of it inside of the PUB main ... which are where those PST calls are made. Once I can get that, I'll work backwards towards inputting it into the other PASM cog.

    Mike Green wrote: »
    This is all too complicated. How about reducing everything to two source files ... a main program and one object. You could really use only one source file, but you might not believe that it's the same thing as a main program and a separate object file. Eliminate everything but an initialization routine in the object and a PASM routine that takes the address of a table and fills the table with addresses and values of some sort. The main program just displays everything you might want to look at.
  • kuronekokuroneko Posts: 3,623
    edited 2012-04-13 16:37
    turbosupra wrote: »
    This output was from the code below addresses: 00002B5C : 00002C24
    They are expected to be the same (i.e. first and second variant). The commented out assignment to base was there to indicate that it should be assigned to something before being accessed.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-13 21:49
    Hello, yes I understood that hint and am doing as you've suggested. I've spent 5 hours trying to make this work and humbly come back for more help. I believe this shouldn't be very hard and so I think I am missing something fundamental and that is why it is not working. I wrote the simplest program I could think of in PASM and that still isn't working either.

    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.
    crankTimingAddr := fcrank.getTimingAddress
      camTimingAddr := fcam.getTimingAddress
    
      comp.init(crankTimingAddr, camTimingAddr)
    



    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     492
                             
    
  • kuronekokuroneko Posts: 3,623
    edited 2012-04-13 22:21
    Have a look at this. The idea is to pass an address reference to a VAR section (@crTAddr) which is known to hold cr, ca and pst. The latter can be used directly (after adding 8 to par). The former two need to have their values extracted (those are the addresses passed to the init method). Then you can read from them. It helps when you draw yourself a picture. HTH
    var
      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
    
    DAT
    
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-14 08:11
    Thank you Kuroneko, that worked. Why did you use @crTAddr in the cognew, when an address was already being passed via cr to crTAddr?

    I'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?
  • kuronekokuroneko Posts: 3,623
    edited 2012-04-14 16:08
    turbosupra wrote: »
    Why did you use @crTAddr in the cognew, when an address was already being passed via cr to crTAddr?
    If you just pass crTAddr to cognew then only its value arrives in PASM land. In this case PASM would see cr (assigned just before the call to cognew) which has no link whatsoever to e.g. pst (which I assumed you need downstairs). What we really need is a reference to the 3-long-array starting with crTAddr (followed by caTAddr and pst). Which means address-of-first-member (@crTAddr). You could have easily passed crTAddr (par == cr) but how do you communicate ca and pst then?

    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.
    turbosupra wrote: »
    I'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?
    You'll have to give us some more info on this one ...
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-15 10:57
    Thanks for the reply ... so even though it is originally set to an address with
    pub getTimingAddress
      result := @pst9
    


    and then passed as a variable storing an address with
    crankTimingAddr := fcrank.getTimingAddress
      camTimingAddr := fcam.getTimingAddress
    
      comp.init(crankTimingAddr, camTimingAddr)
    


    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) + 1
     
    

    I 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?



    propscopedegreesoffseta.jpg
  • kuronekokuroneko Posts: 3,623
    edited 2012-04-15 16:51
    Re: timing, that sounds OK. You basically timestamp the two events with cnt and evaluate them later. What's the problem you're experiencing?
  • kuronekokuroneko Posts: 3,623
    edited 2012-04-15 17:00
    Re: parameter passing, it's picture time (well, sort of). See if this rings a bell for you.
    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]
    
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-16 11:15
    I'm experiencing the problem of uncertainty, since no one else (that I know) has done what I'm doing, I'm trying to ensure that I'm going down the right path and that my logic is sound. I don't have a baseline, so that makes it difficult.
    kuroneko wrote: »
    Re: timing, that sounds OK. You basically timestamp the two events with cnt and evaluate them later. What's the problem you're experiencing?


    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! :) ... bell was rung! Thank you for taking the time to write that code.
    kuroneko wrote: »
    Re: parameter passing, it's picture time (well, sort of). See if this rings a bell for you.
    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]
    
  • kuronekokuroneko Posts: 3,623
    edited 2012-04-16 16:46
    turbosupra wrote: »
    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, ...
    Yes, that's all there is to it. Have fun!
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-17 20:15
    I'm back :)

    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
    goodcompst4a.jpg

    http://img855.imageshack.us/img855/6355/badcompst4a.jpg
    badcompst4a.jpg

    http://img442.imageshack.us/img442/4540/badcompst4b.jpg
    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
    
                            fit
    
  • kuronekokuroneko Posts: 3,623
    edited 2012-04-17 20:40
                            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
    
    I don't know what the logic is supposed to be here but the way it's now means you'll get an update (wrlong) even if lastCrGapTime < lastCaGapTime. IOW, the greater condition (!Z&!C) only applies to the following cmp. If it isn't true (equal or less) then the following 4 insns are still executed for !Z (less). That would explain the reverse order for certain values.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-17 21:43
    That is interesting, thank you. I actually shouldn't ever get a reverse order and wrote that as an attempt to see if I could filter it out, now I know why the filter didn't work. I was trying to write something that would be similar to a SPIN nested if statement, that is nested inside of another if statement. I guess you cannot do conditional comparisons in PASM? Do you see anything else that appears wrong? With the simulation code, the results are 100% perfect, it is just in the car that they get messed up.

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