Display 2 WORDs as a 32bit integer


+ Reply to Thread
Results 1 to 14 of 14

Hybrid View

  1. #1
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604

    Default Display 2 WORDs as a 32bit integer

    I have two WORD variables representing a 32bit number, lets call them CountH and CountL.
    I am displaying these as the two individual variables they are, using HSEROUT with the DEC modifier. (ex: 12, 45234 where 12 is CountH and 45234 is CountL)
    Ideally I'd like to display them as the signed 32bit integer that they represent (ex: 831666). I'm at 14.8k on a 16k device, switching to LONGs is not an option, switching device is not an option either since the 18F2431 is the only bloody 8-bitter with the QEI peripheral.

    Anyone have a nifty routine to do it?

    /Henrik.

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


    Did you find this post helpful? Yes | No

    Default Re: Display 2 WORDs as a 32bit integer

    maybe something like this old gem

    Code:
    Hours     VAR WORD[2]    ; 32-bit (Dword) Holds up to 99999.9 hoursHoursH    VAR Hours(1)
    HoursL    Var Hours(0)
    
    
    Result    Var Word
    Remainder Var Word
    
    
    ;----[Load a 32-bit (Dword) variable into PBP registers, Prior to DIV32]--------
    Asm
    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
    EndAsm
    
    
    ;====[Simple loop to test the HourMeter]========================================
    MainLoop:
        gosub AddHourTenth
        Gosub ShowHourMeter
    goto MainLoop    ;============================================================
    
    
    
    
    ;----[Add 1 tenth of an hour to the hourmeter]----------------------------------
    AddHourTenth:
        HoursL = HoursL + 1
        IF HoursL = 0 then HoursH = HoursH + 1
        if (HoursH = $F) and (HoursL = $4240) then   ; Roll over at 1,000,000
            HoursH = 0                               ;            99999.9 + .1
            HoursL = 0
        endif
    return
    
    
    ;----[Display hourmeter using LCDOUT]-------------------------------------------
    ShowHourMeter:
    @   PutMulResult?D  _Hours
        Result = DIV32 1000
        Remainder = R2
        LCDOUT $FE, 2            ; Home Cursor
        IF Result > 0 then
            LCDOUT Dec Result, DEC2 Remainder/10,".",DEC1 Remainder//10
        else
            LCDOUT DEC Remainder/10,".",DEC1 Remainder//10
        endif   
    return



    the other way is n-bit math
    like post #23 here
    Last edited by richard; - 30th November 2024 at 22:42.
    Warning I'm not a teacher

  3. #3
    Join Date
    May 2013
    Location
    australia
    Posts
    2,631


    Did you find this post helpful? Yes | No

    Default Re: Display 2 WORDs as a 32bit integer

    signed 32 bit divide here

    or do it the easy way in C where its not an issue
    Warning I'm not a teacher

  4. #4
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default Re: Display 2 WORDs as a 32bit integer

    Thanks Richard,
    I don't need to "do" anything with the value, "all" I need is to display it

    ValueH = 12
    ValueL = 45234
    GOSUB Print32BitValue

    Result: 831666

    I tried your HourMeter aproach and it works fine with example above. Cool!
    Unfortunately it falls appart when the high word is >1000, ie when the Result of DIV32 is >65535.
    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.

    I feel daft...

  5. #5
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    966


    Did you find this post helpful? Yes | No

    Default Re: Display 2 WORDs as a 32bit integer

    Many years back, I solved the problem like this.

    I have a variable Total defined as 4 bytes

    In the routine that increments the total, I did it like this
    Code:
         
    Total       var byte[4]    ' packed BCD totalizer upto 99999999
    
    asm
    ; assembler code embedded into PBP increments Total till 99999999 and then rolls over
    
              incf  _Total+3
    	  movlw 100
    	  subwf _Total+3,w
    	  btfss status,c
    	  goto  DoneTotal
    	  clrf  _Total+3
    	  ;
    	  incf  _Total+2
    	  movlw 100
    	  subwf _Total+2,w
    	  btfss status,c
    	  goto  DoneTotal
    	  clrf  _Total+2
    	  ;
    	  incf  _Total+1
    	  movlw 100
    	  subwf _Total+1,w
    	  btfss status,c
    	  goto  DoneTotal
    	  clrf  _Total+1
    	  ;
    	  incf  _Total+0
    	  movlw 100
    	  subwf _Total+0,w
    	  btfss status,c
    	  goto  DoneTotal
    	  clrf  _Total+0
    DoneTotal:
    
    endasm
    This allows for a maximum total content of 99,99,99,99 with Total[3] being the lowest byte

    Now, in the display routine, I did something like this to show the lower 6 digits. Mind you, this is only for unsigned values.

    Code:
      		Dat = Total[2] dig 0
      			gosub Code2Segment       ' convert to 7 segment code
      			gosub Dsp_Data                ' display the 7 segment code
                            Dat = Total[2] dig 1
      			gosub Code2Segment
      			gosub Dsp_Data
      
      			Dat = Total[1] dig 0
      			gosub Code2Segment
      			gosub Dsp_Data
                            Dat = Total[1] dig 1
      			gosub Code2Segment
      			gosub Dsp_Data
      
      			Dat = Total[0] dig 0
      			gosub Code2Segment
      			gosub Dsp_Data
                            Dat = Total[0] dig 1
      			gosub Code2Segment
      			gosub Dsp_Data
    I hope this will help you find some solution to your stated problem.

    Cheers
    Last edited by Jerson; - 1st December 2024 at 14:06. Reason: Error in code fixed

  6. #6
    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

  7. #7
    Join Date
    May 2013
    Location
    australia
    Posts
    2,631


    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

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