News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

Main Menu

SFR middle bits aliases ?

Started by trastikata, Feb 06, 2023, 06:41 PM

Previous topic - Next topic

trastikata

Hello all,

currently I set the SFRs using full byte/word binary formatted i.e.: 

T0CON = %00000111
or I address the individual bits aliasing them i.e.

Symbol PEIE = INTCON.6
PEIE = 1

However it's not very practical modifying SFR's middle bits written in binary format, especially 16-bit devices.

Thus here's my question - how to alias and address multiple middle bits in SFRs? For example bits 5-4-3-2 in ADCON0 control channel select and I'd like to call the entirety of those bits ADCON0_CS. Then to set that alias ADCON0_CS to 1011 for example?

Thank you

 

Yasin

Hi. You must have examined the timer macros in the examples.
"OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_EXT & T0_PS_1_32)"
Considering this example, "T0_PS_1_32" seems to be the closest usage type to your request. Do you want "T0_PS = 32" and if so it won't be possible without the necessary rotate.

I apologize in advance for the poor English expression.

Best regards.

keytapper

#2
Quote from: trastikata on Feb 06, 2023, 06:41 PMhow to alias and address multiple middle bits in SFRs?
That is possible to use Symbols and try to OR bits with the interested byte.
Symbol ADCON0_ADON 1
Symbol CHS0 = 2
Symbol CHS1 = 3
Symbol CHS2 = 4
Symbol CHS3 = 5
Symbol CHS4 = 6
Symbol ADCON_FVR_MASK (1 << CHS0) | (1 << CHS1) | (1 << CHS2) | (1 << CHS3) | (1 << CHS4)
Symbol ADCON0_DAC_ON (1 << CHS1) |(1 << CHS2) |(1 << CHS3) |(1 << CHS4)
Symbol ADCON0_TEMP_OUT (1 << CHS0) | (1 << CHS2) |(1 << CHS3) |(1 << CHS4)
Symbol ADCON0_AN3_ON (1 << CHS0) | (1 << CHS1)
Symbol ADCON0_AN2_ON (1 << CHS1)
Symbol ADCON0_AN1_ON (1 << CHS0)
Symbol ADCON0_AN0_ON 0
ADCONMASK ADCON0_AN0_ON | ADCON0_ADO ' An user selection
ADCON0 = ADCON0 | ADCONMASK      ' a fast setting with one single cycle
I presume this will imply a bit of work with the preprocessor and gives the user's own definitions.
Ignorance comes with a cost

Dompie

I don't know if this is a solution, but the .def file of the PIC contains all the bit names and you could use those. I always use those names.
; ADCON0 Bits
ADCON0bits_ADON
ADCON0bits_GO_NOT_DONE
ADCON0bits_GO_DONE
ADCON0bits_DONE
ADCON0bits_NOT_DONE
ADCON0bits_CHS0
ADCON0bits_CHS1
ADCON0bits_CHS2
ADCON0bits_CHS3
ADCON0bits_CHS4
In the past I read in the SFR, cleared the relevant bits with an AND and put my value in with an OR. I found this method inconvenient hence my use of the bit names.

Johan

Stephen Moss

If none of the other methods work you could try something like...

ADCON0_CS = %1011  'Might have to use %0001011 if 1011 not placed in LSB's
Set_ADC_Channels()   'Call Subroutine to SET ADC Channels

Sub Set_ADC_Channels
For x = 0 to 3

If ADCON0_CS.0 = 0 then
  Clearbit ADCON0,(x + Offset)  'Where Offset is the value of LSB bit of the group to be set (bits in the group must be consecutive) so for ADCON0 bits 4, 5, 6 & 7 offset would be 4 
Else
  Setbit ADCON0,(x + Offset)    'Where Offset is the value of LSB bit of the group to be set (bits in the group must be consecutive)
EndIF

ADCON0_CS >> 1    'Move next channel set bit to bit 0 of ADCON0_CS for testing
Next
EndSub

trastikata

Thank you all for the responses.

What you suggest is pretty much what I currently do. I should have been more thorough with my question...

I was actually hoping that there might be a more direct way embedded in the compiler, which I don't know of, to alias and simultaneously address several bits in a SFR/Variable.

keytapper

@Stephen Moss
I learnt to program in a tight space, procedures need space. I would rather call in the preprocessor to make the good work, since it would be a constant to be set. Unless there's a dynamic usage, for such extent the SetBit and ClearBit are one option. But it needs to be repeated for the number of bits that are involved.

@Dompie
Lately I discovered this naming, but I still accustomed by the old stile to put a long list of Symbol on the file header.
Ignorance comes with a cost

top204

#7
Altering multiple bits within a variable or SFR requires both Anding and Oring with a mask, and sometimes rotates to move the value into the correct position within the assignment variable or SFR. So it is very clumsy and time consuming.

For example, the relevant bits within the assignment SFR are Anded with the mask so they are cleared. Then the value to place into the bits is rotated x amount of times so it matches the bit positions. Then they are Ored into the assignment SFR to set the relevant bits and keep the bits not required, cleared.

It can be accomplished with a pre-processor meta-macro so it looks good in the program's listing, but the underlying code is rather messy and it is sometimes easier and smaller to set/clear the relevant bits individually, or make a mask of the bits in their correct places and And/Or that into the variable or SFR.

Or sometimes, multiple $if statements can choose what bits to set or clear for a specific value. For example:

'-------------------------------------------------------------
' Alter the bits for a required Timer1 Prescaler on a PIC18F26K40 device
'
$define Timer1_Prescaler(pPrescaler)'
    $if pPrescaler = 1              '
        T1CONbits_CKPS0 = 0         '
        T1CONbits_CKPS1 = 0         '
    $elseif pPrescaler = 2          '
        T1CONbits_CKPS0 = 1         '
        T1CONbits_CKPS1 = 0         '
    $elseif pPrescaler = 4          '
        T1CONbits_CKPS0 = 0         '
        T1CONbits_CKPS1 = 1         '
    $elseif pPrescaler = 8          '
        T1CONbits_CKPS0 = 1         '
        T1CONbits_CKPS1 = 1         '
    $else                           '
        $error "Unknown Timer1 prescaler value. Supported values for this device are 1 or 2 or 4 or 8" '
    $endif

It looks messy in the code listing, but produces nice clean code, so it is better to place meta-macros inside .inc files, so they are out of the way of the main code listing and make it easier to scan and read.

The above will operate with the line of code:

Timer1_Prescaler(2)