EDIT: I think this fits better in the C++ Stack Overflow, so I'm going to re-post this there.
I am working on a menu system with #define
macros (inspired by the Marlin firmware on my 3D printer) I am attempting to generalize each menu item with the macro #define MENU_ITEM_EDIT()
. The full code is really long, so I am leaving out chunks of code of compactness. However, you can find the full code here: https://pastebin.com/h24itG9y
void draw_row(int row, char* value) { /* Stuff here*/ } // Draws row
char* uiToStr(int x) { /* Stuff here*/ } // Converts unsigned int to a string
#define disp_array(display, value) display[value]
#define disp_func(display, value) display(value)
#define disp_char(display, value) display
#define MENU_ITEM_EDIT(min, max, rate, display, displayType, width, label, value) \
// A bunch of stuff
draw_row(rowNum, disp_ ## displayType(display, value)); \
// More stuff
Using the code macro would look like:
// Values
const char item1[] = "Item 1", item2[] = "Item 2", item3[] = "Item 3";
const char* const itemList[] = {item1, item2, item3};
int currentItem = 0;
uint8_t item1Val = 10;
void menu1()
{
START_MENU();
MENU_ITEM_EDIT(0, 3, 1, itemList, array, 6, "Item:", currentItem);
MENU_ITEM_EDIT(0, 255, 1, uiToStr, func, 3, "Item 1 Value:", item1Val);
END_MENU();
}
Which displays as:
Item: Item 1
Item 1 Value: 10
For convenience in the declarations of my menus, I am trying to use common menu types, such as an uint8_t
that ranges from 0 to 255. Then, in the menu, I would use __u255_t
instead of the first 6 arguments.
#define __u255_t 0, 255, 1, uiToStr, func, 3
void menu2()
{
int item2Val = 10;
START_MENU();
MENU_ITEM_EDIT(__u255_t, "Item 2 Value", item2Val);
END_MENU();
}
Previously, I had it set up such that every time I wanted a different type of menu, even if I would only use it once, I had to define a type for it and how it should evaluate in the macro. This way, I can use 1 argument instead of 6 for commonly recurring types in rows. However, I still want the ability to use the 6 argument option when I have a row that has a unique set of arguments, such as a different range or list of display strings.
However, in this example, the program won't compile because it places __u255_t
into min
in the MENU_ITEM_EDIT()
macro, rather than expanding __u255_t
into its 6 values and placing them into the first 6 arguments of MENU_ITEM_EDIT()
. The macro evaluates as:
MENU_ITEM_EDIT(__u255_t, "Item 2 Value", item2Val);
// Evaluates as:
MENU_ITEM_EDIT( (0, 255, 1, uiToStr, func, 3), "Item 2 Value", item2val, , , , , );
Note: I put an extra set of parentheses to make it more clear to understand.
But I want:
MENU_ITEM_EDIT(__u255_t, "Item 2 Value", item2Val);
// Evaluates as:
MENU_ITEM_EDIT(0, 255, 1, uiToStr, func, 3, "Item 2 Value", item2Val);
I thought about using a struct
, however I'm not sure that I can because depending on the row, the value
string in draw_row()
could be a function or an array. Does anyone have any advice on how to solve this problem?
Also, please let me know if I need to add any more code to make my problem more clear.
including variable-length parameter lists
-- actually they do:__VA_ARGS__
and#define foo(...)