-
Notifications
You must be signed in to change notification settings - Fork 212
Elements in Flash Memory
Starting with release v0.8.2, Arduino-based designs can store read-only GUI elements in Flash (PROGMEM)! Doing so can free up a significant amount of RAM, making it possible to run more complex GUIs even on RAM-constrained Arduino devices (such as the UNO / ATmega328P). To use this feature, simply replace the gslc_ElemCreate*() call with the equivalent gslc_ElemCreate*_P() call. The following functions are supported at this time:
gslc_ElemCreateTxt_P()
-
gslc_ElemCreateTxt_P_R()
(allows read-write text) gslc_ElemCreateBox_P()
gslc_ElemCreateBtnTxt_P()
Once the element create functions have been replaced by the _P() variants, the RAM-based element array (gslc_tsElem[]) can be made smaller as fewer elements need to be resident in RAM. The total number of elements in the element reference array (gslc_tsElemRef[]) will remain unchanged. Finally, the call to gslc_PageAdd() needs to indicate the revised number of RAM-resident elements.
Behind the scenes, the _P() functions are really a set of macros that create a set of data structures to match the non-Flash APIs.
Let's start by assuming that a read-only label "Count:" was created on the page as follows:
pElem = gslc_ElemCreateTxt(&m_gui,GSLC_ID_AUTO,E_PG_MAIN,(gslc_tsRect){20,60,50,10},
"Count:",0,E_FONT_TXT);
In the above, the entire element (including text string) will be stored in RAM. Alternately, one might performed some optimization by requesting that the text string "Count:" be stored in PROGMEM with the remainder of the element stored in RAM. Code to do this might look like the following:
static const char mstr2[] PROGMEM = "Count:";
pElem = gslc_ElemCreateTxt(&m_gui,GSLC_ID_AUTO,E_PG_MAIN,(gslc_tsRect){20,60,50,10},
(char*)mstr2,strlen_P(mstr2),E_FONT_TXT);
gslc_ElemSetTxtMem(pElem,GSLC_TXT_MEM_PROG);
To convert the above element creation call into one that stores the entire element in Flash, one can replace the above with the following:
gslc_ElemCreateTxt_P(m_gui,101,E_PG_MAIN,20,60,50,10,"Count:",0,
GSLC_COL_YELLOW,GSLC_COL_BLACK,GSLC_COL_BLACK,GSLC_ALIGN_MID_LEFT,false,true);
Note that these "macro functions" handle parameters a little differently than regular functions. One of the main differences is when passing a parameter that includes a comma. One example scenario is when passing a custom RGB color as a parameter: in this case, one might be tempted to pass (gslc_tsColor){255,200,0}
instead of GSLC_COL_ORANGE
. To avoid any issues with macro expansion, such parameters should be wrapped in parentheses, ie: ((gslc_tsColor){255,200,0})
.
Now assume that there are a total of 14 created elements on the main page (E_PG_MAIN), with all 14 originally defaulting to RAM storage (ie. stored in m_asPageElem[]). We might have allocated space for these elements as follows:
#define MAX_ELEM_PG_MAIN 14 // # Elems total
gslc_tsElem m_asPageElem[MAX_ELEM_PG_MAIN];
gslc_tsElemRef m_asPageElemRef[MAX_ELEM_PG_MAIN];
...
gslc_PageAdd(&m_gui,E_PG_MAIN,m_asPageElem,MAX_ELEM_PG_MAIN,m_asPageElemRef,MAX_ELEM_PG_MAIN);
If we then moved 6 of the read-only elements from RAM to Flash (using the gslc_ElemCreate*_P() functions), we could revise our variable declaration and PageAdd to the following:
#define MAX_ELEM_PG_MAIN 14 // # Elems total
#define MAX_ELEM_PG_MAIN_PROG 6 // # Elems in Flash
#define MAX_ELEM_PG_MAIN_RAM MAX_ELEM_PG_MAIN - MAX_ELEM_PG_MAIN_PROG // # Elems in RAM
gslc_tsElem m_asPageElem[MAX_ELEM_PG_MAIN];
gslc_tsElemRef m_asPageElemRef[MAX_ELEM_PG_MAIN];
...
gslc_PageAdd(&m_gui,E_PG_MAIN,m_asPageElem,MAX_ELEM_PG_MAIN_RAM,m_asPageElemRef,MAX_ELEM_PG_MAIN);
Note that new #defines have been created to help us calculate the remaining number of elements that need to be stored in the internal RAM element array given a certain number of elements that have been migrated to use Flash.
Please refer to the online API guide under Flash-based Element Macros