PIC Microcontoller Bit Math Method

Copy unaligned bits from one register to another:

With possibility of "jitter" on destination pin

	bsf     PORTA,4
	btfss   STATUS,C
	bcf     PORTA,4

ie: Assume the bit is one, then change to 0 if it is not. A C/C++ macro for Hitech C is available

Saves 1 instruction over the more standard:

With possibility of error due to change in value on source pin

        btfsc   STATUS,C        ; load the data
        bsf     PORTA,4
        btfss   STATUS,C
        bcf     PORTA,4

This macro...

COPY_BIT     MACRO   var_A,bit_N,var_B,bit_M
        NOEXPAND
         btfsc   var_A,bit_N
         bsf     var_B,bit_M
         btfss   var_A,bit_N
         bcf     var_B,bit_M
        ENDM

remember to define the dummy macro variables:
var_A   equ     0
bit_N   equ     0

...will produce the same output if called like this:

COPY_BIT STATUS,C,PORTA,4

but can be used on any current bank registers.

Question:

I have a register that holds a 3 bit number <0:2>. How do I put the value of those three bit on PORTC <7:5> without changing the rest of the bits on PORTC?
Andrew Warren answers
If you had stored the 3 bits in SOURCE bits 5-7 instead of bits 0-2, you'd have been able to do it in 4 lines:
    MOVF    SOURCE,W   ;W = SOURCE.
    XORWF   PORTC,W    ;Copy W bits 5-7 to PORTC bits 5-7.  This
    ANDLW   11100000B  ;code only works if the upper three bits
    XORWF   PORTC      ;of PORTC are guaranteed not to change
                       ;between the two XORs.
Since the data's stored in bits 0-2, though, you have to do a little more... If you have an extra register to spare, you can do it in 6 lines:
    SWAPF   SOURCE,W   ;Copy SOURCE bits 0-2 to W bits 5-7.
    MOVWF   TEMP       ;
    RLF     TEMP,W     ;

    XORWF   PORTC,W    ;Copy W bits 5-7 to PORTC bits 5-7.  This
    ANDLW   11100000B  ;code only works if the upper three bits
    XORWF   PORTC      ;of PORTC are guaranteed not to change
                       ;between the two XORs.
Without a TEMP register, you can do it in 8 lines. Unfortunately, this code glitches PORTC bits 5-7 low, and it switches the pins one at a time:
    MOVLW   00011111B  ;Clear the upper 3 bits of PORTC.
    ANDWF   PORTC      ;

    BTFSC   SOURCE,2   ;Copy SOURCE bits 0-2 to PORTC bits 5-7.
    BSF     PORTC,7    ;
    BTFSC   SOURCE,1   ;
    BSF     PORTC,6    ;
    BTFSC   SOURCE,0   ;
    BSF     PORTC,5    ;
The shortest way (9 cycles/instructions) that glitchlessly switches all three PORTC pins simultaneously without using any additional registers:
    BTFSC   SOURCE,2   ;Copy SOURCE bits 0-2 to W bits 5-7.
    ADDLW   10000000B  ;
    BTFSC   SOURCE,1   ;
    ADDLW   01000000B  ;
    BTFSC   SOURCE,0   ;
    ADDLW   00100000B  ;

    XORWF   PORTC,W    ;Copy W bits 5-7 to PORTC bits 5-7.  This
    ANDLW   11100000B  ;code only works if the upper three bits
    XORWF   PORTC      ;of PORTC are guaranteed not to change
                       ;between the two XORs.
Another way, also 9 cycles/instructions:
    MOVF    PORTC,W    ;W = PORTC.
    ANDLW   00011111B  ;Clear W bits 5-7.

    BTFSC   SOURCE,2   ;Copy SOURCE bits 0-2 to W bits 5-7.
    ADDLW   10000000B  ;
    BTFSC   SOURCE,1   ;
    ADDLW   01000000B  ;
    BTFSC   SOURCE,0   ;
    ADDLW   00100000B  ;

    MOVWF   PORTC      ;PORTC = W.

Archive: