PIC Microcontoller Radix Math Method

Unpacked BCD to 16 bit binary conversion

;***********************************************************************
; TEST_ASC_TO_BIN
; Routine to test ascii to 16 binary conversion
; 41 instructions and cycles.
TEST_ASC_TO_BIN
        GLOBAL  TEST_ASC_TO_BIN

        ; load test value
        MOVLW   D'1'
        MOVWF   TenK,B
        MOVLW   D'2'
        MOVWF   Thou,B
        MOVLW   D'0'
        MOVWF   Hun,B
        MOVLW   D'7'
        MOVWF   Ten,B
        MOVLW   D'5'
        MOVWF   Ones,B
        NOP

        ; these are not needed only used during dev. test
        CLRF    Hi,B
        CLRF    Lo,B


        ; bcd to binary conversion 16 bits ( i.e. max input is 65535 )
        ; 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:
        ; 0000000000000001=    1     = 1
        ; 0000000000001010=    10    = 8+2
        ; 0000000001100100=    100   = 64+32+4
        ; 0000001111101000=    1000  = 512+256+128+64+32+8
        ; 0010011100010000=    10000 = 8192+1024+512+256+32
        ;
        ; calculation perform according to the following pseudo code:
        ; Separate each nibble:
        ;
        ; 0000 0000 0000 0001=    1     = 1
        ; 0000 0000 0000 1010=    10    = 8+2
        ; 0000 0000 0110 0100=    100   = 64+32+4
        ; 0000 0011 1110 1000=    1000  = 512+256+128+64+32+8
        ; 0010 0111 0001 0000=    10000 = 8192+1024+512+256+32
        ;       
        ; 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..
        ;
        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
        MOVF    Thou,W  ; w =Thou 
        ADDWF   Thou,W  ; w = 2 * Thou
        ADDWF   Hun,W           ; w = 2 * Thou + hun
        ADDWF   Thou,W  ; w = 2 * Thou + hun + thou
        MOVWF   Hi              ; hi = 2 * Thou + hun + thou
        ADDWF   Hi,W            ; w = 2*(2 * Thou + hun + thou) = 6*thou + 2*hun
        ADDWF   Thou,W  ; w = 6*thou + 2*hun + thou
        ADDWF   Hun,W           ; w = 6*thou + 2*hun + thou + hun
        MOVWF   Hi              ; hi = 6*thou + 2*hun + thou + hun
        ADDWF   Hi,W            ; w = 2* ( 6*thou + 2*hun + thou + hun )) = 14*thou + 6*hun
        ADDWF   TenK,W  ; w =  14*thou + 6*hun + tenk
        MOVWF   Hi              ; hi =  14*thou + 6*hun + tenk
        ; 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 ) 
        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
        MOVWF   Hi              ; Hi = overflow(lo)
        ; now we have overflow from lo byte caculation in Hi therefor we cannot use the hi byte temporarily
        ; the following calculation must be performed in w only ( I just whish an temp was available :) 
        ; or one could trash the input....) 
        RLF     TenK,W  ; w = 2*tenk
        ADDWF   TenK,W  ; w = 3*tenk 
        ADDWF   TenK,W  ; w = 4*tenk 
        ADDWF   TenK,W  ; w = 5*tenk 
        ADDWF   TenK,W  ; w = 6*tenk 
        ADDWF   TenK,W  ; w = 7*tenk 
        ADDWF   Thou,W  ; w = 7*tenk + thou
        ADDWF   Thou,W  ; w = 7*tenk + 2*thou
        ADDWF   Thou,W  ; w = 7*tenk + 3*thou
        ADDWF   Hi,F            ; add it to the overflow from lo        
        SWAPF   TenK,W  ; w = 32 * tenk
        ADDWF   Hi,F            ; hi = 7*tenk + 3*thou + 32*Tenk
        ADDWF   Hi,F            ; hi = 7*tenk + 3*thou + 32*Tenk + 32*Tenk = 7*tenk + 3*thou + 64*Tenk 
        NOP
        RETURN


Questions: