Compare commits
No commits in common. "588008e370e26e61c59c66f5c92fa92a47262168" and "fa4b563ff077aa6e628fe8795a954431e56f720a" have entirely different histories.
588008e370
...
fa4b563ff0
|
@ -526,17 +526,3 @@ env.Append(
|
||||||
)
|
)
|
||||||
#script does not run on clean yet - maybe in the future
|
#script does not run on clean yet - maybe in the future
|
||||||
env.AddPostAction("clean",cleangenerated)
|
env.AddPostAction("clean",cleangenerated)
|
||||||
|
|
||||||
#look for extra task scripts and include them here
|
|
||||||
for taskdir in userTaskDirs:
|
|
||||||
script = os.path.join(taskdir, "extra_task.py")
|
|
||||||
if os.path.isfile(script):
|
|
||||||
taskname = os.path.basename(os.path.normpath(taskdir))
|
|
||||||
print("#extra task script for '{}'".format(taskname))
|
|
||||||
with open(script) as fh:
|
|
||||||
try:
|
|
||||||
code = compile(fh.read(), taskname, 'exec')
|
|
||||||
except SyntaxError:
|
|
||||||
print("#ERROR: script does not compile")
|
|
||||||
continue
|
|
||||||
exec(code)
|
|
||||||
|
|
|
@ -520,23 +520,19 @@ prebuild(env)
|
||||||
board="PLATFORM_BOARD_%s"%env["BOARD"].replace("-","_").upper()
|
board="PLATFORM_BOARD_%s"%env["BOARD"].replace("-","_").upper()
|
||||||
print("Board=#%s#"%board)
|
print("Board=#%s#"%board)
|
||||||
print("BuildFlags=%s"%(" ".join(env["BUILD_FLAGS"])))
|
print("BuildFlags=%s"%(" ".join(env["BUILD_FLAGS"])))
|
||||||
|
|
||||||
|
epdtype = "unknown"
|
||||||
|
pcbvers = "unknown"
|
||||||
|
for x in env["BUILD_FLAGS"]:
|
||||||
|
if x.startswith("-D HARDWARE_"):
|
||||||
|
pcbvers = x.split('_')[1]
|
||||||
|
if x.startswith("-D DISPLAY_"):
|
||||||
|
epdtype = x.split('_')[1]
|
||||||
|
|
||||||
env.Append(
|
env.Append(
|
||||||
LINKFLAGS=[ "-u", "custom_app_desc" ],
|
LINKFLAGS=[ "-u", "custom_app_desc" ],
|
||||||
CPPDEFINES=[(board,"1")]
|
CPPDEFINES=[(board,"1"), ("BOARD", env["BOARD"]), ("EPDTYPE", epdtype),
|
||||||
|
("PCBVERS", pcbvers)]
|
||||||
)
|
)
|
||||||
#script does not run on clean yet - maybe in the future
|
#script does not run on clean yet - maybe in the future
|
||||||
env.AddPostAction("clean",cleangenerated)
|
env.AddPostAction("clean",cleangenerated)
|
||||||
|
|
||||||
#look for extra task scripts and include them here
|
|
||||||
for taskdir in userTaskDirs:
|
|
||||||
script = os.path.join(taskdir, "extra_task.py")
|
|
||||||
if os.path.isfile(script):
|
|
||||||
taskname = os.path.basename(os.path.normpath(taskdir))
|
|
||||||
print("#extra task script for '{}'".format(taskname))
|
|
||||||
with open(script) as fh:
|
|
||||||
try:
|
|
||||||
code = compile(fh.read(), taskname, 'exec')
|
|
||||||
except SyntaxError:
|
|
||||||
print("#ERROR: script does not compile")
|
|
||||||
continue
|
|
||||||
exec(code)
|
|
||||||
|
|
|
@ -300,49 +300,6 @@ void fillPoly4(const std::vector<Point>& p4, uint16_t color) {
|
||||||
getdisplay().fillTriangle(p4[0].x, p4[0].y, p4[2].x, p4[2].y, p4[3].x, p4[3].y, color);
|
getdisplay().fillTriangle(p4[0].x, p4[0].y, p4[2].x, p4[2].y, p4[3].x, p4[3].y, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split string into words, whitespace separated
|
|
||||||
std::vector<String> split(const String &s) {
|
|
||||||
std::vector<String> words;
|
|
||||||
String word = "";
|
|
||||||
for (size_t i = 0; i < s.length(); i++) {
|
|
||||||
if (s[i] == ' ' || s[i] == '\t' || s[i] == '\r' || s[i] == '\n') {
|
|
||||||
if (word.length() > 0) {
|
|
||||||
words.push_back(word);
|
|
||||||
word = "";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
word += s[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (word.length() > 0) {
|
|
||||||
words.push_back(word);
|
|
||||||
}
|
|
||||||
return words;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wordwrap single line, monospaced font
|
|
||||||
std::vector<String> wordwrap(String &line, uint16_t maxwidth) {
|
|
||||||
std::vector<String> lines;
|
|
||||||
std::vector<String> words = split(line);
|
|
||||||
String currentLine = "";
|
|
||||||
for (const auto& word : words) {
|
|
||||||
if (currentLine.length() + word.length() + 1 > maxwidth) {
|
|
||||||
if (currentLine.length() > 0) {
|
|
||||||
lines.push_back(currentLine);
|
|
||||||
currentLine = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (currentLine.length() > 0) {
|
|
||||||
currentLine += " ";
|
|
||||||
}
|
|
||||||
currentLine += word;
|
|
||||||
}
|
|
||||||
if (currentLine.length() > 0) {
|
|
||||||
lines.push_back(currentLine);
|
|
||||||
}
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw centered text
|
// Draw centered text
|
||||||
void drawTextCenter(int16_t cx, int16_t cy, String text) {
|
void drawTextCenter(int16_t cx, int16_t cy, String text) {
|
||||||
int16_t x1, y1;
|
int16_t x1, y1;
|
||||||
|
@ -588,47 +545,6 @@ void displayFooter(CommonData &commonData) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alarm overlay, to be drawn as very last draw operation
|
|
||||||
void displayAlarm(CommonData &commonData) {
|
|
||||||
|
|
||||||
const uint16_t x = 50; // overlay area
|
|
||||||
const uint16_t y = 100;
|
|
||||||
const uint16_t w = 300;
|
|
||||||
const uint16_t h = 150;
|
|
||||||
|
|
||||||
getdisplay().setFont(&Atari16px);
|
|
||||||
getdisplay().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);
|
|
||||||
|
|
||||||
// exclamation icon in left top corner
|
|
||||||
getdisplay().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);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
n += 16;
|
|
||||||
if (n > 64) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drawTextCenter(x + w / 2, y + h - 16, "Press button 1 to dismiss alarm");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sunset und sunrise calculation
|
// Sunset und sunrise calculation
|
||||||
SunData calcSunsetSunrise(double time, double date, double latitude, double longitude, float timezone){
|
SunData calcSunsetSunrise(double time, double date, double latitude, double longitude, float timezone){
|
||||||
SunData returnset;
|
SunData returnset;
|
||||||
|
|
|
@ -57,11 +57,6 @@ GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay();
|
||||||
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay();
|
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Page display return values
|
|
||||||
#define PAGE_OK 0 // all ok, do nothing
|
|
||||||
#define PAGE_UPDATE 1 // page wants display to update
|
|
||||||
#define PAGE_HIBERNATE 2 // page wants displey to hibernate
|
|
||||||
|
|
||||||
struct Point {
|
struct Point {
|
||||||
double x;
|
double x;
|
||||||
double y;
|
double y;
|
||||||
|
@ -102,7 +97,6 @@ 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, GwApi::BoatValue *date, GwApi::BoatValue *time, GwApi::BoatValue *hdop); // Draw display header
|
||||||
void displayFooter(CommonData &commonData);
|
void displayFooter(CommonData &commonData);
|
||||||
void displayAlarm(CommonData &commonData);
|
|
||||||
|
|
||||||
SunData calcSunsetSunrise(double time, double date, double latitude, double longitude, float timezone); // Calulate sunset and sunrise
|
SunData calcSunsetSunrise(double time, double date, double latitude, double longitude, float timezone); // Calulate sunset and sunrise
|
||||||
SunData calcSunsetSunriseRTC(struct tm *rtctime, double latitude, double longitude, float timezone);
|
SunData calcSunsetSunriseRTC(struct tm *rtctime, double latitude, double longitude, float timezone);
|
||||||
|
@ -148,12 +142,12 @@ static unsigned char fram_bits[] PROGMEM = {
|
||||||
0xff, 0xff, 0xf8, 0x1f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f,
|
0xff, 0xff, 0xf8, 0x1f, 0xf8, 0x1f, 0xff, 0xff, 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 = {
|
static unsigned char ap_bits[] = {
|
||||||
0xe0, 0x03, 0x18, 0x0c, 0x04, 0x10, 0xc2, 0x21, 0x30, 0x06, 0x08, 0x08,
|
0xe0, 0x03, 0x18, 0x0c, 0x04, 0x10, 0xc2, 0x21, 0x30, 0x06, 0x08, 0x08,
|
||||||
0xc0, 0x01, 0x20, 0x02, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x01, 0xc0, 0x01,
|
0xc0, 0x01, 0x20, 0x02, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x01, 0xc0, 0x01,
|
||||||
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
|
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
|
||||||
|
|
||||||
static unsigned char dish_bits[] PROGMEM = {
|
static unsigned char dish_bits[] PROGMEM= {
|
||||||
0x3c, 0x00, 0x42, 0x18, 0xfa, 0x1b, 0x02, 0x04, 0x02, 0x0a, 0x02, 0x09,
|
0x3c, 0x00, 0x42, 0x18, 0xfa, 0x1b, 0x02, 0x04, 0x02, 0x0a, 0x02, 0x09,
|
||||||
0x82, 0x08, 0x06, 0x0a, 0x0e, 0x1b, 0x9c, 0x2b, 0x38, 0x2b, 0x74, 0x20,
|
0x82, 0x08, 0x06, 0x0a, 0x0e, 0x1b, 0x9c, 0x2b, 0x38, 0x2b, 0x74, 0x20,
|
||||||
0xec, 0x1f, 0x1c, 0x00, 0xf4, 0x00, 0xfe, 0x03 };
|
0xec, 0x1f, 0x1c, 0x00, 0xf4, 0x00, 0xfe, 0x03 };
|
||||||
|
|
|
@ -37,21 +37,9 @@ String formatTime(char fmttype, uint8_t hour, uint8_t minute, uint8_t second) {
|
||||||
return String(buffer);
|
return String(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
String formatLatitude(double lat) {
|
FormatedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
||||||
float degree = abs(int(lat));
|
|
||||||
float minute = abs((lat - int(lat)) * 60);
|
|
||||||
return String(degree, 0) + "\x90 " + String(minute, 4) + "' " + ((lat > 0) ? "N" : "S");
|
|
||||||
}
|
|
||||||
|
|
||||||
String formatLongitude(double lon) {
|
|
||||||
float degree = abs(int(lon));
|
|
||||||
float minute = abs((lon - int(lon)) * 60);
|
|
||||||
return String(degree, 0) + "\x90 " + String(minute, 4) + "' " + ((lon > 0) ? "E" : "W");
|
|
||||||
}
|
|
||||||
|
|
||||||
FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
|
|
||||||
GwLog *logger = commondata.logger;
|
GwLog *logger = commondata.logger;
|
||||||
FormattedData result;
|
FormatedData result;
|
||||||
static int dayoffset = 0;
|
static int dayoffset = 0;
|
||||||
double rawvalue = 0;
|
double rawvalue = 0;
|
||||||
|
|
|
@ -1,158 +0,0 @@
|
||||||
#include "OBPDataOperations.h"
|
|
||||||
|
|
||||||
double WindUtils::to2PI(double a)
|
|
||||||
{
|
|
||||||
a = fmod(a, 2 * M_PI);
|
|
||||||
if (a < 0.0) {
|
|
||||||
a += 2 * M_PI;
|
|
||||||
}
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
double WindUtils::toPI(double a)
|
|
||||||
{
|
|
||||||
a += M_PI;
|
|
||||||
a = to2PI(a);
|
|
||||||
a -= M_PI;
|
|
||||||
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
double WindUtils::to360(double a)
|
|
||||||
{
|
|
||||||
a = fmod(a, 360);
|
|
||||||
if (a < 0.0) {
|
|
||||||
a += 360;
|
|
||||||
}
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
double WindUtils::to180(double a)
|
|
||||||
{
|
|
||||||
a += 180;
|
|
||||||
a = to360(a);
|
|
||||||
a -= 180;
|
|
||||||
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindUtils::toCart(const double* phi, const double* r, double* x, double* y)
|
|
||||||
{
|
|
||||||
*x = *r * sin(*phi);
|
|
||||||
*y = *r * cos(*phi);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindUtils::toPol(const double* x, const double* y, double* phi, double* r)
|
|
||||||
{
|
|
||||||
*phi = (M_PI / 2) - atan2(*y, *x);
|
|
||||||
*phi = to2PI(*phi);
|
|
||||||
*r = sqrt(*x * *x + *y * *y);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindUtils::addPolar(const double* phi1, const double* r1,
|
|
||||||
const double* phi2, const double* r2,
|
|
||||||
double* phi, double* r)
|
|
||||||
{
|
|
||||||
double x1, y1, x2, y2;
|
|
||||||
toCart(phi1, r1, &x1, &y1);
|
|
||||||
toCart(phi2, r2, &x2, &y2);
|
|
||||||
x1 += x2;
|
|
||||||
y1 += y2;
|
|
||||||
toPol(&x1, &y1, phi, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindUtils::calcTwdSA(const double* AWA, const double* AWS,
|
|
||||||
const double* CTW, const double* STW, const double* HDT,
|
|
||||||
double* TWD, double* TWS, double* TWA)
|
|
||||||
{
|
|
||||||
double awd = *AWA + *HDT;
|
|
||||||
awd = to2PI(awd);
|
|
||||||
double stw = -*STW;
|
|
||||||
// Serial.println("\ncalcTwdSA: AWA: " + String(*AWA) + ", AWS: " + String(*AWS) + ", CTW: " + String(*CTW) + ", STW: " + String(*STW) + ", HDT: " + String(*HDT));
|
|
||||||
addPolar(&awd, AWS, CTW, &stw, TWD, TWS);
|
|
||||||
|
|
||||||
// Normalize TWD and TWA to 0-360°
|
|
||||||
*TWD = to2PI(*TWD);
|
|
||||||
*TWA = toPI(*TWD - *HDT);
|
|
||||||
// Serial.println("calcTwdSA: TWD: " + String(*TWD) + ", TWS: " + String(*TWS));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WindUtils::calcTrueWind(const double* awaVal, const double* awsVal,
|
|
||||||
const double* cogVal, const double* stwVal, const double* sogVal, const double* hdtVal,
|
|
||||||
const double* hdmVal, const double* varVal, double* twdVal, double* twsVal, double* twaVal)
|
|
||||||
{
|
|
||||||
double stw, hdt, ctw;
|
|
||||||
double twd, tws, twa;
|
|
||||||
static const double DBL_MIN = std::numeric_limits<double>::lowest();
|
|
||||||
|
|
||||||
if (*hdtVal != DBL_MIN) {
|
|
||||||
hdt = *hdtVal; // Use HDT if available
|
|
||||||
} else {
|
|
||||||
if (*hdmVal != DBL_MIN && *varVal != DBL_MIN) {
|
|
||||||
hdt = *hdmVal + *varVal; // Use corrected HDM if HDT is not available
|
|
||||||
hdt = to2PI(hdt);
|
|
||||||
} else if (*cogVal != DBL_MIN) {
|
|
||||||
hdt = *cogVal; // Use COG as fallback if HDT and HDM are not available
|
|
||||||
} else {
|
|
||||||
return false; // Cannot calculate without valid HDT or HDM
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*cogVal != DBL_MIN) {
|
|
||||||
ctw = *cogVal; // Use COG as CTW if available
|
|
||||||
// ctw = *cogVal + ((*cogVal - hdt) / 2); // Estimate CTW from COG
|
|
||||||
} else {
|
|
||||||
ctw = hdt; // 2nd approximation for CTW;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*stwVal != DBL_MIN) {
|
|
||||||
stw = *stwVal; // Use STW if available
|
|
||||||
} else if (*sogVal != DBL_MIN) {
|
|
||||||
stw = *sogVal;
|
|
||||||
} else {
|
|
||||||
// If STW and SOG are not available, we cannot calculate true wind
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((*awaVal == DBL_MIN) || (*awsVal == DBL_MIN) || (*cogVal == DBL_MIN) || (*stwVal == DBL_MIN)) {
|
|
||||||
// Cannot calculate true wind without valid AWA, AWS, COG, or STW
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
calcTwdSA(awaVal, awsVal, &ctw, stwVal, &hdt, &twd, &tws, &twa);
|
|
||||||
*twdVal = twd;
|
|
||||||
*twsVal = tws;
|
|
||||||
*twaVal = twa;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HstryBuf::fillWndBufSimData(tBoatHstryData& hstryBufs)
|
|
||||||
// Fill most part of TWD and TWS history buffer with simulated data
|
|
||||||
{
|
|
||||||
double value = 20.0;
|
|
||||||
int16_t value2 = 0;
|
|
||||||
for (int i = 0; i < 900; i++) {
|
|
||||||
value += random(-20, 20);
|
|
||||||
value = WindUtils::to360(value);
|
|
||||||
value2 = static_cast<int16_t>(value * DEG_TO_RAD * 1000);
|
|
||||||
hstryBufs.twdHstry->add(value2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* double genTwdSimDat()
|
|
||||||
{
|
|
||||||
simTwd += random(-20, 20);
|
|
||||||
if (simTwd < 0.0)
|
|
||||||
simTwd += 360.0;
|
|
||||||
if (simTwd >= 360.0)
|
|
||||||
simTwd -= 360.0;
|
|
||||||
|
|
||||||
int16_t z = static_cast<int16_t>(DegToRad(simTwd) * 1000.0);
|
|
||||||
pageData.boatHstry.twdHstry->add(z); // Fill the buffer with some test data
|
|
||||||
|
|
||||||
simTws += random(-200, 150) / 10.0; // TWS value in knots
|
|
||||||
simTws = constrain(simTws, 0.0f, 50.0f); // Ensure TWS is between 0 and 50 knots
|
|
||||||
twsValue = simTws;
|
|
||||||
}*/
|
|
|
@ -1,36 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include "GwApi.h"
|
|
||||||
#include "OBPRingBuffer.h"
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
RingBuffer<int16_t>* twdHstry;
|
|
||||||
RingBuffer<int16_t>* twsHstry;
|
|
||||||
} tBoatHstryData; // Holds pointers to all history buffers for boat data
|
|
||||||
|
|
||||||
class HstryBuf {
|
|
||||||
|
|
||||||
public:
|
|
||||||
void fillWndBufSimData(tBoatHstryData& hstryBufs); // Fill most part of the TWD and TWS history buffer with simulated data
|
|
||||||
};
|
|
||||||
|
|
||||||
class WindUtils {
|
|
||||||
|
|
||||||
public:
|
|
||||||
static double to2PI(double a);
|
|
||||||
static double toPI(double a);
|
|
||||||
static double to360(double a);
|
|
||||||
static double to180(double a);
|
|
||||||
static void toCart(const double* phi, const double* r, double* x, double* y);
|
|
||||||
static void toPol(const double* x, const double* y, double* phi, double* r);
|
|
||||||
static void addPolar(const double* phi1, const double* r1,
|
|
||||||
const double* phi2, const double* r2,
|
|
||||||
double* phi, double* r);
|
|
||||||
static void calcTwdSA(const double* AWA, const double* AWS,
|
|
||||||
const double* CTW, const double* STW, const double* HDT,
|
|
||||||
double* TWD, double* TWS, double* TWA);
|
|
||||||
static bool calcTrueWind(const double* awaVal, const double* awsVal,
|
|
||||||
const double* cogVal, const double* stwVal, const double* sogVal, const double* hdtVal,
|
|
||||||
const double* hdmVal, const double* varVal, double* twdVal, double* twsVal, double* twaVal);
|
|
||||||
};
|
|
|
@ -1,60 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include "GwSynchronized.h"
|
|
||||||
#include <algorithm>
|
|
||||||
#include <limits>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <vector>
|
|
||||||
#include "WString.h"
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class RingBuffer {
|
|
||||||
private:
|
|
||||||
mutable SemaphoreHandle_t bufLocker;
|
|
||||||
std::vector<T> buffer;
|
|
||||||
size_t capacity;
|
|
||||||
size_t head; // Points to the next insertion position
|
|
||||||
size_t first; // Points to the first (oldest) valid element
|
|
||||||
size_t last; // Points to the last (newest) valid element
|
|
||||||
size_t count; // Number of valid elements currently in buffer
|
|
||||||
bool is_Full; // Indicates that all buffer elements are used and ringing is in use
|
|
||||||
T MIN_VAL; // lowest possible value of buffer
|
|
||||||
T MAX_VAL; // highest possible value of buffer of type <T>
|
|
||||||
|
|
||||||
// metadata for buffer
|
|
||||||
String dataName; // Name of boat data in buffer
|
|
||||||
String dataFmt; // Format of boat data in buffer
|
|
||||||
int updFreq; // Update frequency in milliseconds
|
|
||||||
T smallest; // Value range of buffer: smallest value
|
|
||||||
T largest; // Value range of buffer: biggest value
|
|
||||||
|
|
||||||
public:
|
|
||||||
RingBuffer(size_t size);
|
|
||||||
void setMetaData(String name, String format, int updateFrequency, T minValue, T maxValue); // Set meta data for buffer
|
|
||||||
bool getMetaData(String& name, String& format, int& updateFrequency, T& minValue, T& maxValue); // Get meta data of buffer
|
|
||||||
String getName() const; // Get buffer name
|
|
||||||
void add(const T& value); // Add a new value to buffer
|
|
||||||
T get(size_t index) const; // Get value at specific position (0-based index from oldest to newest)
|
|
||||||
T getFirst() const; // Get the first (oldest) value in buffer
|
|
||||||
T getLast() const; // Get the last (newest) value in buffer
|
|
||||||
T getMin() const; // Get the lowest value in buffer
|
|
||||||
T getMin(size_t amount) const; // Get minimum value of the last <amount> values of buffer
|
|
||||||
T getMax() const; // Get the highest value in buffer
|
|
||||||
T getMax(size_t amount) const; // Get maximum value of the last <amount> values of buffer
|
|
||||||
T getMid() const; // Get mid value between <min> and <max> value in buffer
|
|
||||||
T getMid(size_t amount) const; // Get mid value between <min> and <max> value of the last <amount> values of buffer
|
|
||||||
T getMedian() const; // Get the median value in buffer
|
|
||||||
T getMedian(size_t amount) const; // Get the median value of the last <amount> values of buffer
|
|
||||||
size_t getCapacity() const; // Get the buffer capacity (maximum size)
|
|
||||||
size_t getCurrentSize() const; // Get the current number of elements in buffer
|
|
||||||
size_t getFirstIdx() const; // Get the index of oldest value in buffer
|
|
||||||
size_t getLastIdx() const; // Get the index of newest value in buffer
|
|
||||||
bool isEmpty() const; // Check if buffer is empty
|
|
||||||
bool isFull() const; // Check if buffer is full
|
|
||||||
T getMinVal() const; // Get lowest possible value for buffer; used for initialized buffer data
|
|
||||||
T getMaxVal() const; // Get highest possible value for buffer
|
|
||||||
void clear(); // Clear buffer
|
|
||||||
T operator[](size_t index) const; // Operator[] for convenient access (same as get())
|
|
||||||
std::vector<T> getAllValues() const; // Get all current values as a vector
|
|
||||||
};
|
|
||||||
|
|
||||||
#include "OBPRingBuffer.tpp"
|
|
|
@ -1,376 +0,0 @@
|
||||||
#include "OBPRingBuffer.h"
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
RingBuffer<T>::RingBuffer(size_t size)
|
|
||||||
: capacity(size)
|
|
||||||
, head(0)
|
|
||||||
, first(0)
|
|
||||||
, last(0)
|
|
||||||
, count(0)
|
|
||||||
, is_Full(false)
|
|
||||||
{
|
|
||||||
bufLocker = xSemaphoreCreateMutex();
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
// return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
MIN_VAL = std::numeric_limits<T>::lowest();
|
|
||||||
MAX_VAL = std::numeric_limits<T>::max();
|
|
||||||
dataName = "";
|
|
||||||
dataFmt = "";
|
|
||||||
updFreq = -1;
|
|
||||||
smallest = MIN_VAL;
|
|
||||||
largest = MAX_VAL;
|
|
||||||
|
|
||||||
buffer.resize(size, MIN_VAL);
|
|
||||||
|
|
||||||
// return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Specify meta data of buffer content
|
|
||||||
template <typename T>
|
|
||||||
void RingBuffer<T>::setMetaData(String name, String format, int updateFrequency, T minValue, T maxValue)
|
|
||||||
{
|
|
||||||
GWSYNCHRONIZED(&bufLocker);
|
|
||||||
dataName = name;
|
|
||||||
dataFmt = format;
|
|
||||||
updFreq = updateFrequency;
|
|
||||||
smallest = std::max(MIN_VAL, minValue);
|
|
||||||
largest = std::min(MAX_VAL, maxValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get meta data of buffer content
|
|
||||||
template <typename T>
|
|
||||||
bool RingBuffer<T>::getMetaData(String& name, String& format, int& updateFrequency, T& minValue, T& maxValue)
|
|
||||||
{
|
|
||||||
if (dataName == "" || dataFmt == "" || updFreq == -1) {
|
|
||||||
return false; // Meta data not set
|
|
||||||
}
|
|
||||||
|
|
||||||
GWSYNCHRONIZED(&bufLocker);
|
|
||||||
name = dataName;
|
|
||||||
format = dataFmt;
|
|
||||||
updateFrequency = updFreq;
|
|
||||||
minValue = smallest;
|
|
||||||
maxValue = largest;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get buffer name
|
|
||||||
template <typename T>
|
|
||||||
String RingBuffer<T>::getName() const
|
|
||||||
{
|
|
||||||
return dataName;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a new value to buffer
|
|
||||||
template <typename T>
|
|
||||||
void RingBuffer<T>::add(const T& value)
|
|
||||||
{
|
|
||||||
GWSYNCHRONIZED(&bufLocker);
|
|
||||||
if (value < smallest || value > largest) {
|
|
||||||
buffer[head] = MIN_VAL; // Store MIN_VAL if value is out of range
|
|
||||||
} else {
|
|
||||||
buffer[head] = value;
|
|
||||||
}
|
|
||||||
last = head;
|
|
||||||
|
|
||||||
if (is_Full) {
|
|
||||||
first = (first + 1) % capacity; // Move pointer to oldest element when overwriting
|
|
||||||
} else {
|
|
||||||
count++;
|
|
||||||
if (count == capacity) {
|
|
||||||
is_Full = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
head = (head + 1) % capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get value at specific position (0-based index from oldest to newest)
|
|
||||||
template <typename T>
|
|
||||||
T RingBuffer<T>::get(size_t index) const
|
|
||||||
{
|
|
||||||
GWSYNCHRONIZED(&bufLocker);
|
|
||||||
if (isEmpty() || index < 0 || index >= count) {
|
|
||||||
return MIN_VAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t realIndex = (first + index) % capacity;
|
|
||||||
return buffer[realIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Operator[] for convenient access (same as get())
|
|
||||||
template <typename T>
|
|
||||||
T RingBuffer<T>::operator[](size_t index) const
|
|
||||||
{
|
|
||||||
return get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the first (oldest) value in the buffer
|
|
||||||
template <typename T>
|
|
||||||
T RingBuffer<T>::getFirst() const
|
|
||||||
{
|
|
||||||
if (isEmpty()) {
|
|
||||||
return MIN_VAL;
|
|
||||||
}
|
|
||||||
return get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the last (newest) value in the buffer
|
|
||||||
template <typename T>
|
|
||||||
T RingBuffer<T>::getLast() const
|
|
||||||
{
|
|
||||||
if (isEmpty()) {
|
|
||||||
return MIN_VAL;
|
|
||||||
}
|
|
||||||
return get(count - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the lowest value in the buffer
|
|
||||||
template <typename T>
|
|
||||||
T RingBuffer<T>::getMin() const
|
|
||||||
{
|
|
||||||
if (isEmpty()) {
|
|
||||||
return MIN_VAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
T minVal = MAX_VAL;
|
|
||||||
T value;
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
value = get(i);
|
|
||||||
if (value < minVal && value != MIN_VAL) {
|
|
||||||
minVal = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return minVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get minimum value of the last <amount> values of buffer
|
|
||||||
template <typename T>
|
|
||||||
T RingBuffer<T>::getMin(size_t amount) const
|
|
||||||
{
|
|
||||||
if (isEmpty() || amount <= 0) {
|
|
||||||
return MIN_VAL;
|
|
||||||
}
|
|
||||||
if (amount > count)
|
|
||||||
amount = count;
|
|
||||||
|
|
||||||
T minVal = MAX_VAL;
|
|
||||||
T value;
|
|
||||||
for (size_t i = 0; i < amount; i++) {
|
|
||||||
value = get(count - 1 - i);
|
|
||||||
if (value < minVal && value != MIN_VAL) {
|
|
||||||
minVal = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return minVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the highest value in the buffer
|
|
||||||
template <typename T>
|
|
||||||
T RingBuffer<T>::getMax() const
|
|
||||||
{
|
|
||||||
if (isEmpty()) {
|
|
||||||
return MIN_VAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
T maxVal = MIN_VAL;
|
|
||||||
T value;
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
value = get(i);
|
|
||||||
if (value > maxVal && value != MIN_VAL) {
|
|
||||||
maxVal = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return maxVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get maximum value of the last <amount> values of buffer
|
|
||||||
template <typename T>
|
|
||||||
T RingBuffer<T>::getMax(size_t amount) const
|
|
||||||
{
|
|
||||||
if (isEmpty() || amount <= 0) {
|
|
||||||
return MIN_VAL;
|
|
||||||
}
|
|
||||||
if (amount > count)
|
|
||||||
amount = count;
|
|
||||||
|
|
||||||
T maxVal = MIN_VAL;
|
|
||||||
T value;
|
|
||||||
for (size_t i = 0; i < amount; i++) {
|
|
||||||
value = get(count - 1 - i);
|
|
||||||
if (value > maxVal && value != MIN_VAL) {
|
|
||||||
maxVal = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return maxVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mid value between <min> and <max> value in the buffer
|
|
||||||
template <typename T>
|
|
||||||
T RingBuffer<T>::getMid() const
|
|
||||||
{
|
|
||||||
if (isEmpty()) {
|
|
||||||
return MIN_VAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (getMin() + getMax()) / static_cast<T>(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mid value between <min> and <max> value of the last <amount> values of buffer
|
|
||||||
template <typename T>
|
|
||||||
T RingBuffer<T>::getMid(size_t amount) const
|
|
||||||
{
|
|
||||||
if (isEmpty() || amount <= 0) {
|
|
||||||
return MIN_VAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amount > count)
|
|
||||||
amount = count;
|
|
||||||
|
|
||||||
return (getMin(amount) + getMax(amount)) / static_cast<T>(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the median value in the buffer
|
|
||||||
template <typename T>
|
|
||||||
T RingBuffer<T>::getMedian() const
|
|
||||||
{
|
|
||||||
if (isEmpty()) {
|
|
||||||
return MIN_VAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a temporary vector with current valid elements
|
|
||||||
std::vector<T> temp;
|
|
||||||
temp.reserve(count);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
temp.push_back(get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort to find median
|
|
||||||
std::sort(temp.begin(), temp.end());
|
|
||||||
|
|
||||||
if (count % 2 == 1) {
|
|
||||||
// Odd number of elements
|
|
||||||
return temp[count / 2];
|
|
||||||
} else {
|
|
||||||
// Even number of elements - return average of middle two
|
|
||||||
// Note: For integer types, this truncates. For floating point, it's exact.
|
|
||||||
return (temp[count / 2 - 1] + temp[count / 2]) / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the median value of the last <amount> values of buffer
|
|
||||||
template <typename T>
|
|
||||||
T RingBuffer<T>::getMedian(size_t amount) const
|
|
||||||
{
|
|
||||||
if (isEmpty() || amount <= 0) {
|
|
||||||
return MIN_VAL;
|
|
||||||
}
|
|
||||||
if (amount > count)
|
|
||||||
amount = count;
|
|
||||||
|
|
||||||
// Create a temporary vector with current valid elements
|
|
||||||
std::vector<T> temp;
|
|
||||||
temp.reserve(amount);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < amount; i++) {
|
|
||||||
temp.push_back(get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort to find median
|
|
||||||
std::sort(temp.begin(), temp.end());
|
|
||||||
|
|
||||||
if (amount % 2 == 1) {
|
|
||||||
// Odd number of elements
|
|
||||||
return temp[amount / 2];
|
|
||||||
} else {
|
|
||||||
// Even number of elements - return average of middle two
|
|
||||||
// Note: For integer types, this truncates. For floating point, it's exact.
|
|
||||||
return (temp[amount / 2 - 1] + temp[amount / 2]) / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the buffer capacity (maximum size)
|
|
||||||
template <typename T>
|
|
||||||
size_t RingBuffer<T>::getCapacity() const
|
|
||||||
{
|
|
||||||
return capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the current number of elements in the buffer
|
|
||||||
template <typename T>
|
|
||||||
size_t RingBuffer<T>::getCurrentSize() const
|
|
||||||
{
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the first index of buffer
|
|
||||||
template <typename T>
|
|
||||||
size_t RingBuffer<T>::getFirstIdx() const
|
|
||||||
{
|
|
||||||
return first;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the last index of buffer
|
|
||||||
template <typename T>
|
|
||||||
size_t RingBuffer<T>::getLastIdx() const
|
|
||||||
{
|
|
||||||
return last;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if buffer is empty
|
|
||||||
template <typename T>
|
|
||||||
bool RingBuffer<T>::isEmpty() const
|
|
||||||
{
|
|
||||||
return count == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if buffer is full
|
|
||||||
template <typename T>
|
|
||||||
bool RingBuffer<T>::isFull() const
|
|
||||||
{
|
|
||||||
return is_Full;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get lowest possible value for buffer; used for non-set buffer data
|
|
||||||
template <typename T>
|
|
||||||
T RingBuffer<T>::getMinVal() const
|
|
||||||
{
|
|
||||||
return MIN_VAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get highest possible value for buffer
|
|
||||||
template <typename T>
|
|
||||||
T RingBuffer<T>::getMaxVal() const
|
|
||||||
{
|
|
||||||
return MAX_VAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear buffer
|
|
||||||
template <typename T>
|
|
||||||
void RingBuffer<T>::clear()
|
|
||||||
{
|
|
||||||
GWSYNCHRONIZED(&bufLocker);
|
|
||||||
head = 0;
|
|
||||||
first = 0;
|
|
||||||
last = 0;
|
|
||||||
count = 0;
|
|
||||||
is_Full = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all current values as a vector
|
|
||||||
template <typename T>
|
|
||||||
std::vector<T> RingBuffer<T>::getAllValues() const
|
|
||||||
{
|
|
||||||
std::vector<T> result;
|
|
||||||
result.reserve(count);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
result.push_back(get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
|
@ -498,18 +498,14 @@ void sensorTask(void *param){
|
||||||
// Send supply voltage value all 1s
|
// Send supply voltage value all 1s
|
||||||
if(millis() > starttime5 + 1000 && String(powsensor1) == "off"){
|
if(millis() > starttime5 + 1000 && String(powsensor1) == "off"){
|
||||||
starttime5 = millis();
|
starttime5 = millis();
|
||||||
float rawVoltage = 0; // Default value
|
float rawVoltage = 0;
|
||||||
#ifdef BOARD_OBP40S3
|
#if defined(BOARD_OBP40S3) && defined(VOLTAGE_SENSOR)
|
||||||
sensors.batteryVoltage = 0; // If no sensor then zero voltage
|
|
||||||
#endif
|
|
||||||
#if defined(BOARD_OBP40S3) && defined(VOLTAGE_SENSOR)
|
|
||||||
rawVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.53) * 2; // Vin = 1/2 for OBP40
|
rawVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.53) * 2; // Vin = 1/2 for OBP40
|
||||||
sensors.batteryVoltage = rawVoltage * vslope + voffset; // Calibration
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef BOARD_OBP60S3
|
#ifdef BOARD_OBP60S3
|
||||||
rawVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20 for OBP60
|
rawVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20 for OBP60
|
||||||
sensors.batteryVoltage = rawVoltage * vslope + voffset; // Calibration
|
|
||||||
#endif
|
#endif
|
||||||
|
sensors.batteryVoltage = rawVoltage * vslope + voffset; // Calibration
|
||||||
// Save new data in average array
|
// Save new data in average array
|
||||||
batV.reading(int(sensors.batteryVoltage * 100));
|
batV.reading(int(sensors.batteryVoltage * 100));
|
||||||
// Calculate the average values for different time lines from integer values
|
// Calculate the average values for different time lines from integer values
|
||||||
|
|
|
@ -20,7 +20,7 @@ class PageBME280 : public Page
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -176,7 +176,9 @@ class PageBME280 : public Page
|
||||||
// Show bus data
|
// Show bus data
|
||||||
getdisplay().print(svalue3); // Real value as formated string
|
getdisplay().print(svalue3); // Real value as formated string
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ class PageBattery : public Page
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -288,7 +288,9 @@ class PageBattery : public Page
|
||||||
getdisplay().print("---"); // No sensor data (sensor is off)
|
getdisplay().print("---"); // No sensor data (sensor is off)
|
||||||
}
|
}
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ public:
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData)
|
virtual void displayPage(PageData &pageData)
|
||||||
{
|
{
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
@ -334,7 +334,8 @@ public:
|
||||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||||
getdisplay().print("W");
|
getdisplay().print("W");
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ bool homevalid = false; // homelat and homelon are valid
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData)
|
virtual void displayPage(PageData &pageData)
|
||||||
{
|
{
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
@ -120,7 +120,7 @@ bool homevalid = false; // homelat and homelon are valid
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
value1 = simtime++; // Simulation data for time value 11:36 in seconds
|
value1 = simtime++; // Simulation data for time value 11:36 in seconds
|
||||||
} // Other simulation data see OBP60Formatter.cpp
|
} // Other simulation data see OBP60Formater.cpp
|
||||||
bool valid1 = bvalue1->valid; // Valid information
|
bool valid1 = bvalue1->valid; // Valid information
|
||||||
String svalue1 = formatValue(bvalue1, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue1 = formatValue(bvalue1, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
String unit1 = formatValue(bvalue1, *commonData).unit; // Unit of value
|
String unit1 = formatValue(bvalue1, *commonData).unit; // Unit of value
|
||||||
|
@ -162,7 +162,7 @@ bool homevalid = false; // homelat and homelon are valid
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging boat values
|
// Logging boat values
|
||||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
if (bvalue1 == NULL) return;
|
||||||
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", name1.c_str(), value1, name2.c_str(), value2);
|
||||||
|
|
||||||
// Draw page
|
// Draw page
|
||||||
|
@ -438,7 +438,9 @@ bool homevalid = false; // homelat and homelon are valid
|
||||||
getdisplay().fillCircle(200, 150, startwidth + 6, commonData->bgcolor);
|
getdisplay().fillCircle(200, 150, startwidth + 6, commonData->bgcolor);
|
||||||
getdisplay().fillCircle(200, 150, startwidth + 4, commonData->fgcolor);
|
getdisplay().fillCircle(200, 150, startwidth + 4, commonData->fgcolor);
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ class PageCompass : public Page
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ class PageCompass : public Page
|
||||||
String DataText[HowManyValues];
|
String DataText[HowManyValues];
|
||||||
String DataUnits[HowManyValues];
|
String DataUnits[HowManyValues];
|
||||||
String DataFormat[HowManyValues];
|
String DataFormat[HowManyValues];
|
||||||
FormattedData TheFormattedData;
|
FormatedData TheFormattedData;
|
||||||
|
|
||||||
for (int i = 0; i < HowManyValues; i++){
|
for (int i = 0; i < HowManyValues; i++){
|
||||||
bvalue = pageData.values[i];
|
bvalue = pageData.values[i];
|
||||||
|
@ -104,7 +104,7 @@ class PageCompass : public Page
|
||||||
setFlashLED(false);
|
setFlashLED(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bvalue == NULL) return PAGE_OK; // WTF why this statement?
|
if (bvalue == NULL) return;
|
||||||
|
|
||||||
//***********************************************************
|
//***********************************************************
|
||||||
|
|
||||||
|
@ -235,11 +235,12 @@ class PageCompass : public Page
|
||||||
// if ( x_test > 390)
|
// if ( x_test > 390)
|
||||||
// x_test = 320;
|
// x_test = 320;
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
static Page *createPage(CommonData &common){
|
static Page *createPage(CommonData &common){
|
||||||
return new PageCompass(common);
|
return new PageCompass(common);
|
||||||
}/**
|
}/**
|
||||||
|
|
|
@ -20,7 +20,7 @@ public:
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging boat values
|
// Logging boat values
|
||||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
if (bvalue1 == NULL) return;
|
||||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageDST810, %s: %f, %s: %f, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3, name4.c_str(), value4);
|
LOG_DEBUG(GwLog::LOG,"Drawing at PageDST810, %s: %f, %s: %f, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3, name4.c_str(), value4);
|
||||||
|
|
||||||
// Draw page
|
// Draw page
|
||||||
|
@ -242,7 +242,9 @@ public:
|
||||||
unit4old = unit4; // Save the old unit
|
unit4old = unit4; // Save the old unit
|
||||||
}
|
}
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ class PageFluid : public Page
|
||||||
commonData->logger->logDebug(GwLog::LOG,"New PageFluid: fluidtype=%d", fluidtype);
|
commonData->logger->logDebug(GwLog::LOG,"New PageFluid: fluidtype=%d", fluidtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -252,7 +252,9 @@ class PageFluid : public Page
|
||||||
getdisplay().fillCircle(c.x, c.y, 6, commonData->bgcolor);
|
getdisplay().fillCircle(c.x, c.y, 6, commonData->bgcolor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ class PageFourValues : public Page
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ class PageFourValues : public Page
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging boat values
|
// Logging boat values
|
||||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
if (bvalue1 == NULL) return;
|
||||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageFourValues, %s: %f, %s: %f, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3, name4.c_str(), value4);
|
LOG_DEBUG(GwLog::LOG,"Drawing at PageFourValues, %s: %f, %s: %f, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3, name4.c_str(), value4);
|
||||||
|
|
||||||
// Draw page
|
// Draw page
|
||||||
|
@ -287,7 +287,9 @@ class PageFourValues : public Page
|
||||||
unit4old = unit4; // Save the old unit
|
unit4old = unit4; // Save the old unit
|
||||||
}
|
}
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ class PageFourValues2 : public Page
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ class PageFourValues2 : public Page
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging boat values
|
// Logging boat values
|
||||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
if (bvalue1 == NULL) return;
|
||||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageFourValues2, %s: %f, %s: %f, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3, name4.c_str(), value4);
|
LOG_DEBUG(GwLog::LOG,"Drawing at PageFourValues2, %s: %f, %s: %f, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3, name4.c_str(), value4);
|
||||||
|
|
||||||
// Draw page
|
// Draw page
|
||||||
|
@ -287,7 +287,9 @@ class PageFourValues2 : public Page
|
||||||
unit4old = unit4; // Save the old unit
|
unit4old = unit4; // Save the old unit
|
||||||
}
|
}
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ public:
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData)
|
virtual void displayPage(PageData &pageData)
|
||||||
{
|
{
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
@ -203,7 +203,8 @@ public:
|
||||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||||
getdisplay().print("W");
|
getdisplay().print("W");
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ public:
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData)
|
virtual void displayPage(PageData &pageData)
|
||||||
{
|
{
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
@ -206,7 +206,9 @@ public:
|
||||||
getdisplay().print("No sensor data"); // Info missing sensor
|
getdisplay().print("No sensor data"); // Info missing sensor
|
||||||
}
|
}
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ class PageOneValue : public Page
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ class PageOneValue : public Page
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging boat values
|
// Logging boat values
|
||||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
if (bvalue1 == NULL) return;
|
||||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageOneValue, %s: %f", name1.c_str(), value1);
|
LOG_DEBUG(GwLog::LOG,"Drawing at PageOneValue, %s: %f", name1.c_str(), value1);
|
||||||
|
|
||||||
// Draw page
|
// Draw page
|
||||||
|
@ -104,7 +104,9 @@ class PageOneValue : public Page
|
||||||
unit1old = unit1; // Save the old unit
|
unit1old = unit1; // Save the old unit
|
||||||
}
|
}
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ public:
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging boat values
|
// Logging boat values
|
||||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
if (bvalue1 == NULL) return;
|
||||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageRollPitch, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2);
|
LOG_DEBUG(GwLog::LOG,"Drawing at PageRollPitch, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2);
|
||||||
|
|
||||||
// Draw page
|
// Draw page
|
||||||
|
@ -305,7 +305,9 @@ public:
|
||||||
getdisplay().print("No sensor data"); // Info missing sensor
|
getdisplay().print("No sensor data"); // Info missing sensor
|
||||||
}
|
}
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ public:
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging boat values
|
// Logging boat values
|
||||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
if (bvalue1 == NULL) return;
|
||||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageRudderPosition, %s:%f", name1.c_str(), value1);
|
LOG_DEBUG(GwLog::LOG,"Drawing at PageRudderPosition, %s:%f", name1.c_str(), value1);
|
||||||
|
|
||||||
// Draw page
|
// Draw page
|
||||||
|
@ -207,7 +207,8 @@ public:
|
||||||
getdisplay().fillCircle(200, 150, startwidth + 6, commonData->bgcolor);
|
getdisplay().fillCircle(200, 150, startwidth + 6, commonData->bgcolor);
|
||||||
getdisplay().fillCircle(200, 150, startwidth + 4, commonData->fgcolor);
|
getdisplay().fillCircle(200, 150, startwidth + 4, commonData->fgcolor);
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ class PageSixValues : public Page
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ class PageSixValues : public Page
|
||||||
setFlashLED(false);
|
setFlashLED(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bvalue == NULL) return PAGE_OK; // WTF why this statement?
|
if (bvalue == NULL) return;
|
||||||
|
|
||||||
// Draw page
|
// Draw page
|
||||||
//***********************************************************
|
//***********************************************************
|
||||||
|
@ -149,7 +149,9 @@ class PageSixValues : public Page
|
||||||
getdisplay().fillRect(SixValues_x1+SixValues_DeltaX-8, SixValues_y1+i*SixValues_DeltaY, 3, SixValues_DeltaY, commonData->fgcolor);
|
getdisplay().fillRect(SixValues_x1+SixValues_DeltaX-8, SixValues_y1+i*SixValues_DeltaY, 3, SixValues_DeltaY, commonData->fgcolor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,7 @@ public:
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -199,7 +199,8 @@ public:
|
||||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||||
getdisplay().print("W");
|
getdisplay().print("W");
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#define BOARDINFO STRINGIZE(BOARD)
|
#define BOARDINFO STRINGIZE(BOARD)
|
||||||
#define PCBINFO STRINGIZE(PCBVERS)
|
#define PCBINFO STRINGIZE(PCBVERS)
|
||||||
#define DISPLAYINFO STRINGIZE(EPDTYPE)
|
#define DISPLAYINFO STRINGIZE(EPDTYPE)
|
||||||
#define GXEPD2INFO STRINGIZE(GXEPD2VERS)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Special system page, called directly with fast key sequence 5,4
|
* Special system page, called directly with fast key sequence 5,4
|
||||||
|
@ -44,8 +43,6 @@ String batt_sensor;
|
||||||
String solar_sensor;
|
String solar_sensor;
|
||||||
String gen_sensor;
|
String gen_sensor;
|
||||||
String rot_sensor;
|
String rot_sensor;
|
||||||
double homelat;
|
|
||||||
double homelon;
|
|
||||||
|
|
||||||
char mode = 'N'; // (N)ormal, (S)ettings, (D)evice list, (C)ard
|
char mode = 'N'; // (N)ormal, (S)ettings, (D)evice list, (C)ard
|
||||||
|
|
||||||
|
@ -72,8 +69,6 @@ public:
|
||||||
solar_sensor = common.config->getString(common.config->usePowSensor2);
|
solar_sensor = common.config->getString(common.config->usePowSensor2);
|
||||||
gen_sensor = common.config->getString(common.config->usePowSensor3);
|
gen_sensor = common.config->getString(common.config->usePowSensor3);
|
||||||
rot_sensor = common.config->getString(common.config->useRotSensor);
|
rot_sensor = common.config->getString(common.config->useRotSensor);
|
||||||
homelat = common.config->getString(common.config->homeLAT).toDouble();
|
|
||||||
homelon = common.config->getString(common.config->homeLON).toDouble();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setupKeys(){
|
virtual void setupKeys(){
|
||||||
|
@ -164,7 +159,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -208,21 +203,19 @@ public:
|
||||||
|
|
||||||
getdisplay().setCursor(8, 95);
|
getdisplay().setCursor(8, 95);
|
||||||
getdisplay().print("Firmware version: ");
|
getdisplay().print("Firmware version: ");
|
||||||
getdisplay().setCursor(150, 95);
|
getdisplay().setCursor(160, 95);
|
||||||
getdisplay().print(VERSINFO);
|
getdisplay().print(VERSINFO);
|
||||||
|
|
||||||
getdisplay().setCursor(8, 113);
|
getdisplay().setCursor(8, 113);
|
||||||
getdisplay().print("Board version: ");
|
getdisplay().print("Board version: ");
|
||||||
getdisplay().setCursor(150, 113);
|
getdisplay().setCursor(160, 113);
|
||||||
getdisplay().print(BOARDINFO);
|
getdisplay().print(BOARDINFO);
|
||||||
getdisplay().print(String(" HW ") + String(PCBINFO));
|
getdisplay().print(String(" HW ") + String(PCBINFO));
|
||||||
|
|
||||||
getdisplay().setCursor(8, 131);
|
getdisplay().setCursor(8, 131);
|
||||||
getdisplay().print("Display version: ");
|
getdisplay().print("Display version: ");
|
||||||
getdisplay().setCursor(150, 131);
|
getdisplay().setCursor(160, 131);
|
||||||
getdisplay().print(DISPLAYINFO);
|
getdisplay().print(DISPLAYINFO);
|
||||||
getdisplay().print("; GxEPD2 v");
|
|
||||||
getdisplay().print(GXEPD2INFO);
|
|
||||||
|
|
||||||
getdisplay().setCursor(8, 265);
|
getdisplay().setCursor(8, 265);
|
||||||
#ifdef BOARD_OBP60S3
|
#ifdef BOARD_OBP60S3
|
||||||
|
@ -302,44 +295,34 @@ public:
|
||||||
// left column
|
// left column
|
||||||
getdisplay().setCursor(x0, y0);
|
getdisplay().setCursor(x0, y0);
|
||||||
getdisplay().print("Simulation:");
|
getdisplay().print("Simulation:");
|
||||||
getdisplay().setCursor(120, y0);
|
getdisplay().setCursor(140, y0);
|
||||||
getdisplay().print(simulation ? "on" : "off");
|
getdisplay().print(simulation ? "on" : "off");
|
||||||
|
|
||||||
getdisplay().setCursor(x0, y0 + 16);
|
getdisplay().setCursor(x0, y0 + 16);
|
||||||
getdisplay().print("Environment:");
|
getdisplay().print("Environment:");
|
||||||
getdisplay().setCursor(120, y0 + 16);
|
getdisplay().setCursor(140, y0 + 16);
|
||||||
getdisplay().print(env_module);
|
getdisplay().print(env_module);
|
||||||
|
|
||||||
getdisplay().setCursor(x0, y0 + 32);
|
getdisplay().setCursor(x0, y0 + 32);
|
||||||
getdisplay().print("Buzzer:");
|
getdisplay().print("Buzzer:");
|
||||||
getdisplay().setCursor(120, y0 + 32);
|
getdisplay().setCursor(140, y0 + 32);
|
||||||
getdisplay().print(buzzer_mode);
|
getdisplay().print(buzzer_mode);
|
||||||
|
|
||||||
getdisplay().setCursor(x0, y0 + 64);
|
getdisplay().setCursor(x0, y0 + 64);
|
||||||
getdisplay().print("GPS:");
|
getdisplay().print("GPS:");
|
||||||
getdisplay().setCursor(120, y0 + 64);
|
getdisplay().setCursor(140, y0 + 64);
|
||||||
getdisplay().print(gps_module);
|
getdisplay().print(gps_module);
|
||||||
|
|
||||||
getdisplay().setCursor(x0, y0 + 80);
|
getdisplay().setCursor(x0, y0 + 80);
|
||||||
getdisplay().print("RTC:");
|
getdisplay().print("RTC:");
|
||||||
getdisplay().setCursor(120, y0 + 80);
|
getdisplay().setCursor(140, y0 + 80);
|
||||||
getdisplay().print(rtc_module);
|
getdisplay().print(rtc_module);
|
||||||
|
|
||||||
getdisplay().setCursor(x0, y0 + 96);
|
getdisplay().setCursor(x0, y0 + 96);
|
||||||
getdisplay().print("Wifi:");
|
getdisplay().print("Wifi:");
|
||||||
getdisplay().setCursor(120, y0 + 96);
|
getdisplay().setCursor(140, y0 + 96);
|
||||||
getdisplay().print(commonData->status.wifiApOn ? "on" : "off");
|
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
|
// right column
|
||||||
getdisplay().setCursor(202, y0);
|
getdisplay().setCursor(202, y0);
|
||||||
getdisplay().print("Batt. sensor:");
|
getdisplay().print("Batt. sensor:");
|
||||||
|
@ -391,7 +374,7 @@ public:
|
||||||
|
|
||||||
// Update display
|
// Update display
|
||||||
getdisplay().nextPage(); // Partial update (fast)
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
return PAGE_OK;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ class PageThreeValues : public Page
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ class PageThreeValues : public Page
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging boat values
|
// Logging boat values
|
||||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
if (bvalue1 == NULL) return;
|
||||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageThreeValues, %s: %f, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3);
|
LOG_DEBUG(GwLog::LOG,"Drawing at PageThreeValues, %s: %f, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3);
|
||||||
|
|
||||||
// Draw page
|
// Draw page
|
||||||
|
@ -226,7 +226,8 @@ class PageThreeValues : public Page
|
||||||
unit3old = unit3; // Save the old unit
|
unit3old = unit3; // Save the old unit
|
||||||
}
|
}
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ class PageTwoValues : public Page
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ class PageTwoValues : public Page
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging boat values
|
// Logging boat values
|
||||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
if (bvalue1 == NULL) return;
|
||||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageTwoValues, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2);
|
LOG_DEBUG(GwLog::LOG,"Drawing at PageTwoValues, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2);
|
||||||
|
|
||||||
// Draw page
|
// Draw page
|
||||||
|
@ -166,7 +166,8 @@ class PageTwoValues : public Page
|
||||||
unit2old = unit2; // Save the old unit
|
unit2old = unit2; // Save the old unit
|
||||||
}
|
}
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ public:
|
||||||
getdisplay().fillRect(x + 16, y + 11, 6, 3, color);
|
getdisplay().fillRect(x + 16, y + 11, 6, 3, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -187,6 +187,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging voltage value
|
// Logging voltage value
|
||||||
|
if (raw == 0) return;
|
||||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageVoltage, Type:%s %s:=%f", batType, name1.c_str(), raw);
|
LOG_DEBUG(GwLog::LOG,"Drawing at PageVoltage, Type:%s %s:=%f", batType, name1.c_str(), raw);
|
||||||
|
|
||||||
// Draw page
|
// Draw page
|
||||||
|
@ -383,7 +384,8 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,8 @@
|
||||||
|
|
||||||
#include "Pagedata.h"
|
#include "Pagedata.h"
|
||||||
#include "OBP60Extensions.h"
|
#include "OBP60Extensions.h"
|
||||||
|
#include "MFD_OBP60_400x300_sw.h" // MFD with logo
|
||||||
#include "images/OBP_400x300.xbm" // OBP Logo
|
#include "Logo_OBP_400x300_sw.h" // OBP Logo
|
||||||
#ifdef BOARD_OBP60S3
|
|
||||||
#include "images/OBP60_400x300.xbm" // MFD with logo
|
|
||||||
#endif
|
|
||||||
#ifdef BOARD_OBP40S3
|
|
||||||
#include "images/OBP40_400x300.xbm" // MFD with logo
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class PageWhite : public Page
|
class PageWhite : public Page
|
||||||
{
|
{
|
||||||
|
@ -37,7 +31,7 @@ public:
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -67,21 +61,17 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == 'L') {
|
if (mode == 'L') {
|
||||||
getdisplay().drawXBitmap(0, 0, OBP_400x300_bits, OBP_400x300_width, OBP_400x300_height, commonData->fgcolor);
|
getdisplay().drawBitmap(0, 0, gImage_Logo_OBP_400x300_sw, getdisplay().width(), getdisplay().height(), commonData->fgcolor);
|
||||||
} else if (mode == 'M') {
|
} else if (mode == 'M') {
|
||||||
#ifdef BOARD_OBP60S3
|
getdisplay().drawBitmap(0, 0, gImage_MFD_OBP60_400x300_sw, getdisplay().width(), getdisplay().height(), commonData->fgcolor);
|
||||||
getdisplay().drawXBitmap(0, 0, OBP60_400x300_bits, OBP60_400x300_width, OBP60_400x300_height, commonData->fgcolor);
|
|
||||||
#endif
|
|
||||||
#ifdef BOARD_OBP40S3
|
|
||||||
getdisplay().drawXBitmap(0, 0, OBP40_400x300_bits, OBP40_400x300_width, OBP40_400x300_height, commonData->fgcolor);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage();
|
||||||
if (mode == 'W') {
|
if (mode == 'W') {
|
||||||
ret |= PAGE_HIBERNATE;
|
getdisplay().hibernate();
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -296,7 +296,7 @@ public:
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData)
|
virtual void displayPage(PageData &pageData)
|
||||||
{
|
{
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
@ -354,7 +354,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging boat values
|
// Logging boat values
|
||||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
if (bvalue1 == NULL) return;
|
||||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageWind, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2);
|
LOG_DEBUG(GwLog::LOG,"Drawing at PageWind, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2);
|
||||||
|
|
||||||
// Draw page
|
// Draw page
|
||||||
|
@ -618,7 +618,9 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,489 +0,0 @@
|
||||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
|
||||||
|
|
||||||
#include "BoatDataCalibration.h"
|
|
||||||
#include "OBP60Extensions.h"
|
|
||||||
#include "OBPRingBuffer.h"
|
|
||||||
#include "Pagedata.h"
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
static const double radToDeg = 180.0 / M_PI; // Conversion factor from radians to degrees
|
|
||||||
|
|
||||||
// Get maximum difference of last <amount> of TWD ringbuffer values to center chart
|
|
||||||
int getRng(const RingBuffer<int16_t>& windDirHstry, int center, size_t amount)
|
|
||||||
{
|
|
||||||
int minVal = windDirHstry.getMinVal();
|
|
||||||
size_t count = windDirHstry.getCurrentSize();
|
|
||||||
// size_t capacity = windDirHstry.getCapacity();
|
|
||||||
// size_t last = windDirHstry.getLastIdx();
|
|
||||||
|
|
||||||
if (windDirHstry.isEmpty() || amount <= 0) {
|
|
||||||
return minVal;
|
|
||||||
}
|
|
||||||
if (amount > count)
|
|
||||||
amount = count;
|
|
||||||
|
|
||||||
int value = 0;
|
|
||||||
int rng = 0;
|
|
||||||
int maxRng = minVal;
|
|
||||||
// Start from the newest value (last) and go backwards x times
|
|
||||||
for (size_t i = 0; i < amount; i++) {
|
|
||||||
// value = windDirHstry.get(((last - i) % capacity + capacity) % capacity);
|
|
||||||
value = windDirHstry.get(count - 1 - i);
|
|
||||||
|
|
||||||
if (value == minVal) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = value / 1000.0 * radToDeg;
|
|
||||||
rng = abs(((value - center + 540) % 360) - 180);
|
|
||||||
if (rng > maxRng)
|
|
||||||
maxRng = rng;
|
|
||||||
}
|
|
||||||
if (maxRng > 180) {
|
|
||||||
maxRng = 180;
|
|
||||||
}
|
|
||||||
|
|
||||||
return maxRng;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ****************************************************************
|
|
||||||
class PageWindPlot : public Page {
|
|
||||||
|
|
||||||
bool keylock = false; // Keylock
|
|
||||||
char chrtMode = 'D'; // Chart mode: 'D' for TWD, 'S' for TWS, 'B' for both
|
|
||||||
int dataIntv = 1; // Update interval for wind history chart:
|
|
||||||
// (1)|(2)|(3)|(4) seconds for approx. 4, 8, 12, 16 min. history chart
|
|
||||||
bool showTWS = true; // Show TWS value in chart area
|
|
||||||
|
|
||||||
public:
|
|
||||||
PageWindPlot(CommonData& common)
|
|
||||||
{
|
|
||||||
commonData = &common;
|
|
||||||
common.logger->logDebug(GwLog::LOG, "Instantiate PageWindPlot");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setupKeys()
|
|
||||||
{
|
|
||||||
Page::setupKeys();
|
|
||||||
// commonData->keydata[0].label = "MODE";
|
|
||||||
commonData->keydata[1].label = "INTV";
|
|
||||||
commonData->keydata[4].label = "TWS";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Key functions
|
|
||||||
virtual int handleKey(int key)
|
|
||||||
{
|
|
||||||
// Set chart mode TWD | TWS -> to be implemented
|
|
||||||
if (key == 1) {
|
|
||||||
if (chrtMode == 'D') {
|
|
||||||
chrtMode = 'S';
|
|
||||||
} else if (chrtMode == 'S') {
|
|
||||||
chrtMode = 'B';
|
|
||||||
} else {
|
|
||||||
chrtMode = 'D';
|
|
||||||
}
|
|
||||||
return 0; // Commit the key
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set interval for wind history chart update time
|
|
||||||
if (key == 2) {
|
|
||||||
if (dataIntv == 1) {
|
|
||||||
dataIntv = 2;
|
|
||||||
} else if (dataIntv == 2) {
|
|
||||||
dataIntv = 3;
|
|
||||||
} else if (dataIntv == 3) {
|
|
||||||
dataIntv = 4;
|
|
||||||
} else {
|
|
||||||
dataIntv = 1;
|
|
||||||
}
|
|
||||||
return 0; // Commit the key
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch TWS on/off
|
|
||||||
if (key == 5) {
|
|
||||||
showTWS = !showTWS;
|
|
||||||
return 0; // Commit the key
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keylock function
|
|
||||||
if (key == 11) { // Code for keylock
|
|
||||||
commonData->keylock = !commonData->keylock;
|
|
||||||
return 0; // Commit the key
|
|
||||||
}
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
int displayPage(PageData& pageData)
|
|
||||||
{
|
|
||||||
GwConfigHandler* config = commonData->config;
|
|
||||||
GwLog* logger = commonData->logger;
|
|
||||||
|
|
||||||
float twsValue; // TWS value in chart area
|
|
||||||
static String twdName, twdUnit; // TWD name and unit
|
|
||||||
static int updFreq; // Update frequency for TWD
|
|
||||||
static int16_t twdLowest, twdHighest; // TWD range
|
|
||||||
// static int16_t twdBufMinVal; // lowest possible twd buffer value; used for non-set data
|
|
||||||
|
|
||||||
// current boat data values; TWD only for validation test, TWS for display of current value
|
|
||||||
const int numBoatData = 2;
|
|
||||||
GwApi::BoatValue* bvalue;
|
|
||||||
String BDataName[numBoatData];
|
|
||||||
double BDataValue[numBoatData];
|
|
||||||
bool BDataValid[numBoatData];
|
|
||||||
String BDataText[numBoatData];
|
|
||||||
String BDataUnit[numBoatData];
|
|
||||||
String BDataFormat[numBoatData];
|
|
||||||
|
|
||||||
static bool isInitialized = false; // Flag to indicate that page is initialized
|
|
||||||
static bool wndDataValid = false; // Flag to indicate if wind data is valid
|
|
||||||
static int numNoData; // Counter for multiple invalid data values in a row
|
|
||||||
static bool simulation = false;
|
|
||||||
static bool holdValues = false;
|
|
||||||
|
|
||||||
static int width; // Screen width
|
|
||||||
static int height; // Screen height
|
|
||||||
static int xCenter; // Center of screen in x direction
|
|
||||||
static const int yOffset = 48; // Offset for y coordinates of chart area
|
|
||||||
static int cHeight; // height of chart area
|
|
||||||
static int bufSize; // History buffer size: 960 values for appox. 16 min. history chart
|
|
||||||
static int intvBufSize; // Buffer size used for currently selected time interval
|
|
||||||
int count; // current size of buffer
|
|
||||||
static int numWndVals; // number of wind values available for current interval selection
|
|
||||||
static int bufStart; // 1st data value in buffer to show
|
|
||||||
int numAddedBufVals; // Number of values added to buffer since last display
|
|
||||||
size_t currIdx; // Current index in TWD history buffer
|
|
||||||
static size_t lastIdx; // Last index of TWD history buffer
|
|
||||||
static size_t lastAddedIdx = 0; // Last index of TWD history buffer when new data was added
|
|
||||||
static int oldDataIntv; // remember recent user selection of data interval
|
|
||||||
|
|
||||||
static int wndCenter; // chart wind center value position
|
|
||||||
static int wndLeft; // chart wind left value position
|
|
||||||
static int wndRight; // chart wind right value position
|
|
||||||
static int chrtRng; // Range of wind values from mid wind value to min/max wind value in degrees
|
|
||||||
int diffRng; // Difference between mid and current wind value
|
|
||||||
static const int dfltRng = 40; // Default range for chart
|
|
||||||
int midWndDir; // New value for wndCenter after chart start / shift
|
|
||||||
static int simTwd; // Simulation value for TWD
|
|
||||||
static float simTws; // Simulation value for TWS
|
|
||||||
|
|
||||||
int x, y; // x and y coordinates for drawing
|
|
||||||
static int prevX, prevY; // Last x and y coordinates for drawing
|
|
||||||
static float chrtScl; // Scale for wind values in pixels per degree
|
|
||||||
int chrtVal; // Current wind value
|
|
||||||
static int chrtPrevVal; // Last wind value in chart area for check if value crosses 180 degree line
|
|
||||||
|
|
||||||
LOG_DEBUG(GwLog::LOG, "Display page WindPlot");
|
|
||||||
|
|
||||||
// Get config data
|
|
||||||
simulation = config->getBool(config->useSimuData);
|
|
||||||
holdValues = config->getBool(config->holdvalues);
|
|
||||||
String flashLED = config->getString(config->flashLED);
|
|
||||||
String backlightMode = config->getString(config->backlight);
|
|
||||||
|
|
||||||
if (!isInitialized) {
|
|
||||||
width = getdisplay().width();
|
|
||||||
height = getdisplay().height();
|
|
||||||
xCenter = width / 2;
|
|
||||||
cHeight = height - yOffset - 22;
|
|
||||||
bufSize = pageData.boatHstry.twdHstry->getCapacity();
|
|
||||||
numNoData = 0;
|
|
||||||
simTwd = pageData.boatHstry.twdHstry->getLast() / 1000.0 * radToDeg;
|
|
||||||
simTws = 0;
|
|
||||||
twsValue = 0;
|
|
||||||
bufStart = 0;
|
|
||||||
oldDataIntv = 0;
|
|
||||||
numAddedBufVals, currIdx, lastIdx = 0;
|
|
||||||
lastAddedIdx = pageData.boatHstry.twdHstry->getLastIdx();
|
|
||||||
pageData.boatHstry.twdHstry->getMetaData(twdName, twdUnit, updFreq, twdLowest, twdHighest);
|
|
||||||
wndCenter = INT_MIN;
|
|
||||||
midWndDir = 0;
|
|
||||||
diffRng = dfltRng;
|
|
||||||
chrtRng = dfltRng;
|
|
||||||
|
|
||||||
isInitialized = true; // Set flag to indicate that page is now initialized
|
|
||||||
}
|
|
||||||
|
|
||||||
// read boat data values; TWD only for validation test, TWS for display of current value
|
|
||||||
for (int i = 0; i < numBoatData; i++) {
|
|
||||||
bvalue = pageData.values[i];
|
|
||||||
// BDataName[i] = xdrDelete(bvalue->getName());
|
|
||||||
BDataName[i] = BDataName[i].substring(0, 6); // String length limit for value name
|
|
||||||
calibrationData.calibrateInstance(bvalue, logger); // Check if boat data value is to be calibrated
|
|
||||||
BDataValue[i] = bvalue->value; // Value as double in SI unit
|
|
||||||
BDataValid[i] = bvalue->valid;
|
|
||||||
BDataText[i] = formatValue(bvalue, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
|
||||||
BDataUnit[i] = formatValue(bvalue, *commonData).unit;
|
|
||||||
BDataFormat[i] = bvalue->getFormat(); // Unit of value
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optical warning by limit violation (unused)
|
|
||||||
if (String(flashLED) == "Limit Violation") {
|
|
||||||
setBlinkingLED(false);
|
|
||||||
setFlashLED(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Identify buffer size and buffer start position for chart
|
|
||||||
count = pageData.boatHstry.twdHstry->getCurrentSize();
|
|
||||||
currIdx = pageData.boatHstry.twdHstry->getLastIdx();
|
|
||||||
numAddedBufVals = (currIdx - lastAddedIdx + bufSize) % bufSize; // Number of values added to buffer since last display
|
|
||||||
if (dataIntv != oldDataIntv || count == 1) {
|
|
||||||
// new data interval selected by user
|
|
||||||
intvBufSize = cHeight * dataIntv;
|
|
||||||
numWndVals = min(count, (cHeight - 60) * dataIntv);
|
|
||||||
bufStart = max(0, count - numWndVals);
|
|
||||||
lastAddedIdx = currIdx;
|
|
||||||
oldDataIntv = dataIntv;
|
|
||||||
} else {
|
|
||||||
numWndVals = numWndVals + numAddedBufVals;
|
|
||||||
lastAddedIdx = currIdx;
|
|
||||||
if (count == bufSize) {
|
|
||||||
bufStart = max(0, bufStart - numAddedBufVals);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Dataset: count: %d, TWD: %.0f, TWS: %.1f, TWD_valid? %d, intvBufSize: %d, numWndVals: %d, bufStart: %d, numAddedBufVals: %d, lastIdx: %d, old: %d, act: %d",
|
|
||||||
count, pageData.boatHstry.twdHstry->getLast() / 1000.0 * radToDeg, pageData.boatHstry.twsHstry->getLast() / 10.0 * 1.94384, BDataValid[0],
|
|
||||||
intvBufSize, numWndVals, bufStart, numAddedBufVals, pageData.boatHstry.twdHstry->getLastIdx(), oldDataIntv, dataIntv);
|
|
||||||
|
|
||||||
// Set wndCenter from 1st real buffer value
|
|
||||||
if (wndCenter == INT_MIN || (wndCenter == 0 && count == 1)) {
|
|
||||||
midWndDir = pageData.boatHstry.twdHstry->getMid(numWndVals);
|
|
||||||
if (midWndDir != INT16_MIN) {
|
|
||||||
midWndDir = midWndDir / 1000.0 * radToDeg;
|
|
||||||
wndCenter = int((midWndDir + (midWndDir >= 0 ? 5 : -5)) / 10) * 10; // Set new center value; round to nearest 10 degree value
|
|
||||||
} else {
|
|
||||||
wndCenter = 0;
|
|
||||||
}
|
|
||||||
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Range Init: count: %d, TWD: %.0f, wndCenter: %d, diffRng: %d, chrtRng: %d", count, pageData.boatHstry.twdHstry->getLast() / 1000.0 * radToDeg,
|
|
||||||
wndCenter, diffRng, chrtRng);
|
|
||||||
} else {
|
|
||||||
// check and adjust range between left, center, and right chart limit
|
|
||||||
diffRng = getRng(*pageData.boatHstry.twdHstry, wndCenter, numWndVals);
|
|
||||||
diffRng = (diffRng == INT16_MIN ? 0 : diffRng);
|
|
||||||
if (diffRng > chrtRng) {
|
|
||||||
chrtRng = int((diffRng + (diffRng >= 0 ? 9 : -1)) / 10) * 10; // Round up to next 10 degree value
|
|
||||||
} else if (diffRng + 10 < chrtRng) { // Reduce chart range for higher resolution if possible
|
|
||||||
chrtRng = max(dfltRng, int((diffRng + (diffRng >= 0 ? 9 : -1)) / 10) * 10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
chrtScl = float(width) / float(chrtRng) / 2.0; // Chart scale: pixels per degree
|
|
||||||
wndLeft = wndCenter - chrtRng;
|
|
||||||
if (wndLeft < 0)
|
|
||||||
wndLeft += 360;
|
|
||||||
wndRight = (chrtRng < 180 ? wndCenter + chrtRng : wndCenter + chrtRng - 1);
|
|
||||||
if (wndRight >= 360)
|
|
||||||
wndRight -= 360;
|
|
||||||
|
|
||||||
// Draw page
|
|
||||||
//***********************************************************************
|
|
||||||
|
|
||||||
// Set display in partial refresh mode
|
|
||||||
getdisplay().setPartialWindow(0, 0, width, height); // Set partial update
|
|
||||||
getdisplay().setTextColor(commonData->fgcolor);
|
|
||||||
|
|
||||||
// chart lines
|
|
||||||
getdisplay().fillRect(0, yOffset, width, 2, commonData->fgcolor);
|
|
||||||
getdisplay().fillRect(xCenter, yOffset, 1, cHeight, commonData->fgcolor);
|
|
||||||
|
|
||||||
// chart labels
|
|
||||||
char sWndLbl[4]; // char buffer for Wind angle label
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
|
||||||
getdisplay().setCursor(xCenter - 88, yOffset - 3);
|
|
||||||
getdisplay().print("TWD"); // Wind data name
|
|
||||||
snprintf(sWndLbl, 4, "%03d", (wndCenter < 0) ? (wndCenter + 360) : wndCenter);
|
|
||||||
drawTextCenter(xCenter, yOffset - 11, sWndLbl);
|
|
||||||
getdisplay().drawCircle(xCenter + 25, yOffset - 17, 2, commonData->fgcolor); // <degree> symbol
|
|
||||||
getdisplay().drawCircle(xCenter + 25, yOffset - 17, 3, commonData->fgcolor); // <degree> symbol
|
|
||||||
getdisplay().setCursor(1, yOffset - 3);
|
|
||||||
snprintf(sWndLbl, 4, "%03d", (wndLeft < 0) ? (wndLeft + 360) : wndLeft);
|
|
||||||
getdisplay().print(sWndLbl); // Wind left value
|
|
||||||
getdisplay().drawCircle(46, yOffset - 17, 2, commonData->fgcolor); // <degree> symbol
|
|
||||||
getdisplay().drawCircle(46, yOffset - 17, 3, commonData->fgcolor); // <degree> symbol
|
|
||||||
getdisplay().setCursor(width - 50, yOffset - 3);
|
|
||||||
snprintf(sWndLbl, 4, "%03d", (wndRight < 0) ? (wndRight + 360) : wndRight);
|
|
||||||
getdisplay().print(sWndLbl); // Wind right value
|
|
||||||
getdisplay().drawCircle(width - 5, yOffset - 17, 2, commonData->fgcolor); // <degree> symbol
|
|
||||||
getdisplay().drawCircle(width - 5, yOffset - 17, 3, commonData->fgcolor); // <degree> symbol
|
|
||||||
|
|
||||||
if (pageData.boatHstry.twdHstry->getMax() == pageData.boatHstry.twdHstry->getMinVal()) {
|
|
||||||
// only <INT16_MIN> values in buffer -> no valid wind data available
|
|
||||||
wndDataValid = false;
|
|
||||||
} else if (!BDataValid[0]) {
|
|
||||||
// currently no valid TWD data available
|
|
||||||
numNoData++;
|
|
||||||
wndDataValid = true;
|
|
||||||
if (numNoData > 3) {
|
|
||||||
// If more than 4 invalid values in a row, send message
|
|
||||||
wndDataValid = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
numNoData = 0; // reset data error counter
|
|
||||||
wndDataValid = true; // At least some wind data available
|
|
||||||
}
|
|
||||||
// Draw wind values in chart
|
|
||||||
//***********************************************************************
|
|
||||||
if (wndDataValid) {
|
|
||||||
for (int i = 0; i < (numWndVals / dataIntv); i++) {
|
|
||||||
chrtVal = static_cast<int>(pageData.boatHstry.twdHstry->get(bufStart + (i * dataIntv))); // show the latest wind values in buffer; keep 1st value constant in a rolling buffer
|
|
||||||
if (chrtVal == INT16_MIN) {
|
|
||||||
chrtPrevVal = INT16_MIN;
|
|
||||||
/* if (i == linesToShow - 1) {
|
|
||||||
numNoData++;
|
|
||||||
// If more than 4 invalid values in a row, reset chart
|
|
||||||
} else {
|
|
||||||
numNoData = 0; // Reset invalid value counter
|
|
||||||
}
|
|
||||||
if (numNoData > 4) {
|
|
||||||
// If more than 4 invalid values in a row, send message
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold10pt8b);
|
|
||||||
getdisplay().fillRect(xCenter - 66, height / 2 - 20, 146, 24, commonData->bgcolor); // Clear area for TWS value
|
|
||||||
drawTextCenter(xCenter, height / 2 - 10, "No sensor data");
|
|
||||||
} */
|
|
||||||
} else {
|
|
||||||
chrtVal = static_cast<int>((chrtVal / 1000.0 * radToDeg) + 0.5); // Convert to degrees and round
|
|
||||||
x = ((chrtVal - wndLeft + 360) % 360) * chrtScl;
|
|
||||||
y = yOffset + cHeight - i; // Position in chart area
|
|
||||||
|
|
||||||
if (i >= (numWndVals / dataIntv) - 10)
|
|
||||||
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Chart: i: %d, chrtVal: %d, bufStart: %d, count: %d, linesToShow: %d", i, chrtVal, bufStart, count, (numWndVals / dataIntv));
|
|
||||||
|
|
||||||
if ((i == 0) || (chrtPrevVal == INT16_MIN)) {
|
|
||||||
// just a dot for 1st chart point or after some invalid values
|
|
||||||
prevX = x;
|
|
||||||
prevY = y;
|
|
||||||
} else {
|
|
||||||
// cross borders check; shift values to [-180..0..180]; when crossing borders, range is 2x 180 degrees
|
|
||||||
int wndLeftDlt = -180 - ((wndLeft >= 180) ? (wndLeft - 360) : wndLeft);
|
|
||||||
int chrtVal180 = ((chrtVal + wndLeftDlt + 180) % 360 + 360) % 360 - 180;
|
|
||||||
int chrtPrevVal180 = ((chrtPrevVal + wndLeftDlt + 180) % 360 + 360) % 360 - 180;
|
|
||||||
if (((chrtPrevVal180 >= -180) && (chrtPrevVal180 < -90) && (chrtVal180 > 90)) || ((chrtPrevVal180 <= 179) && (chrtPrevVal180 > 90) && chrtVal180 <= -90)) {
|
|
||||||
// If current value crosses chart borders compared to previous value, split line
|
|
||||||
int xSplit = (((chrtPrevVal180 > 0 ? wndRight : wndLeft) - wndLeft + 360) % 360) * chrtScl;
|
|
||||||
getdisplay().drawLine(prevX, prevY, xSplit, y, commonData->fgcolor);
|
|
||||||
getdisplay().drawLine(prevX, prevY - 1, ((xSplit != prevX) ? xSplit : xSplit - 1), ((xSplit != prevX) ? y - 1 : y), commonData->fgcolor);
|
|
||||||
prevX = (((chrtVal180 > 0 ? wndRight : wndLeft) - wndLeft + 360) % 360) * chrtScl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw line with 2 pixels width + make sure vertical line are drawn correctly
|
|
||||||
getdisplay().drawLine(prevX, prevY, x, y, commonData->fgcolor);
|
|
||||||
getdisplay().drawLine(prevX, prevY - 1, ((x != prevX) ? x : x - 1), ((x != prevX) ? y - 1 : y), commonData->fgcolor);
|
|
||||||
chrtPrevVal = chrtVal;
|
|
||||||
prevX = x;
|
|
||||||
prevY = y;
|
|
||||||
}
|
|
||||||
// Reaching chart area top end
|
|
||||||
if (i >= (cHeight - 1)) {
|
|
||||||
oldDataIntv = 0; // force reset of buffer start and number of values to show in next display loop
|
|
||||||
|
|
||||||
int minWndDir = pageData.boatHstry.twdHstry->getMin(numWndVals) / 1000.0 * radToDeg;
|
|
||||||
int maxWndDir = pageData.boatHstry.twdHstry->getMax(numWndVals) / 1000.0 * radToDeg;
|
|
||||||
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot FreeTop: Minimum: %d, Maximum: %d, OldwndCenter: %d", minWndDir, maxWndDir, wndCenter);
|
|
||||||
if ((minWndDir + 540 >= wndCenter + 540) || (maxWndDir + 540 <= wndCenter + 540)) {
|
|
||||||
// Check if all wind value are left or right of center value -> optimize chart range
|
|
||||||
midWndDir = pageData.boatHstry.twdHstry->getMid(numWndVals) / 1000.0 * radToDeg;
|
|
||||||
if (midWndDir != INT16_MIN) {
|
|
||||||
wndCenter = int((midWndDir + (midWndDir >= 0 ? 5 : -5)) / 10) * 10; // Set new center value; round to nearest 10 degree value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot FreeTop: cHeight: %d, bufStart: %d, numWndVals: %d, wndCenter: %d", cHeight, bufStart, numWndVals, wndCenter);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// No valid data available
|
|
||||||
LOG_DEBUG(GwLog::LOG, "PageWindPlot: No valid data available");
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold10pt8b);
|
|
||||||
getdisplay().fillRect(xCenter - 33, height / 2 - 20, 66, 24, commonData->bgcolor); // Clear area for message
|
|
||||||
drawTextCenter(xCenter, height / 2 - 10, "No data");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print TWS value
|
|
||||||
if (showTWS) {
|
|
||||||
int currentZone;
|
|
||||||
static int lastZone = 0;
|
|
||||||
static bool flipTws = false;
|
|
||||||
int xPosTws;
|
|
||||||
static const int yPosTws = yOffset + 40;
|
|
||||||
|
|
||||||
twsValue = pageData.boatHstry.twsHstry->getLast() / 10.0 * 1.94384; // TWS value in knots
|
|
||||||
|
|
||||||
xPosTws = flipTws ? 20 : width - 138;
|
|
||||||
currentZone = (y >= yPosTws - 38) && (y <= yPosTws + 6) && (x >= xPosTws - 4) && (x <= xPosTws + 146) ? 1 : 0; // Define current zone for TWS value
|
|
||||||
if (currentZone != lastZone) {
|
|
||||||
// Only flip when x moves to a different zone
|
|
||||||
if ((y >= yPosTws - 38) && (y <= yPosTws + 6) && (x >= xPosTws - 4) && (x <= xPosTws + 146)) {
|
|
||||||
flipTws = !flipTws;
|
|
||||||
xPosTws = flipTws ? 20 : width - 145;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastZone = currentZone;
|
|
||||||
|
|
||||||
getdisplay().fillRect(xPosTws - 4, yPosTws - 38, 142, 44, commonData->bgcolor); // Clear area for TWS value
|
|
||||||
getdisplay().setFont(&DSEG7Classic_BoldItalic16pt7b);
|
|
||||||
getdisplay().setCursor(xPosTws, yPosTws);
|
|
||||||
if (!BDataValid[1]) {
|
|
||||||
getdisplay().print("--.-");
|
|
||||||
} else {
|
|
||||||
double dbl = BDataValue[1] * 3.6 / 1.852;
|
|
||||||
if (dbl < 10.0) {
|
|
||||||
getdisplay().printf("!%3.1f", dbl); // Value, round to 1 decimal
|
|
||||||
} else {
|
|
||||||
getdisplay().printf("%4.1f", dbl); // Value, round to 1 decimal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
|
||||||
getdisplay().setCursor(xPosTws + 82, yPosTws - 14);
|
|
||||||
// getdisplay().print("TWS"); // Name
|
|
||||||
getdisplay().print(BDataName[1]); // Name
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
|
||||||
// getdisplay().setCursor(xPosTws + 78, yPosTws + 1);
|
|
||||||
getdisplay().setCursor(xPosTws + 82, yPosTws + 1);
|
|
||||||
// getdisplay().printf(" kn"); // Unit
|
|
||||||
getdisplay().print(BDataUnit[1]); // Unit
|
|
||||||
}
|
|
||||||
|
|
||||||
// chart Y axis labels; print at last to overwrite potential chart lines in label area
|
|
||||||
int yPos;
|
|
||||||
int chrtLbl;
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
|
||||||
for (int i = 1; i <= 3; i++) {
|
|
||||||
yPos = yOffset + (i * 60);
|
|
||||||
getdisplay().fillRect(0, yPos, width, 1, commonData->fgcolor);
|
|
||||||
getdisplay().fillRect(0, yPos - 8, 24, 16, commonData->bgcolor); // Clear small area to remove potential chart lines
|
|
||||||
getdisplay().setCursor(1, yPos + 4);
|
|
||||||
if (count >= intvBufSize) {
|
|
||||||
// Calculate minute value for label
|
|
||||||
chrtLbl = ((i - 1 + (prevY < yOffset + 30)) * dataIntv) * -1; // change label if last data point is more than 30 lines (= seconds) from chart line
|
|
||||||
} else {
|
|
||||||
int j = 3 - i;
|
|
||||||
chrtLbl = (int((((numWndVals / dataIntv) - 50) * dataIntv / 60) + 1) - (j * dataIntv)) * -1; // 50 lines left below last chart line
|
|
||||||
}
|
|
||||||
getdisplay().printf("%3d", chrtLbl); // Wind value label
|
|
||||||
}
|
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
static Page* createPage(CommonData& common)
|
|
||||||
{
|
|
||||||
return new PageWindPlot(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 (0 here)
|
|
||||||
* and will will provide the names of the fixed values we need
|
|
||||||
*/
|
|
||||||
PageDescription registerPageWindPlot(
|
|
||||||
"WindPlot", // Page name
|
|
||||||
createPage, // Action
|
|
||||||
0, // Number of bus values depends on selection in Web configuration
|
|
||||||
{ "TWD", "TWS" }, // Bus values we need in the page
|
|
||||||
// {}, // Bus values we need in the page
|
|
||||||
true // Show display header on/off
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging boat values
|
// Logging boat values
|
||||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
if (bvalue1 == NULL) return;
|
||||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageWindRose, %s:%f, %s:%f, %s:%f, %s:%f, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3, name4.c_str(), value4, name5.c_str(), value5, name6.c_str(), value6);
|
LOG_DEBUG(GwLog::LOG,"Drawing at PageWindRose, %s:%f, %s:%f, %s:%f, %s:%f, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3, name4.c_str(), value4, name5.c_str(), value5, name6.c_str(), value6);
|
||||||
|
|
||||||
// Draw page
|
// Draw page
|
||||||
|
@ -357,7 +357,8 @@ public:
|
||||||
getdisplay().print(unit6old); // Unit
|
getdisplay().print(unit6old); // Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging boat values
|
// Logging boat values
|
||||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
if (bvalue1 == NULL) return;
|
||||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageWindRoseFlex, %s:%f, %s:%f, %s:%f, %s:%f, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3, name4.c_str(), value4, name5.c_str(), value5, name6.c_str(), value6);
|
LOG_DEBUG(GwLog::LOG,"Drawing at PageWindRoseFlex, %s:%f, %s:%f, %s:%f, %s:%f, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3, name4.c_str(), value4, name5.c_str(), value5, name6.c_str(), value6);
|
||||||
|
|
||||||
// Draw page
|
// Draw page
|
||||||
|
@ -362,7 +362,8 @@ if ( cos(value1) > 0){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ class PageXTETrack : public Page
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int displayPage(PageData &pageData){
|
virtual void displayPage(PageData &pageData){
|
||||||
GwConfigHandler *config = commonData->config;
|
GwConfigHandler *config = commonData->config;
|
||||||
GwLog *logger = commonData->logger;
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
@ -207,7 +207,9 @@ class PageXTETrack : public Page
|
||||||
drawSegment(399, 100, 318, 24, 289, 24, 350, 100, commonData->fgcolor, seg[4]);
|
drawSegment(399, 100, 318, 24, 289, 24, 350, 100, commonData->fgcolor, seg[4]);
|
||||||
drawSegment(399, 54, 354, 24, 325, 24, 399, 90, commonData->fgcolor, seg[5]);
|
drawSegment(399, 54, 354, 24, 325, 24, 399, 90, commonData->fgcolor, seg[5]);
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,19 +4,15 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "LedSpiTask.h"
|
#include "LedSpiTask.h"
|
||||||
#include "OBPRingBuffer.h"
|
|
||||||
#include "OBPDataOperations.h"
|
|
||||||
|
|
||||||
#define MAX_PAGE_NUMBER 10 // Max number of pages for show data
|
#define MAX_PAGE_NUMBER 10 // Max number of pages for show data
|
||||||
|
|
||||||
typedef std::vector<GwApi::BoatValue *> ValueList;
|
typedef std::vector<GwApi::BoatValue *> ValueList;
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
String pageName;
|
String pageName;
|
||||||
uint8_t pageNumber; // page number in sequence of visible pages
|
uint8_t pageNumber; // page number in sequence of visible pages
|
||||||
//the values will always contain the user defined values first
|
//the values will always contain the user defined values first
|
||||||
ValueList values;
|
ValueList values;
|
||||||
tBoatHstryData boatHstry;
|
|
||||||
} PageData;
|
} PageData;
|
||||||
|
|
||||||
// Sensor data structure (only for extended sensors, not for NMEA bus sensors)
|
// Sensor data structure (only for extended sensors, not for NMEA bus sensors)
|
||||||
|
@ -82,22 +78,6 @@ typedef struct{
|
||||||
bool on; // fast on/off detector
|
bool on; // fast on/off detector
|
||||||
} BacklightData;
|
} BacklightData;
|
||||||
|
|
||||||
enum AlarmSource {
|
|
||||||
Alarm_Generic,
|
|
||||||
Alarm_Local,
|
|
||||||
Alarm_NMEA0183,
|
|
||||||
Alarm_NMEA2000
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
uint8_t id; // alarm-id e.g. 01..99 from NMEA0183
|
|
||||||
AlarmSource source;
|
|
||||||
String message; // single line of plain text
|
|
||||||
bool active = false;
|
|
||||||
uint8_t signal; // how to signal MESSAGE | LED | BUZZER
|
|
||||||
uint8_t length_sec; // seconds until alarm disappeares without user interaction
|
|
||||||
} AlarmData;
|
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
GwApi::Status status;
|
GwApi::Status status;
|
||||||
GwLog *logger=NULL;
|
GwLog *logger=NULL;
|
||||||
|
@ -106,7 +86,6 @@ typedef struct{
|
||||||
SunData sundata;
|
SunData sundata;
|
||||||
TouchKeyData keydata[6];
|
TouchKeyData keydata[6];
|
||||||
BacklightData backlight;
|
BacklightData backlight;
|
||||||
AlarmData alarm;
|
|
||||||
GwApi::BoatValue *time=NULL;
|
GwApi::BoatValue *time=NULL;
|
||||||
GwApi::BoatValue *date=NULL;
|
GwApi::BoatValue *date=NULL;
|
||||||
uint16_t fgcolor;
|
uint16_t fgcolor;
|
||||||
|
@ -121,7 +100,7 @@ class Page{
|
||||||
CommonData *commonData;
|
CommonData *commonData;
|
||||||
public:
|
public:
|
||||||
int refreshtime = 1000;
|
int refreshtime = 1000;
|
||||||
virtual int displayPage(PageData &pageData)=0;
|
virtual void displayPage(PageData &pageData)=0;
|
||||||
virtual void displayNew(PageData &pageData){}
|
virtual void displayNew(PageData &pageData){}
|
||||||
virtual void setupKeys() {
|
virtual void setupKeys() {
|
||||||
#ifdef HARDWARE_V21
|
#ifdef HARDWARE_V21
|
||||||
|
@ -189,15 +168,13 @@ class PageStruct{
|
||||||
// Standard format functions without overhead
|
// Standard format functions without overhead
|
||||||
String formatDate(String fmttype, uint16_t year, uint8_t month, uint8_t day);
|
String formatDate(String fmttype, uint16_t year, uint8_t month, uint8_t day);
|
||||||
String formatTime(char fmttype, uint8_t hour, uint8_t minute, uint8_t second);
|
String formatTime(char fmttype, uint8_t hour, uint8_t minute, uint8_t second);
|
||||||
String formatLatitude(double lat);
|
|
||||||
String formatLongitude(double lon);
|
|
||||||
|
|
||||||
// Structure for formatted boat values
|
// Structure for formatted boat values
|
||||||
typedef struct{
|
typedef struct{
|
||||||
double value;
|
double value;
|
||||||
String svalue;
|
String svalue;
|
||||||
String unit;
|
String unit;
|
||||||
} FormattedData;
|
} FormatedData;
|
||||||
|
|
||||||
// Formatter for boat values
|
// Formatter for boat values
|
||||||
FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata);
|
FormatedData formatValue(GwApi::BoatValue *value, CommonData &commondata);
|
||||||
|
|
|
@ -219,17 +219,6 @@
|
||||||
"obp60":"true"
|
"obp60":"true"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "calcTrueWnds",
|
|
||||||
"label": "Calculate True Wind",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": "false",
|
|
||||||
"description": "If not available, calculate true wind data from appearant wind and other boat data",
|
|
||||||
"category": "OBP60 Settings",
|
|
||||||
"capabilities": {
|
|
||||||
"obp60": "true"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "lengthFormat",
|
"name": "lengthFormat",
|
||||||
"label": "Length Format",
|
"label": "Length Format",
|
||||||
|
@ -737,7 +726,7 @@
|
||||||
"condition": [
|
"condition": [
|
||||||
{ "calInstance1": "AWA" },
|
{ "calInstance1": "AWA" },
|
||||||
{ "calInstance1": "AWS" },
|
{ "calInstance1": "AWS" },
|
||||||
{ "calInstance1": "COG" },
|
{ "calInstance2": "COG" },
|
||||||
{ "calInstance1": "DBT" },
|
{ "calInstance1": "DBT" },
|
||||||
{ "calInstance1": "HDM" },
|
{ "calInstance1": "HDM" },
|
||||||
{ "calInstance1": "PRPOS" },
|
{ "calInstance1": "PRPOS" },
|
||||||
|
@ -762,7 +751,7 @@
|
||||||
"condition": [
|
"condition": [
|
||||||
{ "calInstance1": "AWA" },
|
{ "calInstance1": "AWA" },
|
||||||
{ "calInstance1": "AWS" },
|
{ "calInstance1": "AWS" },
|
||||||
{ "calInstance1": "COG" },
|
{ "calInstance2": "COG" },
|
||||||
{ "calInstance1": "DBT" },
|
{ "calInstance1": "DBT" },
|
||||||
{ "calInstance1": "HDM" },
|
{ "calInstance1": "HDM" },
|
||||||
{ "calInstance1": "PRPOS" },
|
{ "calInstance1": "PRPOS" },
|
||||||
|
@ -790,7 +779,7 @@
|
||||||
"condition": [
|
"condition": [
|
||||||
{ "calInstance1": "AWA" },
|
{ "calInstance1": "AWA" },
|
||||||
{ "calInstance1": "AWS" },
|
{ "calInstance1": "AWS" },
|
||||||
{ "calInstance1": "COG" },
|
{ "calInstance2": "COG" },
|
||||||
{ "calInstance1": "DBT" },
|
{ "calInstance1": "DBT" },
|
||||||
{ "calInstance1": "HDM" },
|
{ "calInstance1": "HDM" },
|
||||||
{ "calInstance1": "PRPOS" },
|
{ "calInstance1": "PRPOS" },
|
||||||
|
@ -1296,6 +1285,8 @@
|
||||||
"obp60":"true"
|
"obp60":"true"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "page1type",
|
"name": "page1type",
|
||||||
"label": "Type",
|
"label": "Type",
|
||||||
|
@ -1324,7 +1315,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -1605,7 +1595,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -1883,7 +1872,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -2158,7 +2146,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -2430,7 +2417,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -2699,7 +2685,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -2965,7 +2950,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -3228,7 +3212,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -3488,7 +3471,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -3745,7 +3727,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
|
|
@ -219,17 +219,6 @@
|
||||||
"obp40": "true"
|
"obp40": "true"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "calcTrueWnds",
|
|
||||||
"label": "Calculate True Wind",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": "false",
|
|
||||||
"description": "If not available, calculate true wind data from appearant wind and other boat data",
|
|
||||||
"category": "OBP40 Settings",
|
|
||||||
"capabilities": {
|
|
||||||
"obp40": "true"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "lengthFormat",
|
"name": "lengthFormat",
|
||||||
"label": "Length Format",
|
"label": "Length Format",
|
||||||
|
@ -718,12 +707,10 @@
|
||||||
"---",
|
"---",
|
||||||
"AWA",
|
"AWA",
|
||||||
"AWS",
|
"AWS",
|
||||||
"COG",
|
|
||||||
"DBT",
|
"DBT",
|
||||||
"HDM",
|
"HDM",
|
||||||
"PRPOS",
|
"PRPOS",
|
||||||
"RPOS",
|
"RPOS",
|
||||||
"SOG",
|
|
||||||
"STW",
|
"STW",
|
||||||
"TWA",
|
"TWA",
|
||||||
"TWS",
|
"TWS",
|
||||||
|
@ -743,22 +730,8 @@
|
||||||
"description": "Offset for data instance 1",
|
"description": "Offset for data instance 1",
|
||||||
"category": "OBP40 Calibrations",
|
"category": "OBP40 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp40":"true"
|
"obp40": "true"
|
||||||
},
|
}
|
||||||
"condition": [
|
|
||||||
{ "calInstance1": "AWA" },
|
|
||||||
{ "calInstance1": "AWS" },
|
|
||||||
{ "calInstance1": "COG" },
|
|
||||||
{ "calInstance1": "DBT" },
|
|
||||||
{ "calInstance1": "HDM" },
|
|
||||||
{ "calInstance1": "PRPOS" },
|
|
||||||
{ "calInstance1": "RPOS" },
|
|
||||||
{ "calInstance1": "SOG" },
|
|
||||||
{ "calInstance1": "STW" },
|
|
||||||
{ "calInstance1": "TWA" },
|
|
||||||
{ "calInstance1": "TWS" },
|
|
||||||
{ "calInstance1": "TWD" },
|
|
||||||
{ "calInstance1": "WTemp" } ]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "calSlope1",
|
"name": "calSlope1",
|
||||||
|
@ -768,22 +741,8 @@
|
||||||
"description": "Slope for data instance 1",
|
"description": "Slope for data instance 1",
|
||||||
"category": "OBP40 Calibrations",
|
"category": "OBP40 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp40":"true"
|
"obp40": "true"
|
||||||
},
|
}
|
||||||
"condition": [
|
|
||||||
{ "calInstance1": "AWA" },
|
|
||||||
{ "calInstance1": "AWS" },
|
|
||||||
{ "calInstance1": "COG" },
|
|
||||||
{ "calInstance1": "DBT" },
|
|
||||||
{ "calInstance1": "HDM" },
|
|
||||||
{ "calInstance1": "PRPOS" },
|
|
||||||
{ "calInstance1": "RPOS" },
|
|
||||||
{ "calInstance1": "SOG" },
|
|
||||||
{ "calInstance1": "STW" },
|
|
||||||
{ "calInstance1": "TWA" },
|
|
||||||
{ "calInstance1": "TWS" },
|
|
||||||
{ "calInstance1": "TWD" },
|
|
||||||
{ "calInstance1": "WTemp" } ]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "calSmooth1",
|
"name": "calSmooth1",
|
||||||
|
@ -793,25 +752,11 @@
|
||||||
"check": "checkMinMax",
|
"check": "checkMinMax",
|
||||||
"min": 0,
|
"min": 0,
|
||||||
"max": 10,
|
"max": 10,
|
||||||
"description": "Smoothing factor [0..10]; 0 = no smoothing",
|
"description": "Smoothing factor for data instance 1",
|
||||||
"category": "OBP40 Calibrations",
|
"category": "OBP40 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp40":"true"
|
"obp40": "true"
|
||||||
},
|
}
|
||||||
"condition": [
|
|
||||||
{ "calInstance1": "AWA" },
|
|
||||||
{ "calInstance1": "AWS" },
|
|
||||||
{ "calInstance1": "COG" },
|
|
||||||
{ "calInstance1": "DBT" },
|
|
||||||
{ "calInstance1": "HDM" },
|
|
||||||
{ "calInstance1": "PRPOS" },
|
|
||||||
{ "calInstance1": "RPOS" },
|
|
||||||
{ "calInstance1": "SOG" },
|
|
||||||
{ "calInstance1": "STW" },
|
|
||||||
{ "calInstance1": "TWA" },
|
|
||||||
{ "calInstance1": "TWS" },
|
|
||||||
{ "calInstance1": "TWD" },
|
|
||||||
{ "calInstance1": "WTemp" } ]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "calInstance2",
|
"name": "calInstance2",
|
||||||
|
@ -823,12 +768,10 @@
|
||||||
"---",
|
"---",
|
||||||
"AWA",
|
"AWA",
|
||||||
"AWS",
|
"AWS",
|
||||||
"COG",
|
|
||||||
"DBT",
|
"DBT",
|
||||||
"HDM",
|
"HDM",
|
||||||
"PRPOS",
|
"PRPOS",
|
||||||
"RPOS",
|
"RPOS",
|
||||||
"SOG",
|
|
||||||
"STW",
|
"STW",
|
||||||
"TWA",
|
"TWA",
|
||||||
"TWS",
|
"TWS",
|
||||||
|
@ -848,22 +791,8 @@
|
||||||
"description": "Offset for data instance 2",
|
"description": "Offset for data instance 2",
|
||||||
"category": "OBP40 Calibrations",
|
"category": "OBP40 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp40":"true"
|
"obp40": "true"
|
||||||
},
|
}
|
||||||
"condition": [
|
|
||||||
{ "calInstance2": "AWA" },
|
|
||||||
{ "calInstance2": "AWS" },
|
|
||||||
{ "calInstance2": "COG" },
|
|
||||||
{ "calInstance2": "DBT" },
|
|
||||||
{ "calInstance2": "HDM" },
|
|
||||||
{ "calInstance2": "PRPOS" },
|
|
||||||
{ "calInstance2": "RPOS" },
|
|
||||||
{ "calInstance2": "SOG" },
|
|
||||||
{ "calInstance2": "STW" },
|
|
||||||
{ "calInstance2": "TWA" },
|
|
||||||
{ "calInstance2": "TWS" },
|
|
||||||
{ "calInstance2": "TWD" },
|
|
||||||
{ "calInstance2": "WTemp" } ]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "calSlope2",
|
"name": "calSlope2",
|
||||||
|
@ -873,22 +802,8 @@
|
||||||
"description": "Slope for data instance 2",
|
"description": "Slope for data instance 2",
|
||||||
"category": "OBP40 Calibrations",
|
"category": "OBP40 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp40":"true"
|
"obp40": "true"
|
||||||
},
|
}
|
||||||
"condition": [
|
|
||||||
{ "calInstance2": "AWA" },
|
|
||||||
{ "calInstance2": "AWS" },
|
|
||||||
{ "calInstance2": "COG" },
|
|
||||||
{ "calInstance2": "DBT" },
|
|
||||||
{ "calInstance2": "HDM" },
|
|
||||||
{ "calInstance2": "PRPOS" },
|
|
||||||
{ "calInstance2": "RPOS" },
|
|
||||||
{ "calInstance2": "SOG" },
|
|
||||||
{ "calInstance2": "STW" },
|
|
||||||
{ "calInstance2": "TWA" },
|
|
||||||
{ "calInstance2": "TWS" },
|
|
||||||
{ "calInstance2": "TWD" },
|
|
||||||
{ "calInstance2": "WTemp" } ]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "calSmooth2",
|
"name": "calSmooth2",
|
||||||
|
@ -898,25 +813,11 @@
|
||||||
"check": "checkMinMax",
|
"check": "checkMinMax",
|
||||||
"min": 0,
|
"min": 0,
|
||||||
"max": 10,
|
"max": 10,
|
||||||
"description": "Smoothing factor [0..10]; 0 = no smoothing",
|
"description": "Smoothing factor for data instance 2",
|
||||||
"category": "OBP40 Calibrations",
|
"category": "OBP40 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp40":"true"
|
"obp40": "true"
|
||||||
},
|
}
|
||||||
"condition": [
|
|
||||||
{ "calInstance2": "AWA" },
|
|
||||||
{ "calInstance2": "AWS" },
|
|
||||||
{ "calInstance2": "COG" },
|
|
||||||
{ "calInstance2": "DBT" },
|
|
||||||
{ "calInstance2": "HDM" },
|
|
||||||
{ "calInstance2": "PRPOS" },
|
|
||||||
{ "calInstance2": "RPOS" },
|
|
||||||
{ "calInstance2": "SOG" },
|
|
||||||
{ "calInstance2": "STW" },
|
|
||||||
{ "calInstance2": "TWA" },
|
|
||||||
{ "calInstance2": "TWS" },
|
|
||||||
{ "calInstance2": "TWD" },
|
|
||||||
{ "calInstance2": "WTemp" } ]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "calInstance3",
|
"name": "calInstance3",
|
||||||
|
@ -928,12 +829,10 @@
|
||||||
"---",
|
"---",
|
||||||
"AWA",
|
"AWA",
|
||||||
"AWS",
|
"AWS",
|
||||||
"COG",
|
|
||||||
"DBT",
|
"DBT",
|
||||||
"HDM",
|
"HDM",
|
||||||
"PRPOS",
|
"PRPOS",
|
||||||
"RPOS",
|
"RPOS",
|
||||||
"SOG",
|
|
||||||
"STW",
|
"STW",
|
||||||
"TWA",
|
"TWA",
|
||||||
"TWS",
|
"TWS",
|
||||||
|
@ -953,22 +852,8 @@
|
||||||
"description": "Offset for data instance 3",
|
"description": "Offset for data instance 3",
|
||||||
"category": "OBP40 Calibrations",
|
"category": "OBP40 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp40":"true"
|
"obp40": "true"
|
||||||
},
|
}
|
||||||
"condition": [
|
|
||||||
{ "calInstance3": "AWA" },
|
|
||||||
{ "calInstance3": "AWS" },
|
|
||||||
{ "calInstance3": "COG" },
|
|
||||||
{ "calInstance3": "DBT" },
|
|
||||||
{ "calInstance3": "HDM" },
|
|
||||||
{ "calInstance3": "PRPOS" },
|
|
||||||
{ "calInstance3": "RPOS" },
|
|
||||||
{ "calInstance3": "SOG" },
|
|
||||||
{ "calInstance3": "STW" },
|
|
||||||
{ "calInstance3": "TWA" },
|
|
||||||
{ "calInstance3": "TWS" },
|
|
||||||
{ "calInstance3": "TWD" },
|
|
||||||
{ "calInstance3": "WTemp" } ]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "calSlope3",
|
"name": "calSlope3",
|
||||||
|
@ -978,22 +863,8 @@
|
||||||
"description": "Slope for data instance 3",
|
"description": "Slope for data instance 3",
|
||||||
"category": "OBP40 Calibrations",
|
"category": "OBP40 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp40":"true"
|
"obp40": "true"
|
||||||
},
|
}
|
||||||
"condition": [
|
|
||||||
{ "calInstance3": "AWA" },
|
|
||||||
{ "calInstance3": "AWS" },
|
|
||||||
{ "calInstance3": "COG" },
|
|
||||||
{ "calInstance3": "DBT" },
|
|
||||||
{ "calInstance3": "HDM" },
|
|
||||||
{ "calInstance3": "PRPOS" },
|
|
||||||
{ "calInstance3": "RPOS" },
|
|
||||||
{ "calInstance3": "SOG" },
|
|
||||||
{ "calInstance3": "STW" },
|
|
||||||
{ "calInstance3": "TWA" },
|
|
||||||
{ "calInstance3": "TWS" },
|
|
||||||
{ "calInstance3": "TWD" },
|
|
||||||
{ "calInstance3": "WTemp" } ]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "calSmooth3",
|
"name": "calSmooth3",
|
||||||
|
@ -1003,25 +874,11 @@
|
||||||
"check": "checkMinMax",
|
"check": "checkMinMax",
|
||||||
"min": 0,
|
"min": 0,
|
||||||
"max": 10,
|
"max": 10,
|
||||||
"description": "Smoothing factor [0..10]; 0 = no smoothing",
|
"description": "Smoothing factor for data instance 3",
|
||||||
"category": "OBP40 Calibrations",
|
"category": "OBP40 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp40":"true"
|
"obp40": "true"
|
||||||
},
|
}
|
||||||
"condition": [
|
|
||||||
{ "calInstance3": "AWA" },
|
|
||||||
{ "calInstance3": "AWS" },
|
|
||||||
{ "calInstance3": "COG" },
|
|
||||||
{ "calInstance3": "DBT" },
|
|
||||||
{ "calInstance3": "HDM" },
|
|
||||||
{ "calInstance3": "PRPOS" },
|
|
||||||
{ "calInstance3": "RPOS" },
|
|
||||||
{ "calInstance3": "SOG" },
|
|
||||||
{ "calInstance3": "STW" },
|
|
||||||
{ "calInstance3": "TWA" },
|
|
||||||
{ "calInstance3": "TWS" },
|
|
||||||
{ "calInstance3": "TWD" },
|
|
||||||
{ "calInstance3": "WTemp" } ]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "display",
|
"name": "display",
|
||||||
|
@ -1347,7 +1204,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -1628,7 +1484,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -1906,7 +1761,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -2181,7 +2035,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -2453,7 +2306,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -2722,7 +2574,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -2988,7 +2839,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -3251,7 +3101,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -3511,7 +3360,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -3768,7 +3616,6 @@
|
||||||
"Voltage",
|
"Voltage",
|
||||||
"WhitePage",
|
"WhitePage",
|
||||||
"Wind",
|
"Wind",
|
||||||
"WindPlot",
|
|
||||||
"WindRose",
|
"WindRose",
|
||||||
"WindRoseFlex",
|
"WindRoseFlex",
|
||||||
"XTETrack"
|
"XTETrack"
|
||||||
|
@ -3995,4 +3842,3 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -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,30 +0,0 @@
|
||||||
# PlatformIO extra script for obp60task
|
|
||||||
|
|
||||||
epdtype = "unknown"
|
|
||||||
pcbvers = "unknown"
|
|
||||||
for x in env["BUILD_FLAGS"]:
|
|
||||||
if x.startswith("-D HARDWARE_"):
|
|
||||||
pcbvers = x.split('_')[1]
|
|
||||||
if x.startswith("-D DISPLAY_"):
|
|
||||||
epdtype = x.split('_')[1]
|
|
||||||
|
|
||||||
propfilename = os.path.join(env["PROJECT_LIBDEPS_DIR"], env["PIOENV"], "GxEPD2/library.properties")
|
|
||||||
properties = {}
|
|
||||||
with open(propfilename, 'r') as file:
|
|
||||||
for line in file:
|
|
||||||
match = re.match(r'^([^=]+)=(.*)$', line)
|
|
||||||
if match:
|
|
||||||
key = match.group(1).strip()
|
|
||||||
value = match.group(2).strip()
|
|
||||||
properties[key] = value
|
|
||||||
|
|
||||||
gxepd2vers = "unknown"
|
|
||||||
try:
|
|
||||||
if properties["name"] == "GxEPD2":
|
|
||||||
gxepd2vers = properties["version"]
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
env["CPPDEFINES"].extend([("BOARD", env["BOARD"]), ("EPDTYPE", epdtype), ("PCBVERS", pcbvers), ("GXEPD2VERS", gxepd2vers)])
|
|
||||||
|
|
||||||
print("added hardware info to CPPDEFINES")
|
|
|
@ -31,7 +31,6 @@ no_of_fields_per_page = {
|
||||||
"TwoValues": 2,
|
"TwoValues": 2,
|
||||||
"Voltage": 0,
|
"Voltage": 0,
|
||||||
"WhitePage": 0,
|
"WhitePage": 0,
|
||||||
"WindPlot": 0,
|
|
||||||
"WindRose": 0,
|
"WindRose": 0,
|
||||||
"WindRoseFlex": 6,
|
"WindRoseFlex": 6,
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -13,8 +13,6 @@
|
||||||
#include "OBP60Extensions.h" // Functions lib for extension board
|
#include "OBP60Extensions.h" // Functions lib for extension board
|
||||||
#include "OBP60Keypad.h" // Functions for keypad
|
#include "OBP60Keypad.h" // Functions for keypad
|
||||||
#include "BoatDataCalibration.h" // Functions lib for data instance calibration
|
#include "BoatDataCalibration.h" // Functions lib for data instance calibration
|
||||||
#include "OBPRingBuffer.h" // Functions lib with ring buffer for history storage of some boat data
|
|
||||||
#include "OBPDataOperations.h" // Functions lib for data operations such as true wind calculation
|
|
||||||
|
|
||||||
#ifdef BOARD_OBP40S3
|
#ifdef BOARD_OBP40S3
|
||||||
#include "driver/rtc_io.h" // Needs for weakup from deep sleep
|
#include "driver/rtc_io.h" // Needs for weakup from deep sleep
|
||||||
|
@ -277,8 +275,6 @@ void registerAllPages(PageList &list){
|
||||||
list.add(®isterPageFourValues2);
|
list.add(®isterPageFourValues2);
|
||||||
extern PageDescription registerPageWind;
|
extern PageDescription registerPageWind;
|
||||||
list.add(®isterPageWind);
|
list.add(®isterPageWind);
|
||||||
extern PageDescription registerPageWindPlot;
|
|
||||||
list.add(®isterPageWindPlot);
|
|
||||||
extern PageDescription registerPageWindRose;
|
extern PageDescription registerPageWindRose;
|
||||||
list.add(®isterPageWindRose);
|
list.add(®isterPageWindRose);
|
||||||
extern PageDescription registerPageWindRoseFlex;
|
extern PageDescription registerPageWindRoseFlex;
|
||||||
|
@ -376,125 +372,6 @@ void underVoltageDetection(GwApi *api, CommonData &common){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool addTrueWind(GwApi* api, BoatValueList* boatValues, double *twd, double *tws, double *twa) {
|
|
||||||
bool addTrueWind(GwApi* api, BoatValueList* boatValues) {
|
|
||||||
// Calculate true wind data and add to obp60task boat data list
|
|
||||||
|
|
||||||
double awaVal, awsVal, cogVal, stwVal, sogVal, hdtVal, hdmVal, varVal;
|
|
||||||
double twd, tws, twa;
|
|
||||||
bool isCalculated = false;
|
|
||||||
const double DBL_MIN = std::numeric_limits<double>::lowest();
|
|
||||||
|
|
||||||
GwApi::BoatValue *twdBVal = boatValues->findValueOrCreate("TWD");
|
|
||||||
GwApi::BoatValue *twsBVal = boatValues->findValueOrCreate("TWS");
|
|
||||||
GwApi::BoatValue *twaBVal = boatValues->findValueOrCreate("TWA");
|
|
||||||
GwApi::BoatValue *awaBVal = boatValues->findValueOrCreate("AWA");
|
|
||||||
GwApi::BoatValue *awsBVal = boatValues->findValueOrCreate("AWS");
|
|
||||||
GwApi::BoatValue *cogBVal = boatValues->findValueOrCreate("COG");
|
|
||||||
GwApi::BoatValue *stwBVal = boatValues->findValueOrCreate("STW");
|
|
||||||
GwApi::BoatValue *sogBVal = boatValues->findValueOrCreate("SOG");
|
|
||||||
GwApi::BoatValue *hdtBVal = boatValues->findValueOrCreate("HDT");
|
|
||||||
GwApi::BoatValue *hdmBVal = boatValues->findValueOrCreate("HDM");
|
|
||||||
GwApi::BoatValue *varBVal = boatValues->findValueOrCreate("VAR");
|
|
||||||
awaVal = awaBVal->valid ? awaBVal->value : DBL_MIN;
|
|
||||||
awsVal = awsBVal->valid ? awsBVal->value : DBL_MIN;
|
|
||||||
cogVal = cogBVal->valid ? cogBVal->value : DBL_MIN;
|
|
||||||
stwVal = stwBVal->valid ? stwBVal->value : DBL_MIN;
|
|
||||||
sogVal = sogBVal->valid ? sogBVal->value : DBL_MIN;
|
|
||||||
hdtVal = hdtBVal->valid ? hdtBVal->value : DBL_MIN;
|
|
||||||
hdmVal = hdmBVal->valid ? hdmBVal->value : DBL_MIN;
|
|
||||||
varVal = varBVal->valid ? varBVal->value : DBL_MIN;
|
|
||||||
api->getLogger()->logDebug(GwLog::DEBUG,"obp60task addTrueWind: AWA: %.1f, AWS: %.1f, COG: %.1f, STW: %.1f, HDT: %.1f, HDM: %.1f, VAR: %.1f", awaBVal->value * RAD_TO_DEG, awsBVal->value * 3.6 / 1.852,
|
|
||||||
cogBVal->value * RAD_TO_DEG, stwBVal->value * 3.6 / 1.852, hdtBVal->value * RAD_TO_DEG, hdmBVal->value * RAD_TO_DEG, varBVal->value * RAD_TO_DEG);
|
|
||||||
|
|
||||||
// isCalculated = WindUtils::calcTrueWind(&awaVal, &awsVal, &cogVal, &stwVal, &sogVal, &hdtVal, &hdmVal, &varVal, &twdBVal->value, &twsBVal->value, &twaBVal->value);
|
|
||||||
isCalculated = WindUtils::calcTrueWind(&awaVal, &awsVal, &cogVal, &stwVal, &sogVal, &hdtVal, &hdmVal, &varVal, &twd, &tws, &twa);
|
|
||||||
|
|
||||||
if (isCalculated) { // Replace values only, if successfully calculated and not already available
|
|
||||||
if (!twdBVal->valid) {
|
|
||||||
twdBVal->value = twd;
|
|
||||||
twdBVal->valid = true;
|
|
||||||
}
|
|
||||||
if (!twsBVal->valid) {
|
|
||||||
twsBVal->value = tws;
|
|
||||||
twsBVal->valid = true;
|
|
||||||
}
|
|
||||||
if (!twaBVal->valid) {
|
|
||||||
twaBVal->value = twa;
|
|
||||||
twaBVal->valid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
api->getLogger()->logDebug(GwLog::DEBUG,"obp60task calcTrueWind: TWD_Valid? %d, TWD=%.1f, TWS=%.1f, TWA=%.1f, isCalculated? %d", twdBVal->valid, twdBVal->value * RAD_TO_DEG, twsBVal->value * 3.6 / 1.852,
|
|
||||||
twaBVal->value * RAD_TO_DEG, isCalculated);
|
|
||||||
|
|
||||||
return isCalculated;
|
|
||||||
}
|
|
||||||
|
|
||||||
void initHstryBuf(GwApi* api, BoatValueList* boatValues, tBoatHstryData hstryBufList) {
|
|
||||||
// Init history buffers for TWD, TWS
|
|
||||||
|
|
||||||
GwApi::BoatValue *calBVal; // temp variable just for data calibration -> we don't want to calibrate the original data here
|
|
||||||
|
|
||||||
int hstryUpdFreq = 1000; // Update frequency for history buffers in ms
|
|
||||||
int hstryMinVal = 0; // Minimum value for these history buffers
|
|
||||||
int twdHstryMax = 6283; // Max value for wind direction (TWD) in rad (0...2*PI), shifted by 1000 for 3 decimals
|
|
||||||
int twsHstryMax = 1000; // Max value for wind speed (TWS) in m/s, shifted by 10 for 1 decimal
|
|
||||||
// Initialize history buffers with meta data
|
|
||||||
hstryBufList.twdHstry->setMetaData("TWD", "formatCourse", hstryUpdFreq, hstryMinVal, twdHstryMax);
|
|
||||||
hstryBufList.twsHstry->setMetaData("TWS", "formatKnots", hstryUpdFreq, hstryMinVal, twsHstryMax);
|
|
||||||
|
|
||||||
GwApi::BoatValue *twdBVal = boatValues->findValueOrCreate(hstryBufList.twdHstry->getName());
|
|
||||||
GwApi::BoatValue *twsBVal = boatValues->findValueOrCreate(hstryBufList.twsHstry->getName());
|
|
||||||
GwApi::BoatValue *twaBVal = boatValues->findValueOrCreate("TWA");
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleHstryBuf(GwApi* api, BoatValueList* boatValues, tBoatHstryData hstryBufList) {
|
|
||||||
// Handle history buffers for TWD, TWS
|
|
||||||
|
|
||||||
GwLog *logger = api->getLogger();
|
|
||||||
|
|
||||||
int16_t twdHstryMin = hstryBufList.twdHstry->getMinVal();
|
|
||||||
int16_t twdHstryMax = hstryBufList.twdHstry->getMaxVal();
|
|
||||||
int16_t twsHstryMin = hstryBufList.twsHstry->getMinVal();
|
|
||||||
int16_t twsHstryMax = hstryBufList.twsHstry->getMaxVal();
|
|
||||||
int16_t twdBuf, twsBuf;
|
|
||||||
GwApi::BoatValue *calBVal; // temp variable just for data calibration -> we don't want to calibrate the original data here
|
|
||||||
|
|
||||||
GwApi::BoatValue *twdBVal = boatValues->findValueOrCreate(hstryBufList.twdHstry->getName());
|
|
||||||
GwApi::BoatValue *twsBVal = boatValues->findValueOrCreate(hstryBufList.twsHstry->getName());
|
|
||||||
GwApi::BoatValue *twaBVal = boatValues->findValueOrCreate("TWA");
|
|
||||||
|
|
||||||
api->getLogger()->logDebug(GwLog::DEBUG,"obp60task handleHstryBuf: twdBVal: %f, twsBVal: %f, twaBVal: %f, TWD_isValid? %d", twdBVal->value * RAD_TO_DEG,
|
|
||||||
twsBVal->value * 3.6 / 1.852, twaBVal->value * RAD_TO_DEG, twdBVal->valid);
|
|
||||||
calBVal = new GwApi::BoatValue("TWD"); // temporary solution for calibration of history buffer values
|
|
||||||
calBVal->setFormat(twdBVal->getFormat());
|
|
||||||
if (twdBVal->valid) {
|
|
||||||
calBVal->value = twdBVal->value;
|
|
||||||
calBVal->valid = twdBVal->valid;
|
|
||||||
calibrationData.calibrateInstance(calBVal, logger); // Check if boat data value is to be calibrated
|
|
||||||
twdBuf = static_cast<int16_t>(std::round(calBVal->value * 1000));
|
|
||||||
if (twdBuf >= twdHstryMin && twdBuf <= twdHstryMax) {
|
|
||||||
hstryBufList.twdHstry->add(twdBuf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete calBVal;
|
|
||||||
calBVal = nullptr;
|
|
||||||
|
|
||||||
calBVal = new GwApi::BoatValue("TWS"); // temporary solution for calibration of history buffer values
|
|
||||||
calBVal->setFormat(twsBVal->getFormat());
|
|
||||||
if (twsBVal->valid) {
|
|
||||||
calBVal->value = twsBVal->value;
|
|
||||||
calBVal->valid = twsBVal->valid;
|
|
||||||
calibrationData.calibrateInstance(calBVal, logger); // Check if boat data value is to be calibrated
|
|
||||||
twsBuf = static_cast<int16_t>(std::round(calBVal->value * 10));
|
|
||||||
if (twsBuf >= twsHstryMin && twsBuf <= twsHstryMax) {
|
|
||||||
hstryBufList.twsHstry->add(twsBuf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete calBVal;
|
|
||||||
calBVal = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// OBP60 Task
|
// OBP60 Task
|
||||||
//####################################################################################
|
//####################################################################################
|
||||||
void OBP60Task(GwApi *api){
|
void OBP60Task(GwApi *api){
|
||||||
|
@ -544,7 +421,7 @@ void OBP60Task(GwApi *api){
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DISPLAY_GDEY042T81
|
#ifdef DISPLAY_GDEY042T81
|
||||||
getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
getdisplay().init(115200, true, 2, false); // Use this for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||||
#else
|
#else
|
||||||
getdisplay().init(115200); // Init for normal displays
|
getdisplay().init(115200); // Init for normal displays
|
||||||
#endif
|
#endif
|
||||||
|
@ -608,11 +485,6 @@ void OBP60Task(GwApi *api){
|
||||||
//commonData.distanceformat=config->getString(xxx);
|
//commonData.distanceformat=config->getString(xxx);
|
||||||
//add all necessary data to common data
|
//add all necessary data to common data
|
||||||
|
|
||||||
// Create ring buffers for history storage of some boat data
|
|
||||||
RingBuffer<int16_t> twdHstry(960); // Circular buffer to store wind direction values; store 960 TWD values for 16 minutes history
|
|
||||||
RingBuffer<int16_t> twsHstry(960); // Circular buffer to store wind speed values (TWS)
|
|
||||||
tBoatHstryData hstryBufList = {&twdHstry, &twsHstry};
|
|
||||||
|
|
||||||
//fill the page data from config
|
//fill the page data from config
|
||||||
numPages=config->getInt(config->visiblePages,1);
|
numPages=config->getInt(config->visiblePages,1);
|
||||||
if (numPages < 1) numPages=1;
|
if (numPages < 1) numPages=1;
|
||||||
|
@ -651,10 +523,6 @@ void OBP60Task(GwApi *api){
|
||||||
LOG_DEBUG(GwLog::DEBUG,"added fixed value %s to page %d",value->getName().c_str(),i);
|
LOG_DEBUG(GwLog::DEBUG,"added fixed value %s to page %d",value->getName().c_str(),i);
|
||||||
pages[i].parameters.values.push_back(value);
|
pages[i].parameters.values.push_back(value);
|
||||||
}
|
}
|
||||||
if (pages[i].description->pageName == "WindPlot") {
|
|
||||||
// Add boat history data to page parameters
|
|
||||||
pages[i].parameters.boatHstry = hstryBufList;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// add out of band system page (always available)
|
// add out of band system page (always available)
|
||||||
Page *syspage = allPages.pages[0]->creator(commonData);
|
Page *syspage = allPages.pages[0]->creator(commonData);
|
||||||
|
@ -662,13 +530,6 @@ void OBP60Task(GwApi *api){
|
||||||
// Read all calibration data settings from config
|
// Read all calibration data settings from config
|
||||||
calibrationData.readConfig(config, logger);
|
calibrationData.readConfig(config, logger);
|
||||||
|
|
||||||
// Check user setting for true wind calculation
|
|
||||||
bool calcTrueWnds = api->getConfig()->getBool(api->getConfig()->calcTrueWnds, false);
|
|
||||||
// bool simulation = api->getConfig()->getBool(api->getConfig()->useSimuData, false);
|
|
||||||
|
|
||||||
// Initialize history buffer for certain boat data
|
|
||||||
initHstryBuf(api, &boatValues, hstryBufList);
|
|
||||||
|
|
||||||
// Display screenshot handler for HTTP request
|
// Display screenshot handler for HTTP request
|
||||||
// http://192.168.15.1/api/user/OBP60Task/screenshot
|
// http://192.168.15.1/api/user/OBP60Task/screenshot
|
||||||
api->registerRequestHandler("screenshot", [api, &pageNumber, pages](AsyncWebServerRequest *request) {
|
api->registerRequestHandler("screenshot", [api, &pageNumber, pages](AsyncWebServerRequest *request) {
|
||||||
|
@ -850,7 +711,7 @@ void OBP60Task(GwApi *api){
|
||||||
}
|
}
|
||||||
|
|
||||||
// #9 or #10 Refresh display after a new page after 4s waiting time and if refresh is disabled
|
// #9 or #10 Refresh display after a new page after 4s waiting time and if refresh is disabled
|
||||||
if(refreshmode == true && (keyboardMessage == 9 || keyboardMessage == 10 || keyboardMessage == 4 || keyboardMessage == 3)){
|
if(refreshmode == true && (keyboardMessage == 9 || keyboardMessage == 10)){
|
||||||
starttime4 = millis();
|
starttime4 = millis();
|
||||||
starttime2 = millis(); // Reset the timer for full display update
|
starttime2 = millis(); // Reset the timer for full display update
|
||||||
delayedDisplayUpdate = true;
|
delayedDisplayUpdate = true;
|
||||||
|
@ -886,22 +747,12 @@ void OBP60Task(GwApi *api){
|
||||||
starttime1 = millis();
|
starttime1 = millis();
|
||||||
starttime2 = millis();
|
starttime2 = millis();
|
||||||
getdisplay().setFullWindow(); // Set full update
|
getdisplay().setFullWindow(); // Set full update
|
||||||
if(fastrefresh == "true"){
|
getdisplay().nextPage();
|
||||||
getdisplay().nextPage(); // Full update
|
if(fastrefresh == "false"){
|
||||||
}
|
|
||||||
else{
|
|
||||||
getdisplay().fillScreen(commonData.fgcolor); // Clear display
|
getdisplay().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
|
|
||||||
#else
|
|
||||||
getdisplay().init(115200); // Init for normal displays
|
|
||||||
#endif
|
|
||||||
getdisplay().firstPage(); // Full update
|
|
||||||
getdisplay().nextPage(); // Full update
|
getdisplay().nextPage(); // Full update
|
||||||
// getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||||
// getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
getdisplay().nextPage(); // Full update
|
||||||
// getdisplay().nextPage(); // Partial update
|
|
||||||
// getdisplay().nextPage(); // Partial update
|
|
||||||
}
|
}
|
||||||
delayedDisplayUpdate = false;
|
delayedDisplayUpdate = false;
|
||||||
}
|
}
|
||||||
|
@ -913,22 +764,12 @@ void OBP60Task(GwApi *api){
|
||||||
starttime2 = millis();
|
starttime2 = millis();
|
||||||
LOG_DEBUG(GwLog::DEBUG,"E-Ink full refresh first 5 min");
|
LOG_DEBUG(GwLog::DEBUG,"E-Ink full refresh first 5 min");
|
||||||
getdisplay().setFullWindow(); // Set full update
|
getdisplay().setFullWindow(); // Set full update
|
||||||
if(fastrefresh == "true"){
|
getdisplay().nextPage();
|
||||||
getdisplay().nextPage(); // Full update
|
if(fastrefresh == "false"){
|
||||||
}
|
|
||||||
else{
|
|
||||||
getdisplay().fillScreen(commonData.fgcolor); // Clear display
|
getdisplay().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
|
|
||||||
#else
|
|
||||||
getdisplay().init(115200); // Init for normal displays
|
|
||||||
#endif
|
|
||||||
getdisplay().firstPage(); // Full update
|
|
||||||
getdisplay().nextPage(); // Full update
|
getdisplay().nextPage(); // Full update
|
||||||
// getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||||
// getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
getdisplay().nextPage(); // Full update
|
||||||
// getdisplay().nextPage(); // Partial update
|
|
||||||
// getdisplay().nextPage(); // Partial update
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -937,25 +778,15 @@ void OBP60Task(GwApi *api){
|
||||||
starttime2 = millis();
|
starttime2 = millis();
|
||||||
LOG_DEBUG(GwLog::DEBUG,"E-Ink full refresh");
|
LOG_DEBUG(GwLog::DEBUG,"E-Ink full refresh");
|
||||||
getdisplay().setFullWindow(); // Set full update
|
getdisplay().setFullWindow(); // Set full update
|
||||||
if(fastrefresh == "true"){
|
getdisplay().nextPage();
|
||||||
getdisplay().nextPage(); // Full update
|
if(fastrefresh == "false"){
|
||||||
}
|
|
||||||
else{
|
|
||||||
getdisplay().fillScreen(commonData.fgcolor); // Clear display
|
getdisplay().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
|
|
||||||
#else
|
|
||||||
getdisplay().init(115200); // Init for normal displays
|
|
||||||
#endif
|
|
||||||
getdisplay().firstPage(); // Full update
|
|
||||||
getdisplay().nextPage(); // Full update
|
getdisplay().nextPage(); // Full update
|
||||||
// getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||||
// getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
getdisplay().nextPage(); // Full update
|
||||||
// getdisplay().nextPage(); // Partial update
|
|
||||||
// getdisplay().nextPage(); // Partial update
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh display data, default all 1s
|
// Refresh display data, default all 1s
|
||||||
currentPage = pages[pageNumber].page;
|
currentPage = pages[pageNumber].page;
|
||||||
int pagetime = 1000;
|
int pagetime = 1000;
|
||||||
|
@ -971,12 +802,6 @@ void OBP60Task(GwApi *api){
|
||||||
api->getBoatDataValues(boatValues.numValues,boatValues.allBoatValues);
|
api->getBoatDataValues(boatValues.numValues,boatValues.allBoatValues);
|
||||||
api->getStatus(commonData.status);
|
api->getStatus(commonData.status);
|
||||||
|
|
||||||
if (calcTrueWnds) {
|
|
||||||
addTrueWind(api, &boatValues);
|
|
||||||
}
|
|
||||||
// Handle history buffers for TWD, TWS for wind plot page and other usage
|
|
||||||
handleHstryBuf(api, &boatValues, hstryBufList);
|
|
||||||
|
|
||||||
// Clear display
|
// Clear display
|
||||||
// getdisplay().fillRect(0, 0, getdisplay().width(), getdisplay().height(), commonData.bgcolor);
|
// getdisplay().fillRect(0, 0, getdisplay().width(), getdisplay().height(), commonData.bgcolor);
|
||||||
getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||||
|
@ -1018,16 +843,7 @@ void OBP60Task(GwApi *api){
|
||||||
if (pages[pageNumber].description && pages[pageNumber].description->header){
|
if (pages[pageNumber].description && pages[pageNumber].description->header){
|
||||||
displayFooter(commonData);
|
displayFooter(commonData);
|
||||||
}
|
}
|
||||||
int ret = currentPage->displayPage(pages[pageNumber].parameters);
|
currentPage->displayPage(pages[pageNumber].parameters);
|
||||||
if (commonData.alarm.active) {
|
|
||||||
displayAlarm(commonData);
|
|
||||||
}
|
|
||||||
if (ret & PAGE_UPDATE) {
|
|
||||||
getdisplay().nextPage(); // Partial update (fast)
|
|
||||||
}
|
|
||||||
if (ret & PAGE_HIBERNATE) {
|
|
||||||
getdisplay().hibernate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,20 +40,19 @@ lib_deps =
|
||||||
paulstoffregen/OneWire@2.3.8
|
paulstoffregen/OneWire@2.3.8
|
||||||
milesburton/DallasTemperature@3.11.0
|
milesburton/DallasTemperature@3.11.0
|
||||||
signetica/SunRise@2.0.2
|
signetica/SunRise@2.0.2
|
||||||
adafruit/Adafruit FRAM I2C@2.0.3
|
adafruit/Adafruit FRAM I2C@^2.0.3
|
||||||
build_flags=
|
build_flags=
|
||||||
#https://thingpulse.com/usb-settings-for-logging-with-the-esp32-s3-in-platformio/?srsltid=AfmBOopGskbkr4GoeVkNlFaZXe_zXkLceKF6Rn-tmoXABCeAR2vWsdHL
|
#https://thingpulse.com/usb-settings-for-logging-with-the-esp32-s3-in-platformio/?srsltid=AfmBOopGskbkr4GoeVkNlFaZXe_zXkLceKF6Rn-tmoXABCeAR2vWsdHL
|
||||||
# -D CORE_DEBUG_LEVEL=1 #Debug level for CPU core via CDC (serial device)
|
# -D CORE_DEBUG_LEVEL=1 #Debug level for CPU core via CDC (seral device)
|
||||||
# -D TIME=$UNIX_TIME #Set PC time for RTC (only settable via VSC)
|
# -D TIME=$UNIX_TIME #Set PC time for RTC (only settable via VSC)
|
||||||
-D DISABLE_DIAGNOSTIC_OUTPUT #Disable diagnostic output for GxEPD2 lib
|
-D DISABLE_DIAGNOSTIC_OUTPUT #Disable diagnostic output for GxEPD2 lib
|
||||||
-D BOARD_OBP60S3 #Board OBP60 V2.1 with ESP32S3
|
-D BOARD_OBP60S3 #Board OBP60 V2.1 with ESP32S3
|
||||||
# -D HARDWARE_V20 #OBP60 hardware revision V2.0
|
# -D HARDWARE_V20 #OBP60 hardware revision V2.0
|
||||||
-D HARDWARE_V21 #OBP60 hardware revision V2.1
|
-D HARDWARE_V21 #OBP60 hardware revision V2.1
|
||||||
# -D DISPLAY_GDEW042T2 #old E-Ink display from GoodDisplay (Waveshare), R10 0.47 ohm - very good
|
# -D DISPLAY_GDEW042T2 #old E-Ink display from Waveshare, R10 0.47 ohm
|
||||||
-D DISPLAY_GDEY042T81 #new E-Ink display from GoodDisplay (Waveshare), R10 2.2 ohm - good (contast lost by shunshine)
|
-D DISPLAY_GDEY042T81 #new E-Ink display from Waveshare, R10 2.2 ohm
|
||||||
# -D DISPLAY_GYE042A87 #alternativ E-Ink display from Genyo Optical, R10 2.2 ohm - medium
|
# -D DISPLAY_GYE042A87 #alternativ E-Ink display from Genyo Optical, R10 2.2 ohm
|
||||||
# -D DISPLAY_SE0420NQ04 #alternativ E-Ink display from SID Technology, R10 2.2 ohm - bad (burn in effects)
|
# -D DISPLAY_SE0420NQ04 #alternativ E-Ink display from SID Technology, R10 2.2 ohm
|
||||||
# -D DISPLAY_ZJY400300-042CAAMFGN #alternativ E-Ink display from ZZE Technology, R10 2.2 ohm - very good
|
|
||||||
${env.build_flags}
|
${env.build_flags}
|
||||||
#CONFIG_ESP_TASK_WDT_TIMEOUT_S = 10 #Task Watchdog timeout period (seconds) [1...60] 5 default
|
#CONFIG_ESP_TASK_WDT_TIMEOUT_S = 10 #Task Watchdog timeout period (seconds) [1...60] 5 default
|
||||||
upload_port = /dev/ttyACM0 #OBP60 download via USB-C direct
|
upload_port = /dev/ttyACM0 #OBP60 download via USB-C direct
|
||||||
|
@ -92,13 +91,12 @@ lib_deps =
|
||||||
paulstoffregen/OneWire@2.3.8
|
paulstoffregen/OneWire@2.3.8
|
||||||
milesburton/DallasTemperature@3.11.0
|
milesburton/DallasTemperature@3.11.0
|
||||||
signetica/SunRise@2.0.2
|
signetica/SunRise@2.0.2
|
||||||
adafruit/Adafruit FRAM I2C@2.0.3
|
adafruit/Adafruit FRAM I2C@^2.0.3
|
||||||
build_flags=
|
build_flags=
|
||||||
-D DISABLE_DIAGNOSTIC_OUTPUT #Disable diagnostic output for GxEPD2 lib
|
-D DISABLE_DIAGNOSTIC_OUTPUT #Disable diagnostic output for GxEPD2 lib
|
||||||
-D BOARD_OBP40S3 #Board OBP40 with ESP32S3
|
-D BOARD_OBP40S3 #Board OBP40 with ESP32S3
|
||||||
-D HARDWARE_V10 #OBP40 hardware revision V1.0 SKU:DIE07300S V1.1 (CrowPanel 4.2)
|
-D HARDWARE_V10 #OBP40 hardware revision V1.0 SKU:DIE07300S V1.1 (CrowPanel 4.2)
|
||||||
-D DISPLAY_GDEY042T81 #new E-Ink display from Good Display (Waveshare), R10 2.2 ohm - good (contast lost by shunshine)
|
-D DISPLAY_GDEY042T81 #new E-Ink display from Waveshare, R10 2.2 ohm
|
||||||
#-D DISPLAY_ZJY400300-042CAAMFGN #alternativ E-Ink display from ZZE Technology, R10 2.2 ohm - very good
|
|
||||||
#-D LIPO_ACCU_1200 #Hardware extension, LiPo accu 3,7V 1200mAh
|
#-D LIPO_ACCU_1200 #Hardware extension, LiPo accu 3,7V 1200mAh
|
||||||
#-D VOLTAGE_SENSOR #Hardware extension, LiPo voltage sensor with two resistors
|
#-D VOLTAGE_SENSOR #Hardware extension, LiPo voltage sensor with two resistors
|
||||||
${env.build_flags}
|
${env.build_flags}
|
||||||
|
|
Loading…
Reference in New Issue