Searching \ for '[PIC]: Challenge: bcd to 24 bit binary (was: Maths' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: techref.massmind.org/techref/microchip/math/index.htm?key=math
Search entire site for: 'Challenge: bcd to 24 bit binary (was: Maths'.

Exact match. Not showing close matches.
PICList Thread
'[PIC]: Challenge: bcd to 24 bit binary (was: Maths'
2001\01\24@115138 by o-8859-1?Q?K=FCbek_Tony?=

flavicon
face
Ok here we go again, following up the interesting
challenge bcd to binary conversion here is an
24 bit version. Anyone up for grabs :) ?

It's not particulary effective, 78 cycles for numbers<10'mil
and 89'ish cycles for numbers>10'mil.
I have a much better one lurking in the back of my head but
way to little time for this ( thanks nicolai :) ).
This one took an hour or so originating from the previous
44 cycle slouch for 16bit conversion ( which btw can be shortened
by 1-2 cycles, but is still far from Nicolai's 36 cycle screamer ).


;
***********************************************************************
; TEST_BCD_TO_BIN24
; Routine to test bcd to 24bit binary conversion
;
TEST_BCD_TO_BIN24
       GLOBAL  TEST_BCD_TO_BIN24
       ; ram required:
       ; input = TenMil,OneMil,HunK,TenK,Thou,Hun,Ten,Ones
       ; output = Hi,Med,Lo ( where Hi is msb )
       ; no temp used

       ; load test value 12212075, should become 0xBA576B
       MOVLW   D'1'
       MOVWF   TenMil
       MOVLW   D'2'
       MOVWF   OneMil
       MOVLW   D'2'
       MOVWF   HunK
       MOVLW   D'1'
       MOVWF   TenK
       MOVLW   D'2'
       MOVWF   Thou
       MOVLW   D'0'
       MOVWF   Hun
       MOVLW   D'7'
       MOVWF   Ten
       MOVLW   D'5'
       MOVWF   Ones

       CLRF    Hi      ; not required
       CLRF    Lo     ; not required

TEST_BCD_START  
       CLRF    Med     ; required !

       ; bcd to binary conversion 24 bits ( i.e. max input is 16777215
)
       ; uses nibble math there lowest nibble i calculated first
       ; the 'overflow' added to the calculation for the second nibble
       ; etc. upto the third nibble. Then the last additions for the
       ; fourth nibble which only is affected by ( apart from overflow
from lower nibbles )
       ; the input byte tenk.
       ; uses factorisation of the decimal weight contants as per this
table:

       ; 000000000000000000000001 =  1       = 1
       ; 000000000000000000001010 =          10      = 8+2
       ; 000000000000000001100100 =  100     = 64+32+4
       ; 000000000000001111101000 =  1000    = 512+256+128+64+32+8
       ; 000000000010011100010000 =  10000   = 8192+1024+512+256+32
       ; 000000011000011010100000 =  100000  =
65536+32768+1024+512+128+32
       ; 000011110100001001000000 =  1000000 =
524288+262144+131072+65536+16384+512+64
       ; 100110001001011010000000 =  10000000=
8388608+1048576+524288+32768+4096+1024+512+128
       ;
       ; calculation perform according to the following pseudo code:
       ; Separate each nibble and calculate the result for that nibble
into
       ; one byte ( top nibble = overflow ), then we calculate the next
nibble
       ; and add the lowest nibble of the resultant byte to the top
nibble of the first.
       ; This way, propagating evetual overflow throught the nibbles we
continue through the input.
       ;
       ; 0000 0000 0000 0000 0000 0001 =     1       = 1
       ; 0000 0000 0000 0000 0000 1010 =     10      = 8+2
       ; 0000 0000 0000 0000 0110 0100 =     100     = 64+32+4
       ; 0000 0000 0000 0011 1110 1000 =     1000    =
512+256+128+64+32+8
       ; 0000 0000 0010 0111 0001 0000 =     10000   =
8192+1024+512+256+32

       ; 0000 0001 1000 0110 1010 0000 =     100000  =
65536+32768+1024+512+128+32
       ; 0000 1111 0100 0010 0100 0000 =     1000000 =
524288+262144+131072+65536+16384+512+64
       ; 1001 1000 1001 0110 1000 0000 =     10000000=
8388608+1048576+524288+32768+4096+1024+512+128
       ; s--- +--- +--- +--- +--- +---
       ; |    |    |    |    |    =  Thou*8 + Hun*4 + Ten*(8+2) +
Ones
       ; |    |    |    |    =               TenMil*8 + OneMil*4 + HunK*(8+2)
+ Tenk + Thou*(8+4+2) + Hun*(4+2)
       ; |    |    |    =            etc..
       ; |    |    =                 etc..
       ; |    =                      eyc..
       ; = Special case, as we only accept 10'mil digit to be either 0
or 1 we can by
       ;   checking for TenMil to be nonzero add 10'mil as a constant
at the end.
       ;
       ;
       ; Use the variable lo to calculate the result of the lowest
nibble:
       ; lo = Thou*8 + Hun*4 + Ten*(8+2) + Ones
       ; the result and overflow ( top nibble ) is saved and
calculation is perfromed on the second nibble
       ; by using the variable hi:
       ; hi = Tenk + Thou*(8+4+2) + Hun*(4+2)
       ; The low nibble from the result is added to the high nibble
from the
       ; previous calculation of lo:
       ; lo = hi<<4 + lo
       ; etc. etc..
       ; ********code start********
       ; *nibble 1
       MOVF    Thou,W  ; w = thou
       ADDWF   Ten,W           ; w = thou + ten
       MOVWF   Lo              ; lo = thou + ten
       ADDWF   Lo,W            ; w = 2*(thou + ten)
       ADDWF   Hun,W           ; w = 2*(thou + ten) + hun
       MOVWF   Lo              ; lo = 2*(thou + ten) + hun
       ADDWF   Lo,W            ; w = 2*(2*(thou + ten) + hun)
       ADDWF   Ten,W           ; w = 2*(2*(thou + ten) + hun)+ten
       MOVWF   Lo              ; lo = 2*(2*(thou + ten) + hun)+ten
       ADDWF   Lo,W            ; w = 2*(2*(2*(thou + ten) + hun))
       ADDWF   Ones,W  ; w = 2*(2*(2*(thou + ten) + hun)) + ones
       MOVWF   Lo              ; lo = 2*(2*(2*(thou + ten) + hun)) +
ones = 8*Thou + 10*ten + 4*hun + ones
       ; low byte lowest nibble now fully calculated in lo
       ; now we calculate high nibble lo byte by using hi as temp
storage
       ; *nibble 2
       MOVF    Thou,W  ; w = thou
       ADDWF   HunK,W  ; w = thou + hunk
       ; ** note we do not add variable tenmil, that will be at the
end, else it should have been here
       MOVWF   Hi              ; w = 2*(thou + hunk)
       ADDWF   Hi,W            ; hi = 2*(thou + hunk)
       ADDWF   Hun,W           ; w = 2*(thou + hunk) + hun
       ADDWF   Thou,W  ; w = 2*(thou + hunk) + hun + thou
       ADDWF   OneMil,W        ; w = 2*(thou + hunk) + hun + thou +
onemil
       MOVWF   Hi              ; hi = 2*(thou + hunk) + hun + thou +
onemil
       ADDWF   Hi,W            ; w = 2*(2*(thou + hunk) + hun + thou +
onemil )
       ADDWF   Thou,W  ; w = 2*(2*(thou + hunk) + hun + thou + onemil )
+ thou
       ADDWF   Hun,W           ; w = 2*(2*(thou + hunk) + hun + thou +
onemil )  + thou + hun
       ADDWF   HunK,W  ; w = 2*(2*(thou + hunk) + hun + thou + onemil )
+ thou + hun + hunk
       MOVWF   Hi              ; hi = 2*(2*(thou + hunk) + hun + thou +
onemil )  + thou + hun + hunk
                               ; Potential maximum value here:
2*(2*(9+9)+9+9+9)+9+9+9 = 153
                               ; therefore we now must watch the carry
when doubling and performing the last addition
       ADDWF   Hi,W            ; w = 2*(2*(2*(thou + hunk) + hun + thou
+ onemil )  + thou + hun + hunk)
       ; propagate carry
       RLF     Med,F           ; rotate eventual carry into lowest bit
of med
       ADDWF   TenK,W  ; w =  2*(2*(2*(thou + hunk) + hun + thou +
onemil )  + thou + hun + hunk) + tenk
       ; check carry again
       BTFSC   STATUS,C
       ADDLW   0x01            ; propagate carry
       MOVWF   Hi              ; hi =  2*(2*(2*(thou + hunk) + hun +
thou + onemil )  + thou + hun + hunk) + tenk
                               ; i.e. = HunK*(8+2) + Tenk +
Thou*(8+4+2) + Hun*(4+2)
                               ; and med contains the eventual overflow
from this nibble
       ; low byte high nibble fully calculated in hi
       ; now we need to add the low nibble to previous content in lo (
from low nibble calc. )
       SWAPF   Hi,W            ; swap nibbles  ( lownibble->high )
       ANDLW   0xF0            ; mask out high nibble
       ADDWF   Lo,F            ; add result to lo byte ( note carry
checked 4 rows down ! )
       SWAPF   Hi,W            ; swap nibbles ( high nibble->low )
       SWAPF   Med,F           ; swap eventual overflow from high
nibble calc. ( i.e. bit0 becomes bit4 )
       ANDLW   0x0F            ; mask out low nibble
       BTFSC   STATUS,C        ; now we check the carry from the
addition of the lo byte
       ADDLW   0x01            ; in case of ripple carry we add one to
hi byte
       ADDWF   Med,F           ; and add it to the carry propagation
                               ; Med = OverFlow(lo)
       ; *nibble 3
       ; still using hi as temp we calculate the third nibble
       MOVF    TenK,W  ; w = tenk
       ADDWF   HunK,W  ; w = tenk + hunk
       ; ** note we do not add variable tenmil, that will be at the
end, else it should have been here
       MOVWF   Hi              ; hi = tenk + hunk
       ADDWF   Hi,W            ; w = 2*(tenk + hunk)
       ADDWF   Hi,W            ; w = 3*(tenk + hunk)
       ADDWF   OneMil,W        ; w = 3*(tenk + hunk)+onemil
       ADDWF   Thou,W  ; w = 3*(tenk + hunk)+onemil+thou
       ADDWF   Hi,F            ; hi = 4*(tenk + hunk)+onemil+thou
       ADDWF   Thou,W  ; w = 3*(tenk + hunk)+onemil+2*thou
       ADDWF   Hi,F            ; hi = 7*(tenk+hunk)+2*onemil+3*thou
       MOVF    HunK,W  ; w = hunk
       SUBWF   Hi,W            ; w = 7*tenk+6*hunk+2*onemil+3*thou
       ; third nibble fully calculated in w
       ; add to the previous overflow from lo we saved in med
       ; potential maximum value here: 7*9+6*9+2*9+3*9+32(maximum
overflow from lo ) = 194
       ; i.e. no risk of carry
       ADDWF   Med,F           ; med = 7*tenk+6*hunk+2*onemil+3*thou +
overflow(lo)
       ; *nibble 4
       ; using hi as temp
       RLF     HunK,W  ; w = 2*hunk ( carry known to be cleared )
       ADDWF   OneMil,W        ; w = 2*hunk+onemil  
       MOVWF   Hi              ; hi = 2*hunk+onemil  
       ADDWF   Hi,W            ; w = 2*(2*hunk+onemil)
       ADDWF   TenK,W  ; w = 2*(2*hunk+onemil)+tenk
       MOVWF   Hi              ; hi = 2*(2*hunk+onemil)+tenk
       ADDWF   Hi,F            ; hi = 2*(2*(2*hunk+onemil)+tenk) =
8*hunk+4*onemil+2*tenk
       ; now we add the low nibble to med
       SWAPF   Hi,W            ; swap nibbles  ( lownibble->high )
       ANDLW   0xF0            ; mask out high nibble
       ADDWF   Med,F           ; add result to lo byte ( note carry
checked 4 rows down ! )
       SWAPF   Hi,W            ; swap nibbles ( high nibble->low )
       ANDLW   0x0F            ; mask out low nibble
       BTFSC   STATUS,C        ; now we check the carry from the
addition of the lo byte
       ADDLW   0x01            ; in case of ripple carry we add one to
hi byte
       ; w contains the overflow from med and lo bytes
       ; we end  by calculation the 5'th ( and last nibble before
10'mil check)
       MOVWF   Hi              ; hi = overflow(med,lo)
       ; *nibble 5
       SWAPF   OneMil,W        ; w = 16*onemil
       ADDWF   Hi              ; hi = overflow(med,lo)+16*onemil
       MOVF    OneMil,W        ; w = onemil
       SUBWF   Hi,W            ; w = overflow(med,lo)+15*onemil
       ADDWF   HunK,W  ; w = overflow(med,lo)+15*onemil+hunk
       MOVWF   Hi              ; hi byte done
       ; now the last step is to check if tenmil is nonzero
       ; if so we add 10'mil to current result
       MOVF    TenMil,F
       BTFSC   STATUS,Z
       RETURN  ; we are done, 78 cycles
       ; we need to add 10 mil to current result. 0x989680
       MOVLW   0x80 ; lowest byte
       ADDWF   Lo,F

       MOVLW   0x96    ; middle byte
        SKPNC  
           MOVLW 0x97
             ADDWF Med,F
             
       MOVLW   0x98    ; highest byte
        SKPNC  
           MOVLW 0x99
             ADDWF Hi,F
               
       RETURN  ; we are done, 89'ish cycles





Tony Kübek, Flintab AB            
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²
E-mail: spam_OUTtony.kubekTakeThisOuTspamflintab.com
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.


2001\01\24@191150 by o-8859-1?Q?K=FCbek_Tony?=

flavicon
face
Here is the error ( not so easily detected if one doesn't
read the code ). I don't know how this line was replaced
but I somehow managed to change it. Detected by entering
the number 84999xx ( where the xx's are any number ) :)

The lines at the end of nibble two calc:

       ; check carry again
       BTFSC   STATUS,C
       ADDLW   0x01            ; propagate carry

Should ofcource be:

       ; check carry again
       BTFSC   STATUS,C
       INCF    Med,F           ; propagate carry in to med

Sorry about the hasty work,

/Tony


Tony Kübek, Flintab AB            
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²
E-mail: .....tony.kubekKILLspamspam@spam@flintab.com
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.


2001\01\24@191153 by o-8859-1?Q?K=FCbek_Tony?=

flavicon
face
Ah there's an error I belive in the snippet I sent,
I dosen't look the same, hmmm maybe to much search/replace before
I sent it ( to remove 18Cxxx only instructions ).
Have to print it out and check it anyway it seems to work
originally ( before I went at it with the editor :) ).
I'll post when i find it.

/Tony

Tony Kübek, Flintab AB            
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²
E-mail: tony.kubekspamKILLspamflintab.com
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.


More... (looser matching)
- Last day of these posts
- In 2001 , 2002 only
- Today
- New search...