mirror of
https://github.com/thooge/esp32-nmea2000-obp60.git
synced 2025-12-28 13:13:07 +01:00
Compare commits
3 Commits
7edd201daa
...
system
| Author | SHA1 | Date | |
|---|---|---|---|
| d5b0af3b19 | |||
| aed389f3b2 | |||
| 32ba4a64ed |
204
lib/obp60task/ConfigMenu.cpp
Normal file
204
lib/obp60task/ConfigMenu.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
Menu system for online configuration
|
||||
*/
|
||||
#include "ConfigMenu.h"
|
||||
|
||||
ConfigMenuItem::ConfigMenuItem(String itemtype, String itemlabel, uint16_t itemval, String itemunit) {
|
||||
if (! (itemtype == "int" or itemtype == "bool")) {
|
||||
valtype = "int";
|
||||
} else {
|
||||
valtype = itemtype;
|
||||
}
|
||||
label = itemlabel;
|
||||
min = 0;
|
||||
max = std::numeric_limits<uint16_t>::max();
|
||||
value = itemval;
|
||||
unit = itemunit;
|
||||
}
|
||||
|
||||
void ConfigMenuItem::setRange(uint16_t valmin, uint16_t valmax, std::vector<uint16_t> valsteps) {
|
||||
min = valmin;
|
||||
max = valmax;
|
||||
steps = valsteps;
|
||||
};
|
||||
|
||||
bool ConfigMenuItem::checkRange(uint16_t checkval) {
|
||||
return (checkval >= min) and (checkval <= max);
|
||||
}
|
||||
|
||||
String ConfigMenuItem::getLabel() {
|
||||
return label;
|
||||
};
|
||||
|
||||
uint16_t ConfigMenuItem::getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
bool ConfigMenuItem::setValue(uint16_t newval) {
|
||||
if (valtype == "int") {
|
||||
if (newval >= min and newval <= max) {
|
||||
value = newval;
|
||||
return true;
|
||||
}
|
||||
return false; // out of range
|
||||
} else if (valtype == "bool") {
|
||||
value = (newval != 0) ? 1 : 0;
|
||||
return true;
|
||||
}
|
||||
return false; // invalid type
|
||||
};
|
||||
|
||||
void ConfigMenuItem::incValue() {
|
||||
// increase value by step
|
||||
if (valtype == "int") {
|
||||
if (value + step < max) {
|
||||
value += step;
|
||||
} else {
|
||||
value = max;
|
||||
}
|
||||
} else if (valtype == "bool") {
|
||||
value = !value;
|
||||
}
|
||||
};
|
||||
|
||||
void ConfigMenuItem::decValue() {
|
||||
// decrease value by step
|
||||
if (valtype == "int") {
|
||||
if (value - step > min) {
|
||||
value -= step;
|
||||
} else {
|
||||
value = min;
|
||||
}
|
||||
} else if (valtype == "bool") {
|
||||
value = !value;
|
||||
}
|
||||
};
|
||||
|
||||
String ConfigMenuItem::getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
||||
uint16_t ConfigMenuItem::getStep() {
|
||||
return step;
|
||||
}
|
||||
|
||||
void ConfigMenuItem::setStep(uint16_t newstep) {
|
||||
if (std::find(steps.begin(), steps.end(), newstep) == steps.end()) {
|
||||
return; // invalid step: not in list of possible steps
|
||||
}
|
||||
step = newstep;
|
||||
}
|
||||
|
||||
int8_t ConfigMenuItem::getPos() {
|
||||
return position;
|
||||
};
|
||||
|
||||
void ConfigMenuItem::setPos(int8_t newpos) {
|
||||
position = newpos;
|
||||
};
|
||||
|
||||
String ConfigMenuItem::getType() {
|
||||
return valtype;
|
||||
}
|
||||
|
||||
ConfigMenu::ConfigMenu(String menutitle, uint16_t menu_x, uint16_t menu_y) {
|
||||
title = menutitle;
|
||||
x = menu_x;
|
||||
y = menu_y;
|
||||
};
|
||||
|
||||
ConfigMenuItem* ConfigMenu::addItem(String key, String label, String valtype, uint16_t val, String valunit) {
|
||||
if (items.find(key) != items.end()) {
|
||||
// duplicate keys not allowed
|
||||
return nullptr;
|
||||
}
|
||||
ConfigMenuItem *itm = new ConfigMenuItem(valtype, label, val, valunit);
|
||||
items.insert(std::pair<String, ConfigMenuItem*>(key, itm));
|
||||
// Append key to index, index starting with 0
|
||||
int8_t ix = items.size() - 1;
|
||||
index[ix] = key;
|
||||
itm->setPos(ix);
|
||||
return itm;
|
||||
};
|
||||
|
||||
void ConfigMenu::setItemDimension(uint16_t itemwidth, uint16_t itemheight) {
|
||||
w = itemwidth;
|
||||
h = itemheight;
|
||||
};
|
||||
|
||||
void ConfigMenu::setItemActive(String key) {
|
||||
if (items.find(key) != items.end()) {
|
||||
activeitem = items[key]->getPos();
|
||||
} else {
|
||||
activeitem = -1;
|
||||
}
|
||||
};
|
||||
|
||||
int8_t ConfigMenu::getActiveIndex() {
|
||||
return activeitem;
|
||||
}
|
||||
|
||||
ConfigMenuItem* ConfigMenu::getActiveItem() {
|
||||
if (activeitem < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return items[index[activeitem]];
|
||||
};
|
||||
|
||||
ConfigMenuItem* ConfigMenu::getItemByIndex(uint8_t ix) {
|
||||
if (ix > index.size() - 1) {
|
||||
return nullptr;
|
||||
}
|
||||
return items[index[ix]];
|
||||
};
|
||||
|
||||
ConfigMenuItem* ConfigMenu::getItemByKey(String key) {
|
||||
if (items.find(key) == items.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return items[key];
|
||||
};
|
||||
|
||||
uint8_t ConfigMenu::getItemCount() {
|
||||
return items.size();
|
||||
};
|
||||
|
||||
void ConfigMenu::goPrev() {
|
||||
if (activeitem == 0) {
|
||||
activeitem = items.size() - 1;
|
||||
} else {
|
||||
activeitem--;
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigMenu::goNext() {
|
||||
if (activeitem == items.size() - 1) {
|
||||
activeitem = 0;
|
||||
} else {
|
||||
activeitem++;
|
||||
}
|
||||
}
|
||||
|
||||
Point ConfigMenu::getXY() {
|
||||
return {static_cast<double>(x), static_cast<double>(y)};
|
||||
}
|
||||
|
||||
Rect ConfigMenu::getRect() {
|
||||
return {static_cast<double>(x), static_cast<double>(y),
|
||||
static_cast<double>(w), static_cast<double>(h)};
|
||||
}
|
||||
|
||||
Rect ConfigMenu::getItemRect(int8_t index) {
|
||||
return {static_cast<double>(x), static_cast<double>(y + index * h),
|
||||
static_cast<double>(w), static_cast<double>(h)};
|
||||
}
|
||||
|
||||
void ConfigMenu::setCallback(void (*callback)()) {
|
||||
fptrCallback = callback;
|
||||
}
|
||||
|
||||
void ConfigMenu::storeValues() {
|
||||
if (fptrCallback) {
|
||||
fptrCallback();
|
||||
}
|
||||
}
|
||||
66
lib/obp60task/ConfigMenu.h
Normal file
66
lib/obp60task/ConfigMenu.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "Graphics.h" // for Point and Rect
|
||||
|
||||
class ConfigMenuItem {
|
||||
private:
|
||||
String label;
|
||||
uint16_t value;
|
||||
String unit;
|
||||
String valtype; // "int" | "bool"
|
||||
uint16_t min;
|
||||
uint16_t max;
|
||||
std::vector<uint16_t> steps;
|
||||
uint16_t step;
|
||||
int8_t position; // counted fom 0
|
||||
|
||||
public:
|
||||
ConfigMenuItem(String itemtype, String itemlabel, uint16_t itemval, String itemunit);
|
||||
void setRange(uint16_t valmin, uint16_t valmax, std::vector<uint16_t> steps);
|
||||
bool checkRange(uint16_t checkval);
|
||||
String getLabel();
|
||||
uint16_t getValue();
|
||||
bool setValue(uint16_t newval);
|
||||
void incValue();
|
||||
void decValue();
|
||||
String getUnit();
|
||||
uint16_t getStep();
|
||||
void setStep(uint16_t newstep);
|
||||
int8_t getPos();
|
||||
void setPos(int8_t newpos);
|
||||
String getType();
|
||||
};
|
||||
|
||||
class ConfigMenu {
|
||||
private:
|
||||
String title;
|
||||
std::map <String,ConfigMenuItem*> items;
|
||||
std::map <uint8_t,String> index;
|
||||
int8_t activeitem = -1; // refers to position of item
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint16_t w;
|
||||
uint16_t h;
|
||||
void (*fptrCallback)();
|
||||
|
||||
public:
|
||||
ConfigMenu(String title, uint16_t menu_x, uint16_t menu_y);
|
||||
ConfigMenuItem* addItem(String key, String label, String valtype, uint16_t val, String valunit);
|
||||
void setItemDimension(uint16_t itemwidth, uint16_t itemheight);
|
||||
int8_t getActiveIndex();
|
||||
void setItemActive(String key);
|
||||
ConfigMenuItem* getActiveItem();
|
||||
ConfigMenuItem* getItemByIndex(uint8_t index);
|
||||
ConfigMenuItem* getItemByKey(String key);
|
||||
uint8_t getItemCount();
|
||||
void goPrev();
|
||||
void goNext();
|
||||
Point getXY();
|
||||
Rect getRect();
|
||||
Rect getItemRect(int8_t index);
|
||||
void setCallback(void (*callback)());
|
||||
void storeValues();
|
||||
};
|
||||
25
lib/obp60task/Graphics.cpp
Normal file
25
lib/obp60task/Graphics.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Generic graphics functions
|
||||
|
||||
*/
|
||||
#include <math.h>
|
||||
#include "Graphics.h"
|
||||
|
||||
Point rotatePoint(const Point& origin, const Point& p, double angle) {
|
||||
// rotate poind around origin by degrees
|
||||
Point rotated;
|
||||
double phi = angle * M_PI / 180.0;
|
||||
double dx = p.x - origin.x;
|
||||
double dy = p.y - origin.y;
|
||||
rotated.x = origin.x + cos(phi) * dx - sin(phi) * dy;
|
||||
rotated.y = origin.y + sin(phi) * dx + cos(phi) * dy;
|
||||
return rotated;
|
||||
}
|
||||
|
||||
std::vector<Point> rotatePoints(const Point& origin, const std::vector<Point>& pts, double angle) {
|
||||
std::vector<Point> rotatedPoints;
|
||||
for (const auto& p : pts) {
|
||||
rotatedPoints.push_back(rotatePoint(origin, p, angle));
|
||||
}
|
||||
return rotatedPoints;
|
||||
}
|
||||
17
lib/obp60task/Graphics.h
Normal file
17
lib/obp60task/Graphics.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
|
||||
struct Point {
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
|
||||
struct Rect {
|
||||
double x;
|
||||
double y;
|
||||
double w;
|
||||
double h;
|
||||
};
|
||||
|
||||
Point rotatePoint(const Point& origin, const Point& p, double angle);
|
||||
std::vector<Point> rotatePoints(const Point& origin, const std::vector<Point>& pts, double angle);
|
||||
@@ -14,6 +14,30 @@ https://controllerstech.com/ws2812-leds-using-spi/
|
||||
|
||||
*/
|
||||
|
||||
String Color::toHex() {
|
||||
char hexColor[8];
|
||||
sprintf(hexColor, "#%02X%02X%02X", r, g, b);
|
||||
return String(hexColor);
|
||||
}
|
||||
|
||||
String Color::toName() {
|
||||
static std::map<int, String> const names = {
|
||||
{0xff0000, "Red"},
|
||||
{0x00ff00, "Green"},
|
||||
{0x0000ff, "Blue",},
|
||||
{0xff9900, "Orange"},
|
||||
{0xffff00, "Yellow"},
|
||||
{0x3366ff, "Aqua"},
|
||||
{0xff0066, "Violet"},
|
||||
{0xffffff, "White"}
|
||||
};
|
||||
int color = (r << 16) + (g << 8) + b;
|
||||
auto it = names.find(color);
|
||||
if (it == names.end()) {
|
||||
return toHex();
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
static uint8_t mulcolor(uint8_t f1, uint8_t f2){
|
||||
uint16_t rt=f1;
|
||||
|
||||
@@ -10,7 +10,7 @@ class Color{
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
Color():r(0),g(0),b(0){}
|
||||
Color(uint8_t cr, uint8_t cg,uint8_t cb):
|
||||
Color(uint8_t cr, uint8_t cg, uint8_t cb):
|
||||
b(cb),g(cg),r(cr){}
|
||||
Color(const Color &o):b(o.b),g(o.g),r(o.r){}
|
||||
bool equal(const Color &o) const{
|
||||
@@ -22,6 +22,8 @@ class Color{
|
||||
bool operator != (const Color &other) const{
|
||||
return ! equal(other);
|
||||
}
|
||||
String toHex();
|
||||
String toName();
|
||||
};
|
||||
|
||||
static Color COLOR_GREEN=Color(0,255,0);
|
||||
|
||||
@@ -297,30 +297,20 @@ String xdrDelete(String input){
|
||||
return input;
|
||||
}
|
||||
|
||||
Point rotatePoint(const Point& origin, const Point& p, double angle) {
|
||||
// rotate poind around origin by degrees
|
||||
Point rotated;
|
||||
double phi = angle * M_PI / 180.0;
|
||||
double dx = p.x - origin.x;
|
||||
double dy = p.y - origin.y;
|
||||
rotated.x = origin.x + cos(phi) * dx - sin(phi) * dy;
|
||||
rotated.y = origin.y + sin(phi) * dx + cos(phi) * dy;
|
||||
return rotated;
|
||||
}
|
||||
|
||||
std::vector<Point> rotatePoints(const Point& origin, const std::vector<Point>& pts, double angle) {
|
||||
std::vector<Point> rotatedPoints;
|
||||
for (const auto& p : pts) {
|
||||
rotatedPoints.push_back(rotatePoint(origin, p, angle));
|
||||
}
|
||||
return rotatedPoints;
|
||||
}
|
||||
|
||||
void fillPoly4(const std::vector<Point>& p4, uint16_t color) {
|
||||
getdisplay().fillTriangle(p4[0].x, p4[0].y, p4[1].x, p4[1].y, p4[2].x, p4[2].y, color);
|
||||
getdisplay().fillTriangle(p4[0].x, p4[0].y, p4[2].x, p4[2].y, p4[3].x, p4[3].y, color);
|
||||
}
|
||||
|
||||
void drawPoly(const std::vector<Point>& points, uint16_t color) {
|
||||
size_t polysize = points.size();
|
||||
for (size_t i = 0; i < polysize - 1; i++) {
|
||||
getdisplay().drawLine(points[i].x, points[i].y, points[i+1].x, points[i+1].y, color);
|
||||
}
|
||||
// close path
|
||||
getdisplay().drawLine(points[polysize-1].x, points[polysize-1].y, points[0].x, points[0].y, color);
|
||||
}
|
||||
|
||||
// Split string into words, whitespace separated
|
||||
std::vector<String> split(const String &s) {
|
||||
std::vector<String> words;
|
||||
@@ -382,6 +372,24 @@ void drawTextRalign(int16_t x, int16_t y, String text) {
|
||||
getdisplay().print(text);
|
||||
}
|
||||
|
||||
// Draw text inside box, normal or inverted
|
||||
void drawTextBoxed(Rect box, String text, uint16_t fg, uint16_t bg, bool inverted, bool border) {
|
||||
if (inverted) {
|
||||
getdisplay().fillRect(box.x, box.y, box.w, box.h, fg);
|
||||
getdisplay().setTextColor(bg);
|
||||
} else {
|
||||
if (border) {
|
||||
getdisplay().fillRect(box.x + 1, box.y + 1, box.w - 2, box.h - 2, bg);
|
||||
getdisplay().drawRect(box.x, box.y, box.w, box.h, fg);
|
||||
}
|
||||
getdisplay().setTextColor(fg);
|
||||
}
|
||||
uint16_t border_offset = box.h / 4; // 25% of box height
|
||||
getdisplay().setCursor(box.x + border_offset, box.y + box.h - border_offset);
|
||||
getdisplay().print(text);
|
||||
getdisplay().setTextColor(fg);
|
||||
}
|
||||
|
||||
// Show a triangle for trend direction high (x, y is the left edge)
|
||||
void displayTrendHigh(int16_t x, int16_t y, uint16_t size, uint16_t color){
|
||||
getdisplay().fillTriangle(x, y, x+size*2, y, x+size, y-size*2, color);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <Arduino.h>
|
||||
#include "OBP60Hardware.h"
|
||||
#include "LedSpiTask.h"
|
||||
#include "Graphics.h"
|
||||
#include <GxEPD2_BW.h> // E-paper lib V2
|
||||
#include <Adafruit_FRAM_I2C.h> // I2C FRAM
|
||||
|
||||
@@ -62,13 +63,8 @@ GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay();
|
||||
#define PAGE_UPDATE 1 // page wants display to update
|
||||
#define PAGE_HIBERNATE 2 // page wants displey to hibernate
|
||||
|
||||
struct Point {
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
Point rotatePoint(const Point& origin, const Point& p, double angle);
|
||||
std::vector<Point> rotatePoints(const Point& origin, const std::vector<Point>& pts, double angle);
|
||||
void fillPoly4(const std::vector<Point>& p4, uint16_t color);
|
||||
void drawPoly(const std::vector<Point>& points, uint16_t color);
|
||||
|
||||
void deepSleep(CommonData &common);
|
||||
|
||||
@@ -97,6 +93,7 @@ String xdrDelete(String input); // Delete xdr prefix from string
|
||||
|
||||
void drawTextCenter(int16_t cx, int16_t cy, String text);
|
||||
void drawTextRalign(int16_t x, int16_t y, String text);
|
||||
void drawTextBoxed(Rect box, String text, uint16_t fg, uint16_t bg, bool inverted, bool border);
|
||||
|
||||
void displayTrendHigh(int16_t x, int16_t y, uint16_t size, uint16_t color);
|
||||
void displayTrendLow(int16_t x, int16_t y, uint16_t size, uint16_t color);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
#include "ConfigMenu.h"
|
||||
#include "images/logo64.xbm"
|
||||
#include <esp32/clk.h>
|
||||
#include "qrcode.h"
|
||||
@@ -44,6 +45,9 @@
|
||||
class PageSystem : public Page
|
||||
{
|
||||
private:
|
||||
GwConfigHandler *config;
|
||||
GwLog *logger;
|
||||
|
||||
// NVRAM config options
|
||||
String flashLED;
|
||||
|
||||
@@ -67,6 +71,9 @@ private:
|
||||
double homelon;
|
||||
|
||||
char mode = 'N'; // (N)ormal, (S)ettings, (C)onfiguration, (D)evice list, c(A)rd
|
||||
int8_t editmode = -1; // marker for menu/edit/set function
|
||||
|
||||
ConfigMenu *menu;
|
||||
|
||||
void incMode() {
|
||||
if (mode == 'N') { // Normal
|
||||
@@ -219,7 +226,7 @@ private:
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
|
||||
getdisplay().setCursor(x0, y0);
|
||||
/*getdisplay().setCursor(x0, y0);
|
||||
getdisplay().print("CPU speed: 80 | 160 | 240");
|
||||
getdisplay().setCursor(x0, y0 + 1 * dy);
|
||||
getdisplay().print("Power mode: Max | 5V | Min");
|
||||
@@ -228,7 +235,30 @@ private:
|
||||
|
||||
// TODO Change NVRAM-preferences settings here
|
||||
getdisplay().setCursor(x0, y0 + 4 * dy);
|
||||
getdisplay().print("Simulation: On | Off");
|
||||
getdisplay().print("Simulation: On | Off"); */
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
for (int i = 0 ; i < menu->getItemCount(); i++) {
|
||||
ConfigMenuItem *itm = menu->getItemByIndex(i);
|
||||
if (!itm) {
|
||||
LOG_DEBUG(GwLog::ERROR, "Menu item not found: %d", i);
|
||||
} else {
|
||||
Rect r = menu->getItemRect(i);
|
||||
bool inverted = (i == menu->getActiveIndex());
|
||||
drawTextBoxed(r, itm->getLabel(), commonData->fgcolor, commonData->bgcolor, inverted, false);
|
||||
if (inverted and editmode > 0) {
|
||||
// triangle as edit marker
|
||||
getdisplay().fillTriangle(r.x + r.w + 20, r.y, r.x + r.w + 30, r.y + r.h / 2, r.x + r.w + 20, r.y + r.h, commonData->fgcolor);
|
||||
}
|
||||
getdisplay().setCursor(r.x + r.w + 40, r.y + r.h - 4);
|
||||
if (itm->getType() == "int") {
|
||||
getdisplay().print(itm->getValue());
|
||||
getdisplay().print(itm->getUnit());
|
||||
} else {
|
||||
getdisplay().print(itm->getValue() == 0 ? "No" : "Yes");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void displayModeSettings() {
|
||||
@@ -310,7 +340,7 @@ private:
|
||||
getdisplay().setCursor(202, y0 + 80);
|
||||
getdisplay().print("Bl color:");
|
||||
getdisplay().setCursor(320, y0 + 80);
|
||||
getdisplay().print(commonData->backlight.color);
|
||||
getdisplay().print(commonData->backlight.color.toName());
|
||||
getdisplay().setCursor(202, y0 + 96);
|
||||
getdisplay().print("Bl mode:");
|
||||
getdisplay().setCursor(320, y0 + 96);
|
||||
@@ -351,10 +381,17 @@ private:
|
||||
getdisplay().print(String(commonData->status.n2kTx));
|
||||
}
|
||||
|
||||
void storeConfig() {
|
||||
menu->storeValues();
|
||||
}
|
||||
|
||||
public:
|
||||
PageSystem(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageSystem");
|
||||
config = commonData->config;
|
||||
logger = commonData->logger;
|
||||
|
||||
logger->logDebug(GwLog::LOG,"Instantiate PageSystem");
|
||||
if (hasFRAM) {
|
||||
mode = fram.read(FRAM_SYSTEM_MODE);
|
||||
}
|
||||
@@ -378,6 +415,24 @@ public:
|
||||
rot_sensor = common.config->getString(common.config->useRotSensor);
|
||||
homelat = common.config->getString(common.config->homeLAT).toDouble();
|
||||
homelon = common.config->getString(common.config->homeLON).toDouble();
|
||||
|
||||
// CPU speed: 80 | 160 | 240
|
||||
// Power mode: Max | 5V | Min
|
||||
// Accesspoint: On | Off
|
||||
|
||||
// TODO Change NVRAM-preferences settings here
|
||||
// getdisplay().setCursor(x0, y0 + 4 * dy);
|
||||
// getdisplay().print("Simulation: On | Off");
|
||||
|
||||
// Initialize config menu
|
||||
menu = new ConfigMenu("Options", 40, 80);
|
||||
menu->setItemDimension(150, 20);
|
||||
|
||||
ConfigMenuItem *newitem;
|
||||
newitem = menu->addItem("accesspoint", "Accesspoint", "bool", 0, "");
|
||||
newitem = menu->addItem("simulation", "Simulation", "on/off", 0, "");
|
||||
menu->setItemActive("accesspoint");
|
||||
|
||||
}
|
||||
|
||||
virtual void setupKeys(){
|
||||
|
||||
Reference in New Issue
Block a user