[Logo] TCC discussion forum
  [Search] Search   [Recent Topics] Recent Topics   [Hottest Topics] Hottest Topics   [Top Downloads] Top Downloads   [Groups] Back to home page 
[Register] Register /  [Login] Login 


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.

STM32F401 / STM32G0B1 not compiling in Arduino IDE. Error:HalStm32EepromAbstraction RSS feed
Forum Index » tcMenu Arduinio library
Author Message
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'?


--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
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_
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.

If you take a look at

https://github.com/davetcc/IoAbstraction/blob/master/src/mbed/HalStm32EepromAbstraction.h#L16

and

https://github.com/davetcc/IoAbstraction/blob/master/src/mbed/HalStm32EepromAbstraction.cpp#L6

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
{
  "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   ";
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:

https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/menu-item-types/scrollchoice-menu-item/
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

Edit: Just saw your response, ignore this message
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:

https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/menu-item-types/scrollchoice-menu-item/


Awesome, thank you.
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.

https://github.com/davetcc/tcMenu/issues/216

Should be quite simple and go into the next release.
 
Forum Index » tcMenu Arduinio library
Go to:   
Mobile view
Powered by JForum 2.7.0 © 2020 JForum Team • Maintained by Andowson Chang and Ulf Dittmer

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.

Our privacy policy applies to all pages on our site

Should you need further guidance on how to proceed: External link for information about cookie management.