Searching \ for '[PIC]: Challenge: bcd to 24 bit binary (was: Maths' in subject line. ()
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.
'[PIC]: Challenge: bcd to 24 bit binary (was: Maths'
2001\01\24@115138 by

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
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
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
ADDLW   0x01            ; in case of ripple carry we add one to
hi byte
; 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
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
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

MOVLW   0x96    ; middle byte
SKPNC
MOVLW 0x97

MOVLW   0x98    ; highest byte
SKPNC
MOVLW 0x99

RETURN  ; we are done, 89'ish cycles

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

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

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

Should ofcource be:

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

/Tony

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

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

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.kubekflintab.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...