N-Bit_MATH


Results 1 to 39 of 39

Thread: N-Bit_MATH

Threaded View

  1. #1
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959

    Cool N-Bit_MATH

    I recently came across these great routines from Alexander Avtanski, on the PicList ...
    http://avtanski.net/projects/math/
    All credit goes to Alexander!

    Everything was there, it just needed a few tweaks to be used with PicBasic Pro.

    They're so cool ...

    8, 16, 24, 32, 64, 128-bit Integer Math or more.
    You want BIG numbers? .... you got 'em.
    N-Bit means any number of bits.

    16F, 18F ... doesn't matter (other than RAM space), and you must be using MPASM.
    <hr>
    The number of bytes used in the math depends on the PRECISION constant.
    If PRECISION = 4, then all math is done as 32-bit operations.

    So you need to have variables of the same size, which is easy to do with ...
    Code:
    PRECISION  CON 4 SYSTEM         ' 4 bytes = 32-bit
    
    SetPoint  VAR BYTE[PRECISION]
    Position  VAR BYTE[PRECISION]
    Error     VAR BYTE[PRECISION]
    Current   VAR BYTE[PRECISION]
    MyVar     VAR BYTE[PRECISION]
    Then you can do the math on those variables with ...
    Code:
    @  MATH_SUB  _SetPoint, _Position, _Error   ; subtract Position from setpoint
    Which subtracts Position from Setpoint and puts the result in Error.
    <hr>

    All I've done is put a "wrapper" around the original routines from Alexander, so they can still be used exactly like the webpage says.
    I've also added some macros to make things easier with PBP.

    Code:
    @  MATH_CLR  _Pvar               ; clear an N-Bit variable
    @  MATH_INC  _Pvar               ; increment an N-Bit variable
    @  MATH_DEC  _Pvar               ; decrement an N-Bit variable
    @  MATH_ROL  _Pvar               ; rotate LEFT
    @  MATH_ROR  _Pvar               ; rotate RIGHT
    @  MATH_CMP  _A, _B              ; Compare Pvars - result in M_EQ and M_GTE bits
    @  MATH_ADD  _A, _B, _Res        ; Res = A + B
    @  MATH_SUB  _A, _B, _Res        ; Res = A - B
    @  MATH_MUL  _A, _B, _Res        ; Res = A * B
    @  MATH_DIV  _A, _B, _Res        ; Res = A / B - Remainder in REG_Z
    At this point I'm calling them Pvar's because unlike a byte or word, they could be any length specified by the PRECISION constant.
    ALL math done with these routines are done at the PRECISION level, and all variables used with the MATH functions must be (PRECISION) bytes in length.

    Additional macros were created to allow movement of variables between bytes, words, longs and the Pvars.
    Code:
    @  MOVE?CP  Cin, _Pout           ; copy a CONSTANT to a Pvar
    @  MOVE?BP  _Bin, _Pout          ; copy a BYTE to a Pvar
    @  MOVE?WP  _Win, _Pout          ; copy a WORD to a Pvar
    @  MOVE?LP  _Lin, _Pout          ; copy a LONG to a Pvar (PBPL only)
    @  MOVE?PP  _BeerIN, _Pout       ; copy a Pvar to a Pvar
    And the inverse of those puts them back into PBP variables again.
    Code:
    @  MOVE?PB  _Pin, _Bout          ; truncate a Pvar into a BYTE var
    @  MOVE?PW  _Pin, _Wout          ; truncate a Pvar into a WORD var 
    @  MOVE?PL  _Pin, _Lout          ; truncate a Pvar into a LONG var (PBPL only)


    So let's say you were getting a 16-bit value from the QEI counter, and the upper 16-bits from a Rollover interrupt.
    You could move them all into a Pvar with two lines ...
    Code:
    RollOvers  VAR WORD                        ; QEI rollovers (from interrupt)
    
    @  MOVE?WP   POSCNTL, _Position            ; copy QEI count to Position.Word0
    @  MOVE?WW   _RollOvers, _Position + 2     ; copy rollovers to Position.Word1
    
       ;-- Calculate the Error --
    @  MATH_SUB  _SetPoint, _Position, _Error  ; Error = Setpoint - Position
    @  MOVE?PW   _Error, _pid_Error            ; copy Pvar result to a WORD variable
    This way you can do 32-bit math without PBPL. Or 64-bit if you needed.
    It's not as easy as PBPL, but can be very useful.

    Keep in mind that the math is all Software. Multiplication does not use the hardware multiplier.
    So with 18F's, MATH_MUL at 32-bits will take longer than PBPL with 32-bits.

    However, you can still use all of the math statements within PBP, and they will be faster without PBPL, or BIGGER with PBPL.



    Another recent request from someone in this forum was to have a counter that keeps track of the number of milliseconds since the power was turned on.
    That can be a pretty big number ... if it's been powered-up for a decade or two.
    No problem ...

    Code:
    '----[N-Bit Math]-----------------------------------------------------------
    PRECISION  CON 5 SYSTEM          ; 5 bytes=40-bit
    INCLUDE "N-Bit_MATH.pbp"
    
    Powered_MS   VAR BYTE[PRECISION]
    
    MS_intHandler:  ; this routine should be called every mS via a timer interrupt
      @ FSRSAVE                   ; Save FSR value before interrupt code
      @ MATH_INC  _Powered_MS     ; increment # of mS since PWR_ON
      @ FSRREST                   ; Restore FSR
    ; return from interrupt, depends on the type of interrupt.
    ; interrupt code and context saving not shown.
    That will happily count the number of milliseconds passed for over 34 years. 2<sup>^</sup>40/(1000*60*60*24*365)
    If you need it to count longer ... go with 6 byte PRECISION (8,925 years).

    <hr>
    The routines are completely ASM, and do not use any of PBP's system variables. So it's OK to use them within ASM type Interrupts if desired.
    But you'll need to save the FSR value before doing any MATH because it uses the FSR and would disrupt the flow of the Main program if not saved.

    The @ FSRSAVE and @ FSRREST can be used to make it easy.

    Note: DT_INTS already saves/restores the FSR's at the beginning/end of an interrupt, so you don't have to.
    For ASM interrupts, you will need to save it. FSR's don't matter with ON INTERRUPT.

    <hr>
    Please understand that these are "Advanced Level" math routines.
    I can not debug everyone's program that ends up not compiling because of syntax errors.

    If you truely believe that something is wrong with the routines, I would love to hear it. And I will do my best to fix it.
    If you can't get it to compile ... keep trying ... it will.

    Here's the Include File.
    Current Version = 1.4 Beta (8/4/2010); Workaround for MPASMs shift > 32-bits

    History:
    &nbsp; &nbsp; 1.3 Beta 1/7/2010 ; compatability with 16F1xxx chips (enhanced core)
    &nbsp; &nbsp; 1.2 Alpha 1/4/2010 ; adds ability to turn Case Sensitivity off in MPASM
    &nbsp; &nbsp; 1.1 Alpha 1/4/2010 ; fixes FSR conflict with DT_INTS-18
    &nbsp; &nbsp; 1.0 Alpha 1/3/2010 ; initial release
    Attached Files Attached Files
    Last edited by Darrel Taylor; - 5th August 2010 at 00:27. Reason: Version 1.4
    DT

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts