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

How can I share data in between cogs in PASM?

2»

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2012-04-17 22:14
    Could you also post the SPIN code so that a comparison is possible?

    As for conditional comparisons, they are possible, you just have to keep an eye on what you're doing (especially when the condition isn't met). Depending on what your SPIN code looks like it may be better to jump over the relevant code rather than rely on being able to cover it with more conditionals (this doesn't always work).

    Re: order of values. Both get updated in rather large intervals. The comparison code can read the update between AN+0 and BN+0 or BN+0 and AN+1. In the first case it would read AN+0 and BN-1 in the second case AN+0 and BN+0.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-18 05:55
    Sure.

    There is a larger loop then this, as you could guess by all of the screen outputs, but this is what it looked like in the second screen capture where most of the pst updates were commented out so they didn't display. How do you suggest I control when the comparison code reads and outputs? Is there a best practice for this?
    PUB com | timeStamp,lpcnt1,lpcnt2, addr1, addr2, offset, deg
    
    
     
      initScreen   ' initiates stationary labels in pst
      
      l_updateRateDenominator := 100000
       
      timeStamp := cnt
    
      lpcnt1:=0                                
      lpcnt2:=0
    
    
      repeat
        charAt( 12,2 , proc[ lpcnt1 ] )
        lpcnt1 := (lpcnt1+1) & 3
        
        if((cnt-timeStamp) > (clkfreq/l_updateRateDenominator))
    
          charAt( 28,2 , proc[ lpcnt2 ] )
          lpcnt2 := (lpcnt2+1) & 3
        
          timeStamp := cnt
          charAt( 12, 4, " " )  ' ("Gap RPM:") )
          pst.Dec((clkfreq/(fcrank.getPst11/10))*6) 
          pst.str(@spaces)
    
          charAt( 43, 4, " " )  ' ( "Tooth RPM:" ) )
          pst.Dec(((clkfreq/fcrank.getPst5)/6)*10)   ' ((clkfreq/period)/36)*60  
          pst.str(@spaces)
    
          charAt( 12, 5, " " )  ' ("delta t:") ) or ("cGap RPM:") ) 
          pst.dec((clkfreq/(fcam.getPst11/10))*12)
          pst.str(@spaces)
    
          charAt( 43, 5, " " )  ' ( "peak Cnt:" ) ) or ( "cTooth RPM:" ) )
          pst.dec(9999999)
          pst.str(@spaces)
    
          charAt( 12, 14, " " )  ' ("Pst:") )
          pst.dec(fcrank.getPst)
          pst.str(@spaces)
    
          charAt( 12, 15, " " )  ' ("Pst2:") )
          pst.dec(fcrank.getPst2)
          pst.str(@spaces)
    
          charAt( 12, 16, " " )  ' ("Pst3:") ) ' cycles per tooth and gap combined or 10 degrees
          pst.dec(fcrank.getPst3)
          pst.str(@spaces)
    
    
    
    
         charAt( 43, 22, " " )  ' ("Pst9:") )
          pst.dec(fcam.getPst9)
          pst.str(@spaces)
    
    
    
     charAt( 73, 14, " " )  ' ("comPst:") )
          pst.dec(comp.getPst)
          pst.str(@spaces)
          
          charAt( 73, 15, " " )  ' ("comPst2:") )
          pst.dec(comp.getPst2)
          pst.str(@spaces)
    
          charAt( 73, 16, " " )  ' ("comPst3:") )
          pst.dec(comp.getPst3)
          pst.str(@spaces)
          
          deg := (comp.getPst/(fcrank.getPst3/10))
          {if (deg => 360)
            deg := deg - 360
    
          if (deg =< 0)
            deg := deg + 360}  
            
          charAt( 73, 17, " " )  ' ("comPst4:") )
          pst.dec(deg)
          pst.str(@spaces)
    
    
    
    
       if (l_sendAllValuesOnce == 1)
          if(cnt > (timeStamp + (clkfreq/l_updateRateDenominator))) 
            sendValues
            l_sendAllValuesOnce := 0
       
        if (l_sendAllValues == 1)
          sendValues 
       
        l_myReceivedByte := pst.RxCheck
         
        if l_myReceivedByte <> -1
          b_waitingToBeParsed[b_byteMoveIndex++] := l_myReceivedByte
         
          ' pst.str(@b_waitingToBeParsed)
          ' pst.str(string(pst#NL))
         
          if l_myReceivedByte == 13
            DelimiterFinder(@b_waitingToBeParsed)
            ByteFill(@b_waitingToBeParsed, 0, strsize(@b_waitingToBeParsed))
            b_byteMoveIndex := 0    
      
    
  • kuronekokuroneko Posts: 3,623
    edited 2012-04-18 23:55
    I'm trying to understand the meaning of the difference you're measuring.
    turbosupra wrote: »
    How do you suggest I control when the comparison code reads and outputs? Is there a best practice for this?
    A few posts back you mentioned:
    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.
    So for example you have event A and some time later event B which gives us a difference of C which is obtained say immediately after B occurred. We keep monitoring the time stamps and we get another A event next which has a difference of D (to the most recent B):
    ----A----------------A-------
    -----------------B-----------
        |     C      | D |
    
    Looking only at absolute differences, there is obviously a jump. This is repeated once we get the next B event. Can your math handle this? Also, provided you force B-more-recent-than-A as in your current code, your quote above (trail/lead) suggests that one tooth can overtake the other (correct me if I'm wrong). Which means that e.g. B may build up an increasing delta to (the previous) A, then it passes (the next) A which in turn introduces a jump toward smaller values again. Same issue (but less jumpy than with absolute measurements). Can you elaborate?
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-19 16:57
    (in case this was better than PM)

    What I decided last night was to use tooth 26, instead of tooth 23. This allows me to not have situations where the difference is both positive and negative. Using tooth 26 and sans some sort of defect, A could never occur after B in a properly done measurement. Do you agree with this logic?

    When you ask if my math can handle this, I think you are asking if I have code to alleviate this?If so, I have tried to do force B to be greater than A, as you know. The case you've pointed out where D was occurring was happening until I forced B to be greater than A and started using tooth 26. I did not consider that B could build a delta, but I believe the comparison code clears the values with the waitpeq mov command, if not that is a good point and maybe I'll throw in some code to ensure that the values are cleared when B is not greater than A, to make sure my code works as intended.

    To reiterate, I've included an oscope measurement picture to make a little more sense of it. The pattern of channel 1 is: 34 peaks and valleys and then a "silence" for the length of 2 peaks/3valleys and the it repeats itself. The pattern for channel 2 is: peak1/valley1/peak2/valley2/peak3/longvalley(valley3) and then it repeats itself as shown in the scope picture. I am currently comparing the times of channel 2 peak3 which would be "A" to channel 1 peak26 which would be "B".

    Peak3 will always happen before tooth 26 and never occur before tooth 21 or 22 (I have not been able to measure this yet to determine which one). Also, the time channel 2 takes to start over and repeat itself is 1/2 of the time channel 1 takes to repeat itself and start over.




    ----A
    A

    B
    | C | D |

    camcrankcomparedkuronek.jpg
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-19 17:32
    I've discovered something interesting today ... my program is actually partially working, but seemingly slow to respond? Or something because it appears accurate at more constant values? I'm really not sure what is causing this yet, it obviously isn't PASM, so it has to be my code. It didn't show up when I had a steady state frequency, but it sure seems to be showing up when I use a varying frequency.

    I am bench marking my results against a known good output, which has the frequency rate of about a 60hz shared serial channel (which ironically is the whole reason I did this project in the first place, because the response time of my benchmark is too slow, lol) of which it can output different values, one being the degree difference I am looking for.

    I was able to drive around and screen capture the known good tool, my code outputted to the PST and the propscope. The propscope verifies that the known good benchmark tool is working and my code is not working. In the first picture they match, but I believe that is because the value was slow to change and was pretty steady. You'll see in the other pictures, they do not match at all.

    I was thinking of building something that varied the frequency rate drastically over a few seconds, do you agree with this testing method to see what in my code is broken? I included the links to the pictures since they are entire screen captures, the forum will probably shrink them to where they are hard to read. I know in some of the propscope pictures I used cam tooth #1 instead of cam tooth #3, but the measurement is the same since it is exactly 180 out from cam tooth #3 and that frequency turns at 1/2 the speed of the channel above it. I can edit the pictures if it is too confusing.


    http://img19.imageshack.us/img19/7318/slightlyoffdegrees8.jpg
    slightlyoffdegrees8.jpg

    http://img195.imageshack.us/img195/1242/slightlyoffdegrees9.jpg
    slightlyoffdegrees9.jpg

    http://img17.imageshack.us/img17/9475/slightlyoffdegrees10.jpg
    slightlyoffdegrees10.jpg

    http://img528.imageshack.us/img528/8148/slightlyoffdegrees11.jpg
    slightlyoffdegrees11.jpg
  • kuronekokuroneko Posts: 3,623
    edited 2012-04-19 17:49
    turbosupra wrote: »
    To reiterate, I've included an oscope measurement picture to make a little more sense of it. The pattern of channel 1 is: 34 peaks and valleys and then a "silence" for the length of 2 peaks/3valleys and the it repeats itself. The pattern for channel 2 is: peak1/valley1/peak2/valley2/peak3/longvalley(valley3) and then it repeats itself as shown in the scope picture. I am currently comparing the times of channel 2 peak3 which would be "A" to channel 1 peak26 which would be "B".
    OK, we are on the same page now. Thanks for clearing that up.
  • kuronekokuroneko Posts: 3,623
    edited 2012-04-19 18:05
    turbosupra wrote: »
    I was thinking of building something that varied the frequency rate drastically over a few seconds, do you agree with this testing method to see what in my code is broken?
    That would certainly help (i.e. I pull here and it twitches over there). I'd cut down on the whole display code first. Just display the essential bits starting with input values and result, then go back from the result until the values match your expected values (or forward from the input). Also, using hex format may be less confusing than huge negative values (especially when timestamps are involved).
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-19 23:46
    I haven't tried this yet, couldn't sleep so I did a little writing, what do you think? Is this what you had in mind?

    CON
      ' current code only allows from 1Hz upwards 
      MIN_FREQUENCY = 1
      ' dunno which upper limit can be achieved by the SPIN-code        
      MAX_FREQUENCY = 9200
    
    
       
    VAR
      byte   pin, presentTeeth, missingTeeth, cog
      long   frequencyRate
    
      long   pulse, sync, timing, l_localIndex
      long   crankStack[100]
      long   camPin, camRpm, rotationalRatio, degree1, degree2, degree3, triggerDegree
      long   camStack[100]
    
    
    PUB camStart(p, r, rots, one, two, three, trig)
      camPin := p                                                
      camRpm := r
      rotationalRatio := rots
      degree1 := one
      degree2 := two
      degree3 := three
      triggerDegree := trig
    
      if cog
        cogstop( cog-1 )
    
      cog := cognew(simulateCamWheel(camPin, camRpm, rotationalRatio, degree1, degree2, degree3, triggerDegree, true, 1), @camStack )+1  'cognew(simulateCamWheel(2, 500, 2, 100, 100, 145, 5), @simulateCamWheelstack) 
    
    PUB simulateCamWheel(simCamWheelPinNum, engineRPM, crankRotsToCamRots, degreeOfTrigger1, degreeOfTrigger2, degreeOfTrigger3, camTriggerDegreeWidth, autoRangeVVTI, degreeChangesPerSecond) | localIndex, crankRpmPerSecond, camRpmPerSecond, localCnt, trigger1Wait, trigger2Wait, trigger3Wait, emtpySpace1Wait, emtpySpace2Wait, emtpySpace3Wait, cyclesPerDegOfRot, toothWaitDelay, startTooth, autoRangeChangesPerSecond, advancing, retarding, degreesShifted, updateCnt
    
      
    
      
      
      dira[simCamWheelPinNum]~~
      outa[simCamWheelPinNum]~
      localIndex := 0
    
      crankRpmPerSecond := (engineRPM/60)                   ' 166.667 crank rots per second at 10k rpm
      camRpmPerSecond := (((engineRPM*10)/60)/2)                 ' 83.333 cam rots per second at 10k rpm
      cyclesPerDegOfRot := (((clkfreq/camRpmPerSecond)/360)*10)  ' 960000/360 at 10k or 2660
      toothWaitDelay := (clkfreq/(crankRpmPerSecond*36))
      autoRangeChangesPerSecond := (clkfreq/degreeChangesPerSecond)
    
      trigger1Wait := (camTriggerDegreeWidth*cyclesPerDegOfRot)                     ' 19 degrees
      trigger2Wait := (camTriggerDegreeWidth*cyclesPerDegOfRot)                     ' 19 degrees
      trigger3Wait := (camTriggerDegreeWidth*cyclesPerDegOfRot)                     ' 19 degrees
      emtpySpace1Wait := (degreeOfTrigger1*cyclesPerDegOfRot)                       ' 72 degrees
      emtpySpace2Wait := (degreeOfTrigger2*cyclesPerDegOfRot)                       ' 72 degrees 
      emtpySpace3Wait := (degreeOfTrigger3*cyclesPerDegOfRot)                       ' 159 degrees    
                                                                                    
    
      startTooth := 26
    
      advancing := true                                     ' moving intake cam closer to the exhaust cam events
      degreesShifted := 0
      'waitcnt(cnt + (toothWaitDelay*22))    ' comment out for high rpms altogether
      updateCnt := cnt
      localCnt := cnt                                      
    
      repeat
    
        if (autoRangeVVTI == true) and updateCnt < cnt      ' autoRange set to true and updatecnt is less than cnt
          updateCnt += autoRangeChangesPerSecond            ' cycles based on how many times I want a degree added/subtracted per second
          
          if advancing == true                              ' if advancing the cam
            localCnt -= cyclesPerDegOfRot
            degreesShifted += 1
    
          if retarding == true                              ' if retarding the cam
            localCnt += cyclesPerDegOfRot 
            degreesShifted -= 1
    
          if degreesShifted =< 0                            ' if 0, go back to advancing cam
            advancing := true
            retarding := false
              
         if degreesShifted => 43                            ' if 43, go back to retarding cam
            advancing := false
            retarding := true
            
        outa[simCamWheelPinNum]~~                           ' pin high
        waitcnt(localCnt += trigger1Wait)                   ' wait cnt time stamp plus trigger degree width in cycles                    
        outa[simCamWheelPinNum]~                            ' pin low
        'waitcnt(localCnt += (clkfreq/521))                 
        waitcnt(localCnt += emtpySpace1Wait)                ' wait cnt time stamp plus first empty space degree width in cycles
        outa[simCamWheelPinNum]~~                           ' pin high
        waitcnt(localCnt += trigger2Wait)                   ' wait cnt time stamp plus trigger degree width in cycles              
        outa[simCamWheelPinNum]~                            ' pin low
        'waitcnt(localCnt += (clkfreq/521))                  
        waitcnt(localCnt += emtpySpace2Wait)                ' wait cnt time stamp plus second empty space degree width in cycles
        outa[simCamWheelPinNum]~~                           ' pin high
        waitcnt(localCnt += trigger3Wait)                   ' wait cnt time stamp plus trigger degree width in cycles            
        outa[simCamWheelPinNum]~                            ' pin low
        'waitcnt(localCnt += (clkfreq/521))               
        waitcnt(localCnt += emtpySpace3Wait)                ' wait cnt time stamp plus third empty space degree width in cycles
      
       
    
  • kuronekokuroneko Posts: 3,623
    edited 2012-04-19 23:54
    Not quite. I was more after something like the top right corner of your last screen. Both timestamps and their difference. That's just collection of data and one delta which it should be impossibe to mess up. Then somehow you arrive at comPst4 (which I assume is based on the timestamps). Provided the timestamps are correct something between those two points goes wrong.

    IOW I was more concentrating on the history of the calculation(s). So anything which could vaguely duplicate real life data should be fine as input.

    Also, you say it seems slow to respond. What is the behaviour when you go from constant value to another (e.g. 5sec A then switch to B)? Does it kind of level out for the new value and if so how (immediately or smooth transition)?
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-20 07:58
    Hi,

    What do you mean by the top right hand corner? That code block I pasted was the code I use to simulate the signal, when I was first writing the code and had not done anything with it real world. It generates the signal, but does not calculate it, and sends it from one pin on the prop to another through a resistor, and then receiving pin is the one that is monitored by the calculation code. I added the part to it last night that I've sectioned out and quoted in this post, to try and simulate the ranging that happens in the real world.

    It works, it just is not responsive as shown by the pictures and therefore not accurate 1/2 of the time. I don't have any real world control (yet) of the values generated in the car, which is why I was trying to tweak the simulation code to create a range of values like what would happen in the car driving around.

    Is that what you were asking?
      if (autoRangeVVTI == true) and updateCnt < cnt      ' autoRange set to true and updatecnt is less than cnt
          updateCnt += autoRangeChangesPerSecond            ' cycles based on how many times I want a degree added/subtracted per second
          
          if advancing == true                              ' if advancing the cam
            localCnt -= cyclesPerDegOfRot
            degreesShifted += 1
    
          if retarding == true                              ' if retarding the cam
            localCnt += cyclesPerDegOfRot 
            degreesShifted -= 1
    
          if degreesShifted =< 0                            ' if 0, go back to advancing cam
            advancing := true
            retarding := false
              
         if degreesShifted => 43                            ' if 43, go back to retarding cam
            advancing := false
            retarding := true
    
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-20 13:09
    I found one mistake, the bolded part used to be "if_nz".

    This comparison calc problem is really giving me a hard time. I'm hoping this was the entire issue, but I'm not sure. I'm also having a hard time simulating the variable signal of the car. It seems to be accurate at a steady state frequency.

                            cmp     lastCrGapTime, lastCaGapTime WZ, WC    ' if crank time is greater
             
    if_nz_and_c             jmp     #restart                               ' if not greater, go back to restart
                            cmp     prevCaGapTime, lastCaGapTime WZ, WC    ' make sure cam has rotated once to give a different value, before updating, lastCaGapTime should always be larger than prevCaGapTime
    [b]if_nz_and_c[/b]             wrlong  lastCrGapTime, pstptr3
    [b]if_nz_and_c[/b]             sub     lastCrGapTime, lastCaGapTime
    [b]if_nz_and_c[/b]             wrlong  lastCaGapTime, pstptr2
    [b]if_nz_and_c[/b]             wrlong  lastCrGapTime, pstptr
                           
    
                            jmp     #restart
    
  • kuronekokuroneko Posts: 3,623
    edited 2012-04-20 16:39
    turbosupra wrote: »
    It works, it just is not responsive as shown by the pictures and therefore not accurate 1/2 of the time. I don't have any real world control (yet) of the values generated in the car, which is why I was trying to tweak the simulation code to create a range of values like what would happen in the car driving around.
    The last picture in post #36 shows a 21 in PST while the logging app(?) shows 36 instead. As both are circled I assume the should be the same. Is that correct? Then my question is, how do you arrive at 21 and where does the 36 come from? I mean you post all these code fragments but in the picture the 21 is only labelled as comPst4.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-20 17:51
    http://img528.imageshack.us/img528/8148/slightlyoffdegrees11.jpg (This one right?)

    Ok, now I understand, sorry for the confusion, I should have explained that my apologies, if the pst pics are confusing just let me know. comPst4 = difference between the peak (center) of the square wave of the red channel (this channel is variable in reference to the other channel) and the center of the 26th tooth in the blue channel. Currently everything is in reference to tooth 26 on the channel that has far more teeth then the other one, the blue channel in this case.

    My code is indicating there is a 21 degree difference, when in actuality it is a 36 degree difference as shown on the benchmark software and verified with the propscope. So pst/code shows 21, but in real life it is 36 degrees difference between the peak of the lower speed channel tooth and the peak of the higher speed channel's tooth 26.

    I believe my code is slow to react and so I'm trying to figure out why that is. Please let me know if that doesn't make sense, I can write a long explanation in finite detail if you'd like me to.

    http://img27.imageshack.us/img27/6536/slightlyoffdegrees11b.jpg
    slightlyoffdegrees11b.jpg
    kuroneko wrote: »
    The last picture in post #36 shows a 21 in PST while the logging app(?) shows 36 instead. As both are circled I assume the should be the same. Is that correct? Then my question is, how do you arrive at 21 and where does the 36 come from? I mean you post all these code fragments but in the picture the 21 is only labelled as comPst4.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-20 19:10
    Ok, looks like I need a total rewrite, my crank read object is catching about 20% of the amount of events it should in the actual environment and it catches 100% of them in the test environment. As much as I don't want to, my gut tells me I'd be better off starting over from scratch. :(
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-24 22:22
    Hi Kuroneko,

    I finally got most of the bugs worked out and had some success tonight, what do you think of the PASM section of this code? Thank you very much for helping me get this far!

    I had to create sort of a do --> until loop and I'm not sure if this was done in a way that is acceptable.

    If this code is solid, I'm going to try and then use it to modify a solenoids pulse width. I guess I will have to build a target table and something that allows it to send different pulse widths based on how far it is from the target? I've never done anything like this before so I'm hoping to see some best practice examples to bench mark and save myself from having to learn the hard way how to do this properly.

    You probably remember this, but crTAddr is the time stamp for crank TDC and caTAddr is the time stamp for camshaft TDC. They are compared and a calculation is done to figure out how many degrees caTAddr is ahead of crTAddr. Also, how do you divide by 10 in PASM?
    var
      long  cog
      long  crTAddr
      long  caTAddr
      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  pst15
      long  pst16
    
    
    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 getCaTAddr
      result := caTAddr
        
    pub getPst
      result := pst
    
    pub getPst2
      result := pst2
    
    pub getPst3
      result := pst3    
    
    pub getPst4
      result := pst4    
    
    pub getPst5
      result := pst5    
    
    pub getPst6
      result := pst6    
    
    pub getPst7
      result := pst7    
    
    pub getPst8
      result := pst8    
    
    pub getPst9
      result := pst9    
    
    pub getPst10
      result := pst10    
    
    pub getPst11
      result := pst11    
    
    pub getPst12
      result := pst12    
    
    pub getPst13
      result := pst13    
    
    pub getPst14
      result := pst14    
    
    pub getPst15
      result := pst15    
    
    pub getPst16
      result := pst16    
    
    
    DAT                     org     0
    
    diffcntr                add     crtptr, par     ' @crTAddr
                            add     catptr, par     ' @caTAddr
                            add     pstptr, par     ' @pst
                            add     pstptr2, par    ' @pst2
                            add     pstptr3, par    ' @pst3
                            add     pstptr4, par    ' @pst4
                            add     pstptr5, par    ' @pst5
                            add     pstptr6, par    ' @pst6
                            add     pstptr7, par    ' @pst7
                            add     pstptr8, par    ' @pst8
                            add     pstptr9, par    ' @pst9
                            add     pstptr10, par    ' @pst10
                            add     pstptr11, par    ' @pst11
                            add     pstptr12, par    ' @pst12
                            add     pstptr13, par    ' @pst13
                            add     pstptr14, par    ' @pst14
                            add     pstptr15, par    ' @pst15
                            add     pstptr16, par    ' @pst16 
    
                            rdlong  crtptr, crtptr  ' cr
                            rdlong  catptr, catptr  ' ca
    
                            jmp     #restart
                            
    
    waitforcrvalue
                            'mov     prevCrGapTime, lastCrGapTime
                            rdlong  lastCrGapTime, crtptr                   ' read long[cr]
                            cmp     lastCrGapTime, lastCaGapTime WZ, WC     ' compare crank to cam
    if_nz_and_c             jmp     #waitforcrvalue                         ' if crank is less than cam, jump to waitforcrvalue
    if_nc                   wrlong  lastCrGapTime, pstptr13                                      
    if_nc                   jmp     #continue
                            
    restart                     
    
                            mov     prevCaGapTime, lastCaGapTime
                            rdlong  lastCaGapTime, catptr    ' long[ca]
                            cmp     prevCaGapTime, lastCaGapTime WZ, WC  ' compare current cam gap time to previous cam gap time
    if_z_and_nc             jmp     #restart
    if_nz_and_nc            jmp     #restart                           ' if equal, go to restart
    if_nz_and_c             wrlong  lastCaGapTime, pstptr14
    if_nz_and_c             jmp     #waitforcrvalue        
    
                            
    continue                                
                          
    
                            wrlong  lastCrGapTime, pstptr2             ' write crank to pst
                            mov     lastCrGapTimeT, lastCrGapTime      ' move crank to crank temp
                            wrlong  lastCaGapTime, pstptr3             ' write cam to pst
                            sub     lastCrGapTimeT, lastCaGapTime      ' subtract cam from crank temp
                            wrlong  lastCrGapTimeT, pstptr             ' write gaptime to pst
    
                            jmp     #restart
    ' --------------------------------------------------------------------------------------------------
    crtptr                  long    0
    catptr                  long    4
    pstptr                  long    8
    pstptr2                 long    12
    pstptr3                 long    16
    pstptr4                 long    20
    pstptr5                 long    24
    pstptr6                 long    28
    pstptr7                 long    32
    pstptr8                 long    36
    pstptr9                 long    40
    pstptr10                long    44
    pstptr11                long    48
    pstptr12                long    52
    pstptr13                long    56
    pstptr14                long    60
    pstptr15                long    64
    pstptr16                long    68
    
    
    ' 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-24 23:02
    The logic could be written a bit simpler. No point jumping all over the place only to come back a few clocks later. I keep mixing up crank and cam, which one is the 26th-tooth-signal? I assume crank ATM. So given that you finally calculate crank - cam shouldn't you be waiting for a change in crank and then simply sample cam? Otherwise you may end up with sampling peak 2 (post #35) rather than 1 or 3. Correct me if I'm wrong.
    restart                 mov     prevCaGapTime, lastCaGapTime
    
    waitforcavalue          rdlong  lastCaGapTime, catptr                   ' long[ca]
                            cmp     prevCaGapTime, lastCaGapTime WZ, WC     ' compare current to previous cam gap time
    if_ae                   jmp     #waitforcavalue
                            wrlong  lastCaGapTime, pstptr14
    
    waitforcrvalue          rdlong  lastCrGapTime, crtptr                   ' long[cr]
                            cmp     lastCrGapTime, lastCaGapTime WZ, WC     ' compare crank to cam
    if_b                    jmp     #waitforcrvalue                         ' if crank is less than cam, jump to waitforcrvalue
                            wrlong  lastCrGapTime, pstptr13                                      
                            
                            wrlong  lastCrGapTime, pstptr2                  ' write crank to pst
                            mov     lastCrGapTimeT, lastCrGapTime           ' move crank to crank temp
                            wrlong  lastCaGapTime, pstptr3                  ' write cam to pst
                            sub     lastCrGapTimeT, lastCaGapTime           ' subtract cam from crank temp
                            wrlong  lastCrGapTimeT, pstptr                  ' write gaptime to pst
    
                            jmp     #restart
    
    Also, given the number of addresses you resolve in the init phase it may be beneficial to do that in a loop later. It doesn't do any harm right now though.

    As for division by 10, unless you can map that to powers of 2 it's going to be the hard way, e.g. Propeller Manual Appendix B and friends.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-25 08:28
    The reason I have to wait for cam first is because the cam (3 tooth wheel) is 1/2 the frequency rate of the crank (34 tooth wheel).

    I have my cam calculation write a cnt value when tooth 3 of the cam wheel passes
    I have my crank calculation write a cnt value when tooth 26 of the crank wheel passes (which passes twice for each time the cam passes tooth 3 and only 1 of those crank passes is valid)

    The cam is exactly 1/2 the revolution frequency rate of the crank if you were measuring the time from a single tooth to that same tooth the next time around. This is the reason I wait for cam, because I need to compare cam tooth3 to crank tooth 26 when they are very close, not when cam tooth3 is 180 out on the preceding or following time tooth 26 comes around.

    I know this is kind of confusing, and I may not have done a great job explaining it, so I made a diagram even though you probably don't need it to understand. It's pretty terrible as far as artistry, but I think it does well as far as function and might make it easier to picture in your head. :D

    Does that help explain it?


    crankcamdiagram1.jpg



    kuroneko wrote: »
    The logic could be written a bit simpler. No point jumping all over the place only to come back a few clocks later. I keep mixing up crank and cam, which one is the 26th-tooth-signal? I assume crank ATM. So given that you finally calculate crank - cam shouldn't you be waiting for a change in crank and then simply sample cam? Otherwise you may end up with sampling peak 2 (post #35) rather than 1 or 3. Correct me if I'm wrong.
  • kuronekokuroneko Posts: 3,623
    edited 2012-04-25 17:22
    turbosupra wrote: »
    The reason I have to wait for cam first is because the cam (3 tooth wheel) is 1/2 the frequency rate of the crank (34 tooth wheel).

    I have my cam calculation write a cnt value when tooth 3 of the cam wheel passes. I have my crank calculation write a cnt value when tooth 26 of the crank wheel passes (which passes twice for each time the cam passes tooth 3 and only 1 of those crank passes is valid).
    OK, that explains it. Thanks. I was under the impression that each cam tooth (1/2/3) is recorded with timestamp. If it's only ever tooth 3 then the logic is fine.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-01 09:10
    As an update to this (in case it comes up in a search), I keep getting roll over runaway / lockup, so I had to add the following code to make sure when I compare the two numbers, that I was comparing to positive numbers to two positive numbers and subtracting, or two negative numbers to two negative numbers and subtracting.

    I don't know if this is the best way to do it, but it worked after I implemented it and I didn't find a better way when searching through old posts.

    I'm also doing PASM division (thank you Kye) with the second code block, instead of wasting time inside of my com loop with spin division, that way the com loop just spits out data and loops as fast as it can.

                            cmps     lastCrGapTime, zero WZ, WC  ' compare SIGNED to see if number is greater or less than 0                      
    if_nc                   mov     crState, #1               ' greater or equal to 0
    if_nz_and_c             mov     crState, #0               ' less than 0
                            wrlong  crState, pstptr10
    
                            cmps     lastCaGapTime, zero WZ, WC  ' compare SIGNED to see if number is greater or less than 0
    if_nc                   mov     caState, #1               ' greater or equal to 0
    if_nz_and_c             mov     caState, #0               ' less than 0
                            wrlong  caState, pstptr11
    
                            cmp     crState, caState WZ, WC  ' make sure both numbers are greater or less than 0 together
    if_nz                   jmp     #restart                 ' if not equal, bail out and start over
     
    
    
    ' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    '                       Unsigned Divide
    ' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    LNDivide                mov     LNDivideQuotient,       #0                           ' Setup to divide.
                            mov     LNDivideBuffer,         #0                           '
                            mov     LNDivideCounter,        #32                          '
    
                            cmp     LNDivideDivsor,         #0 wz                        ' Clear if dividing by zero.
    if_z                    mov     LNDivideDividend,       #0                           '
    if_z                    jmp     #LNDivide_ret                                        '
                         
    LNDivideLoopPre         shr     LNDivideDivsor,         #1 wc, wz                    ' Align divisor MSB and count size.
                            rcr     LNDivideBuffer,         #1                           '
    if_nz                   djnz    LNDivideCounter,        #LNDivideLoopPre             '
                                                      
    LNDivideLoopPost        cmpsub  LNDivideDividend,       LNDivideBuffer wc            ' Preform division.
                            rcl     LNDivideQuotient,       #1                           '
                            shr     LNDivideBuffer,         #1                           '
                            djnz    LNDivideCounter,        #LNDivideLoopPost            '
                              
                            'wrlong  LNDivideQuotient, pstptr7
                            'wrlong  LNDivideDividend, pstptr8
                            mov     divisionResult, LNDivideQuotient  
    LNDivide_ret            ret                                                          ' Return. Remainder in dividend on exit.
    
    ' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    '                       Unsigned Multiply                            
    ' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    LNMultiply              mov     LNMultiplyProduct,      #0                           ' Clear product.
    
    LNMultiplyLoop          shr     LNMultiplyMultiplicand, #1 wc                        ' Preform multiplication.
    if_c                    add     LNMultiplyProduct,      LNMultiplyMultiplier         '
                            shl     LNMultiplyMultiplier,   #1                           '     
                            tjnz    LNMultiplyMultiplicand, #LNMultiplyLoop              '  
          
    LNMultiply_ret          ret                                                          ' Return.
    
    ' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    '                       Data
    ' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    
    
  • kuronekokuroneko Posts: 3,623
    edited 2012-05-01 16:55
    turbosupra wrote: »
    As an update to this (in case it comes up in a search), I keep getting roll over runaway / lockup, so I had to add the following code to make sure when I compare the two numbers, that I was comparing to positive numbers to two positive numbers and subtracting, or two negative numbers to two negative numbers and subtracting.
    I don't quite see how un/signedness is important with the times involved here. Do you have an example?
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-01 17:45
    Here is what I have from the last time this happened, crank has to always be later then cam, so a smaller negative number or larger positive number, depending on where in the clk cycle we are at and upon rollover it would go positive and not be treated as "later"? And the only way it would unfreeze would be if crank time happened to randomly hit a value between -1 and -162603? It would lock up within 5 minutes of use on both the negative rollover and positive roll over, but I ran it for 3 hours today after this and it did not lock up. What do you think?

    Crank time: -115734
    Cam time: -162604
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-01 17:57
    Maybe the project would help? Pardon the messy messy code and lots of commented out things.

    To duplicate this you could flash a prop with this code, I believe the only additional things needed would be pin 2 feeding pin 3 via a 100ohm resistor and pin 4 feeding pin 5 via a 100ohm resistor.

    I just tested this code and it endlessly looped the first time it rolled over from negative to positive.
  • kuronekokuroneko Posts: 3,623
    edited 2012-05-01 17:59
    turbosupra wrote: »
    Crank time: -115734
    Cam time: -162604

    A (timestamp) difference between cnt values is good for up to 26sec (@80MHz).

    With the above values you get -115734 ($FFFE3BEA) and -162604 ($FFFD84D4), so crank time (the former) is later than cam time (the latter). To avoid the rollover issue you could simply always calculate the delta and do the comparison on the delta. So the first loop can simply check for not equal meaning timestamp has changed, and the second loop reads the timestamp, calculates the delta and goes from there.
  • kuronekokuroneko Posts: 3,623
    edited 2012-05-01 18:17
    turbosupra wrote: »
    I just tested this code and it endlessly looped the first time it rolled over from negative to positive.
    What am I looking for here? comPst2/3 just keep incrementing ... just got a lockup.
  • kuronekokuroneko Posts: 3,623
    edited 2012-05-01 19:10
    Try this:
    '---------------------------------------------------------------
                            rdlong  lastCaGapTime, catPtr           ' long[ca] preset
    restart                 mov     prevCaGapTime, lastCaGapTime
    
    :again                  rdlong  lastCaGapTime, catPtr           ' long[ca]
                            cmp     prevCaGapTime, lastCaGapTime wz ' compare current cam gap time to previous cam gap time
                    if_e    jmp     #:again                         ' no change yet
    
                            wrlong  lastCaGapTime, pstptr14         ' communicate current value
    
    waitforcrvalue
    :again                  rdlong  lastCrGapTime, crtPtr           ' long[cr]
                            mov     tmp1, lastCrGapTime             ' copy
                            sub     tmp1, lastCaGapTime             ' calculate delta
                            cmps    tmp1, #0 wc                     ' check sign
                    if_c    jmp     #:again                         ' negative, try again
    
                            wrlong  lastCrGapTime, pstptr13         ' communicate current value
    '---------------------------------------------------------------
    
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-01 19:12
    comPst2 (crank) and comPst3 (cam) are constantly comparing cnts (with comPst2 being "later") and comPst2-comPst3 is printed at comPst. A calc is then done against comPst to output a difference converted to degrees at comPst4.

    Does that make sense? I'm working on putting labeled information at the top of the screen as we speak so that it's easier to interpret, but it isn't done yet :)
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-01 19:59
    Thank you. I'm going to compare tomorrow at work where I have a few monitors and try and figure out how my code was shrunk so dramatically :D so I can learn.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-02 07:06
    This is great Kuroneko, and it flows more logically from top to bottom as well ... thank you for all of your help.



    trigun_kuroneko.jpgBow-001.jpg
Sign In or Register to comment.