Message |
|
|
|
|
davetcc wrote:If you don't plan on using the BSP ROM you could just change it for another ROM storage option in the code generator dialog. For example No EEPROM or I2C EEPROM.
I played around with that before posting here, but didn't have much luck compiling with those options either,
No EEPROM, I2C EEPROM and Arduino EEPROM all resulted in a 'undefined reference to `ramDataSet'' error, thankfully the solution to this in your examples.
Would it possible to add the ramDataSet definition to the generated code, or have I missed something obvious in the Designer
Edit: Just saw your response, ignore this message
|
|
|
Thank you for getting back to me so soon.
Yeah the Battery backed up memory isn't something that the project really needed, the internal flash memory should be sufficient with its 10K write cycles, but I will look into the ability to add an external 24C32 or 24C64 EEPROM in the future if it turns out we need more write cycles.
I think the second issue I had while trying out the menu generated fully from the TcMenu designer, with the EEPROM disabled was it still gave an error.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Test1.emf
{
"version": "1.00",
"projectName": "Project description",
"author": "benja",
"items": [
{
"parentId": 0,
"type": "analogItem",
"item": {
"maxValue": 1000,
"offset": 0,
"divisor": 10,
"unitName": "d",
"name": "Decimal",
"variableName": "Decimal",
"id": 1,
"eepromAddress": 2,
"functionName": "decimalDidChange",
"readOnly": false,
"localOnly": false,
"visible": true
}
},
{
"parentId": 0,
"type": "analogItem",
"item": {
"maxValue": 255,
"offset": 0,
"divisor": 2,
"unitName": "dB",
"name": "Halves",
"variableName": "Halves",
"id": 2,
"eepromAddress": 4,
"readOnly": false,
"localOnly": false,
"visible": true
}
},
{
"parentId": 0,
"type": "largeNumItem",
"item": {
"digitsAllowed": 9,
"decimalPlaces": 3,
"negativeAllowed": true,
"name": "Lge Num",
"variableName": "LgeNum",
"id": 3,
"eepromAddress": 6,
"functionName": "largeNumDidChange",
"readOnly": false,
"localOnly": false,
"visible": true
}
},
{
"parentId": 0,
"type": "subMenu",
"item": {
"secured": false,
"name": "More Items",
"variableName": "MoreItems",
"id": 4,
"eepromAddress": -1,
"readOnly": false,
"localOnly": false,
"visible": true
}
},
{
"parentId": 4,
"type": "enumItem",
"item": {
"enumEntries": [
"Pizza",
"Pasta",
"Salad"
],
"name": "Options",
"variableName": "MoreItemsOptions",
"id": 5,
"eepromAddress": 14,
"readOnly": false,
"localOnly": false,
"visible": true
}
},
{
"parentId": 4,
"type": "boolItem",
"item": {
"naming": "YES_NO",
"name": "Toppings",
"variableName": "MoreItemsToppings",
"id": 6,
"eepromAddress": 16,
"readOnly": false,
"localOnly": false,
"visible": true
}
},
{
"parentId": 4,
"type": "boolItem",
"item": {
"naming": "ON_OFF",
"name": "Power",
"variableName": "MoreItemsPower",
"id": 7,
"eepromAddress": 17,
"readOnly": false,
"localOnly": false,
"visible": true
}
},
{
"parentId": 4,
"type": "actionMenu",
"item": {
"name": "Save",
"variableName": "MoreItemsPressMe",
"id": 8,
"eepromAddress": -1,
"functionName": "saveWasPressed",
"readOnly": false,
"localOnly": false,
"visible": true
}
},
{
"parentId": 4,
"type": "floatItem",
"item": {
"numDecimalPlaces": 2,
"name": "Number",
"variableName": "MoreItemsNumber",
"id": 9,
"eepromAddress": -1,
"readOnly": false,
"localOnly": false,
"visible": true
}
},
{
"parentId": 4,
"type": "scrollItem",
"item": {
"itemWidth": 10,
"eepromOffset": 0,
"numEntries": 5,
"choiceMode": "ARRAY_IN_RAM",
"variable": "ramDataSet",
"name": "Scroll",
"variableName": "MoreItemsScroll",
"id": 10,
"eepromAddress": -1,
"readOnly": false,
"localOnly": false,
"visible": true
}
},
{
"parentId": 0,
"type": "subMenu",
"item": {
"secured": false,
"name": "Runtimes",
"variableName": "Runtimes",
"id": 11,
"eepromAddress": -1,
"readOnly": false,
"localOnly": false,
"visible": true
}
},
{
"parentId": 11,
"type": "textItem",
"item": {
"textLength": 5,
"itemType": "PLAIN_TEXT",
"name": "Text",
"variableName": "RuntimesText",
"id": 12,
"eepromAddress": 18,
"readOnly": false,
"localOnly": false,
"visible": true
}
},
{
"parentId": 11,
"type": "runtimeList",
"item": {
"initialRows": 0,
"name": "Custom List",
"variableName": "RuntimesCustomList",
"id": 13,
"eepromAddress": -1,
"functionName": "",
"readOnly": false,
"localOnly": false,
"visible": true
}
},
{
"parentId": 11,
"type": "customBuildItem",
"item": {
"menuType": "REMOTE_IOT_MONITOR",
"name": "IoT Monitor",
"id": 14,
"eepromAddress": -1,
"readOnly": false,
"localOnly": false,
"visible": true
}
},
{
"parentId": 11,
"type": "customBuildItem",
"item": {
"menuType": "AUTHENTICATION",
"name": "Authenticator",
"id": 15,
"eepromAddress": -1,
"readOnly": false,
"localOnly": false,
"visible": true
}
}
],
"codeOptions": {
"embeddedPlatform": "STM32DUINO",
"lastDisplayUuid": "fd998437-c4b2-4386-ba88-d0ae7c20620b",
"lastInputUuid": "6dd87e7d-e751-4912-a70d-91793b1d3d87",
"lastRemoteUuid": "2c101fec-1f7d-4ff3-8d2b-992ad41e7fcb",
"lastRemoteUuids": [
"2c101fec-1f7d-4ff3-8d2b-992ad41e7fcb"
],
"lastThemeUuid": "0dd60ceb-7e0f-46e2-8d40-b264eb3aa7e0",
"applicationUUID": "ecd5607f-55eb-4252-a512-aab769452dd3",
"applicationName": "stm32DuinoDemo",
"lastProperties": [
{
"name": "DISPLAY_VARIABLE",
"latestValue": "gfx",
"subsystem": "DISPLAY"
},
{
"name": "DISPLAY_TYPE",
"latestValue": "U8G2_SSD1306_128X64_NONAME_F_HW_I2C",
"subsystem": "DISPLAY"
},
{
"name": "DISPLAY_ROTATION",
"latestValue": "U8G2_R0",
"subsystem": "DISPLAY"
},
{
"name": "DISPLAY_CLOCK_PIN",
"latestValue": "PB8",
"subsystem": "DISPLAY"
},
{
"name": "DISPLAY_DATA_PIN",
"latestValue": "PB9",
"subsystem": "DISPLAY"
},
{
"name": "DISPLAY_RESET_PIN",
"latestValue": "U8X8_PIN_NONE",
"subsystem": "DISPLAY"
},
{
"name": "DISPLAY_CS_PIN",
"latestValue": "PF13",
"subsystem": "DISPLAY"
},
{
"name": "DISPLAY_RS_PIN",
"latestValue": "PD15",
"subsystem": "DISPLAY"
},
{
"name": "UPDATES_PER_SEC",
"latestValue": "5",
"subsystem": "DISPLAY"
},
{
"name": "YIELDING_WIRE_CB",
"latestValue": "true",
"subsystem": "DISPLAY"
},
{
"name": "SW_POLLING_MODE",
"latestValue": "SWITCHES_POLL_EVERYTHING",
"subsystem": "INPUT"
},
{
"name": "SWITCH_IODEVICE",
"latestValue": "devicePins",
"subsystem": "INPUT"
},
{
"name": "ENCODER_PIN_A",
"latestValue": "PB14",
"subsystem": "INPUT"
},
{
"name": "ENCODER_PIN_B",
"latestValue": "PB13",
"subsystem": "INPUT"
},
{
"name": "ENCODER_PIN_OK",
"latestValue": "PB12",
"subsystem": "INPUT"
},
{
"name": "ENCODER_BACK_PIN",
"latestValue": "-1",
"subsystem": "INPUT"
},
{
"name": "ENCODER_NEXT_PIN",
"latestValue": "-1",
"subsystem": "INPUT"
},
{
"name": "PULLUP_LOGIC",
"latestValue": "true",
"subsystem": "INPUT"
},
{
"name": "ENCODER_IS_QUARTER_CYCLE",
"latestValue": "false",
"subsystem": "INPUT"
},
{
"name": "ITEM_FONT",
"latestValue": "def:,1",
"subsystem": "THEME"
},
{
"name": "TITLE_FONT",
"latestValue": "avl:u8g2_font_prospero_bold_nbp_tr,1",
"subsystem": "THEME"
},
{
"name": "TITLE_HEADER_PADDING",
"latestValue": "1",
"subsystem": "THEME"
},
{
"name": "TITLE_TO_ITEM_SPACING",
"latestValue": "0",
"subsystem": "THEME"
},
{
"name": "TITLE_SHOW_MODE",
"latestValue": "TITLE_ALWAYS",
"subsystem": "THEME"
}
],
"namingRecursive": true,
"saveToSrc": false,
"useCppMain": false,
"eepromDefinition": "",
"authenticatorDefinition": "",
"projectIoExpanders": [
"deviceIO:"
],
"menuInMenuCollection": {
"menuDefinitions": []
},
"packageNamespace": "",
"appIsModular": false
}
}
The resulting code, ran in Arduino 1.8.18 for a "BlackPill F401CC", gives the following error:
c:/users/user/appdata/local/arduino15/packages/stmicroelectronics/tools/xpack-arm-none-eabi-gcc/9.3.1-1.3/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld.exe: sketch\objs.a(Test1_menu.cpp.o): in function `_GLOBAL__sub_I_defaultItemPaletteMono':
Test1_menu.cpp:(.text.startup._GLOBAL__sub_I_defaultItemPaletteMono+0x228): undefined reference to `ramDataSet'
collect2.exe: error: ld returned 1 exit status
exit status 1
Error compiling for board Generic STM32F4 series.
It seems the solution was to add the following line to the main INO file, to mimic the example
// 0123456789 0123456789 0123456789 0123456789 0123456789
const char* ramDataSet = "Item 1\0 Item 2\0 Item 3\0 Item 4\0 Item 5\0 ";
|
|
|
Good afternoon,
I have been looking at your library for a couple of days, and I believe it will be an ideal solution for the User Interface to be used in the PolyFormer project
I'm currently testing this on the Arduino IDE (on both a STM32F401 and a STM32G0B1), using the 'stm32DuinoDemo' example (only commenting out the ethernet.begin and subsequent 3 lines), however I'm currently getting the error ''HalStm32EepromAbstraction' does not name a type;'
I have even tried to compile if for the MCU listed in the supported hardware list STM32F439(ZGTx,ZITx,ZGYx and ZIYx) all show the same error
Using the menu builder also results in the same error, please can you advise what I am doing wrong, and how to resolve the compilation error?
Arduino IDE is 1.8.19
Libraries are the following:
TcMenu - 2.3.1
IoAbstraction 2.3.1
LiquidCrystalIO 1.4.1
TaskManagerIO 1.3.3
SimpleCollections 1.2.0
TcMenuDesigner 2.3.1
Many thanks
Alextrical
Arduino error output:
stm32DuinoDemo_menu.cpp:17:1: error: 'HalStm32EepromAbstraction' does not name a type; did you mean 'EepromAbstraction'?
17 | HalStm32EepromAbstraction glBspRom;
| ^~~~~~~~~~~~~~~~~~~~~~~~~
| EepromAbstraction
C:\Users\user\AppData\Local\Temp\arduino_modified_sketch_680963\stm32DuinoDemo_menu.cpp: In function 'void setupMenu()':
stm32DuinoDemo_menu.cpp:65:5: error: 'glBspRom' was not declared in this scope
65 | glBspRom.initialise(0);
| ^~~~~~~~
C:\Users\user\AppData\Local\Temp\arduino_modified_sketch_680963\stm32DuinoDemo.ino: In function 'void saveWasPressed(int)':
stm32DuinoDemo:118:43: error: 'HalStm32EepromAbstraction' does not name a type; did you mean 'EepromAbstraction'?
118 | auto bspBackupRam = reinterpret_cast<HalStm32EepromAbstraction*>(menuMgr.getEepromAbstraction());
| ^~~~~~~~~~~~~~~~~~~~~~~~~
| EepromAbstraction
stm32DuinoDemo:118:68: error: expected '>' before '*' token
118 | auto bspBackupRam = reinterpret_cast<HalStm32EepromAbstraction*>(menuMgr.getEepromAbstraction());
| ^
stm32DuinoDemo:118:68: error: expected '(' before '*' token
118 | auto bspBackupRam = reinterpret_cast<HalStm32EepromAbstraction*>(menuMgr.getEepromAbstraction());
| ^
| (
stm32DuinoDemo:118:69: error: expected primary-expression before '>' token
118 | auto bspBackupRam = reinterpret_cast<HalStm32EepromAbstraction*>(menuMgr.getEepromAbstraction());
| ^
stm32DuinoDemo:118:102: error: expected ')' before ';' token
118 | auto bspBackupRam = reinterpret_cast<HalStm32EepromAbstraction*>(menuMgr.getEepromAbstraction());
| ^
| )
exit status 1
'HalStm32EepromAbstraction' does not name a type; did you mean 'EepromAbstraction'?
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
STM32DuinoDemo.ino
/**
* This is a simple demo application for Stm32Duino based boards. It just showcases many of the types of editor that
* are available. By default it is setup for an OLED screen and a rotary encoder, although it could be moved to use
* many other different display and input technologies.
*/
#include "stm32DuinoDemo_menu.h"
#include <PlatformDetermination.h>
#include <SPI.h>
#include <TaskManagerIO.h>
// 0123456789 0123456789 0123456789 0123456789 0123456789
const char* ramDataSet = "Item 1\0 Item 2\0 Item 3\0 Item 4\0 Item 5\0 ";
class MyCustomDrawing : public CustomDrawing {
private:
GraphicsDeviceRenderer& dev;
int ticks;
public:
MyCustomDrawing(GraphicsDeviceRenderer& r) : dev(r), ticks(0) {}
void registerWithRenderer() {
dev.setCustomDrawingHandler(this);
}
void started(BaseMenuRenderer *currentRenderer) override {
// called once when the take-over display is started before calling renderLoop so you can set things up.
switches.getEncoder()->changePrecision(100, 50);
}
void reset() override {
// called whenever the display is reset, IE times out on editing etc.
}
void renderLoop(unsigned int currentValue, RenderPressMode userClick) override {
// called in a game loop between takeOverDisplay and giveBackDisplay, at this point you renderer the display.
if(userClick == RPRESS_PRESSED) {
dev.giveBackDisplay();
}
else if(++ticks % 10 == 1) {
// Why write your own code using device drawable? The main reason is, that it works exactly the same over
// adafruit, u8g2 and TFTeSPI with a moderately complete API.
DeviceDrawable *dd = dev.getDeviceDrawable();
dd->startDraw();
const Coord &dims = dd->getDisplayDimensions();
dd->setDrawColor(BLACK);
dd->drawBox(Coord(0, 0), dims, true);
dd->setColors(WHITE, BLACK);
auto height = int(dims.y) - 16;
int width = int(dims.x) - 20;
dd->drawText(Coord(rand() % width, (rand() % height) + 10), nullptr, 1, "hello");
dd->drawText(Coord(rand() % width, (rand() % height) + 10), nullptr, 1, "world");
char sz[10];
ltoaClrBuff(sz, currentValue, 4, NOT_PADDED, sizeof sz);
dd->drawText(Coord(0, 0), nullptr, 1, sz);
dd->endDraw();
}
}
} myCustomDrawing(renderer);
void setup() {
// Start up serial and prepare the correct SPI
Serial.begin(115200);
SPI.setMISO(PB4);
SPI.setMOSI(PB5);
SPI.setSCLK(PB3);
// Now start up the ethernet library.
// Ethernet.begin();
// Serial.print("My IP address is ");
// Ethernet.localIP().printTo(Serial);
// Serial.println();
// and then run the menu setup
setupMenu();
menuMgr.load();
myCustomDrawing.registerWithRenderer();
setTitlePressedCallback([](int) {
renderer.takeOverDisplay();
});
}
void loop() {
taskManager.runLoop();
}
// see tcMenu list documentation on thecoderscorner.com
int CALLBACK_FUNCTION fnRuntimesCustomListRtCall(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize) {
switch(mode) {
case RENDERFN_INVOKE:
// TODO - your code to invoke goes here - row is the index of the item
return true;
case RENDERFN_NAME:
// TODO - each row has it's own name - 0xff is the parent item
ltoaClrBuff(buffer, row, 3, NOT_PADDED, bufferSize);
return true;
case RENDERFN_VALUE:
// TODO - each row can has its own value - 0xff is the parent item
buffer[0] = 'V'; buffer[1]=0;
fastltoa(buffer, row, 3, NOT_PADDED, bufferSize);
return true;
case RENDERFN_EEPROM_POS: return 0xffff; // lists are generally not saved to EEPROM
default: return false;
}
}
void CALLBACK_FUNCTION decimalDidChange(int id) {
// TODO - your menu change code
}
void CALLBACK_FUNCTION saveWasPressed(int id) {
auto bspBackupRam = reinterpret_cast<HalStm32EepromAbstraction*>(menuMgr.getEepromAbstraction());
menuMgr.save();
bspBackupRam->commit();
}
void CALLBACK_FUNCTION largeNumDidChange(int id) {
// TODO - your menu change code
}
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ThemeMonoBoarder.h
#ifndef TCMENU_THEME_MONO_BORDER
#define TCMENU_THEME_MONO_BORDER
color_t defaultItemPaletteMono[] = {WHITE, BLACK, WHITE, WHITE};
#define TITLE_BORDER_THICKNESS 2
#define TITLE_SPACING 2
void installMonoBorderedTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) {
bgr.setDisplayDimensions(bgr.getDeviceDrawable()->getDisplayDimensions().x, bgr.getDeviceDrawable()->getDisplayDimensions().y);
auto& factory = bgr.getGraphicsPropertiesFactory();
factory.setSelectedColors(0, 1);
MenuPadding titlePadding(1);
MenuPadding itemPadding(1);
int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding);
int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding);
factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResEditingIcon));
factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResActiveIcon));
factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, defaultItemPaletteMono, titlePadding, titleFont.fontData, titleFont.fontMag,
TITLE_SPACING, titleHeight + 1, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE,
MenuBorder(0, 0, TITLE_BORDER_THICKNESS, 0));
factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag,
1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT , MenuBorder(0));
factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag,
1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0));
tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache();
}
#endif //TCMENU_THEME_MONO_BORDER
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
stm32DunioDeom-menu.cpp
/*
The code in this file uses open source libraries provided by thecoderscorner
DO NOT EDIT THIS FILE, IT WILL BE GENERATED EVERY TIME YOU USE THE UI DESIGNER
INSTEAD EITHER PUT CODE IN YOUR SKETCH OR CREATE ANOTHER SOURCE FILE.
All the variables you may need access to are marked extern in this file for easy
use elsewhere.
*/
#include <tcMenu.h>
#include "stm32DuinoDemo_menu.h"
#include "ThemeMonoBordered.h"
// Global variable declarations
const ConnectorLocalInfo applicationInfo = { "stm32DuinoDemo", "ecd5607f-55eb-4252-a512-aab769452dd3" };
HalStm32EepromAbstraction glBspRom;
EepromAuthenticatorManager authManager(4);
U8G2_SSD1306_128X64_NONAME_F_HW_I2C gfx(U8G2_R2, U8X8_PIN_NONE, PB8, PB9);
U8g2Drawable gfxDrawable(&gfx);
GraphicsDeviceRenderer renderer(30, applicationInfo.name, &gfxDrawable);
// Global Menu Item declarations
const char pgmStrRuntimesAuthenticatorText[] = { "Authenticator" };
EepromAuthenticationInfoMenuItem menuRuntimesAuthenticator(pgmStrRuntimesAuthenticatorText, NO_CALLBACK, 15, NULL);
const char pgmStrRuntimesIoTMonitorText[] = { "IoT Monitor" };
RemoteMenuItem menuRuntimesIoTMonitor(pgmStrRuntimesIoTMonitorText, 14, &menuRuntimesAuthenticator);
ListRuntimeMenuItem menuRuntimesCustomList(13, 0, fnRuntimesCustomListRtCall, &menuRuntimesIoTMonitor);
RENDERING_CALLBACK_NAME_INVOKE(fnRuntimesTextRtCall, textItemRenderFn, "Text", 18, NO_CALLBACK)
TextMenuItem menuRuntimesText(fnRuntimesTextRtCall, 12, 5, &menuRuntimesCustomList);
RENDERING_CALLBACK_NAME_INVOKE(fnRuntimesRtCall, backSubItemRenderFn, "Runtimes", -1, NO_CALLBACK)
const SubMenuInfo minfoRuntimes = { "Runtimes", 11, 0xffff, 0, NO_CALLBACK };
BackMenuItem menuBackRuntimes(fnRuntimesRtCall, &menuRuntimesText);
SubMenuItem menuRuntimes(&minfoRuntimes, &menuBackRuntimes, NULL);
extern const char* ramDataSet;
RENDERING_CALLBACK_NAME_INVOKE(fnMoreItemsScrollRtCall, enumItemRenderFn, "Scroll", -1, NO_CALLBACK)
ScrollChoiceMenuItem menuMoreItemsScroll(10, fnMoreItemsScrollRtCall, 0, ramDataSet, 10, 5, NULL);
const FloatMenuInfo minfoMoreItemsNumber = { "Number", 9, 0xffff, 2, NO_CALLBACK };
FloatMenuItem menuMoreItemsNumber(&minfoMoreItemsNumber, &menuMoreItemsScroll);
const AnyMenuInfo minfoMoreItemsPressMe = { "Save", 8, 0xffff, 0, saveWasPressed };
ActionMenuItem menuMoreItemsPressMe(&minfoMoreItemsPressMe, &menuMoreItemsNumber);
const BooleanMenuInfo minfoMoreItemsPower = { "Power", 7, 17, 1, NO_CALLBACK, NAMING_ON_OFF };
BooleanMenuItem menuMoreItemsPower(&minfoMoreItemsPower, false, &menuMoreItemsPressMe);
const BooleanMenuInfo minfoMoreItemsToppings = { "Toppings", 6, 16, 1, NO_CALLBACK, NAMING_YES_NO };
BooleanMenuItem menuMoreItemsToppings(&minfoMoreItemsToppings, false, &menuMoreItemsPower);
const char enumStrMoreItemsOptions_0[] = "Pizza";
const char enumStrMoreItemsOptions_1[] = "Pasta";
const char enumStrMoreItemsOptions_2[] = "Salad";
const char* const enumStrMoreItemsOptions[] = { enumStrMoreItemsOptions_0, enumStrMoreItemsOptions_1, enumStrMoreItemsOptions_2 };
const EnumMenuInfo minfoMoreItemsOptions = { "Options", 5, 14, 2, NO_CALLBACK, enumStrMoreItemsOptions };
EnumMenuItem menuMoreItemsOptions(&minfoMoreItemsOptions, 0, &menuMoreItemsToppings);
RENDERING_CALLBACK_NAME_INVOKE(fnMoreItemsRtCall, backSubItemRenderFn, "More Items", -1, NO_CALLBACK)
const SubMenuInfo minfoMoreItems = { "More Items", 4, 0xffff, 0, NO_CALLBACK };
BackMenuItem menuBackMoreItems(fnMoreItemsRtCall, &menuMoreItemsOptions);
SubMenuItem menuMoreItems(&minfoMoreItems, &menuBackMoreItems, &menuRuntimes);
RENDERING_CALLBACK_NAME_INVOKE(fnLgeNumRtCall, largeNumItemRenderFn, "Lge Num", 6, largeNumDidChange)
EditableLargeNumberMenuItem menuLgeNum(fnLgeNumRtCall, 3, 9, 3, true, &menuMoreItems);
const AnalogMenuInfo minfoHalves = { "Halves", 2, 4, 255, NO_CALLBACK, 0, 2, "dB" };
AnalogMenuItem menuHalves(&minfoHalves, 0, &menuLgeNum);
const AnalogMenuInfo minfoDecimal = { "Decimal", 1, 2, 1000, decimalDidChange, 0, 10, "d" };
AnalogMenuItem menuDecimal(&minfoDecimal, 0, &menuHalves);
void setupMenu() {
// First we set up eeprom and authentication (if needed).
glBspRom.initialise(0);
menuMgr.setEepromRef(&glBspRom);
authManager.initialise(menuMgr.getEepromAbstraction(), 150);
menuMgr.setAuthenticator(&authManager);
// Code generated by plugins.
gfx.begin();
renderer.setUpdatesPerSecond(10);
switches.init(internalDigitalIo(), SWITCHES_NO_POLLING, true);
menuMgr.initForEncoder(&renderer, &menuDecimal, PB13, PB14, PB12, QUARTER_CYCLE);
renderer.setTitleMode(BaseGraphicalRenderer::TITLE_ALWAYS);
renderer.setUseSliderForAnalog(false);
installMonoBorderedTheme(renderer, MenuFontDef(nullptr, 1), MenuFontDef(u8g2_font_prospero_bold_nbp_tr, 1), true);
}
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
stm32DuinoDemo_menu.h
/*
The code in this file uses open source libraries provided by thecoderscorner
DO NOT EDIT THIS FILE, IT WILL BE GENERATED EVERY TIME YOU USE THE UI DESIGNER
INSTEAD EITHER PUT CODE IN YOUR SKETCH OR CREATE ANOTHER SOURCE FILE.
All the variables you may need access to are marked extern in this file for easy
use elsewhere.
*/
#ifndef MENU_GENERATED_CODE_H
#define MENU_GENERATED_CODE_H
#include <Arduino.h>
#include <tcMenu.h>
#include "tcMenuU8g2.h"
#include <RemoteMenuItem.h>
#include <RuntimeMenuItem.h>
#include <ScrollChoiceMenuItem.h>
#include <EditableLargeNumberMenuItem.h>
#include <IoAbstraction.h>
#include <mbed/HalStm32EepromAbstraction.h>
#include <RemoteAuthentication.h>
// variables we declare that you may need to access
extern const PROGMEM ConnectorLocalInfo applicationInfo;
extern U8G2_SSD1306_128X64_NONAME_F_HW_I2C gfx;
extern GraphicsDeviceRenderer renderer;
// Any externals needed by IO expanders, EEPROMs etc
// Global Menu Item exports
extern EepromAuthenticationInfoMenuItem menuRuntimesAuthenticator;
extern RemoteMenuItem menuRuntimesIoTMonitor;
extern ListRuntimeMenuItem menuRuntimesCustomList;
extern TextMenuItem menuRuntimesText;
extern BackMenuItem menuBackRuntimes;
extern SubMenuItem menuRuntimes;
extern ScrollChoiceMenuItem menuMoreItemsScroll;
extern FloatMenuItem menuMoreItemsNumber;
extern ActionMenuItem menuMoreItemsPressMe;
extern BooleanMenuItem menuMoreItemsPower;
extern BooleanMenuItem menuMoreItemsToppings;
extern EnumMenuItem menuMoreItemsOptions;
extern BackMenuItem menuBackMoreItems;
extern SubMenuItem menuMoreItems;
extern EditableLargeNumberMenuItem menuLgeNum;
extern AnalogMenuItem menuHalves;
extern AnalogMenuItem menuDecimal;
// Provide a wrapper to get hold of the root menu item and export setupMenu
inline MenuItem& rootMenuItem() { return menuDecimal; }
void setupMenu();
// Callback functions must always include CALLBACK_FUNCTION after the return type
#define CALLBACK_FUNCTION
void CALLBACK_FUNCTION decimalDidChange(int id);
int fnRuntimesCustomListRtCall(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize);
void CALLBACK_FUNCTION largeNumDidChange(int id);
void CALLBACK_FUNCTION saveWasPressed(int id);
#endif // MENU_GENERATED_CODE_H
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
tcMenuU8g2.cpp
/*
* Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry).
* This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
*/
/**
* @file tcMenuU8g2.h
*
* U8g2 renderer that renders menus onto this type of display. This file is a plugin file and should not
* be directly edited, it will be replaced each time the project is built. If you want to edit this file in place,
* make sure to rename it first.
*
* LIBRARY REQUIREMENT
* This library requires the u8g2 library available for download from your IDE library manager.
*/
#include <U8g2lib.h>
#include <Wire.h>
#include "tcMenuU8g2.h"
const uint8_t* safeGetFont(const void* fnt) {
if(fnt) return static_cast<const uint8_t *>(fnt);
return u8g2_font_6x10_tf;
}
#if WANT_TASK_MANAGER_FRIENDLY_YIELD == 1
static uint8_t bytesSent = 0;
TwoWire* U8g2Drawable::pWire = nullptr;
uint8_t u8g2_byte_with_yield(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {
if(!U8g2Drawable::pWire) return 0;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
bytesSent+= arg_int;
U8g2Drawable::pWire->write((uint8_t *)arg_ptr, (int)arg_int);
if(bytesSent > 16) {
taskManager.yieldForMicros(0);
bytesSent = 0;
}
break;
case U8X8_MSG_BYTE_START_TRANSFER:
U8g2Drawable::pWire->beginTransmission(u8x8_GetI2CAddress(u8x8)>>1);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
U8g2Drawable::pWire->endTransmission();
break;
case U8X8_MSG_BYTE_INIT:
case U8X8_MSG_BYTE_SET_DC:
break;
default:
return 0;
}
return 1;
}
#endif // WANT_TASK_MANAGER_FRIENDLY_YIELD
U8g2Drawable::U8g2Drawable(U8G2 *u8g2, TwoWire* wireImpl) : u8g2(u8g2) {
#if WANT_TASK_MANAGER_FRIENDLY_YIELD == 1
pWire = wireImpl;
if(wireImpl) {
u8g2->getU8x8()->byte_cb = u8g2_byte_with_yield;
}
#endif
}
void U8g2Drawable::drawText(const Coord &where, const void *font, int mag, const char *text) {
u8g2->setFont(safeGetFont(font));
u8g2->setFontMode(drawColor == 2);
auto extraHeight = u8g2->getMaxCharHeight();
u8g2->setDrawColor(drawColor);
u8g2->setCursor(where.x, where.y + extraHeight);
u8g2->print(text);
}
void U8g2Drawable::drawBitmap(const Coord &where, const DrawableIcon *icon, bool selected) {
u8g2->setDrawColor(backgroundColor);
u8g2->drawBox(where.x, where.y, icon->getDimensions().x, icon->getDimensions().y);
u8g2->setDrawColor(drawColor);
if(icon->getIconType() == DrawableIcon::ICON_XBITMAP) {
#if defined(__AVR__) || defined(ESP8266)
u8g2->drawXBMP(where.x, where.y, icon->getDimensions().x, icon->getDimensions().y, icon->getIcon(selected));
#else
u8g2->drawXBM(where.x, where.y, icon->getDimensions().x, icon->getDimensions().y, icon->getIcon(selected));
#endif
}
}
void U8g2Drawable::drawXBitmap(const Coord &where, const Coord &size, const uint8_t *data) {
u8g2->setDrawColor(backgroundColor);
u8g2->drawBox(where.x, where.y, size.x, size.y);
u8g2->setDrawColor(drawColor);
#if defined(__AVR__) || defined(ESP8266)
u8g2->drawXBMP(where.x, where.y, size.x, size.y, data);
#else
u8g2->drawXBM(where.x, where.y, size.x, size.y, data);
#endif
}
void U8g2Drawable::drawBox(const Coord &where, const Coord &size, bool filled) {
u8g2->setDrawColor(drawColor);
if(filled) {
u8g2->drawBox(where.x, where.y, size.x, size.y);
}
else {
u8g2->drawFrame(where.x, where.y, size.x, size.y);
}
}
void U8g2Drawable::drawCircle(const Coord &where, int radius, bool filled) {
u8g2->setDrawColor(drawColor);
u8g2->drawCircle(where.x, where.y, radius);
}
void U8g2Drawable::drawPolygon(const Coord *points, int numPoints, bool filled) {
if(numPoints == 2) {
u8g2->drawLine(points[0].x, points[0].y, points[1].x, points[1].y);
}
else if(numPoints == 3) {
u8g2->drawTriangle(points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y);
}
}
void U8g2Drawable::transaction(bool isStarting, bool redrawNeeded) {
if(isStarting) {
u8g2->setFontPosBottom();
u8g2->setFontRefHeightExtendedText();
}
else if(redrawNeeded) {
u8g2->sendBuffer();
}
}
Coord U8g2Drawable::textExtents(const void *font, int mag, const char *text, int *baseline) {
u8g2->setFont(safeGetFont(font));
if(baseline) *baseline = (int)u8g2->getFontDescent();
return Coord(u8g2->getStrWidth(text), u8g2->getMaxCharHeight());
}
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
tcMenuU8g2.h
/*
* Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry).
* This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
*/
/**
* @file tcMenuU8g2.h
*
* U8g2 renderer that renders menus onto this type of display. This file is a plugin file and should not
* be directly edited, it will be replaced each time the project is built. If you want to edit this file in place,
* make sure to rename it first.
*
* LIBRARY REQUIREMENT
* This library requires the u8g2 library available for download from your IDE library manager.
*/
#ifndef _TCMENU_U8G2_H_
#define _TCMENU_U8G2_H_
#include <tcMenu.h>
#include <tcUtil.h>
#include <Wire.h>
#include <U8g2lib.h>
#include <graphics/BaseGraphicalRenderer.h>
#include <graphics/GraphicsDeviceRenderer.h>
#include <BaseDialog.h>
#include <tcUtil.h>
// If you DONT want task manager yield code in I2C set to 0
#ifndef WANT_TASK_MANAGER_FRIENDLY_YIELD
#define WANT_TASK_MANAGER_FRIENDLY_YIELD 0
#endif // WANT_TASK_MANAGER_FRIENDLY_YIELD
using namespace tcgfx;
/**
* A standard menu render configuration that describes how to renderer each item and the title.
* Specialised for u8g2 fonts.
*/
typedef struct ColorGfxMenuConfig<const uint8_t*> U8g2GfxMenuConfig;
// some colour displays don't create this value
#ifndef BLACK
#define BLACK 0
#endif
// some colour displays don't create this value
#ifndef WHITE
#define WHITE 1
#endif
/**
* This is used to draw to I2C including a task manager yield to improve performance on slower I2C devices.
* Not really needed for SPI as we are talking in low order millis for a full refresh.
*/
uint8_t u8g2_byte_with_yield(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
/**
* A basic renderer that can use the AdaFruit_GFX library to render information onto a suitable
* display. It is your responsibility to fully initialise and prepare the display before passing
* it to this renderer. The usual procedure is to create a display variable globally in your
* sketch and then provide that as the parameter to setGraphicsDevice. If you are using the
* designer you provide the display variable name in the code generation parameters.
*
* You can also override many elements of the display using AdaColorGfxMenuConfig, to use the defaults
* just call prepareAdaColorDefaultGfxConfig(..) passing it a pointer to your config object. Again the
* designer UI takes care of this.
*/
class U8g2Drawable : public DeviceDrawable {
private:
U8G2* u8g2;
#if WANT_TASK_MANAGER_FRIENDLY_YIELD == 1
static TwoWire* pWire;
friend uint8_t u8g2_byte_with_yield(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
#endif // WANT_TASK_MANAGER_FRIENDLY_YIELD
public:
explicit U8g2Drawable(U8G2* u8g2, TwoWire* wire = nullptr);
~U8g2Drawable() override = default;
DeviceDrawable* getSubDeviceFor(const Coord &where, const Coord &size, const color_t *palette, int paletteSize) override {return nullptr; }
void drawText(const Coord &where, const void *font, int mag, const char *text) override;
void drawBitmap(const Coord &where, const DrawableIcon *icon, bool selected) override;
void drawXBitmap(const Coord &where, const Coord &size, const uint8_t *data) override;
void drawBox(const Coord &where, const Coord &size, bool filled) override;
void drawCircle(const Coord &where, int radius, bool filled) override;
void drawPolygon(const Coord *points, int numPoints, bool filled) override;
Coord getDisplayDimensions() override { return Coord(u8g2->getWidth(), u8g2->getHeight()); }
void transaction(bool isStarting, bool redrawNeeded) override;
Coord textExtents(const void *font, int mag, const char *text, int *baseline) override;
color_t getUnderlyingColor(color_t col) { return (col<4) ? col : 1; }
};
#endif // _TCMENU_U8G2_H_
|
|
|
|
|