Integrated config menu into system page
This commit is contained in:
parent
aed389f3b2
commit
d5b0af3b19
|
@ -192,3 +192,13 @@ Rect ConfigMenu::getItemRect(int8_t index) {
|
||||||
return {static_cast<double>(x), static_cast<double>(y + index * h),
|
return {static_cast<double>(x), static_cast<double>(y + index * h),
|
||||||
static_cast<double>(w), static_cast<double>(h)};
|
static_cast<double>(w), static_cast<double>(h)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfigMenu::setCallback(void (*callback)()) {
|
||||||
|
fptrCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigMenu::storeValues() {
|
||||||
|
if (fptrCallback) {
|
||||||
|
fptrCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ private:
|
||||||
uint16_t y;
|
uint16_t y;
|
||||||
uint16_t w;
|
uint16_t w;
|
||||||
uint16_t h;
|
uint16_t h;
|
||||||
|
void (*fptrCallback)();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConfigMenu(String title, uint16_t menu_x, uint16_t menu_y);
|
ConfigMenu(String title, uint16_t menu_x, uint16_t menu_y);
|
||||||
|
@ -60,4 +61,6 @@ public:
|
||||||
Point getXY();
|
Point getXY();
|
||||||
Rect getRect();
|
Rect getRect();
|
||||||
Rect getItemRect(int8_t index);
|
Rect getItemRect(int8_t index);
|
||||||
|
void setCallback(void (*callback)());
|
||||||
|
void storeValues();
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
|
@ -297,30 +297,20 @@ String xdrDelete(String input){
|
||||||
return 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) {
|
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[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);
|
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
|
// Split string into words, whitespace separated
|
||||||
std::vector<String> split(const String &s) {
|
std::vector<String> split(const String &s) {
|
||||||
std::vector<String> words;
|
std::vector<String> words;
|
||||||
|
@ -382,6 +372,24 @@ void drawTextRalign(int16_t x, int16_t y, String text) {
|
||||||
getdisplay().print(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)
|
// 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){
|
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);
|
getdisplay().fillTriangle(x, y, x+size*2, y, x+size, y-size*2, color);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "OBP60Hardware.h"
|
#include "OBP60Hardware.h"
|
||||||
#include "LedSpiTask.h"
|
#include "LedSpiTask.h"
|
||||||
|
#include "Graphics.h"
|
||||||
#include <GxEPD2_BW.h> // E-paper lib V2
|
#include <GxEPD2_BW.h> // E-paper lib V2
|
||||||
#include <Adafruit_FRAM_I2C.h> // I2C FRAM
|
#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_UPDATE 1 // page wants display to update
|
||||||
#define PAGE_HIBERNATE 2 // page wants displey to hibernate
|
#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 fillPoly4(const std::vector<Point>& p4, uint16_t color);
|
||||||
|
void drawPoly(const std::vector<Point>& points, uint16_t color);
|
||||||
|
|
||||||
void deepSleep(CommonData &common);
|
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 drawTextCenter(int16_t cx, int16_t cy, String text);
|
||||||
void drawTextRalign(int16_t x, int16_t y, 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 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);
|
void displayTrendLow(int16_t x, int16_t y, uint16_t size, uint16_t color);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "Pagedata.h"
|
#include "Pagedata.h"
|
||||||
#include "OBP60Extensions.h"
|
#include "OBP60Extensions.h"
|
||||||
|
#include "ConfigMenu.h"
|
||||||
#include "images/logo64.xbm"
|
#include "images/logo64.xbm"
|
||||||
#include <esp32/clk.h>
|
#include <esp32/clk.h>
|
||||||
#include "qrcode.h"
|
#include "qrcode.h"
|
||||||
|
@ -44,6 +45,9 @@
|
||||||
class PageSystem : public Page
|
class PageSystem : public Page
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
GwConfigHandler *config;
|
||||||
|
GwLog *logger;
|
||||||
|
|
||||||
// NVRAM config options
|
// NVRAM config options
|
||||||
String flashLED;
|
String flashLED;
|
||||||
|
|
||||||
|
@ -67,6 +71,9 @@ private:
|
||||||
double homelon;
|
double homelon;
|
||||||
|
|
||||||
char mode = 'N'; // (N)ormal, (S)ettings, (C)onfiguration, (D)evice list, c(A)rd
|
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() {
|
void incMode() {
|
||||||
if (mode == 'N') { // Normal
|
if (mode == 'N') { // Normal
|
||||||
|
@ -219,7 +226,7 @@ private:
|
||||||
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||||
|
|
||||||
getdisplay().setCursor(x0, y0);
|
/*getdisplay().setCursor(x0, y0);
|
||||||
getdisplay().print("CPU speed: 80 | 160 | 240");
|
getdisplay().print("CPU speed: 80 | 160 | 240");
|
||||||
getdisplay().setCursor(x0, y0 + 1 * dy);
|
getdisplay().setCursor(x0, y0 + 1 * dy);
|
||||||
getdisplay().print("Power mode: Max | 5V | Min");
|
getdisplay().print("Power mode: Max | 5V | Min");
|
||||||
|
@ -228,7 +235,30 @@ private:
|
||||||
|
|
||||||
// TODO Change NVRAM-preferences settings here
|
// TODO Change NVRAM-preferences settings here
|
||||||
getdisplay().setCursor(x0, y0 + 4 * dy);
|
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() {
|
void displayModeSettings() {
|
||||||
|
@ -351,10 +381,17 @@ private:
|
||||||
getdisplay().print(String(commonData->status.n2kTx));
|
getdisplay().print(String(commonData->status.n2kTx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void storeConfig() {
|
||||||
|
menu->storeValues();
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PageSystem(CommonData &common){
|
PageSystem(CommonData &common){
|
||||||
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) {
|
if (hasFRAM) {
|
||||||
mode = fram.read(FRAM_SYSTEM_MODE);
|
mode = fram.read(FRAM_SYSTEM_MODE);
|
||||||
}
|
}
|
||||||
|
@ -378,6 +415,24 @@ public:
|
||||||
rot_sensor = common.config->getString(common.config->useRotSensor);
|
rot_sensor = common.config->getString(common.config->useRotSensor);
|
||||||
homelat = common.config->getString(common.config->homeLAT).toDouble();
|
homelat = common.config->getString(common.config->homeLAT).toDouble();
|
||||||
homelon = common.config->getString(common.config->homeLON).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(){
|
virtual void setupKeys(){
|
||||||
|
|
Loading…
Reference in New Issue