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 =3D TenMil,OneMil,HunK,TenK,Thou,Hun,Ten,Ones = ; output =3D 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 =3D 1 =3D 1 ; 000000000000000000001010 =3D 10 =3D 8+2 ; 000000000000000001100100 =3D 100 =3D 64+32+4 ; 000000000000001111101000 =3D 1000 =3D 512+256+128+64+32+8 ; 000000000010011100010000 =3D 10000 =3D 8192+1024+512+256+32 ; 000000011000011010100000 =3D 100000 =3D 65536+32768+1024+512+128+32 ; 000011110100001001000000 =3D 1000000 =3D 524288+262144+131072+65536+16384+512+64 ; 100110001001011010000000 =3D 10000000=3D 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 =3D 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 =3D 1 =3D 1 ; 0000 0000 0000 0000 0000 1010 =3D 10 =3D 8+2 ; 0000 0000 0000 0000 0110 0100 =3D 100 =3D 64+32+4 ; 0000 0000 0000 0011 1110 1000 =3D 1000 =3D 512+256+128+64+32+8 ; 0000 0000 0010 0111 0001 0000 =3D 10000 =3D 8192+1024+512+256+32 ; 0000 0001 1000 0110 1010 0000 =3D 100000 =3D 65536+32768+1024+512+128+32 ; 0000 1111 0100 0010 0100 0000 =3D 1000000 =3D 524288+262144+131072+65536+16384+512+64 ; 1001 1000 1001 0110 1000 0000 =3D 10000000=3D 8388608+1048576+524288+32768+4096+1024+512+128 ; s--- +--- +--- +--- +--- +--- = ; | | | | | =3D Thou*8 + Hun*4 + Ten*(8+2) + Ones ; | | | | =3D TenMil*8 + OneMil*4 + HunK*(8+2) + Tenk + Thou*(8+4+2) + Hun*(4+2) ; | | | =3D etc.. ; | | =3D etc.. ; | =3D eyc.. ; =3D 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 =3D 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 =3D 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 =3D hi<<4 + lo ; etc. etc.. ; ********code start******** ; *nibble 1 MOVF Thou,W ; w =3D thou ADDWF Ten,W ; w =3D thou + ten MOVWF Lo ; lo =3D thou + ten ADDWF Lo,W ; w =3D 2*(thou + ten) ADDWF Hun,W ; w =3D 2*(thou + ten) + hun MOVWF Lo ; lo =3D 2*(thou + ten) + hun ADDWF Lo,W ; w =3D 2*(2*(thou + ten) + hun) ADDWF Ten,W ; w =3D 2*(2*(thou + ten) + hun)+ten MOVWF Lo ; lo =3D 2*(2*(thou + ten) + hun)+ten ADDWF Lo,W ; w =3D 2*(2*(2*(thou + ten) + hun)) ADDWF Ones,W ; w =3D 2*(2*(2*(thou + ten) + hun)) + ones MOVWF Lo ; lo =3D 2*(2*(2*(thou + ten) + hun)) + ones =3D 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 =3D thou = ADDWF HunK,W ; w =3D thou + hunk ; ** note we do not add variable tenmil, that will be at the end, else it should have been here MOVWF Hi ; w =3D 2*(thou + hunk) ADDWF Hi,W ; hi =3D 2*(thou + hunk) ADDWF Hun,W ; w =3D 2*(thou + hunk) + hun ADDWF Thou,W ; w =3D 2*(thou + hunk) + hun + thou ADDWF OneMil,W ; w =3D 2*(thou + hunk) + hun + thou + onemil MOVWF Hi ; hi =3D 2*(thou + hunk) + hun + thou + onemil ADDWF Hi,W ; w =3D 2*(2*(thou + hunk) + hun + thou + onemil ) = ADDWF Thou,W ; w =3D 2*(2*(thou + hunk) + hun + thou + onemil ) + thou ADDWF Hun,W ; w =3D 2*(2*(thou + hunk) + hun + thou + onemil ) + thou + hun ADDWF HunK,W ; w =3D 2*(2*(thou + hunk) + hun + thou + onemil ) + thou + hun + hunk MOVWF Hi ; hi =3D 2*(2*(thou + hunk) + hun + thou + onemil ) + thou + hun + hunk ; Potential maximum value here: 2*(2*(9+9)+9+9+9)+9+9+9 =3D 153 ; therefore we now must watch the carry when doubling and performing the last addition ADDWF Hi,W ; w =3D 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 =3D 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 =3D 2*(2*(2*(thou + hunk) + hun + thou + onemil ) + thou + hun + hunk) + tenk ; i.e. =3D 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 =3D OverFlow(lo) ; *nibble 3 ; still using hi as temp we calculate the third nibble MOVF TenK,W ; w =3D tenk = ADDWF HunK,W ; w =3D tenk + hunk ; ** note we do not add variable tenmil, that will be at the end, else it should have been here MOVWF Hi ; hi =3D tenk + hunk ADDWF Hi,W ; w =3D 2*(tenk + hunk) ADDWF Hi,W ; w =3D 3*(tenk + hunk) ADDWF OneMil,W ; w =3D 3*(tenk + hunk)+onemil ADDWF Thou,W ; w =3D 3*(tenk + hunk)+onemil+thou ADDWF Hi,F ; hi =3D 4*(tenk + hunk)+onemil+thou ADDWF Thou,W ; w =3D 3*(tenk + hunk)+onemil+2*thou ADDWF Hi,F ; hi =3D 7*(tenk+hunk)+2*onemil+3*thou MOVF HunK,W ; w =3D hunk SUBWF Hi,W ; w =3D 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 ) =3D 194 ; i.e. no risk of carry ADDWF Med,F ; med =3D 7*tenk+6*hunk+2*onemil+3*thou + overflow(lo) ; *nibble 4 ; using hi as temp RLF HunK,W ; w =3D 2*hunk ( carry known to be cleared ) ADDWF OneMil,W ; w =3D 2*hunk+onemil = MOVWF Hi ; hi =3D 2*hunk+onemil = ADDWF Hi,W ; w =3D 2*(2*hunk+onemil) ADDWF TenK,W ; w =3D 2*(2*hunk+onemil)+tenk MOVWF Hi ; hi =3D 2*(2*hunk+onemil)+tenk ADDWF Hi,F ; hi =3D 2*(2*(2*hunk+onemil)+tenk) =3D 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 =3D overflow(med,lo) ; *nibble 5 SWAPF OneMil,W ; w =3D 16*onemil ADDWF Hi ; hi =3D overflow(med,lo)+16*onemil MOVF OneMil,W ; w =3D onemil SUBWF Hi,W ; w =3D overflow(med,lo)+15*onemil ADDWF HunK,W ; w =3D 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=FCbek, Flintab AB = =B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2= =B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2= =B2=B2=B2=B2=B2=B2=B2=B2=B2=B2 E-mail: tony.kubek@flintab.com =B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2= =B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2=B2= =B2=B2=B2=B2=B2=B2=B2=B2=B2=B2 -- http://www.piclist.com hint: The PICList is archived three different ways. See http://www.piclist.com/#archives for details.