avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] efficiency of assigning bits


From: David Brown
Subject: Re: [avr-gcc-list] efficiency of assigning bits
Date: Mon, 21 Mar 2005 08:16:03 +0100

>
> I know the preprocessor is somewhat out of style these days, but consider
> the scheme I use:
>
> // Helper macros common to all projects
> //
> #define BIT(p,b)                (b)
>
> #define PORT(p,b)               (PORT ## p)
> #define PIN(p,b)                (PIN ## p)
> #define DDR(p,b)                (DDR ## p)
>
> #define MASK(b)                 (1 << (b))
>
> #define Set_Port_Bit(p,b)       ((p) |= MASK(b))
> #define Clr_Port_Bit(p,b)       ((p) &= ~MASK(b))
> #define Tgl_Port_Bit(p,b)       ((p) ^= MASK(b))
>
> #define Get_Port_Bit(p,b)       (((p) & MASK(b)) != 0)
>
> #define Set_Output(io)          Set_Port_Bit(PORT(io),BIT(io))
> #define Reset_Output(io)        Clr_Port_Bit(PORT(io),BIT(io))
> #define Toggle_Output(io)       Tgl_Port_Bit(PORT(io),BIT(io))
> #define Get_Output(io)          Get_Port_Bit(PORT(io),BIT(io))
>
> #define Get_Input(io)           Get_Port_Bit(PIN(io),BIT(io))
>
> #define Tristate(io)            Clr_Port_Bit(DDR(io),BIT(io))
> #define Drive(io)               Set_Port_Bit(DDR(io),BIT(io))
>
> // LED example
> // These macros (except IO_LED) are the ones to appear in in functions
> //
> #define IO_LED        A,3                 // Port letter and bit number
> #define Led_On()   Reset_Output(IO_LED)   // inverted logic, just for fun
> #define Led_Off()   Set_Output(IO_LED)
> #define Is_Led_On() (!Get_Output(IO_LED))
> #define Enable_Led() Drive(IO_LED)
> #define Disable_Led() Tristate(IO_LED)  // I don't know why, just examples
>
> Note that the seperate Get_Input and Get_Output macros prevent one from
> inadvertently trying to read the output latch instead of the pin state.
>
> Note also the *_Port_Bit macros can be used for other kinds of ports,
e.g.,
>
>    Set_Port_Bit(ADCSRA, ADEN);  // Enable ADC converter
>
>
> Regards,
>    -=Dave
>

<aol> Me too! </aol>

Tying the port along with the bit number is a huge step up from just
defining a name for a bit number.

I use a similar setup, although I seldom go as far as to make a set of
macros for each individual output (Led_On(), etc.).  I'm quite happy to
write Reset_Output(IO_LED) in my main code.  The macros I use are a bit more
complex in the pre-processor "junk", but just as simple in use.  The also
work happily (and efficiently) for bits in a variable (even local
variables), making them good for flags.  Different compilers and different
architectures need variations in the pre-processor macros, but I have the
same user-level macros for around half a dozen C compilers, and as many
assemblers.

And for those that use simpler setups (they are still useful), why this
obsession with using bit numbers rather than masks?  Rather than writing
    #define STATUS_LED 3
    PORTA |= _BV(STATUS_LED);
or
    PORTA |= (1 << STATUS_LED);

just write
    #define STATUS_LED (1 << 3)
    PORTA |= STATUS_LED;

Macros (and constants, and inline functions) are there to improve
readability, and save repetative typing.  Since it's the mask you use, not
the bit number, put the mask in the definition.






reply via email to

[Prev in Thread] Current Thread [Next in Thread]