0

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?

5
  • Do you mean "number of paramaters" >= 2? In this case it's possible. The syntax is: #define MACRO(A, B, ...) and then inside the macro the part corresponding to ... is obtained, again, with __VA_ARGS__. Commented Sep 5, 2014 at 16:26
  • possible duplicate of Variable arguements in macro using ellipsis Commented Sep 5, 2014 at 16:29
  • No, not a duplicate. By bigger >= 2, I just meant that at least one pin has to be passed to macro. Commented Sep 5, 2014 at 16:31
  • Oh, sorry, then use: #define MACRO(PIN1, __VA_ARGS__). Commented Sep 5, 2014 at 16:33
  • I am sorry, I dont get it... Commented Sep 5, 2014 at 16:36

2 Answers 2

1

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);

Sign up to request clarification or add additional context in comments.

6 Comments

No, its a program for a microcontroller.
which microcontroller?
8-bit AVR, it would be an overkill to use C++.
I have always used avr-g++ and arduino is actually C++.
I am not using arduino. I am programming "raw AVR".
|
0

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.

1 Comment

Yes, that's right, I would want to iterate. How would I accomplish that?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.