Searching \ for '[PIC]: Challenge: bcd to 16 bit binary (was: M' 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/devices.htm?key=pic
Search entire site for: 'Challenge: bcd to 16 bit binary (was: M'.

No exact or substring matches. trying for part
PICList Thread
'[PIC]: Challenge: bcd to 16 bit binary (was: Maths'
2001\01\20@041051 by Nikolai Golovchenko

flavicon
face
#include <p16f84.inc>
       cblock 0x0C
       ones, tens, hund, thou, tenk
       lo, hi
       endc


mov     macro __x, __y
       movlw __x
       movwf __y
       endm

       mov 1, ones
       mov 2, tens
       mov 0, hund
       mov 7, thou
       mov 5, tenk
       call bcd2bin16
       nop
;*******************************************************************************
; Input: unpacked BCD in  tenk:thou:hund:tens:ones
;Output: 16 bit binary in hi:lo
;  Size: 35 instructions
;Timing: 2+3+10+6+10+1+10+3+7+1+10+3+10+1+10+2+2=91 instruction cycles
;
; Notes:
;1) uses two stack levels
;2) if input is higher than 65535 output is meaningless
;3) algorithm synopsis:
;
;» dec2bin([1 10 100 1000 1e4], 16)
;ans = ;0000000000000001
;0000000000001010
;0000000001100100
;0000001111101000
;0010011100010000
;
;Or coded in three levels ('+' represents +1, '-' represents -1):
;00000000 0000000+      ones
;00000000 0000+0+0      tens
;00000000 0++00+00      hund
;00000+00 00-0+000      thou
;00+0+00- 000+0000      tenk
;
;bin = (((((((((((hund<<1)+
;       hund-thou+tenk*256)<<1)+
;       tenk)<<1)+
;       tens+thou+tenk*256)<<1)+
;       hund+thou*256)<<1)+
;       tens)<<1)+
;       ones-tenk*256
;
;January 20, 2000 by Nikolai Golovchenko
;*******************************************************************************
bcd2bin16
       movf hund, w
       movwf lo
       clrf hi
       call shift1add
       movf thou, w
       subwf lo, f
       skpc
        decf hi, f
       movf tenk, w
       addwf hi, f
       call shift1add
       movf tens, w
       call shift1add
       movf tenk, w
       addwf hi, f
       movf thou, w
       call shift0add
       movf hund, w
       call shift1add
       movf thou, w
       addwf hi, f
       movf tens, w
       call shift1add
       movf ones, w
       call shift1add
       movf tenk, w
       subwf hi, f
       return

shift1add
       clrc
       rlf lo, f
       rlf hi, f
shift0add
       addwf lo, f
       skpnc
        incf hi, f
       return
;*******************************************************************************

       END
       ---- Original Message ----
From: Philip Martin <spam_OUTphilip.martin1TakeThisOuTspamBTINTERNET.COM>
Sent: Friday, January 19, 2001 19:00:50
 To: .....PICLISTKILLspamspam@spam@MITVMA.MIT.EDU
Subj: [PIC]:Maths Problem

{Quote hidden}

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listservspamKILLspammitvma.mit.edu with SET PICList DIGEST in the body


2001\01\23@102727 by o-8859-1?Q?K=FCbek_Tony?=

flavicon
face
Ok..a challenge..from Nicolai...no chance of beating him
I guess :) ..but here goes 44'ish instructions ( not counting
setup of input ) executes in the same amount of cycles (i.e 44 ) :


;
***********************************************************************
; TEST_ASC_TO_BIN
; Routine to test ascii to 16 binary conversion
;
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


But I just happen to know that Nicolai has an 37 cycle waiting,
:( ...anyway..this beat's his 91 cycle version...

Have fun,

/Tony




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

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics


2001\01\24@025833 by Nikolai Golovchenko

flavicon
face
Very interesting, Tony! It also shows that there is a lot of
possible implementations, as many as Piclisters probably. So, a
pretty high chance of making an improvement!

It even gives me an idea to squeeze one more line out of the previous
36. :) But first the initial code:

;*******************************************************************************
; Input: unpacked BCD in  tenk:thou:hund:tens:ones
;Output: 16 bit binary in hi:lo
;  Size: 36 instructions
;Timing: 2+35+2=39 instruction cycles
;
; Notes:
;1) if input is higher than 65535 output is meaningless
;2) algorithm synopsis:
;
;> dec2bin([1 10 100 1000 1e4], 16)
;ans = ;0000000000000001
;0000000000001010
;0000000001100100
;0000001111101000
;0010011100010000
;
;Or coded in three levels ('+' represents +1, '-' represents -1):
;0000 0000 0000 000+ * ones +
;0000 0000 0000 +0+0 * tens +
;0000 0000 0++0 0+00 * hund +
;0000 0+00 00-0 +000 * thou +
;00+0 +00- 000+ 0000 * tenk
;
;bin = (((tens+thou+tenk*256)*2+
;       hund+hund*16+thou*256)*2+
;       tens+hund*16-thou*16+tenk*16*256)*2+
;       ones+tenk*16-tenk*256
;
;January 22, 2001 by Nikolai Golovchenko
;*******************************************************************************

dec2bin16
       movf tens, w
       addwf thou, w
       movwf lo
       movf tenk, w
       movwf hi
       rlf lo, f
       rlf hi, f

       swapf hund, w
       addwf hund, w
       addwf lo, f
       movf thou, w
       addwf hi, f
       rlf lo, f
       rlf hi, f

       swapf hund, w
       addwf tens, w
       addwf lo, f
       swapf tenk, w
       skpnc
        iorlw 0x01
       addwf hi, f
       swapf thou, w
       subwf lo, f
       skpc
        decf hi, f
       clrc
       rlf lo, f
       rlf hi, f

       swapf tenk, w
       addwf ones, w
       addwf lo, f
       movf tenk, w
       skpnc
        decf tenk, w
       subwf hi, f
       return
;*******************************************************************************

The first few lines:
dec2bin16
       movf tens, w
       addwf thou, w
       movwf lo
       movf tenk, w
       movwf hi
       rlf lo, f
       rlf hi, f

can be replaced by these:
dec2bin16
       movf tens, w
       addwf thou, w
       movwf lo
       addwf lo, f
       rlf tenk, w
       movwf hi

Thanks Tony. Hmm, I wonder how much code a C compiler would
generate for the routine above?

If someone is really desperate on the free RAM and ROM space,
here is a a smaller version (but much longer to execute) which
operates on packed BCD:

#include <p16f84.inc>
       cblock 0x0C
       bcd0, bcd1, bcd2
       lo, hi
       counter
       endc

mov     macro __x, __y
       movlw __x
       movwf __y
       endm

       mov 0x06, bcd2
       mov 0x55, bcd1
       mov 0x35, bcd0
       call bcd2bin16
       nop

;*******************************************************************************
;    Input: packed BCD in bcd2:bcd1:bcd0 (modified!)
;           bcd0 = tens:ones
;           bcd1 = thou:hund
;           bcd2 = 0:tenk
;   Output: 16 bit binary in hi:lo
;Temporary: counter
;     Size: 23 instructions
;   Timing: 2+2+16*(6+12+3)-1+2=341 instruction cycles
;
; Notes: The routine uses BCD division by 2. Each iteration
;        the LSB of BCD value (which coincides with correspondent
;        binary bit) is shifted to output and BCD value is
;        divided by 2. To do the division, BCD is shifted right
;        once and corrected. Correction: if MSB of a nibble is set,
;        subtract 3 from it.
;
;January 22, 2001 by Nikolai Golovchenko
;*******************************************************************************
bcd2bin16
       movlw 16
       movwf counter
bcd2bin16loop
       clrc
       rrf bcd2, f
       rrf bcd1, f
       rrf bcd0, f
       rrf hi, f
       rrf lo, f

       clrw
       btfsc bcd0, 3
        iorlw 0x03
       btfsc bcd0, 7
        iorlw 0x30
       subwf bcd0, f
       clrw
       btfsc bcd1, 3
        iorlw 0x03
       btfsc bcd1, 7
        iorlw 0x30
       subwf bcd1, f
               decfsz counter, f
        goto bcd2bin16loop
       return
;*******************************************************************************

       END

       Best regards,
Nikolai

---- Original Message ----
From: Kübek Tony <EraseMEtony.kubekspam_OUTspamTakeThisOuTFLINTAB.COM>
Sent: Tuesday, January 23, 2001 17:04:34
 To: PICLISTspamspam_OUTMITVMA.MIT.EDU
Subj: [PIC]: Challenge: bcd to 16 bit binary (was: Maths Problem)

{Quote hidden}

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