mirror of
https://github.com/thooge/esp32-nmea2000-obp60.git
synced 2025-12-28 05:03:06 +01:00
Compare commits
22 Commits
keypad
...
39966098cc
| Author | SHA1 | Date | |
|---|---|---|---|
| 39966098cc | |||
| 11a061d5a2 | |||
| 4600cb7228 | |||
| e89d1ac62e | |||
| 6fb5e01969 | |||
| 5c731bc662 | |||
| 25c2742f5b | |||
| 6479c7d711 | |||
| e287bfa72e | |||
| 5a652e2c19 | |||
| 5081f3a684 | |||
| 7de226b447 | |||
| f6e2fa7806 | |||
| d5b0af3b19 | |||
| aed389f3b2 | |||
| 32ba4a64ed | |||
|
|
7edd201daa | ||
| eb51092b23 | |||
| f4d88f1b8b | |||
| 08cd2ad4b1 | |||
| b50d82eff0 | |||
| 6ae4e195d6 |
@@ -501,7 +501,7 @@ def prebuild(env):
|
||||
genereateUserTasks(os.path.join(outPath(), TASK_INCLUDE))
|
||||
generateFile(os.path.join(basePath(),XDR_FILE),os.path.join(outPath(),XDR_INCLUDE),generateXdrMappings)
|
||||
generateFile(os.path.join(basePath(),GROVE_CONFIG_IN),os.path.join(outPath(),GROVE_CONFIG),generateGroveDefs,inMode='r')
|
||||
version="dev"+datetime.now().strftime("%Y%m%d")
|
||||
version = "dev{}{}".format(datetime.now().strftime("%Y%m%d"), "-ext")
|
||||
env.Append(CPPDEFINES=[('GWDEVVERSION',version)])
|
||||
|
||||
def cleangenerated(source, target, env):
|
||||
|
||||
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();
|
||||
};
|
||||
@@ -1,6 +0,0 @@
|
||||
Craete new page for OBP60
|
||||
1. Create page under /lib/obp60task/PageXXXX.cpp
|
||||
2. Set page name in PageXXXX.cpp on file name
|
||||
3. Register new page in /lib/obp60task/obp60task.cpp line 242 (registerAllPages)
|
||||
4. Add new page in /lib/obp60task/config.json for each page type or add new page to gen_set.py and run it to auto-generate the relevant section of config.json
|
||||
|
||||
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);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include <Arduino.h>
|
||||
@@ -33,28 +34,32 @@
|
||||
// Set display type and SPI pins for display
|
||||
GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST, OBP_SPI_BUSY)); // GDEW042T2 400x300, UC8176 (IL0398)
|
||||
// Export display in new funktion
|
||||
GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> & getdisplay(){return display;}
|
||||
GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> & getdisplay(){return display;} // DEPRECATED
|
||||
gxepd2display *epd = &display;
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_GDEY042T81
|
||||
// Set display type and SPI pins for display
|
||||
GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> display(GxEPD2_420_GDEY042T81(OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST, OBP_SPI_BUSY)); // GDEW042T2 400x300, UC8176 (IL0398)
|
||||
// Export display in new funktion
|
||||
GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> & getdisplay(){return display;}
|
||||
GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> & getdisplay(){return display;} // DEPRECATED
|
||||
gxepd2display *epd = &display;
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_GYE042A87
|
||||
// Set display type and SPI pins for display
|
||||
GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> display(GxEPD2_420_GYE042A87(OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST, OBP_SPI_BUSY)); // GDEW042T2 400x300, UC8176 (IL0398)
|
||||
// Export display in new funktion
|
||||
GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay(){return display;}
|
||||
GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay(){return display;} // DEPRECATED
|
||||
gxepd2display *epd = &display;
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_SE0420NQ04
|
||||
// Set display type and SPI pins for display
|
||||
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> display(GxEPD2_420_SE0420NQ04(OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST, OBP_SPI_BUSY)); // GDEW042T2 400x300, UC8176 (IL0398)
|
||||
// Export display in new funktion
|
||||
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay(){return display;}
|
||||
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay(){return display;} // DEPRECATED
|
||||
gxepd2display *epd = &display;
|
||||
#endif
|
||||
|
||||
// Horter I2C moduls
|
||||
@@ -107,6 +112,27 @@ void hardwareInit(GwApi *api)
|
||||
}
|
||||
}
|
||||
|
||||
void powerInit(String powermode) {
|
||||
// Max Power | Only 5.0V | Min Power
|
||||
if (powermode == "Max Power" || powermode == "Only 5.0V") {
|
||||
#ifdef HARDWARE_V21
|
||||
setPortPin(OBP_POWER_50, true); // Power on 5.0V rail
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
setPortPin(OBP_POWER_EPD, true);// Power on ePaper display
|
||||
setPortPin(OBP_POWER_SD, true); // Power on SD card
|
||||
#endif
|
||||
} else { // Min Power
|
||||
#ifdef HARDWARE_V21
|
||||
setPortPin(OBP_POWER_50, false); // Power off 5.0V rail
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
setPortPin(OBP_POWER_EPD, false);// Power off ePaper display
|
||||
setPortPin(OBP_POWER_SD, false); // Power off SD card
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void setPortPin(uint pin, bool value){
|
||||
pinMode(pin, OUTPUT);
|
||||
digitalWrite(pin, value);
|
||||
@@ -276,30 +302,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;
|
||||
@@ -361,6 +377,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);
|
||||
@@ -372,7 +406,7 @@ void displayTrendLow(int16_t x, int16_t y, uint16_t size, uint16_t color){
|
||||
}
|
||||
|
||||
// Show header informations
|
||||
void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatValue *time, GwApi::BoatValue *hdop){
|
||||
void displayHeader(CommonData &commonData, bool symbolmode, GwApi::BoatValue *date, GwApi::BoatValue *time, GwApi::BoatValue *hdop){
|
||||
|
||||
static bool heartbeat = false;
|
||||
static unsigned long usbRxOld = 0;
|
||||
@@ -386,31 +420,70 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa
|
||||
static unsigned long n2kRxOld = 0;
|
||||
static unsigned long n2kTxOld = 0;
|
||||
|
||||
uint16_t symbol_x = 2;
|
||||
static const uint16_t symbol_offset = 20;
|
||||
|
||||
if(commonData.config->getBool(commonData.config->statusLine) == true){
|
||||
|
||||
if (symbolmode) {
|
||||
commonData.logger->logDebug(GwLog::LOG,"Header: Symbolmode");
|
||||
} else {
|
||||
commonData.logger->logDebug(GwLog::LOG,"Header: Textmode");
|
||||
}
|
||||
|
||||
// Show status info
|
||||
getdisplay().setTextColor(commonData.fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(0, 15);
|
||||
if(commonData.status.wifiApOn){
|
||||
getdisplay().print(" AP ");
|
||||
if (commonData.status.wifiApOn) {
|
||||
if (symbolmode) {
|
||||
getdisplay().drawXBitmap(symbol_x, 1, iconmap["AP"], icon_width, icon_height, commonData.fgcolor);
|
||||
symbol_x += symbol_offset;
|
||||
} else {
|
||||
getdisplay().print(" AP ");
|
||||
}
|
||||
}
|
||||
// If receive new telegram data then display bus name
|
||||
if(commonData.status.tcpClRx != tcpClRxOld || commonData.status.tcpClTx != tcpClTxOld || commonData.status.tcpSerRx != tcpSerRxOld || commonData.status.tcpSerTx != tcpSerTxOld){
|
||||
getdisplay().print("TCP ");
|
||||
if (symbolmode) {
|
||||
getdisplay().drawXBitmap(symbol_x, 1, iconmap["TCP"], icon_width, icon_height, commonData.fgcolor);
|
||||
symbol_x += symbol_offset;
|
||||
} else {
|
||||
getdisplay().print("TCP ");
|
||||
}
|
||||
}
|
||||
if(commonData.status.n2kRx != n2kRxOld || commonData.status.n2kTx != n2kTxOld){
|
||||
getdisplay().print("N2K ");
|
||||
if (symbolmode) {
|
||||
getdisplay().drawXBitmap(symbol_x, 1, iconmap["N2K"], icon_width, icon_height, commonData.fgcolor);
|
||||
symbol_x += symbol_offset;
|
||||
} else {
|
||||
getdisplay().print("N2K ");
|
||||
}
|
||||
}
|
||||
if(commonData.status.serRx != serRxOld || commonData.status.serTx != serTxOld){
|
||||
getdisplay().print("183 ");
|
||||
if (symbolmode) {
|
||||
getdisplay().drawXBitmap(symbol_x, 1, iconmap["0183"], icon_width, icon_height, commonData.fgcolor);
|
||||
symbol_x += symbol_offset;
|
||||
} else {
|
||||
getdisplay().print("183 ");
|
||||
}
|
||||
}
|
||||
if(commonData.status.usbRx != usbRxOld || commonData.status.usbTx != usbTxOld){
|
||||
getdisplay().print("USB ");
|
||||
if (symbolmode) {
|
||||
getdisplay().drawXBitmap(symbol_x, 1, iconmap["USB"], icon_width, icon_height, commonData.fgcolor);
|
||||
symbol_x += symbol_offset;
|
||||
} else {
|
||||
getdisplay().print("USB ");
|
||||
}
|
||||
}
|
||||
double gpshdop = formatValue(hdop, commonData).value;
|
||||
if(commonData.config->getString(commonData.config->useGPS) != "off" && gpshdop <= commonData.config->getInt(commonData.config->hdopAccuracy) && hdop->valid == true){
|
||||
getdisplay().print("GPS");
|
||||
if (symbolmode) {
|
||||
getdisplay().drawXBitmap(symbol_x, 1, iconmap["GPS"], icon_width, icon_height, commonData.fgcolor);
|
||||
symbol_x += symbol_offset;
|
||||
} else {
|
||||
getdisplay().print("GPS");
|
||||
}
|
||||
}
|
||||
// Save old telegram counter
|
||||
tcpClRxOld = commonData.status.tcpClRx;
|
||||
@@ -427,26 +500,26 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa
|
||||
#ifdef HARDWARE_V21
|
||||
// Display key lock status
|
||||
if (commonData.keylock) {
|
||||
getdisplay().drawXBitmap(170, 1, lock_bits, icon_width, icon_height, commonData.fgcolor);
|
||||
epd->drawXBitmap(170, 1, lock_bits, icon_width, icon_height, commonData.fgcolor);
|
||||
} else {
|
||||
getdisplay().drawXBitmap(166, 1, swipe_bits, swipe_width, swipe_height, commonData.fgcolor);
|
||||
epd->drawXBitmap(166, 1, swipe_bits, swipe_width, swipe_height, commonData.fgcolor);
|
||||
}
|
||||
#endif
|
||||
#ifdef LIPO_ACCU_1200
|
||||
if (commonData.data.BatteryChargeStatus == 1) {
|
||||
getdisplay().drawXBitmap(170, 1, battery_loading_bits, battery_width, battery_height, commonData.fgcolor);
|
||||
epd->drawXBitmap(170, 1, battery_loading_bits, battery_width, battery_height, commonData.fgcolor);
|
||||
} else {
|
||||
#ifdef VOLTAGE_SENSOR
|
||||
if (commonData.data.batteryLevelLiPo < 10) {
|
||||
getdisplay().drawXBitmap(170, 1, battery_0_bits, battery_width, battery_height, commonData.fgcolor);
|
||||
epd->drawXBitmap(170, 1, battery_0_bits, battery_width, battery_height, commonData.fgcolor);
|
||||
} else if (commonData.data.batteryLevelLiPo < 25) {
|
||||
getdisplay().drawXBitmap(170, 1, battery_25_bits, battery_width, battery_height, commonData.fgcolor);
|
||||
epd->drawXBitmap(170, 1, battery_25_bits, battery_width, battery_height, commonData.fgcolor);
|
||||
} else if (commonData.data.batteryLevelLiPo < 50) {
|
||||
getdisplay().drawXBitmap(170, 1, battery_50_bits, battery_width, battery_height, commonData.fgcolor);
|
||||
epd->drawXBitmap(170, 1, battery_50_bits, battery_width, battery_height, commonData.fgcolor);
|
||||
} else if (commonData.data.batteryLevelLiPo < 75) {
|
||||
getdisplay().drawXBitmap(170, 1, battery_75_bits, battery_width, battery_height, commonData.fgcolor);
|
||||
epd->drawXBitmap(170, 1, battery_75_bits, battery_width, battery_height, commonData.fgcolor);
|
||||
} else {
|
||||
getdisplay().drawXBitmap(170, 1, battery_100_bits, battery_width, battery_height, commonData.fgcolor);
|
||||
epd->drawXBitmap(170, 1, battery_100_bits, battery_width, battery_height, commonData.fgcolor);
|
||||
}
|
||||
#endif // VOLTAGE_SENSOR
|
||||
}
|
||||
@@ -454,13 +527,13 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa
|
||||
|
||||
// Heartbeat as page number
|
||||
if (heartbeat) {
|
||||
getdisplay().setTextColor(commonData.bgcolor);
|
||||
getdisplay().fillRect(201, 0, 23, 19, commonData.fgcolor);
|
||||
epd->setTextColor(commonData.bgcolor);
|
||||
epd->fillRect(201, 0, 23, 19, commonData.fgcolor);
|
||||
} else {
|
||||
getdisplay().setTextColor(commonData.fgcolor);
|
||||
getdisplay().drawRect(201, 0, 23, 19, commonData.fgcolor);
|
||||
epd->setTextColor(commonData.fgcolor);
|
||||
epd->drawRect(201, 0, 23, 19, commonData.fgcolor);
|
||||
}
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
drawTextCenter(211, 9, String(commonData.data.actpage));
|
||||
heartbeat = !heartbeat;
|
||||
|
||||
@@ -468,19 +541,19 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa
|
||||
String fmttype = commonData.config->getString(commonData.config->dateFormat);
|
||||
String timesource = commonData.config->getString(commonData.config->timeSource);
|
||||
double tz = commonData.config->getString(commonData.config->timeZone).toDouble();
|
||||
getdisplay().setTextColor(commonData.fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(230, 15);
|
||||
epd->setTextColor(commonData.fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(230, 15);
|
||||
if (timesource == "RTC" or timesource == "iRTC") {
|
||||
// TODO take DST into account
|
||||
if (commonData.data.rtcValid) {
|
||||
time_t tv = mktime(&commonData.data.rtcTime) + (int)(tz * 3600);
|
||||
struct tm *local_tm = localtime(&tv);
|
||||
getdisplay().print(formatTime('m', local_tm->tm_hour, local_tm->tm_min, 0));
|
||||
getdisplay().print(" ");
|
||||
getdisplay().print(formatDate(fmttype, local_tm->tm_year + 1900, local_tm->tm_mon + 1, local_tm->tm_mday));
|
||||
getdisplay().print(" ");
|
||||
getdisplay().print(tz == 0 ? "UTC" : "LOT");
|
||||
epd->print(formatTime('m', local_tm->tm_hour, local_tm->tm_min, 0));
|
||||
epd->print(" ");
|
||||
epd->print(formatDate(fmttype, local_tm->tm_year + 1900, local_tm->tm_mon + 1, local_tm->tm_mday));
|
||||
epd->print(" ");
|
||||
epd->print(tz == 0 ? "UTC" : "LOT");
|
||||
} else {
|
||||
drawTextRalign(396, 15, "RTC invalid");
|
||||
}
|
||||
@@ -491,15 +564,15 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa
|
||||
String acttime = formatValue(time, commonData).svalue;
|
||||
acttime = acttime.substring(0, 5);
|
||||
String actdate = formatValue(date, commonData).svalue;
|
||||
getdisplay().print(acttime);
|
||||
getdisplay().print(" ");
|
||||
getdisplay().print(actdate);
|
||||
getdisplay().print(" ");
|
||||
getdisplay().print(tz == 0 ? "UTC" : "LOT");
|
||||
epd->print(acttime);
|
||||
epd->print(" ");
|
||||
epd->print(actdate);
|
||||
epd->print(" ");
|
||||
epd->print(tz == 0 ? "UTC" : "LOT");
|
||||
}
|
||||
else{
|
||||
if(commonData.config->getBool(commonData.config->useSimuData) == true){
|
||||
getdisplay().print("12:00 01.01.2024 LOT");
|
||||
epd->print("12:00 01.01.2024 LOT");
|
||||
}
|
||||
else{
|
||||
drawTextRalign(396, 15, "No GPS data");
|
||||
@@ -507,15 +580,15 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa
|
||||
}
|
||||
} // timesource == "GPS"
|
||||
else {
|
||||
getdisplay().print("No time source");
|
||||
epd->print("No time source");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void displayFooter(CommonData &commonData) {
|
||||
|
||||
getdisplay().setFont(&Atari16px);
|
||||
getdisplay().setTextColor(commonData.fgcolor);
|
||||
epd->setFont(&Atari16px);
|
||||
epd->setTextColor(commonData.fgcolor);
|
||||
|
||||
#ifdef HARDWARE_V21
|
||||
// Frame around key icon area
|
||||
@@ -524,14 +597,14 @@ void displayFooter(CommonData &commonData) {
|
||||
const uint16_t top = 280;
|
||||
const uint16_t bottom = 299;
|
||||
// horizontal stub lines
|
||||
getdisplay().drawLine(commonData.keydata[0].x, top, commonData.keydata[0].x+10, top, commonData.fgcolor);
|
||||
epd->drawLine(commonData.keydata[0].x, top, commonData.keydata[0].x+10, top, commonData.fgcolor);
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
getdisplay().drawLine(commonData.keydata[i].x-10, top, commonData.keydata[i].x+10, top, commonData.fgcolor);
|
||||
epd->drawLine(commonData.keydata[i].x-10, top, commonData.keydata[i].x+10, top, commonData.fgcolor);
|
||||
}
|
||||
getdisplay().drawLine(commonData.keydata[5].x + commonData.keydata[5].w - 10, top, commonData.keydata[5].x + commonData.keydata[5].w + 1, top, commonData.fgcolor);
|
||||
epd->drawLine(commonData.keydata[5].x + commonData.keydata[5].w - 10, top, commonData.keydata[5].x + commonData.keydata[5].w + 1, top, commonData.fgcolor);
|
||||
// vertical key separators
|
||||
for (int i = 0; i <= 4; i++) {
|
||||
getdisplay().drawLine(commonData.keydata[i].x + commonData.keydata[i].w, top, commonData.keydata[i].x + commonData.keydata[i].w, bottom, commonData.fgcolor);
|
||||
epd->drawLine(commonData.keydata[i].x + commonData.keydata[i].w, top, commonData.keydata[i].x + commonData.keydata[i].w, bottom, commonData.fgcolor);
|
||||
}
|
||||
for (int i = 0; i < 6; i++) {
|
||||
uint16_t x, y;
|
||||
@@ -542,7 +615,7 @@ void displayFooter(CommonData &commonData) {
|
||||
if (iconmap.find(icon_name) != iconmap.end()) {
|
||||
x = commonData.keydata[i].x + (commonData.keydata[i].w - icon_width) / 2;
|
||||
y = commonData.keydata[i].y + (commonData.keydata[i].h - icon_height) / 2;
|
||||
getdisplay().drawXBitmap(x, y, iconmap[icon_name], icon_width, icon_height, commonData.fgcolor);
|
||||
epd->drawXBitmap(x, y, iconmap[icon_name], icon_width, icon_height, commonData.fgcolor);
|
||||
} else {
|
||||
// icon is missing, use name instead
|
||||
x = commonData.keydata[i].x + commonData.keydata[i].w / 2;
|
||||
@@ -557,8 +630,8 @@ void displayFooter(CommonData &commonData) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getdisplay().setCursor(65, 295);
|
||||
getdisplay().print("Press 1 and 6 fast to unlock keys");
|
||||
epd->setCursor(65, 295);
|
||||
epd->print("Press 1 and 6 fast to unlock keys");
|
||||
}
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
@@ -569,21 +642,21 @@ void displayFooter(CommonData &commonData) {
|
||||
uint16_t x0 = (GxEPD_WIDTH - w) / 2 + r * 2;
|
||||
for (int i = 0; i < commonData.data.maxpage; i++) {
|
||||
if (i == (commonData.data.actpage - 1)) {
|
||||
getdisplay().fillCircle(x0 + i * (r * 2 + space), 290, r, commonData.fgcolor);
|
||||
epd->fillCircle(x0 + i * (r * 2 + space), 290, r, commonData.fgcolor);
|
||||
} else {
|
||||
getdisplay().drawCircle(x0 + i * (r * 2 + space), 290, r, commonData.fgcolor);
|
||||
epd->drawCircle(x0 + i * (r * 2 + space), 290, r, commonData.fgcolor);
|
||||
}
|
||||
}
|
||||
// key indicators
|
||||
// left side = top key "menu"
|
||||
getdisplay().drawLine(0, 280, 10, 280, commonData.fgcolor);
|
||||
getdisplay().drawLine(55, 280, 65, 280, commonData.fgcolor);
|
||||
getdisplay().drawLine(65, 280, 65, 299, commonData.fgcolor);
|
||||
epd->drawLine(0, 280, 10, 280, commonData.fgcolor);
|
||||
epd->drawLine(55, 280, 65, 280, commonData.fgcolor);
|
||||
epd->drawLine(65, 280, 65, 299, commonData.fgcolor);
|
||||
drawTextCenter(33, 291, commonData.keydata[0].label);
|
||||
// right side = bottom key "exit"
|
||||
getdisplay().drawLine(390, 280, 399, 280, commonData.fgcolor);
|
||||
getdisplay().drawLine(335, 280, 345, 280, commonData.fgcolor);
|
||||
getdisplay().drawLine(335, 280, 335, 399, commonData.fgcolor);
|
||||
epd->drawLine(390, 280, 399, 280, commonData.fgcolor);
|
||||
epd->drawLine(335, 280, 345, 280, commonData.fgcolor);
|
||||
epd->drawLine(335, 280, 335, 399, commonData.fgcolor);
|
||||
drawTextCenter(366, 291, commonData.keydata[1].label);
|
||||
#endif
|
||||
}
|
||||
@@ -596,31 +669,31 @@ void displayAlarm(CommonData &commonData) {
|
||||
const uint16_t w = 300;
|
||||
const uint16_t h = 150;
|
||||
|
||||
getdisplay().setFont(&Atari16px);
|
||||
getdisplay().setTextColor(commonData.fgcolor);
|
||||
epd->setFont(&Atari16px);
|
||||
epd->setTextColor(commonData.fgcolor);
|
||||
|
||||
// overlay
|
||||
getdisplay().drawRect(x, y, w, h, commonData.fgcolor);
|
||||
getdisplay().fillRect(x + 1, y + 1, w - 1, h - 1, commonData.bgcolor);
|
||||
getdisplay().drawRect(x + 3, y + 3, w - 5, h - 5, commonData.fgcolor);
|
||||
epd->drawRect(x, y, w, h, commonData.fgcolor);
|
||||
epd->fillRect(x + 1, y + 1, w - 1, h - 1, commonData.bgcolor);
|
||||
epd->drawRect(x + 3, y + 3, w - 5, h - 5, commonData.fgcolor);
|
||||
|
||||
// exclamation icon in left top corner
|
||||
getdisplay().drawXBitmap(x + 16, y + 16, exclamation_bits, exclamation_width, exclamation_height, commonData.fgcolor);
|
||||
epd->drawXBitmap(x + 16, y + 16, exclamation_bits, exclamation_width, exclamation_height, commonData.fgcolor);
|
||||
|
||||
// title
|
||||
getdisplay().setCursor(x + 64, y + 30);
|
||||
getdisplay().print("A L A R M");
|
||||
getdisplay().setCursor(x + 64, y + 48);
|
||||
getdisplay().print("#" + commonData.alarm.id);
|
||||
getdisplay().print(" from ");
|
||||
getdisplay().print(commonData.alarm.source);
|
||||
epd->setCursor(x + 64, y + 30);
|
||||
epd->print("A L A R M");
|
||||
epd->setCursor(x + 64, y + 48);
|
||||
epd->print("#" + commonData.alarm.id);
|
||||
epd->print(" from ");
|
||||
epd->print(commonData.alarm.source);
|
||||
|
||||
// message, but maximum 4 lines
|
||||
std::vector<String> lines = wordwrap (commonData.alarm.message, w - 16 - 8 / 8);
|
||||
int n = 0;
|
||||
for (const auto& l : lines) {
|
||||
getdisplay().setCursor(x + 16, y + 80 + n);
|
||||
getdisplay().print(l);
|
||||
epd->setCursor(x + 16, y + 80 + n);
|
||||
epd->print(l);
|
||||
n += 16;
|
||||
if (n > 64) {
|
||||
break;
|
||||
@@ -713,20 +786,20 @@ void batteryGraphic(uint x, uint y, float percent, int pcolor, int bcolor){
|
||||
}
|
||||
// Battery corpus 100x80 with fill level
|
||||
int level = int((100.0 - percent) * (80-(2*t)) / 100.0);
|
||||
getdisplay().fillRect(xb, yb, 100, 80, pcolor);
|
||||
epd->fillRect(xb, yb, 100, 80, pcolor);
|
||||
if(percent < 99){
|
||||
getdisplay().fillRect(xb+t, yb+t, 100-(2*t), level, bcolor);
|
||||
epd->fillRect(xb+t, yb+t, 100-(2*t), level, bcolor);
|
||||
}
|
||||
// Plus pol 20x15
|
||||
int xp = xb + 20;
|
||||
int yp = yb - 15 + t;
|
||||
getdisplay().fillRect(xp, yp, 20, 15, pcolor);
|
||||
getdisplay().fillRect(xp+t, yp+t, 20-(2*t), 15-(2*t), bcolor);
|
||||
epd->fillRect(xp, yp, 20, 15, pcolor);
|
||||
epd->fillRect(xp+t, yp+t, 20-(2*t), 15-(2*t), bcolor);
|
||||
// Minus pol 20x15
|
||||
int xm = xb + 60;
|
||||
int ym = yb -15 + t;
|
||||
getdisplay().fillRect(xm, ym, 20, 15, pcolor);
|
||||
getdisplay().fillRect(xm+t, ym+t, 20-(2*t), 15-(2*t), bcolor);
|
||||
epd->fillRect(xm, ym, 20, 15, pcolor);
|
||||
epd->fillRect(xm+t, ym+t, 20-(2*t), 15-(2*t), bcolor);
|
||||
}
|
||||
|
||||
// Solar graphic with fill level
|
||||
@@ -738,17 +811,17 @@ void solarGraphic(uint x, uint y, int pcolor, int bcolor){
|
||||
int percent = 0;
|
||||
// Solar corpus 100x80
|
||||
int level = int((100.0 - percent) * (80-(2*t)) / 100.0);
|
||||
getdisplay().fillRect(xb, yb, 100, 80, pcolor);
|
||||
epd->fillRect(xb, yb, 100, 80, pcolor);
|
||||
if(percent < 99){
|
||||
getdisplay().fillRect(xb+t, yb+t, 100-(2*t), level, bcolor);
|
||||
epd->fillRect(xb+t, yb+t, 100-(2*t), level, bcolor);
|
||||
}
|
||||
// Draw horizontel lines
|
||||
getdisplay().fillRect(xb, yb+28-t, 100, t, pcolor);
|
||||
getdisplay().fillRect(xb, yb+54-t, 100, t, pcolor);
|
||||
epd->fillRect(xb, yb+28-t, 100, t, pcolor);
|
||||
epd->fillRect(xb, yb+54-t, 100, t, pcolor);
|
||||
// Draw vertical lines
|
||||
getdisplay().fillRect(xb+19+t, yb, t, 80, pcolor);
|
||||
getdisplay().fillRect(xb+39+2*t, yb, t, 80, pcolor);
|
||||
getdisplay().fillRect(xb+59+3*t, yb, t, 80, pcolor);
|
||||
epd->fillRect(xb+19+t, yb, t, 80, pcolor);
|
||||
epd->fillRect(xb+39+2*t, yb, t, 80, pcolor);
|
||||
epd->fillRect(xb+59+3*t, yb, t, 80, pcolor);
|
||||
|
||||
}
|
||||
|
||||
@@ -760,13 +833,13 @@ void generatorGraphic(uint x, uint y, int pcolor, int bcolor){
|
||||
int t = 4; // Line thickness
|
||||
|
||||
// Generator corpus with radius 45
|
||||
getdisplay().fillCircle(xb, yb, 45, pcolor);
|
||||
getdisplay().fillCircle(xb, yb, 41, bcolor);
|
||||
epd->fillCircle(xb, yb, 45, pcolor);
|
||||
epd->fillCircle(xb, yb, 41, bcolor);
|
||||
// Insert G
|
||||
getdisplay().setTextColor(pcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold32pt8b);
|
||||
getdisplay().setCursor(xb-22, yb+20);
|
||||
getdisplay().print("G");
|
||||
epd->setTextColor(pcolor);
|
||||
epd->setFont(&Ubuntu_Bold32pt8b);
|
||||
epd->setCursor(xb-22, yb+20);
|
||||
epd->print("G");
|
||||
}
|
||||
|
||||
// Function to handle HTTP image request
|
||||
@@ -780,7 +853,7 @@ void doImageRequest(GwApi *api, int *pageno, const PageStruct pages[MAX_PAGE_NUM
|
||||
|
||||
logger->logDebug(GwLog::LOG,"handle image request [%s]: %s", imgformat, filename);
|
||||
|
||||
uint8_t *fb = getdisplay().getBuffer(); // EPD framebuffer
|
||||
uint8_t *fb = epd->getBuffer(); // EPD framebuffer
|
||||
std::vector<uint8_t> imageBuffer; // image in webserver transferbuffer
|
||||
String mimetype;
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#ifndef _OBP60EXTENSIONPORT_H
|
||||
#define _OBP60EXTENSIONPORT_H
|
||||
|
||||
#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
|
||||
|
||||
@@ -42,19 +44,27 @@ extern const GFXfont Atari16px;
|
||||
|
||||
// Global functions
|
||||
#ifdef DISPLAY_GDEW042T2
|
||||
GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> & getdisplay();
|
||||
GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> & getdisplay(); // DEPRECATED
|
||||
typedef GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> gxepd2display;
|
||||
extern gxepd2display *epd;
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_GDEY042T81
|
||||
GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> & getdisplay();
|
||||
GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> & getdisplay(); // DEPRECATED
|
||||
typedef GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> gxepd2display;
|
||||
extern gxepd2display *epd;
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_GYE042A87
|
||||
GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay();
|
||||
GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay(); // DEPRECATED
|
||||
typedef GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> gxepd2display;
|
||||
extern gxepd2display *epd;
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_SE0420NQ04
|
||||
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay();
|
||||
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay(); // DEPRECATED
|
||||
typedef GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> gxepd2display;
|
||||
extern gxepd2display *epd;
|
||||
#endif
|
||||
|
||||
// Page display return values
|
||||
@@ -62,19 +72,15 @@ 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);
|
||||
|
||||
uint8_t getLastPage();
|
||||
|
||||
void hardwareInit(GwApi *api);
|
||||
void powerInit(String powermode);
|
||||
|
||||
void setPortPin(uint pin, bool value); // Set port pin for extension port
|
||||
|
||||
@@ -96,11 +102,12 @@ 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);
|
||||
|
||||
void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatValue *time, GwApi::BoatValue *hdop); // Draw display header
|
||||
void displayHeader(CommonData &commonData, bool symbolmode, GwApi::BoatValue *date, GwApi::BoatValue *time, GwApi::BoatValue *hdop); // Draw display header
|
||||
void displayFooter(CommonData &commonData);
|
||||
void displayAlarm(CommonData &commonData);
|
||||
|
||||
@@ -148,24 +155,62 @@ static unsigned char fram_bits[] PROGMEM = {
|
||||
0xff, 0xff, 0xf8, 0x1f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f,
|
||||
0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f };
|
||||
|
||||
static unsigned char ap_bits[] PROGMEM = {
|
||||
// Header symbols
|
||||
|
||||
static unsigned char ap_bits[] PROGMEM= {
|
||||
0xe0, 0x03, 0x18, 0x0c, 0x04, 0x10, 0xc2, 0x21, 0x30, 0x06, 0x08, 0x08,
|
||||
0xc0, 0x01, 0x20, 0x02, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x01, 0xc0, 0x01,
|
||||
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
|
||||
|
||||
static unsigned char dish_bits[] PROGMEM = {
|
||||
static unsigned char gps_bits[] PROGMEM = {
|
||||
0x3c, 0x00, 0x42, 0x18, 0xfa, 0x1b, 0x02, 0x04, 0x02, 0x0a, 0x02, 0x09,
|
||||
0x82, 0x08, 0x06, 0x0a, 0x0e, 0x1b, 0x9c, 0x2b, 0x38, 0x2b, 0x74, 0x20,
|
||||
0xec, 0x1f, 0x1c, 0x00, 0xf4, 0x00, 0xfe, 0x03 };
|
||||
|
||||
static unsigned char nmea_bits[] PROGMEM = {
|
||||
0x00, 0x00, 0x22, 0x21, 0x26, 0x33, 0x26, 0x33, 0x2a, 0x2d, 0x32, 0x2d,
|
||||
0x32, 0x21, 0x22, 0x21, 0x00, 0x00, 0x3c, 0x0c, 0x04, 0x0c, 0x04, 0x12,
|
||||
0x3c, 0x12, 0x04, 0x1e, 0x04, 0x21, 0x3c, 0x21 };
|
||||
|
||||
static unsigned char n2k_bits[] PROGMEM = {
|
||||
0xe0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x02, 0x40, 0x32, 0x4c, 0x31, 0x8c,
|
||||
0x01, 0x80, 0x81, 0x81, 0x81, 0x81, 0x01, 0x80, 0x31, 0x8c, 0x32, 0x4c,
|
||||
0x02, 0x40, 0x04, 0x20, 0x98, 0x19, 0xe0, 0x07 };
|
||||
|
||||
static unsigned char tcp_bits[] PROGMEM = {
|
||||
0x00, 0x00, 0xe0, 0x03, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0xe0, 0x03,
|
||||
0x80, 0x00, 0x80, 0x00, 0xff, 0xff, 0x08, 0x10, 0x08, 0x10, 0x3e, 0x7c,
|
||||
0x22, 0x44, 0x22, 0x44, 0x22, 0x44, 0x3e, 0x7c };
|
||||
|
||||
static unsigned char usb_bits[] PROGMEM = {
|
||||
0x00, 0x00, 0x92, 0x39, 0x52, 0x4a, 0x52, 0x48, 0x92, 0x39, 0x12, 0x4a,
|
||||
0x52, 0x4a, 0x8c, 0x39, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x04, 0x20,
|
||||
0xf4, 0x2f, 0x04, 0x20, 0xf8, 0x1f, 0x00, 0x00 };
|
||||
|
||||
static unsigned char sdcard_bits[] PROGMEM = {
|
||||
0xf8, 0x07, 0x0c, 0x08, 0x04, 0x08, 0xc4, 0x09, 0x24, 0x1a, 0xe4, 0x13,
|
||||
0x04, 0x20, 0x24, 0x21, 0xa4, 0x12, 0x44, 0x12, 0x04, 0x20, 0x04, 0x20,
|
||||
0xc4, 0x23, 0x34, 0x2c, 0xd8, 0x1b, 0x00, 0x00 };
|
||||
|
||||
static unsigned char bluetooth_bits[] PROGMEM = {
|
||||
0x00, 0x00, 0x22, 0x21, 0x26, 0x33, 0x26, 0x33, 0x2a, 0x2d, 0x32, 0x2d,
|
||||
0x32, 0x21, 0x22, 0x21, 0x00, 0x00, 0x3c, 0x0c, 0x04, 0x0c, 0x04, 0x12,
|
||||
0x3c, 0x12, 0x04, 0x1e, 0x04, 0x21, 0x3c, 0x21 };
|
||||
|
||||
static std::map<String, unsigned char *> iconmap = {
|
||||
{"LEFT", left_bits},
|
||||
{"RIGHT", right_bits},
|
||||
{"LOCK", lock_bits},
|
||||
{"PLUS", plus_bits},
|
||||
{"MINUS", minus_bits},
|
||||
{"DISH", dish_bits},
|
||||
{"AP", ap_bits}
|
||||
{"GPS", gps_bits},
|
||||
{"AP", ap_bits},
|
||||
{"0183", nmea_bits},
|
||||
{"N2K", n2k_bits},
|
||||
{"TCP", tcp_bits},
|
||||
{"USB", usb_bits},
|
||||
{"SDCARD", sdcard_bits},
|
||||
{"BLUE", bluetooth_bits}
|
||||
};
|
||||
|
||||
// Battery
|
||||
|
||||
@@ -65,6 +65,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||
String tempFormat = commondata.config->getString(commondata.config->tempFormat); // [K|°C|°F]
|
||||
String dateFormat = commondata.config->getString(commondata.config->dateFormat); // [DE|GB|US]
|
||||
bool usesimudata = commondata.config->getBool(commondata.config->useSimuData); // [on|off]
|
||||
String precision = commondata.config->getString(commondata.config->valueprecision); // [1|2]
|
||||
|
||||
// If boat value not valid
|
||||
if (! value->valid && !usesimudata){
|
||||
@@ -72,6 +73,19 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* fmt_dec_1;
|
||||
const char* fmt_dec_10;
|
||||
const char* fmt_dec_100;
|
||||
if (precision == "1") {
|
||||
fmt_dec_1 = "%3.1f";
|
||||
fmt_dec_10 = "%3.0f";
|
||||
fmt_dec_100 = "%3.0f";
|
||||
} else {
|
||||
fmt_dec_1 = "%3.2f";
|
||||
fmt_dec_10 = "%3.1f";
|
||||
fmt_dec_100 = "%3.0f";
|
||||
}
|
||||
|
||||
// LOG_DEBUG(GwLog::DEBUG,"formatValue init: getFormat: %s date->value: %f time->value: %f", value->getFormat(), commondata.date->value, commondata.time->value);
|
||||
static const int bsize = 30;
|
||||
char buffer[bsize+1];
|
||||
@@ -91,25 +105,25 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||
tmElements_t parts;
|
||||
time_t tv=tNMEA0183Msg::daysToTime_t(value->value + dayoffset);
|
||||
tNMEA0183Msg::breakTime(tv,parts);
|
||||
if(usesimudata == false) {
|
||||
if(String(dateFormat) == "DE"){
|
||||
snprintf(buffer,bsize,"%02d.%02d.%04d",parts.tm_mday,parts.tm_mon+1,parts.tm_year+1900);
|
||||
if (usesimudata == false) {
|
||||
if (String(dateFormat) == "DE") {
|
||||
snprintf(buffer,bsize, "%02d.%02d.%04d", parts.tm_mday, parts.tm_mon+1, parts.tm_year+1900);
|
||||
}
|
||||
else if(String(dateFormat) == "GB"){
|
||||
snprintf(buffer,bsize,"%02d/%02d/%04d",parts.tm_mday,parts.tm_mon+1,parts.tm_year+1900);
|
||||
else if(String(dateFormat) == "GB") {
|
||||
snprintf(buffer, bsize, "%02d/%02d/%04d", parts.tm_mday, parts.tm_mon+1, parts.tm_year+1900);
|
||||
}
|
||||
else if(String(dateFormat) == "US"){
|
||||
snprintf(buffer,bsize,"%02d/%02d/%04d",parts.tm_mon+1,parts.tm_mday,parts.tm_year+1900);
|
||||
else if(String(dateFormat) == "US") {
|
||||
snprintf(buffer, bsize, "%02d/%02d/%04d", parts.tm_mon+1, parts.tm_mday, parts.tm_year+1900);
|
||||
}
|
||||
else if(String(dateFormat) == "ISO"){
|
||||
snprintf(buffer,bsize,"%04d-%02d-%02d",parts.tm_year+1900,parts.tm_mon+1,parts.tm_mday);
|
||||
else if(String(dateFormat) == "ISO") {
|
||||
snprintf(buffer, bsize, "%04d-%02d-%02d", parts.tm_year+1900, parts.tm_mon+1, parts.tm_mday);
|
||||
}
|
||||
else{
|
||||
snprintf(buffer,bsize,"%02d.%02d.%04d",parts.tm_mday,parts.tm_mon+1,parts.tm_year+1900);
|
||||
else {
|
||||
snprintf(buffer, bsize, "%02d.%02d.%04d", parts.tm_mday, parts.tm_mon+1, parts.tm_year+1900);
|
||||
}
|
||||
}
|
||||
else{
|
||||
snprintf(buffer,bsize,"01.01.2022");
|
||||
snprintf(buffer, bsize, "01.01.2022");
|
||||
}
|
||||
if(timeZone == 0){
|
||||
result.unit = "UTC";
|
||||
@@ -130,11 +144,11 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||
if (timeInSeconds > 86400) {timeInSeconds = timeInSeconds - 86400;}
|
||||
if (timeInSeconds < 0) {timeInSeconds = timeInSeconds + 86400;}
|
||||
// LOG_DEBUG(GwLog::DEBUG,"... formatTime value: %f tz: %f corrected timeInSeconds: %f ", value->value, timeZone, timeInSeconds);
|
||||
if(usesimudata == false) {
|
||||
val=modf(timeInSeconds/3600.0,&inthr);
|
||||
val=modf(val*3600.0/60.0,&intmin);
|
||||
if (usesimudata == false) {
|
||||
val = modf(timeInSeconds/3600.0, &inthr);
|
||||
val = modf(val*3600.0/60.0, &intmin);
|
||||
modf(val*60.0,&intsec);
|
||||
snprintf(buffer,bsize,"%02.0f:%02.0f:%02.0f",inthr,intmin,intsec);
|
||||
snprintf(buffer, bsize, "%02.0f:%02.0f:%02.0f", inthr, intmin, intsec);
|
||||
}
|
||||
else{
|
||||
static long sec;
|
||||
@@ -143,7 +157,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||
sec ++;
|
||||
}
|
||||
sec = sec % 60;
|
||||
snprintf(buffer,bsize,"11:36:%02i", int(sec));
|
||||
snprintf(buffer, bsize, "11:36:%02i", int(sec));
|
||||
lasttime = millis();
|
||||
}
|
||||
if(timeZone == 0){
|
||||
@@ -156,23 +170,23 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatFixed0"){
|
||||
if(usesimudata == false) {
|
||||
snprintf(buffer,bsize,"%3.0f",value->value);
|
||||
snprintf(buffer, bsize, "%3.0f", value->value);
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
rawvalue = 8.0 + float(random(0, 10)) / 10.0;
|
||||
snprintf(buffer,bsize,"%3.0f", rawvalue);
|
||||
snprintf(buffer, bsize, "%3.0f", rawvalue);
|
||||
}
|
||||
result.unit = "";
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatCourse" || value->getFormat() == "formatWind"){
|
||||
double course = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
course = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
course = 2.53 + float(random(0, 10) / 100.0);
|
||||
rawvalue = course;
|
||||
}
|
||||
@@ -185,7 +199,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatKnots" && (value->getName() == "SOG" || value->getName() == "STW")){
|
||||
double speed = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
speed = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -193,85 +207,85 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||
rawvalue = 4.0 + float(random(0, 40));
|
||||
speed = rawvalue;
|
||||
}
|
||||
if(String(speedFormat) == "km/h"){
|
||||
if (String(speedFormat) == "km/h"){
|
||||
speed = speed * 3.6; // Unit conversion form m/s to km/h
|
||||
result.unit = "km/h";
|
||||
}
|
||||
else if(String(speedFormat) == "kn"){
|
||||
else if (String(speedFormat) == "kn"){
|
||||
speed = speed * 1.94384; // Unit conversion form m/s to kn
|
||||
result.unit = "kn";
|
||||
}
|
||||
else{
|
||||
else {
|
||||
speed = speed; // Unit conversion form m/s to m/s
|
||||
result.unit = "m/s";
|
||||
}
|
||||
if(speed < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",speed);
|
||||
if(speed < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, speed);
|
||||
}
|
||||
if(speed >= 10 && speed < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",speed);
|
||||
else if (speed < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, speed);
|
||||
}
|
||||
if(speed >= 100){
|
||||
snprintf(buffer,bsize,"%3.0f",speed);
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_100, speed);
|
||||
}
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatKnots" && (value->getName() == "AWS" || value->getName() == "TWS" || value->getName() == "MaxAws" || value->getName() == "MaxTws")){
|
||||
double speed = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
speed = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 4.0 + float(random(0, 40));
|
||||
speed = rawvalue;
|
||||
}
|
||||
if(String(windspeedFormat) == "km/h"){
|
||||
speed = speed * 3.6; // Unit conversion form m/s to km/h
|
||||
if (String(windspeedFormat) == "km/h"){
|
||||
speed = speed * 3.6; // Unit conversion form m/s to km/h
|
||||
result.unit = "km/h";
|
||||
}
|
||||
else if(String(windspeedFormat) == "kn"){
|
||||
else if (String(windspeedFormat) == "kn"){
|
||||
speed = speed * 1.94384; // Unit conversion form m/s to kn
|
||||
result.unit = "kn";
|
||||
}
|
||||
else if(String(windspeedFormat) == "bft"){
|
||||
if(speed < 0.3){
|
||||
if (speed < 0.3) {
|
||||
speed = 0;
|
||||
}
|
||||
if(speed >=0.3 && speed < 1.5){
|
||||
else if (speed < 1.5) {
|
||||
speed = 1;
|
||||
}
|
||||
if(speed >=1.5 && speed < 3.3){
|
||||
else if (speed < 3.3) {
|
||||
speed = 2;
|
||||
}
|
||||
if(speed >=3.3 && speed < 5.4){
|
||||
else if (speed < 5.4) {
|
||||
speed = 3;
|
||||
}
|
||||
if(speed >=5.4 && speed < 7.9){
|
||||
else if (speed < 7.9) {
|
||||
speed = 4;
|
||||
}
|
||||
if(speed >=7.9 && speed < 10.7){
|
||||
else if (speed < 10.7) {
|
||||
speed = 5;
|
||||
}
|
||||
if(speed >=10.7 && speed < 13.8){
|
||||
else if (speed < 13.8) {
|
||||
speed = 6;
|
||||
}
|
||||
if(speed >=13.8 && speed < 17.1){
|
||||
else if (speed < 17.1) {
|
||||
speed = 7;
|
||||
}
|
||||
if(speed >=17.1 && speed < 20.7){
|
||||
else if (speed < 20.7) {
|
||||
speed = 8;
|
||||
}
|
||||
if(speed >=20.7 && speed < 24.4){
|
||||
else if (speed < 24.4) {
|
||||
speed = 9;
|
||||
}
|
||||
if(speed >=24.4 && speed < 28.4){
|
||||
else if (speed < 28.4) {
|
||||
speed = 10;
|
||||
}
|
||||
if(speed >=28.4 && speed < 32.6){
|
||||
else if (speed < 32.6) {
|
||||
speed = 11;
|
||||
}
|
||||
if(speed >=32.6){
|
||||
else {
|
||||
speed = 12;
|
||||
}
|
||||
result.unit = "bft";
|
||||
@@ -280,82 +294,85 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||
speed = speed; // Unit conversion form m/s to m/s
|
||||
result.unit = "m/s";
|
||||
}
|
||||
if(String(windspeedFormat) == "bft"){
|
||||
snprintf(buffer,bsize,"%2.0f",speed);
|
||||
if (String(windspeedFormat) == "bft"){
|
||||
snprintf(buffer, bsize, "%2.0f", speed);
|
||||
}
|
||||
else{
|
||||
if(speed < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",speed);
|
||||
if (speed < 10){
|
||||
snprintf(buffer, bsize, fmt_dec_1, speed);
|
||||
}
|
||||
if(speed >= 10 && speed < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",speed);
|
||||
else if (speed < 100){
|
||||
snprintf(buffer, bsize, fmt_dec_10, speed);
|
||||
}
|
||||
if(speed >= 100){
|
||||
snprintf(buffer,bsize,"%3.0f",speed);
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_100, speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatRot"){
|
||||
double rotation = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
rotation = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 0.04 + float(random(0, 10)) / 100.0;
|
||||
rotation = rawvalue;
|
||||
}
|
||||
rotation = rotation * 57.2958; // Unit conversion form rad/s to deg/s
|
||||
result.unit = "Deg/s";
|
||||
if(rotation < -100){
|
||||
if (rotation < -100){
|
||||
rotation = -99;
|
||||
}
|
||||
if(rotation > 100){
|
||||
if (rotation > 100){
|
||||
rotation = 99;
|
||||
}
|
||||
if(rotation > -10 && rotation < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",rotation);
|
||||
if (rotation > -10 && rotation < 10){
|
||||
snprintf(buffer, bsize, "%3.2f", rotation);
|
||||
}
|
||||
if(rotation <= -10 || rotation >= 10){
|
||||
snprintf(buffer,bsize,"%3.0f",rotation);
|
||||
if (rotation <= -10 || rotation >= 10){
|
||||
snprintf(buffer, bsize, "%3.0f", rotation);
|
||||
}
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatDop"){
|
||||
double dop = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
dop = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 2.0 + float(random(0, 40)) / 10.0;
|
||||
dop = rawvalue;
|
||||
}
|
||||
result.unit = "m";
|
||||
if(dop > 99.9){
|
||||
if (dop > 99.9){
|
||||
dop = 99.9;
|
||||
}
|
||||
if(dop < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",dop);
|
||||
if (dop < 10){
|
||||
snprintf(buffer, bsize, fmt_dec_1, dop);
|
||||
}
|
||||
if(dop >= 10 && dop < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",dop);
|
||||
else if(dop < 100){
|
||||
snprintf(buffer, bsize, fmt_dec_10, dop);
|
||||
}
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_100, dop);
|
||||
}
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatLatitude"){
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
double lat = value->value;
|
||||
rawvalue = value->value;
|
||||
String latitude = "";
|
||||
String latdir = "";
|
||||
float degree = abs(int(lat));
|
||||
float minute = abs((lat - int(lat)) * 60);
|
||||
if(lat > 0){
|
||||
if (lat > 0){
|
||||
latdir = "N";
|
||||
}
|
||||
else{
|
||||
else {
|
||||
latdir = "S";
|
||||
}
|
||||
latitude = String(degree,0) + "\x90 " + String(minute,4) + "' " + latdir;
|
||||
@@ -364,41 +381,41 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||
}
|
||||
else{
|
||||
rawvalue = 35.0 + float(random(0, 10)) / 10000.0;
|
||||
snprintf(buffer,bsize," 51\" %2.4f' N", rawvalue);
|
||||
snprintf(buffer, bsize, " 51\" %2.4f' N", rawvalue);
|
||||
}
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatLongitude"){
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
double lon = value->value;
|
||||
rawvalue = value->value;
|
||||
String longitude = "";
|
||||
String londir = "";
|
||||
float degree = abs(int(lon));
|
||||
float minute = abs((lon - int(lon)) * 60);
|
||||
if(lon > 0){
|
||||
if (lon > 0){
|
||||
londir = "E";
|
||||
}
|
||||
else{
|
||||
else {
|
||||
londir = "W";
|
||||
}
|
||||
longitude = String(degree,0) + "\x90 " + String(minute,4) + "' " + londir;
|
||||
result.unit = "";
|
||||
strcpy(buffer, longitude.c_str());
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 6.0 + float(random(0, 10)) / 100000.0;
|
||||
snprintf(buffer,bsize," 15\" %2.4f'", rawvalue);
|
||||
snprintf(buffer, bsize, " 15\" %2.4f'", rawvalue);
|
||||
}
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatDepth"){
|
||||
double depth = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
depth = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 18.0 + float(random(0, 100)) / 10.0;
|
||||
depth = rawvalue;
|
||||
}
|
||||
@@ -409,14 +426,14 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||
else{
|
||||
result.unit = "m";
|
||||
}
|
||||
if(depth < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",depth);
|
||||
if (depth < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, depth);
|
||||
}
|
||||
if(depth >= 10 && depth < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",depth);
|
||||
else if (depth < 100){
|
||||
snprintf(buffer, bsize, fmt_dec_10, depth);
|
||||
}
|
||||
if(depth >= 100){
|
||||
snprintf(buffer,bsize,"%3.0f",depth);
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_100, depth);
|
||||
}
|
||||
}
|
||||
//########################################################
|
||||
@@ -430,50 +447,50 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||
xte = rawvalue;
|
||||
}
|
||||
if (xte >= 100) {
|
||||
snprintf(buffer,bsize,"%3.0f",value->value);
|
||||
snprintf(buffer, bsize, fmt_dec_100, value->value);
|
||||
} else if (xte >= 10) {
|
||||
snprintf(buffer,bsize,"%3.1f",value->value);
|
||||
snprintf(buffer, bsize, fmt_dec_10, value->value);
|
||||
} else {
|
||||
snprintf(buffer,bsize,"%3.2f",value->value);
|
||||
snprintf(buffer, bsize, fmt_dec_1, value->value);
|
||||
}
|
||||
result.unit = "nm";
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "kelvinToC"){
|
||||
double temp = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
temp = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 296.0 + float(random(0, 10)) / 10.0;
|
||||
temp = rawvalue;
|
||||
}
|
||||
if(String(tempFormat) == "C"){
|
||||
if (String(tempFormat) == "C") {
|
||||
temp = temp - 273.15;
|
||||
result.unit = "C";
|
||||
}
|
||||
else if(String(tempFormat) == "F"){
|
||||
else if (String(tempFormat) == "F") {
|
||||
temp = (temp - 273.15) * 9 / 5 + 32;
|
||||
result.unit = "F";
|
||||
}
|
||||
else{
|
||||
result.unit = "K";
|
||||
}
|
||||
if(temp < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",temp);
|
||||
if(temp < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, temp);
|
||||
}
|
||||
if(temp >= 10 && temp < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",temp);
|
||||
else if (temp < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, temp);
|
||||
}
|
||||
if(temp >= 100){
|
||||
snprintf(buffer,bsize,"%3.0f",temp);
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_100, temp);
|
||||
}
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "mtr2nm"){
|
||||
double distance = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
distance = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -481,25 +498,25 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||
rawvalue = 2960.0 + float(random(0, 10));
|
||||
distance = rawvalue;
|
||||
}
|
||||
if(String(distanceFormat) == "km"){
|
||||
if (String(distanceFormat) == "km") {
|
||||
distance = distance * 0.001;
|
||||
result.unit = "km";
|
||||
}
|
||||
else if(String(distanceFormat) == "nm"){
|
||||
else if (String(distanceFormat) == "nm") {
|
||||
distance = distance * 0.000539957;
|
||||
result.unit = "nm";
|
||||
}
|
||||
else{;
|
||||
else {
|
||||
result.unit = "m";
|
||||
}
|
||||
if(distance < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",distance);
|
||||
if (distance < 10){
|
||||
snprintf(buffer, bsize, fmt_dec_1, distance);
|
||||
}
|
||||
if(distance >= 10 && distance < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",distance);
|
||||
else if (distance < 100){
|
||||
snprintf(buffer, bsize, fmt_dec_10, distance);
|
||||
}
|
||||
if(distance >= 100){
|
||||
snprintf(buffer,bsize,"%3.0f",distance);
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_100, distance);
|
||||
}
|
||||
}
|
||||
//########################################################
|
||||
@@ -508,122 +525,122 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:P:P"){
|
||||
double pressure = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
pressure = value->value;
|
||||
rawvalue = value->value;
|
||||
pressure = pressure / 100.0; // Unit conversion form Pa to hPa
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 968 + float(random(0, 10));
|
||||
pressure = rawvalue;
|
||||
}
|
||||
snprintf(buffer,bsize,"%4.0f",pressure);
|
||||
snprintf(buffer, bsize, "%4.0f", pressure);
|
||||
result.unit = "hPa";
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:P:B"){
|
||||
double pressure = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
pressure = value->value;
|
||||
rawvalue = value->value;
|
||||
pressure = pressure / 100.0; // Unit conversion form Pa to mBar
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = value->value;
|
||||
pressure = 968 + float(random(0, 10));
|
||||
}
|
||||
snprintf(buffer,bsize,"%4.0f",pressure);
|
||||
snprintf(buffer, bsize, "%4.0f", pressure);
|
||||
result.unit = "mBar";
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:U:V"){
|
||||
double voltage = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
voltage = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 12 + float(random(0, 30)) / 10.0;
|
||||
voltage = rawvalue;
|
||||
}
|
||||
if(voltage < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",voltage);
|
||||
if (voltage < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, voltage);
|
||||
}
|
||||
else{
|
||||
snprintf(buffer,bsize,"%3.1f",voltage);
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_10, voltage);
|
||||
}
|
||||
result.unit = "V";
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:I:A"){
|
||||
double current = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
current = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 8.2 + float(random(0, 50)) / 10.0;
|
||||
current = rawvalue;
|
||||
}
|
||||
if(current < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",current);
|
||||
if (current < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, current);
|
||||
}
|
||||
if(current >= 10 && current < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",current);
|
||||
else if(current < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, current);
|
||||
}
|
||||
if(current >= 100){
|
||||
snprintf(buffer,bsize,"%3.0f",current);
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_100, current);
|
||||
}
|
||||
result.unit = "A";
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:C:K"){
|
||||
double temperature = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
temperature = value->value - 273.15; // Convert K to C
|
||||
rawvalue = value->value - 273.15;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 21.8 + float(random(0, 50)) / 10.0;
|
||||
temperature = rawvalue;
|
||||
}
|
||||
if(temperature < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",temperature);
|
||||
if (temperature < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, temperature);
|
||||
}
|
||||
if(temperature >= 10 && temperature < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",temperature);
|
||||
else if (temperature < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, temperature);
|
||||
}
|
||||
if(temperature >= 100){
|
||||
snprintf(buffer,bsize,"%3.0f",temperature);
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_100, temperature);
|
||||
}
|
||||
result.unit = "Deg C";
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:C:C"){
|
||||
double temperature = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
temperature = value->value; // Value in C
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 21.8 + float(random(0, 50)) / 10.0;
|
||||
temperature = rawvalue;
|
||||
}
|
||||
if(temperature < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",temperature);
|
||||
if (temperature < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, temperature);
|
||||
}
|
||||
if(temperature >= 10 && temperature < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",temperature);
|
||||
else if(temperature < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, temperature);
|
||||
}
|
||||
if(temperature >= 100){
|
||||
snprintf(buffer,bsize,"%3.0f",temperature);
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_100, temperature);
|
||||
}
|
||||
result.unit = "Deg C";
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:H:P"){
|
||||
double humidity = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
humidity = value->value; // Value in %
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -631,143 +648,143 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||
rawvalue = 41.3 + float(random(0, 50)) / 10.0;
|
||||
humidity = rawvalue;
|
||||
}
|
||||
if(humidity < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",humidity);
|
||||
if (humidity < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, humidity);
|
||||
}
|
||||
if(humidity >= 10 && humidity < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",humidity);
|
||||
else if(humidity < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, humidity);
|
||||
}
|
||||
if(humidity >= 100){
|
||||
snprintf(buffer,bsize,"%3.0f",humidity);
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_100, humidity);
|
||||
}
|
||||
result.unit = "%";
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:V:P"){
|
||||
double volume = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
volume = value->value; // Value in %
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 85.8 + float(random(0, 50)) / 10.0;
|
||||
volume = rawvalue;
|
||||
}
|
||||
if(volume < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",volume);
|
||||
if (volume < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, volume);
|
||||
}
|
||||
if(volume >= 10 && volume < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",volume);
|
||||
else if (volume < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, volume);
|
||||
}
|
||||
if(volume >= 100){
|
||||
snprintf(buffer,bsize,"%3.0f",volume);
|
||||
else if (volume >= 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_100, volume);
|
||||
}
|
||||
result.unit = "%";
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:V:M"){
|
||||
double volume = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
volume = value->value; // Value in l
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 75.2 + float(random(0, 50)) / 10.0;
|
||||
volume = rawvalue;
|
||||
}
|
||||
if(volume < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",volume);
|
||||
if (volume < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, volume);
|
||||
}
|
||||
if(volume >= 10 && volume < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",volume);
|
||||
else if (volume < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, volume);
|
||||
}
|
||||
if(volume >= 100){
|
||||
snprintf(buffer,bsize,"%3.0f",volume);
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_100, volume);
|
||||
}
|
||||
result.unit = "l";
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:R:I"){
|
||||
double flow = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
flow = value->value; // Value in l/min
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 7.5 + float(random(0, 20)) / 10.0;
|
||||
flow = rawvalue;
|
||||
}
|
||||
if(flow < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",flow);
|
||||
if (flow < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, flow);
|
||||
}
|
||||
if(flow >= 10 && flow < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",flow);
|
||||
else if (flow < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, flow);
|
||||
}
|
||||
if(flow >= 100){
|
||||
snprintf(buffer,bsize,"%3.0f",flow);
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_100, flow);
|
||||
}
|
||||
result.unit = "l/min";
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:G:"){
|
||||
double generic = 0;
|
||||
if(usesimudata == false) {
|
||||
generic = value->value; // Value in l/min
|
||||
if (usesimudata == false) {
|
||||
generic = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 18.5 + float(random(0, 20)) / 10.0;
|
||||
generic = rawvalue;
|
||||
}
|
||||
if(generic < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",generic);
|
||||
if (generic < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, generic);
|
||||
}
|
||||
if(generic >= 10 && generic < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",generic);
|
||||
else if (generic < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, generic);
|
||||
}
|
||||
if(generic >= 100){
|
||||
snprintf(buffer,bsize,"%3.0f",generic);
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_100, generic);
|
||||
}
|
||||
result.unit = "";
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:A:P"){
|
||||
double dplace = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
dplace = value->value; // Value in %
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 55.3 + float(random(0, 20)) / 10.0;
|
||||
dplace = rawvalue;
|
||||
}
|
||||
if(dplace < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",dplace);
|
||||
if (dplace < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, dplace);
|
||||
}
|
||||
if(dplace >= 10 && dplace < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",dplace);
|
||||
else if (dplace < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, dplace);
|
||||
}
|
||||
if(dplace >= 100){
|
||||
snprintf(buffer,bsize,"%3.0f",dplace);
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_100, dplace);
|
||||
}
|
||||
result.unit = "%";
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:A:D"){
|
||||
double angle = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
angle = value->value;
|
||||
angle = angle * 57.2958; // Unit conversion form rad to deg
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = PI / 100 + (random(-5, 5) / 360 * 2* PI);
|
||||
angle = rawvalue * 57.2958;
|
||||
}
|
||||
if(angle > -10 && angle < 10){
|
||||
if (angle > -10 && angle < 10) {
|
||||
snprintf(buffer,bsize,"%3.1f",angle);
|
||||
}
|
||||
else{
|
||||
else {
|
||||
snprintf(buffer,bsize,"%3.0f",angle);
|
||||
}
|
||||
result.unit = "Deg";
|
||||
@@ -775,41 +792,41 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:T:R"){
|
||||
double rpm = 0;
|
||||
if(usesimudata == false) {
|
||||
if (usesimudata == false) {
|
||||
rpm = value->value; // Value in rpm
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rawvalue = 2505 + random(0, 20);
|
||||
rpm = rawvalue;
|
||||
}
|
||||
if(rpm < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",rpm);
|
||||
if (rpm < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, rpm);
|
||||
}
|
||||
if(rpm >= 10 && rpm < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",rpm);
|
||||
else if (rpm < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, rpm);
|
||||
}
|
||||
if(rpm >= 100){
|
||||
snprintf(buffer,bsize,"%3.0f",rpm);
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_100, rpm);
|
||||
}
|
||||
result.unit = "rpm";
|
||||
}
|
||||
//########################################################
|
||||
// Default format
|
||||
//########################################################
|
||||
else{
|
||||
if(value->value < 10){
|
||||
snprintf(buffer,bsize,"%3.2f",value->value);
|
||||
else {
|
||||
if (value->value < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, value->value);
|
||||
}
|
||||
if(value->value >= 10 && value->value < 100){
|
||||
snprintf(buffer,bsize,"%3.1f",value->value);
|
||||
else if (value->value < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, value->value);
|
||||
}
|
||||
if(value->value >= 100){
|
||||
snprintf(buffer,bsize,"%3.0f",value->value);
|
||||
else {
|
||||
snprintf(buffer, bsize, fmt_dec_100, value->value);
|
||||
}
|
||||
result.unit = "";
|
||||
}
|
||||
buffer[bsize]=0;
|
||||
buffer[bsize] = 0;
|
||||
result.value = rawvalue; // Return value is only necessary in case of simulation of graphic pointer
|
||||
result.svalue = String(buffer);
|
||||
return result;
|
||||
|
||||
433
lib/obp60task/PageAnchor.cpp
Normal file
433
lib/obp60task/PageAnchor.cpp
Normal file
@@ -0,0 +1,433 @@
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
#include "ConfigMenu.h"
|
||||
|
||||
/*
|
||||
Anchor overview with additional associated data
|
||||
This page is in experimental stage so be warned!
|
||||
North is up.
|
||||
|
||||
Boatdata used
|
||||
DBS - Water depth
|
||||
HDT - Boat heading
|
||||
AWS - Wind strength; Boat not moving so we assume AWS=TWS and AWD=TWD
|
||||
AWD - Wind direction
|
||||
LAT/LON - Boat position, current
|
||||
HDOP - Position error
|
||||
|
||||
This is the fist page to contain a configuration page with
|
||||
data entry option.
|
||||
Also it will make use of the new alarm function.
|
||||
|
||||
Data
|
||||
Anchor position lat/lon
|
||||
Depth at anchor position
|
||||
Chain length used
|
||||
Boat position current
|
||||
Depth at boat position
|
||||
Boat heading
|
||||
Wind direction
|
||||
Wind strength
|
||||
Alarm j/n
|
||||
Alarm radius
|
||||
GPS position error
|
||||
Timestamp while dropping anchor
|
||||
|
||||
Drop / raise function in device OBP40 has to be done inside
|
||||
config mode because of limited number of buttons.
|
||||
|
||||
*/
|
||||
|
||||
#define anchor_width 16
|
||||
#define anchor_height 16
|
||||
static unsigned char anchor_bits[] = {
|
||||
0x80, 0x01, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, 0xf0, 0x0f, 0x80, 0x01,
|
||||
0x80, 0x01, 0x88, 0x11, 0x8c, 0x31, 0x8e, 0x71, 0x84, 0x21, 0x86, 0x61,
|
||||
0x86, 0x61, 0xfc, 0x3f, 0xf8, 0x1f, 0x80, 0x01 };
|
||||
|
||||
class PageAnchor : public Page
|
||||
{
|
||||
private:
|
||||
GwConfigHandler *config;
|
||||
GwLog *logger;
|
||||
bool simulation = false;
|
||||
bool holdvalues = false;
|
||||
String flashLED;
|
||||
String backlightMode;
|
||||
String lengthformat;
|
||||
|
||||
int scale = 50; // Radius of display circle in meter
|
||||
|
||||
bool alarm = false;
|
||||
bool alarm_enabled = false;
|
||||
uint8_t alarm_range;
|
||||
|
||||
uint8_t chain_length;
|
||||
uint8_t chain;
|
||||
|
||||
bool anchor_set = false;
|
||||
double anchor_lat;
|
||||
double anchor_lon;
|
||||
double anchor_depth;
|
||||
int anchor_ts; // time stamp anchor dropped
|
||||
|
||||
char mode = 'N'; // (N)ormal, (C)onfig
|
||||
int8_t editmode = -1; // marker for menu/edit/set function
|
||||
|
||||
ConfigMenu *menu;
|
||||
|
||||
void displayModeNormal(PageData &pageData) {
|
||||
|
||||
// Boatvalues: DBS, HDT, AWS, AWD, LAT, LON, HDOP
|
||||
GwApi::BoatValue *bv_dbs = pageData.values[0]; // DBS
|
||||
String sval_dbs = formatValue(bv_dbs, *commonData).svalue;
|
||||
String sunit_dbs = formatValue(bv_dbs, *commonData).unit;
|
||||
GwApi::BoatValue *bv_hdt = pageData.values[1]; // HDT
|
||||
String sval_hdt = formatValue(bv_hdt, *commonData).svalue;
|
||||
GwApi::BoatValue *bv_aws = pageData.values[2]; // AWS
|
||||
String sval_aws = formatValue(bv_aws, *commonData).svalue;
|
||||
String sunit_aws = formatValue(bv_aws, *commonData).unit;
|
||||
GwApi::BoatValue *bv_awd = pageData.values[3]; // AWD
|
||||
String sval_awd = formatValue(bv_awd, *commonData).svalue;
|
||||
GwApi::BoatValue *bv_lat = pageData.values[4]; // LAT
|
||||
String sval_lat = formatValue(bv_lat, *commonData).svalue;
|
||||
GwApi::BoatValue *bv_lon = pageData.values[5]; // LON
|
||||
String sval_lon = formatValue(bv_lon, *commonData).svalue;
|
||||
GwApi::BoatValue *bv_hdop = pageData.values[6]; // HDOP
|
||||
String sval_hdop = formatValue(bv_hdop, *commonData).svalue;
|
||||
String sunit_hdop = formatValue(bv_hdop, *commonData).unit;
|
||||
|
||||
LOG_DEBUG(GwLog::DEBUG,"Drawing at PageAnchor; DBS=%f, HDT=%f, AWS=%f", bv_dbs->value, bv_hdt->value, bv_aws->value);
|
||||
|
||||
Point c = {200, 150}; // center = anchor position
|
||||
uint16_t r = 125;
|
||||
|
||||
Point b = {200, 180}; // boat position while dropping anchor
|
||||
|
||||
const std::vector<Point> pts_boat = { // polygon lines
|
||||
{b.x - 5, b.y},
|
||||
{b.x - 5, b.y - 10},
|
||||
{b.x, b.y - 16},
|
||||
{b.x + 5, b.y - 10},
|
||||
{b.x + 5, b.y}
|
||||
};
|
||||
//rotatePoints und dann Linien zeichnen
|
||||
// TODO rotate boat according to current heading
|
||||
//drawPoly(rotatePoints(c, pts, RadToDeg(value2)), commonData->fgcolor);
|
||||
drawPoly(pts_boat, commonData->fgcolor);
|
||||
|
||||
// Draw wind arrow
|
||||
const std::vector<Point> pts_wind = {
|
||||
{c.x, c.y - r + 25},
|
||||
{c.x - 12, c.y - r - 4},
|
||||
{c.x, c.y - r + 6},
|
||||
{c.x + 12, c.y - r - 4}
|
||||
};
|
||||
if (bv_awd->valid) {
|
||||
fillPoly4(rotatePoints(c, pts_wind, bv_awd->value), commonData->fgcolor);
|
||||
}
|
||||
|
||||
// Title and corner value headings
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(8, 48);
|
||||
getdisplay().print("Anchor");
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold10pt8b);
|
||||
getdisplay().setCursor(8, 200);
|
||||
getdisplay().print("Depth");
|
||||
drawTextRalign(392, 38, "Chain");
|
||||
drawTextRalign(392, 200, "Wind");
|
||||
|
||||
// Units
|
||||
getdisplay().setCursor(8, 272);
|
||||
getdisplay().print(sunit_dbs);
|
||||
drawTextRalign(392, 272, sunit_aws);
|
||||
drawTextRalign(392, 100, lengthformat); // chain unit not implemented
|
||||
|
||||
// Corner values
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(8, 70);
|
||||
getdisplay().print("Alarm: ");
|
||||
getdisplay().print(alarm_enabled ? "On" : "Off");
|
||||
|
||||
getdisplay().setCursor(8, 90);
|
||||
getdisplay().print("HDOP");
|
||||
getdisplay().setCursor(8, 106);
|
||||
if (bv_hdop->valid) {
|
||||
getdisplay().print(round(bv_hdop->value), 0);
|
||||
getdisplay().print(sunit_hdop);
|
||||
} else {
|
||||
getdisplay().print("n/a");
|
||||
}
|
||||
|
||||
// Values
|
||||
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
// Current chain used
|
||||
getdisplay().setCursor(328, 85);
|
||||
getdisplay().print("27");
|
||||
|
||||
// Depth
|
||||
getdisplay().setCursor(8, 250);
|
||||
getdisplay().print(sval_dbs);
|
||||
// Wind
|
||||
getdisplay().setCursor(328, 250);
|
||||
getdisplay().print(sval_aws);
|
||||
|
||||
getdisplay().drawCircle(c.x, c.y, r, commonData->fgcolor);
|
||||
getdisplay().drawCircle(c.x, c.y, r + 1, commonData->fgcolor);
|
||||
|
||||
// zoom scale
|
||||
getdisplay().drawLine(c.x + 10, c.y, c.x + r - 4, c.y, commonData->fgcolor);
|
||||
// arrow left
|
||||
getdisplay().drawLine(c.x + 10, c.y, c.x + 16, c.y - 4, commonData->fgcolor);
|
||||
getdisplay().drawLine(c.x + 10, c.y, c.x + 16, c.y + 4, commonData->fgcolor);
|
||||
// arrow right
|
||||
getdisplay().drawLine(c.x + r - 4, c.y, c.x + r - 10, c.y - 4, commonData->fgcolor);
|
||||
getdisplay().drawLine(c.x + r - 4, c.y, c.x + r - 10, c.y + 4, commonData->fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
drawTextCenter(c.x + r / 2, c.y + 8, String(scale) + "m");
|
||||
|
||||
// alarm range circle
|
||||
if (alarm_enabled) {
|
||||
// alarm range in meter has to be smaller than the scale in meter
|
||||
// r and r_range are pixel values
|
||||
uint16_t r_range = int(alarm_range * r / scale);
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageAnchor; Alarm range = %d", r_range);
|
||||
getdisplay().drawCircle(c.x, c.y, r_range, commonData->fgcolor);
|
||||
}
|
||||
|
||||
// draw anchor symbol (as bitmap)
|
||||
getdisplay().drawXBitmap(c.x - anchor_width / 2, c.y - anchor_height / 2,
|
||||
anchor_bits, anchor_width, anchor_height, commonData->fgcolor);
|
||||
|
||||
}
|
||||
|
||||
void displayModeConfig() {
|
||||
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(8, 48);
|
||||
getdisplay().print("Anchor configuration");
|
||||
|
||||
// TODO
|
||||
// show lat/lon for anchor pos
|
||||
// show lat/lon for boat pos
|
||||
// show distance anchor <-> boat
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
PageAnchor(CommonData &common)
|
||||
{
|
||||
commonData = &common;
|
||||
config = commonData->config;
|
||||
logger = commonData->logger;
|
||||
logger->logDebug(GwLog::LOG,"Instantiate PageAnchor");
|
||||
|
||||
// preload configuration data
|
||||
simulation = config->getBool(config->useSimuData);
|
||||
holdvalues = config->getBool(config->holdvalues);
|
||||
flashLED = config->getString(config->flashLED);
|
||||
backlightMode = config->getString(config->backlight);
|
||||
lengthformat = config->getString(config->lengthFormat);
|
||||
chain_length = config->getInt(config->chainLength);
|
||||
|
||||
chain = 0;
|
||||
anchor_set = false;
|
||||
alarm_range = 30;
|
||||
|
||||
// Initialize config menu
|
||||
menu = new ConfigMenu("Options", 40, 80);
|
||||
menu->setItemDimension(150, 20);
|
||||
|
||||
ConfigMenuItem *newitem;
|
||||
newitem = menu->addItem("chain", "Chain out", "int", 0, "m");
|
||||
if (! newitem) {
|
||||
// Demo: in case of failure exit here, should never be happen
|
||||
logger->logDebug(GwLog::ERROR,"Menu item creation failed");
|
||||
return;
|
||||
}
|
||||
newitem->setRange(0, 200, {1, 5, 10});
|
||||
newitem = menu->addItem("chainmax", "Chain max", "int", chain_length, "m");
|
||||
newitem->setRange(0, 200, {1, 5, 10});
|
||||
newitem = menu->addItem("zoom", "Zoom", "int", 50, "m");
|
||||
newitem->setRange(0, 200, {1, });
|
||||
newitem = menu->addItem("range", "Alarm range", "int", 40, "m");
|
||||
newitem->setRange(0, 200, {1, 5, 10});
|
||||
newitem = menu->addItem("alat", "Adjust anchor lat.", "int", 0, "m");
|
||||
newitem->setRange(0, 200, {1, 5, 10});
|
||||
newitem = menu->addItem("alon", "Adjust anchor lon.", "int", 0, "m");
|
||||
newitem->setRange(0, 200, {1, 5, 10});
|
||||
#ifdef BOARD_OBP40S3
|
||||
// Intodruced here because of missing keys for OBP40
|
||||
newitem = menu->addItem("anchor", "Anchor down", "bool", 0, "");
|
||||
#endif
|
||||
menu->setItemActive("zoom");
|
||||
}
|
||||
|
||||
void setupKeys(){
|
||||
Page::setupKeys();
|
||||
commonData->keydata[0].label = "MODE";
|
||||
commonData->keydata[1].label = "ALARM";
|
||||
}
|
||||
|
||||
#ifdef BOARD_OBP60S3
|
||||
int handleKey(int key){
|
||||
if (key == 1) { // Switch between normal and config mode
|
||||
if (mode == 'N') {
|
||||
mode = 'C';
|
||||
} else {
|
||||
mode = 'N';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (mode == 'N') {
|
||||
if (key == 2) { // Toggle alarm
|
||||
alarm_enabled = !alarm_enabled;
|
||||
return 0;
|
||||
}
|
||||
} else { // Config mode
|
||||
if (key == 3) {
|
||||
// menu down
|
||||
menu->goNext();
|
||||
return 0;
|
||||
}
|
||||
if (key == 4) {
|
||||
// menu up
|
||||
menu->goPrev();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (key == 11) { // Code for keylock
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
int handleKey(int key){
|
||||
if (key == 1) { // Switch between normal and config mode
|
||||
if (mode == 'N') {
|
||||
mode = 'C';
|
||||
commonData->keydata[1].label = "EDIT";
|
||||
} else {
|
||||
mode = 'N';
|
||||
commonData->keydata[1].label = "ALARM";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (mode == 'N') {
|
||||
if (key == 2) { // Toggle alarm
|
||||
alarm_enabled = !alarm_enabled;
|
||||
return 0;
|
||||
}
|
||||
} else { // Config mode
|
||||
// TODO different code for OBP40 / OBP60
|
||||
if (key == 9) {
|
||||
// menu down
|
||||
if (editmode > 0) {
|
||||
// decrease item value
|
||||
menu->getActiveItem()->decValue();
|
||||
} else {
|
||||
menu->goNext();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (key == 10) {
|
||||
// menu up or value up
|
||||
if (editmode > 0) {
|
||||
// increase item value
|
||||
menu->getActiveItem()->incValue();
|
||||
} else {
|
||||
menu->goPrev();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (key == 2) {
|
||||
// enter / leave edit mode for current menu item
|
||||
if (editmode > 0) {
|
||||
commonData->keydata[1].label = "EDIT";
|
||||
editmode = 0;
|
||||
} else {
|
||||
commonData->keydata[1].label = "SET";
|
||||
editmode = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (key == 11) { // Code for keylock
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
#endif
|
||||
|
||||
void displayNew(PageData &pageData){
|
||||
};
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
|
||||
// Logging boat values
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageAnchor; Mode=%c", mode);
|
||||
|
||||
// Set display in partial refresh mode
|
||||
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
|
||||
if (mode == 'N') {
|
||||
displayModeNormal(pageData);
|
||||
} else if (mode == 'C') {
|
||||
displayModeConfig();
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
};
|
||||
|
||||
static Page *createPage(CommonData &common){
|
||||
return new PageAnchor(common);
|
||||
}
|
||||
|
||||
/**
|
||||
* with the code below we make this page known to the PageTask
|
||||
* we give it a type (name) that can be selected in the config
|
||||
* we define which function is to be called
|
||||
* and we provide the number of user parameters we expect
|
||||
* this will be number of BoatValue pointers in pageData.values
|
||||
*/
|
||||
PageDescription registerPageAnchor(
|
||||
"Anchor", // Page name
|
||||
createPage, // Action
|
||||
0, // Number of bus values depends on selection in Web configuration
|
||||
{"DBS", "HDT", "AWS", "AWD", "LAT", "LON", "HDOP"}, // Names of bus values undepends on selection in Web configuration (refer GwBoatData.h)
|
||||
true // Show display header on/off
|
||||
);
|
||||
|
||||
#endif
|
||||
@@ -31,6 +31,15 @@ bool homevalid = false; // homelat and homelon are valid
|
||||
PageClock(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageClock");
|
||||
|
||||
// WIP time source
|
||||
#ifdef BOARD_OBP60S3
|
||||
String use_rtc = common.config->getString(common.config->useRTC);
|
||||
if (use_rtc == "off") {
|
||||
source = 'G';
|
||||
}
|
||||
#endif
|
||||
|
||||
simulation = common.config->getBool(common.config->useSimuData);
|
||||
timezone = common.config->getString(common.config->timeZone).toDouble();
|
||||
homelat = common.config->getString(common.config->homeLAT).toDouble();
|
||||
@@ -100,9 +109,10 @@ bool homevalid = false; // homelat and homelon are valid
|
||||
static String svalue5old = "";
|
||||
static String svalue6old = "";
|
||||
|
||||
double value1 = 0;
|
||||
double value2 = 0;
|
||||
double value3 = 0;
|
||||
double value1 = 0; // GPS time
|
||||
double value2 = 0; // GPS date FIXME date defined as uint32_t!
|
||||
double value3 = 0; // HDOP
|
||||
bool gpsvalid = false;
|
||||
|
||||
// Get config data
|
||||
String lengthformat = config->getString(config->lengthFormat);
|
||||
@@ -155,6 +165,9 @@ bool homevalid = false; // homelat and homelon are valid
|
||||
unit3old = unit3; // Save old unit
|
||||
}
|
||||
|
||||
// GPS date and time are valid and can be used
|
||||
gpsvalid = (valid1 && valid2 && valid3);
|
||||
|
||||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
@@ -163,7 +176,7 @@ bool homevalid = false; // homelat and homelon are valid
|
||||
|
||||
// Logging boat values
|
||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageClock, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2);
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageClock, %s:%f, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
@@ -231,7 +244,7 @@ bool homevalid = false; // homelat and homelon are valid
|
||||
|
||||
// Show values sunrise
|
||||
String sunrise = "---";
|
||||
if ((valid1 and valid2 and valid3 == true) or (homevalid and commonData->data.rtcValid)) {
|
||||
if (((source == 'G') and gpsvalid) or (homevalid and commonData->data.rtcValid)) {
|
||||
sunrise = String(commonData->sundata.sunriseHour) + ":" + String(commonData->sundata.sunriseMinute + 100).substring(1);
|
||||
svalue5old = sunrise;
|
||||
} else if (simulation) {
|
||||
@@ -251,7 +264,7 @@ bool homevalid = false; // homelat and homelon are valid
|
||||
|
||||
// Show values sunset
|
||||
String sunset = "---";
|
||||
if ((valid1 and valid2 and valid3 == true) or (homevalid and commonData->data.rtcValid)) {
|
||||
if (((source == 'G') and gpsvalid) or (homevalid and commonData->data.rtcValid)) {
|
||||
sunset = String(commonData->sundata.sunsetHour) + ":" + String(commonData->sundata.sunsetMinute + 100).substring(1);
|
||||
svalue6old = sunset;
|
||||
} else if (simulation) {
|
||||
|
||||
153
lib/obp60task/PageSkyView.cpp
Normal file
153
lib/obp60task/PageSkyView.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
|
||||
/*
|
||||
* SkyView / Satellites
|
||||
*/
|
||||
|
||||
class PageSkyView : public Page
|
||||
{
|
||||
public:
|
||||
PageSkyView(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Show PageSkyView");
|
||||
}
|
||||
|
||||
int handleKey(int key){
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0; // Commit the key
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData) {
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
// Get config data
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
String displaycolor = config->getString(config->displaycolor);
|
||||
String backlightMode = config->getString(config->backlight);
|
||||
|
||||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageSkyView");
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
|
||||
// current position
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
|
||||
GwApi::BoatValue *bv_lat = pageData.values[0];
|
||||
String sv_lat = formatValue(bv_lat, *commonData).svalue;
|
||||
//getdisplay().setCursor(300, 40);
|
||||
//getdisplay().print(sv_lat);
|
||||
|
||||
GwApi::BoatValue *bv_lon = pageData.values[1];
|
||||
String sv_lon = formatValue(bv_lon, *commonData).svalue;
|
||||
//getdisplay().setCursor(300, 60);
|
||||
//getdisplay().print(sv_lon);
|
||||
|
||||
GwApi::BoatValue *bv_hdop = pageData.values[2];
|
||||
String sv_hdop = formatValue(bv_hdop, *commonData).svalue;
|
||||
//getdisplay().setCursor(300, 80);
|
||||
//getdisplay().print(sv_hdop);
|
||||
|
||||
// sky view
|
||||
Point c = {130, 148};
|
||||
uint16_t r = 125;
|
||||
uint16_t r1 = r / 2;
|
||||
|
||||
getdisplay().fillCircle(c.x, c.y, r, commonData->bgcolor);
|
||||
getdisplay().drawCircle(c.x, c.y, r + 1, commonData->fgcolor);
|
||||
getdisplay().drawCircle(c.x, c.y, r + 2, commonData->fgcolor);
|
||||
getdisplay().drawCircle(c.x, c.y, r1, commonData->fgcolor);
|
||||
|
||||
// separation lines
|
||||
getdisplay().drawLine(c.x - r, c.y, c.x + r, c.y, commonData->fgcolor);
|
||||
getdisplay().drawLine(c.x, c.y - r, c.x, c.y + r, commonData->fgcolor);
|
||||
Point p = {c.x, c.y - r};
|
||||
Point p1, p2;
|
||||
p1 = rotatePoint(c, p, 45);
|
||||
p2 = rotatePoint(c, p, 45 + 180);
|
||||
getdisplay().drawLine(p1.x, p1.y, p2.x, p2.y, commonData->fgcolor);
|
||||
p1 = rotatePoint(c, p, -45);
|
||||
p2 = rotatePoint(c, p, -45 + 180);
|
||||
getdisplay().drawLine(p1.x, p1.y, p2.x, p2.y, commonData->fgcolor);
|
||||
|
||||
// directions
|
||||
|
||||
int16_t x1, y1;
|
||||
uint16_t w, h;
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
|
||||
getdisplay().getTextBounds("N", 0, 150, &x1, &y1, &w, &h);
|
||||
getdisplay().setCursor(c.x - w / 2, c.y - r + h + 2);
|
||||
getdisplay().print("N");
|
||||
|
||||
getdisplay().getTextBounds("S", 0, 150, &x1, &y1, &w, &h);
|
||||
getdisplay().setCursor(c.x - w / 2, c.y + r - 2);
|
||||
getdisplay().print("S");
|
||||
|
||||
getdisplay().getTextBounds("E", 0, 150, &x1, &y1, &w, &h);
|
||||
getdisplay().setCursor(c.x + r - w - 2, c.y + h / 2);
|
||||
getdisplay().print("E");
|
||||
|
||||
getdisplay().getTextBounds("W", 0, 150, &x1, &y1, &w, &h);
|
||||
getdisplay().setCursor(c.x - r + 2 , c.y + h / 2);
|
||||
getdisplay().print("W");
|
||||
|
||||
// satellites
|
||||
|
||||
|
||||
// Signal / Noise bars
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(325, 34);
|
||||
getdisplay().print("SNR");
|
||||
getdisplay().drawRect(270, 20, 125, 257, commonData->fgcolor);
|
||||
for (int i = 0; i < 12; i++) {
|
||||
uint16_t y = 29 + (i + 1) * 20;
|
||||
getdisplay().setCursor(276, y);
|
||||
char buffer[3];
|
||||
snprintf(buffer, 3, "%02d", i+1);
|
||||
getdisplay().print(String(buffer));
|
||||
getdisplay().drawRect(305, y-12, 85, 14, commonData->fgcolor);
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
};
|
||||
|
||||
static Page* createPage(CommonData &common){
|
||||
return new PageSkyView(common);
|
||||
}
|
||||
|
||||
/**
|
||||
* with the code below we make this page known to the PageTask
|
||||
* we give it a type (name) that can be selected in the config
|
||||
* we define which function is to be called
|
||||
* and we provide the number of user parameters we expect
|
||||
* this will be number of BoatValue pointers in pageData.values
|
||||
*/
|
||||
PageDescription registerPageSkyView(
|
||||
"SkyView", // Page name
|
||||
createPage, // Action
|
||||
0, // Number of bus values depends on selection in Web configuration
|
||||
{"LAT", "LON", "HDOP"}, // Bus values we need in the page
|
||||
true // Show display header on/off
|
||||
);
|
||||
|
||||
#endif
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
#include "ConfigMenu.h"
|
||||
#include "images/logo64.xbm"
|
||||
#include <esp32/clk.h>
|
||||
#include "qrcode.h"
|
||||
@@ -25,37 +26,377 @@
|
||||
* Consists of some sub-pages with following content:
|
||||
* 1. Hard and software information
|
||||
* 2. System settings
|
||||
* 3. NMEA2000 device list
|
||||
* 3. System configuration: running and NVRAM
|
||||
* 4. NMEA2000 device list
|
||||
* 5. SD Card information if available
|
||||
*
|
||||
* TODO
|
||||
* - setCpuFrequencyMhz(80|160|240);
|
||||
* - Accesspoint / ! Änderung im Gatewaycode erforderlich?
|
||||
* if (! isApActive()) {
|
||||
* wifiSSID = config->getString(config->wifiSSID);
|
||||
* wifiPass = config->getString(config->wifiPass);
|
||||
* wifiSoftAP(wifiSSID, wifiPass);
|
||||
* }
|
||||
* - Power mode
|
||||
* powerInit(powermode);
|
||||
*/
|
||||
|
||||
class PageSystem : public Page
|
||||
{
|
||||
uint64_t chipid;
|
||||
bool simulation;
|
||||
bool sdcard;
|
||||
String buzzer_mode;
|
||||
uint8_t buzzer_power;
|
||||
String cpuspeed;
|
||||
String rtc_module;
|
||||
String gps_module;
|
||||
String env_module;
|
||||
private:
|
||||
GwConfigHandler *config;
|
||||
GwLog *logger;
|
||||
|
||||
String batt_sensor;
|
||||
String solar_sensor;
|
||||
String gen_sensor;
|
||||
String rot_sensor;
|
||||
double homelat;
|
||||
double homelon;
|
||||
// NVRAM config options
|
||||
String flashLED;
|
||||
|
||||
char mode = 'N'; // (N)ormal, (S)ettings, (D)evice list, (C)ard
|
||||
// Generic data access
|
||||
|
||||
uint64_t chipid;
|
||||
bool simulation;
|
||||
bool sdcard;
|
||||
String buzzer_mode;
|
||||
uint8_t buzzer_power;
|
||||
String cpuspeed;
|
||||
String rtc_module;
|
||||
String gps_module;
|
||||
String env_module;
|
||||
|
||||
String batt_sensor;
|
||||
String solar_sensor;
|
||||
String gen_sensor;
|
||||
String rot_sensor;
|
||||
double homelat;
|
||||
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
|
||||
mode = 'S';
|
||||
} else if (mode == 'S') { // Settings
|
||||
mode = 'C';
|
||||
} else if (mode == 'C') { // Config
|
||||
mode = 'D';
|
||||
} else if (mode == 'D') { // Device list
|
||||
if (sdcard) {
|
||||
mode = 'A'; // SD-Card
|
||||
} else {
|
||||
mode = 'N';
|
||||
}
|
||||
} else {
|
||||
mode = 'N';
|
||||
}
|
||||
}
|
||||
|
||||
void decMode() {
|
||||
if (mode == 'N') {
|
||||
if (sdcard) {
|
||||
mode = 'A';
|
||||
} else {
|
||||
mode = 'D';
|
||||
}
|
||||
} else if (mode == 'S') { // Settings
|
||||
mode = 'N';
|
||||
} else if (mode == 'C') { // Config
|
||||
mode = 'S';
|
||||
} else if (mode == 'D') { // Device list
|
||||
mode = 'C';
|
||||
} else {
|
||||
mode = 'D';
|
||||
}
|
||||
}
|
||||
|
||||
void displayModeNormal() {
|
||||
// Default system page view
|
||||
|
||||
uint16_t y0 = 155;
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(8, 48);
|
||||
getdisplay().print("System information");
|
||||
|
||||
getdisplay().drawXBitmap(320, 25, logo64_bits, logo64_width, logo64_height, commonData->fgcolor);
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
|
||||
char ssid[13];
|
||||
snprintf(ssid, 13, "%04X%08X", (uint16_t)(chipid >> 32), (uint32_t)chipid);
|
||||
displayBarcode(String(ssid), 320, 200, 2);
|
||||
getdisplay().setCursor(8, 70);
|
||||
getdisplay().print(String("MCUDEVICE-") + String(ssid));
|
||||
|
||||
getdisplay().setCursor(8, 95);
|
||||
getdisplay().print("Firmware version: ");
|
||||
getdisplay().setCursor(150, 95);
|
||||
getdisplay().print(VERSINFO);
|
||||
|
||||
getdisplay().setCursor(8, 113);
|
||||
getdisplay().print("Board version: ");
|
||||
getdisplay().setCursor(150, 113);
|
||||
getdisplay().print(BOARDINFO);
|
||||
getdisplay().print(String(" HW ") + String(PCBINFO));
|
||||
|
||||
getdisplay().setCursor(8, 131);
|
||||
getdisplay().print("Display version: ");
|
||||
getdisplay().setCursor(150, 131);
|
||||
getdisplay().print(DISPLAYINFO);
|
||||
getdisplay().print("; GxEPD2 v");
|
||||
getdisplay().print(GXEPD2INFO);
|
||||
|
||||
getdisplay().setCursor(8, 265);
|
||||
#ifdef BOARD_OBP60S3
|
||||
getdisplay().print("Press STBY to enter deep sleep mode");
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
getdisplay().print("Press wheel to enter deep sleep mode");
|
||||
#endif
|
||||
|
||||
// Flash memory size
|
||||
uint32_t flash_size = ESP.getFlashChipSize();
|
||||
getdisplay().setCursor(8, y0);
|
||||
getdisplay().print("FLASH:");
|
||||
getdisplay().setCursor(90, y0);
|
||||
getdisplay().print(String(flash_size / 1024) + String(" kB"));
|
||||
|
||||
// PSRAM memory size
|
||||
uint32_t psram_size = ESP.getPsramSize();
|
||||
getdisplay().setCursor(8, y0 + 16);
|
||||
getdisplay().print("PSRAM:");
|
||||
getdisplay().setCursor(90, y0 + 16);
|
||||
getdisplay().print(String(psram_size / 1024) + String(" kB"));
|
||||
|
||||
// FRAM available / status
|
||||
getdisplay().setCursor(8, y0 + 32);
|
||||
getdisplay().print("FRAM:");
|
||||
getdisplay().setCursor(90, y0 + 32);
|
||||
getdisplay().print(hasFRAM ? "available" : "not found");
|
||||
|
||||
#ifdef BOARD_OBP40S3
|
||||
// SD-Card
|
||||
getdisplay().setCursor(8, y0 + 48);
|
||||
getdisplay().print("SD-Card:");
|
||||
getdisplay().setCursor(90, y0 + 48);
|
||||
if (sdcard) {
|
||||
uint64_t cardsize = SD.cardSize() / (1024 * 1024);
|
||||
getdisplay().print(String(cardsize) + String(" MB"));
|
||||
} else {
|
||||
getdisplay().print("off");
|
||||
}
|
||||
#endif
|
||||
|
||||
// CPU speed config / active
|
||||
getdisplay().setCursor(202, y0);
|
||||
getdisplay().print("CPU speed:");
|
||||
getdisplay().setCursor(300, y0);
|
||||
getdisplay().print(cpuspeed);
|
||||
getdisplay().print(" / ");
|
||||
int cpu_freq = esp_clk_cpu_freq() / 1000000;
|
||||
getdisplay().print(String(cpu_freq));
|
||||
|
||||
// total RAM free
|
||||
int Heap_free = esp_get_free_heap_size();
|
||||
getdisplay().setCursor(202, y0 + 16);
|
||||
getdisplay().print("Total free:");
|
||||
getdisplay().setCursor(300, y0 + 16);
|
||||
getdisplay().print(String(Heap_free));
|
||||
|
||||
// RAM free for task
|
||||
int RAM_free = uxTaskGetStackHighWaterMark(NULL);
|
||||
getdisplay().setCursor(202, y0 + 32);
|
||||
getdisplay().print("Task free:");
|
||||
getdisplay().setCursor(300, y0 + 32);
|
||||
getdisplay().print(String(RAM_free));
|
||||
}
|
||||
|
||||
void displayModeConfig() {
|
||||
// Configuration interface
|
||||
|
||||
uint16_t x0 = 16;
|
||||
uint16_t y0 = 80;
|
||||
uint16_t dy = 20;
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(8, 48);
|
||||
getdisplay().print("System configuration");
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
|
||||
/*getdisplay().setCursor(x0, y0);
|
||||
getdisplay().print("CPU speed: 80 | 160 | 240");
|
||||
getdisplay().setCursor(x0, y0 + 1 * dy);
|
||||
getdisplay().print("Power mode: Max | 5V | Min");
|
||||
getdisplay().setCursor(x0, y0 + 2 * dy);
|
||||
getdisplay().print("Accesspoint: On | Off");
|
||||
|
||||
// TODO Change NVRAM-preferences settings here
|
||||
getdisplay().setCursor(x0, y0 + 4 * dy);
|
||||
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() {
|
||||
// View some of the current settings
|
||||
|
||||
const uint16_t x0 = 8;
|
||||
const uint16_t y0 = 72;
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(x0, 48);
|
||||
getdisplay().print("System settings");
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
|
||||
// left column
|
||||
getdisplay().setCursor(x0, y0);
|
||||
getdisplay().print("Simulation:");
|
||||
getdisplay().setCursor(120, y0);
|
||||
getdisplay().print(simulation ? "on" : "off");
|
||||
|
||||
getdisplay().setCursor(x0, y0 + 16);
|
||||
getdisplay().print("Environment:");
|
||||
getdisplay().setCursor(120, y0 + 16);
|
||||
getdisplay().print(env_module);
|
||||
|
||||
getdisplay().setCursor(x0, y0 + 32);
|
||||
getdisplay().print("Buzzer:");
|
||||
getdisplay().setCursor(120, y0 + 32);
|
||||
getdisplay().print(buzzer_mode);
|
||||
|
||||
getdisplay().setCursor(x0, y0 + 64);
|
||||
getdisplay().print("GPS:");
|
||||
getdisplay().setCursor(120, y0 + 64);
|
||||
getdisplay().print(gps_module);
|
||||
|
||||
getdisplay().setCursor(x0, y0 + 80);
|
||||
getdisplay().print("RTC:");
|
||||
getdisplay().setCursor(120, y0 + 80);
|
||||
getdisplay().print(rtc_module);
|
||||
|
||||
getdisplay().setCursor(x0, y0 + 96);
|
||||
getdisplay().print("Wifi:");
|
||||
getdisplay().setCursor(120, y0 + 96);
|
||||
getdisplay().print(commonData->status.wifiApOn ? "on" : "off");
|
||||
|
||||
// Home location
|
||||
getdisplay().setCursor(x0, y0 + 128);
|
||||
getdisplay().print("Home Lat.:");
|
||||
drawTextRalign(230, y0 + 128, formatLatitude(homelat));
|
||||
getdisplay().setCursor(x0, y0 + 144);
|
||||
getdisplay().print("Home Lon.:");
|
||||
drawTextRalign(230, y0 + 144, formatLongitude(homelon));
|
||||
|
||||
// right column
|
||||
getdisplay().setCursor(202, y0);
|
||||
getdisplay().print("Batt. sensor:");
|
||||
getdisplay().setCursor(320, y0);
|
||||
getdisplay().print(batt_sensor);
|
||||
|
||||
// Solar sensor
|
||||
getdisplay().setCursor(202, y0 + 16);
|
||||
getdisplay().print("Solar sensor:");
|
||||
getdisplay().setCursor(320, y0 + 16);
|
||||
getdisplay().print(solar_sensor);
|
||||
|
||||
// Generator sensor
|
||||
getdisplay().setCursor(202, y0 + 32);
|
||||
getdisplay().print("Gen. sensor:");
|
||||
getdisplay().setCursor(320, y0 + 32);
|
||||
getdisplay().print(gen_sensor);
|
||||
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Backlight infos
|
||||
getdisplay().setCursor(202, y0 + 64);
|
||||
getdisplay().print("Backlight:");
|
||||
getdisplay().setCursor(320, y0 + 64);
|
||||
getdisplay().printf("%d%%", commonData->backlight.brightness);
|
||||
// TODO test function with OBP60 device
|
||||
getdisplay().setCursor(202, y0 + 80);
|
||||
getdisplay().print("Bl color:");
|
||||
getdisplay().setCursor(320, y0 + 80);
|
||||
getdisplay().print(commonData->backlight.color.toName());
|
||||
getdisplay().setCursor(202, y0 + 96);
|
||||
getdisplay().print("Bl mode:");
|
||||
getdisplay().setCursor(320, y0 + 96);
|
||||
getdisplay().print(commonData->backlight.mode);
|
||||
// TODO Buzzer mode and power
|
||||
#endif
|
||||
|
||||
// Gyro sensor
|
||||
// WIP / FEATURE
|
||||
}
|
||||
|
||||
void displayModeSDCard() {
|
||||
// SD card info
|
||||
uint16_t x0 = 20;
|
||||
uint16_t y0 = 72;
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(8, 48);
|
||||
getdisplay().print("SD Card info");
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(x0, y0);
|
||||
getdisplay().print("Work in progress...");
|
||||
}
|
||||
|
||||
void displayModeDevicelist() {
|
||||
// NMEA2000 device list
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(8, 48);
|
||||
getdisplay().print("NMEA2000 device list");
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(20, 80);
|
||||
getdisplay().print("RxD: ");
|
||||
getdisplay().print(String(commonData->status.n2kRx));
|
||||
getdisplay().setCursor(20, 100);
|
||||
getdisplay().print("TxD: ");
|
||||
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);
|
||||
}
|
||||
flashLED = common.config->getString(common.config->flashLED);
|
||||
|
||||
chipid = ESP.getEfuseMac();
|
||||
simulation = common.config->getBool(common.config->useSimuData);
|
||||
#ifdef BOARD_OBP40S3
|
||||
@@ -74,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(){
|
||||
@@ -90,19 +449,7 @@ public:
|
||||
// Switch display mode
|
||||
commonData->logger->logDebug(GwLog::LOG, "System keyboard handler");
|
||||
if (key == 2) {
|
||||
if (mode == 'N') {
|
||||
mode = 'S';
|
||||
} else if (mode == 'S') {
|
||||
mode = 'D';
|
||||
} else if (mode == 'D') {
|
||||
if (sdcard) {
|
||||
mode = 'C';
|
||||
} else {
|
||||
mode = 'N';
|
||||
}
|
||||
} else {
|
||||
mode = 'N';
|
||||
}
|
||||
incMode();
|
||||
if (hasFRAM) fram.write(FRAM_SYSTEM_MODE, mode);
|
||||
return 0;
|
||||
}
|
||||
@@ -126,8 +473,13 @@ public:
|
||||
}
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
// grab cursor keys to disable page navigation
|
||||
if (key == 9 or key == 10) {
|
||||
// use cursor keys for local mode navigation
|
||||
if (key == 9) {
|
||||
incMode();
|
||||
return 0;
|
||||
}
|
||||
if (key == 10) {
|
||||
decMode();
|
||||
return 0;
|
||||
}
|
||||
// standby / deep sleep
|
||||
@@ -168,225 +520,35 @@ public:
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
// Get config data
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
|
||||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
if(flashLED == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageSystem");
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
uint16_t x0 = 8; // left column
|
||||
uint16_t y0 = 48; // data table starts here
|
||||
// Logging page information
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageSystem, Mode=%c", mode);
|
||||
|
||||
// Set display in partial refresh mode
|
||||
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height());
|
||||
|
||||
if (mode == 'N') {
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(8, 48);
|
||||
getdisplay().print("System Information");
|
||||
|
||||
getdisplay().drawXBitmap(320, 25, logo64_bits, logo64_width, logo64_height, commonData->fgcolor);
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
y0 = 155;
|
||||
|
||||
char ssid[13];
|
||||
snprintf(ssid, 13, "%04X%08X", (uint16_t)(chipid >> 32), (uint32_t)chipid);
|
||||
displayBarcode(String(ssid), 320, 200, 2);
|
||||
getdisplay().setCursor(8, 70);
|
||||
getdisplay().print(String("MCUDEVICE-") + String(ssid));
|
||||
|
||||
getdisplay().setCursor(8, 95);
|
||||
getdisplay().print("Firmware version: ");
|
||||
getdisplay().setCursor(150, 95);
|
||||
getdisplay().print(VERSINFO);
|
||||
|
||||
getdisplay().setCursor(8, 113);
|
||||
getdisplay().print("Board version: ");
|
||||
getdisplay().setCursor(150, 113);
|
||||
getdisplay().print(BOARDINFO);
|
||||
getdisplay().print(String(" HW ") + String(PCBINFO));
|
||||
|
||||
getdisplay().setCursor(8, 131);
|
||||
getdisplay().print("Display version: ");
|
||||
getdisplay().setCursor(150, 131);
|
||||
getdisplay().print(DISPLAYINFO);
|
||||
getdisplay().print("; GxEPD2 v");
|
||||
getdisplay().print(GXEPD2INFO);
|
||||
|
||||
getdisplay().setCursor(8, 265);
|
||||
#ifdef BOARD_OBP60S3
|
||||
getdisplay().print("Press STBY to enter deep sleep mode");
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
getdisplay().print("Press wheel to enter deep sleep mode");
|
||||
#endif
|
||||
|
||||
// Flash memory size
|
||||
uint32_t flash_size = ESP.getFlashChipSize();
|
||||
getdisplay().setCursor(8, y0);
|
||||
getdisplay().print("FLASH:");
|
||||
getdisplay().setCursor(90, y0);
|
||||
getdisplay().print(String(flash_size / 1024) + String(" kB"));
|
||||
|
||||
// PSRAM memory size
|
||||
uint32_t psram_size = ESP.getPsramSize();
|
||||
getdisplay().setCursor(8, y0 + 16);
|
||||
getdisplay().print("PSRAM:");
|
||||
getdisplay().setCursor(90, y0 + 16);
|
||||
getdisplay().print(String(psram_size / 1024) + String(" kB"));
|
||||
|
||||
// FRAM available / status
|
||||
getdisplay().setCursor(8, y0 + 32);
|
||||
getdisplay().print("FRAM:");
|
||||
getdisplay().setCursor(90, y0 + 32);
|
||||
getdisplay().print(hasFRAM ? "available" : "not found");
|
||||
|
||||
#ifdef BOARD_OBP40S3
|
||||
// SD-Card
|
||||
getdisplay().setCursor(8, y0 + 48);
|
||||
getdisplay().print("SD-Card:");
|
||||
getdisplay().setCursor(90, y0 + 48);
|
||||
if (sdcard) {
|
||||
uint64_t cardsize = SD.cardSize() / (1024 * 1024);
|
||||
getdisplay().print(String(cardsize) + String(" MB"));
|
||||
} else {
|
||||
getdisplay().print("off");
|
||||
}
|
||||
#endif
|
||||
|
||||
// CPU speed config / active
|
||||
getdisplay().setCursor(202, y0);
|
||||
getdisplay().print("CPU speed:");
|
||||
getdisplay().setCursor(300, y0);
|
||||
getdisplay().print(cpuspeed);
|
||||
getdisplay().print(" / ");
|
||||
int cpu_freq = esp_clk_cpu_freq() / 1000000;
|
||||
getdisplay().print(String(cpu_freq));
|
||||
|
||||
// total RAM free
|
||||
int Heap_free = esp_get_free_heap_size();
|
||||
getdisplay().setCursor(202, y0 + 16);
|
||||
getdisplay().print("Total free:");
|
||||
getdisplay().setCursor(300, y0 + 16);
|
||||
getdisplay().print(String(Heap_free));
|
||||
|
||||
// RAM free for task
|
||||
int RAM_free = uxTaskGetStackHighWaterMark(NULL);
|
||||
getdisplay().setCursor(202, y0 + 32);
|
||||
getdisplay().print("Task free:");
|
||||
getdisplay().setCursor(300, y0 + 32);
|
||||
getdisplay().print(String(RAM_free));
|
||||
|
||||
} else if (mode == 'S') {
|
||||
// Settings
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(x0, 48);
|
||||
getdisplay().print("System settings");
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
x0 = 8;
|
||||
y0 = 72;
|
||||
|
||||
// left column
|
||||
getdisplay().setCursor(x0, y0);
|
||||
getdisplay().print("Simulation:");
|
||||
getdisplay().setCursor(120, y0);
|
||||
getdisplay().print(simulation ? "on" : "off");
|
||||
|
||||
getdisplay().setCursor(x0, y0 + 16);
|
||||
getdisplay().print("Environment:");
|
||||
getdisplay().setCursor(120, y0 + 16);
|
||||
getdisplay().print(env_module);
|
||||
|
||||
getdisplay().setCursor(x0, y0 + 32);
|
||||
getdisplay().print("Buzzer:");
|
||||
getdisplay().setCursor(120, y0 + 32);
|
||||
getdisplay().print(buzzer_mode);
|
||||
|
||||
getdisplay().setCursor(x0, y0 + 64);
|
||||
getdisplay().print("GPS:");
|
||||
getdisplay().setCursor(120, y0 + 64);
|
||||
getdisplay().print(gps_module);
|
||||
|
||||
getdisplay().setCursor(x0, y0 + 80);
|
||||
getdisplay().print("RTC:");
|
||||
getdisplay().setCursor(120, y0 + 80);
|
||||
getdisplay().print(rtc_module);
|
||||
|
||||
getdisplay().setCursor(x0, y0 + 96);
|
||||
getdisplay().print("Wifi:");
|
||||
getdisplay().setCursor(120, y0 + 96);
|
||||
getdisplay().print(commonData->status.wifiApOn ? "on" : "off");
|
||||
|
||||
// Home location
|
||||
getdisplay().setCursor(x0, y0 + 128);
|
||||
getdisplay().print("Home Lat.:");
|
||||
getdisplay().setCursor(120, y0 + 128);
|
||||
getdisplay().print(formatLatitude(homelat));
|
||||
getdisplay().setCursor(x0, y0 + 144);
|
||||
getdisplay().print("Home Lon.:");
|
||||
getdisplay().setCursor(120, y0 + 144);
|
||||
getdisplay().print(formatLongitude(homelon));
|
||||
|
||||
// right column
|
||||
getdisplay().setCursor(202, y0);
|
||||
getdisplay().print("Batt. sensor:");
|
||||
getdisplay().setCursor(320, y0);
|
||||
getdisplay().print(batt_sensor);
|
||||
|
||||
// Solar sensor
|
||||
getdisplay().setCursor(202, y0 + 16);
|
||||
getdisplay().print("Solar sensor:");
|
||||
getdisplay().setCursor(320, y0 + 16);
|
||||
getdisplay().print(solar_sensor);
|
||||
|
||||
// Generator sensor
|
||||
getdisplay().setCursor(202, y0 + 32);
|
||||
getdisplay().print("Gen. sensor:");
|
||||
getdisplay().setCursor(320, y0 + 32);
|
||||
getdisplay().print(gen_sensor);
|
||||
|
||||
// Gyro sensor
|
||||
|
||||
} else if (mode == 'C') {
|
||||
// Card info
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(8, 48);
|
||||
getdisplay().print("SD Card info");
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
|
||||
x0 = 20;
|
||||
y0 = 72;
|
||||
getdisplay().setCursor(x0, y0);
|
||||
getdisplay().print("Work in progress...");
|
||||
|
||||
|
||||
} else {
|
||||
// NMEA2000 device list
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(8, 48);
|
||||
getdisplay().print("NMEA2000 device list");
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(20, 80);
|
||||
getdisplay().print("RxD: ");
|
||||
getdisplay().print(String(commonData->status.n2kRx));
|
||||
getdisplay().setCursor(20, 100);
|
||||
getdisplay().print("TxD: ");
|
||||
getdisplay().print(String(commonData->status.n2kTx));
|
||||
// call current system page
|
||||
switch (mode) {
|
||||
case 'N':
|
||||
displayModeNormal();
|
||||
break;
|
||||
case 'S':
|
||||
displayModeSettings();
|
||||
break;
|
||||
case 'C':
|
||||
displayModeConfig();
|
||||
break;
|
||||
case 'A':
|
||||
displayModeSDCard();
|
||||
break;
|
||||
case 'D':
|
||||
displayModeDevicelist();
|
||||
break;
|
||||
}
|
||||
|
||||
// Update display
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
@@ -6,16 +7,20 @@
|
||||
|
||||
class PageVoltage : public Page
|
||||
{
|
||||
bool init = false; // Marker for init done
|
||||
uint8_t average = 0; // Average type [0...3], 0=off, 1=10s, 2=60s, 3=300s
|
||||
bool trend = true; // Trend indicator [0|1], 0=off, 1=on
|
||||
double raw = 0;
|
||||
char mode = 'D'; // display mode (A)nalog | (D)igital
|
||||
private:
|
||||
bool init = false; // Marker for init done
|
||||
uint8_t average = 0; // Average type [0...3], 0=off, 1=10s, 2=60s, 3=300s
|
||||
bool trend = true; // Trend indicator [0|1], 0=off, 1=on
|
||||
double raw = 0;
|
||||
char mode = 'D'; // display mode (A)nalog | (D)igital
|
||||
|
||||
public:
|
||||
PageVoltage(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageVoltage");
|
||||
config = commonData->config;
|
||||
logger = commonData->logger;
|
||||
|
||||
logger->logDebug(GwLog::LOG,"Instantiate PageVoltage");
|
||||
if (hasFRAM) {
|
||||
average = fram.read(FRAM_VOLTAGE_AVG);
|
||||
trend = fram.read(FRAM_VOLTAGE_TREND);
|
||||
@@ -23,6 +28,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
~PageVoltage(){
|
||||
logger->logDebug(GwLog::LOG,"Destroy PageVoltage");
|
||||
}
|
||||
|
||||
virtual void setupKeys(){
|
||||
Page::setupKeys();
|
||||
commonData->keydata[0].label = "AVG";
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include "GwApi.h"
|
||||
@@ -98,6 +100,10 @@ typedef struct{
|
||||
uint8_t length_sec; // seconds until alarm disappeares without user interaction
|
||||
} AlarmData;
|
||||
|
||||
typedef struct{
|
||||
int voltage = 0;
|
||||
} AvgData;
|
||||
|
||||
typedef struct{
|
||||
GwApi::Status status;
|
||||
GwLog *logger=NULL;
|
||||
@@ -107,6 +113,7 @@ typedef struct{
|
||||
TouchKeyData keydata[6];
|
||||
BacklightData backlight;
|
||||
AlarmData alarm;
|
||||
AvgData avgdata;
|
||||
GwApi::BoatValue *time=NULL;
|
||||
GwApi::BoatValue *date=NULL;
|
||||
uint16_t fgcolor;
|
||||
@@ -117,9 +124,11 @@ typedef struct{
|
||||
|
||||
//a base class that all pages must inherit from
|
||||
class Page{
|
||||
protected:
|
||||
protected:
|
||||
CommonData *commonData;
|
||||
public:
|
||||
GwConfigHandler *config;
|
||||
GwLog *logger;
|
||||
public:
|
||||
int refreshtime = 1000;
|
||||
virtual int displayPage(PageData &pageData)=0;
|
||||
virtual void displayNew(PageData &pageData){}
|
||||
|
||||
82
lib/obp60task/README
Normal file
82
lib/obp60task/README
Normal file
@@ -0,0 +1,82 @@
|
||||
Development information
|
||||
=======================
|
||||
|
||||
This file contains some hints concerning building the firmware as well as
|
||||
developing and debugging it.
|
||||
|
||||
|
||||
Git commands
|
||||
------------
|
||||
Some useful commands are
|
||||
|
||||
git status
|
||||
git fetch upstream
|
||||
git diff --name-status upstream/master
|
||||
git checkout upstream/master platformio.ini
|
||||
|
||||
# how to reset my Repo to match norbert's status
|
||||
|
||||
git remote add upstream https://github.com/norbert-walter/esp32-nmea2000-obp60
|
||||
git fetch upstream
|
||||
git checkout master
|
||||
git reset --hard upstream/master
|
||||
git push origin master --force
|
||||
|
||||
|
||||
New pages
|
||||
---------
|
||||
To create a new page for OBP60 the following steps are necessary:
|
||||
|
||||
1. Create a page under /lib/obp60task/PageXXXX.cpp
|
||||
2. Set page name in PageXXXX.cpp on file name
|
||||
3. Register new page in /lib/obp60task/obp60task.cpp in function
|
||||
'registerAllPages'
|
||||
4. Add new page in /lib/obp60task/config.json for each page type or add
|
||||
new page to gen_set.py and run it to auto-generate the relevant
|
||||
section of config.json
|
||||
5. Copy the changes in config.json to config_obp40.json and rename
|
||||
strings accordingly. E.g. obp60 to obp40.
|
||||
|
||||
|
||||
Using Gitpod
|
||||
------------
|
||||
|
||||
Open web page:
|
||||
https://gitpod.io/#https://github.com/norbert-walter/esp32-nmea2000-obp60/tree/master/lib/obp60task
|
||||
|
||||
Input in terminal:
|
||||
cd /workspace/esp32-nmea2000-obp60
|
||||
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run_installing_tools
|
||||
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run_obp60_s3
|
||||
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run_obp40_s3
|
||||
|
||||
Compile result for OBP60:
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/bootloader.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/firmware.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/partitions.bin
|
||||
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-all.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-dev<yyyymmdd>-all.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-dev<yyyymmdd>-update.bin
|
||||
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-all.bin, ready to flash to offset 0x0000
|
||||
|
||||
Compile result for OBP40 (CrowPanel 4.2):
|
||||
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/bootloader.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/firmware.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/partitions.bin
|
||||
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-all.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-dev<yyyymmdd>-all.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-dev<yyyymmdd>-update.bin
|
||||
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-all.bin, ready to flash to offset 0x0000
|
||||
|
||||
|
||||
Debugging tool
|
||||
--------------
|
||||
|
||||
log.txt = text file with error messages from terminal console
|
||||
|
||||
tools/decoder.py -p ESP32S3 -t ~/.platformio/packages/toolchain-xtensa-esp32s3/ -e .pio/build/obp60_s3/firmware.elf log.txt
|
||||
@@ -1,38 +0,0 @@
|
||||
Using Gitpod
|
||||
############
|
||||
|
||||
Open web page:
|
||||
https://gitpod.io/#https://github.com/norbert-walter/esp32-nmea2000-obp60/tree/master/lib/obp60task
|
||||
|
||||
Input in terminal:
|
||||
cd /workspace/esp32-nmea2000-obp60
|
||||
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run_installing_tools
|
||||
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run_obp60_s3
|
||||
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run_obp40_s3
|
||||
|
||||
Compile result for OBP60
|
||||
########################
|
||||
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/bootloader.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/firmware.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/partitions.bin
|
||||
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-all.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-dev20231220-all.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-dev20231220-update.bin
|
||||
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-all.bin, ready to flash to offset 0x0000
|
||||
|
||||
Compile result for OBP40 (CrowPanel 4.2)
|
||||
########################################
|
||||
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/bootloader.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/firmware.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/partitions.bin
|
||||
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-all.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-dev20231220-all.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-dev20231220-update.bin
|
||||
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-all.bin, ready to flash to offset 0x0000
|
||||
|
||||
@@ -75,6 +75,20 @@
|
||||
"obp60":"true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "chainLength",
|
||||
"label": "Anchor Chain Length [m]",
|
||||
"type": "number",
|
||||
"default": "0",
|
||||
"check": "checkMinMax",
|
||||
"min": 0,
|
||||
"max": 255,
|
||||
"description": "The length of the anchor chain [0...255m]",
|
||||
"category": "OBP60 Settings",
|
||||
"capabilities": {
|
||||
"obp60":"true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "fuelTank",
|
||||
"label": "Fuel Tank [l]",
|
||||
@@ -1117,6 +1131,36 @@
|
||||
"obp60":"true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "valueprecision",
|
||||
"label": "Display value precision",
|
||||
"type": "list",
|
||||
"default": "2",
|
||||
"description": "Maximum number of decimal places to display [1|2]",
|
||||
"list": [
|
||||
"1",
|
||||
"2"
|
||||
],
|
||||
"category": "OBP60 Display",
|
||||
"capabilities": {
|
||||
"obp60":"true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "headerFormat",
|
||||
"label": "Header Format",
|
||||
"type": "list",
|
||||
"default":"TEXT",
|
||||
"description": "Header format: Text or Symbols",
|
||||
"list": [
|
||||
{"l":"Text","v":"TEXT"},
|
||||
{"l":"Symbols","v":"ICON"}
|
||||
],
|
||||
"category":"OBP60 Pages",
|
||||
"capabilities": {
|
||||
"obp60":"true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "backlight",
|
||||
"label": "Backlight Mode",
|
||||
@@ -1303,6 +1347,7 @@
|
||||
"default": "Voltage",
|
||||
"description": "Type of page for page 1",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -1318,6 +1363,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -1584,6 +1630,7 @@
|
||||
"default": "WindRose",
|
||||
"description": "Type of page for page 2",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -1599,6 +1646,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -1862,6 +1910,7 @@
|
||||
"default": "OneValue",
|
||||
"description": "Type of page for page 3",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -1877,6 +1926,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -2137,6 +2187,7 @@
|
||||
"default": "TwoValues",
|
||||
"description": "Type of page for page 4",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -2152,6 +2203,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -2409,6 +2461,7 @@
|
||||
"default": "ThreeValues",
|
||||
"description": "Type of page for page 5",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -2424,6 +2477,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -2678,6 +2732,7 @@
|
||||
"default": "FourValues",
|
||||
"description": "Type of page for page 6",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -2693,6 +2748,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -2944,6 +3000,7 @@
|
||||
"default": "FourValues2",
|
||||
"description": "Type of page for page 7",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -2959,6 +3016,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -3207,6 +3265,7 @@
|
||||
"default": "Clock",
|
||||
"description": "Type of page for page 8",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -3222,6 +3281,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -3467,6 +3527,7 @@
|
||||
"default": "RollPitch",
|
||||
"description": "Type of page for page 9",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -3482,6 +3543,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -3724,6 +3786,7 @@
|
||||
"default": "Battery2",
|
||||
"description": "Type of page for page 10",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -3739,6 +3802,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
|
||||
@@ -75,6 +75,20 @@
|
||||
"obp40": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "chainLength",
|
||||
"label": "Anchor Chain Length [m]",
|
||||
"type": "number",
|
||||
"default": "0",
|
||||
"check": "checkMinMax",
|
||||
"min": 0,
|
||||
"max": 255,
|
||||
"description": "The length of the anchor chain [0...255m]",
|
||||
"category": "OBP40 Settings",
|
||||
"capabilities": {
|
||||
"obp40":"true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "fuelTank",
|
||||
"label": "Fuel Tank [l]",
|
||||
@@ -348,7 +362,7 @@
|
||||
"label": "RTC Modul",
|
||||
"type": "list",
|
||||
"default": "off",
|
||||
"description": "Use internal RTC module type [off|DS1388]",
|
||||
"description": "Use RTC module type [off|DS1388]",
|
||||
"list": [
|
||||
"off",
|
||||
"DS1388"
|
||||
@@ -1129,6 +1143,36 @@
|
||||
"obp40": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "valueprecision",
|
||||
"label": "Display value precision",
|
||||
"type": "list",
|
||||
"default": "2",
|
||||
"description": "Maximum number of decimal places to display [1|2]",
|
||||
"list": [
|
||||
"1",
|
||||
"2"
|
||||
],
|
||||
"category": "OBP40 Display",
|
||||
"capabilities": {
|
||||
"obp40":"true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "headerFormat",
|
||||
"label": "Header Format",
|
||||
"type": "list",
|
||||
"default":"TEXT",
|
||||
"description": "Header format: Text or Symbols",
|
||||
"list": [
|
||||
{"l":"Text","v":"TEXT"},
|
||||
{"l":"Symbols","v":"ICON"}
|
||||
],
|
||||
"category":"OBP40 Display",
|
||||
"capabilities": {
|
||||
"obp40":"true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "backlight",
|
||||
"label": "Backlight Mode",
|
||||
@@ -1326,6 +1370,7 @@
|
||||
"default": "Clock",
|
||||
"description": "Type of page for page 1",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -1341,6 +1386,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -1607,6 +1653,7 @@
|
||||
"default": "Wind",
|
||||
"description": "Type of page for page 2",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -1622,6 +1669,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -1885,6 +1933,7 @@
|
||||
"default": "OneValue",
|
||||
"description": "Type of page for page 3",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -1900,6 +1949,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -2160,6 +2210,7 @@
|
||||
"default": "TwoValues",
|
||||
"description": "Type of page for page 4",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -2175,6 +2226,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -2432,6 +2484,7 @@
|
||||
"default": "ThreeValues",
|
||||
"description": "Type of page for page 5",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -2447,6 +2500,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -2701,6 +2755,7 @@
|
||||
"default": "FourValues",
|
||||
"description": "Type of page for page 6",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -2716,6 +2771,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -2967,6 +3023,7 @@
|
||||
"default": "FourValues2",
|
||||
"description": "Type of page for page 7",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -2982,6 +3039,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -3230,6 +3288,7 @@
|
||||
"default": "Fluid",
|
||||
"description": "Type of page for page 8",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -3245,6 +3304,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -3490,6 +3550,7 @@
|
||||
"default": "RollPitch",
|
||||
"description": "Type of page for page 9",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -3505,6 +3566,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
@@ -3747,6 +3809,7 @@
|
||||
"default": "Battery2",
|
||||
"description": "Type of page for page 10",
|
||||
"list": [
|
||||
"Anchor",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
@@ -3762,6 +3825,7 @@
|
||||
"RollPitch",
|
||||
"RudderPosition",
|
||||
"SixValues",
|
||||
"SkyView",
|
||||
"Solar",
|
||||
"ThreeValues",
|
||||
"TwoValues",
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
Debugging tool
|
||||
##############
|
||||
|
||||
log.txt = text file with error messages from terminal console
|
||||
|
||||
tools/decoder.py -p ESP32S3 -t ~/.platformio/packages/toolchain-xtensa-esp32s3/ -e .pio/build/obp60_s3/firmware.elf log.txt
|
||||
@@ -1,12 +0,0 @@
|
||||
git status
|
||||
git fetch upstream
|
||||
git diff --name-status upstream/master
|
||||
git checkout upstream/master platformio.ini
|
||||
|
||||
# how to reset my Repo to match norbert'status
|
||||
|
||||
git remote add upstream https://github.com/norbert-walter/esp32-nmea2000-obp60
|
||||
git fetch upstream
|
||||
git checkout master
|
||||
git reset --hard upstream/master
|
||||
git push origin master --force
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
#include "obp60task.h"
|
||||
#include "Pagedata.h" // Data exchange for pages
|
||||
@@ -54,31 +55,13 @@ void OBP60Init(GwApi *api){
|
||||
|
||||
// Check I2C devices
|
||||
|
||||
|
||||
// Init hardware
|
||||
hardwareInit(api);
|
||||
|
||||
// Init power rail 5.0V
|
||||
// Init power
|
||||
String powermode = api->getConfig()->getConfigItem(api->getConfig()->powerMode,true)->asString();
|
||||
api->getLogger()->logDebug(GwLog::DEBUG,"Power Mode is: %s", powermode.c_str());
|
||||
if(powermode == "Max Power" || powermode == "Only 5.0V"){
|
||||
#ifdef HARDWARE_V21
|
||||
setPortPin(OBP_POWER_50, true); // Power on 5.0V rail
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
setPortPin(OBP_POWER_EPD, true);// Power on ePaper display
|
||||
setPortPin(OBP_POWER_SD, true); // Power on SD card
|
||||
#endif
|
||||
}
|
||||
else{
|
||||
#ifdef HARDWARE_V21
|
||||
setPortPin(OBP_POWER_50, false); // Power off 5.0V rail
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
setPortPin(OBP_POWER_EPD, false);// Power off ePaper display
|
||||
setPortPin(OBP_POWER_SD, false); // Power off SD card
|
||||
#endif
|
||||
}
|
||||
powerInit(powermode);
|
||||
|
||||
#ifdef BOARD_OBP40S3
|
||||
bool sdcard = config->getBool(config->useSDCard);
|
||||
@@ -313,6 +296,10 @@ void registerAllPages(PageList &list){
|
||||
list.add(®isterPageXTETrack);
|
||||
extern PageDescription registerPageFluid;
|
||||
list.add(®isterPageFluid);
|
||||
extern PageDescription registerPageSkyView;
|
||||
list.add(®isterPageSkyView);
|
||||
extern PageDescription registerPageAnchor;
|
||||
list.add(®isterPageAnchor);
|
||||
}
|
||||
|
||||
// Undervoltage detection for shutdown display
|
||||
@@ -336,18 +323,18 @@ void underVoltageDetection(GwApi *api, CommonData &common){
|
||||
setFlashLED(false); // Flash LED Off
|
||||
buzzer(TONE4, 20); // Buzzer tone 4kHz 20ms
|
||||
// Shutdown EInk display
|
||||
getdisplay().setFullWindow(); // Set full Refresh
|
||||
//getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
getdisplay().fillScreen(common.bgcolor);// Clear screen
|
||||
getdisplay().setTextColor(common.fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(65, 150);
|
||||
getdisplay().print("Undervoltage");
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(65, 175);
|
||||
getdisplay().print("Charge battery and restart system");
|
||||
getdisplay().nextPage(); // Partial update
|
||||
getdisplay().powerOff(); // Display power off
|
||||
epd->setFullWindow(); // Set full Refresh
|
||||
//epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
epd->fillScreen(common.bgcolor);// Clear screen
|
||||
epd->setTextColor(common.fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(65, 150);
|
||||
epd->print("Undervoltage");
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(65, 175);
|
||||
epd->print("Charge battery and restart system");
|
||||
epd->nextPage(); // Partial update
|
||||
epd->powerOff(); // Display power off
|
||||
setPortPin(OBP_POWER_EPD, false); // Power off ePaper display
|
||||
setPortPin(OBP_POWER_SD, false); // Power off SD card
|
||||
#else
|
||||
@@ -357,17 +344,17 @@ void underVoltageDetection(GwApi *api, CommonData &common){
|
||||
buzzer(TONE4, 20); // Buzzer tone 4kHz 20ms
|
||||
setPortPin(OBP_POWER_50, false); // Power rail 5.0V Off
|
||||
// Shutdown EInk display
|
||||
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
getdisplay().fillScreen(common.bgcolor);// Clear screen
|
||||
getdisplay().setTextColor(common.fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(65, 150);
|
||||
getdisplay().print("Undervoltage");
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(65, 175);
|
||||
getdisplay().print("To wake up repower system");
|
||||
getdisplay().nextPage(); // Partial update
|
||||
getdisplay().powerOff(); // Display power off
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
epd->fillScreen(common.bgcolor);// Clear screen
|
||||
epd->setTextColor(common.fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(65, 150);
|
||||
epd->print("Undervoltage");
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(65, 175);
|
||||
epd->print("To wake up repower system");
|
||||
epd->nextPage(); // Partial update
|
||||
epd->powerOff(); // Display power off
|
||||
#endif
|
||||
// Stop system
|
||||
while(true){
|
||||
@@ -536,6 +523,7 @@ void OBP60Task(GwApi *api){
|
||||
String systemname = api->getConfig()->getConfigItem(api->getConfig()->systemName,true)->asString();
|
||||
String wifipass = api->getConfig()->getConfigItem(api->getConfig()->apPassword,true)->asString();
|
||||
bool refreshmode = api->getConfig()->getConfigItem(api->getConfig()->refresh,true)->asBoolean();
|
||||
bool symbolmode = (config->getString(config->headerFormat) == "ICON");
|
||||
String fastrefresh = api->getConfig()->getConfigItem(api->getConfig()->fastRefresh,true)->asString();
|
||||
uint fullrefreshtime = uint(api->getConfig()->getConfigItem(api->getConfig()->fullRefreshTime,true)->asInt());
|
||||
#ifdef BOARD_OBP40S3
|
||||
@@ -543,37 +531,37 @@ void OBP60Task(GwApi *api){
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_GDEY042T81
|
||||
getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||
epd->init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||
#else
|
||||
getdisplay().init(115200); // Init for normal displays
|
||||
epd->init(115200); // Init for normal displays
|
||||
#endif
|
||||
|
||||
getdisplay().setRotation(0); // Set display orientation (horizontal)
|
||||
getdisplay().setFullWindow(); // Set full Refresh
|
||||
getdisplay().firstPage(); // set first page
|
||||
getdisplay().fillScreen(commonData.bgcolor);
|
||||
getdisplay().setTextColor(commonData.fgcolor);
|
||||
getdisplay().nextPage(); // Full Refresh
|
||||
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
getdisplay().fillScreen(commonData.bgcolor);
|
||||
getdisplay().nextPage(); // Fast Refresh
|
||||
getdisplay().nextPage(); // Fast Refresh
|
||||
epd->setRotation(0); // Set display orientation (horizontal)
|
||||
epd->setFullWindow(); // Set full Refresh
|
||||
epd->firstPage(); // set first page
|
||||
epd->fillScreen(commonData.bgcolor);
|
||||
epd->setTextColor(commonData.fgcolor);
|
||||
epd->nextPage(); // Full Refresh
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
epd->fillScreen(commonData.bgcolor);
|
||||
epd->nextPage(); // Fast Refresh
|
||||
epd->nextPage(); // Fast Refresh
|
||||
if(String(displaymode) == "Logo + QR Code" || String(displaymode) == "Logo"){
|
||||
getdisplay().fillScreen(commonData.bgcolor);
|
||||
getdisplay().drawBitmap(0, 0, gImage_Logo_OBP_400x300_sw, getdisplay().width(), getdisplay().height(), commonData.fgcolor); // Draw start logo
|
||||
getdisplay().nextPage(); // Fast Refresh
|
||||
getdisplay().nextPage(); // Fast Refresh
|
||||
epd->fillScreen(commonData.bgcolor);
|
||||
epd->drawBitmap(0, 0, gImage_Logo_OBP_400x300_sw, epd->width(), epd->height(), commonData.fgcolor); // Draw start logo
|
||||
epd->nextPage(); // Fast Refresh
|
||||
epd->nextPage(); // Fast Refresh
|
||||
delay(SHOW_TIME); // Logo show time
|
||||
if(String(displaymode) == "Logo + QR Code"){
|
||||
getdisplay().fillScreen(commonData.bgcolor);
|
||||
epd->fillScreen(commonData.bgcolor);
|
||||
qrWiFi(systemname, wifipass, commonData.fgcolor, commonData.bgcolor); // Show QR code for WiFi connection
|
||||
getdisplay().nextPage(); // Fast Refresh
|
||||
getdisplay().nextPage(); // Fast Refresh
|
||||
epd->nextPage(); // Fast Refresh
|
||||
epd->nextPage(); // Fast Refresh
|
||||
delay(SHOW_TIME); // QR code show time
|
||||
}
|
||||
getdisplay().fillScreen(commonData.bgcolor);
|
||||
getdisplay().nextPage(); // Fast Refresh
|
||||
getdisplay().nextPage(); // Fast Refresh
|
||||
epd->fillScreen(commonData.bgcolor);
|
||||
epd->nextPage(); // Fast Refresh
|
||||
epd->nextPage(); // Fast Refresh
|
||||
}
|
||||
|
||||
// Init pages
|
||||
@@ -884,23 +872,23 @@ void OBP60Task(GwApi *api){
|
||||
if(millis() > starttime4 + 4000 && delayedDisplayUpdate == true){
|
||||
starttime1 = millis();
|
||||
starttime2 = millis();
|
||||
getdisplay().setFullWindow(); // Set full update
|
||||
epd->setFullWindow(); // Set full update
|
||||
if(fastrefresh == "true"){
|
||||
getdisplay().nextPage(); // Full update
|
||||
epd->nextPage(); // Full update
|
||||
}
|
||||
else{
|
||||
getdisplay().fillScreen(commonData.fgcolor); // Clear display
|
||||
epd->fillScreen(commonData.fgcolor); // Clear display
|
||||
#ifdef DISPLAY_GDEY042T81
|
||||
getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||
epd->init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||
#else
|
||||
getdisplay().init(115200); // Init for normal displays
|
||||
epd->init(115200); // Init for normal displays
|
||||
#endif
|
||||
getdisplay().firstPage(); // Full update
|
||||
getdisplay().nextPage(); // Full update
|
||||
// getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
// getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||
// getdisplay().nextPage(); // Partial update
|
||||
// getdisplay().nextPage(); // Partial update
|
||||
epd->firstPage(); // Full update
|
||||
epd->nextPage(); // Full update
|
||||
// epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
// epd->fillScreen(commonData.bgcolor); // Clear display
|
||||
// epd->nextPage(); // Partial update
|
||||
// epd->nextPage(); // Partial update
|
||||
}
|
||||
delayedDisplayUpdate = false;
|
||||
}
|
||||
@@ -911,23 +899,23 @@ void OBP60Task(GwApi *api){
|
||||
starttime1 = millis();
|
||||
starttime2 = millis();
|
||||
LOG_DEBUG(GwLog::DEBUG,"E-Ink full refresh first 5 min");
|
||||
getdisplay().setFullWindow(); // Set full update
|
||||
epd->setFullWindow(); // Set full update
|
||||
if(fastrefresh == "true"){
|
||||
getdisplay().nextPage(); // Full update
|
||||
epd->nextPage(); // Full update
|
||||
}
|
||||
else{
|
||||
getdisplay().fillScreen(commonData.fgcolor); // Clear display
|
||||
epd->fillScreen(commonData.fgcolor); // Clear display
|
||||
#ifdef DISPLAY_GDEY042T81
|
||||
getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||
epd->init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||
#else
|
||||
getdisplay().init(115200); // Init for normal displays
|
||||
epd->init(115200); // Init for normal displays
|
||||
#endif
|
||||
getdisplay().firstPage(); // Full update
|
||||
getdisplay().nextPage(); // Full update
|
||||
// getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
// getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||
// getdisplay().nextPage(); // Partial update
|
||||
// getdisplay().nextPage(); // Partial update
|
||||
epd->firstPage(); // Full update
|
||||
epd->nextPage(); // Full update
|
||||
// epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
// epd->fillScreen(commonData.bgcolor); // Clear display
|
||||
// epd->nextPage(); // Partial update
|
||||
// epd->nextPage(); // Partial update
|
||||
}
|
||||
}
|
||||
|
||||
@@ -935,23 +923,23 @@ void OBP60Task(GwApi *api){
|
||||
if(millis() > starttime2 + fullrefreshtime * 60 * 1000){
|
||||
starttime2 = millis();
|
||||
LOG_DEBUG(GwLog::DEBUG,"E-Ink full refresh");
|
||||
getdisplay().setFullWindow(); // Set full update
|
||||
epd->setFullWindow(); // Set full update
|
||||
if(fastrefresh == "true"){
|
||||
getdisplay().nextPage(); // Full update
|
||||
epd->nextPage(); // Full update
|
||||
}
|
||||
else{
|
||||
getdisplay().fillScreen(commonData.fgcolor); // Clear display
|
||||
epd->fillScreen(commonData.fgcolor); // Clear display
|
||||
#ifdef DISPLAY_GDEY042T81
|
||||
getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||
epd->init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||
#else
|
||||
getdisplay().init(115200); // Init for normal displays
|
||||
epd->init(115200); // Init for normal displays
|
||||
#endif
|
||||
getdisplay().firstPage(); // Full update
|
||||
getdisplay().nextPage(); // Full update
|
||||
// getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
// getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||
// getdisplay().nextPage(); // Partial update
|
||||
// getdisplay().nextPage(); // Partial update
|
||||
epd->firstPage(); // Full update
|
||||
epd->nextPage(); // Full update
|
||||
// epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
// epd->fillScreen(commonData.bgcolor); // Clear display
|
||||
// epd->nextPage(); // Partial update
|
||||
// epd->nextPage(); // Partial update
|
||||
}
|
||||
}
|
||||
|
||||
@@ -977,13 +965,13 @@ void OBP60Task(GwApi *api){
|
||||
handleHstryBuf(api, &boatValues, hstryBufList);
|
||||
|
||||
// Clear display
|
||||
// getdisplay().fillRect(0, 0, getdisplay().width(), getdisplay().height(), commonData.bgcolor);
|
||||
getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||
// epd->fillRect(0, 0, epd->width(), epd->height(), commonData.bgcolor);
|
||||
epd->fillScreen(commonData.bgcolor); // Clear display
|
||||
|
||||
// Show header if enabled
|
||||
if (pages[pageNumber].description && pages[pageNumber].description->header or systemPage){
|
||||
// build header using commonData
|
||||
displayHeader(commonData, date, time, hdop); // Show page header
|
||||
displayHeader(commonData, symbolmode, date, time, hdop); // Show page header
|
||||
}
|
||||
|
||||
// Call the particular page
|
||||
@@ -996,13 +984,13 @@ void OBP60Task(GwApi *api){
|
||||
if (currentPage == NULL){
|
||||
LOG_DEBUG(GwLog::ERROR,"page number %d not found", pageNumber);
|
||||
// Error handling for missing page
|
||||
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||
getdisplay().drawXBitmap(200 - unknown_width / 2, 150 - unknown_height / 2, unknown_bits, unknown_width, unknown_height, commonData.fgcolor);
|
||||
getdisplay().setCursor(140, 250);
|
||||
getdisplay().setFont(&Atari16px);
|
||||
getdisplay().print("Here be dragons!");
|
||||
getdisplay().nextPage(); // Partial update (fast)
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
epd->fillScreen(commonData.bgcolor); // Clear display
|
||||
epd->drawXBitmap(200 - unknown_width / 2, 150 - unknown_height / 2, unknown_bits, unknown_width, unknown_height, commonData.fgcolor);
|
||||
epd->setCursor(140, 250);
|
||||
epd->setFont(&Atari16px);
|
||||
epd->print("Here be dragons!");
|
||||
epd->nextPage(); // Partial update (fast)
|
||||
}
|
||||
else{
|
||||
if (lastPage != pageNumber){
|
||||
@@ -1022,10 +1010,10 @@ void OBP60Task(GwApi *api){
|
||||
displayAlarm(commonData);
|
||||
}
|
||||
if (ret & PAGE_UPDATE) {
|
||||
getdisplay().nextPage(); // Partial update (fast)
|
||||
epd->nextPage(); // Partial update (fast)
|
||||
}
|
||||
if (ret & PAGE_HIBERNATE) {
|
||||
getdisplay().hibernate();
|
||||
epd->hibernate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user