This forum is read only and new users cannot register, please ask all new questions either using GitHub discussions, or in Arduino forum tagging @davetcc.
Alextrical Joined: Aug 1, 2022 Messages: 4 Offline
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'?
/**
* 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
}
/*
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
/*
* 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_
davetcc Joined: Jan 19, 2019 Messages: 686 Offline
I've taken a look now, and there's a protection statement around the class because it requires BSP headers to be available for the board.
I question if the protection define is really required, as it may be causing more harm than good, especially if you're using Arduino IDE as you can't add a define at compile time.
the error is because the code is not being included due to the define. The problem is that without the define, the code would attempt to compile whenever we detected Stm32Duino (or a suitable mbed board) and the BSP header needed by not be there. However, needing the define means that user hit this error unless the define is added.
For now, you can either add the compiler flag, or if you're using the standard IDE, just above the check in the header file, add
#define IOA_ENABLE_STM32_HAL_EXTRAS
This needs a bit more thought, it's trival for platformIO and mbed users, as they can easily add an extra build flag, but for Arduino IDE it is more difficult.
davetcc Joined: Jan 19, 2019 Messages: 686 Offline
As a bit more detail, not everyone would want to use the battery-backed ram segment as EEPROM, and I don't think that all boards supported by Stm32Duino even have that available to them. As a result of this, I added that extra define to prevent it from attempting to bring in the BSP headers on boards that may not support that feature, or have slightly different capabilities. It is always a balance in these cases between supporting as many features as possible, and it not breaking for other users.
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.
davetcc Joined: Jan 19, 2019 Messages: 686 Offline
Seems like a very interesting project BTW. Always happy to help other open source projects.
Maybe the thing here is that I've baked something pretty custom into an example, that requires advanced features of the library that depend on specific boards to be enabled. Perhaps the example shouldn't use the BSP EEPROM to make it easier to get started.
Any feedback you have on how we could better handle that BSP support from a user perspective would also very welcome.
Alextrical Joined: Aug 1, 2022 Messages: 4 Offline
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
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
davetcc Joined: Jan 19, 2019 Messages: 686 Offline
Yes, it is the scroll item that caused that, if you choose the array in RAM option, it requires you to define the array yourself, you can read about scroll items here:
Alextrical Joined: Aug 1, 2022 Messages: 4 Offline
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
Alextrical Joined: Aug 1, 2022 Messages: 4 Offline
davetcc wrote:Yes, it is the scroll item that caused that, if you choose the array in RAM option, it requires you to define the array yourself, you can read about scroll items here:
davetcc Joined: Jan 19, 2019 Messages: 686 Offline
Yes, RAM scroll choices are a bit tricky, I'll add an issue to autogenerate the variable in the sketch/main unless it is prepended with an @ symbol, in which case it assumes you will define it somewhere else.
This site uses cookies to analyse traffic, serve ads by Google AdSense (non-personalized in EEA/UK),
and to record consent. We also embed Twitter, Youtube and Disqus content on some pages, these companies
have their own privacy policies.