Shop OBEX P1 Docs P2 Docs Learn Events
Two Qs regarding jm_ez_spi_demo code. Division and Rev operation — Parallax Forums

Two Qs regarding jm_ez_spi_demo code. Division and Rev operation

Hi, All.

Long-time Propeller 1 user (dozens of successful projects), now playing with Propeller 2 Edge Module. I will eventually be writing code to communicate via SPI with the Adc-6-Click (https://www.mikroe.com/adc-6-click) an 8-ch 24-bit ADC. If anyone has already written code for this device please let me know, I would hate to re-invent the wheel !

I'm using Johnny Mac's jm_ez_spi demo code as a starting point for learning P2 coding.

I have two hopefully-simple-to-answer questions after taking a deep dive into his code:

Q1: Within jm_ez_spi.spin2 file:
At function: pub start(sdipin, sdopin, sckpin, khz) : result | m, x
There is a line of code:
x.word[0] := 2 #> (clkfreq / (khz*1000)) <# $FFFF ' ticks in period
I have a question regarding the division operator "/" in P2.
The Spin2 documentation file shows:
"/" as a "signed divide, return quotient"
and "float expr" is checked.
Elsewhere: "Floats are encoded in IEEE-754 single-precision 32-bit format"
P2 Feature Description: "2-clock execution for all math and logic instructions, including 16 x 16 multiply"
MY QUESTION is in regards to how P2 handles division in general.
Is 16-bit division operation built-in to the P2 assembly ? (I don't think so)
Has Chip incorporated a division routine into his SPIN2 implementation ?
I was not expecting the "/" operation to work for non-constant operations
(in other words, I thought it would be restricted to compile-time only use, like the P1).
So how should I understand the availability of integer division in SPIN2 ?

Q2: Within jm_ez_spi.spin2 file:
At function: pub shiftin(mode, bits) : value
There is a line of code:
value rev= 31
The Spin2 doc file explains: for "var REV= y" : "Reverse y LSBs of x and zero-extend"
I assumed that to reverse the bit position for all 32 bits the expression should read:
"value rev= 32"
I modified the code, and of course it bombed, so "31" is obviously correct.
MY QUESTION:
Should the documentation file be changed to read "Reverse y+1 LSBs of x and zero-extend" ?

Thanks for any guidance you may have to offer. Looking forward to using the P2 in a lot of future work.

Greg

Comments

  • Please use code where necessary. Surround with one backtick for inline, three for a block.

  • Q1 This is spin code.
    Assembler has a fast 16*16 hardware multiply and a slower cordic hardware multiply and division.
    P2 Manual gives some hints about cordic.

  • @greg_physics said:
    Q1: ... MY QUESTION is in regards to how P2 handles division in general.
    Is 16-bit division operation built-in to the P2 assembly ? (I don't think so)
    Has Chip incorporated a division routine into his SPIN2 implementation ?
    I was not expecting the "/" operation to work for non-constant operations
    (in other words, I thought it would be restricted to compile-time only use, like the P1).
    So how should I understand the availability of integer division in SPIN2 ?

    The Spin2 interpreter has a built in routine for 32:32 integer division which uses the CORDIC solver. There is no (single, 2-clock) assembler instruction for division. But there's a scaling instruction (SCA) that can be used to divide by a small constant number with fairly good precision.

    Spin also can handle floating point division. "/" always worked for constant float numbers and recently support for runtime floating point math was added. But you need to use "/." instead of "/" because the compiler doesn't keep track of the type of variables.

  • I did some further experimenting with a block of SPIN2 code using the P2 Edge Module (with its 20MHz crystal) and _clkfreq = 200_000_000 ...

    Repeat i from 1 to 20 step 1    
    
        w := 100_000_000
        DEBUG("100,000,000 divided by ",SDEC_(i))
    
        t1:= GetCT()
        c1:= w/i    'integer division, return quotient'
        t2:= (GetCT()-t1)
        tnS:= t2*1_000_000/(clkfreq/1000)
    
        c2:= w//i   'integer division, return remainder'
    
        DEBUG("  Q: ",SDEC_(c1))
        DEBUG("  R: ",SDEC_(c2))
        DEBUG("  CLK CYCLES: " , SDEC_(t2))
        DEBUG("  ELAPSED TIME (nS) : ", SDEC_(tnS))
    
    

    Debug spits out 224 cycles (or 1.12uS) of elapsed time for the integer division operation shown above.

    The reply from ManAtWork:

    The Spin2 interpreter has a built in routine for 32:32 integer division which uses the CORDIC solver.

    seems to be the most logical answer.

    By the way ....
    When substituting c1:=1, I get 80 cycles (or 400nS) of elapsed time.
    When commenting out the entire line of code I get 40 cycles (or 200nS) of elapsed time.

  • Remember that it takes time to read the system timer so you have to remove that if you're looking at sub-microsecond accuracy. I do timing checks like this

      elapsed := getct()
      ' code to test
      elapsed := getct() - elapsed - 48
    

    You'll may need to adjust the constant at the end based on the compiler you're using.

Sign In or Register to comment.