Multi-bit manipulation in a variable or SFR using the preprocessor's meta-macros

Started by top204, Apr 06, 2023, 01:36 PM

Previous topic - Next topic

top204

I do use masking mechanisms sometimes for multi-bit manipulation, by my personal preference for altering multiple bits within a variable or SFR is to use a pre-processor meta-macro and its comparisons to do the task, because they are easier to create and can be copied and pasted and used multiple times for different bits and SFRs with such small changes made to them. For example:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Demonstrate a preprocessor meta-macro mechanism to alter more than one bit within a variable or SFR
'
' Written for the Positron8 compiler by Les Johnson.
'
    Device = 18F25K20                               ' Tell the compiler what device to compile for
    Declare Xtal = 16                               ' Tell the compiler what frequency the device will be operating at (in MHz)
'
' Setup USART1
'
    Declare Hserial1_Baud = 9600                    ' Set the Baud rate to 9600
    Declare HRSOut1_Pin = PORTC.6                   ' Set the TX pin

    Dim MySFR1 As Byte                              ' Create a variable to be be altered bit-wise
       
'-------------------------------------------------------------------------
' Use bit manipulation to alter more than one bit within a variable or SFR
' Input     : pValue holds the constant value to place into the bits
' Output    : MySFR1 will have its bits 0 and 1 changed
' Notes     : None
'
$define MySFR1_LoadBits01(pValue) '
    $if pValue = 0                '
        MySFR1.0 = 0              '
        MySFR1.1 = 0              '
    $elseif pValue = 1            '
        MySFR1.0 = 1              '
        MySFR1.1 = 0              '
    $elseif pValue= 2             '
        MySFR1.0 = 0              '
        MySFR1.1 = 1              '
    $elseif pValue= 3             '
        MySFR1.0 = 1              '
        MySFR1.1 = 1              '
    $else                         '
        $error "MySFR1_LoadBits01 can only handle a constant value from 0 to 3" '
    $endif
   
'-------------------------------------------------------------------------
' Use bit manipulation to alter more than one bit within a variable or SFR
' Input     : pValue holds the constant value to place into the bits
' Output    : MySFR1 will have its bits 2, 3, and 4 changed
' Notes     : None
'
$define MySFR1_LoadBits234(pValue) '
    $if pValue = 0                 '
        MySFR1.2 = 0               '
        MySFR1.3 = 0               '
        MySFR1.4 = 0               '
    $elseif pValue = 1             '
        MySFR1.2 = 1               '
        MySFR1.3 = 0               '
        MySFR1.4 = 0               '
    $elseif pValue= 2              '
        MySFR1.2 = 0               '
        MySFR1.3 = 1               '
        MySFR1.4 = 0               '
    $elseif pValue= 3              '
        MySFR1.2 = 1               '
        MySFR1.3 = 1               '
        MySFR1.4 = 0               '
    $elseif pValue= 4              '
        MySFR1.2 = 0               '
        MySFR1.3 = 0               '
        MySFR1.4 = 1               '
    $elseif pValue= 5              '
        MySFR1.2 = 1               '
        MySFR1.3 = 0               '
        MySFR1.4 = 1               '
    $elseif pValue= 6              '
        MySFR1.2 = 0               '
        MySFR1.3 = 1               '
        MySFR1.4 = 1               '
    $elseif pValue= 7              '
        MySFR1.2 = 1               '
        MySFR1.3 = 1               '
        MySFR1.4 = 1               '
    $else                          '
        $error "MySFR1_LoadBits234 can only handle a constant value from 0 to 7" '
    $endif         
          
'-------------------------------------------------------------------------
' The main program starts here
'
Main:
    MySFR1 = %10000000                          ' Load MySFR1 with a value, to make sure it remains in place
    HRSOutLn "Raw    : ", Bin8 MySFR1           ' Transmit its binary value to a serial terminal
   
    MySFR1_LoadBits01(2)                        ' Alter bits 0 and 1 of MySFR1 only
    HRSOutLn "Mask01 : ", Bin8 MySFR1           ' Transmit its binary value to a serial terminal
   
    MySFR1_LoadBits234(5)                       ' Alter bits 2, 3, and 4 of MySFR1 only   
    HRSOutLn "Mask234: ", Bin8 MySFR1           ' Transmit its binary value to a serial terminal

I know the meta-macros look large and bulky in the program's listing, but the above program's operation is quite efficient and very easy to alter for other SFRs and bits within an SFR, and when the meta-macros are placed in an Include file, they do not bulk up the main program's listing at all.

For example, the MySFR1_LoadBits01 meta-macro will produce the assembler code:

bcf MySFR1,0,0
bsf MySFR1,1,0


And the MySFR1_LoadBits234 meta-macro will produce the assembler code:

bsf MySFR1,2,0
bcf MySFR1,3,0
bsf MySFR1,4,0


Not forgetting if the SFR or variable is in a banked RAM area, the above meta-macro machanisms will alter the RAM bank once only and remember it when altering the other bits of the variable or SFR, instead of the multiple RAM bank changes that may be required when masking. Even when using the WREG SFR as a temporary workspace on some of the newer devices!

And if an incorrect constant value is passed to them, they will produce an error message.