HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER?

Page: << < ..6789 > Showing page 6 of 9
Author
1and0
Access is Denied
  • Total Posts : 7745
  • 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/29 13:23:10 (permalink)
0
NorthGuy
What's important is that it's more than 62! :)

It is 60 now :)
 
NorthGuy
BTW: You can improve your routine from post #24 in the reffered thread by using the same technique as I did in my PIC18 code. At some point, you can switch from 32-bit fractional to 16-bit one. You just need to figure out where this point is.

Will visit that thread in the future...when I get a faster computer. grin: grin  Thanks!
post edited by 1and0 - 2015/03/29 13:58:40
1and0
Access is Denied
  • Total Posts : 7745
  • 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/29 13:29:51 (permalink)
+1 (1)
JorgeF

; Convert 5 digit BCD to ASCII
movlw 0x3f
iorwf ONETH, F
iorwf TENTH, F
iorwf HUNDREDTH, F
iorwf THOUSANDTH, F
iorwf TENTHOUSANDTH, F


That should be "movlw 0x30" but I prefer to let the assembler work for me :)  movlw '0'
NorthGuy
Super Member
  • Total Posts : 4830
  • Reward points : 0
  • Joined: 2014/02/23 14:23:23
  • Location: Northern Canada
  • Status: offline
Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/29 14:06:32 (permalink)
0
1and0
It is 60 now :)



Wow!
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/30 04:29:06 (permalink)
0
You guys are geniuses!
Is that for unpacking the packed digits, 1and0?
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/30 04:31:14 (permalink)
+1 (1)
night leads tips.
changes were painless.  Harry can test the following routine?   it should also go with PIC16.
subl2 macro frH,frL,lit,addr
        movlw low lit
        subwf frL,f
        movlw high lit
        subwfb frH,f
        bnc addr
        endm

addl2 macro frH,frL,lit,addr
        movlw low lit
        addwf frL,f
        movlw high lit
        addwfc frH,f
        bc addr
        endm

;----------------------------
BIN16TOASC
        movlw 0x30
        movwf tenk
        movwf thou
        movwf hund
        movwf tens
        movwf ones
        subl2 binH,binL,.40000,p20kn
        bsf tenk,2
        subl2 binH,binL,.20000,p10kn
p20ks bsf tenk,1
        bnc p4k
        subl2 binH,binL,.10000,p8kn
p10ks bsf tenk,0
        subl2 binH,binL,.8000,p4kn
p8ks bsf thou,3
        bnc p1k
p4k subl2 binH,binL,.4000,p2kn
p4ks bsf thou,2
        subl2 binH,binL,.2000,p1kn
p2ks bsf thou,1
p1k subl2 binH,binL,.1000,p800n
p1ks bsf thou,0

        subl2 binH,binL,.800,p400n
p800s bsf hund,3
        bnc p100
        subl2 binH,binL,.400,p200n
p400s bsf hund,2
        subl2 binH,binL,.200,p100n
p200s bsf hund,1
        movf binL,w
p100 addlw 0x9c
        bnc p80n
p100s bsf hund,0
        addlw 0xb0
        bnc p40n
p80s bsf tens,3
        bnc p10
        addlw 0xd8
        bnc p20n
p40s bsf tens,2
        addlw 0xec
        bnc p10n
p20s bsf tens,1
p10 addlw 0xf6
        bnc donen
p10s bsf tens,0
done iorwf ones,f
        return


; sequence if goes negative

p20kn addl2 binH,binL,.20000,p20ks
p10kn addl2 binH,binL,.10000,p10ks
p8kn addl2 binH,binL,.2000,p8ks
p4kn addl2 binH,binL,.4000,p4ks
p2kn addl2 binH,binL,.2000,p2ks
p1kn addl2 binH,binL,.1000,p1ks
p800n addl2 binH,binL,.200,p800s
p400n addl2 binH,binL,.400,p400s
p200n addl2 binH,binL,.200,p200s
p100n movf binL,w
     addlw .100
        bc p100s
p80n addlw .20
        bc p80s
p40n addlw .40
        bc p40s
p20n addlw .20
        bc p20s
p10n addlw .10
        bc p10s
donen addlw .10
        iorwf ones,f
        return

 END

1and0
Access is Denied
  • Total Posts : 7745
  • 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/30 09:11:06 (permalink)
0
schmity
You guys are geniuses!
Is that for unpacking the packed digits, 1and0?

Yes, Jorge's snippet in Post #100 with a small correction from Post #104 will unpack the digits, provided the five BCD digits are packed in the TENTHOUSANDTH, HUNDREDTH and ONETH variables in the first place.
1and0
Access is Denied
  • Total Posts : 7745
  • 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/30 09:19:58 (permalink)
+1 (1)
i1ctg
night leads tips.
changes were painless.  Harry can test the following routine?   it should also go with PIC16.

I stand corrected.  YOU DID IT!!  For the PIC16, I modified your macros to handle the ADDWFC and SUBWFB instructions:
subl2   macro   frH,frL,lit,addr
    if  (PIC == PIC18) || (PIC == PIC16E) || (PIC == PIC12E)
        movlw   low lit
        subwf   frL,f
        movlw   high lit
        subwfb  frH,f
        bnc     addr
    else
    if  (PIC == PIC16) || (PIC == PIC12)
        movlw   low  lit
        subwf   frL,f
        movlw   high lit
        skpc
        addlw   1
        subwf   frH,f
        bnc     addr
    else
        error "No PIC device selected"
    endif
    endif
        endm
       
addl2   macro   frH,frL,lit,addr
    if  (PIC == PIC18) || (PIC == PIC16E) || (PIC == PIC12E)
        movlw   low lit
        addwf   frL,f
        movlw   high lit
        addwfc  frH,f
        bc      addr
    else
    if  (PIC == PIC16) || (PIC == PIC12)
        movlw   low  lit
        addwf   frL,f
        movlw   high lit
        skpnc
        addlw   1
        addwf   frH,f
        bc      addr
    else
        error "No PIC device selected"
    endif
    endif
        endm

and here are the timings on your routine:
;
; 16-bit Unsigned Binary To 5-digit BCD (4-2-1, 8-4-2-1, i1ctg's Post #105)
;
; input  = binH:binL                = 16-bit binary number
; output = tenk:thou:hund:tens:ones = 5-digit unpacked BCD number in ASCII
;
; For PIC18:
;  cycle =  93 maximum   , for binary numbers 2955x, 2956x, 3555x, 3556x
;        =  84 average
;        =  72 minimum   , for binary numbers 0..9
;  size  = 147 words
;
; For PIC16:
;  cycle = 130 maximum   , for 2955x, 2956x, 2959x, 2969x, 2995x, 2996x, 2999x
;        = 120 average
;        = 107 minimum   , for binary numbers 0..9
;  size  = 218 words
;

For comparison to the other routines, these cycle time should be two cycles less because
your routine returns digits in ASCII.  So, your routine takes 145 words of program memory and executes in a maximum of 91 instruction cycles on a PIC18.  NICELY DONE!  Smile: Smile
 
* Cycle timing does not include the CALL instruction.
 
NorthGuy
Super Member
  • Total Posts : 4830
  • Reward points : 0
  • Joined: 2014/02/23 14:23:23
  • Location: Northern Canada
  • Status: offline
Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/30 09:59:55 (permalink)
+1 (1)
Nice job!
 
And it's still some room for improvement, e.g. special handling for 200/-200, so, in the end, it is only couple dozen cycles off from multiplication routines. Probably, the fastest for PIC16.
 
@Harry: Would you measure it for enchanced PIC16s? With enchanced the only drag is bc/bnc, so should be around 110.
 
1and0
Access is Denied
  • Total Posts : 7745
  • 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/30 10:41:57 (permalink)
+1 (1)
NorthGuy
And it's still some room for improvement, e.g. special handling for 200/-200, so, in the end, it is only couple dozen cycles off from multiplication routines. Probably, the fastest for PIC16.

Agreed.
 

@Harry: Would you measure it for enchanced PIC16s? With enchanced the only drag is bc/bnc, so should be around 110.

You're right on the money! grin: grin
;
; For PIC16F1:
;  cycle = 110 maximum   , for 2955x, 2956x, 2959x, 2969x, 2995x, 2996x, 2999x
;        = 100 average
;        =  87 minimum   , for binary numbers 0..9
;  size  = 180 words
;

<edit> Removing "bnc p4k" after comparing with 20000 shaves one cycle off the maximum for PIC18 and two cycles for PIC16 and PIC16F1.  It only helps with numbers above 64000, and there's not enough numbers to affect the average cycle.
 
post edited by 1and0 - 2015/03/30 11:10:54
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/30 11:21:59 (permalink)
0
thank you, 1and0, for test and performance data.
i think than can not remove "bnc p4k" some results would be wrong
we can not do -40000 -20000 -10000  cumulating do -70000.
1and0
Access is Denied
  • Total Posts : 7745
  • 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/30 11:53:30 (permalink)
0
For i1ctg's routine in Post #105, branching from 60k to 4k, 8k to 1k, 800 to 100, and 80 to 10 do more harm than good.  They not only take up program memory but also either increase the maximum and average cycles or have no effect on the maximum, average and minimum cycles at all.  Here are the timing after removing those four branches:
;
; For PIC18:
;  cycle =  92 maximum   , for binary numbers 2955x, 2956x, 3555x, 3556x
;        =  83 average
;        =  72 minimum   , for binary numbers 0..9
;  size  = 143 words
;
; For PIC16F1:
;  cycle = 107 maximum   , for 2955x, 2956x, 2959x, 2969x, 2995x, 2996x, 2999x
;        =  98 average
;        =  87 minimum   , for binary numbers 0..9
;  size  = 172 words
;
; For PIC16:
;  cycle = 127 maximum   , for 2955x, 2956x, 2959x, 2969x, 2995x, 2996x, 2999x
;        = 118 average
;        = 107 minimum   , for binary numbers 0..9
;  size  = 210 words
;

post edited by 1and0 - 2015/03/30 12:10:48
1and0
Access is Denied
  • Total Posts : 7745
  • 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/30 16:56:29 (permalink)
0
In addition to removing the four BNC branches mentioned in Post #111, adding special handling for 200/-200 suggested by NorthGuy in Post #108 as followed:
        movlw   .200                   ; binH:binL = 0..399 here
        subwf   binL
    if  (PIC == PIC18)
        btfss   binH,0
        bnc     p100n                  ; bnc takes 1 word
    else
        btfsc   binH,0
        bra     p200s       
        bnc     p100n                  ; bnc takes 2 words
    endif
p200s   bsf     hund,1

p200n   movlw   .200
        addwf   binL
    if  (PIC == PIC18) || (PIC == PIC16E) || (PIC == PIC12E)
        movlw   0
        addwfc  binH
    else
        movlw   1
        skpnc
        addwf   binH
    endif
        bc      p200s

gives the following timings for i1ctg's routine:
; For PIC18:
;  cycle =  91 maximum   , for 3555x, 3556x, 5555x, 5556x
;        =  83 average
;        =  72 minimum   , for binary numbers 0..9
;  size  = 142 words
;
; For PIC16F1:
;  cycle = 107 maximum   , for 3555x, 3556x, 5555x, 5556x
;        =  98 average
;        =  87 minimum   , for binary numbers 0..9
;  size  = 172 words
;
; For PIC16:
;  cycle = 125 maximum   , for 3555x, 3556x, 5555x, 5556x
;        = 117 average
;        = 106 minimum   , for binary numbers 0..9
;  size  = 207 words

So far, this is the fastest for PIC16 at 123 instruction cycles.
 
<edit> We can shave another word and cycle off the maximum by removing the "movf binL,w" near "p200s", moving the "movf binL,w" at "p100n" to before "bc p200s", and changing the destination of "movlw .200/subwf binL,w" to the WREG.  So, that makes 122 Tcy for PIC16.
post edited by 1and0 - 2015/03/30 22:32:29
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/31 01:55:05 (permalink)
0
Thank you. I will try it now.
1and0
Access is Denied
  • Total Posts : 7745
  • 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/31 07:39:25 (permalink)
0
NorthGuy
Here's my attempt with hardware multiplication. I expected it to be faster, but it takes 67 cycles (66 words). The initial 16x24 nultiplication takes too long. ...

Changing the order of the various partial products calculation and avoiding overflow, I'm able to get it down to 62 cycles -- three more cycles to go :)
NorthGuy
Super Member
  • Total Posts : 4830
  • Reward points : 0
  • Joined: 2014/02/23 14:23:23
  • Location: Northern Canada
  • Status: offline
Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/31 07:49:48 (permalink)
0
1and0
Changing the order of the various partial products calculation and avoiding overflow, I'm able to get it down to 62 cycles -- three more cycles to go :)



I tried this, and it always were few numbers which required carry to the end. I didn't check different orders though.
 
I was checking it on PC, which is 32-bit, of course, and I forgot to chop it to 8-bit in one place, and I found out that I can remove almost all carries, and the cycle count went down to 61. I wanted to post the code, but then I thought it was too good to be true, so I looked through the code, found my bug, and put all the carries back :(
SeanD
Super Member
  • Total Posts : 475
  • Reward points : 0
  • Joined: 2009/10/23 07:48:32
  • Location: Dark Rural Northumberland
  • Status: offline
Re: HOW TO EXTRACT DIGITS FROM 16-BIT COUNTER? 2015/03/31 09:58:17 (permalink)
0
I'm probably missing something and many thanks to all who contributed this thread to this thread; this is exactly what I would like to see more of in this forum.
 
The subtract macro on Harry's #70 seems a bit odd and doesn't seem to work for me; possibly this is a cut and paste error?
;-------------------------------
;
; Subtract literal from frH:frL
;
sublf2  macro   frH,frL,lit
        movwf   frH
        movlw   low lit
        subwf   frL
        endm
;-------------------------------

 
When I use my own subtract macro things work as expected
Sublf  macro    value from register
; Subtracts a literal "value" from the register
; Value is limited to INT32 (4 Bytes signed) because of ASM Restrictions
; If value has more bytes than the register any higher bytes of value are set to zero
; and the borrow propagated through
;
   errorlevel -207,-311,-302

; For LSByte (byte0)-------------------
        Cbank   register              ; change to register bank if necessary
        movlw   low value              ; move 1east significant byte (byte0) to WREG
        subwf   register,f             ; subtract from LSB of the register
 ; for other bytes (if any)------------
    if SizeOf(register)>1
       i = 1                           ;if yes then add the other bytes with carry
            while i<SizeOf(register) ; while i is less than the number of register bytes
                if i==1
                    movlw high value   ;byte 1 (use of high eliminates some 151 errors)
                endif
                if i==2 | i==3         ; for byte2 and byte3 there can be valid data in the literal
                    movlw   0xFF & (value >> 8*i) ;mask and rotate
                endif
                if i==4
                    clrw               ;for byte4 the literal can't contain data and >> wraps around
                endif   
                subwfb   register+i,f
                i++
            endw
       endif
     endm

1and0
Access is Denied
  • Total Posts : 7745
  • 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/31 10:29:11 (permalink)
0
SeanD
I'm probably missing something ...

;-------------------------------
;
; Compare frH:frL to lit and jump if <
;
cjltl2  macro   frH,frL,lit,addr
        movlw   low  lit
        subwf   frL,w
        movlw   high lit
        subwfb  frH,w
        bnc     addr
        endm
;-------------------------------
;
; Subtract literal from frH:frL
;
sublf2  macro   frH,frL,lit
        movwf   frH
        movlw   low lit
        subwf   frL
        endm
;-------------------------------

That "sublf2" macro works in conjunction with and must follow the "cjltl2" macro shown in the same post to perform a 16-bit subtraction, when the comparison is false, where the high byte result* comes from "cjltl2".
 
A general 16-bit unsigned subtraction of a literal from a variable for the enhanced mid-range device is:
;
; Subtract literal from frH:frL
;
sublf2  macro   frH,frL,lit
        movlw   low (lit)
        subwf   frL,f
        movlw   high(lit)
        subwfb  frH,f

 
<edit> * That was done to save one cycle and one word since the high byte has already been calculated.
post edited by 1and0 - 2015/03/31 13:37:33
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/31 17:28:20 (permalink)
+1 (1)
Jorge, problem solved.
I had the loop jump to wrong label. Thanks you all for this neat efficient piece of code - pretty fast, only takes 85.8 µs.compared to the older version (125us), this about 45.7% improvement in speed. Surely this forum is full of geniuses!!!(:  My original way of unpacking also works fine, too. Just in case someone else makes the same mistake, correction is as highlighted.
 
;************************************************* *************************************************
; 16-bit Binary To 5-digit Packed BCD
; input = binH:binL = 16-bit binary number
; output = bcdU:bcdH:bcdL = 5-digit packed BCD number
;************************************************* *************************************************
LCD_BIN16TOBCD5
      MOVF LCD_POINT,W
      MOVWF LCD_TEMP_LO ;GET LOWER BYTE
      MOVF LCD_POINT + 1,W
      MOVWF LCD_TEMP_HI ;GET LOWER BYTE

                           CLRF LCD_TENTS
                           CLRF LCD_THOUS
                           CLRF LCD_HUNDS
                           CLRF LCD_TENS
      CLRF LCD_ONES

      MOVLW .16
      MOVWF BCD_BITCNT
      GOTO BCD_SHIFT
BCD5_CHECK_REM
                           MOVLW 0x33
      ADDWF LCD_ONES,F
      BTFSC LCD_ONES,3 ;CHECK BIT 3
      ANDLW 0xF0 ;IF SET, EXTRACT UPPER BITS
      BTFSC LCD_ONES,7 ;IF CLEAR, TEST MSB
      ANDLW 0X0F ;IF SET, EXTRACT LOW NIBBLE
      SUBWF LCD_ONES,F ;SUBTRACT B'0011 0011'

      MOVLW 0x33
      ADDWF LCD_HUNDS,F
      BTFSC LCD_HUNDS,3 ;CHECK BIT 3
      ANDLW 0xF0 ;IF SET, EXTRACT UPPER BITS
      BTFSC LCD_HUNDS,7 ;IF CLEAR, TEST MSB
      ANDLW 0x0F ;IF SET, EXTRACT LOW NIBBLE
      SUBWF LCD_HUNDS,F ;SUBTRACT B'0011 0011'

      MOVLW 0x03
      ADDWF LCD_TENTS,F
      BTFSS LCD_TENTS,3
      SUBWF LCD_TENTS,F

BCD_SHIFT RLF LCD_TEMP_LO,F
      RLF LCD_TEMP_HI,F
      RLF LCD_ONES,F ;ONETHS
      RLF LCD_HUNDS,F ;HUNDS
      RLF LCD_TENTS,F ;TENTHOUSANDTH
      DECFSZ BCD_BITCNT,F ;DECREMENT COUNTER
      GOTO BCD_CHECK_REM    ;Here is the problem. Jumping to wrong label
                                            ;UNPACKING THE BCD TO 5 BYTES
               SWAPF LCD_ONES,W
               ANDLW H'0F'
               MOVWF LCD_TENS

               SWAPF LCD_HUNDS,W
               ANDLW H'0F'
               MOVWF LCD_THOUS

               MOVLW H'0F'
               ANDWF LCD_ONES,F
               ANDWF LCD_HUNDS,F
               ANDWF LCD_TENTS,F

               MOVLW H'30' ;CONVERT BCD TO ASCII
               ;MOVLW H'3F' ;CONVERT BCD TO ASCII - TRIED THIS BUT SAME RESULTS
               IORWF LCD_ONES,F
               IORWF LCD_TENS,F
               IORWF LCD_HUNDS,F
               IORWF LCD_THOUS,F
               IORWF LCD_TENTS,F
        RETURN
;************************************************* *************************************************

 
post edited by schmity - 2015/03/31 20:21:46

Attachment(s)

Attachments are not available: Download requirements not met
1and0
Access is Denied
  • Total Posts : 7745
  • 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/31 20:17:21 (permalink)
0
These four lines are unnecessary and can be deleted.

MOVLW 0x03
ADDWF LCD_TENTS,F
BTFSS LCD_TENTS,3
SUBWF LCD_TENTS,F

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/31 20:24:06 (permalink)
0
So I may understand, any reason as to why, 1and0? Thanks for your tireless input.
Page: << < ..6789 > Showing page 6 of 9
Jump to:
© 2018 APG vNext Commercial Version 4.5