Hot!HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER?

Page: 12345.. > >> Showing page 1 of 9
Author
schmity
Starting Member
  • Total Posts : 37
  • Reward points : 0
  • Joined: 2015/02/01 18:12:41
  • Location: 0
  • Status: offline
2015/03/19 03:17:58 (permalink)
5 (1)

HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER?

HI GENTS,
i'M HAVING ISSUES WITH MY ALGORITHM TO EXTRACT DIGITS FROM 16-BITS COUNTER. I WILL APPRECIATE IF YOU COULD HELP ME FIGURE OUT WHAT IS WRONG WITH IT, OR SUGGEST AN ALTERNATIVE. BASICALLY, I HAVE A DECLARED A 16-BIT COUNTER. COUNTER LOW COUNT FROM 0 TO 255 AND ROLLER OVER AND INCREMENT COUNTER HIGH. I THEN CALLED A SUBROUTINE TO EXTRACT THE RESPECTIVE DIGITS I.E. THOUSANDTH, HUNDREDTH, TENTHS, ONETH. FOR SOME REASONS, THE EXTRACTOR FUNCTION/SUBROUTINE DOES NOT FUNCTION AS EXPECTED. HERE IT'S BELOW. THANK YOU FOR YOUR HELP IN ADVANCE.
;************************************************* ************************************************* 
; SHARED VARIABLES DECLARATION
;************************************************* *************************************************
DIG_SHR_VARS UDATA_SHR 0X20
THOUSANDTH RES 1 ;RESERVE ONE BYTE AT ADDRESS 20
HUNDREDTH RES 1 ;RESERVE ONE BYTE AT ADDRESS 21
TENTH RES 1 ;RESERVE ONE BYTE AT ADDRESS 22
ONETH RES 1 ;RESERVE ONE BYTE AT ADDRESS 23
COUNTER RES 2 ;RESERVE TWO BYTES ADDRESS 23-24
;************************************************* *************************************************
;EXTRACTING DIGITS FROM 16-BIT COUNTER
;************************************************* *************************************************
DIGIT_FROM_WORD
               MOVF COUNTER + 1,W ;GET HIGHER BYTE
               BTFSS STATUS, Z ;IS THE HIGHER BYTE ZER0?
               GOTO EXTRACT_HUNDTH ;YES, GO TO EXTRACT LOW BYTE
EXTRACT_THOUDTH ;EXTRACT HIGHER BYTE DIGIT
               INCF THOUSANDTH,F
               DECF COUNTER + 1,F ;DECREMENT HIGHER BYTE BY 1
               CLRW ;CLEAR WORKING REGISTER
               ADDLW .256 ;ADD 256
               IORWF COUNTER,F
               MOVLW .100
               GOTO CARRY_SET
               
EXTRACT_HUNDTH
               MOVF COUNTER,W ;GET LOWER BYTE
               MOVWF TEMP ;SAVE IN TEMP
               MOVLW .100
CARRY_SET
               INCF HUNDREDTH ;INCREMENT THE HUNDREDTH
               SUBWF TEMP,W ;HUNDREDTH - 100 = 0?
               BTFSC STATUS,C ;CARRY CLEARED, SKIP NEXT LINE
               GOTO CARRY_SET ;HUNDREDTH > 100
               DECF HUNDREDTH,F
               ADDWF TEMP,F
               MOVF COUNTER+1,F ;CHECK IF COUNTER+1 = 0
               BFTSC STATUS,Z ;IS COUNTER+1 EQUAL TO 0
               GOTO EXTRACT_THOUDTH ; NO
                                  
EXTRACT_TENTH
               MOVLW .10
               INCF TENTH ;INCREMENT THE HUNDREDTH
               SUBWF TEMP,W ;HUNDREDTH - 100 = 0?
               BTFSC STATUS,C ;CARRY CLEARED, SKIP NEXT LINE
               GOTO EXTRACT_TENTH ;HUNDREDTH > 100
               DECF TENTH,F
               ADDWF TEMP,F
EXTRACT_ONETH
               MOVF TEMP,W
               MOVWF ONETH ;SAVE RESULT IN ONETH REGISTER
               RETURN
;************************************************* *************************************************
MAIN ;INITIALIZE VARIABLES TO ZER0 HERE
            ;CLRF THOUSANDTH
            ;CLRF HUNDREDTH
            ;CLRF TENTH
            ;CLRF ONETH
            ;CLRF COUNTER
            ;CLRF COUNTER+1

FOREVER
             INCF COUNTER,F ;INCREMENT LOW COUNT
             MOVF COUNTER,W
             BTFSC STATUS,Z ;CHECK IF LOW COUNT IS ROLLED OVER TO 0
             INCF COUNTER+1,F ;YES, INCREMENT HIGHER COUNT
              
             CALL DIGIT_FROM_WORD ;EXTRACT DIGITS
             ;CALL DISPLAY THOUSANDS
             ;DISPLAY HUNDRETHS
             ;DISPLAY TENTHS
             ;DISPLAY ONETH
             ;CALL DELAY_250MS ;WAIT 250 MILISECONDS
             GOTO FOREVER
;************************************************* *************************************************

post edited by schmity - 2015/03/19 03:20:44
#1

179 Replies Related Threads

    DarioG
    Allmächtig.
    • Total Posts : 53419
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: porcodioland
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/20 12:35:13 (permalink)
    0
    What is not working exactly?
     
    PS: every INCF etc instructions should *always* have the destination specified, i.e. ",F" or ",W"

    DEUTSCHLAND TOOOOOR!!! Brandenburger springt :D

    #2
    1and0
    Access is Denied
    • Total Posts : 8006
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/21 01:26:10 (permalink)
    +1 (1)
    There is so many things wrong with OP's routine that I wouldn't ever attend to fix it.  @OP: search for binary to BCD conversion.
    #3
    schmity
    Starting Member
    • Total Posts : 37
    • Reward points : 0
    • Joined: 2015/02/01 18:12:41
    • Location: 0
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/22 05:38:00 (permalink)
    0
    Many thanks, I got it fixed now.

    Attachment(s)

    Attachments are not available: Download requirements not met
    #4
    DarioG
    Allmächtig.
    • Total Posts : 53419
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: porcodioland
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/22 09:30:27 (permalink)
    0
    ah ah please tell us how grin

    DEUTSCHLAND TOOOOOR!!! Brandenburger springt :D

    #5
    schmity
    Starting Member
    • Total Posts : 37
    • Reward points : 0
    • Joined: 2015/02/01 18:12:41
    • Location: 0
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/22 20:04:53 (permalink)
    +1 (1)
    I used a double dabble "shift and add 3" algorithm to extract the digits. Basically, you shift a 16-bit binary number left and shift a carry bit each time into low byte-> low byte into high byte. Then check the nibble of each byte to see if greater than 5, and add 3 if true, otherwise continue shifting the bytes. The only caveat is, it's a bit slow - takes about 125us to execute or extract 16-bit counter to 5-digit on a micro running 20MHz external clock. Since that execution time is unacceptable to me, I'm working currently on using "divide and mod" algorithm to see if I can reduce execution time.
    Thanks.
    #6
    cbarn24050
    Junior Member
    • Total Posts : 102
    • Reward points : 0
    • Joined: 2015/02/17 17:13:46
    • Location: 0
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/22 23:32:26 (permalink)
    0
    You can cut the execution time down if you write the shift/add loop in assembler.
    #7
    crosland
    Super Member
    • Total Posts : 1188
    • Reward points : 0
    • Joined: 2005/05/10 10:55:05
    • Location: Bucks, UK
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/23 01:45:35 (permalink)
    0
    cbarn24050
    You can cut the execution time down if you write the shift/add loop in assembler.


    Since the code he posted IS assembler...
    #8
    cbarn24050
    Junior Member
    • Total Posts : 102
    • Reward points : 0
    • Joined: 2015/02/17 17:13:46
    • Location: 0
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/23 03:13:02 (permalink)
    0
    Oh yes so it is!! I guess i'll have to look at it now to see why it's taking so long.
    #9
    cbarn24050
    Junior Member
    • Total Posts : 102
    • Reward points : 0
    • Joined: 2015/02/17 17:13:46
    • Location: 0
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/23 03:19:13 (permalink)
    0
    Well now I've looked at it yet again I see he didn't post the code for the binary to bcd converter.
    #10
    JorgeF
    Super Member
    • Total Posts : 3039
    • Reward points : 0
    • Joined: 2011/07/09 11:56:58
    • Location: PT/EU @ Third rock from the Sun
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/23 03:46:40 (permalink)
    +1 (1)
    Hi
     
    schmity
    125us to execute or extract 16-bit counter to 5-digit on a micro running 20MHz external clock. Since that execution time is unacceptable to me, I'm working currently on using "divide and mod" algorithm to see if I can reduce execution time.
    Thanks.



    How did you manage to spend 125uS <=> 625 ASM instructions cycles in that?
    As for the DIV / MOD algorithm, I guess it will take you a lot more time than the shift-add3.
    The digit extraction is a convertion from binary to decimal, as 10 is not a power of 2 the division will allways take a long time.
     
    By my experience a DIV/MOD is allways much slower than the ****-ADD3.
    But I might be missing some math trick, so I'm waiting to see and learn.
     
    Best regards
    Jorge
     
     
     
    #11
    1and0
    Access is Denied
    • Total Posts : 8006
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/23 06:45:07 (permalink)
    0
    JorgeF
    How did you manage to spend 125uS <=> 625 ASM instructions cycles in that?
    As for the DIV / MOD algorithm, I guess it will take you a lot more time than the shift-add3.
    The digit extraction is a convertion from binary to decimal, as 10 is not a power of 2 the division will allways take a long time.
     
    By my experience a DIV/MOD is allways much slower than the ****-ADD3.
    But I might be missing some math trick, so I'm waiting to see and learn.

    625 instruction cycles is slow, even for the shift-add3 method.  Dependent on the algorithms and PIC device, div-mod method can be faster than the shift-add3 method but at the expensive of more code space.
     
    @OP: Which PIC device?  PIC18 has the DAW instruction that can make BCD math easier.  I assume speed is more important than space, so how fast do you need it to be?
    #12
    Mysil
    Super Member
    • Total Posts : 2760
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/23 08:02:55 (permalink)
    +1 (1)
    Hi,
    In this thread, there is a project containing a 16 bit binary to BCD conversion used in preparing values for display. http://www.microchip.com/forums/FindPost/852526 
    It is using a "shift and add3" algorithm as found in some old Microchip assembler demo.
    As inline assembler in XC8 for PIC16, it use nearly 900 instruction cycles including C function call overhead,
    so is no improvement over what schmity have already been using,
    but is still much better than C library "utoa(...)" function which have been seen to use between 3300 cycles and 8600 instruction cycles.
     
    In the original post in this thread, schmity seem not to try to do general division.
    Instead doing repeated subtraction using precalculated constants for powers of 10,
    it could be possible to get away with 36 (or maybe 41) subtractions in the worst case,
    and less in average.
     
    With the following code in C, it has been possible to run a test over all 16 bit values
    with average 433 instruction cycles including loop and call overhead.
    /*
     * Unsigned Binary to Decimal conversion.
     */
    void uBin16_Dec(unsigned char* sptr, unsigned int Arg)
    {
        *sptr = 0;
        while (Arg >= 10000)
        {    Arg -= 10000;
           *sptr += 1;
        }
        sptr++;
        *sptr = 0;
        while (Arg >= 1000)
        {    Arg -= 1000;
           *sptr += 1;
        }
        sptr++;
        *sptr = 0;
        while (Arg >= 100)
        {    Arg -= 100;
           *sptr += 1;
        }
        sptr++;
        *sptr = 0;
        while (Arg >= 10)
        {    Arg -= 10;
           *sptr += 1;
        }
        sptr++;
        *sptr = (unsigned char)Arg;

     
    Regards,
       Mysil
     
    Code edited to correct program bugs.
       Mysil
    post edited by Mysil - 2015/03/26 07:26:08
    #13
    1and0
    Access is Denied
    • Total Posts : 8006
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/23 08:15:30 (permalink)
    0
    Mysil
    ...
    It is using a "shift and add3" algorithm as found in some old Microchip assembler demo.
    As inline assembler in XC8 for PIC16, it use nearly 900 instruction cycles including C function call overhead,
    so is no improvement over what schmity have already been using,

    It should take about 1/2 that many instruction cycles in ASM for a PIC16; faster with PIC18.
     

    In the original post in this thread, schmity seem not to try to do general division.
    Instead doing repeated subtraction using precalculated constants for powers of 10,
    it could be possible to get away with 36 (or maybe 41) subtractions in the worst case,
    and less in average.
     
    With the following code in C, it has been possible to run a test over all 16 bit values
    with average 433 instruction cycles including loop and call overhead.

    Yes, division can be done by repeating subtraction, and it probably takes ~300's instruction cycles in ASM for a PIC16; again, faster with PIC18.
     
    #14
    i1ctg
    Super Member
    • Total Posts : 206
    • Reward points : 0
    • Joined: 2012/10/18 08:43:35
    • Location: OMEGNA-VB- ITALY
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/23 09:38:41 (permalink)
    +1 (1)
     
    this C code is a variant of double dabble for 31 bit
    it can be reduced to 16 bit changing W=0x8000.
    I show it as an idea for conversion in assembler.
     
    uint32_t double_dabble (uint32_t Fbin) //max 99,999,999
    { uint32_t Fbcd, W=0x40000000;
    while (W) {
    Fbcd +=(((Fbcd+0x33333333)&0x88888888)>>3)*3; Fbcd<<=1 ;
    if (Fbin&W) Fbcd++;
    W >>=1 ; }
    return Fbcd;
    }

    #15
    JorgeF
    Super Member
    • Total Posts : 3039
    • Reward points : 0
    • Joined: 2011/07/09 11:56:58
    • Location: PT/EU @ Third rock from the Sun
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/23 18:45:00 (permalink)
    +2 (2)
    Hi
     
    This all question about instruction cycles and my own surprise by the number of instruction cycles the OP measured for the SHIF / ADD3 algorithm, started itching...and itching....and I ended up scratching it.
     
    And this is the result, obtained with a PIC16F886 programmed in absolute assembler.
    Worst case: 554 instruction cycles to convert the value "51190"
    Best case: 528 instruction cycles converting the value "0" 
    The measurement method was to use TIMER1 (16 bit) to count the instruction cycles and colect the maximum and minimum count values while converting all numbers from 0x0000 ("0") to 0xffff (65535).
     
    In case someone is interested in double ckecking or for the sake of curiosity, the ASM source code I used can be found in the attachement.
    Have fun.
     
    Best regards
    Jorge
     
    post edited by JorgeF - 2015/03/23 18:57:27

    Attachment(s)

    Attachments are not available: Download requirements not met
    #16
    schmity
    Starting Member
    • Total Posts : 37
    • Reward points : 0
    • Joined: 2015/02/01 18:12:41
    • Location: 0
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/24 02:12:56 (permalink)
    0
    GENTS, SORRY I DIDN'T POST THE CODE UTILIZING DOUBLE DABBLE. HERE IT'S.
    ;*******************************************************************************
    ; BINARY TO BCD CONVERSION
    ; IMPLEMENTATION OF DOUBLE DABBLY ALGORITHM
    ;*******************************************************************************
    LCD_CONV_BIN2BCD
                  MOVF LCD_POINT,W
                  MOVWF LCD_TEMP_LO ;GET LOWER BYTE
                  MOVF LCD_POINT + 1, W
                  MOVWF LCD_TEMP_HI ;GET LOWER BYTE

                  CLRF BCD_LOBYTE ;HOLDS BCD FOR ONES AND TENS
                  CLRF BCD_LOBYTE + 1 ;HOLDS BCD FOR HUNDS AND THOUS
                  CLRF BCD_TENTS ;HOLDS BCD FOR TEN THOUSANDS
                  CLRF BCD_WORKING

                 MOVLW D'03'
                 MOVWF BCD_BITCNT
    BCD_INIT_SHIFT BCF STATUS,C ;CLEAR CARRY BIT
                   RLF LCD_TEMP_LO,W
                   RLF LCD_TEMP_LO,F ;ROTATE BINARY NUMBER LEFT 3 TIMES
                   RLF LCD_TEMP_HI,F ;ROTATE BINARY NUMBER LEFT 3 TIMES
                   RLF BCD_LOBYTE,F ;NO, JUST ROTATE LEFT
                   DECFSZ BCD_BITCNT ,F ;DECREMENT COUNTER
                   GOTO BCD_INIT_SHIFT

                   MOVLW D'13'
                   MOVWF BCD_BITCNT
                   BCF STATUS,C ;RLF LCD_TEMP_LO,W
    BCD_CHECK_REM MOVF BCD_LOBYTE,W
                   ANDLW H'0F' ;CHECK LOWER NIBLE TO SEE IF GREATER THAN 4
                   SUBLW H'04'
                   BTFSC STATUS,C
                   GOTO BCD_CHECK_TENS
                   MOVLW H'03'
                   ADDWF BCD_LOBYTE,F ;ADD 3 TO IT IF TRUE
    BCD_CHECK_TENS MOVF BCD_LOBYTE,W
                   ANDLW H'F0' ;CHECK LOWER NIBLE TO SEE IF GREATER THAN 4
                   SUBLW H'40'
                   BTFSC STATUS,C
                   GOTO BCD_CHCK_HUNDS
                   MOVLW H'30' ;ADD 30h TO HIGH BYTE NIBBLE
                   ADDWF BCD_LOBYTE,F
    BCD_CHCK_HUNDS MOVF BCD_LOBYTE+1,W
                   ANDLW H'0F' ;CHECK LOWER NIBLE TO SEE IF GREATER THAN 4
                   SUBLW H'04'
                   BTFSC STATUS,C
                   GOTO BCD_CHCK_THOUS
                   MOVLW H'03'
                   ADDWF BCD_LOBYTE+1,F ;ADD 3 TO IT IF TRUE
    BCD_CHCK_THOUS MOVF BCD_LOBYTE+1,W
                   ANDLW H'F0' ;CHECK LOWER NIBLE TO SEE IF GREATER THAN 4
                   SUBLW H'40' ;FORMERLY 50h
                   BTFSC STATUS,C
                   GOTO BCD_CHCK_TENTS
                   MOVLW H'30' ;ADD 30h TO HIGH BYTE NIBBLE
                   ADDWF BCD_LOBYTE + 1,F
    BCD_CHCK_TENTS MOVF BCD_TENTS,W
                   ANDLW H'0F' ;CHECK LOWER NIBLE TO SEE IF GREATER THAN 4
                   SUBLW H'04'
                   BTFSC STATUS,C
                   GOTO BCD_SHIFT_BITS ;CARRY IS SET, ROTATE REGISTERS THROUGH CARRY BIT
                   MOVLW H'03'
                   ADDWF BCD_TENTS,F ;ADD 3 TO IT IF TRUE
    BCD_SHIFT_BITS RLF LCD_TEMP_LO,F ;ROTATE TEMP LOW REMAINING BIT INTO CARRY BIT AND CHECK IT'S ONE
                   RLF LCD_TEMP_HI,F ;ROTATE TEMP LOW REMAINING BIT INTO CARRY BIT AND CHECK IT'S ONE
                   RLF BCD_LOBYTE,F
                   RLF BCD_LOBYTE + 1,F
                   RLF BCD_TENTS,F
    BCD_CHECK_CNTS DECFSZ BCD_BITCNT,F ;DECREMENT COUNTER
                   GOTO BCD_CHECK_REM
                   MOVF BCD_LOBYTE,W
                   ANDLW H'0F' ;GRAB LOWER NIBBLE
                   ADDLW H'30' ;CONVERT TO ASCII
                   MOVWF LCD_ONES ;SAVE IN LCD_ONES REG
                   ;CLRW
                   SWAPF BCD_LOBYTE,W ;GRAB THE HIGHER NIBBLE
                   ANDLW H'0F' ;EXTRACT THE NIBBLE
                   ADDLW H'30' ;CONVERT TO ASCII
                   MOVWF LCD_TENS ;SAVE IN TENS REG
                   MOVF BCD_LOBYTE + 1,W ;GRAB HIGHER BYTE LOWER NIBBLE
                   ANDLW H'0F' ;EXTRACT THE LOWER NIBBLE
                   ADDLW H'30' ;CONVERT TO ASCII
                   MOVWF LCD_HUNDS ;SAVE IN HUNDS REG
                   ;CLRW
                   SWAPF BCD_LOBYTE + 1,W ;GRAB HIGHER BTYE HIGHER NIBBLE AND CONVERT O LOWER NIBBLE
                   ANDLW H'0F' ;EXTRACT LOWER NIBBLE
                   ADDLW H'30' ;CONVERT TO ASCII
                   MOVWF LCD_THOUS ;SAVE IN THOUS REG
                   MOVF BCD_TENTS,W ;GET TENS LOWER NIBBLE
                   ANDLW H'0F' ;EXTRACT THE LOWER NIBBLE
                   ADDLW H'30' ;CONVERT TO ASCII
                   MOVWF LCD_TENTS ;SAVE IN TENTS REG
          RETURN
    ;*******************************************************************************

    post edited by schmity - 2015/03/24 02:20:07
    #17
    1and0
    Access is Denied
    • Total Posts : 8006
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/24 08:00:02 (permalink)
    +3 (3)
    Your implementation of double dabble is the same as Jorge's which is based too literally on the algorithm described in Wikipedia's article of Double Dabble and as a result takes more execution time and memory spaces.  Here's a more efficient implementation of double dabble for PIC16 devices:
    ;
    ; 16-bit Binary To 5-digit Packed BCD
    ;
    ; input  = binH:binL      = 16-bit binary number
    ; output = bcdU:bcdH:bcdL = 5-digit packed BCD number
    ;
    Bin16ToBCD5
            clrf    bcdL            ; clear bcd result
            clrf    bcdH
            clrf    bcdU
            movlw   .16             ; 16 bits counter
            movwf   count
            goto    bcd0            ; branch to reduce 16 Tcy
           
    bcd_lp  movlw   0x33            ; adjust Tens:Ones digits
            addwf   bcdL
            btfsc   bcdL,3
            andlw   0xF0
            btfsc   bcdL,7
            andlw   0x0F
            subwf   bcdL
           
            movlw   0x33            ; adjust Thou:Hund digits
            addwf   bcdH
            btfsc   bcdH,3
            andlw   0xF0
            btfsc   bcdH,7
            andlw   0x0F
            subwf   bcdH
           
    ;       movlw   0x03            ; adjust TenK digit
    ;       addwf   bcdU
    ;       btfss   bcdU,3
    ;       subwf   bcdU
           
    bcd0    rlf     binL            ; shift out a binary bit
            rlf     binH
            rlf     bcdL            ; into bcd result (double)
            rlf     bcdH
            rlf     bcdU
           
            decfsz  count           ; repeat for all bits
            goto    bcd_lp
            return                  ; exit

    which takes 32 28 words of program memory and executes in 409 349 isochronous instruction cycles (Tcy) including call.
     
    As I said earlier the division-by-subtraction method should be faster at 300's Tcy, and there're other methods that are even faster at 200's Tcy.
     
    <edit> Shaved 60 cycles and 4 words off the code -- see Post #38.
     
    post edited by 1and0 - 2015/03/25 22:21:36
    #18
    JorgeF
    Super Member
    • Total Posts : 3039
    • Reward points : 0
    • Joined: 2011/07/09 11:56:58
    • Location: PT/EU @ Third rock from the Sun
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/24 11:59:11 (permalink)
    +1 (1)
    Hi
     
    Wow, I'm saving this one for future reference.
    Somehow this algorithm makes me remember the DAA (decimal adjust accumulator) of the Intel80xx range of processors.
     
    As a matter of fact is the first time I heard (see) the term "Double Dabble".
    I've been using this algorithm, under the name of "SHIFT/ADD3" since around 1981, when I was at the University learning i8085 ASM on an Intel SDK-85.
     
    I think that using integer division by 10 will take more time since we need to run a 16bit by 8bit division at least 4 times, to extract the 5 digits.
    Or am I missing something here?
     
     
    Best regards
    Jorge
     
    post edited by JorgeF - 2015/03/24 12:08:39
    #19
    Mysil
    Super Member
    • Total Posts : 2760
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/24 14:41:06 (permalink)
    0
    Hi,
    Playing with the code and test program contributed by JorgeF,
    and code shown by 1and0 today, I have noticed some properties of the double dabble algorithm.
     
    Jorge noticed the fact that the first 2 sequences of shifts will never cause a "add 3" adjustment to be needed.
    Then the most significant nibble in result will not achieve a value that will need a adjustment either.
    Modifying 1and0's code, it has been possible to run the algorithm in 315 instruction cycles.
     
    Regards,
       Mysil
    #20
    Page: 12345.. > >> Showing page 1 of 9
    Jump to:
    © 2018 APG vNext Commercial Version 4.5