If I had a dollar for every time I've fixed someones code simply by moving the // comment in a #define to the line before.You wouldn't earn a single dollar.
I'm sorry but for years people have put in their code some register anded and ored to set certain bits with a numerical value. I put it behind a macro and now that number has to be a constant??? what the fuck are you all on about? jesus christ! you want me to either create a constant whoes name if generic will be erm... let me think.... the number it represents and if i do them specific I'll just be making multiple constants that have the same values....
Indeed, coding is a sodding religion!!!!!!!!!!!!!!!!!!
You have demonstrated numerous times that you don't yet fully understand some pretty fundamental concepts in C (e.g. integer promotion, const values etc.), so why do you feel qualified to criticise both the language and peoples advice on how to use it?
ORing a value with zero is pointless. Even though the optimiser should strip it out it adds nothing to the readability of your code and arguably detracts from it, so why do it?
// CNTMODE[2:0] Timer Mode Writing these bits selects the Timer mode
#define TCB0_TIMER_MODE_MASK 0b00000111
#define TCB0_SET_TIMER_MODE_PERIODIC_INTERRUPT TCB0.CTRLB = ((TCB0.CTRLB & (^TCB0_TIMER_MODE_MASK)) | 0b000)
#define TCB0_SET_TIMER_MODE_TIME_OUT_CHECK TCB0.CTRLB = ((TCB0.CTRLB & (^TCB0_TIMER_MODE_MASK)) | 0b001)
#define TCB0_SET_TIMER_MODE_EVENT TCB0.CTRLB = ((TCB0.CTRLB & (^TCB0_TIMER_MODE_MASK)) | 0b010)
#define TCB0_SET_TIMER_MODE_FREQ_MEASUREMENT TCB0.CTRLB = ((TCB0.CTRLB & (^TCB0_TIMER_MODE_MASK)) | 0b011)
#define TCB0_SET_TIMER_MODE_PW_MEASUREMENT TCB0.CTRLB = ((TCB0.CTRLB & (^TCB0_TIMER_MODE_MASK)) | 0b100)
#define TCB0_SET_TIMER_MODE_FREQ_PW_MEASUREMENT TCB0.CTRLB = ((TCB0.CTRLB & (^TCB0_TIMER_MODE_MASK)) | 0b101)
#define TCB0_SET_TIMER_MODE_SINGLE_SHOT TCB0.CTRLB = ((TCB0.CTRLB & (^TCB0_TIMER_MODE_MASK)) | 0b110)
#define TCB0_SET_TIMER_MODE_8BIT_PWM TCB0.CTRLB = ((TCB0.CTRLB & (^TCB0_TIMER_MODE_MASK)) | 0b111)
so why do you feel qualified to criticise both the language and peoples advice on how to use it?
I'm sorry but for years people have put in their code some register anded and ored to set certain bits with a numerical value. I put it behind a macro and now that number has to be a constant??? what the fuck are you all on about? jesus christ! you want me to either create a constant whoes name if generic will be erm... let me think.... the number it represents and if i do them specific I'll just be making multiple constants that have the same values....
Indeed, coding is a sodding religion!!!!!!!!!!!!!!!!!!
You have demonstrated numerous times that you don't yet fully understand some pretty fundamental concepts in C (e.g. integer promotion, const values etc.), so why do you feel qualified to criticise both the language and peoples advice on how to use it?
ORing a value with zero is pointless. Even though the optimiser should strip it out it adds nothing to the readability of your code and arguably detracts from it, so why do it?
You said you'd need to define 2^8 symbols for every register value but this isn't true for typical peripherals that use one or more bits per register to control specific functions. You define symbols for each function in the register and then OR them together. Usually these are already defined for you in a target specific header that comes with the compiler. This way someone reading your code can see what it's doing without having to decode "magic" numbers.
Also using binary notation is not a good idea, this is a specific GCC extension and not supported by many/most compilers. Use hex notation in these cases, it's very easy to mentally convert this to a binary sequence and is standard C.
#define TCB0_MODE(v) TCB0.CTRLB = ((TCB0.CTRLB & 0xf8) | (v))
#define TCB0_MODE_PERIODIC_INTERRUPT TCB0_MODE(0)
#define TCB0_MODE_TIME_OUT_CHECK TCB0_MODE(1)
#define TCB0_MODE(v) TCB0.CTRLB ^= (TCB0.CTRLB ^ (v)) & 0x07
#define TCB0_MODE_PERIODIC_INTERRUPT TCB0_MODE(0)
#define TCB0_MODE_TIME_OUT_CHECK TCB0_MODE(1)
I was not aware that binary was GCC specific.
I was not aware that binary was GCC specific.It's not. It was previously an extension to the language, supported early on by gcc and others, but became part of the C++14 standard.
If I had a dollar for every time I've fixed someones code simply by moving the // comment in a #define to the line before.
You wouldn't earn a single dollar.One of my rules for writing portable code is never put a comment on the same line as a #define. True, it won't bite you 99.9% of the time, but finding those 0.1% problems makes up for it!
Could you show a single example of how this can cause a problem?
/*
This code contibuted by Triffid_Hunter and modified by Kliment
why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
2012/3/10 AT90USB128x modified by lincomatic to match Teensyduino
*/
#ifndef _ARDUINO_H
#define _ARDUINO_H
#include <avr/io.h>
/*
utility functions
*/
#ifndef MASK
/// MASKING- returns \f$2^PIN\f$
#define MASK(PIN) (1 << PIN)
#endif
/*
magic I/O routines
now you can simply SET_OUTPUT(STEP); WRITE(STEP, 1); WRITE(STEP, 0);
*/
/// Read a pin
#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN)))
/// write to a pin
#define _WRITE(IO, v) do { if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }; } while (0)
/// toggle a pin
#define _TOGGLE(IO) do {DIO ## IO ## _RPORT = MASK(DIO ## IO ## _PIN); } while (0)
/// set pin as input
#define _SET_INPUT(IO) do {DIO ## IO ## _DDR &= ~MASK(DIO ## IO ## _PIN); } while (0)
/// set pin as output
#define _SET_OUTPUT(IO) do {DIO ## IO ## _DDR |= MASK(DIO ## IO ## _PIN); } while (0)
/// check if pin is an input
#define _GET_INPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) == 0)
/// check if pin is an output
#define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) != 0)
// why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
/// Read a pin wrapper
#define READ(IO) _READ(IO)
/// Write to a pin wrapper
#define WRITE(IO, v) _WRITE(IO, v)
#define PULLUP(IO,v) _WRITE(IO, v)
/// toggle a pin wrapper
#define TOGGLE(IO) _TOGGLE(IO)
/// set pin as input wrapper
#define SET_INPUT(IO) _SET_INPUT(IO)
/// set pin as output wrapper
#define SET_OUTPUT(IO) _SET_OUTPUT(IO)
/// check if pin is an input wrapper
#define GET_INPUT(IO) _GET_INPUT(IO)
/// check if pin is an output wrapper
#define GET_OUTPUT(IO) _GET_OUTPUT(IO)
/*
ports and functions
added as necessary or if I feel like it- not a comprehensive list!
*/
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__)
// UART
#define RXD DIO0
#define TXD DIO1
// SPI
#define SCK 13
#define MISO DIO12
#define MOSI DIO11
#define SS 10
// TWI (I2C)
#define SCL AIO5
#define SDA AIO4
// timers and PWM
#define OC0A DIO6
#define OC0B DIO5
#define OC1A DIO9
#define OC1B DIO10
#define OC2A DIO11
#define OC2B DIO3
#define DEBUG_LED AIO5
/*
pins
*/
#define DIO0_PIN PIND0
#define DIO0_RPORT PIND
#define DIO0_WPORT PORTD
#define DIO0_DDR DDRD
#define DIO0_PWM NULL
#define DIO1_PIN PIND1
#define DIO1_RPORT PIND
#define DIO1_WPORT PORTD
#define DIO1_DDR DDRD
#define DIO1_PWM NULL
#define DIO2_PIN PIND2
#define DIO2_RPORT PIND
#define DIO2_WPORT PORTD
#define DIO2_DDR DDRD
#define DIO2_PWM NULL
#define DIO3_PIN PIND3
#define DIO3_RPORT PIND
#define DIO3_WPORT PORTD
#define DIO3_DDR DDRD
#define DIO3_PWM &OCR2B
///* SNIP....you get the idea, and the file is way too long to copy here anyway */
If I had a dollar for every time I've fixed someones code simply by moving the // comment in a #define to the line before.You wouldn't earn a single dollar.On any C99-or-later conforming compiler... C99 is the first version of the C standard that clarified how those comments where to be handled in the pre-processor phase.
Before that, I could certainly believe that early cfront implementations (the original C++ to C preprocessor) or any C pre-processor that didn't understand "//" but where the subsequent compiler did could have exhibited such behavior.
If I had a dollar for every time I've fixed someones code simply by moving the // comment in a #define to the line before.You wouldn't earn a single dollar.On any C99-or-later conforming compiler... C99 is the first version of the C standard that clarified how those comments where to be handled in the pre-processor phase.
Before that, I could certainly believe that early cfront implementations (the original C++ to C preprocessor) or any C pre-processor that didn't understand "//" but where the subsequent compiler did could have exhibited such behavior.
I've been getting paid for code since 1973, so I've lived the entire era where the preprocessor didn't support it, while the compiler did. And yes, it's certainly possible some of my personal rules are a bit obsolete, but they have served me well.
This particular rule still has some value, as I just demonstrated in my previous response.
You have to remember these are strings, not numbers. Does it expand to "16" or "16 "? Most of the time it doesn't matter. This is one of those cases where it does.
#define Z_PROBE_PIN 16// mini-rambo ext pins on P3 ext next to LCD header
#define MASK(PIN) (1 << PIN)
#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN)))
#define READ(IO) _READ(IO)
READ(Z_PROBE_PIN)
#define Z_PROBE_PIN 16 // mini-rambo ext pins on P3 ext next to LCD header
#define MASK(PIN) (1 << PIN)
#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN)))
#define READ(IO) _READ(IO)
READ(Z_PROBE_PIN)
((bool)(DIO16_RPORT & (1 << DIO16_PIN)))
#define TCB0_MODE(v) TCB0.CTRLB = ((TCB0.CTRLB & 0xf8) | (v))
//just to make sure using a valid timer number
//(there could already be something in the avr include for this, I don't know)
typedef enum { TCBn0, TCBn1, TCBn2, TCBn3 } TCBn_t;
//simple function
//if we want to know what some of these defines are- look in one file- iom4809.h
//this function and iom4809.h are all we need to see how this function works
TCBmode(TCBn_t n, TCB_CNTMODE_t mode){
TCB0[n].CTRLB = (TCB0[n].CTRLB & (TCB_CNTMODE_gm<<TCB_CNTMODE_gp)) | mode;
}
//usage- it looks like a function, and it is a functionIf you haveopen sourcecrappy proprietary tools, rather than adhering to their bugs, you better fix the tools (or find a better mcu).
If you haveopen sourcecrappy proprietary tools, rather than adhering to their bugs, you better fix the tools (or find a better mcu).FTFY.
If you have open source tools, rather than adhering to their bugs, you better fix the tools.
Quote#define TCB0_MODE(v) TCB0.CTRLB = ((TCB0.CTRLB & 0xf8) | (v))you can even take it further since you have more than one of the same timer-
#define TCB_MODE(n,v) TCB##n##.CTRLB = ((TCB##n##.CTRLB & 0xf8) | (v))
now you have a generic for every timer b
TCB_MODE(0, 0)
TCB_MODE(1, 0)
(you would even get an error if n was an invalid number)
but it is endless when it comes to defines/macros, and you end up with another language to maintain where you use the manufacturers defines/macros, your own defines/macros, and ultimately the functions which will use a combination of both
not trying to throw wrenches into gears, but maybe consider just using functions to do the work
a simple example using the avr defines already provided, and turning the mode setting into a function-Code: [Select]//just to make sure using a valid timer number
//usage- it looks like a function, and it is a function
//(there could already be something in the avr include for this, I don't know)
typedef enum { TCBn0, TCBn1, TCBn2, TCBn3 } TCBn_t;
//simple function
//if we want to know what some of these defines are- look in one file- iom4809.h
//this function and iom4809.h are all we need to see how this function works
TCBmode(TCBn_t n, TCB_CNTMODE_t mode){
TCB0[n].CTRLB = (TCB0[n].CTRLB & (TCB_CNTMODE_gm<<TCB_CNTMODE_gp)) | mode;
}
TCBmode( TCBn0 ,TCB_CNTMODE_TIMEOUT_gc );
//compare to
TCB0_MODE_TIME_OUT_CHECK;
//or
SET_TCB0_MODE(TCB0_MODE_TIME_OUT_CHECK);
//or
TCB_MODE(0, TCB0_MODE_TIME_OUT_CHECK);
//or any other type of macro/define
//AND_IT_ENDS_UP_LOOKING_LIKE_THIS_EVERYWHERE_FOR_EVERYTHING & WHICH_IS_HARD_TO_READ & DECIPHER
I know every last byte wants to be squeezed out of a micro, but compilers are good at removing unused code, in-lining, etc., and in many cases the defines/macros are not worth the trouble when a function will do the job with little cost and where readability/reliability becomes much better (in my opinion).
I'll go crawl back into my hole in the ground.
If you have open source tools, rather than adhering to their bugs, you better fix the tools.
Nonetheless, I provided you with the ONE example you asked for. Just because it worked it in your own personal environment doesn't mean it wasn't a real problem for real people in real lives that needed real solutions right now.
Remember, I said this is one of my "rules for writing portable code". I have to write for the world that exists, not the world that is perfect. This is a detail that, in the real world, has never been implemented consistently between implementations. I've already proved that. A simple habit avoids the problem entirely, so that's the way I go. And if someone takes some of my code to a new platform 10 years from now and it still works, I've done my job correctly.
P.S. No charge, but it would be nice if you sent me a dollar anyway.
P.S. No charge, but it would be nice if you sent me a dollar anyway.Why me?
If I had a dollar for every time I've fixed someones code simply by moving the // comment in a #define to the line before.
You wouldn't earn a single dollar.One of my rules for writing portable code is never put a comment on the same line as a #define. True, it won't bite you 99.9% of the time, but finding those 0.1% problems makes up for it!
Could you show a single example of how this can cause a problem?
If you haveopen sourcecrappy proprietary tools, rather than adhering to their bugs, you better fix the tools (or find a better mcu).FTFY.
I don't understand your communication, but I do consider it impolite to present your own stuff as if it was said by me. I didn't say what you have quoted, nor anything remotely similar.
FTFY means "Fixed That For You". I.e., I disagreed with your statement and made a snarky edit as a demonstration. I don't consider that impolite really, so perhaps we disagree on that as well.
If you have open source tools, rather than adhering to their bugs, you better fix the tools.
Welcome to the internet.
You didn't disagree with my statement. You disagreed with your personal interpretation of my statement.
That is exactly why quoting should be exact.
Internet is not in the parallel virtual universe where nothing matters any more. Other participants are not robots, but human beings.
What? Are you trying to start a food fight?