Is this OK to do?

I find myself using a lot of global flags. Is there anything wrong with what I'm doing here? Later methods like the one that actually polls the button use SETF and CLRF to set and clear the flags and the defined macros allow checking just by saying for instance if(BUTTON_PRESSED) ...

It works, but I'm always afraid that there are pitfalls I can't see.

/***********     FLAGS  ***********/
#define SETF(_flag) (PROGRAM_FLAGS |= (_flag))
#define CLRF(_flag) (PROGRAM_FLAGS &= ~(_flag))
#define CHKF(_flag) (PROGRAM_FLAGS & (_flag))



volatile byte PROGRAM_FLAGS;

// Set if button enabled
#define BUTTON_FLAG 0x01
#define BUTTON_ON CHKF(BUTTON_FLAG)

// Not Debouned Set when button is made low (contact made)
#define BUTTONMADE_FLAG 0x02
#define BUTTON_MADE CHKF(BUTTONMADE_FLAG)

// Requires a debounced press and release to set
#define BUTTONPRESS_FLAG 0x04
#define BUTTON_PRESSED CHKF(BUTTONPRESS_FLAG)

// Set if Encoder Enabled
#define ENCODER_FLAG 0x08
#define ENCODER_ON CHKF(ENCODER_FLAG)

// Set if PWM enabled
#define PWM_FLAG 0x10
#define PWM_ENABLED CHKF(PWM_FLAG)
volatile byte PROGRAM_FLAGS;

As a matter of style, variables should not be all upper-case. That is reserved for constants.


I personally don't particularly like the use of #define to that extent. To test one flag you are nesting two defines, eg.

#define CHKF(_flag) (PROGRAM_FLAGS & (_flag))
...
#define BUTTON_MADE CHKF(BUTTONMADE_FLAG)

It may work, but it is rather obscure.

I think I would rather use functions, and hope that the compiler inlines them for you.

I think I would rather use functions, and hope that the compiler inlines them for you.

I’d make only a few changes to this statement:
I know I would rather use functions, and not care that the compiler inlines them for you.

Being able to read the code, and understand what it is doing without remembering just exactly what the #defines are doing is a huge plus, in my book.

Considering just your example of “if(BUTTON_PRESSED)”, what are you going to do when you add a second switch? If you assign meaningful names to functions and to variables containing pin numbers, “if(isPressed(resetPin))” is nearly as short as your example, but has the advantages that no #defines need to be understood AND can deal with any number of switched AND it is clear exactly which switch is being tested.

Another advantage is that no global variables are needed in the definition or use of this function, although pin number variables generally are globals. They don’t need to be, though.