Status DC bit

Discussion in 'Programmer's Corner' started by Dodgydave, Jul 11, 2012.

  1. Dodgydave

    Thread Starter Distinguished Member

    Jun 22, 2012
    4,965
    743
    Can anyone explain how the dc bit operates in pic language, as thedatasheet is useless at explaining it.
     
  2. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    It tests if the register has changed from < 16 to >= 16, or vice versa. You could go your whole life without needing to use it, but occasionally it could save you a couple of cycles if you remember it.
     
  3. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    I've used it a few times. There's a very old PutHex routine that uses it to convert a byte value to two ASCII hexadecimal characters, "00" to "FF", for display. I've also used it for incrementing and/or decrementing packed BCD variables. Why would I use packed BCD variables, you might ask? Well, there are times when it's handy. For example, instead of performing (hours / 10) | '0' and (hours % 10) | '0' operations on a binary "hours" variable in order to print hours*10 and hours*1 characters to a display, you can use much less computationally intense (hours >> 4) | '0' and (hours & 15) | '0' operations on a packed BCD variable to produce the same display characters.

    Cheerful regards, Mike

    Code ( (Unknown Language)):
    1.    void putNyb()                //
    2.    { asm andlw  0x0F            // keep lower nibble
    3.      asm addlw  0x36            // 0-9 > 0x36-0x3F, A-F > 0x40-0x45
    4.      asm btfsc  _status,DC      // A..F?  no, skip, else
    5.      asm addlw  7               // A-F(0x40..0x45) > 'A'+6..'F'+6
    6.      asm addlw  -6              // '0'..'9' or 'A'..'F'
    7.      put232(wreg);              //
    8.    }                            //
    9.  
    10.    void putHex(char data)       //
    11.    { asm swapf  _data,W         //
    12.      putNyb();                  // send upper nibble '0'..'F'
    13.      asm movf   _data,W         //
    14.      putNyb();                  // send lower nibble '0'..'F'
    15.    }                            //
    16.  
     
    Last edited: Jul 12, 2012
  4. WBahn

    Moderator

    Mar 31, 2012
    17,715
    4,788
    The DC is "digit carry" and indicates that a the low order nibble as, as pointed out by Markd77, rolled across the FFFF <-> 0000 boundary.

    This is useful if you are doing "packed-BCD" computations.

    Consider storing a two-digit decimal number in a single byte using BCD. So your numbers can range from 00 to 99.

    Let's only talk about addition.

    Now, let's say that you want to add 34 and 17. When you are done, you want the byte to contain 51. But the binary add is going to put 4B in there. However, B is not a valid hex digit. Whenever your low digit exceeds 9, you need to adjust the byte by adding 6 in order to wrap the low digit to the right place and force a carry to the high digit. So you can test is see if the low nibble is greater than 9 and, if so, add six.

    But what about when you add something that results in a carry across the digit boundary even when the addition is done in binary? For instance, 39 + 18. The result of the binary addition will be 51 and checking for the low nibble exceeding 9 won't work because it exceeded 9 by enough to force the carry from the low digit. But we still need to add 6 to wrap the low digit up to the correct value. So to catch this case, we check the DC bit in the status register and, if set, add 6 to get 57, which is what we want.

    If we want multibyte BCD representations, then we do this same thing between bytes by adding 6 to the upper nibble (so 0x60) if either the upper nibble is greater than nine or the normal carry (C) flag is set. In either case, we need to add one to the next higher byte (since this does not happen automatically the way it does between nibbles in the same byte.
     
Loading...