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?=
|
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.kubekTakeThisOuT
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@191150
by
o-8859-1?Q?K=FCbek_Tony?=
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.kubekKILLspam
@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?=
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.kubek
KILLspamflintab.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...