I made myself a macro to avoid the expensive use of modulo for a 1-incrementing value. Unlike "var = (var+1)%MOD", which seem to be interrupt safe, this macro is not.
Actually I have two versions which execute in slightly different time but also have a slightly different effective program size depending on the location in the code. I don't quite understand it at the moment.
The two versions of the macro:
// fast except with volatile; often larger
#define plusOneModuloX(var, x) if (++(var)>=(x)) (var)=0;
// fast with volatile; often smaller
#define plusOneModuloX(var, x) (var) = ((var) >= (x)-1 ? 0 : (var)+1)
I would like to combine this macro with calls to cli() and sei() to make it interrupt-safe, only if one of the input variables are defined as volatile.
Is there a way to do this in the preprocessor?
(I know there's generally not much point in shaving off two cycles or four program bytes like this.)
The two options I currently have are to either make sure to manually supply calls to cli() and sei() for interrupt-sensitive sections, or to put these calls into the macro in general.
Approximate average execution speeds over 50000 calls using 16 MHz ATmega328 (e.g. ~0.0625 us per cycle). MODULO is a constant, var is uint8_t.
if (++var>=MODULO) var=0: 0.24 us per call // 4 cycles
cli(); if (++var>=MODULO) var=0; sei(): 0.37 us per call // 6 cycles
var = (var >= MODULO-1 ? 0 : var+1): 0.35 us per call
cli(); var = (var >= MODULO-1 ? 0 : var+1); sei(): 0.48 us per call
if (++var>=MODULO) var=0: 0.76 us per call // 12 cycles
cli(); if (++var>=MODULO) var=0; sei(): 0.88 us per call // 14 cycles
var = (var >= MODULO-1 ? 0 : var+1): 0.64 us per call
cli(); var = (var >= MODULO-1 ? 0 : var+1); sei(): 0.77 us per call