user1806687
user1806687

Reputation: 920

Multiple parameters in macro

I am trying to simplify writing my embedded programs in C. How would I create a macro that could accept any number or parameters up from 2?

I currently have this:

#define P_PIN_HIGH(pin_letter, pin_num)         (PORT##pin_letter |= (1 << pin_num))
#define PIN_HIGH(...)           P_PIN_HIGH(__VA_ARGS__)

And I can use this like so:

#define PIN_TEST    A, 0    // Every pin gets defined this way.

PIN_HIGH(PIN_TEST);         // Set this pin to high.

But, I would like to be able to pass any number of pins(they must have the same letter) to the macro, like so:

#define PIN_TEST     A, 0
#define PIN_TEST1    A, 1
#define PIN_TEST2    A, 2

PIN_HIGH(PIN_TEST, PIN_TEST1, PIN_TEST2);

So, the compiled code, would look like this:

PORTA |= ((1<<0) | (1<<1) | (1<<2));

Is this doable?

Upvotes: 0

Views: 400

Answers (2)

programmerjake
programmerjake

Reputation: 1824

not really. If you can use c++ then it's very easy with templates.

template <volatile char *port_, size_t bit_number_>
struct port_descriptor
{
    static constexpr size_t bit_number = bit_number_;
    static volatile char *const port;
};
template <volatile char *port_, size_t bit_number_>
volatile char *const port_descriptor<port_, bit_number_>::port = port_;

typedef port_descriptor<&PORTA, 0> PIN_TEST;

template <class ...args>
char get_set_port_value(bool new_value);

template <class ...args>
void set_port_value(bool new_value);

template <volatile char *port_, size_t bit_number_>
char get_set_port_value<port_descriptor<port_, bit_number_>>(bool new_value)
{
    char v = *port_;
    if(new_value)
        return v | 1 << bit_number_;
    return v & ~(1 << bit_number_);
}

template <volatile char *port_, size_t bit_number_, class ...Args>
char get_set_port_value<port_descriptor<port_, bit_number_>, Args...>(bool new_value)
{
    char v = get_set_port_value<Args...>();
    if(new_value)
        return v | 1 << bit_number_;
    return v & ~(1 << bit_number_);
}

template <volatile char *port_, size_t bit_number_, class ...Args>
void set_port_value<port_descriptor<port_, bit_number_>, Args...>(bool new_value)
{
    char v = get_set_port_value<port_descriptor<port_, bit_number_>, Args...>(new_value);
    *port_ = v;
}

then you can do set_port_value<PIN_TEST>(true);

Upvotes: 1

shikamaru
shikamaru

Reputation: 54

Your P_PIN_HIGH() macro seems to take only two arguments. In your variadic macro PIN_HIGH, you are passing 3 argument pairs which, as per that macro's definition, would be passed as arguments to P_PIN_HIGH (which expects only 2 arguments). Seems like you would want to iterate over your argument pairs, in your P_PIN_HIGH() macro, by explicitly passing the number of argument pairs.

Upvotes: 0

Related Questions