The problem:
I'm writing a general C library for an LCD in a microcontroller project.
up to 8 LCDs with various sizes(e.g. 128*96 or 64*48) in various addresses may be added (e.g. LCD3 and LCD7). but only one of them is actively coded at a time. so I thought for a mechanism to do so.
in the code, there is a definition for CLCD_ROWS and CLCD_COLS which correspond to the Active display size.
#define CLCD_ROWS // Active LCD rows
#define CLCD_COLS // Active LCD columns
and there's definitions for the various LCDs. for example, if we have LCD3 and LCD7 connected, we define their sizes with :
#define CLCD_ROWS3 96
#define CLCD_COLS3 64
#define CLCD_ROWS7 128
#define CLCD_COLS7 32
The question:
I've written a [wrong] macro to redefine the values of CLCD_ROWS and CLCD_COLS :
#define cLcd_setActiveI2CcLcd(X) \
CLCD_ROWS = CLCD_ROWS##X \
CLCD_COLS = CLCD_COLS##X
and in my main code I call the macro:
cLcd_setActiveI2CcLcd(7);
which gives me an error of "missing ;".
it is easy to implement it with variables. but since these values are hardcoded , I thought they are "preprocessable" since need every bit of RAM in a low end MCU.
Is my approach about preprocessing this values, correct ?
What is the right way to write a macro for that purpose ?
I'm using a C99 compiler.
First things first, your method of using function-type macro is wrong. Even if you fix the error you have, the macro will not do CLCD_ROWS equal to CLCD_ROWS7, but to CLCD_ROWSX (that is how macros work, it concatenates the thing you give, not its value). Instead if you want to use macros for reducing RAM usage you can change your code to:
1st Solution
#define ROW_COLS 7 // change this if you use different display
#if ROW_COLS == 7
#define CLCD_ROWS 128
#define CLCD_COLS 32
#elif ROW_COLS == 3
#define CLCD_ROWS 96
#define CLCD_COLS 64
#endif
2nd Solution
If you want dynamically change the size of your display in the runtime, you can do it like this:
static int display_cnt;
#define CLCD_ROWS ((display_cnt == 3) ? 96 : 128)
#define CLCD_COLS ((display_cnt == 3) ? 64 : 32)
So when you change the value of display_cnt variable, the macro will automatically change its value.
Related
I'm wondering if it can be written that the prepocessor evaluates assigned constants known at compile time and returns the result as a string. I believe the answer is no or complex, but I'll give a try.
Basically I have constants which are expressed in milliseconds but I want to display the results as secs, therefore divide by 1000, and wonder because all is known at compile time, if the preprocessor can directly put the result of this division into the code rather than eval at runtime.
Example:
#define FREQ_AUTO_WHEN_RELAY_ON 150000UL
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
STR( FREQ_AUTO_WHEN_RELAY_ON/1000UL ) " secs"
would yield to "150000UL/1000UL secs"
which is not I want to display, aka "150 secs"
Thanks
You have to first prepare a header with all possible outputs:
// calculate.h
#if VALUE == 1
#define RESULT 1
#elif VALUE == 2
#define RESULT 2
/* etc. millions of lines */
#elif VALUE == 150
#define RESULT 150
#endif
Then you can do:
#define VALUE FREQ_AUTO_WHEN_RELAY_ON/1000UL
#include "calculate.h"
STR(VALUE)
Similarly, you first have to define a matrix of all possible combinations of values:
#define DIV_1UL_1UL 1
#define DIV_1UL_2UL 0
#define DIV_2UL_1UL 2
/* etc. really millions of lines */
#define DIV_150000UL_1000UL 150
Then you can:
#define DIV(a, b) DIV_##a##_##b
#define XDIV(a, b) DIV(a, b)
STR(XDIV(FREQ_AUTO_WHEN_RELAY_ON, 1000UL))
Can C-preprocessor can output as a string the evaluation of compiled known constants values(e.g. 150000UL/1000UL)?
Yes, but it's not practical. Instead, generate the header file from a build system.
I access registers by concatenated defines unsing the function GETREG
#define NUMBER 1 //changes
#define REG1 register.N1
#define REG2 register.N2
#define REG8 register.N8
#define GETREG_(N) REG ## N
#define GETREG(N) GETREG_(N)
Sometimes the registers for that NUMBER are not defined so i want to make sure the macro correctly expands before inserting it in the code so i tried to do:
#define NUMBER 5
#ifdef GETREG(NUMBER)
GETREG(NUMBER) = 0
#endif
However this always seems to evaluate as true and the compiler prints
Warning:extra tokens at end of #ifdef directive
Background Story:
In my projects I create libraries to interface with a HAL to abstract the hardware level. Often from one project to another the codebasis in the HAL stays exactly the same but just the location of pins changes. For that reason i would like to use macro-expansion to access the pins. The following macro does the job for me at adressing the analog features of the pin:
#define ANSEL_(Pin) _ANS ## Pin
#define ANSEL(...) ANSEL_(__VA_ARGS__)
that way i can turn on or off analog features by:
#define PIN_RX A0
ANSEL(PIN_RX)= 0;
and other registers by similar macros. The problem i am facing now is that some pins for example do not have analog features (e.g. Pin A5). Because of that i would like to test if the define in the library esists. I was tryin to do this by:
#ifdef ANSEL(PIN_RX)
ANSEL(PIN_RX)= 0;
#endif
However this simple approach is not working.
The microcontroller (PIC33) lib:
Edit: Shipped from the manufactorer
#define ANSELA ANSELA
extern volatile unsigned int ANSELA __attribute__((__sfr__));
typedef struct tagANSELABITS {
unsigned ANSA0:1;
unsigned ANSA1:1;
unsigned ANSA2:1;
unsigned ANSA3:1;
unsigned ANSA4:1;
unsigned :4;
unsigned ANSA9:1;
} ANSELABITS;
extern volatile ANSELABITS ANSELAbits __attribute__((__sfr__));
/* ANSELA */
#define _ANSA0 ANSELAbits.ANSA0
#define _ANSA1 ANSELAbits.ANSA1
#define _ANSA2 ANSELAbits.ANSA2
#define _ANSA3 ANSELAbits.ANSA3
#define _ANSA4 ANSELAbits.ANSA4
#define _ANSA9 ANSELAbits.ANSA9
You have the wrong expectation for the behavior of the #ifdef directive. That directive is equivalent to #if defined, where defined is a preprocessing operator in that context. Although the condition of an overall #if directive is evaluated only after the line is fully macro-expanded, the defined operator operates on the next preprocessing token, which must have the form of an identifier, before macro expansion:
Prior to evaluation, macro invocations in the list of preprocessing tokens that will become the controlling constant expression are replaced (except for those macro names modified by the defined unary operator) [...]
[C2011, 6.10.1/4]
Thus, your
#ifdef GETREG(NUMBER)
tests whether GETREG is a defined macro, and the (NUMBER) constitutes a sequence of unexpected extra tokens.
The defined operator therefore cannot serve your purpose. It is conceivable that there is a way to use a more general #if directive to achieve your aim, but I'm not seeing it at the moment. Instead, I'm inclined to suggest letting the compiler find such errors for you, instead of expecting the preprocessor to do it. If compile time is too late, then perhaps you need to look to a build configuration system such as the Autotools or CMake could help you create.
You can do more or less what you want if you are prepared to use two #defines instead of one for each pin:
#define HAS_ANS_A0 1
#define ANS_A0 ANSELAbits.ANSA0
#define HAS_ANS_A1 1
#define ANS_A1 ANSELAbits.ANSA1
#define HAS_ANS_A5 1
#define ANS_A5 ANSELAbits.ANSA5
#define HAS_ANSEL_(Pin) HAS_ANS_ ## Pin
#define HAS_ANSEL(...) HAS_ANSEL_(__VA_ARGS__)
#define ANSEL_(Pin) ANS_ ## Pin
#define ANSEL(...) ANSEL_(__VA_ARGS__)
#if HAS_ANSEL(PIN_RX)
ANSEL(PIN_RX)= 0;
#endif
This works because in an #if, an undefined identifier token (that is, an identifier token which has not been #defined) has the value 0. It is not an error, or even a warning.
Note: I changed the symbols starting _ANS to conform with ยง7.1.3 (Reserved Names), paragraph 1:
All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.
Is it possible to create a preprocessor function that will cause multiple other preoprocessor macros to be defined?
I'm working in a micro controller framework that requires a few macros to be made in order for a generic interrupt handler to function:
<MODULE_NAME>_IRQ_PIN //ex: PORTB_PIN(0)
<MODULE_NAME>_IRQ_IN_REGISTER //ex: GPIO_PBIN
<MODULE_NAME>_IRQ_NUMBER //ex: GPIO_IRQA
<MODULE_NAME>_IRQ_INTCFG_REG //ex: GPIO_INTCFGA
I am trying to make this process more generic and easier from an implementation standpoint. There are about ten of these macros that need to be defined, but their definitions can all be derived when given 1) the port name 2) the pin number and 3) the IRQ name. I am hoping then to create a pre-processor function that will result in the generation of all of these macros. Something like:
#define MAKE_INTERRUPT_MACROS(module, port, pin, irq_num) \
#define module##_IRQ_pin PORT##port##_PIN(##pin##) \
#define module##_IRQ_IN_REGISTER GPIO_P##port##IN \
#define module##_IRQ_NUMBER GPIO_IRQ##irq_num \
#define module##_IRQ_INTCFG_REG GPIO_INTCFG##irq_num
Is there a legal way to get the proprocessor to do something like the above, where a single preprocessor function causes the generation of multiple other macros based on the parameters passed to the function?
I think this classical scheme may solve your problem. This is a simple and clear way:
#ifdef CPU_X
#define IRQ_PIN 0
#define IRQ_IN_REGISTER 3
#define IRQ_NUMBER 11
#define IRQ_INTCFG_REG 12
#endif
#ifdef CPU_YY
#define IRQ_PIN PORTB_PIN(1)
#define IRQ_IN_REGISTER GPIO_PBIN(6)
#define IRQ_NUMBER GPIO_IRQA(9)
#define IRQ_INTCFG_REG GPIO_INTCFGA(0xA)
#endif
#ifdef CPU_KK
/* .
. Another CPU
.
*/
#endif
#ifdef CPU_K2
/* .
. Another CPU
.
*/
#endif
You may compile the code specifying the CPU using -D CPU_xx and the problem shoudl be solved!
I assume you might have some other macros (E.G.: GPIO_IRQA(9)), and in CPU_YY I've used it, but It might be used also for the other CPUs.
If you can use C++ rather than C, look at using classes, one per CPU type, and simply use constants and interfaces in the class. Then, you don't even care that they are different, simply use the same names to access them (the differentiation is done based upon the class being instantiated.
If you really and truly must use C (such as writing a device driver), you can use the approach device driver writers use (all flavors of *nix, VxWorks, PSOS, QNX, and most of the old DEC OSs use this approach, don't know about Windows): Simply build a structure containing the values and any functions you may need to manipulate the hardware (or anything else, for that matter). Create one instance of this structure per hardware (or in your case, module) type. Then indirect through the structure.
Example:
struct module_wrapper {
const char *module_name;
int irq_pin;
int irq_register;
int irq_number;
int irq_intcfg_reg;
int (*init_fcn)(void);
int (*reg_access)(int register_number);
int (*open)(void);
int (*close)(void);
int (*read)(char *dst_buffer, int len);
int (*write)(const char *src_buffer, int len);
};
module_wrapper portB = { /* initialize here */ };
module_wrapper gpio = { /* initialize here */ };
printf("GPIO pin %d\n", gpio.irq_pin);
Obviously, modify as desired. You can also replace the constant variables with functions that return the values.
You can't define other macros with a macro, but you achieve something similar by doing it kind of in a totally opposite way.
You could autogenerate a file which has the following block for each possible module:
#ifdef <MODULE>_IRQ_DATA
#define <MODULE>_IRQ_pin CALL(GET_IRQ_PIN, <MODULE>_IRQ_DATA)
#define <MODULE>_IRQ_IN_REGISTER CALL(GET_IRQ_IN_REGISTER, <MODULE>_IRQ_DATA)
#define <MODULE>_IRQ_NUMBER CALL(GET_IRQ_NUMBER, <MODULE>_IRQ_DATA)
#define <MODULE>_IRQ_INTCFG_REG CALL(GET_IRQ_INTCFG_REG, <MODULE>_IRQ_DATA)
#endif
And then have:
#define CALL(MACRO, ...) MACRO(__VA_ARGS__)
#define GET_IRQ_PIN(port, pin, irq_num) PORT##port##_PIN(pin)
#define GET_IRQ_IN_REGISTER(port, pin, irq_num) GPIO_P##port##IN
#define GET_IRQ_NUMBER(port, pin, irq_num) GPIO_IRQ##irq_num
#define GET_IRQ_INTCFG_REG(port, pin, irq_num) GPIO_INTCFG##irq_num
(Depending on how the defines are used, you can possibly get rid of the #ifdef-#endif -pairs, eg. if all of them must/can always be defined)
Then actually defining the needed values could be done with just:
#define <MODULE>_IRQ_DATA B,0,A
I'm trying to make my header file easily changeable with macros. I'm debugging my code and it seems these MACROS are not doing what they are supposed to. Can someone tell me how I achieve the following effect? LED_ID_AMS etc.
#define LED_NUMBER (2)
#define LED_ID_X (0)
#define LED_ID_Y (1)
#define LED_PIN_X (0)
#define LED_PIN_Y (3)
#define LED_PORT_X (PORTE)
#define LED_PORT_Y (PORTG)
#define LED_DD_X (DDRE)
#define LED_DD_Y (DDRG)
#define LED_PORT(LED_ID_X) (LED_PORT_X)
#define LED_PORT(LED_ID_Y) (LED_PORT_Y)
#define LED_PIN(LED_ID_X) (LED_PIN_X)
#define LED_PIN(LED_ID_Y) (LED_PIN_Y)
#define LED_DD(LED_ID_X) (LED_DD_X)
#define LED_DD(LED_ID_Y) (LED_DD_Y)
What am I trying to achieve?
I'm trying to make it so I can loop through the port init like so:
for(i=0;i<LED_NUMBER;i++){
/* set data direction to output*/
LED_DD(i)|=((0x01)<<LED_PIN(i));
/* turn on led */
LED_PORT(i)|=((0x01)<<LED_PIN(i));
}
You will regret using too many macros later. Actually, you're regretting it already, as they don't work and, being macros, they are very difficult to debug.
Just a few points:
your LED_PIN(i) expressions are always expanding to 0
your LED_PORT(i) expressions are always expanding to PORTE whatever that may be
For instance LED_PIN(LED_ID_X) expands to LED_PIN_X. Note, macro parameter LED_ID_X is not used at all. Instead, LED_PIN_X simply expands to 0.
This should scream warnings at you, as e.g. LED_PORT(SOME_ARG) has several definitions. And in LED_PORT(LED_ID_X) the LED_ID_X is just a dummy argument, with absolutely no relation to your constant LED_ID_X.
You can make your code equally readable by using a constant array, perhaps used from macros like you try to do here.
Unless there are a massive number of LED_ID_<foo>, this is at best a minor simplification. Don't do that. If there is a lot of code futzing around with those is mostly the same way, it might make sense to define a macro that iterates some action over each of them, i.e.:
#define FROB_LEDS \\
action(LED_ID_X); \\
action(LED_ID_Y); \\
action(LED_ID_Z);
and define action(X) locally as a macro to do the action on LED X, FROB them, and undefine action again. Quite ugly, true.
You'll have to add at least one of:
arrays
inline functions
more complicated macros
And it also seems to me that dereferencing of hardware addresses will be required.
For example, using macros, you can define:
#define LED_PORT(i) *(uint16_t *)( \
(i) == LED_ID_X ? LED_PORT_X : \
(i) == LED_ID_Y ? LED_PORT_Y : \
etc)
where:
#define LED_ID_X (0)
#define LED_ID_Y (1)
#define LED_PORT_X (PORTE)
#define LED_PORT_Y (PORTG)
#define PORTE (0x11112222U) // example only
#define PORTG (0x33334444U) // example only
Here uint16_t is only a guess: I'm assuming 16-bit ports in a 32-bit address space.
Or, using arrays and C99's designated initializers:
const uint32_t LED_PORT[] = {
[LED_ID_X] = LED_PORT_X,
[LED_ID_Y] = LED_PORT_Y
};
#define LED_PORT(i) (*(uint16_t *)LED_PORT[i])
And of course, without C99 you can use just:
const uint32_t LED_PORT[] = {LED_PORT_X, LED_PORT_Y};
which assumes that LED_ID_X is 0, etc.
I'm having problem building C macro for my PIC. It's the same for other C-based system's, so non-PIC C experts are also more than welcome.
Lets assume that I have defined my LED_1 pin :
#define LED_1 A1 //A1 as output for LED_1
So if I want to light a LED I would write:
PORTAbits.RA1 = 1;
And if I would like to do it using my LED_1 definition I have to add two more macros:
#define change_PORT_(var) PORTAbits.R##var
#define change_PORT(var) change_PORT_(var
And to use it:
change_PORT(LED_1) = 1;
And it works like a charm. But the problem is that in definitions above I have
PORT A bits.##var
So what if I want to change PORTB values? I would have to build separate macros for PORTs A and B. But it's not even close to be a robust solution.
And I came up with an idea which, I don't know why, doesnt work.
#define LED_1 A1
#define LED_2 B1
#define __A1 A //This would be defined for all PORTA's pins such as A2,A3,A4 etc
#define __B1 B
#define ___change_PORT(var,var2) PORT##var2 bits.R##var
#define __change_PORT(var,var2) ___change_PORT(var,var2)
#define _change_PORT(var) __change_PORT(var,__##var) // creating e.g. __A1
#define change_PORT(var) _change_PORT(var)
And when I try to run this:
change_PORT(LED_1);
The compiler changes __##var to ___A1 but it never changes __A1 to A so this MACRO doesn't work as it supposed to.
I spent a lot of time trying to fix it so I'd appreciate any help :)
EDIT::
I might have found a solution to my problem:
(LAT is just another register name, but it works same as PORT, so this name-change is irrelevant)
#define ___PORTchange(var,var2) PORT##var2##bits.R##var
#define __PORTchange(var,var2) ___PORTchange(var,var2)
#define CHANGE_TO_PORT_NAME(var) ___##var
#define _PORTchange(var) __PORTchange(var,CHANGE_TO_PORT_NAME(var))
#define PORTchange(var) _PORTchange(var)
but I get a compiler error:
100: PORTAbits.RA0 = 1;
^ (374) missing basic type; int assumed (warning)
^ (983) storage class redeclared
^ (984) type redeclared
^ (239) identifier "PORTAbits" redefined (from line 3900)
^ (314) ";" expected
So no it does substitute it correctly but I get a compiler warning telling me that I redefine PORTAbits which I cannot understand. I just wanted preprocessor to change PORTchange(var) to PORTxbits.Rvar where x is A or B. But instead it seems that I'm redeclaring something.
I don't get it.
If I preprocess (tried with several gcc versions and sun cc)
#define LED_1 A1
#define LED_2 B1
#define __A1 AX
#define __B1 BX
#define ___change_PORT(var,var2) PORT##var2##bits.R##var
#define __change_PORT(var,var2) ___change_PORT(var,var2)
#define _change_PORT(var) __change_PORT(var,__##var)
#define change_PORT(var) _change_PORT(var)
change_PORT(LED_1);
change_PORT(LED_2);
I get
PORTAXbits.RA1;
PORTBXbits.RB1;
which is apparently what you are wanting. A bug in your compiler?