Display 2 WORDs as a 32bit integer


+ Reply to Thread
Results 1 to 14 of 14

Hybrid View

  1. #1
    Join Date
    Oct 2012
    Posts
    82


    Did you find this post helpful? Yes | No

    Default Re: Display 2 WORDs as a 32bit integer

    Many years ago DT helped me with something similar
    https://www.picbasic.co.uk/forum/showthread.php/24-Retrieving-32bit-Multiply-Result
    Not sure if it might apply to your application.

    Nick

  2. #2
    Join Date
    May 2013
    Location
    australia
    Posts
    2,636


    Did you find this post helpful? Yes | No

    Default Re: Display 2 WORDs as a 32bit integer

    Without really thinking I changed DIV32 to 10000 and massaged the display code but obviously it only pushes the problem to when the high word is >10000.
    yes biggest num is 655359999
    this does a divide by 100000 first in asm and will do rest in pbp to encompass the entire 32 bit signed range



    Code:
    #config CONFIG RETEN=OFF
     CONFIG XINST = OFF ;Extended Instruction Set
     CONFIG FOSC = INTIO2 ;internal RC oscillator 
     CONFIG SOSCSEL=DIG
     CONFIG FCMEN = OFF   ;Fail-Safe Clock Monitor ****
     CONFIG IESO = OFF  ;Two-Speed Start-up is disabled
     CONFIG PLLCFG = OFF  ;4x xtal PLL 
     CONFIG PWRTEN = ON ;Power-up Timer
     CONFIG BOREN = SBORDIS ; Brown-out Reset Enabled in hardware, SBOREN disabled
     CONFIG BORPWR = HIGH ;BOR MV set to high power level
     CONFIG BORV = 2 ; Brown-out Reset  0=3v, 1=2.7v, 2=2v, 3=1.8v 
     CONFIG WDTEN = SWDTDIS ;ON ;OFF ;WDT enabled in hardware; SWDTEN bit disabled
     CONFIG WDTPS = 512 ;WDT     512*4Ms = 2 SECONDS 
     CONFIG RTCOSC = INTOSCREF  ; RTCC uses INTRC 
     CONFIG  MCLRE = ON
     CONFIG STVREN = ON ;Stack Full/Underflow Reset
     CONFIG DEBUG = OFF ;Background Debugger 
     CONFIG CP0 = OFF  ;code-protected
     CONFIG CP1 = OFF
     CONFIG CP2 = OFF
     CONFIG CP3 = OFF
     CONFIG CP4 = OFF
     CONFIG CP5 = OFF
     CONFIG CP6 = OFF
     CONFIG CP7 = OFF
     CONFIG CPB = OFF ;Boot Block Code Protection
     CONFIG CPD = OFF ;Data EEPROM Code Protection
    #endconfig
    
    
    DEFINE OSC 64 
    DEFINE DEBUG_REG PORTD         
    DEFINE DEBUG_BIT 4
    DEFINE DEBUG_BAUD 9600 
    DEFINE DEBUG_MODE 0  '0=TRUE 1=INVERTER
    
    
    
    
        OSCCON=110100 
        OSCTUNE.6=1 'Frequency Multiplier PLL Enable bit FOR INIT RC 
        TRISD=$ed
        ANCON0=0 'AN0-AN7 digital port
        ANCON1=0 'AN8-AN15 digital port
        ANCON2=0 'AN16-AN23 dig
    
    
        PSPCON.4=0 'General Purpose I/O mode 'PSPMODE: Parallel Slave Port Mode Select bit
        
        Test     var byte[3] SYSTEM
        Dividend   var byte[6] SYSTEM
        Remainder  var byte[4] SYSTEM      ; remainder from 1000000 division
        Shift  var byte[6] SYSTEM
        Counter  VAR BYTE  SYSTEM
        Hours     VAR WORD[2]    ; 32-bit (Dword) Holds up to 99999.9 hours
        HoursH    VAR Hours(1)
        HoursL    Var Hours(0)
        QUOTL     VAR WORD EXT       ; top 5 digits
        Result    Var Word           ;  middle 10,000;s  single digit 
        Remains Var Word             ; bottom 4 digits
        i var byte
    goto overasm
     Asm
    QUOTL=Dividend 
    PutMulResult?D macro Din
        MOVE?BB   Din, R2
        MOVE?BB   Din + 1 , R2 + 1
        MOVE?BB   Din + 2, R0
        MOVE?BB   Din + 3, R0 + 1
        RST?RP
      endm
    PutDIV?D macro Din
        MOVE?BB   Din, Dividend 
        MOVE?BB   Din + 1 , Dividend  + 1
        MOVE?BB   Din + 2, Dividend   + 2
        MOVE?BB   Din + 3, Dividend  + 3
        MOVE?CB   0 ,   Dividend  + 4
        MOVE?CB   0 ,   Dividend  + 5
        RST?RP
      endm 
      
      
      
    EndAsm    
    Remainder[3]=0    
    overasm:
        HoursL=$fff0
        HoursH=$7fff
        latd=18
        debug "ready",13,10
        pause 1000
       
    
    
    
    
    
    
    MainLoop:
        gosub AddHourTenth
        Gosub ShowHourMeter
    goto MainLoop    ;============================================================
    
    
    
    
    
    
    AddHourTenth:
        HoursL = HoursL + 1
        IF HoursL = 0 then HoursH = HoursH + 1
    return
    
    
    
    
    ShowHourMeter:
        Test    [0]=$a0       ;divisor 100000
        Test    [1]=$86
        Test    [2]=1
        
    @   PutDIV?D  _Hours
        CALL  Div4824U      ;divide by 100000
         debug  ,13,10
    
    
    @   PutMulResult?D  Remainder
        Result = DIV32 10000
        Remains = R2
        debug DEC QUOTL, Dec1 Result, ".",DEC4 Remains ,13,10
        pause 1000
    return   
    
    
    ;**************************************************************************
    ;Div4824U
    ;Inputs:
    ;    Dividend - Dividend:6    (0 - least significant!)
    ;    Divisor     - Test:3    (0 - least significant!)
    ;Temporary:
    ;    Counter     - Count
    ;    Shift     - Shift:6
    ;Output:
    ;    Quotient - Dividend:6    (0 - least significant!)
    ;    Remainder- Rem:3    (0 - least significant!)
    ;
    ;Adaptation of 24x24 division by Tony Nixon with corrections
    ;by Frank Finster 3/15/2005.
    ;Code adapted by Andy Lee
    ;01-Sep-2006    Original version
    ;**************************************************************************
    
    
    Div4824U:
    asm
    ;---------------------------------------------------
    ; SUBROUTINE - 48 by 24 BIT DIVISION
        movlw 48
        movwf Counter
        movff Dividend+0, Shift+0
        movff Dividend+1, Shift+1
        movff Dividend+2, Shift+2
        movff Dividend+3, Shift+3
        movff Dividend+4, Shift+4
        movff Dividend+5, Shift+5
        clrf Dividend+0
        clrf Dividend+1
        clrf Dividend+2
        clrf Dividend+3
        clrf Dividend+4
        clrf Dividend+5
        clrf Remainder+2
        clrf Remainder+1
        clrf Remainder+0
    dloop
        bcf STATUS, C
        rlcf Shift+0
        rlcf Shift+1
        rlcf Shift+2
        rlcf Shift+3
        rlcf Shift+4
        rlcf Shift+5
        rlcf Remainder+0
        rlcf Remainder+1
        rlcf Remainder+2
        movf Test+2, w
        subwf Remainder+2, w
        btfss STATUS, Z
        bra nochk
        movf Test+1,w
        subwf Remainder+1,w
        btfss STATUS, Z
        bra nochk
        movf Test+0,w
        subwf Remainder+0,w
    nochk
        btfss STATUS, C
        bra nogo
        movf Test+0,w
        subwf Remainder+0
        btfsc STATUS, C
        bra    nodec_remainM
        decf Remainder+1, f
        movf Remainder+1, w
        xorlw 0xff
        btfsc STATUS, Z
        decf Remainder+2, f
    nodec_remainM
        movf Test+1, w
        subwf Remainder+1, f
        btfss STATUS, C
            decf Remainder+2, f
        movf Test+2, w
        subwf Remainder+2, f
        bsf STATUS, C
    nogo
        rlcf Dividend+0
        rlcf Dividend+1
        rlcf Dividend+2
        rlcf Dividend+3
        rlcf Dividend+4
        rlcf Dividend+5
        decfsz Counter, f
        goto dloop
        return
     
     endasm
    Warning I'm not a teacher

  3. #3
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default Re: Display 2 WORDs as a 32bit integer

    Thanks Nick,
    As far as I can see the examples provided by Darrel in that thread has the same limitation as in "only" going to 655359999 which is "only" ~15% of the 32bit range.
    In my case I really do need the full 32bits since the value can and do wrap around. Displaying it signed would be cool but I'll take unsigned over what I have right now any day.

    Richard,
    Wow, thank you very much indeed!
    I have it running on a little dev.board, next is to incorporate it in the actual code, we'll see how that goes.

    Thanks again!

    /Henrik.

  4. #4
    Join Date
    May 2013
    Location
    australia
    Posts
    2,636


    Did you find this post helpful? Yes | No

    Default Re: Display 2 WORDs as a 32bit integer

    A few tweaks to scrounge some resources back

    Code:
        Test     var byte[3] SYSTEM
        Dividend   var byte[6] SYSTEM
        Remainder  var byte[3] SYSTEM      ; 24 bit remainder from 1000000 division
        Shift  var byte[6] SYSTEM
        Counter  VAR BYTE  SYSTEM
        Hours     VAR WORD[2]    ; 32-bit 
        HoursH    VAR Hours(1)
        HoursL    Var Hours(0)
        QUOTL     VAR WORD EXT       ; top 5 digits
        Result    Var Word           ;  middle 10,000;s  single digit 
        Remains Var Word             ; bottom 4 digits
        i var byte
    goto overasm
     Asm
    QUOTL=Dividend 
    PutMulResult?D macro Din
        MOVE?BB   Din, R2
        MOVE?BB   Din + 1 , R2 + 1
        MOVE?BB   Din + 2, R0
        MOVE?BB   Din + 3, R0 + 1
        RST?RP
      endm
    PutDIV?D macro Din
        MOVE?BB   Din, Dividend 
        MOVE?BB   Din + 1 , Dividend  + 1
        MOVE?BB   Din + 2, Dividend   + 2
        MOVE?BB   Din + 3, Dividend  + 3
        MOVE?CB   0 ,   Dividend  + 4
        MOVE?CB   0 ,   Dividend  + 5
        RST?RP
      endm 
    PutSH?D macro Din
        MOVE?BB   Din, Shift
        MOVE?BB   Din + 1 , Shift  + 1
        MOVE?BB   Din + 2, Shift   + 2
        MOVE?BB   Din + 3, Shift  + 3
        MOVE?CB   0 ,   Shift  + 4
        MOVE?CB   0 ,   Shift  + 5
        RST?RP
      endm   
    Put24?D macro Din
        MOVE?BB   Din, R2
        MOVE?BB   Din + 1 , R2 + 1
        MOVE?BB   Din + 2, R0
        MOVE?CB   0, R0 + 1
        RST?RP
      endm  
      
    EndAsm    
    '    Remainder[3]=0  
    
    
    overasm:
        HoursL=$fff0
        HoursH=$7fff
        latd=18
        debug "ready",13,10
        pause 1000
       
    
    
    
    
    
    
    MainLoop:
        gosub AddHourTenth
        Gosub ShowHourMeter
    goto MainLoop    ;============================================================
    
    
    
    
    
    
    AddHourTenth:
        HoursL = HoursL + 1
        IF HoursL = 0 then HoursH = HoursH + 1
    return
    
    
    
    
    ShowHourMeter:
        Test[0]=$a0       ;divisor 100000
        Test[1]=$86
        Test[2]=1  
        
    ;@   PutDIV?D  _Hours
    @   PutSH?D  _Hours    ; take a shortcut and load shift regs directly  
        CALL  Div4824U      ;divide by 100000
        debug  ,13,10
    ;@   PutMulResult?D  Remainder
    @   Put24?D  Remainder     ; only do a 24 bit load since answer is never bigger than that
        Result = DIV32 10000
        Remains = R2
        debug DEC QUOTL, Dec1 Result, ".",DEC4 Remains ,13,10
        pause 1000
    return   
    
    
    ;**************************************************************************
    ;Div4824U
    ;Inputs:
    ;    Dividend - Dividend:6    (0 - least significant!)
    ;    Divisor     - Test:3    (0 - least significant!)
    ;Temporary:
    ;    Counter     - Count
    ;    Shift     - Shift:6
    ;Output:
    ;    Quotient - Dividend:6    (0 - least significant!)
    ;    Remainder- Rem:3    (0 - least significant!)
    ;
    ;Adaptation of 24x24 division by Tony Nixon with corrections
    ;by Frank Finster 3/15/2005.
    ;Code adapted by Andy Lee
    ;01-Sep-2006    Original version
    ;**************************************************************************
    
    
    Div4824U:
    asm
    ;---------------------------------------------------
    ; SUBROUTINE - 48 by 24 BIT DIVISION
        movlw 48
        movwf Counter
        ;movff Dividend+0, Shift+0
        ;movff Dividend+1, Shift+1
        ;movff Dividend+2, Shift+2
        ;movff Dividend+3, Shift+3
        ;movff Dividend+4, Shift+4
        ;movff Dividend+5, Shift+5
        clrf Dividend+0
        clrf Dividend+1
        clrf Dividend+2
        clrf Dividend+3
        clrf Dividend+4
        clrf Dividend+5
        clrf Remainder+2
        clrf Remainder+1
        clrf Remainder+0
    dloop
        bcf STATUS, C
        rlcf Shift+0
        rlcf Shift+1
        rlcf Shift+2
        rlcf Shift+3
        rlcf Shift+4
        rlcf Shift+5
        rlcf Remainder+0
        rlcf Remainder+1
        rlcf Remainder+2
        movf Test+2, w
        subwf Remainder+2, w
        btfss STATUS, Z
        bra nochk
        movf Test+1,w
        subwf Remainder+1,w
        btfss STATUS, Z
        bra nochk
        movf Test+0,w
        subwf Remainder+0,w
    nochk
        btfss STATUS, C
        bra nogo
        movf Test+0,w
        subwf Remainder+0
        btfsc STATUS, C
        bra    nodec_remainM
        decf Remainder+1, f
        movf Remainder+1, w
        xorlw 0xff
        btfsc STATUS, Z
        decf Remainder+2, f
    nodec_remainM
        movf Test+1, w
        subwf Remainder+1, f
        btfss STATUS, C
            decf Remainder+2, f
        movf Test+2, w
        subwf Remainder+2, f
        bsf STATUS, C
    nogo
        rlcf Dividend+0
        rlcf Dividend+1
        rlcf Dividend+2
        rlcf Dividend+3
        rlcf Dividend+4
        rlcf Dividend+5
        decfsz Counter, f
        goto dloop
        return
     endasm
    Last edited by richard; - 3rd December 2024 at 00:06.
    Warning I'm not a teacher

  5. #5
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default Re: Display 2 WORDs as a 32bit integer

    Thanks Richard,
    I won't pretend to comprehend the assembly voodoo but I think we can shave another BYTE worth of RAM off that thing by declaring Result as a BYTE instead of a WORD. At least it seems to work :-)

    /Henrik.

  6. #6
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    1 out of 1 members found this post helpful. Did you find this post helpful? Yes | No

    Default Re: Display 2 WORDs as a 32bit integer

    Richard,
    Just wanted to thank you once again, the code is now incorporated in my project and I can display my two 32bit variables nicely.
    I hardcoded the divisor to 100k and got rid of the Divisor variable. It grew the codebase by 230bytes and 34bytes of RAM out of which 11 is an array to which I write the result
    Code:
    DWORDtoString:
        CALL DivBy100k
    
        ' QUOTL top word, Remainder low word.
        ' Get Remainder into PBP system variables in preparation for DIV32
        ASM
            MOVE?BB   Remainder, R2
            MOVE?BB   Remainder + 1 , R2 + 1
            MOVE?BB   Remainder + 2, R0
            MOVE?CB   0, R0 + 1
            RST?RP
        ENDASM
    
        Result = DIV32 10000
        Remains = R2
        
        IF QUOTL THEN
            ARRAYWRITE DWordString, [DEC QUOTL, DEC Result, DEC4 Remains, 0]
        ELSEIF Result THEN
            ARRAYWRITE DWordString, [DEC Result, DEC4 Remains, 0]
        ELSE
            ARRAYWRITE DWordString, [DEC Remains, 0]
        ENDIF

  7. #7


    Did you find this post helpful? Yes | No

    Default Re: Display 2 WORDs as a 32bit integer

    Is it possible to describe the method or algorithm to get the decimal from the possible 8 hexadecimal of 32 bit number.... the conversion itself is pretty straight forward but the 8 bit manipulations are confusing...
    .
    .Name:  hex.JPG
Views: 356
Size:  53.3 KB

Similar Threads

  1. Microchip 32bit floating point to integer conversion
    By timmers in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 1st February 2011, 16:49
  2. IEEE 754 32bit floating point value.
    By shawn in forum mel PIC BASIC Pro
    Replies: 9
    Last Post: - 18th December 2010, 12:32
  3. Signed 32bit to ASCII?
    By HenrikOlsson in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 7th May 2010, 22:13
  4. Retrieving 32bit Multiply Result
    By Darrel Taylor in forum Code Examples
    Replies: 42
    Last Post: - 28th January 2008, 15:15
  5. Newbee How to get LCD to display 4-6 var words
    By emmett brown in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 15th August 2006, 01:11

Members who have read this thread : 18

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