/* SYNOPSIS: SETR(register_name, bit, bit, ...) DESCRIPTION: register_name Any readable/writable AVR register bit Bit number (0..7) which you want to set or unset. If you want to set a bit, just put a bit number. Otherwise, if you want to UNSET the bit, put BITNOTed (ie. use ~ operator) bit number. See EXAMPLES below. You can specify bits numbers up to eight. EXAMPLES: To set bit: SETR(MCUCR, PUD); // set MCUCR one SETR(GIMSK, INT1, INT0); // set both INT1 INT0 one To unset bit: SETR(MCUCR, ~PUD); // set MCUCR zero SETR(GIMSK, ~INT1, ~INT0); // unset both INT1 INT0 You can mix these set/unset specifier at once: SETR(TCCR0B, CS02, ~CS01, CS00); // set CSO2:CS01:CS00 = 1:0:1 NOTE: This macro heavily expects gcc's optimization. Gcc 4.3 is known to work well with this. Other versions will or will not.*/#define SETR_BIT_(n) \ if(bits[n] != 100) { \ if(bits[n] < 0) \ and_bits += 1<<(~bits[n]); \ else \ or_bits += 1<<(bits[n]); \ }#define SETR(REG, ...) \ do { \ static const int bits[]= \ { __VA_ARGS__, \ 100, 100, 100, 100, \ 100, 100, 100, 100 }; \ int and_bits = 0, or_bits = 0; \ uchar p; \ SETR_BIT_(0) \ SETR_BIT_(1) \ SETR_BIT_(2) \ SETR_BIT_(3) \ SETR_BIT_(4) \ SETR_BIT_(5) \ SETR_BIT_(6) \ SETR_BIT_(7) \ and_bits = ~and_bits; \ if(or_bits == 0xff) { \ (REG) = 0xff; \ } else if(and_bits == 0x00) { \ (REG) = 0x00; \ } else { \ p = (REG); \ if(and_bits != 0x00) p &= and_bits; \ if(or_bits != 0x00) p |= or_bits; \ (REG) = p; \ } \ } while(0)