Search code examples
cmacrosinlinepreprocessor-directivedummy-variable

How to insert a statement inbetween lines with the help of preprocessor directives in C++?


I'm trying to program an Arduino Due to PWM a LED matrix by turning the LEDs on and off very quickly. In order to control brightness I want to add extra instructions between the on and off states of the LEDs. The brightness should be set by a preprocessor variable. The Arduino has a 84MHz Cortex-M3 ARM processor.

This is a simplification of how my code currently increases the brightness:

uint8_t volatile dummy = 0;
uint8_t i;

for (i=0;i<1<<current_layer;i++) { // every next layer has double the amount of pulses
    LED_STATE = ON; // several pulses in one go speeds up the for loop
    dummy = 0; // increases ON-time
    LED_STATE = OFF;
    LED_STATE = ON;
    dummy = 0; 
    LED_STATE = OFF;
    LED_STATE = ON;
    dummy = 0; 
    LED_STATE = OFF;
    LED_STATE = ON;
    dummy = 0;
    LED_STATE = OFF;
}

Now I want to be able to increase the brightness based on a preprocessor variable like so:

#define BRIGHTNESS 2 
// inside loop
        LED_STATE = ON; // several pulses in one go speeds up the for loop
        #if BRIGHTNESS > 0
        dummy = 0; // increases ON-time
        #if BRIGHTNESS == 2
        dummy = 0; // increases ON-time even more
        #endif
        #endif
        LED_STATE = OFF;
        LED_STATE = ON;
        #if BRIGHTNESS > 0
        dummy = 0;
        #if BRIGHTNESS == 2
        dummy = 0;
        #endif
        #endif
        LED_STATE = OFF;
        LED_STATE = ON;
        #if BRIGHTNESS > 0
        dummy = 0;
        #if BRIGHTNESS == 2
        dummy = 0;
        #endif
        #endif
        LED_STATE = OFF;
        LED_STATE = ON;
        #if BRIGHTNESS > 0
        dummy = 0;
        #if BRIGHTNESS == 2
        dummy = 0;
        #endif
        #endif
        LED_STATE = OFF;

As you can see, this makes the code very unreadable. I would like to define a preprocessor macro that adds these dummy statements based on the value of BRIGHTNESS.

This is how the code should look like:

#define BRIGHTNESS 2 
#define B1 ... // adds dummy=0; when BRIGHTNESS > 0 or else nothing at all
#define B2 ...
#define B3 ...
#define B4 ...
// inside loop
        LED_STATE = ON;
        B1 B2 B3 B4 // adds a number of dummy statements based on the value of BRIGHTNESS
        LED_STATE = OFF;
        LED_STATE = ON;
        B1 B2 B3 B4
        LED_STATE = OFF;
        LED_STATE = ON;
        B1 B2 B3 B4
        LED_STATE = OFF;
        LED_STATE = ON;
        B1 B2 B3 B4
        LED_STATE = OFF;

Even better would be a function that inserts those statements based on a variable:

#define ADD_DUMMIES ...
// inside loop
        LED_STATE = ON;
        ADD_DUMMIES(BRIGHNESS)
        LED_STATE = OFF;

How would I define preprocessor macros so that they insert dummy statements based on the value of BRIGHTNESS?


Solution

  • This is how the dummy = 0; statements can be added with the help of the preprocessor:

    #define BRIGHTNESS 2
    #define _GETFOO(n) _FOO ## n
    #define ADD_DUMMIES(n) _GETFOO(n) ()
    
    #define _FOO0()
    #define _FOO1() dummy = 0;
    #define _FOO2() dummy = 0; dummy = 0;
    #define _FOO3() dummy = 0; dummy = 0; dummy = 0;
    #define _FOO4() dummy = 0; dummy = 0; dummy = 0; dummy = 0;
    
    uint8_t volatile dummy = 0;
    // inside loop
            LED_STATE = ON;
            ADD_DUMMIES(BRIGHTNESS)
            LED_STATE = OFF;
            LED_STATE = ON;
            ADD_DUMMIES(BRIGHTNESS)
            LED_STATE = OFF;
            LED_STATE = ON;
            ADD_DUMMIES(BRIGHTNESS)
            LED_STATE = OFF;
            LED_STATE = ON;
            ADD_DUMMIES(BRIGHTNESS)
            LED_STATE = OFF;
    

    The compiler inserts the same store instruction as many times inbetween the lines as the value of BRIGHTNESS dictates, as long as it is within the boundaries.