did i do this macro right ? - Page 1
Forum section: electronics / general

author: Simon
author_rank: Unknown
timestamp: July 05, 2014, 07:39:48 am
content: Before wondering why my PWM code that worked on another chip does not work on my new one I'll assume it may be the changes i made to the macro's i use:Code:#define bit_s(p,m) ((p) |= (BIT(m)))#define bit_c(p,m) ((p) &= ~(BIT(m)))#define BIT(x) (0x01 << (x))These used to be:Code:#define bit_set(p,m) ((p) |= (m))#define bit_clear(p,m) ((p) &= ~(m))

author: bwat
author_rank: Frequent Contributor
timestamp: July 05, 2014, 08:10:07 am
content: Cursory glance: looks good.If you want to test small bits of code like this then I would run it on my host machine not a microcontroller. I would write a small programCode:#include <stdio.h>#define bit_s(p,m) ((p) |= (BIT(m)))#define bit_c(p,m) ((p) &= ~(BIT(m)))#define BIT(x) (0x01 << (x))void test_bit_manipulation(unsigned char byte, unsigned char bit_clr, unsigned char bit_set){unsigned char byte_copy0;unsigned char byte_copy1;byte_copy0 = byte_copy1 = byte; /* The bit manipulation routines are destructive */printf("byte: 0x%x, set: %d, result: 0x%x\n", byte_copy0, bit_set, bit_s(byte, bit_set));printf("byte: 0x%x, clear: %d, result: 0x%x\n", byte_copy1, bit_clr, bit_c(byte_copy0, bit_clr));}int main(int argc, char **argv){(void) argc;(void) argv;test_bit_manipulation(0xff, 3, 3);test_bit_manipulation(0x00, 3, 3);return 0;}Save it in bits.c, build it and run it:Code:bwat@eeepc:~/slask$ make bitscc bits.c -o bitsbwat@eeepc:~/slask$ ./bitsbyte: 0xff, set: 3, result: 0xffbyte: 0xff, clear: 3, result: 0xf7byte: 0x0, set: 3, result: 0x8byte: 0x0, clear: 3, result: 0x0And Bob is your proverbial. When working with more complex target agnostic code, I also have all of my host machine's debuggers, disk space for logging, profilers, etc. The platform specific stuff gets tested on the microcontroller.The above took between 5 and 10 minutes including this writeup.

author: Simon
author_rank: Unknown
timestamp: July 05, 2014, 08:12:54 am
content: ok your going way over my head, was I right or wrong ?

author: bwat
author_rank: Frequent Contributor
timestamp: July 05, 2014, 08:18:51 am
content: You were right but that wasn't the gist of my post. If you can write code then you can write code to test your own code and its easier testing algorithms on a desktop machine than on a microcontroller.

author: Simon
author_rank: Unknown
timestamp: July 05, 2014, 08:20:41 am
content: I thought that is what you meant, thing is I don't do PC programming in C they are still two separate worlds for me. OK so my macro's are right, lord knows then why my PWM output failed to "light up"

author: andyturk
author_rank: Frequent Contributor
timestamp: July 05, 2014, 02:54:17 pm
content: Quote from: Simon on July 05, 2014, 08:20:41 amHaving a native C environment to play with on your PC will help advance your mcu development skills. The language is basically the same in both worlds. When you're starting out, the compile-link-run cycle is a lot quicker on a PC (or linux box) and you generally don't have to worry about the hardware being the problem.

author: zapta
author_rank: Super Contributor
timestamp: July 05, 2014, 03:32:24 pm
content: Any reason for calling the same thing sometimes x and sometimes m?port and bit_index would be clearer names.

author: Simon
author_rank: Unknown
timestamp: July 05, 2014, 03:55:10 pm
content: Well they are macros that I took off a tutorial so i did not originally come up with them, at the end of the day now i know how to call them I don't even look at them.

author: zapta
author_rank: Super Contributor
timestamp: July 05, 2014, 04:19:12 pm
content: Quote from: Simon on July 05, 2014, 03:55:10 pmIt's not about you, it's about the poor guy that will need to read or maintain it down the road ;-)Descriptive names make the code readable, reduce the need for documentation, and does not cost anything at runtime.http://www.makinggoodsoftware.com/2009/05/04/71-tips-for-naming-variables/

author: bwat
author_rank: Frequent Contributor
timestamp: July 05, 2014, 05:17:21 pm
content: Quote from: zapta on July 05, 2014, 04:19:12 pmI'm not buying it. This descriptive naming convention is a new thing and will probably be shown to be quite ephemeral. We've had over two thousand years of mathematical culture from Euclid's Elements to the 1950s and we've survived just fine without the idea that names for conceptual things must be descriptive. There's actually problems in giving meaning to names for conceptual things. Mathematicians and logicians are doing just fine with single letters, often which are taken from languages they do not understand.The following code for a compiler/translator uses only Greek letters for variables. It doesn't need descriptive names as everyone working in the area in which it is used will know Gamma is code, Kappa is a continuation, Pi is a program, Rho is an environment, and Sigma is a memory (store). In fact it's an almost direct translation from an expression of the lambda calculus - it was debugged on paper before I fired up Emacs.Code:(set! B-compile(lambda (pi rho sigma kappa)(if (atom pi)(if (symbolp pi)(kappa rho sigma (list (cons 'var (rho pi))))(signal-exception t (list "invalid input" pi)))(if (eq (car pi) 'lambda)(B-compile (caddr pi)(B-foldright B-extend-rho rho (cadr pi))sigma(lambda (rho-prime sigma-prime gamma-prime)(kappa rho-primesigma-prime(append (list (cons 'lam (length (cadr pi))))gamma-prime))))(B-compile (car pi)rho(+ 1 sigma)(lambda (rho-prime sigma-prime gamma-prime)(B-compile (cadr pi)rho-primesigma-prime(lambda (rho-prime-prime sigma-prime-prime gamma-prime-prime)(kappa rho-prime-primesigma-prime-prime(append (list (cons 'ap sigma))(append gamma-prime(append (list (cons 'label sigma))gamma-prime-prime))))))))))))Finally, the idea that descriptive names can reduce documentation is a dangerous one in my opinion.

author: IanB
author_rank: Super Contributor
timestamp: July 05, 2014, 08:53:33 pm
content: Descriptive names don't have to be long names. Appropriate choices of single letters can help. For instance: "m" for mask, "n" for bit number, "b" for byte, "w" for word, "dw" for double-word, etc.The trouble with those macros is they have no type safety. You don't know whether they are working with bytes, words, or what. Which is a general problem with macros, and why they tend to be frowned upon these days, even though commonly seen in code.The original macro was using "m" for mask, so after changing it to a bit number, it would have been good to use "BIT(n)" instead of "BIT(m)".The letter "p" is commonly used to mean pointer, and I'm not sure if that applies here.In general, are you confident about what those macros will do if applied to 8 bit variables, 16 bit variables, 32 bit variables, signed or unsigned? (I know your answer is "no", which is one of the difficulties with the copy/paste approach to coding. It would help you enormously to set up a programming environment on your PC and test out some of these things with the help of a reference book or two.)

author: zapta
author_rank: Super Contributor
timestamp: July 05, 2014, 09:27:00 pm
content: Quote from: bwat on July 05, 2014, 05:17:21 pmI doubt that everybody that works in Simon's area knows what p, m and x are.

author: Psi
author_rank: Super Contributor
timestamp: July 05, 2014, 09:33:22 pm
content: Make sure when you use those macros you pass the correct 2nd parametereg..This works on AVR because PC3 is defined as 3 (bit position 3)bit_s(PORTC,PC3)But on other toolchains for different mcus they sometimes use mask numbers instead, so the equivalent of AVRs "PC3" definition would be equal to 8 (00001000) which wont work on your bit_s macro. It will however work on your bit_set macro.

author: andyturk
author_rank: Frequent Contributor
timestamp: July 05, 2014, 09:46:54 pm
content: Quote from: IanB on July 05, 2014, 08:53:33 pmThe trouble with macros is that they're evil. A necessary evil in some cases, but they're far too frequent in code written by firmware engineers.Inline functions and enums are much better and handle 90% of what people do with preprocessor macros.

author: zapta
author_rank: Super Contributor
timestamp: July 05, 2014, 10:02:18 pm
content: Quote from: andyturk on July 05, 2014, 09:46:54 pm+7

author: amyk
author_rank: Super Contributor
timestamp: July 06, 2014, 01:11:00 am
content: The first set of macros uses bit numbers, the second set uses preshifted masks.The second way is more common and it's what I prefer, since it allows setting/clearing multiple bits at once (just or the masks together.) I've also seen this convention that defines both the bit position and the preshifted value:Code:#define RG_AGCEN_POS 7#define RG_AGCEN (1 << RG_AGCEN_POS)