PIC Microcontoller Radix Math Method

Binary to BCD unpacked 17 bit to 5 full digits

From: Mike Mansheim of Graco, Inc.

/*

- based on the 16 bit to 5 digit conversion written by John Payson
  & explained by Scott Dattalo
- this version adds the extra bit so that the 5 digit display can
  read to 99,999
- want to express the b_i's in terms of the a_i's for the equations:
       N = a4*16^4 + a3*16^3 + a2*16^2 + a1*16 + a0
       N = b4*10^4 + b3*10^3 + b2*10^2 + b1*10 + b0
  the solution coded below:
       b0 = a0 - (4 * (a4 + a3 + a2 + a1)) - 20
       b1 = (4 * a4) + (6 * a2) + (2 * a1) - 198
       b2 = (5 * a4) + a3 + (2 * a2) - 140
       b3 = (5 * a4) + (4 * a3) - 144
       b4 = (6 * a4) + 16
- written in CCS C
- since ram was plentiful, I used a 3 byte number - only one bit
  of the extra byte is actually required.  I also used three bytes
  of scratchpad ram to increase the efficiency of the compiled code.
  The equations can be coded in C exactly as shown above, but that
  doesn't take advantage of common terms & progressive multiplies.
- even with just the one extra bit, the incoming number  can exceed
  99,999, so it needs to be checked.  This code doesn't show that.
- CCS C is limited to 16 bit as the largest integer data type.  To
  use a 24 bit number, I use an array to make sure the bytes are
  consecutive.  This function operates on the array as a global,
  because I think that is more efficient than passing arrays to
  the function.
- the code could be quite a bit smaller - in John's original, the
  portion of the code that isolated the nibbles and calculated the
  digits took 32 instructions.  If I code that solution in C, using
  two scratchpad bytes to improve things, it compiles to 64 instructions.
  This version compiles to 85 instructions, so I'm sure an asm whiz
  could show quite an improvement.  The C version is still much faster
  than the the original way I did this, and is adequate for what I need.
*/

unsigned int  TenK, Thou, Hund, Tens, Ones;
unsigned int  num[3];

void BIN2DEC(void)
{
     // operates on global variables:
     // set num[0]-[3] (lo-hi) before calling
     // returns with TenK...Ones set from 0-9

     unsigned int a0, a1, a2, a3, a4;
     unsigned int t1, t2, t3;			// scratchpad variables
	
     // isolate the 4 bit nibbles
     // for the purposes of this routine, a4 can be only 0 or 1
     a4 = num[2];
     a3 = num[1] / 16;
     a2 = num[1] & 0b00001111;
     a1 = num[0] / 16;
     a0 = num[0] & 0b00001111;

     // calculate the decimal digits (the b_i's are expressed here
     // as TenK...Ones, as in the original)
     // all are negative, except TenK
     t1 = 4 * a4;
     Ones = a0 - t1 - 20;
     t2 = 2 * a1;
     Tens = t1 + t2 - 198;
     t3 = 2 * a2;
     Hund = a3 + t3 - 140;
     t3 = t3 * 2;              // now = 4 * a2
     t2 = t2 * 2;              // now = 4 * a1
     Ones = Ones - t3 - t2;
     t3 = t3 + a2 + a2;        // now = 6 * a2
     Tens = Tens + t3;         // Tens done
     t1 = t1 + a4;             // now = 5 * a4
     Hund = Hund + t1;
     t3 = 4 * a3;
     Thou = t1 + t3 - 144;     // Thou done
     Ones = Ones - t3;         // Ones done
     TenK = t1 + a4 + 16;      // Tenk done

     // "normalize" the digits - this asm code was
     // copied directly from the original
#asm
       movlw   0x0A  
     Lb1:
       addwf   Ones,f
       decf    Tens,f
       btfss   3,0
       goto   Lb1
     Lb2:
       addwf   Tens,f
       decf    Hund,f
       btfss   3,0
       goto   Lb2
     Lb3:
       addwf   Hund,f
       decf    Thou,f
       btfss   3,0
       goto   Lb3
     Lb4:
       addwf   Thou,f
       decf    TenK,f
       btfss   3,0
       goto   Lb4
#endasm
}
anhalt@zoominternet.net
I tweaked Mike Mansheim's algorithm a little and would like to offer this code:
PICLIST Submission
17BIN2BCD
;February 6, 2018
;John Anhalt
;41 Tcy to Normalize
;Enhanced mid-range PIC16F1829
;"#" marks final polynomial for each BCD

     cblock    0x20
     binU
     binH
     binL
     ones 
     tens
     hund
     thou
     tenK
     endc

	org 0x0000
     nop
     bra  Start
Start

DoA2 
     movf      binH,w    
     andlw     0x0F      ;w=a2
     movwf     ones      ;ones=a2
     movwf     tens      ;tens=a2
     lslf      WREG      ;w=2a2
     addlw     0xC7      ;-57
     movwf     hund      ;hund=2a2-57
     addlw     0xF9      ;-7 -57= -64
     addwf     tens,f    ;tens=3a2-64
DoA4
     movf      binU,w
     addwf     ones,f    ;ones=a4+a2
     addwf     hund,f    ;hund=a4+2a2-57
     movwf     thou      ;thou=a4
     lslf      WREG      ;w=2a4
     movwf     tenK      ;tenK=2a4
     addwf     tens,f    ;tens=2a4+3a2-64
     lslf      WREG      ;w=4a4
     addwf     hund,f    ;hund=5a4+2a2-57
     addwf     thou,f    ;thou=5a4
     addlw     8         ;w=4a4+8
     addwf     tenK,f    ;tenK=6a4+8 #
DoA3
     swapf     binH,w
     andlw     0x0F      ;w=a3
     addwf     ones,f    ;ones=a4+a3+a2
     addwf     hund,f    ;hund=5a4+a3+2a2-57 #
     lslf      WREG      ;w=2a3
     lslf      WREG      ;w=4a3
     addlw     0xB7      ;-73
     addwf     thou,f    ;thou=5a4+4a3-73 #
DoA1                     ;same as Payson/Dattalo, binL preserved
     swapf     binL,w
     andlw     0x0F      ;w=a1
     addwf     tens,f    ;tens=2a4+3a2+a1-64
     addlw     4         ;see: Payson/Dattalo explanation
     addwf     ones      ;ones=a4+a3+a2+a1+4
     lslf      tens,f    ;tens=4a4+6a2+2a1-128,C is set #
     rlf       ones,f    ;moves C into ones
     comf      ones,f    
     rlf       ones,f    ;w/ carry ones is complement 2 negated
     movf      binL,w
     andlw     0x0F      ;w=a0
     addwf     ones,f    ;ones=a0-4(a4+a3+a2+a1)-20 #
Normalize
     movlw     0x0A
Lb1
     addwf     ones,f
     decf      tens,f
     btfss     STATUS,0
     bra       Lb1
Lb2
     addwf     tens,f
     decf      hund,f
     btfss     STATUS,0
     bra       Lb2
Lb3
     addwf     hund,f
     decf      thou,f
     btfss     STATUS,0
     bra       Lb3
Lb4
     addwf     thou,f
     decf      tenK,f
     btfss     STATUS,0
     bra       Lb4
     bra       Done
Done
    
Explanation (Based on Mike Mansheim)

Consider a 17-bit binary (N)= a4(2^16) +a3(2^12) + a2(2^8) + a1(2^4) +a0(2^0) where a_i is a 4-bit nibble.

A set of polynomials can be derived where b_i is the BCD digit:

b0(ones) = a0-4(a4+a3+a2+a1)
b1 (tens) = 4a4+6s2+2a1
b2(hund) = 5a4+a3+2a2
b3(thou) = 5a4+4a3
b4(tenK) = 6a4

Now include adjustment to ensure each equation, except tenK, is negative:

b0(ones) = a0-4(a4+a3+a2+a1)-20
b1 (tens) = 4a4+6s2+2a1-128
b2(hund) = 5a4+a3+2a2-57
b3(thou) = 5a4+4a3-73
b4(tenK) = 6a4+8

The above polynomials are slightly different from those derived by Mansheim and result in code that runs a little faster. Since this set is for only 17 bits, the maximum value for a_4 was 1. John Anhalt