PIC Microcontoller Bit Math Method

Setting bit number X

Tracy Smith says

Here are a couple of ideas for getting 1<<TestBit
10 cycles:

2^n:
    clrw
    btfsc    TestBit,2
     movlw   b'11111100'
    addwf    TestBit,f

    incf     TestBit,w
    btfsc    TestBit,1
     iorwf   TestBit,f

    incf     TestBit,f

    skpnc
     swapf   TestBit,f

.........
another way (7 cycles [including the call])

two_to_n:
    andlw    7
    addwf    pcl,f
    retlw    1
    retlw    2
    retlw    4
    retlw    8
    retlw    0x10
    retlw    0x20
    retlw    0x40
    retlw    0x80


............
or probably more to the point

    movf     portb,w
    movwf    portb_shadow

    btfss    TestBit,2
     swapf   portb_swadow,f


    btfss    TestBit,0
     rlf     portb_shadow,f

    movlw    b'10000000'
    btfss    TestBit,1
     movlw   b'00100000'

    andwf    portb_shadow,f

    skpnz
     goto    _the_bit_is_set

.lo

Kevin Blain says:

clrf    mask    ; empty the mask

; a file called bit contains the 0 to 7 value of the bit position

incf    bit    ; make it 1 to 8, so decfsz works nicely
bsf    STATUS, C    ; set the carry flag. This will be rotated in 'bit' times

loop:
rlf    mask, f
decfsz    bit, f    ; skip out after 'bit' times.
goto    loop
.....               ; rest of code...

Of course, it would be good to ensure that bit is not greater than 7 when
entering the routine.

Scott Dattalo says

set_bit:

  ;Get a pointer to the byte containing the bit we want:

    rrf   bit_position,w
    movwf fsr

    rrf   fsr,f
    rrf   fsr,w
    andlw BIT_ARRAY_MASK
    addlw bit_array
    movwf fsr

  ; find 1<<(bit_position&7) [note, this could be made 2-cycles
  ;                           shorter]

    movlw  0101b
    btfsc  bit_position,0
     movlw 1010b

    movwf  mask

    movlw  0011b
    btfsc  bit_position,1
     movlw 1100b

    andwf  mask,f

    btfsc  bit_position,2
     swapf mask,f

  ; now set or clear the bit

    movf   mask,w
    iorwf  indf,f         ; Assume we're setting.
    btfss  new_state,0
     xorwf indf,w         ; assumption was wrong


Dmitry says:

;Probably it would be better to pre allocate bit position value in cell
;shifted by one bit to left, like xxxx.yyyz where xxxx is byte offset
;and yyy bit offset. It let us write more tight code for this case.

set_bit:
        swapf   bit_position,W
        andlw   0x0F
        addlw   bit_array
        movwf   FSR


        movlw   1
        btfsc   bit_position,2  ;y.1
        movlw   4
        movwf   mask

        btfsc   bit_position,1  ;y.0
        addwf   mask,F

        btfsc   bit_position,3  ;y.2
        swapf   mask,F

        movfw   mask
        iorwf   INDF,F
        btfss   bit_position,0  ;we can use z for this why not?
        xorwf   INDF,F

Bob Ammerman says:

To turn on bit "BitNum" of port "PortNum":

    movf       PortNum,W
    movwf    FSR

    movf       BitNum,W
    call         BitToMask
    iorwf       INDF,F

To turn off bit "BitNum" of port "PortNum":

    movf       PortNum,W
    movwf    FSR

    movf       BitNum,W
    call          BitToMask
    xorlw       0xFF
    andwf      INDF,F

; To test bit "BitNum" or port "PortNum"

    movf    PortNum,W
    movwf FSR
    movf    BitNum,W
    call       BitToMask
    andwf  INDF,W

; At this point Z is set if PortNum,BitNum was clear
;  Z is clear if PortNum,BitNum was set

BitToMask:
    addwf    pcl
    retlw    1
    retlw    2
    retlw    4
    retlw    8
    retlw    16
    retlw    32
    retlw    64
    retlw    128

See Also:

Code: