Shop OBEX P1 Docs P2 Docs Learn Events
Looking to translate spin to PASM — Parallax Forums

Looking to translate spin to PASM

turbosupraturbosupra Posts: 1,088
edited 2012-04-07 21:51 in Propeller 1
Hi,

I have a method (actually two) that are written in spin, they works well but they are too slow for what I need. Unfortunately they involve a lot of math and I'd like to add even more math, and from what I've read in the manual, PASM math/comparisons are pretty difficult for a PASM beginner.

Also I'm about to start trying to translate them to PASM and I'm used to troubleshooting with the PST, how do you debug PASM?


PUB calculateCrankRpm(localCrankPeriod) | elapsed

    elapsed := -cnt

    l_previousNum8 := l_previousNum7 
    l_previousNum7 := l_previousNum6
    l_previousNum6 := l_previousNum5
    l_previousNum5 := l_previousNum4
    l_previousNum4 := l_previousNum3
    l_previousNum3 := l_previousNum2
    l_previousNum2 := l_current
    l_current := localCrankPeriod


    if (l_timeStampCrank == 0)
      l_timeStampCrank := (cnt + clkfreq)

    if (l_previousNum8 <> 0 and l_previousNum7 <> 0 and l_previousNum6 <> 0 and l_previousNum5 <> 0 and l_previousNum4 <> 0 and l_previousNum3 <> 0 and l_previousNum2 <> 0)
      l_previous7average := ((l_previousNum8 + l_previousNum7 + l_previousNum6 + l_previousNum5 + l_previousNum4 + l_previousNum3 + l_previousNum2)/7)
  
      if (((l_current/10)*100) > ((l_previous7average/10)* 110)) or (((l_current/10)*100) < ((l_previous7average/10)*90))
        ' GAP exists if current  greater than 110% of average    or     current  less than 90% of average

        l_gapTimePrevious := l_gapTime
        l_gapTime := cnt  
        l_current := l_previous7average
       
      else

        
               
        if (((clkfreq/l_current)*60)/36) < 200
          pst.str(string("crap2"))
          pst.char(13)
       
        else

          l_toothRpm := (((clkfreq/l_previous7average)*60)/36)

      elapsed += cnt - 544

PUB calculateCamRpm(localCamPeriod)


  
  if(localCamPeriod) <> 0 and l_pstReadCamWheel == 1 
    l_previousCam6 := l_previousCam5
    l_previousCam5 := l_previousCam4
    l_previousCam4 := l_previousCam3
    l_previousCam3 := l_previousCam2
    l_previousCam2 := l_currentCam
    l_currentCam := localCamPeriod
      
    {pst.dec(l_previousCam6) ' 2324128   ' 2323968   ' 4546304   ' 2324128
    pst.char(13)
    pst.dec(l_previousCam5)  ' 2323968   ' 4546304   ' 2324128   ' 2323968
    pst.char(13)
    pst.dec(l_previousCam4)  ' 4546304   ' 2324128   ' 2323968   ' 4546304
    pst.char(13)
    pst.dec(l_previousCam3)  ' 2324128   ' 2323968   ' 4546304   ' 2324128
    pst.char(13)
    pst.dec(l_previousCam2)  ' 2323968   ' 4546304   ' 2324128   ' 2323968
    pst.char(13)
    pst.dec(l_currentCam)    ' 4546304   ' 2324128   ' 2323968   ' 4546304
    pst.char(13)
    pst.char(13)} '(average) ' 2768499   ' 3212934   ' 3212966

            '     4546304 is 1.65% of 2768499 and 2323968 is 83% of 2768499
            '     4546304 is 1.42% of 3212934 and 2323968 is 72% of 3212934
            '     4546304 is 1.42% of 3212966 and 2323968 is 72% of 3212966 
        
      if l_previousCam6 <> 0 and l_previousCam5 <> 0 and l_previousCam4 <> 0 and l_previousCam3 <> 0 and l_previousCam2 <> 0

        l_CamToothAverage := ((l_previousCam6+l_previousCam5+l_previousCam4+l_previousCam3+l_previousCam2/5))
        'if (((l_currentCam/10)*100) =< ((l_CamToothAverage/10)*105)) and (((l_currentCam/10)*100) => ((l_CamToothAverage/10)*95))
        if (((l_currentCam/10)*100) =< ((l_CamToothAverage/10)*170)) or (((l_currentCam/10)*100) => ((l_CamToothAverage/10)*70))
             '(768/10)*100 [7600]   =<  (3812614/10)*170 [40032405]  or   (768/10)*100 [7600]   =>  (3812614/10)*95 [36219795]
                             '   less than 105% of average           or                    greater than 70% of average
          ' trigger1/(cba) 
          '              c > b*1.1               and             c  > a*1.1
          if((l_currentCam*100) > (l_previousCam2*110)) and ((l_currentCam*100) > (l_previousCam3*110)) and (l_trigger1 <> true)
            if((l_previousCam2*100) < (l_previousCam3*105)) and ((l_previousCam2*100) > (l_previousCam3*95))  ' b < a*1.1 and b > a*.95
              l_trigger1 := true
              l_trigger2 := false
              l_trigger3 := false
              
              
          '  trigger2/(acb)    
          '          a*1.1 < c            
          if((l_currentCam*110) < (l_previousCam2*100)) and (l_trigger2 <> true)
            if(((l_currentCam*100) < (l_previousCam3*105)) and ((l_currentCam*100) > (l_previousCam3*95)))  ' a < b*1.05 and a > b*.95
              if((l_previousCam2*100) > (l_previousCam3*110)) 'c > b*1.1
                l_trigger2 := true
                l_trigger3 := false
                l_trigger1 := false
                 

          ' trigger3/(bac)      
          '               b < a*1.05              and             b > a*.95                             b*1.1 < c
          if(((l_currentCam*100) < (l_previousCam2*105)) and ((l_currentCam*100) > (l_previousCam2*95))) and ((l_currentCam*110) < (l_previousCam3*100)) and (l_trigger3 <> true) 
            if((l_previousCam2*110) < (l_previousCam3*100)) ' a*1.1 < c
              l_trigger3 := true
              l_trigger1 := false
              l_trigger2 := false
              
              
          if(l_trigger3 == true)and(l_trigger1 == false)and(l_trigger2 == false)
            l_calculatedCamRpm := (((clkfreq/((l_currentCam+l_previousCam2+l_previousCam3)/10))*120)/10)  ' or ((((clkfreq/1+2+3)*10)*120)/10)
            l_trigger3 := false
            
        else
          
          l_currentCam := l_CamToothAverage 
       

    

Comments

  • JonnyMacJonnyMac Posts: 9,197
    edited 2012-04-07 11:50
    I doubt it's the calculations that are the problem; the real timing crunch is coming from sending serial data from that method. What I tend to do is create a debugging cog that runs serial output autonomously, picking up values from the global space to output. This way the methods I'm running are just doing math, not waiting on serial output.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-07 12:30
    Ok, over the last hour I've tried to translate the first method into PASM

    I'm not sure how to do the math, so my code does not compile because the compiler tells me my compare math is exceeding the registers 9 bits (511) storage location . Are you able to use operators in PASM like you can in spin?

    I also do not see a way to have clkfreq in PASM, although I'm sure there is a way, I used 80000000 temporarily instead.

    How bad does this PASM code look? *hides behind rock* :)
    DAT
    
    
                            org     0
    
    frcntr                  mov     tmp1, par                       ' * start of structure, passes an address to the value par represents and copies that address to tmp1
                            rdlong  tmp2, tmp1                      ' * get beginning variable address location, copy into tmp2
    
    
    start
    
                            mov     previousNum8, previousNum7                      ' l_previousNum8 := l_previousNum7
                            mov     previousNum7, previousNum6                      ' l_previousNum7 := l_previousNum6
                            mov     previousNum6, previousNum5                      ' l_previousNum6 := l_previousNum5
                            mov     previousNum5, previousNum4                      ' l_previousNum5 := l_previousNum4
                            mov     previousNum4, previousNum3                      ' l_previousNum4 := l_previousNum3
                            mov     previousNum3, previousNum2                      ' l_previousNum3 := l_previousNum2
                            mov     previousNum2, current                           ' l_previousNum2 := l_current
                            mov     current, jmfreqperiod                           ' l_current := localCrankPeriod
          
                            cmp     previousNum8, #0 WZ, WC                         ' z=0, c=0              l_previousNum8 <> 0  
    IF_NC_AND_NZ            jmp     #seven
    IF_C_OR_Z               jmp     #start
    
    seven
                            cmp     previousNum7, #0 WZ, WC                         ' z=0, c=0              l_previousNum7 <> 0
    IF_NC_AND_NZ            jmp     #six
    IF_C_OR_Z               jmp     #start
    
    six
                            cmp     previousNum6, #0 WZ, WC                         ' z=0, c=0              l_previousNum6 <> 0
    IF_NC_AND_NZ            jmp     #five
    IF_C_OR_Z               jmp     #start
    
    five
                            cmp     previousNum5, #0 WZ, WC                         ' z=0, c=0              l_previousNum5 <> 0
    IF_NC_AND_NZ            jmp     #four
    IF_C_OR_Z               jmp     #start
    
    four
                            cmp     previousNum4, #0 WZ, WC                         ' z=0, c=0              l_previousNum4 <> 0
    IF_NC_AND_NZ            jmp     #three
    IF_C_OR_Z               jmp     #start
    
    three
                            cmp     previousNum3, #0 WZ, WC                         ' z=0, c=0              l_previousNum3 <> 0
    IF_NC_AND_NZ            jmp     #two
    IF_C_OR_Z               jmp     #start
    
    two
                            cmp     previousNum2, #0 WZ, WC                         ' z=0, c=0              l_previousNum2 <> 0
    IF_NC_AND_NZ            jmp     #sevenAvg
    IF_C_OR_Z               jmp     #start
    
    
    sevenAvg
    
                            add     previous7Avg, previousNum8                      ' l_previous7average + l_previousNum8
                            add     previous7Avg, previousNum7                      ' l_previous7average + l_previousNum7 
                            add     previous7Avg, previousNum6                      ' l_previous7average + l_previousNum6 
                            add     previous7Avg, previousNum5                      ' l_previous7average + l_previousNum5 
                            add     previous7Avg, previousNum4                      ' l_previous7average + l_previousNum4 
                            add     previous7Avg, previousNum3                      ' l_previous7average + l_previousNum3 
                            add     previous7Avg, previousNum2                      ' l_previous7average + l_previousNum2 
                            mov     previous7Avg, (previous7Avg/7)                  ' l_previous7average := (l_previous7average/7)  
    
                            'cmp     ((current/10)*100), ((previous7Avg/10)*110) WZ, WC     ' check for gap/to see if current is greater than 110% of average
    IF_BE                   jmp     #greaterThan90                                  ' jump to see if it is greater than 90% of average
    IF_A                    jmp     #gap                                            ' gap detected, jump to gap
    
    greaterThan90                       
                            cmp     ((current/10)*100), ((previous7Avg/10)*90)      ' check for gap/to see if current is greater than 110% of average
    IF_AE                   jmp     #notGap                                         ' it is smaller than 110% of avg and greater than 90% of avg, not a gap, go to notGap
    IF_B                    jmp     #gap                                            ' gap detected, jump to gap   
    
    gap
                            mov     gapPreviousTime, gapTime                        ' this is to keep track of time
                            mov     gapTime, cnt                                    ' this is to keep track of time
    
    notGap
                            'cmp     (((80000000/current)*60)/36), #200'if (((clkfreq/l_current)*60)/36) < 200
    IF_BE                   jmp     #start                                          ' if below 200, restart
    'IF_A                    mov     toothRpm, (((80000000/previous7Avg)*60)/36)'l_toothRpm := (((clkfreq/l_previous7average)*60)/36)
    
    
    
    ' --------------------------------------------------------------------------------------------------
    
    
    
    current                 long    0
    previousNum2            long    0
    previousNum3            long    0
    previousNum4            long    0
    previousNum5            long    0
    previousNum6            long    0
    previousNum7            long    0
    previousNum8            long    0
    previous7Avg            long    0
    jmfreqperiod            long    0               ' jmfreqperiod is a place holder for a value from another cog, I don't know how to pass that yet
    
    gapPreviousTime         long    0
    gapTime                 long    0
    
    toothRpm                long    0
    
    
    
    tmp1                    res     1
    tmp2                    res     1
    
    mask                    res     1                               ' mask for frequency input pin
    
    
    
                            fit     492
    
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-07 12:35
    Hi Jon,

    Although you are probably right, I only left that PST code in there because it had table data that I needed to reference, I am not using that to send debug data to the PST. I am actually using this method below (in its own cog) for that, which I believe is similar to the way you are describing that you debug.
    PUB com | timeStamp
    
      pst.Start(115_200)
      pst.Clear
      pst.str(string("Start"))
      pst.Str(String(pst#NL))
      
      initScreen
      
      l_updateRateDenominator := 2000
       
      timeStamp := cnt
    
      repeat
    
        if((cnt-timeStamp) > (clkfreq/l_updateRateDenominator))
        
          timeStamp := cnt
          pst.Dec(l_toothGapRpm)
          pst.char(13) 
          pst.str(string("crank: "))
           pst.Dec(l_toothRpm)
          pst.char(13)
          pst.str(string("cam: "))
          pst.Dec(l_calculatedCamRpm) 
           pst.char(13)
          
          if (l_CntPeakRead == false)
            pst.dec(l_CntPeak)
            pst.char(13)
            pst.dec(cnt)
            pst.char(13)
            l_CntPeakRead := true
            l_CntPeak := 0
    
          else
            pst.str(string("read"))
            pst.char(13) 
            
          pst.str(@b_waitingToBeParsed)
          pst.char(13)
          pst.char(13)  
    
             
       
        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    
     
    

    JonnyMac wrote: »
    I doubt it's the calculations that are the problem; the real timing crunch is coming from sending serial data from that method. What I tend to do is create a debugging cog that runs serial output autonomously, picking up values from the global space to output. This way the methods I'm running are just doing math, not waiting on serial output.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-04-07 12:46
    There are some things you can do to make your Spin code more efficient. For example, this code
        l_previousNum8 := l_previousNum7 
        l_previousNum7 := l_previousNum6
        l_previousNum6 := l_previousNum5
        l_previousNum5 := l_previousNum4
        l_previousNum4 := l_previousNum3
        l_previousNum3 := l_previousNum2
        l_previousNum2 := l_current
        l_current := localCrankPeriod
    

    collapses neatly into
    movelong(@l_previousNum2, @l_current, 7)
    l_current := localCrankPeriod
    
    assuming those variables are longs, are declared thus, and in this order:
    VAR
    
      long l_current, l_previousNum2, l_previousNum3, l_previousNum4, l_previousNum5, l_previousNum6, l_previousNum7, l_previousNum8
    
    The Spin compiler makes sure that the move is done in the correct order to avoid toe-stepping when the ranges overlap.

    Also, the "<> 0" in this if statement is redundant:
    if l_previousCam6 <> 0 and l_previousCam5 <> 0 and l_previousCam4 <> 0 and l_previousCam3 <> 0 and l_previousCam2 <> 0
    
    The ands take care of that for you.

    Also, doing 32-bit multiplies and divides in PASM won't save you that much time, since the Spin byte-code interpreter does them in assembly anyway. However, you could save time is by hard-coding the multiplications by constants using predetermined shifts and adds.

    -Phil
  • Mike GreenMike Green Posts: 23,101
    edited 2012-04-07 12:47
    CLKFREQ is the long in location zero. If you want a binary fraction of that, it's easy in assembly, just do a SHR on a copy of it. If you want a decimal fraction or something more complicated, compute it in Spin and store it into the assembly code DAT section before you do the COGNEW on it.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-07 12:54
    Also, to give some example code of what I'm monitoring/working with, I'm able to perfectly replicate my cars cam and crank trigger sensors now on the propscope, with the code below. Worst case scenario has 9000 events per second or 1 event every 8888 clkcyles at clkfreq = 80,000,000. I have to do a fair amount of math inside of this window.


    cognew(simulateCamWheel(2, 15000, 2, 72, 72, 159, 19), @simulateCamWheelstack) (pin, rpm, cam rotations:crank rotations ratio, degrees from 0 degrees, degrees from first trigger, degrees from second trigger, actual metal trigger width in degrees)
    cognew(simulateCrankWheel(4, 36, 2, 15000), @simulateCrankWheelStack) (pin, total teeth, missing teeth, rpm)
    PUB simulateCamWheel(simCamWheelPinNum, engineRPM, crankRotsToCamRots, degreeOfTrigger1, degreeOfTrigger2, degreeOfTrigger3, camTriggerDegreeWidth) | localIndex1, crankRpmPerSecond, camRpmPerSecond, localCnt, trigger1Wait, trigger2Wait, trigger3Wait, emtpySpace1Wait, emtpySpace2Wait, emtpySpace3Wait, cyclesPerDegOfRot
    
      
      dira[simCamWheelPinNum]~~
      outa[simCamWheelPinNum]~
      localIndex1 := 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
    
      trigger1Wait := (camTriggerDegreeWidth*cyclesPerDegOfRot)                     ' 13300 / 5 degrees
      trigger2Wait := (camTriggerDegreeWidth*cyclesPerDegOfRot)                     ' 13300 / 5 degrees
      trigger3Wait := (camTriggerDegreeWidth*cyclesPerDegOfRot)                     ' 13300 / 5 degrees
      emtpySpace1Wait := (degreeOfTrigger1*cyclesPerDegOfRot)                       ' 266000 / 100 degrees
      emtpySpace2Wait := (degreeOfTrigger2*cyclesPerDegOfRot)                       ' 266000 / 100 degrees 
      emtpySpace3Wait := (degreeOfTrigger3*cyclesPerDegOfRot)                       ' 385700 / 145 degrees    
                                                                                    ' + = 957600   (((clkfreq/957600) * 60sec/min) * 2rots campercrank) = 10krpm
     
      localCnt := cnt                                      
    
      repeat
    
        outa[simCamWheelPinNum]~~
        waitcnt(localCnt += trigger1Wait)                ' 6665                
        outa[simCamWheelPinNum]~
        'waitcnt(localCnt += (clkfreq/521))                  ' 160000-6665 
        waitcnt(localCnt += emtpySpace1Wait)
        outa[simCamWheelPinNum]~~
        waitcnt(localCnt += trigger2Wait)                ' 6665
        outa[simCamWheelPinNum]~
        'waitcnt(localCnt += (clkfreq/521))                  ' 160000-6665 
        waitcnt(localCnt += emtpySpace2Wait)
        outa[simCamWheelPinNum]~~
        waitcnt(localCnt += trigger3Wait)                ' 6665
        outa[simCamWheelPinNum]~
        'waitcnt(localCnt += (clkfreq/521))                  ' 160000-6665 
        waitcnt(localCnt += emtpySpace3Wait)
    
    
    PUB simulateCrankWheel(simCrankWheelPinNum, crankTeethSimToothCnt, crankTeethSimMissingToothCnt, crankTeethSimRPM) | localIndex, waitTime, logicHighWaitTime, logicLowWaitTime, logicHighGapWaitTime, logicLowGapWaitTime, startCnt, existingTeeth 
     
    
      
       ' Initialize variables here 
      dira[simCrankWheelPinNum]~~
      outa[simCrankWheelPinNum]~
      localIndex := 0
      waitTime := (clkfreq/((crankTeethSimRPM*(crankTeethSimToothCnt*2))/60))  ' for 1500rpm = 44444
      logicHighWaitTime := ((waitTime/50)*45) 
      logicLowWaitTime := ((waitTime/50)*55)
      logicHighGapWaitTime := ((((waitTime*6)/100)*43)-logicHighWaitTime) ' this percentage can be measured by a prop scope and a signal capture
      logicLowGapWaitTime := ((((waitTime*6)/100)*57)-logicLowWaitTime)
      existingTeeth := (crankTeethSimToothCnt - crankTeethSimMissingToothCnt)
      
      startCnt := cnt
    
      {ctra := (%00100 << 26) | simCrankWheelPinNum                                  ' setup counter for pin
      frqa := 1                                                                     ' this makes the cnt screw up every 26 seconds                                      
      phsa := 0}
    
      {
        This is for a Hall effect signal/sensor simulation
        For 1000rpms on a 36-2 crank trigger wheel, it'd be (1000(36*2)) = 72000, then 72000/60 = 1200 teeth on/teeth off per clkfreq. 80000000(clkfreq)/1200 =
        a tooth on or tooth off every 133333.3 clk cycles. It would be on for 66666.67 clk cycles and then was off for every 66666.67 clk cycles  
        So you'd loop on for 66666.67 cycles and then off for 66666.67 cycles and after 34 times, you'd wait for 66666.67 cycles * 4, to simulate the 2
        missing teeth on and accompanying 2 "missing" teeth off (or gaps in between each tooth) . It should account for 2 missing teeth and 3 missing toothgaps
        An example to start the method would be simulateCamWheel(7, 3, 105, 100)
      }
      
     
      repeat
    
        repeat localIndex from 1 to (existingTeeth)    ' loop number of physical teeth on and off  
          outa[simCrankWheelPinNum]~~
          'l_crankTeethSimOn := startCnt
          waitcnt(startCnt += logicHighWaitTime)              ' on for 1 tooth
          outa[simCrankWheelPinNum]~
          'l_crankTeethSimOff := startCnt
          waitcnt(startCnt += logicLowWaitTime)               ' off for 1 tooth
          
     
        repeat localIndex from 1 to 1'(crankTeethSimMissingToothCnt)                             ' loop number of times for each missing tooth
          outa[simCrankWheelPinNum]~
          'l_crankTeethSimOff := startCnt
          waitcnt(startCnt += logicLowGapWaitTime)            ' off for 57% of 2 teeth
          outa[simCrankWheelPinNum]~~
          'l_crankTeethSimOff := startCnt
          waitcnt(startCnt += logicHighGapWaitTime)           ' on for 43% of 2 teeth
          
    
    
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-07 13:00
    Thanks for the replies

    @Phil

    Can you explain why the below saves time, and if there is a way to estimate how much time it does save? I will incorporate your time savings into my code now.
    longmove(@l_previousNum2, @l_current, 7)
    l_current := localCrankPeriod
    

    Also, if I remove the <>, couldn't it run through the code if just one value wasn't equal to 0, because then the sum would not then equal 0? I need to check and make sure they are not equal to 0 individually, to make sure I have cycled through 7 times and there are 7 different values.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-07 14:43
    Another question ... How do you fix this line of code so it does not generate the error "cannot exceed $1FF" ? Isn't there a way to do mov or cmp with more than 9 bits of data?
    cmp     ((current/10)*100), ((previous7Avg/10)*110) WZ, WC
    
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-04-07 16:01
    turbosupra wrote:
    Can you explain why the below saves time ...
    It saves time because the Spin byte-code interpreter executes the entire move in assembly, rather than interpreting each assignment separately. You can use cnt before and after a block of code to measure how much time it takes.
    turbosupra wrote:
    Also, if I remove the <>, couldn't it run through the code if just one value wasn't equal to 0, because then the sum would not then equal 0?
    No. The logical and operator does not operate bitwise like the "&" operator does. Each of and's operands is deemed to be "true" if it's non-zero.

    -Phil
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-07 17:52
    Thank you, I have this as part of my code now and I believe it still isn't fast enough, my com cog should be reading ~ 320000 cycles all the time, but sometimes it reads ~ 650000 ~ 970000 or even ~ 1280000, which means it is missing events. Also thanks for the explanation about longmove, that is cool, I did not know that.

    I have the loop taking 27888 to 33216 cycles from start to end (more 33216 then 25056) and I need it to happen (this is worst case of course) in less than 8888 or even 1/2 that if I use cog stopping commands like waitpeq. I'm looking for a second and third opinion though ... What do you all think?

    In case you were curious, when I was using the := way of transferring variable values, method time was either 25056 or 30384, so your long move saves me 2832 cycles :)

    The <> part of the code saves me an additional 1920 cycles at 23136 or 28464.

    I removed one of the if statements just to time it [if (((clkfreq/l_current)*60)/36) < 200] ... should that take 3696 cycles?


     longmove(@l_previousNum2, @l_current, 7)
        l_current := localCrankPeriod  
    
        if (l_timeStampCrank == 0)
          l_timeStampCrank := (cnt + clkfreq)
    
        if (l_previousNum8 <> 0 and l_previousNum7 <> 0 and l_previousNum6 <> 0 and l_previousNum5 <> 0 and l_previousNum4 <> 0 and l_previousNum3 <> 0 and l_previousNum2 <> 0)
          l_previous7average := ((l_previousNum8 + l_previousNum7 + l_previousNum6 + l_previousNum5 + l_previousNum4 + l_previousNum3 + l_previousNum2)/7)
      
    
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-04-07 18:38
    Unless you really need the truncation resulting from the divide, why not change
    if (((clkfreq/l_current)*60)/36) < 200
    

    to
    if (clkfreq < 120 * l_current)
    
    

    or, better yet,
    factor := clkfreq / 120      'Way at the beginning of your program.
    ...
    if (factor < l_current)
    

    clkfreq may not be evenly-divisible by 120, but it may not matter.

    -Phil
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-07 19:04
    The math doesn't work out that way, for example at 15000rpm, l_current would be 8888

    if (((clkfreq/l_current)*60)/36) < 200 is the same as 15000 < 200

    if (clkfreq < 120 * l_current) is the same as 80000000 < 1066560

    Maybe I'm missing something?




    I guess more importantly though, is it normal for that operation to take 3600 cycles? And is my loop time math correct from the post quoted below?
    Also, to give some example code of what I'm monitoring/working with, I'm able to perfectly replicate my cars cam and crank trigger sensors now on the propscope, with the code below. Worst case scenario has 9000 events per second or 1 event every 8888 clkcyles at clkfreq = 80,000,000. I have to do a fair amount of math inside of this window.


    cognew(simulateCamWheel(2, 15000, 2, 72, 72, 159, 19), @simulateCamWheelstack) (pin, rpm, cam rotations:crank rotations ratio, degrees from 0 degrees, degrees from first trigger, degrees from second trigger, actual metal trigger width in degrees)
    cognew(simulateCrankWheel(4, 36, 2, 15000), @simulateCrankWheelStack) (pin, total teeth, missing teeth, rpm)
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-04-07 19:30
    turbosupra wrote:
    The math doesn't work out that way, for example at 15000rpm, l_current would be 8888

    if (((clkfreq/l_current)*60)/36) < 200 is the same as 15000 < 200

    if (clkfreq < 120 * l_current) is the same as 80000000 < 1066560

    Maybe I'm missing something?
    Yes, you are. :) Both statements, given your example figures, are false, are they not? The important thing to consider is where the threshold is located. In the first case, it will be where
    (((clkfreq/l_current)*60)/36) == 200

    But, by working though the algebra, that's the very same thing as saying
    clkfreq == 200 * 36 / 60 * i_current == 120 * l_current

    -Phil
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-07 20:31
    I still don't understand :)

    Ok, so if you did 180rpm, which it should be true
    180rpm = 3 revolutions per second or 1 revolution every 26666666 clk cycles

    if (clkfreq < 120 * l_current) or 80,000,000 < 3,199,999,920


    But if you went to 240rpm, which should be false (but is true)
    240rpm = 4 revolutions per second or 1 revolution every 20000000 clk cycles
    if (clkfreq < 120 * l_current) or 80,000,000 < 2,400,000,000

    I think it will evaluate to true until it is greater than 7200rpm or 1 revolution every 666666 clk cycles, when it should be evaluating to false at anything above 200rpm?



    I am probably missing something still, so don't be insulted by the additional questions please, I'm asking again because I want to learn/understand.



    Yes, you are. :) Both statements, given your example figures, are false, are they not? The important thing to consider is where the threshold is located. In the first case, it will be where
    (((clkfreq/l_current)*60)/36) == 200

    But, by working though the algebra, that's the very same thing as saying
    clkfreq == 200 * 36 / 60 * i_current == 120 * l_current

    -Phil
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-04-07 21:11
    Well, check the math with your formula, then:
    clkfreq / i_current * 60 / 36 < 200, with i_current == 20_000_000 (240 rpm)
    80_000_000 / 20_000_000 * 60 / 36 == 6 (integer), which is less than 200

    -Phil
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-07 21:51
    I've been at this all day and just need to sleep on it. I see my error now. Ugh!

    240rpm = 1 tooth every 555555 cycles, and I originally did 4 revolutions and 26666666 which was wrong, sorry about that.
    180rpm = 1 tooth every 740740 cycles

    (clkfreq < 120 * l_current)
    80000000 < 120 * 740740 = 80,000,000 < 88,888,800 - TRUE for 180rpm
    80000000 < 120 * 555555 = 80,000,000 < 66,666,600 - FALSE for 240rpm

    I appreciate your patience, thanks for sticking with me on this :D



    Does spin have the speed to do calculations within 8888 clk cycles or possibly 1/2 that?
Sign In or Register to comment.