Shop OBEX P1 Docs P2 Docs Learn Events
Spin to PASM code conversion help for Ping Sensor — Parallax Forums

Spin to PASM code conversion help for Ping Sensor

Tony B.Tony B. Posts: 356
edited 2011-08-30 05:00 in Propeller 1
I am working to learn PASM and need some help with a line of code from the Ping.spin object available with the Propeller tool Library. The line I am having trouble translating is the following line which involves division of two values located at the end of PUB Ticks.

Microseconds := (||(cnt1 - cnt2) / (clkfreq / 1_000_000)) >> 1

I have researched the issue online and studied the math examples in appendix B of the Propeller Manual and understand that division is done by subtraction. Having never written this type of code I am not familiarwith the process of using subtraction to do division nor how to translate it into PASM. Also, unlike the example in the Propeller Manual I'm not concerned with the remainder, but just need the absolutevalue like the "||" gives in the Spin code. In other words do I use "||" in PASM and if so, how?

Since I will be running at 80Mhz I can evaluate the second value, clkfreq/1_000_000, but the first will be different each time. I also understand that shifting the final value 1 place to the right is like dividing by 2 those removing the return time in the value.

I will first use this code on my Spin Stamp BOE-Bot that I am programing completely in PASM. I have the servos working and hopefully the Ping sensor and will have it roaming around in no time. Then I plan on adding a Serial LCD and will have to learn how to do simple bit banging. Been studying and working on the code, but may need some help in the future. But I will work on one issue at a time.

Guidance and help would be most appreciated. :smile:

Thanks,
Tony

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2011-08-29 17:56
    This should get you started. It uses the division code from the manual (32bit/16bit).
    VAR
      long  storage
      
    PUB null
    
      cognew(@entry, @storage)
      repeat until storage
    
      dira[16..23]~~
      repeat                                        ' display result
        outa[16..23] := storage <-= 8
        waitcnt(clkfreq/2 + cnt)
      
    DAT             org     0
    
    entry           mov     x, cnt                  ' cnt1
    
                    mov     cnt, #256               ' |
                    shl     cnt, #10                ' |
                    add     cnt, cnt                ' |
                    waitcnt cnt, #0                 ' get some distance
                    
                    sub     x, cnt                  ' cnt1 - cnt2
                    abs     x, x                    ' ||(cnt1 - cnt2)
    
                    mov     y, #80
                    call    #divide                 ' ||(cnt1 - cnt2)/80
    
                    and     x, mask                 ' high word is remainder
                    shr     x, #1                   ' (||(cnt1 - cnt2)/80) >> 1
    
                    wrword  x, par                  ' report result
    
                    cogid   cnt                     '
                    cogstop cnt                     ' sayonara
    
    ' Divide x[31..0] by y[15..0] (y[16] must be 0)
    ' on exit, quotient is in x[15..0] and remainder is in x[31..16]
    '
    divide          shl     y, #15                  ' get divisor into y[30..15]
                    mov     t, #16                  ' ready for 16 quotient bits
    :loop           cmpsub  x, y wc                 ' y =< x? Subtract it, quotient bit in c
                    rcl     x, #1                   ' rotate c into quotient, shift dividend
                    djnz    t, #:loop               ' loop until done
    divide_ret      ret                             ' quotient in x[15..0],
                                                    ' remainder in x[31..16]
    mask            long    $0000FFFF
    
    x               res     1
    y               res     1
    t               res     1
    
                    fit
    
    DAT
    
  • Tony B.Tony B. Posts: 356
    edited 2011-08-30 04:46
    kuroneko Thank you for your quick repy and willingness to help.

    I've been studying your code and I have a question concerning your use of "cnt". I understand "cnt" to be a reserve word for the system counter register and is a read-only register never to be used as a destination register. It appears to me that you are using it in this way. Your wellingness to help me understand this bit of code would be most appreciated.
     
                 mov     cnt, #256               ' |
                    shl     cnt, #10                ' |
                    add     cnt, cnt                ' |
                    waitcnt cnt, #0                 ' get some distance
                    sub     x, cnt                  ' cnt1 - cnt2
                    abs     x, x                    ' ||(cnt1 - cnt2)
    


    Thanks,
    Tony
  • kuronekokuroneko Posts: 3,623
    edited 2011-08-30 04:50
    cnt used in the destination slot of an instruction will not access the system counter but its shadow register instead (a free register). As all calculations re: waitcnt are done with it in the destination slot it's safe to do so (maybe a bit showy though). It's equivalent to
    mov     [COLOR="orange"]tmp[/COLOR], #256
    shl     [COLOR="orange"]tmp[/COLOR], #10
    add     [COLOR="orange"]tmp[/COLOR], cnt
    waitcnt [COLOR="orange"]tmp[/COLOR], #0
    
    with tmp being an ordinary register (below $1F0). I could have used par and ina as well (same shadow effect, usually I use par when I have to write zero to a hub location wrlong par, addr).
  • Tony B.Tony B. Posts: 356
    edited 2011-08-30 05:00
    Thank you very much! I had never thought of cnt as a free register before. Very clever. I hope to work with the code tonight.

    Thanks,
    Tony
Sign In or Register to comment.