Compare commits
21 Commits
e72ece8452
...
a2c1c1042d
Author | SHA1 | Date |
---|---|---|
![]() |
a2c1c1042d | |
![]() |
77872fea4a | |
![]() |
8a069b9445 | |
![]() |
b3a9b9990f | |
![]() |
dc8b9e48d7 | |
|
c5a1244519 | |
|
99c3470a22 | |
|
f5cf292804 | |
|
77c05de4fc | |
|
1bac5d8b16 | |
|
c7eafbf9b8 | |
![]() |
4b5aa7ff4b | |
![]() |
ebf6e62389 | |
![]() |
29706df6cd | |
![]() |
d6e3c7ad48 | |
![]() |
02712263d3 | |
![]() |
0c4fce0e25 | |
![]() |
4e6d52d197 | |
![]() |
f9cf73ae04 | |
![]() |
bf59cfbae8 | |
![]() |
214c10ff93 |
|
@ -520,9 +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)
|
||||||
|
|
|
@ -6,12 +6,13 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
CalibrationDataList calibrationData;
|
CalibrationDataList calibrationData;
|
||||||
|
std::unordered_map<std::string, TypeCalibData> CalibrationDataList::calibMap; // list of calibration data instances
|
||||||
|
|
||||||
void CalibrationDataList::readConfig(GwConfigHandler* config, GwLog* logger)
|
void CalibrationDataList::readConfig(GwConfigHandler* config, GwLog* logger)
|
||||||
// Initial load of calibration data into internal list
|
// Initial load of calibration data into internal list
|
||||||
// This method is called once at init phase of <OBP60task> to read the configuration values
|
// This method is called once at init phase of <obp60task> to read the configuration values
|
||||||
{
|
{
|
||||||
String instance;
|
std::string instance;
|
||||||
double offset;
|
double offset;
|
||||||
double slope;
|
double slope;
|
||||||
double smooth;
|
double smooth;
|
||||||
|
@ -29,21 +30,21 @@ void CalibrationDataList::readConfig(GwConfigHandler* config, GwLog* logger)
|
||||||
String tempFormat = config->getString(config->tempFormat); // [K|C|F]
|
String tempFormat = config->getString(config->tempFormat); // [K|C|F]
|
||||||
|
|
||||||
// Read calibration settings for data instances
|
// Read calibration settings for data instances
|
||||||
for (int i = 0; i < maxCalibrationData; i++) {
|
for (int i = 0; i < MAX_CALIBRATION_DATA; i++) {
|
||||||
calInstance = "calInstance" + String(i + 1);
|
calInstance = "calInstance" + String(i + 1);
|
||||||
calOffset = "calOffset" + String(i + 1);
|
calOffset = "calOffset" + String(i + 1);
|
||||||
calSlope = "calSlope" + String(i + 1);
|
calSlope = "calSlope" + String(i + 1);
|
||||||
calSmooth = "calSmooth" + String(i + 1);
|
calSmooth = "calSmooth" + String(i + 1);
|
||||||
calibrationData.list[i] = { "---", 0.0f, 1.0f, 1, 0.0f, false };
|
|
||||||
|
|
||||||
instance = config->getString(calInstance, "---");
|
instance = std::string(config->getString(calInstance, "---").c_str());
|
||||||
if (instance == "---") {
|
if (instance == "---") {
|
||||||
LOG_DEBUG(GwLog::LOG, "no calibration data for instance no. %d", i + 1);
|
LOG_DEBUG(GwLog::LOG, "no calibration data for instance no. %d", i + 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
calibMap[instance] = { 0.0f, 1.0f, 1.0f, 0.0f, false };
|
||||||
offset = (config->getString(calOffset, "")).toFloat();
|
offset = (config->getString(calOffset, "")).toFloat();
|
||||||
slope = (config->getString(calSlope, "")).toFloat();
|
slope = (config->getString(calSlope, "")).toFloat();
|
||||||
smooth = (config->getString(calSmooth, "")).toInt();
|
smooth = (config->getString(calSmooth, "")).toInt(); // user input is int; further math is done with double
|
||||||
|
|
||||||
// Convert calibration values to internal standard formats
|
// Convert calibration values to internal standard formats
|
||||||
if (instance == "AWS" || instance == "TWS") {
|
if (instance == "AWS" || instance == "TWS") {
|
||||||
|
@ -54,10 +55,10 @@ void CalibrationDataList::readConfig(GwConfigHandler* config, GwLog* logger)
|
||||||
} else if (windspeedFormat == "kn") {
|
} else if (windspeedFormat == "kn") {
|
||||||
offset /= 1.94384; // Convert kn to m/s
|
offset /= 1.94384; // Convert kn to m/s
|
||||||
} else if (windspeedFormat == "bft") {
|
} else if (windspeedFormat == "bft") {
|
||||||
offset *= 0.5; // Convert Bft to m/s (approx) -> to be improved
|
offset *= 2 + (offset / 2); // Convert Bft to m/s (approx) -> to be improved
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (instance == "AWA" || instance == "TWA" || instance == "TWD" || instance == "HDM" || instance == "PRPOS" || instance == "RPOS") {
|
} else if (instance == "AWA" || instance == "COG" || instance == "TWA" || instance == "TWD" || instance == "HDM" || instance == "PRPOS" || instance == "RPOS") {
|
||||||
offset *= M_PI / 180; // Convert deg to rad
|
offset *= M_PI / 180; // Convert deg to rad
|
||||||
|
|
||||||
} else if (instance == "DBT") {
|
} else if (instance == "DBT") {
|
||||||
|
@ -67,7 +68,7 @@ void CalibrationDataList::readConfig(GwConfigHandler* config, GwLog* logger)
|
||||||
offset /= 3.28084; // Convert ft to m
|
offset /= 3.28084; // Convert ft to m
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (instance == "STW") {
|
} else if (instance == "SOG" || instance == "STW") {
|
||||||
if (speedFormat == "m/s") {
|
if (speedFormat == "m/s") {
|
||||||
// No conversion needed
|
// No conversion needed
|
||||||
} else if (speedFormat == "km/h") {
|
} else if (speedFormat == "km/h") {
|
||||||
|
@ -92,112 +93,100 @@ void CalibrationDataList::readConfig(GwConfigHandler* config, GwLog* logger)
|
||||||
if (smooth > 10) {
|
if (smooth > 10) {
|
||||||
smooth = 10;
|
smooth = 10;
|
||||||
}
|
}
|
||||||
// calibrationData.list[i].smooth = 1 - (smooth / 10.0); // smooth factor is between 0 and 1
|
|
||||||
smooth = 0.3 + ((smooth - 0.01) * (0.95 - 0.3) / (10 - 0.01));
|
smooth = 0.3 + ((smooth - 0.01) * (0.95 - 0.3) / (10 - 0.01));
|
||||||
}
|
}
|
||||||
smooth = 1 - smooth;
|
smooth = 1 - smooth;
|
||||||
|
|
||||||
calibrationData.list[i].instance = instance;
|
calibMap[instance].offset = offset;
|
||||||
calibrationData.list[i].offset = offset;
|
calibMap[instance].slope = slope;
|
||||||
calibrationData.list[i].slope = slope;
|
calibMap[instance].smooth = smooth;
|
||||||
calibrationData.list[i].smooth = smooth;
|
calibMap[instance].isCalibrated = false;
|
||||||
calibrationData.list[i].isCalibrated = false;
|
LOG_DEBUG(GwLog::LOG, "stored calibration data: %s, offset: %f, slope: %f, smoothing: %f", instance.c_str(),
|
||||||
LOG_DEBUG(GwLog::LOG, "stored calibration data: %s, offset: %f, slope: %f, smoothing: %f", calibrationData.list[i].instance.c_str(),
|
calibMap[instance].offset, calibMap[instance].slope, calibMap[instance].smooth);
|
||||||
calibrationData.list[i].offset, calibrationData.list[i].slope, calibrationData.list[i].smooth);
|
|
||||||
}
|
}
|
||||||
LOG_DEBUG(GwLog::LOG, "all calibration data read");
|
LOG_DEBUG(GwLog::LOG, "all calibration data read");
|
||||||
}
|
}
|
||||||
|
|
||||||
int CalibrationDataList::getInstanceListNo(String instance)
|
void CalibrationDataList::calibrateInstance(GwApi::BoatValue* boatDataValue, GwLog* logger)
|
||||||
// Method to get the index of the requested instance in the list
|
|
||||||
{
|
|
||||||
// Check if instance is in the list
|
|
||||||
for (int i = 0; i < maxCalibrationData; i++) {
|
|
||||||
if (calibrationData.list[i].instance == instance) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1; // instance not found
|
|
||||||
}
|
|
||||||
|
|
||||||
/* void CalibrationDataList::updateBoatDataValidity(String instance)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < maxCalibrationData; i++) {
|
|
||||||
if (calibrationData.list[i].instance == instance) {
|
|
||||||
// test for boat data value validity - to be implemented
|
|
||||||
calibrationData.list[i].isValid = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
|
|
||||||
void CalibrationDataList::calibrateInstance(String instance, GwApi::BoatValue* boatDataValue, GwLog* logger)
|
|
||||||
// Method to calibrate the boat data value
|
// Method to calibrate the boat data value
|
||||||
{
|
{
|
||||||
|
std::string instance = boatDataValue->getName().c_str();
|
||||||
double offset = 0;
|
double offset = 0;
|
||||||
double slope = 1.0;
|
double slope = 1.0;
|
||||||
double dataValue = 0;
|
double dataValue = 0;
|
||||||
|
std::string format = "";
|
||||||
|
|
||||||
int listNo = getInstanceListNo(instance);
|
if (calibMap.find(instance) == calibMap.end()) {
|
||||||
if (listNo < 0) {
|
|
||||||
LOG_DEBUG(GwLog::DEBUG, "BoatDataCalibration: %s not found in calibration data list", instance.c_str());
|
LOG_DEBUG(GwLog::DEBUG, "BoatDataCalibration: %s not found in calibration data list", instance.c_str());
|
||||||
return;
|
return;
|
||||||
|
} else if (!boatDataValue->valid) { // no valid boat data value, so we don't want to apply calibration data
|
||||||
|
calibMap[instance].isCalibrated = false;
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
offset = calibrationData.list[listNo].offset;
|
offset = calibMap[instance].offset;
|
||||||
slope = calibrationData.list[listNo].slope;
|
slope = calibMap[instance].slope;
|
||||||
|
dataValue = boatDataValue->value;
|
||||||
|
format = boatDataValue->getFormat().c_str();
|
||||||
|
LOG_DEBUG(GwLog::DEBUG, "BoatDataCalibration: %s: value: %f, format: %s", instance.c_str(), dataValue, format.c_str());
|
||||||
|
|
||||||
if (!boatDataValue->valid) { // no valid boat data value, so we don't want to apply calibration data
|
if (format == "formatWind") { // instance is of type angle
|
||||||
return;
|
dataValue = (dataValue * slope) + offset;
|
||||||
} else {
|
dataValue = fmod(dataValue, 2 * M_PI);
|
||||||
dataValue = boatDataValue->value;
|
if (dataValue > (M_PI)) {
|
||||||
LOG_DEBUG(GwLog::DEBUG, "BoatDataCalibration: %s: value: %f, format: %s", boatDataValue->getName().c_str(), boatDataValue->value, boatDataValue->getFormat().c_str());
|
dataValue -= (2 * M_PI);
|
||||||
|
} else if (dataValue < (M_PI * -1)) {
|
||||||
if (boatDataValue->getFormat() == "formatWind") { // instance is of type angle
|
dataValue += (2 * M_PI);
|
||||||
dataValue = (dataValue * slope) + offset;
|
|
||||||
dataValue = fmod(dataValue, 2 * M_PI);
|
|
||||||
if (dataValue > (M_PI)) {
|
|
||||||
dataValue -= (2 * M_PI);
|
|
||||||
} else if (dataValue < (M_PI * -1)) {
|
|
||||||
dataValue += (2 * M_PI);
|
|
||||||
}
|
|
||||||
} else if (boatDataValue->getFormat() == "formatCourse") { // instance is of type direction
|
|
||||||
dataValue = (dataValue * slope) + offset;
|
|
||||||
dataValue = fmod(dataValue, 2 * M_PI);
|
|
||||||
if (dataValue < 0) {
|
|
||||||
dataValue += (2 * M_PI);
|
|
||||||
}
|
|
||||||
} else if (boatDataValue->getFormat() == "kelvinToC") { // instance is of type temperature
|
|
||||||
dataValue = ((dataValue - 273.15) * slope) + offset + 273.15;
|
|
||||||
} else {
|
|
||||||
dataValue = (dataValue * slope) + offset;
|
|
||||||
}
|
}
|
||||||
|
} else if (format == "formatCourse") { // instance is of type direction
|
||||||
|
dataValue = (dataValue * slope) + offset;
|
||||||
|
dataValue = fmod(dataValue, 2 * M_PI);
|
||||||
|
if (dataValue < 0) {
|
||||||
|
dataValue += (2 * M_PI);
|
||||||
|
}
|
||||||
|
} else if (format == "kelvinToC") { // instance is of type temperature
|
||||||
|
dataValue = ((dataValue - 273.15) * slope) + offset + 273.15;
|
||||||
|
} else {
|
||||||
|
|
||||||
calibrationData.smoothInstance(instance, dataValue, logger); // smooth the boat data value
|
dataValue = (dataValue * slope) + offset;
|
||||||
calibrationData.list[listNo].value = dataValue;
|
|
||||||
calibrationData.list[listNo].isCalibrated = true;
|
|
||||||
boatDataValue->value = dataValue;
|
|
||||||
LOG_DEBUG(GwLog::DEBUG, "BoatDataCalibration: %s: Offset: %f, Slope: %f, Result: %f", instance.c_str(), offset, slope, boatDataValue->value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
calibMap[instance].isCalibrated = true;
|
||||||
|
boatDataValue->value = dataValue;
|
||||||
|
|
||||||
|
calibrationData.smoothInstance(boatDataValue, logger); // smooth the boat data value
|
||||||
|
calibMap[instance].value = boatDataValue->value; // store the calibrated + smoothed value in the list
|
||||||
|
|
||||||
|
LOG_DEBUG(GwLog::DEBUG, "BoatDataCalibration: %s: Offset: %f, Slope: %f, Result: %f", instance.c_str(), offset, slope, calibMap[instance].value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CalibrationDataList::smoothInstance(String instance, double& dataValue, GwLog* logger)
|
void CalibrationDataList::smoothInstance(GwApi::BoatValue* boatDataValue, GwLog* logger)
|
||||||
// Method to smoothen the boat data value
|
// Method to smoothen the boat data value
|
||||||
{
|
{
|
||||||
// array for last values of smoothed boat data values
|
static std::unordered_map<std::string, double> lastValue; // array for last values of smoothed boat data values
|
||||||
static std::unordered_map<std::string, double> lastValue;
|
|
||||||
|
|
||||||
|
std::string instance = boatDataValue->getName().c_str();
|
||||||
double oldValue = 0;
|
double oldValue = 0;
|
||||||
double smoothFactor = calibrationData.list[getInstanceListNo(instance)].smooth;
|
double dataValue = boatDataValue->value;
|
||||||
|
double smoothFactor = 0;
|
||||||
|
|
||||||
if (lastValue.find(instance.c_str()) != lastValue.end()) {
|
if (!boatDataValue->valid) { // no valid boat data value, so we don't want to smoothen value
|
||||||
oldValue = lastValue[instance.c_str()];
|
return;
|
||||||
|
} else if (calibMap.find(instance) == calibMap.end()) {
|
||||||
|
LOG_DEBUG(GwLog::DEBUG, "BoatDataCalibration: smooth factor for %s not found in calibration data list", instance.c_str());
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
smoothFactor = calibMap[instance].smooth;
|
||||||
|
|
||||||
dataValue = oldValue + (smoothFactor * (dataValue - oldValue)); // exponential smoothing algorithm
|
if (lastValue.find(instance) != lastValue.end()) {
|
||||||
|
oldValue = lastValue[instance];
|
||||||
|
dataValue = oldValue + (smoothFactor * (dataValue - oldValue)); // exponential smoothing algorithm
|
||||||
|
}
|
||||||
|
lastValue[instance] = dataValue; // store the new value for next cycle; first time, store only the current value and return
|
||||||
|
boatDataValue->value = dataValue; // set the smoothed value to the boat data value
|
||||||
|
|
||||||
|
LOG_DEBUG(GwLog::DEBUG, "BoatDataCalibration: %s: Smoothing factor: %f, Smoothed value: %f", instance.c_str(), smoothFactor, dataValue);
|
||||||
}
|
}
|
||||||
lastValue[instance.c_str()] = dataValue; // store the new value for next cycle; first time, store only the current value and return
|
|
||||||
|
|
||||||
LOG_DEBUG(GwLog::DEBUG, "BoatDataCalibration: %s: Smoothing factor: %f, Smoothed value: %f", instance.c_str(), smoothFactor, dataValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -4,27 +4,26 @@
|
||||||
#define _BOATDATACALIBRATION_H
|
#define _BOATDATACALIBRATION_H
|
||||||
|
|
||||||
#include "Pagedata.h"
|
#include "Pagedata.h"
|
||||||
#include "WString.h"
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#define MAX_CALIBRATION_DATA 3 // maximum number of calibration data instances
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
String instance; // data type/instance to be calibrated
|
|
||||||
double offset; // calibration offset
|
double offset; // calibration offset
|
||||||
double slope; // calibration slope
|
double slope; // calibration slope
|
||||||
double smooth; // smoothing factor
|
double smooth; // smoothing factor
|
||||||
double value; // calibrated data value
|
double value; // calibrated data value
|
||||||
bool isCalibrated; // is data instance value calibrated?
|
bool isCalibrated; // is data instance value calibrated?
|
||||||
} CalibData;
|
} TypeCalibData;
|
||||||
|
|
||||||
const int maxCalibrationData = 3; // maximum number of calibration data instances
|
|
||||||
|
|
||||||
class CalibrationDataList {
|
class CalibrationDataList {
|
||||||
public:
|
public:
|
||||||
CalibData list[maxCalibrationData]; // list of calibration data instances
|
static std::unordered_map<std::string, TypeCalibData> calibMap; // list of calibration data instances
|
||||||
|
|
||||||
static void readConfig(GwConfigHandler* config, GwLog* logger);
|
void readConfig(GwConfigHandler* config, GwLog* logger);
|
||||||
static int getInstanceListNo(String instance);
|
void calibrateInstance(GwApi::BoatValue* boatDataValue, GwLog* logger);
|
||||||
static void calibrateInstance(String instance, GwApi::BoatValue* boatDataValue, GwLog* logger);
|
void smoothInstance(GwApi::BoatValue* boatDataValue, GwLog* logger);
|
||||||
void smoothInstance(String instance, double &dataValue, GwLog* logger);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,262 @@
|
||||||
|
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||||
|
|
||||||
|
#include "Pagedata.h"
|
||||||
|
#include "OBP60Extensions.h"
|
||||||
|
|
||||||
|
// these constants have to match the declaration below in :
|
||||||
|
// PageDescription registerPageCompass(
|
||||||
|
// {"COG","HDT", "HDM"}, // Bus values we need in the page
|
||||||
|
const int HowManyValues = 6;
|
||||||
|
|
||||||
|
const int AverageValues = 4;
|
||||||
|
|
||||||
|
const int ShowHDM = 0;
|
||||||
|
const int ShowHDT = 1;
|
||||||
|
const int ShowCOG = 2;
|
||||||
|
const int ShowSTW = 3;
|
||||||
|
const int ShowSOG = 4;
|
||||||
|
const int ShowDBS = 5;
|
||||||
|
|
||||||
|
const int Compass_X0 = 200; // center point of compass band
|
||||||
|
const int Compass_Y0 = 220; // position of compass lines
|
||||||
|
const int Compass_LineLength = 22; // length of compass lines
|
||||||
|
const float Compass_LineDelta = 8.0; // compass band: 1deg = 5 Pixels, 10deg = 50 Pixels
|
||||||
|
|
||||||
|
class PageCompass : public Page
|
||||||
|
{
|
||||||
|
int WhichDataCompass = ShowHDM;
|
||||||
|
int WhichDataDisplay = ShowHDM;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PageCompass(CommonData &common){
|
||||||
|
commonData = &common;
|
||||||
|
common.logger->logDebug(GwLog::LOG,"Instantiate PageCompass");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setupKeys(){
|
||||||
|
Page::setupKeys();
|
||||||
|
commonData->keydata[0].label = "CMP";
|
||||||
|
commonData->keydata[1].label = "SRC";
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int handleKey(int key){
|
||||||
|
// Code for keylock
|
||||||
|
|
||||||
|
if ( key == 1 ) {
|
||||||
|
WhichDataCompass += 1;
|
||||||
|
if ( WhichDataCompass > ShowCOG)
|
||||||
|
WhichDataCompass = ShowHDM;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ( key == 2 ) {
|
||||||
|
WhichDataDisplay += 1;
|
||||||
|
if ( WhichDataDisplay > ShowDBS)
|
||||||
|
WhichDataDisplay = ShowHDM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(key == 11){
|
||||||
|
commonData->keylock = !commonData->keylock;
|
||||||
|
return 0; // Commit the key
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void displayPage(PageData &pageData){
|
||||||
|
GwConfigHandler *config = commonData->config;
|
||||||
|
GwLog *logger = commonData->logger;
|
||||||
|
|
||||||
|
|
||||||
|
// Old values for hold function
|
||||||
|
static String OldDataText[HowManyValues] = {"", "", "","", "", ""};
|
||||||
|
static String OldDataUnits[HowManyValues] = {"", "", "","", "", ""};
|
||||||
|
|
||||||
|
// Get config data
|
||||||
|
String lengthformat = config->getString(config->lengthFormat);
|
||||||
|
// bool simulation = config->getBool(config->useSimuData);
|
||||||
|
bool holdvalues = config->getBool(config->holdvalues);
|
||||||
|
String flashLED = config->getString(config->flashLED);
|
||||||
|
String backlightMode = config->getString(config->backlight);
|
||||||
|
|
||||||
|
GwApi::BoatValue *bvalue;
|
||||||
|
String DataName[HowManyValues];
|
||||||
|
double DataValue[HowManyValues];
|
||||||
|
bool DataValid[HowManyValues];
|
||||||
|
String DataText[HowManyValues];
|
||||||
|
String DataUnits[HowManyValues];
|
||||||
|
String DataFormat[HowManyValues];
|
||||||
|
FormatedData TheFormattedData;
|
||||||
|
|
||||||
|
for (int i = 0; i < HowManyValues; i++){
|
||||||
|
bvalue = pageData.values[i];
|
||||||
|
TheFormattedData = formatValue(bvalue, *commonData);
|
||||||
|
DataName[i] = xdrDelete(bvalue->getName());
|
||||||
|
DataName[i] = DataName[i].substring(0, 6); // String length limit for value name
|
||||||
|
DataUnits[i] = formatValue(bvalue, *commonData).unit;
|
||||||
|
DataText[i] = TheFormattedData.svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
|
DataValue[i] = TheFormattedData.value; // Value as double in SI unit
|
||||||
|
DataValid[i] = bvalue->valid;
|
||||||
|
DataFormat[i] = bvalue->getFormat(); // Unit of value
|
||||||
|
LOG_DEBUG(GwLog::LOG,"Drawing at PageCompass: %d %s %f %s %s", i, DataName[i], DataValue[i], DataFormat[i], DataText[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optical warning by limit violation (unused)
|
||||||
|
if(String(flashLED) == "Limit Violation"){
|
||||||
|
setBlinkingLED(false);
|
||||||
|
setFlashLED(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bvalue == NULL) return;
|
||||||
|
|
||||||
|
//***********************************************************
|
||||||
|
|
||||||
|
// Set display in partial refresh mode
|
||||||
|
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||||
|
getdisplay().setTextColor(commonData->fgcolor);
|
||||||
|
|
||||||
|
// Horizontal line 3 pix top & bottom
|
||||||
|
// print Data on top half
|
||||||
|
getdisplay().fillRect(0, 23, 400, 3, commonData->fgcolor);
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold20pt7b);
|
||||||
|
getdisplay().setCursor(10, 70);
|
||||||
|
getdisplay().print(DataName[WhichDataDisplay]); // Page name
|
||||||
|
// Show unit
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold12pt7b);
|
||||||
|
getdisplay().setCursor(10, 120);
|
||||||
|
getdisplay().print(DataUnits[WhichDataDisplay]);
|
||||||
|
getdisplay().setCursor(200, 120);
|
||||||
|
getdisplay().setFont(&DSEG7Classic_BoldItalic42pt7b);
|
||||||
|
|
||||||
|
if(holdvalues == false){
|
||||||
|
getdisplay().print(DataText[WhichDataDisplay]); // Real value as formated string
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
getdisplay().print(OldDataText[WhichDataDisplay]); // Old value as formated string
|
||||||
|
}
|
||||||
|
if(DataValid[WhichDataDisplay] == true){
|
||||||
|
OldDataText[WhichDataDisplay] = DataText[WhichDataDisplay]; // Save the old value
|
||||||
|
OldDataUnits[WhichDataDisplay] = DataUnits[WhichDataDisplay]; // Save the old unit
|
||||||
|
}
|
||||||
|
// now draw compass band
|
||||||
|
// get the data
|
||||||
|
double TheAngle = DataValue[WhichDataCompass];
|
||||||
|
static double AvgAngle = 0;
|
||||||
|
AvgAngle = ( AvgAngle * AverageValues + TheAngle ) / (AverageValues + 1 );
|
||||||
|
|
||||||
|
int TheTrend = round( ( TheAngle - AvgAngle) * 180.0 / M_PI );
|
||||||
|
|
||||||
|
static const int bsize = 30;
|
||||||
|
char buffer[bsize+1];
|
||||||
|
buffer[0]=0;
|
||||||
|
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold16pt7b);
|
||||||
|
getdisplay().setCursor(10, Compass_Y0-60);
|
||||||
|
getdisplay().print(DataName[WhichDataCompass]); // Page name
|
||||||
|
|
||||||
|
|
||||||
|
// draw compass base line and pointer
|
||||||
|
getdisplay().fillRect(0, Compass_Y0, 400, 3, commonData->fgcolor);
|
||||||
|
getdisplay().fillTriangle(Compass_X0,Compass_Y0-40,Compass_X0-10,Compass_Y0-80,Compass_X0+10,Compass_Y0-80,commonData->fgcolor);
|
||||||
|
// draw trendlines
|
||||||
|
for ( int i = 1; i < abs(TheTrend) / 2; i++){
|
||||||
|
int x1;
|
||||||
|
if ( TheTrend < 0 )
|
||||||
|
x1 = Compass_X0 + 20 * i;
|
||||||
|
else
|
||||||
|
x1 = Compass_X0 - 20 * ( i + 1 );
|
||||||
|
|
||||||
|
getdisplay().fillRect(x1, Compass_Y0 -60, 10, 6, commonData->fgcolor);
|
||||||
|
}
|
||||||
|
// central line + satellite lines
|
||||||
|
double NextSector = round(TheAngle / ( M_PI / 9 )) * ( M_PI / 9 ); // get the next 20degree value
|
||||||
|
double Offset = - ( NextSector - TheAngle); // offest of the center line compared to TheAngle in Radian
|
||||||
|
|
||||||
|
int Delta_X = int ( Offset * 180.0 / M_PI * Compass_LineDelta );
|
||||||
|
for ( int i = 0; i <=4; i++ )
|
||||||
|
{
|
||||||
|
int x0;
|
||||||
|
x0 = Compass_X0 + Delta_X + 2 * i * 5 * Compass_LineDelta;
|
||||||
|
getdisplay().fillRect(x0-1, Compass_Y0 - 2 * Compass_LineLength,3, 2 * Compass_LineLength, commonData->fgcolor);
|
||||||
|
x0 = Compass_X0 + Delta_X + ( 2 * i + 1 ) * 5 * Compass_LineDelta;
|
||||||
|
getdisplay().fillRect(x0-1, Compass_Y0 - Compass_LineLength,3, Compass_LineLength, commonData->fgcolor);
|
||||||
|
|
||||||
|
x0 = Compass_X0 + Delta_X - 2 * i * 5 * Compass_LineDelta;
|
||||||
|
getdisplay().fillRect(x0-1, Compass_Y0 - 2 * Compass_LineLength,3, 2 * Compass_LineLength, commonData->fgcolor);
|
||||||
|
x0 = Compass_X0 + Delta_X - ( 2 * i + 1 ) * 5 * Compass_LineDelta;
|
||||||
|
getdisplay().fillRect(x0-1, Compass_Y0 - Compass_LineLength,3, Compass_LineLength, commonData->fgcolor);
|
||||||
|
}
|
||||||
|
|
||||||
|
getdisplay().fillRect(0, Compass_Y0, 400, 3, commonData->fgcolor);
|
||||||
|
// add the numbers to the compass band
|
||||||
|
int x0;
|
||||||
|
float AngleToDisplay = NextSector * 180.0 / M_PI;
|
||||||
|
|
||||||
|
x0 = Compass_X0 + Delta_X;
|
||||||
|
getdisplay().setFont(&DSEG7Classic_BoldItalic16pt7b);
|
||||||
|
|
||||||
|
do {
|
||||||
|
getdisplay().setCursor(x0 - 40, Compass_Y0 + 40);
|
||||||
|
snprintf(buffer,bsize,"%03.0f", AngleToDisplay);
|
||||||
|
getdisplay().print(buffer);
|
||||||
|
AngleToDisplay += 20;
|
||||||
|
if ( AngleToDisplay >= 360.0 )
|
||||||
|
AngleToDisplay -= 360.0;
|
||||||
|
x0 -= 4 * 5 * Compass_LineDelta;
|
||||||
|
} while ( x0 >= 0 - 60 );
|
||||||
|
|
||||||
|
AngleToDisplay = NextSector * 180.0 / M_PI - 20;
|
||||||
|
if ( AngleToDisplay < 0 )
|
||||||
|
AngleToDisplay += 360.0;
|
||||||
|
|
||||||
|
x0 = Compass_X0 + Delta_X + 4 * 5 * Compass_LineDelta;
|
||||||
|
do {
|
||||||
|
getdisplay().setCursor(x0 - 40, Compass_Y0 + 40);
|
||||||
|
snprintf(buffer,bsize,"%03.0f", AngleToDisplay);
|
||||||
|
// quick and dirty way to prevent wrapping text in next line
|
||||||
|
if ( ( x0 - 40 ) > 380 )
|
||||||
|
buffer[0] = 0;
|
||||||
|
else if ( ( x0 - 40 ) > 355 )
|
||||||
|
buffer[1] = 0;
|
||||||
|
else if ( ( x0 - 40 ) > 325 )
|
||||||
|
buffer[2] = 0;
|
||||||
|
|
||||||
|
getdisplay().print(buffer);
|
||||||
|
|
||||||
|
AngleToDisplay -= 20;
|
||||||
|
if ( AngleToDisplay < 0 )
|
||||||
|
AngleToDisplay += 360.0;
|
||||||
|
x0 += 4 * 5 * Compass_LineDelta;
|
||||||
|
} while (x0 < ( 400 - 20 -40 ) );
|
||||||
|
|
||||||
|
// static int x_test = 320;
|
||||||
|
// x_test += 2;
|
||||||
|
|
||||||
|
// snprintf(buffer,bsize,"%03d", x_test);
|
||||||
|
// getdisplay().setCursor(x_test, Compass_Y0 - 60);
|
||||||
|
// getdisplay().print(buffer);
|
||||||
|
// if ( x_test > 390)
|
||||||
|
// x_test = 320;
|
||||||
|
|
||||||
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
static Page *createPage(CommonData &common){
|
||||||
|
return new PageCompass(common);
|
||||||
|
}/**
|
||||||
|
* with the code below we make this page known to the PageTask
|
||||||
|
* we give it a type (name) that can be selected in the config
|
||||||
|
* we define which function is to be called
|
||||||
|
* and we provide the number of user parameters we expect
|
||||||
|
* this will be number of BoatValue pointers in pageData.values
|
||||||
|
*/
|
||||||
|
PageDescription registerPageCompass(
|
||||||
|
"Compass", // Page name
|
||||||
|
createPage, // Action
|
||||||
|
0, // Number of bus values depends on selection in Web configuration
|
||||||
|
{"HDM","HDT", "COG", "STW", "SOG", "DBS"}, // Bus values we need in the page
|
||||||
|
true // Show display header on/off
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
|
@ -46,9 +46,9 @@ class PageFourValues : public Page
|
||||||
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
|
||||||
String name1 = xdrDelete(bvalue1->getName()); // Value name
|
String name1 = xdrDelete(bvalue1->getName()); // Value name
|
||||||
name1 = name1.substring(0, 6); // String length limit for value name
|
name1 = name1.substring(0, 6); // String length limit for value name
|
||||||
|
calibrationData.calibrateInstance(bvalue1, logger); // Check if boat data value is to be calibrated
|
||||||
double value1 = bvalue1->value; // Value as double in SI unit
|
double value1 = bvalue1->value; // Value as double in SI unit
|
||||||
bool valid1 = bvalue1->valid; // Valid information
|
bool valid1 = bvalue1->valid; // Valid information
|
||||||
calibrationData.calibrateInstance(name1, bvalue1, logger); // Check if boat data value is to be calibrated
|
|
||||||
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
|
||||||
|
|
||||||
|
@ -56,9 +56,9 @@ class PageFourValues : public Page
|
||||||
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list (only one value by PageOneValue)
|
||||||
String name2 = xdrDelete(bvalue2->getName()); // Value name
|
String name2 = xdrDelete(bvalue2->getName()); // Value name
|
||||||
name2 = name2.substring(0, 6); // String length limit for value name
|
name2 = name2.substring(0, 6); // String length limit for value name
|
||||||
|
calibrationData.calibrateInstance(bvalue2, logger); // Check if boat data value is to be calibrated
|
||||||
double value2 = bvalue2->value; // Value as double in SI unit
|
double value2 = bvalue2->value; // Value as double in SI unit
|
||||||
bool valid2 = bvalue2->valid; // Valid information
|
bool valid2 = bvalue2->valid; // Valid information
|
||||||
calibrationData.calibrateInstance(name2, bvalue2, logger); // Check if boat data value is to be calibrated
|
|
||||||
String svalue2 = formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue2 = formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
String unit2 = formatValue(bvalue2, *commonData).unit; // Unit of value
|
String unit2 = formatValue(bvalue2, *commonData).unit; // Unit of value
|
||||||
|
|
||||||
|
@ -66,9 +66,9 @@ class PageFourValues : public Page
|
||||||
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Second element in list (only one value by PageOneValue)
|
||||||
String name3 = xdrDelete(bvalue3->getName()); // Value name
|
String name3 = xdrDelete(bvalue3->getName()); // Value name
|
||||||
name3 = name3.substring(0, 6); // String length limit for value name
|
name3 = name3.substring(0, 6); // String length limit for value name
|
||||||
|
calibrationData.calibrateInstance(bvalue3, logger); // Check if boat data value is to be calibrated
|
||||||
double value3 = bvalue3->value; // Value as double in SI unit
|
double value3 = bvalue3->value; // Value as double in SI unit
|
||||||
bool valid3 = bvalue3->valid; // Valid information
|
bool valid3 = bvalue3->valid; // Valid information
|
||||||
calibrationData.calibrateInstance(name3, bvalue3, logger); // Check if boat data value is to be calibrated
|
|
||||||
String svalue3 = formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue3 = formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
String unit3 = formatValue(bvalue3, *commonData).unit; // Unit of value
|
String unit3 = formatValue(bvalue3, *commonData).unit; // Unit of value
|
||||||
|
|
||||||
|
@ -76,9 +76,9 @@ class PageFourValues : public Page
|
||||||
GwApi::BoatValue *bvalue4 = pageData.values[3]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue4 = pageData.values[3]; // Second element in list (only one value by PageOneValue)
|
||||||
String name4 = xdrDelete(bvalue4->getName()); // Value name
|
String name4 = xdrDelete(bvalue4->getName()); // Value name
|
||||||
name4 = name4.substring(0, 6); // String length limit for value name
|
name4 = name4.substring(0, 6); // String length limit for value name
|
||||||
|
calibrationData.calibrateInstance(bvalue4, logger); // Check if boat data value is to be calibrated
|
||||||
double value4 = bvalue4->value; // Value as double in SI unit
|
double value4 = bvalue4->value; // Value as double in SI unit
|
||||||
bool valid4 = bvalue4->valid; // Valid information
|
bool valid4 = bvalue4->valid; // Valid information
|
||||||
calibrationData.calibrateInstance(name4, bvalue4, logger); // Check if boat data value is to be calibrated
|
|
||||||
String svalue4 = formatValue(bvalue4, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue4 = formatValue(bvalue4, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
String unit4 = formatValue(bvalue4, *commonData).unit; // Unit of value
|
String unit4 = formatValue(bvalue4, *commonData).unit; // Unit of value
|
||||||
|
|
||||||
|
|
|
@ -46,9 +46,9 @@ class PageFourValues2 : public Page
|
||||||
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
|
||||||
String name1 = xdrDelete(bvalue1->getName()); // Value name
|
String name1 = xdrDelete(bvalue1->getName()); // Value name
|
||||||
name1 = name1.substring(0, 6); // String length limit for value name
|
name1 = name1.substring(0, 6); // String length limit for value name
|
||||||
|
calibrationData.calibrateInstance(bvalue1, logger); // Check if boat data value is to be calibrated
|
||||||
double value1 = bvalue1->value; // Value as double in SI unit
|
double value1 = bvalue1->value; // Value as double in SI unit
|
||||||
bool valid1 = bvalue1->valid; // Valid information
|
bool valid1 = bvalue1->valid; // Valid information
|
||||||
calibrationData.calibrateInstance(name1, bvalue1, logger); // Check if boat data value is to be calibrated
|
|
||||||
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
|
||||||
|
|
||||||
|
@ -56,9 +56,9 @@ class PageFourValues2 : public Page
|
||||||
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list (only one value by PageOneValue)
|
||||||
String name2 = xdrDelete(bvalue2->getName()); // Value name
|
String name2 = xdrDelete(bvalue2->getName()); // Value name
|
||||||
name2 = name2.substring(0, 6); // String length limit for value name
|
name2 = name2.substring(0, 6); // String length limit for value name
|
||||||
|
calibrationData.calibrateInstance(bvalue2, logger); // Check if boat data value is to be calibrated
|
||||||
double value2 = bvalue2->value; // Value as double in SI unit
|
double value2 = bvalue2->value; // Value as double in SI unit
|
||||||
bool valid2 = bvalue2->valid; // Valid information
|
bool valid2 = bvalue2->valid; // Valid information
|
||||||
calibrationData.calibrateInstance(name2, bvalue2, logger); // Check if boat data value is to be calibrated
|
|
||||||
String svalue2 = formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue2 = formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
String unit2 = formatValue(bvalue2, *commonData).unit; // Unit of value
|
String unit2 = formatValue(bvalue2, *commonData).unit; // Unit of value
|
||||||
|
|
||||||
|
@ -66,9 +66,9 @@ class PageFourValues2 : public Page
|
||||||
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Second element in list (only one value by PageOneValue)
|
||||||
String name3 = xdrDelete(bvalue3->getName()); // Value name
|
String name3 = xdrDelete(bvalue3->getName()); // Value name
|
||||||
name3 = name3.substring(0, 6); // String length limit for value name
|
name3 = name3.substring(0, 6); // String length limit for value name
|
||||||
|
calibrationData.calibrateInstance(bvalue3, logger); // Check if boat data value is to be calibrated
|
||||||
double value3 = bvalue3->value; // Value as double in SI unit
|
double value3 = bvalue3->value; // Value as double in SI unit
|
||||||
bool valid3 = bvalue3->valid; // Valid information
|
bool valid3 = bvalue3->valid; // Valid information
|
||||||
calibrationData.calibrateInstance(name3, bvalue3, logger); // Check if boat data value is to be calibrated
|
|
||||||
String svalue3 = formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue3 = formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
String unit3 = formatValue(bvalue3, *commonData).unit; // Unit of value
|
String unit3 = formatValue(bvalue3, *commonData).unit; // Unit of value
|
||||||
|
|
||||||
|
@ -76,9 +76,9 @@ class PageFourValues2 : public Page
|
||||||
GwApi::BoatValue *bvalue4 = pageData.values[3]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue4 = pageData.values[3]; // Second element in list (only one value by PageOneValue)
|
||||||
String name4 = xdrDelete(bvalue4->getName()); // Value name
|
String name4 = xdrDelete(bvalue4->getName()); // Value name
|
||||||
name4 = name4.substring(0, 6); // String length limit for value name
|
name4 = name4.substring(0, 6); // String length limit for value name
|
||||||
|
calibrationData.calibrateInstance(bvalue4, logger); // Check if boat data value is to be calibrated
|
||||||
double value4 = bvalue4->value; // Value as double in SI unit
|
double value4 = bvalue4->value; // Value as double in SI unit
|
||||||
bool valid4 = bvalue4->valid; // Valid information
|
bool valid4 = bvalue4->valid; // Valid information
|
||||||
calibrationData.calibrateInstance(name4, bvalue4, logger); // Check if boat data value is to be calibrated
|
|
||||||
String svalue4 = formatValue(bvalue4, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue4 = formatValue(bvalue4, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
String unit4 = formatValue(bvalue4, *commonData).unit; // Unit of value
|
String unit4 = formatValue(bvalue4, *commonData).unit; // Unit of value
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ class PageOneValue : public Page
|
||||||
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
|
||||||
String name1 = xdrDelete(bvalue1->getName()); // Value name
|
String name1 = xdrDelete(bvalue1->getName()); // Value name
|
||||||
name1 = name1.substring(0, 6); // String length limit for value name
|
name1 = name1.substring(0, 6); // String length limit for value name
|
||||||
calibrationData.calibrateInstance(name1, bvalue1, logger); // Check if boat data value is to be calibrated
|
calibrationData.calibrateInstance(bvalue1, logger); // Check if boat data value is to be calibrated
|
||||||
double value1 = bvalue1->value; // Value as double in SI unit
|
double value1 = bvalue1->value; // Value as double in SI unit
|
||||||
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
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list
|
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list
|
||||||
String name1 = bvalue1->getName().c_str(); // Value name
|
String name1 = bvalue1->getName().c_str(); // Value name
|
||||||
name1 = name1.substring(0, 6); // String length limit for value name
|
name1 = name1.substring(0, 6); // String length limit for value name
|
||||||
calibrationData.calibrateInstance(name1, bvalue1, logger); // Check if boat data value is to be calibrated
|
calibrationData.calibrateInstance(bvalue1, logger); // Check if boat data value is to be calibrated
|
||||||
value1 = bvalue1->value; // Raw value without unit convertion
|
value1 = bvalue1->value; // Raw value without unit convertion
|
||||||
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
|
||||||
|
|
|
@ -61,8 +61,8 @@ class PageSixValues : public Page
|
||||||
bvalue = pageData.values[i];
|
bvalue = pageData.values[i];
|
||||||
DataName[i] = xdrDelete(bvalue->getName());
|
DataName[i] = xdrDelete(bvalue->getName());
|
||||||
DataName[i] = DataName[i].substring(0, 6); // String length limit for value name
|
DataName[i] = DataName[i].substring(0, 6); // String length limit for value name
|
||||||
|
calibrationData.calibrateInstance(bvalue, logger); // Check if boat data value is to be calibrated
|
||||||
DataValue[i] = bvalue->value; // Value as double in SI unit
|
DataValue[i] = bvalue->value; // Value as double in SI unit
|
||||||
calibrationData.calibrateInstance(DataName[i], bvalue, logger); // Check if boat data value is to be calibrated
|
|
||||||
DataValid[i] = bvalue->valid;
|
DataValid[i] = bvalue->valid;
|
||||||
DataText[i] = formatValue(bvalue, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
DataText[i] = formatValue(bvalue, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
DataUnits[i] = formatValue(bvalue, *commonData).unit;
|
DataUnits[i] = formatValue(bvalue, *commonData).unit;
|
||||||
|
@ -85,9 +85,10 @@ class PageSixValues : public Page
|
||||||
getdisplay().setTextColor(commonData->fgcolor);
|
getdisplay().setTextColor(commonData->fgcolor);
|
||||||
|
|
||||||
for (int i = 0; i < ( HowManyValues / 2 ); i++){
|
for (int i = 0; i < ( HowManyValues / 2 ); i++){
|
||||||
// Horizontal line 3 pix
|
if (i < (HowManyValues / 2) - 1) { // Don't draw horizontal line after last line of values -> standard design
|
||||||
getdisplay().fillRect(0, SixValues_y1+i*SixValues_DeltaY, 400, 3, commonData->fgcolor);
|
// Horizontal line 3 pix
|
||||||
|
getdisplay().fillRect(0, SixValues_y1+(i+1)*SixValues_DeltaY, 400, 3, commonData->fgcolor);
|
||||||
|
}
|
||||||
for (int j = 0; j < 2; j++){
|
for (int j = 0; j < 2; j++){
|
||||||
int ValueIndex = i * 2 + j;
|
int ValueIndex = i * 2 + j;
|
||||||
int x0 = SixValues_x1 + j * SixValues_DeltaX;
|
int x0 = SixValues_x1 + j * SixValues_DeltaX;
|
||||||
|
@ -151,7 +152,6 @@ class PageSixValues : public Page
|
||||||
// Vertical line 3 pix
|
// Vertical line 3 pix
|
||||||
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);
|
||||||
}
|
}
|
||||||
getdisplay().fillRect(0, SixValues_y1+3*SixValues_DeltaY, 400, 3, commonData->fgcolor);
|
|
||||||
|
|
||||||
// Update display
|
// Update display
|
||||||
getdisplay().nextPage(); // Partial update (fast)
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
|
@ -6,19 +6,32 @@
|
||||||
#include <esp32/clk.h>
|
#include <esp32/clk.h>
|
||||||
#include "qrcode.h"
|
#include "qrcode.h"
|
||||||
|
|
||||||
|
#ifdef BOARD_OBP40S3
|
||||||
|
#include <SD.h>
|
||||||
|
#include <FS.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define STRINGIZE_IMPL(x) #x
|
#define STRINGIZE_IMPL(x) #x
|
||||||
#define STRINGIZE(x) STRINGIZE_IMPL(x)
|
#define STRINGIZE(x) STRINGIZE_IMPL(x)
|
||||||
#define VERSINFO STRINGIZE(GWDEVVERSION)
|
#define VERSINFO STRINGIZE(GWDEVVERSION)
|
||||||
|
#define BOARDINFO STRINGIZE(BOARD)
|
||||||
|
#define PCBINFO STRINGIZE(PCBVERS)
|
||||||
|
#define DISPLAYINFO STRINGIZE(EPDTYPE)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Special system page, called directly with fast key sequence 5,4
|
* Special system page, called directly with fast key sequence 5,4
|
||||||
* Out of normal page order.
|
* Out of normal page order.
|
||||||
|
* Consists of some sub-pages with following content:
|
||||||
|
* 1. Hard and software information
|
||||||
|
* 2. System settings
|
||||||
|
* 3. NMEA2000 device list
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class PageSystem : public Page
|
class PageSystem : public Page
|
||||||
{
|
{
|
||||||
uint64_t chipid;
|
uint64_t chipid;
|
||||||
bool simulation;
|
bool simulation;
|
||||||
|
bool sdcard;
|
||||||
String buzzer_mode;
|
String buzzer_mode;
|
||||||
uint8_t buzzer_power;
|
uint8_t buzzer_power;
|
||||||
String cpuspeed;
|
String cpuspeed;
|
||||||
|
@ -26,7 +39,12 @@ String rtc_module;
|
||||||
String gps_module;
|
String gps_module;
|
||||||
String env_module;
|
String env_module;
|
||||||
|
|
||||||
char mode = 'N'; // (N)ormal, (D)evice list
|
String batt_sensor;
|
||||||
|
String solar_sensor;
|
||||||
|
String gen_sensor;
|
||||||
|
String rot_sensor;
|
||||||
|
|
||||||
|
char mode = 'N'; // (N)ormal, (S)ettings, (D)evice list, (C)ard
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PageSystem(CommonData &common){
|
PageSystem(CommonData &common){
|
||||||
|
@ -37,12 +55,20 @@ public:
|
||||||
}
|
}
|
||||||
chipid = ESP.getEfuseMac();
|
chipid = ESP.getEfuseMac();
|
||||||
simulation = common.config->getBool(common.config->useSimuData);
|
simulation = common.config->getBool(common.config->useSimuData);
|
||||||
|
#ifdef BOARD_OBP40S3
|
||||||
|
sdcard = common.config->getBool(common.config->useSDCard);
|
||||||
|
#endif
|
||||||
buzzer_mode = common.config->getString(common.config->buzzerMode);
|
buzzer_mode = common.config->getString(common.config->buzzerMode);
|
||||||
|
buzzer_mode.toLowerCase();
|
||||||
buzzer_power = common.config->getInt(common.config->buzzerPower);
|
buzzer_power = common.config->getInt(common.config->buzzerPower);
|
||||||
cpuspeed = common.config->getString(common.config->cpuSpeed);
|
cpuspeed = common.config->getString(common.config->cpuSpeed);
|
||||||
env_module = common.config->getString(common.config->useEnvSensor);
|
env_module = common.config->getString(common.config->useEnvSensor);
|
||||||
rtc_module = common.config->getString(common.config->useRTC);
|
rtc_module = common.config->getString(common.config->useRTC);
|
||||||
gps_module = common.config->getString(common.config->useGPS);
|
gps_module = common.config->getString(common.config->useGPS);
|
||||||
|
batt_sensor = common.config->getString(common.config->usePowSensor1);
|
||||||
|
solar_sensor = common.config->getString(common.config->usePowSensor2);
|
||||||
|
gen_sensor = common.config->getString(common.config->usePowSensor3);
|
||||||
|
rot_sensor = common.config->getString(common.config->useRotSensor);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setupKeys(){
|
virtual void setupKeys(){
|
||||||
|
@ -60,7 +86,15 @@ public:
|
||||||
commonData->logger->logDebug(GwLog::LOG, "System keyboard handler");
|
commonData->logger->logDebug(GwLog::LOG, "System keyboard handler");
|
||||||
if (key == 2) {
|
if (key == 2) {
|
||||||
if (mode == 'N') {
|
if (mode == 'N') {
|
||||||
|
mode = 'S';
|
||||||
|
} else if (mode == 'S') {
|
||||||
mode = 'D';
|
mode = 'D';
|
||||||
|
} else if (mode == 'D') {
|
||||||
|
if (sdcard) {
|
||||||
|
mode = 'C';
|
||||||
|
} else {
|
||||||
|
mode = 'N';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mode = 'N';
|
mode = 'N';
|
||||||
}
|
}
|
||||||
|
@ -105,12 +139,12 @@ public:
|
||||||
// s is pixel size of a single box
|
// s is pixel size of a single box
|
||||||
QRCode qrcode;
|
QRCode qrcode;
|
||||||
uint8_t qrcodeData[qrcode_getBufferSize(4)];
|
uint8_t qrcodeData[qrcode_getBufferSize(4)];
|
||||||
#ifdef BOARD_OBP40S3
|
#ifdef BOARD_OBP40S3
|
||||||
String prefix = "OBP40:SN:";
|
String prefix = "OBP40:SN:";
|
||||||
#endif
|
#endif
|
||||||
#ifdef BOARD_OBP60S3
|
#ifdef BOARD_OBP60S3
|
||||||
String prefix = "OBP60:SN:";
|
String prefix = "OBP60:SN:";
|
||||||
#endif
|
#endif
|
||||||
qrcode_initText(&qrcode, qrcodeData, 4, 0, (prefix + serialno).c_str());
|
qrcode_initText(&qrcode, qrcodeData, 4, 0, (prefix + serialno).c_str());
|
||||||
int16_t x0 = x;
|
int16_t x0 = x;
|
||||||
for (uint8_t j = 0; j < qrcode.size; j++) {
|
for (uint8_t j = 0; j < qrcode.size; j++) {
|
||||||
|
@ -144,101 +178,189 @@ public:
|
||||||
// Draw page
|
// Draw page
|
||||||
//***********************************************************
|
//***********************************************************
|
||||||
|
|
||||||
const uint16_t y0 = 120; // data table starts here
|
uint16_t x0 = 8; // left column
|
||||||
|
uint16_t y0 = 48; // data table starts here
|
||||||
|
|
||||||
// Set display in partial refresh mode
|
// Set display in partial refresh mode
|
||||||
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||||
|
|
||||||
if (mode == 'N') {
|
if (mode == 'N') {
|
||||||
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold12pt7b);
|
getdisplay().setFont(&Ubuntu_Bold12pt7b);
|
||||||
getdisplay().setCursor(8, 50);
|
getdisplay().setCursor(8, 48);
|
||||||
getdisplay().print("System Information");
|
getdisplay().print("System Information");
|
||||||
|
|
||||||
getdisplay().drawXBitmap(320, 25, logo64_bits, logo64_width, logo64_height, commonData->fgcolor);
|
getdisplay().drawXBitmap(320, 25, logo64_bits, logo64_width, logo64_height, commonData->fgcolor);
|
||||||
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||||
|
y0 = 155;
|
||||||
|
|
||||||
char ssid[13];
|
char ssid[13];
|
||||||
snprintf(ssid, 13, "%04X%08X", (uint16_t)(chipid >> 32), (uint32_t)chipid);
|
snprintf(ssid, 13, "%04X%08X", (uint16_t)(chipid >> 32), (uint32_t)chipid);
|
||||||
displayBarcode(String(ssid), 320, 200, 2);
|
displayBarcode(String(ssid), 320, 200, 2);
|
||||||
getdisplay().setCursor(8, 70);
|
getdisplay().setCursor(8, 70);
|
||||||
getdisplay().print(String("MUDEVICE-") + String(ssid));
|
getdisplay().print(String("MCUDEVICE-") + String(ssid));
|
||||||
|
|
||||||
getdisplay().setCursor(8, 90);
|
getdisplay().setCursor(8, 95);
|
||||||
getdisplay().print("Firmware Version: ");
|
getdisplay().print("Firmware version: ");
|
||||||
|
getdisplay().setCursor(160, 95);
|
||||||
getdisplay().print(VERSINFO);
|
getdisplay().print(VERSINFO);
|
||||||
|
|
||||||
|
getdisplay().setCursor(8, 113);
|
||||||
|
getdisplay().print("Board version: ");
|
||||||
|
getdisplay().setCursor(160, 113);
|
||||||
|
getdisplay().print(BOARDINFO);
|
||||||
|
getdisplay().print(String(" HW ") + String(PCBINFO));
|
||||||
|
|
||||||
|
getdisplay().setCursor(8, 131);
|
||||||
|
getdisplay().print("Display version: ");
|
||||||
|
getdisplay().setCursor(160, 131);
|
||||||
|
getdisplay().print(DISPLAYINFO);
|
||||||
|
|
||||||
getdisplay().setCursor(8, 265);
|
getdisplay().setCursor(8, 265);
|
||||||
#ifdef BOARD_OBP60S3
|
#ifdef BOARD_OBP60S3
|
||||||
getdisplay().print("Press STBY to enter deep sleep mode");
|
getdisplay().print("Press STBY to enter deep sleep mode");
|
||||||
#endif
|
#endif
|
||||||
#ifdef BOARD_OBP40S3
|
#ifdef BOARD_OBP40S3
|
||||||
getdisplay().print("Press wheel to enter deep sleep mode");
|
getdisplay().print("Press wheel to enter deep sleep mode");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
getdisplay().setCursor(2, y0);
|
// Flash memory size
|
||||||
getdisplay().print("Simulation:");
|
uint32_t flash_size = ESP.getFlashChipSize();
|
||||||
getdisplay().setCursor(120, y0);
|
getdisplay().setCursor(8, y0);
|
||||||
getdisplay().print(simulation ? "on" : "off");
|
getdisplay().print("FLASH:");
|
||||||
|
getdisplay().setCursor(90, y0);
|
||||||
|
getdisplay().print(String(flash_size / 1024) + String(" kB"));
|
||||||
|
|
||||||
getdisplay().setCursor(2, y0 + 16);
|
// PSRAM memory size
|
||||||
getdisplay().print("Environment:");
|
uint32_t psram_size = ESP.getPsramSize();
|
||||||
getdisplay().setCursor(120, y0 + 16);
|
getdisplay().setCursor(8, y0 + 16);
|
||||||
getdisplay().print(env_module);
|
getdisplay().print("PSRAM:");
|
||||||
|
getdisplay().setCursor(90, y0 + 16);
|
||||||
// total RAM free
|
getdisplay().print(String(psram_size / 1024) + String(" kB"));
|
||||||
int Heap_free = esp_get_free_heap_size();
|
|
||||||
getdisplay().setCursor(202, y0);
|
|
||||||
getdisplay().print("Total free:");
|
|
||||||
getdisplay().setCursor(300, y0);
|
|
||||||
getdisplay().print(String(Heap_free));
|
|
||||||
|
|
||||||
getdisplay().setCursor(2, y0 + 32);
|
|
||||||
getdisplay().print("Buzzer:");
|
|
||||||
getdisplay().setCursor(120, y0 + 32);
|
|
||||||
getdisplay().print(buzzer_mode);
|
|
||||||
|
|
||||||
// RAM free for task
|
|
||||||
int RAM_free = uxTaskGetStackHighWaterMark(NULL);
|
|
||||||
getdisplay().setCursor(202, y0 + 16);
|
|
||||||
getdisplay().print("Task free:");
|
|
||||||
getdisplay().setCursor(300, y0 + 16);
|
|
||||||
getdisplay().print(String(RAM_free));
|
|
||||||
|
|
||||||
// FRAM available / status
|
// FRAM available / status
|
||||||
getdisplay().setCursor(202, y0 + 32);
|
getdisplay().setCursor(8, y0 + 32);
|
||||||
getdisplay().print("FRAM:");
|
getdisplay().print("FRAM:");
|
||||||
getdisplay().setCursor(300, y0 + 32);
|
getdisplay().setCursor(90, y0 + 32);
|
||||||
getdisplay().print(hasFRAM ? "available" : "not found");
|
getdisplay().print(hasFRAM ? "available" : "not found");
|
||||||
|
|
||||||
getdisplay().setCursor(202, y0 + 64);
|
#ifdef BOARD_OBP40S3
|
||||||
|
// SD-Card
|
||||||
|
getdisplay().setCursor(8, y0 + 48);
|
||||||
|
getdisplay().print("SD-Card:");
|
||||||
|
getdisplay().setCursor(90, y0 + 48);
|
||||||
|
if (sdcard) {
|
||||||
|
uint64_t cardsize = SD.cardSize() / (1024 * 1024);
|
||||||
|
getdisplay().print(String(cardsize) + String(" MB"));
|
||||||
|
} else {
|
||||||
|
getdisplay().print("off");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// CPU speed config / active
|
||||||
|
getdisplay().setCursor(202, y0);
|
||||||
getdisplay().print("CPU speed:");
|
getdisplay().print("CPU speed:");
|
||||||
getdisplay().setCursor(300, y0 + 64);
|
getdisplay().setCursor(300, y0);
|
||||||
getdisplay().print(cpuspeed);
|
getdisplay().print(cpuspeed);
|
||||||
getdisplay().print(" / ");
|
getdisplay().print(" / ");
|
||||||
int cpu_freq = esp_clk_cpu_freq() / 1000000;
|
int cpu_freq = esp_clk_cpu_freq() / 1000000;
|
||||||
getdisplay().print(String(cpu_freq));
|
getdisplay().print(String(cpu_freq));
|
||||||
|
|
||||||
getdisplay().setCursor(2, y0 + 64);
|
// total RAM free
|
||||||
|
int Heap_free = esp_get_free_heap_size();
|
||||||
|
getdisplay().setCursor(202, y0 + 16);
|
||||||
|
getdisplay().print("Total free:");
|
||||||
|
getdisplay().setCursor(300, y0 + 16);
|
||||||
|
getdisplay().print(String(Heap_free));
|
||||||
|
|
||||||
|
// RAM free for task
|
||||||
|
int RAM_free = uxTaskGetStackHighWaterMark(NULL);
|
||||||
|
getdisplay().setCursor(202, y0 + 32);
|
||||||
|
getdisplay().print("Task free:");
|
||||||
|
getdisplay().setCursor(300, y0 + 32);
|
||||||
|
getdisplay().print(String(RAM_free));
|
||||||
|
|
||||||
|
} else if (mode == 'S') {
|
||||||
|
// Settings
|
||||||
|
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold12pt7b);
|
||||||
|
getdisplay().setCursor(x0, 48);
|
||||||
|
getdisplay().print("System settings");
|
||||||
|
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||||
|
x0 = 8;
|
||||||
|
y0 = 72;
|
||||||
|
|
||||||
|
// left column
|
||||||
|
getdisplay().setCursor(x0, y0);
|
||||||
|
getdisplay().print("Simulation:");
|
||||||
|
getdisplay().setCursor(140, y0);
|
||||||
|
getdisplay().print(simulation ? "on" : "off");
|
||||||
|
|
||||||
|
getdisplay().setCursor(x0, y0 + 16);
|
||||||
|
getdisplay().print("Environment:");
|
||||||
|
getdisplay().setCursor(140, y0 + 16);
|
||||||
|
getdisplay().print(env_module);
|
||||||
|
|
||||||
|
getdisplay().setCursor(x0, y0 + 32);
|
||||||
|
getdisplay().print("Buzzer:");
|
||||||
|
getdisplay().setCursor(140, y0 + 32);
|
||||||
|
getdisplay().print(buzzer_mode);
|
||||||
|
|
||||||
|
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(2, 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(2, 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");
|
||||||
|
|
||||||
|
// right column
|
||||||
|
getdisplay().setCursor(202, y0);
|
||||||
|
getdisplay().print("Batt. sensor:");
|
||||||
|
getdisplay().setCursor(320, y0);
|
||||||
|
getdisplay().print(batt_sensor);
|
||||||
|
|
||||||
|
// Solar sensor
|
||||||
|
getdisplay().setCursor(202, y0 + 16);
|
||||||
|
getdisplay().print("Solar sensor:");
|
||||||
|
getdisplay().setCursor(320, y0 + 16);
|
||||||
|
getdisplay().print(solar_sensor);
|
||||||
|
|
||||||
|
// Generator sensor
|
||||||
|
getdisplay().setCursor(202, y0 + 32);
|
||||||
|
getdisplay().print("Gen. sensor:");
|
||||||
|
getdisplay().setCursor(320, y0 + 32);
|
||||||
|
getdisplay().print(gen_sensor);
|
||||||
|
|
||||||
|
// Gyro sensor
|
||||||
|
|
||||||
|
} else if (mode == 'C') {
|
||||||
|
// Card info
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold12pt7b);
|
||||||
|
getdisplay().setCursor(8, 48);
|
||||||
|
getdisplay().print("SD Card info");
|
||||||
|
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||||
|
|
||||||
|
x0 = 20;
|
||||||
|
y0 = 72;
|
||||||
|
getdisplay().setCursor(x0, y0);
|
||||||
|
getdisplay().print("Work in progress...");
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// NMEA2000 device list
|
// NMEA2000 device list
|
||||||
getdisplay().setFont(&Ubuntu_Bold12pt7b);
|
getdisplay().setFont(&Ubuntu_Bold12pt7b);
|
||||||
getdisplay().setCursor(20, 50);
|
getdisplay().setCursor(8, 48);
|
||||||
getdisplay().print("NMEA2000 device list");
|
getdisplay().print("NMEA2000 device list");
|
||||||
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||||
|
|
|
@ -44,9 +44,9 @@ class PageThreeValues : public Page
|
||||||
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
|
||||||
String name1 = xdrDelete(bvalue1->getName()); // Value name
|
String name1 = xdrDelete(bvalue1->getName()); // Value name
|
||||||
name1 = name1.substring(0, 6); // String length limit for value name
|
name1 = name1.substring(0, 6); // String length limit for value name
|
||||||
|
calibrationData.calibrateInstance(bvalue1, logger); // Check if boat data value is to be calibrated
|
||||||
double value1 = bvalue1->value; // Value as double in SI unit
|
double value1 = bvalue1->value; // Value as double in SI unit
|
||||||
bool valid1 = bvalue1->valid; // Valid information
|
bool valid1 = bvalue1->valid; // Valid information
|
||||||
calibrationData.calibrateInstance(name1, bvalue1, logger); // Check if boat data value is to be calibrated
|
|
||||||
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
|
||||||
|
|
||||||
|
@ -54,9 +54,9 @@ class PageThreeValues : public Page
|
||||||
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list (only one value by PageOneValue)
|
||||||
String name2 = xdrDelete(bvalue2->getName()); // Value name
|
String name2 = xdrDelete(bvalue2->getName()); // Value name
|
||||||
name2 = name2.substring(0, 6); // String length limit for value name
|
name2 = name2.substring(0, 6); // String length limit for value name
|
||||||
|
calibrationData.calibrateInstance(bvalue2, logger); // Check if boat data value is to be calibrated
|
||||||
double value2 = bvalue2->value; // Value as double in SI unit
|
double value2 = bvalue2->value; // Value as double in SI unit
|
||||||
bool valid2 = bvalue2->valid; // Valid information
|
bool valid2 = bvalue2->valid; // Valid information
|
||||||
calibrationData.calibrateInstance(name2, bvalue2, logger); // Check if boat data value is to be calibrated
|
|
||||||
String svalue2 = formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue2 = formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
String unit2 = formatValue(bvalue2, *commonData).unit; // Unit of value
|
String unit2 = formatValue(bvalue2, *commonData).unit; // Unit of value
|
||||||
|
|
||||||
|
@ -64,9 +64,9 @@ class PageThreeValues : public Page
|
||||||
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Second element in list (only one value by PageOneValue)
|
||||||
String name3 = xdrDelete(bvalue3->getName()); // Value name
|
String name3 = xdrDelete(bvalue3->getName()); // Value name
|
||||||
name3 = name3.substring(0, 6); // String length limit for value name
|
name3 = name3.substring(0, 6); // String length limit for value name
|
||||||
|
calibrationData.calibrateInstance(bvalue3, logger); // Check if boat data value is to be calibrated
|
||||||
double value3 = bvalue3->value; // Value as double in SI unit
|
double value3 = bvalue3->value; // Value as double in SI unit
|
||||||
bool valid3 = bvalue3->valid; // Valid information
|
bool valid3 = bvalue3->valid; // Valid information
|
||||||
calibrationData.calibrateInstance(name3, bvalue3, logger); // Check if boat data value is to be calibrated
|
|
||||||
String svalue3 = formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue3 = formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
String unit3 = formatValue(bvalue3, *commonData).unit; // Unit of value
|
String unit3 = formatValue(bvalue3, *commonData).unit; // Unit of value
|
||||||
|
|
||||||
|
|
|
@ -42,9 +42,9 @@ class PageTwoValues : public Page
|
||||||
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
|
||||||
String name1 = xdrDelete(bvalue1->getName()); // Value name
|
String name1 = xdrDelete(bvalue1->getName()); // Value name
|
||||||
name1 = name1.substring(0, 6); // String length limit for value name
|
name1 = name1.substring(0, 6); // String length limit for value name
|
||||||
|
calibrationData.calibrateInstance(bvalue1, logger); // Check if boat data value is to be calibrated
|
||||||
double value1 = bvalue1->value; // Value as double in SI unit
|
double value1 = bvalue1->value; // Value as double in SI unit
|
||||||
bool valid1 = bvalue1->valid; // Valid information
|
bool valid1 = bvalue1->valid; // Valid information
|
||||||
calibrationData.calibrateInstance(name1, bvalue1, logger); // Check if boat data value is to be calibrated
|
|
||||||
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
|
||||||
|
|
||||||
|
@ -52,9 +52,9 @@ class PageTwoValues : public Page
|
||||||
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list (only one value by PageOneValue)
|
||||||
String name2 = xdrDelete(bvalue2->getName()); // Value name
|
String name2 = xdrDelete(bvalue2->getName()); // Value name
|
||||||
name2 = name2.substring(0, 6); // String length limit for value name
|
name2 = name2.substring(0, 6); // String length limit for value name
|
||||||
|
calibrationData.calibrateInstance(bvalue2, logger); // Check if boat data value is to be calibrated
|
||||||
double value2 = bvalue2->value; // Value as double in SI unit
|
double value2 = bvalue2->value; // Value as double in SI unit
|
||||||
bool valid2 = bvalue2->valid; // Valid information
|
bool valid2 = bvalue2->valid; // Valid information
|
||||||
calibrationData.calibrateInstance(name2, bvalue2, logger); // Check if boat data value is to be calibrated
|
|
||||||
String svalue2 = formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue2 = formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
String unit2 = formatValue(bvalue2, *commonData).unit; // Unit of value
|
String unit2 = formatValue(bvalue2, *commonData).unit; // Unit of value
|
||||||
|
|
||||||
|
|
|
@ -324,7 +324,7 @@ public:
|
||||||
}
|
}
|
||||||
String name1 = bvalue1->getName().c_str(); // Value name
|
String name1 = bvalue1->getName().c_str(); // Value name
|
||||||
name1 = name1.substring(0, 6); // String length limit for value name
|
name1 = name1.substring(0, 6); // String length limit for value name
|
||||||
calibrationData.calibrateInstance(name1, bvalue1, logger); // Check if boat data value is to be calibrated
|
calibrationData.calibrateInstance(bvalue1, logger); // Check if boat data value is to be calibrated
|
||||||
double value1 = bvalue1->value; // Value as double in SI unit
|
double value1 = bvalue1->value; // Value as double in SI unit
|
||||||
// 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
|
||||||
|
@ -338,7 +338,7 @@ public:
|
||||||
}
|
}
|
||||||
String name2 = bvalue2->getName().c_str(); // Value name
|
String name2 = bvalue2->getName().c_str(); // Value name
|
||||||
name2 = name2.substring(0, 6); // String length limit for value name
|
name2 = name2.substring(0, 6); // String length limit for value name
|
||||||
calibrationData.calibrateInstance(name2, bvalue2, logger); // Check if boat data value is to be calibrated
|
calibrationData.calibrateInstance(bvalue2, logger); // Check if boat data value is to be calibrated
|
||||||
double value2 = bvalue2->value; // Value as double in SI unit
|
double value2 = bvalue2->value; // Value as double in SI unit
|
||||||
// bool valid2 = bvalue2->valid; // Valid information
|
// bool valid2 = bvalue2->valid; // Valid information
|
||||||
if (simulation) {
|
if (simulation) {
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
|
||||||
String name1 = xdrDelete(bvalue1->getName()); // Value name
|
String name1 = xdrDelete(bvalue1->getName()); // Value name
|
||||||
name1 = name1.substring(0, 6); // String length limit for value name
|
name1 = name1.substring(0, 6); // String length limit for value name
|
||||||
calibrationData.calibrateInstance(name1, bvalue1, logger); // Check if boat data value is to be calibrated
|
calibrationData.calibrateInstance(bvalue1, logger); // Check if boat data value is to be calibrated
|
||||||
double value1 = bvalue1->value; // Value as double in SI unit
|
double value1 = bvalue1->value; // Value as double in SI unit
|
||||||
bool valid1 = bvalue1->valid; // Valid information
|
bool valid1 = bvalue1->valid; // Valid information
|
||||||
value1 = formatValue(bvalue1, *commonData).value;// Format only nesaccery for simulation data for pointer
|
value1 = formatValue(bvalue1, *commonData).value;// Format only nesaccery for simulation data for pointer
|
||||||
|
@ -67,7 +67,7 @@ public:
|
||||||
GwApi::BoatValue *bvalue2 = pageData.values[1]; // First element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue2 = pageData.values[1]; // First element in list (only one value by PageOneValue)
|
||||||
String name2 = xdrDelete(bvalue2->getName()); // Value name
|
String name2 = xdrDelete(bvalue2->getName()); // Value name
|
||||||
name2 = name2.substring(0, 6); // String length limit for value name
|
name2 = name2.substring(0, 6); // String length limit for value name
|
||||||
calibrationData.calibrateInstance(name2, bvalue2, logger); // Check if boat data value is to be calibrated
|
calibrationData.calibrateInstance(bvalue2, logger); // Check if boat data value is to be calibrated
|
||||||
double value2 = bvalue2->value; // Value as double in SI unit
|
double value2 = bvalue2->value; // Value as double in SI unit
|
||||||
bool valid2 = bvalue2->valid; // Valid information
|
bool valid2 = bvalue2->valid; // Valid information
|
||||||
String svalue2 = formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue2 = formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
|
@ -81,7 +81,7 @@ public:
|
||||||
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Second element in list (only one value by PageOneValue)
|
||||||
String name3 = xdrDelete(bvalue3->getName()); // Value name
|
String name3 = xdrDelete(bvalue3->getName()); // Value name
|
||||||
name3 = name3.substring(0, 6); // String length limit for value name
|
name3 = name3.substring(0, 6); // String length limit for value name
|
||||||
calibrationData.calibrateInstance(name3, bvalue3, logger); // Check if boat data value is to be calibrated
|
calibrationData.calibrateInstance(bvalue3, logger); // Check if boat data value is to be calibrated
|
||||||
double value3 = bvalue3->value; // Value as double in SI unit
|
double value3 = bvalue3->value; // Value as double in SI unit
|
||||||
bool valid3 = bvalue3->valid; // Valid information
|
bool valid3 = bvalue3->valid; // Valid information
|
||||||
String svalue3 = formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue3 = formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
|
@ -95,7 +95,7 @@ public:
|
||||||
GwApi::BoatValue *bvalue4 = pageData.values[3]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue4 = pageData.values[3]; // Second element in list (only one value by PageOneValue)
|
||||||
String name4 = xdrDelete(bvalue4->getName()); // Value name
|
String name4 = xdrDelete(bvalue4->getName()); // Value name
|
||||||
name4 = name4.substring(0, 6); // String length limit for value name
|
name4 = name4.substring(0, 6); // String length limit for value name
|
||||||
calibrationData.calibrateInstance(name4, bvalue4, logger); // Check if boat data value is to be calibrated
|
calibrationData.calibrateInstance(bvalue4, logger); // Check if boat data value is to be calibrated
|
||||||
double value4 = bvalue4->value; // Value as double in SI unit
|
double value4 = bvalue4->value; // Value as double in SI unit
|
||||||
bool valid4 = bvalue4->valid; // Valid information
|
bool valid4 = bvalue4->valid; // Valid information
|
||||||
String svalue4 = formatValue(bvalue4, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue4 = formatValue(bvalue4, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
|
@ -109,7 +109,7 @@ public:
|
||||||
GwApi::BoatValue *bvalue5 = pageData.values[4]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue5 = pageData.values[4]; // Second element in list (only one value by PageOneValue)
|
||||||
String name5 = xdrDelete(bvalue5->getName()); // Value name
|
String name5 = xdrDelete(bvalue5->getName()); // Value name
|
||||||
name5 = name5.substring(0, 6); // String length limit for value name
|
name5 = name5.substring(0, 6); // String length limit for value name
|
||||||
calibrationData.calibrateInstance(name5, bvalue5, logger); // Check if boat data value is to be calibrated
|
calibrationData.calibrateInstance(bvalue5, logger); // Check if boat data value is to be calibrated
|
||||||
double value5 = bvalue5->value; // Value as double in SI unit
|
double value5 = bvalue5->value; // Value as double in SI unit
|
||||||
bool valid5 = bvalue5->valid; // Valid information
|
bool valid5 = bvalue5->valid; // Valid information
|
||||||
String svalue5 = formatValue(bvalue5, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue5 = formatValue(bvalue5, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
|
@ -123,7 +123,7 @@ public:
|
||||||
GwApi::BoatValue *bvalue6 = pageData.values[5]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue6 = pageData.values[5]; // Second element in list (only one value by PageOneValue)
|
||||||
String name6 = xdrDelete(bvalue6->getName()); // Value name
|
String name6 = xdrDelete(bvalue6->getName()); // Value name
|
||||||
name6 = name6.substring(0, 6); // String length limit for value name
|
name6 = name6.substring(0, 6); // String length limit for value name
|
||||||
calibrationData.calibrateInstance(name6, bvalue6, logger); // Check if boat data value is to be calibrated
|
calibrationData.calibrateInstance(bvalue6, logger); // Check if boat data value is to be calibrated
|
||||||
double value6 = bvalue6->value; // Value as double in SI unit
|
double value6 = bvalue6->value; // Value as double in SI unit
|
||||||
bool valid6 = bvalue6->valid; // Valid information
|
bool valid6 = bvalue6->valid; // Valid information
|
||||||
String svalue6 = formatValue(bvalue6, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue6 = formatValue(bvalue6, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
|
||||||
String name1 = xdrDelete(bvalue1->getName()); // Value name
|
String name1 = xdrDelete(bvalue1->getName()); // Value name
|
||||||
name1 = name1.substring(0, 6); // String length limit for value name
|
name1 = name1.substring(0, 6); // String length limit for value name
|
||||||
calibrationData.calibrateInstance(name1, bvalue1, logger); // Check if boat data value is to be calibrated
|
calibrationData.calibrateInstance(bvalue1, logger); // Check if boat data value is to be calibrated
|
||||||
double value1 = bvalue1->value; // Value as double in SI unit
|
double value1 = bvalue1->value; // Value as double in SI unit
|
||||||
bool valid1 = bvalue1->valid; // Valid information
|
bool valid1 = bvalue1->valid; // Valid information
|
||||||
value1 = formatValue(bvalue1, *commonData).value;// Format only nesaccery for simulation data for pointer
|
value1 = formatValue(bvalue1, *commonData).value;// Format only nesaccery for simulation data for pointer
|
||||||
|
@ -67,7 +67,7 @@ public:
|
||||||
GwApi::BoatValue *bvalue2 = pageData.values[1]; // First element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue2 = pageData.values[1]; // First element in list (only one value by PageOneValue)
|
||||||
String name2 = xdrDelete(bvalue2->getName()); // Value name
|
String name2 = xdrDelete(bvalue2->getName()); // Value name
|
||||||
name2 = name2.substring(0, 6); // String length limit for value name
|
name2 = name2.substring(0, 6); // String length limit for value name
|
||||||
calibrationData.calibrateInstance(name2, bvalue2, logger); // Check if boat data value is to be calibrated
|
calibrationData.calibrateInstance(bvalue2, logger); // Check if boat data value is to be calibrated
|
||||||
double value2 = bvalue2->value; // Value as double in SI unit
|
double value2 = bvalue2->value; // Value as double in SI unit
|
||||||
bool valid2 = bvalue2->valid; // Valid information
|
bool valid2 = bvalue2->valid; // Valid information
|
||||||
String svalue2 = formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue2 = formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
|
@ -81,7 +81,7 @@ public:
|
||||||
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Second element in list (only one value by PageOneValue)
|
||||||
String name3 = xdrDelete(bvalue3->getName()); // Value name
|
String name3 = xdrDelete(bvalue3->getName()); // Value name
|
||||||
name3 = name3.substring(0, 6); // String length limit for value name
|
name3 = name3.substring(0, 6); // String length limit for value name
|
||||||
calibrationData.calibrateInstance(name3, bvalue3, logger); // Check if boat data value is to be calibrated
|
calibrationData.calibrateInstance(bvalue3, logger); // Check if boat data value is to be calibrated
|
||||||
double value3 = bvalue3->value; // Value as double in SI unit
|
double value3 = bvalue3->value; // Value as double in SI unit
|
||||||
bool valid3 = bvalue3->valid; // Valid information
|
bool valid3 = bvalue3->valid; // Valid information
|
||||||
String svalue3 = formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue3 = formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
|
@ -95,7 +95,7 @@ public:
|
||||||
GwApi::BoatValue *bvalue4 = pageData.values[3]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue4 = pageData.values[3]; // Second element in list (only one value by PageOneValue)
|
||||||
String name4 = xdrDelete(bvalue4->getName()); // Value name
|
String name4 = xdrDelete(bvalue4->getName()); // Value name
|
||||||
name4 = name4.substring(0, 6); // String length limit for value name
|
name4 = name4.substring(0, 6); // String length limit for value name
|
||||||
calibrationData.calibrateInstance(name4, bvalue4, logger); // Check if boat data value is to be calibrated
|
calibrationData.calibrateInstance(bvalue4, logger); // Check if boat data value is to be calibrated
|
||||||
double value4 = bvalue4->value; // Value as double in SI unit
|
double value4 = bvalue4->value; // Value as double in SI unit
|
||||||
bool valid4 = bvalue4->valid; // Valid information
|
bool valid4 = bvalue4->valid; // Valid information
|
||||||
String svalue4 = formatValue(bvalue4, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue4 = formatValue(bvalue4, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
|
@ -109,7 +109,7 @@ public:
|
||||||
GwApi::BoatValue *bvalue5 = pageData.values[4]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue5 = pageData.values[4]; // Second element in list (only one value by PageOneValue)
|
||||||
String name5 = xdrDelete(bvalue5->getName()); // Value name
|
String name5 = xdrDelete(bvalue5->getName()); // Value name
|
||||||
name5 = name5.substring(0, 6); // String length limit for value name
|
name5 = name5.substring(0, 6); // String length limit for value name
|
||||||
calibrationData.calibrateInstance(name5, bvalue5, logger); // Check if boat data value is to be calibrated
|
calibrationData.calibrateInstance(bvalue5, logger); // Check if boat data value is to be calibrated
|
||||||
double value5 = bvalue5->value; // Value as double in SI unit
|
double value5 = bvalue5->value; // Value as double in SI unit
|
||||||
bool valid5 = bvalue5->valid; // Valid information
|
bool valid5 = bvalue5->valid; // Valid information
|
||||||
String svalue5 = formatValue(bvalue5, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue5 = formatValue(bvalue5, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
|
@ -123,7 +123,7 @@ public:
|
||||||
GwApi::BoatValue *bvalue6 = pageData.values[5]; // Second element in list (only one value by PageOneValue)
|
GwApi::BoatValue *bvalue6 = pageData.values[5]; // Second element in list (only one value by PageOneValue)
|
||||||
String name6 = xdrDelete(bvalue6->getName()); // Value name
|
String name6 = xdrDelete(bvalue6->getName()); // Value name
|
||||||
name6 = name6.substring(0, 6); // String length limit for value name
|
name6 = name6.substring(0, 6); // String length limit for value name
|
||||||
calibrationData.calibrateInstance(name6, bvalue6, logger); // Check if boat data value is to be calibrated
|
calibrationData.calibrateInstance(bvalue6, logger); // Check if boat data value is to be calibrated
|
||||||
double value6 = bvalue6->value; // Value as double in SI unit
|
double value6 = bvalue6->value; // Value as double in SI unit
|
||||||
bool valid6 = bvalue6->valid; // Valid information
|
bool valid6 = bvalue6->valid; // Valid information
|
||||||
String svalue6 = formatValue(bvalue6, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
String svalue6 = formatValue(bvalue6, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
"description": "NTP time server. Use only one hostname or IP address",
|
"description": "NTP time server. Use only one hostname or IP address",
|
||||||
"category": "wifi client",
|
"category": "wifi client",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp40": "true"
|
"obp60": "true"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -696,10 +696,12 @@
|
||||||
"---",
|
"---",
|
||||||
"AWA",
|
"AWA",
|
||||||
"AWS",
|
"AWS",
|
||||||
|
"COG",
|
||||||
"DBT",
|
"DBT",
|
||||||
"HDM",
|
"HDM",
|
||||||
"PRPOS",
|
"PRPOS",
|
||||||
"RPOS",
|
"RPOS",
|
||||||
|
"SOG",
|
||||||
"STW",
|
"STW",
|
||||||
"TWA",
|
"TWA",
|
||||||
"TWS",
|
"TWS",
|
||||||
|
@ -720,7 +722,21 @@
|
||||||
"category": "OBP60 Calibrations",
|
"category": "OBP60 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp60":"true"
|
"obp60":"true"
|
||||||
}
|
},
|
||||||
|
"condition": [
|
||||||
|
{ "calInstance1": "AWA" },
|
||||||
|
{ "calInstance1": "AWS" },
|
||||||
|
{ "calInstance2": "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",
|
||||||
|
@ -731,7 +747,21 @@
|
||||||
"category": "OBP60 Calibrations",
|
"category": "OBP60 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp60":"true"
|
"obp60":"true"
|
||||||
}
|
},
|
||||||
|
"condition": [
|
||||||
|
{ "calInstance1": "AWA" },
|
||||||
|
{ "calInstance1": "AWS" },
|
||||||
|
{ "calInstance2": "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",
|
||||||
|
@ -741,11 +771,25 @@
|
||||||
"check": "checkMinMax",
|
"check": "checkMinMax",
|
||||||
"min": 0,
|
"min": 0,
|
||||||
"max": 10,
|
"max": 10,
|
||||||
"description": "Smoothing factor for data instance 1",
|
"description": "Smoothing factor [0..10]; 0 = no smoothing",
|
||||||
"category": "OBP60 Calibrations",
|
"category": "OBP60 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp60":"true"
|
"obp60":"true"
|
||||||
}
|
},
|
||||||
|
"condition": [
|
||||||
|
{ "calInstance1": "AWA" },
|
||||||
|
{ "calInstance1": "AWS" },
|
||||||
|
{ "calInstance2": "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",
|
||||||
|
@ -757,10 +801,12 @@
|
||||||
"---",
|
"---",
|
||||||
"AWA",
|
"AWA",
|
||||||
"AWS",
|
"AWS",
|
||||||
|
"COG",
|
||||||
"DBT",
|
"DBT",
|
||||||
"HDM",
|
"HDM",
|
||||||
"PRPOS",
|
"PRPOS",
|
||||||
"RPOS",
|
"RPOS",
|
||||||
|
"SOG",
|
||||||
"STW",
|
"STW",
|
||||||
"TWA",
|
"TWA",
|
||||||
"TWS",
|
"TWS",
|
||||||
|
@ -781,7 +827,21 @@
|
||||||
"category": "OBP60 Calibrations",
|
"category": "OBP60 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp60":"true"
|
"obp60":"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",
|
||||||
|
@ -792,7 +852,21 @@
|
||||||
"category": "OBP60 Calibrations",
|
"category": "OBP60 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp60":"true"
|
"obp60":"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",
|
||||||
|
@ -802,11 +876,25 @@
|
||||||
"check": "checkMinMax",
|
"check": "checkMinMax",
|
||||||
"min": 0,
|
"min": 0,
|
||||||
"max": 10,
|
"max": 10,
|
||||||
"description": "Smoothing factor for data instance 2",
|
"description": "Smoothing factor [0..10]; 0 = no smoothing",
|
||||||
"category": "OBP60 Calibrations",
|
"category": "OBP60 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp60":"true"
|
"obp60":"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",
|
||||||
|
@ -818,10 +906,12 @@
|
||||||
"---",
|
"---",
|
||||||
"AWA",
|
"AWA",
|
||||||
"AWS",
|
"AWS",
|
||||||
|
"COG",
|
||||||
"DBT",
|
"DBT",
|
||||||
"HDM",
|
"HDM",
|
||||||
"PRPOS",
|
"PRPOS",
|
||||||
"RPOS",
|
"RPOS",
|
||||||
|
"SOG",
|
||||||
"STW",
|
"STW",
|
||||||
"TWA",
|
"TWA",
|
||||||
"TWS",
|
"TWS",
|
||||||
|
@ -842,7 +932,21 @@
|
||||||
"category": "OBP60 Calibrations",
|
"category": "OBP60 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp60":"true"
|
"obp60":"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",
|
||||||
|
@ -853,7 +957,21 @@
|
||||||
"category": "OBP60 Calibrations",
|
"category": "OBP60 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp60":"true"
|
"obp60":"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",
|
||||||
|
@ -863,11 +981,25 @@
|
||||||
"check": "checkMinMax",
|
"check": "checkMinMax",
|
||||||
"min": 0,
|
"min": 0,
|
||||||
"max": 10,
|
"max": 10,
|
||||||
"description": "Smoothing factor for data instance 3",
|
"description": "Smoothing factor [0..10]; 0 = no smoothing",
|
||||||
"category": "OBP60 Calibrations",
|
"category": "OBP60 Calibrations",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp60":"true"
|
"obp60":"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",
|
||||||
|
@ -1117,6 +1249,7 @@
|
||||||
"min": 1,
|
"min": 1,
|
||||||
"max": 10,
|
"max": 10,
|
||||||
"default":"10",
|
"default":"10",
|
||||||
|
"description": "Number of visible data pages [1...10]",
|
||||||
"category":"OBP60 Pages",
|
"category":"OBP60 Pages",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp60":"true"
|
"obp60":"true"
|
||||||
|
@ -1130,6 +1263,7 @@
|
||||||
"min": 1,
|
"min": 1,
|
||||||
"max": 10,
|
"max": 10,
|
||||||
"default":"1",
|
"default":"1",
|
||||||
|
"description": "First page number to display after device startup",
|
||||||
"category":"OBP60 Pages",
|
"category":"OBP60 Pages",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"obp60":"true"
|
"obp60":"true"
|
||||||
|
@ -1152,6 +1286,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "page1type",
|
"name": "page1type",
|
||||||
"label": "Type",
|
"label": "Type",
|
||||||
|
@ -1163,6 +1298,7 @@
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
"Clock",
|
"Clock",
|
||||||
|
"Compass",
|
||||||
"DST810",
|
"DST810",
|
||||||
"Fluid",
|
"Fluid",
|
||||||
"FourValues",
|
"FourValues",
|
||||||
|
@ -1442,6 +1578,7 @@
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
"Clock",
|
"Clock",
|
||||||
|
"Compass",
|
||||||
"DST810",
|
"DST810",
|
||||||
"Fluid",
|
"Fluid",
|
||||||
"FourValues",
|
"FourValues",
|
||||||
|
@ -1718,6 +1855,7 @@
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
"Clock",
|
"Clock",
|
||||||
|
"Compass",
|
||||||
"DST810",
|
"DST810",
|
||||||
"Fluid",
|
"Fluid",
|
||||||
"FourValues",
|
"FourValues",
|
||||||
|
@ -1991,6 +2129,7 @@
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
"Clock",
|
"Clock",
|
||||||
|
"Compass",
|
||||||
"DST810",
|
"DST810",
|
||||||
"Fluid",
|
"Fluid",
|
||||||
"FourValues",
|
"FourValues",
|
||||||
|
@ -2261,6 +2400,7 @@
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
"Clock",
|
"Clock",
|
||||||
|
"Compass",
|
||||||
"DST810",
|
"DST810",
|
||||||
"Fluid",
|
"Fluid",
|
||||||
"FourValues",
|
"FourValues",
|
||||||
|
@ -2528,6 +2668,7 @@
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
"Clock",
|
"Clock",
|
||||||
|
"Compass",
|
||||||
"DST810",
|
"DST810",
|
||||||
"Fluid",
|
"Fluid",
|
||||||
"FourValues",
|
"FourValues",
|
||||||
|
@ -2792,6 +2933,7 @@
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
"Clock",
|
"Clock",
|
||||||
|
"Compass",
|
||||||
"DST810",
|
"DST810",
|
||||||
"Fluid",
|
"Fluid",
|
||||||
"FourValues",
|
"FourValues",
|
||||||
|
@ -3053,6 +3195,7 @@
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
"Clock",
|
"Clock",
|
||||||
|
"Compass",
|
||||||
"DST810",
|
"DST810",
|
||||||
"Fluid",
|
"Fluid",
|
||||||
"FourValues",
|
"FourValues",
|
||||||
|
@ -3311,6 +3454,7 @@
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
"Clock",
|
"Clock",
|
||||||
|
"Compass",
|
||||||
"DST810",
|
"DST810",
|
||||||
"Fluid",
|
"Fluid",
|
||||||
"FourValues",
|
"FourValues",
|
||||||
|
@ -3566,6 +3710,7 @@
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
"Clock",
|
"Clock",
|
||||||
|
"Compass",
|
||||||
"DST810",
|
"DST810",
|
||||||
"Fluid",
|
"Fluid",
|
||||||
"FourValues",
|
"FourValues",
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -15,6 +15,7 @@ no_of_fields_per_page = {
|
||||||
"Battery": 0,
|
"Battery": 0,
|
||||||
"BME280": 0,
|
"BME280": 0,
|
||||||
"Clock": 0,
|
"Clock": 0,
|
||||||
|
"Compass" : 0,
|
||||||
"DST810": 0,
|
"DST810": 0,
|
||||||
"Fluid": 1,
|
"Fluid": 1,
|
||||||
"FourValues2": 4,
|
"FourValues2": 4,
|
||||||
|
@ -24,6 +25,7 @@ no_of_fields_per_page = {
|
||||||
"OneValue": 1,
|
"OneValue": 1,
|
||||||
"RollPitch": 2,
|
"RollPitch": 2,
|
||||||
"RudderPosition": 0,
|
"RudderPosition": 0,
|
||||||
|
"SixValues" : 6,
|
||||||
"Solar": 0,
|
"Solar": 0,
|
||||||
"ThreeValues": 3,
|
"ThreeValues": 3,
|
||||||
"TwoValues": 2,
|
"TwoValues": 2,
|
||||||
|
@ -31,7 +33,6 @@ no_of_fields_per_page = {
|
||||||
"WhitePage": 0,
|
"WhitePage": 0,
|
||||||
"WindRose": 0,
|
"WindRose": 0,
|
||||||
"WindRoseFlex": 6,
|
"WindRoseFlex": 6,
|
||||||
"SixValues" : 6,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# No changes needed beyond this point
|
# No changes needed beyond this point
|
||||||
|
|
|
@ -79,8 +79,8 @@ void OBP60Init(GwApi *api){
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BOARD_OBP40S3
|
#ifdef BOARD_OBP40S3
|
||||||
String sdcard = config->getConfigItem(config->useSDCard, true)->asString();
|
bool sdcard = config->getBool(config->useSDCard);
|
||||||
if (sdcard == "on") {
|
if (sdcard) {
|
||||||
SPIClass SD_SPI = SPIClass(HSPI);
|
SPIClass SD_SPI = SPIClass(HSPI);
|
||||||
SD_SPI.begin(SD_SPI_CLK, SD_SPI_MISO, SD_SPI_MOSI);
|
SD_SPI.begin(SD_SPI_CLK, SD_SPI_MISO, SD_SPI_MOSI);
|
||||||
if (SD.begin(SD_SPI_CS, SD_SPI, 80000000)) {
|
if (SD.begin(SD_SPI_CS, SD_SPI, 80000000)) {
|
||||||
|
|
|
@ -94,7 +94,8 @@ lib_deps =
|
||||||
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 V1.0 with ESP32S3 SKU:DIE07300S (CrowPanel 4.2)
|
-D BOARD_OBP40S3 #Board OBP40 with ESP32S3
|
||||||
|
-D HARDWARE_V10 #OBP40 hardware revision V1.0 SKU:DIE07300S V1.1 (CrowPanel 4.2)
|
||||||
-D DISPLAY_GDEY042T81 #new E-Ink display from Waveshare, R10 2.2 ohm
|
-D DISPLAY_GDEY042T81 #new E-Ink display from Waveshare, R10 2.2 ohm
|
||||||
#-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
|
||||||
|
|
|
@ -0,0 +1,853 @@
|
||||||
|
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||||
|
#include "obp60task.h"
|
||||||
|
#include "Pagedata.h" // Data exchange for pages
|
||||||
|
#include "OBP60Hardware.h" // PIN definitions
|
||||||
|
#include <Wire.h> // I2C connections
|
||||||
|
#include <MCP23017.h> // MCP23017 extension Port
|
||||||
|
#include <N2kTypes.h> // NMEA2000
|
||||||
|
#include <N2kMessages.h>
|
||||||
|
#include <NMEA0183.h> // NMEA0183
|
||||||
|
#include <NMEA0183Msg.h>
|
||||||
|
#include <NMEA0183Messages.h>
|
||||||
|
#include <GxEPD2_BW.h> // GxEPD2 lib for b/w E-Ink displays
|
||||||
|
#include "OBP60Extensions.h" // Functions lib for extension board
|
||||||
|
#include "OBP60Keypad.h" // Functions for keypad
|
||||||
|
|
||||||
|
#ifdef BOARD_OBP40S3
|
||||||
|
#include "driver/rtc_io.h" // Needs for weakup from deep sleep
|
||||||
|
#include <FS.h> // SD-Card access
|
||||||
|
#include <SD.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// True type character sets includes
|
||||||
|
// See OBP60ExtensionPort.cpp
|
||||||
|
|
||||||
|
// Pictures
|
||||||
|
//#include GxEPD_BitmapExamples // Example picture
|
||||||
|
#include "MFD_OBP60_400x300_sw.h" // MFD with logo
|
||||||
|
#include "Logo_OBP_400x300_sw.h" // OBP Logo
|
||||||
|
#include "images/unknown.xbm" // unknown page indicator
|
||||||
|
#include "OBP60QRWiFi.h" // Functions lib for WiFi QR code
|
||||||
|
#include "OBPSensorTask.h" // Functions lib for sensor data
|
||||||
|
|
||||||
|
|
||||||
|
// Global vars
|
||||||
|
bool initComplete = false; // Initialization complete
|
||||||
|
int taskRunCounter = 0; // Task couter for loop section
|
||||||
|
|
||||||
|
// Hardware initialization before start all services
|
||||||
|
//####################################################################################
|
||||||
|
void OBP60Init(GwApi *api){
|
||||||
|
|
||||||
|
GwLog *logger = api->getLogger();
|
||||||
|
GwConfigHandler *config = api->getConfig();
|
||||||
|
|
||||||
|
// Set a new device name and hidden the original name in the main config
|
||||||
|
String devicename = api->getConfig()->getConfigItem(api->getConfig()->deviceName,true)->asString();
|
||||||
|
api->getConfig()->setValue(GwConfigDefinitions::systemName, devicename, GwConfigInterface::ConfigType::HIDDEN);
|
||||||
|
|
||||||
|
api->getLogger()->logDebug(GwLog::LOG,"obp60init running");
|
||||||
|
|
||||||
|
// Check I2C devices
|
||||||
|
|
||||||
|
|
||||||
|
// Init hardware
|
||||||
|
hardwareInit(api);
|
||||||
|
|
||||||
|
// Init power rail 5.0V
|
||||||
|
String powermode = api->getConfig()->getConfigItem(api->getConfig()->powerMode,true)->asString();
|
||||||
|
api->getLogger()->logDebug(GwLog::DEBUG,"Power Mode is: %s", powermode.c_str());
|
||||||
|
if(powermode == "Max Power" || powermode == "Only 5.0V"){
|
||||||
|
#ifdef HARDWARE_V21
|
||||||
|
setPortPin(OBP_POWER_50, true); // Power on 5.0V rail
|
||||||
|
#endif
|
||||||
|
#ifdef BOARD_OBP40S3
|
||||||
|
setPortPin(OBP_POWER_EPD, true);// Power on ePaper display
|
||||||
|
setPortPin(OBP_POWER_SD, true); // Power on SD card
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
#ifdef HARDWARE_V21
|
||||||
|
setPortPin(OBP_POWER_50, false); // Power off 5.0V rail
|
||||||
|
#endif
|
||||||
|
#ifdef BOARD_OBP40S3
|
||||||
|
setPortPin(OBP_POWER_EPD, false);// Power off ePaper display
|
||||||
|
setPortPin(OBP_POWER_SD, false); // Power off SD card
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef BOARD_OBP40S3
|
||||||
|
String sdcard = config->getConfigItem(config->useSDCard, true)->asString();
|
||||||
|
if (sdcard == "on") {
|
||||||
|
SPIClass SD_SPI = SPIClass(HSPI);
|
||||||
|
SD_SPI.begin(SD_SPI_CLK, SD_SPI_MISO, SD_SPI_MOSI);
|
||||||
|
if (SD.begin(SD_SPI_CS, SD_SPI, 80000000)) {
|
||||||
|
String sdtype = "unknown";
|
||||||
|
uint8_t cardType = SD.cardType();
|
||||||
|
switch (cardType) {
|
||||||
|
case CARD_MMC:
|
||||||
|
sdtype = "MMC";
|
||||||
|
break;
|
||||||
|
case CARD_SD:
|
||||||
|
sdtype = "SDSC";
|
||||||
|
break;
|
||||||
|
case CARD_SDHC:
|
||||||
|
sdtype = "SDHC";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
|
||||||
|
LOG_DEBUG(GwLog::LOG,"SD card type %s of size %d MB detected", sdtype, cardSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deep sleep wakeup configuration
|
||||||
|
esp_sleep_enable_ext0_wakeup(OBP_WAKEWUP_PIN, 0); // 1 = High, 0 = Low
|
||||||
|
rtc_gpio_pullup_en(OBP_WAKEWUP_PIN); // Activate pullup resistor
|
||||||
|
rtc_gpio_pulldown_dis(OBP_WAKEWUP_PIN); // Disable pulldown resistor
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Settings for e-paper display
|
||||||
|
String fastrefresh = api->getConfig()->getConfigItem(api->getConfig()->fastRefresh,true)->asString();
|
||||||
|
api->getLogger()->logDebug(GwLog::DEBUG,"Fast Refresh Mode is: %s", fastrefresh.c_str());
|
||||||
|
#ifdef DISPLAY_GDEY042T81
|
||||||
|
if(fastrefresh == "true"){
|
||||||
|
static const bool useFastFullUpdate = true; // Enable fast full display update only for GDEY042T81
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BOARD_OBP60S3
|
||||||
|
touchSleepWakeUpEnable(TP1, 45); // TODO sensitivity should be configurable via web interface
|
||||||
|
touchSleepWakeUpEnable(TP2, 45);
|
||||||
|
touchSleepWakeUpEnable(TP3, 45);
|
||||||
|
touchSleepWakeUpEnable(TP4, 45);
|
||||||
|
touchSleepWakeUpEnable(TP5, 45);
|
||||||
|
touchSleepWakeUpEnable(TP6, 45);
|
||||||
|
esp_sleep_enable_touchpad_wakeup();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Get CPU speed
|
||||||
|
int freq = getCpuFrequencyMhz();
|
||||||
|
api->getLogger()->logDebug(GwLog::LOG,"CPU speed at boot: %i MHz", freq);
|
||||||
|
|
||||||
|
// Settings for backlight
|
||||||
|
String backlightMode = api->getConfig()->getConfigItem(api->getConfig()->backlight,true)->asString();
|
||||||
|
api->getLogger()->logDebug(GwLog::DEBUG,"Backlight Mode is: %s", backlightMode.c_str());
|
||||||
|
uint brightness = uint(api->getConfig()->getConfigItem(api->getConfig()->blBrightness,true)->asInt());
|
||||||
|
String backlightColor = api->getConfig()->getConfigItem(api->getConfig()->blColor,true)->asString();
|
||||||
|
if(String(backlightMode) == "On"){
|
||||||
|
setBacklightLED(brightness, colorMapping(backlightColor));
|
||||||
|
}
|
||||||
|
else if(String(backlightMode) == "Off"){
|
||||||
|
setBacklightLED(0, COLOR_BLACK); // Backlight LEDs off (blue without britghness)
|
||||||
|
}
|
||||||
|
else if(String(backlightMode) == "Control by Key"){
|
||||||
|
setBacklightLED(0, COLOR_BLUE); // Backlight LEDs off (blue without britghness)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Settings flash LED mode
|
||||||
|
String ledMode = api->getConfig()->getConfigItem(api->getConfig()->flashLED,true)->asString();
|
||||||
|
api->getLogger()->logDebug(GwLog::DEBUG,"LED Mode is: %s", ledMode.c_str());
|
||||||
|
if(String(ledMode) == "Off"){
|
||||||
|
setBlinkingLED(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marker for init complete
|
||||||
|
// Used in OBP60Task()
|
||||||
|
initComplete = true;
|
||||||
|
|
||||||
|
// Buzzer tone for initialization finish
|
||||||
|
setBuzzerPower(uint(api->getConfig()->getConfigItem(api->getConfig()->buzzerPower,true)->asInt()));
|
||||||
|
buzzer(TONE4, 500);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int page0=0;
|
||||||
|
QueueHandle_t queue;
|
||||||
|
GwLog* logger = NULL;
|
||||||
|
// GwApi* api = NULL;
|
||||||
|
uint sensitivity = 100;
|
||||||
|
bool use_syspage = true;
|
||||||
|
} MyData;
|
||||||
|
|
||||||
|
// Keyboard Task
|
||||||
|
void keyboardTask(void *param){
|
||||||
|
MyData *data=(MyData *)param;
|
||||||
|
|
||||||
|
int keycode = 0;
|
||||||
|
data->logger->logDebug(GwLog::LOG,"Start keyboard task");
|
||||||
|
|
||||||
|
// Loop for keyboard task
|
||||||
|
while (true){
|
||||||
|
keycode = readKeypad(data->logger, data->sensitivity, data->use_syspage);
|
||||||
|
//send a key event
|
||||||
|
if(keycode != 0){
|
||||||
|
xQueueSend(data->queue, &keycode, 0);
|
||||||
|
data->logger->logDebug(GwLog::LOG,"Send keycode: %d", keycode);
|
||||||
|
}
|
||||||
|
delay(20); // 50Hz update rate (20ms)
|
||||||
|
}
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
class BoatValueList{
|
||||||
|
public:
|
||||||
|
static const int MAXVALUES=100;
|
||||||
|
//we create a list containing all our BoatValues
|
||||||
|
//this is the list we later use to let the api fill all the values
|
||||||
|
//additionally we put the necessary values into the paga data - see below
|
||||||
|
GwApi::BoatValue *allBoatValues[MAXVALUES];
|
||||||
|
int numValues=0;
|
||||||
|
|
||||||
|
bool addValueToList(GwApi::BoatValue *v){
|
||||||
|
for (int i=0;i<numValues;i++){
|
||||||
|
if (allBoatValues[i] == v){
|
||||||
|
//already in list...
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (numValues >= MAXVALUES) return false;
|
||||||
|
allBoatValues[numValues]=v;
|
||||||
|
numValues++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//helper to ensure that each BoatValue is only queried once
|
||||||
|
GwApi::BoatValue *findValueOrCreate(String name){
|
||||||
|
for (int i=0;i<numValues;i++){
|
||||||
|
if (allBoatValues[i]->getName() == name) {
|
||||||
|
return allBoatValues[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GwApi::BoatValue *rt=new GwApi::BoatValue(name);
|
||||||
|
addValueToList(rt);
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//we want to have a list that has all our page definitions
|
||||||
|
//this way each page can easily be added here
|
||||||
|
//needs some minor tricks for the safe static initialization
|
||||||
|
typedef std::vector<PageDescription*> Pages;
|
||||||
|
//the page list class
|
||||||
|
class PageList{
|
||||||
|
public:
|
||||||
|
Pages pages;
|
||||||
|
void add(PageDescription *p){
|
||||||
|
pages.push_back(p);
|
||||||
|
}
|
||||||
|
PageDescription *find(String name){
|
||||||
|
for (auto it=pages.begin();it != pages.end();it++){
|
||||||
|
if ((*it)->pageName == name){
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this function will add all the pages we know to the pagelist
|
||||||
|
* each page should have defined a registerXXXPage variable of type
|
||||||
|
* PageData that describes what it needs
|
||||||
|
*/
|
||||||
|
void registerAllPages(PageList &list){
|
||||||
|
//the next line says that this variable is defined somewhere else
|
||||||
|
//in our case in a separate C++ source file
|
||||||
|
//this way this separate source file can be compiled by it's own
|
||||||
|
//and has no access to any of our data except the one that we
|
||||||
|
//give as a parameter to the page function
|
||||||
|
extern PageDescription registerPageSystem;
|
||||||
|
//we add the variable to our list
|
||||||
|
list.add(®isterPageSystem);
|
||||||
|
extern PageDescription registerPageOneValue;
|
||||||
|
list.add(®isterPageOneValue);
|
||||||
|
extern PageDescription registerPageTwoValues;
|
||||||
|
list.add(®isterPageTwoValues);
|
||||||
|
extern PageDescription registerPageThreeValues;
|
||||||
|
list.add(®isterPageThreeValues);
|
||||||
|
extern PageDescription registerPageSixValues;
|
||||||
|
list.add(®isterPageSixValues);
|
||||||
|
extern PageDescription registerPageFourValues;
|
||||||
|
list.add(®isterPageFourValues);
|
||||||
|
extern PageDescription registerPageFourValues2;
|
||||||
|
list.add(®isterPageFourValues2);
|
||||||
|
extern PageDescription registerPageWind;
|
||||||
|
list.add(®isterPageWind);
|
||||||
|
extern PageDescription registerPageWindRose;
|
||||||
|
list.add(®isterPageWindRose);
|
||||||
|
extern PageDescription registerPageWindRoseFlex;
|
||||||
|
list.add(®isterPageWindRoseFlex); //
|
||||||
|
extern PageDescription registerPageVoltage;
|
||||||
|
list.add(®isterPageVoltage);
|
||||||
|
extern PageDescription registerPageDST810;
|
||||||
|
list.add(®isterPageDST810);
|
||||||
|
extern PageDescription registerPageClock;
|
||||||
|
list.add(®isterPageClock);
|
||||||
|
extern PageDescription registerPageWhite;
|
||||||
|
list.add(®isterPageWhite);
|
||||||
|
extern PageDescription registerPageBME280;
|
||||||
|
list.add(®isterPageBME280);
|
||||||
|
extern PageDescription registerPageRudderPosition;
|
||||||
|
list.add(®isterPageRudderPosition);
|
||||||
|
extern PageDescription registerPageKeelPosition;
|
||||||
|
list.add(®isterPageKeelPosition);
|
||||||
|
extern PageDescription registerPageBattery;
|
||||||
|
list.add(®isterPageBattery);
|
||||||
|
extern PageDescription registerPageBattery2;
|
||||||
|
list.add(®isterPageBattery2);
|
||||||
|
extern PageDescription registerPageRollPitch;
|
||||||
|
list.add(®isterPageRollPitch);
|
||||||
|
extern PageDescription registerPageSolar;
|
||||||
|
list.add(®isterPageSolar);
|
||||||
|
extern PageDescription registerPageGenerator;
|
||||||
|
list.add(®isterPageGenerator);
|
||||||
|
extern PageDescription registerPageXTETrack;
|
||||||
|
list.add(®isterPageXTETrack);
|
||||||
|
extern PageDescription registerPageFluid;
|
||||||
|
list.add(®isterPageFluid);
|
||||||
|
extern PageDescription registerPageCompass;
|
||||||
|
list.add(®isterPageCompass);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Undervoltage detection for shutdown display
|
||||||
|
void underVoltageDetection(GwApi *api, CommonData &common){
|
||||||
|
// Read settings
|
||||||
|
double voffset = (api->getConfig()->getConfigItem(api->getConfig()->vOffset,true)->asString()).toFloat();
|
||||||
|
double vslope = (api->getConfig()->getConfigItem(api->getConfig()->vSlope,true)->asString()).toFloat();
|
||||||
|
// Read supply voltage
|
||||||
|
#if defined VOLTAGE_SENSOR && defined LIPO_ACCU_1200
|
||||||
|
float actVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.53) * 2; // Vin = 1/2 for OBP40
|
||||||
|
float minVoltage = 3.65; // Absolut minimum volatge for 3,7V LiPo accu
|
||||||
|
#else
|
||||||
|
float actVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20 for OBP60
|
||||||
|
float minVoltage = MIN_VOLTAGE;
|
||||||
|
#endif
|
||||||
|
double calVoltage = actVoltage * vslope + voffset; // Calibration
|
||||||
|
if(calVoltage < minVoltage){
|
||||||
|
#if defined VOLTAGE_SENSOR && defined LIPO_ACCU_1200
|
||||||
|
// Switch off all power lines
|
||||||
|
setPortPin(OBP_BACKLIGHT_LED, false); // Backlight Off
|
||||||
|
setFlashLED(false); // Flash LED Off
|
||||||
|
buzzer(TONE4, 20); // Buzzer tone 4kHz 20ms
|
||||||
|
// Shutdown EInk display
|
||||||
|
getdisplay().setFullWindow(); // Set full Refresh
|
||||||
|
//getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||||
|
getdisplay().fillScreen(common.bgcolor);// Clear screen
|
||||||
|
getdisplay().setTextColor(common.fgcolor);
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold20pt7b);
|
||||||
|
getdisplay().setCursor(65, 150);
|
||||||
|
getdisplay().print("Undervoltage");
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||||
|
getdisplay().setCursor(65, 175);
|
||||||
|
getdisplay().print("Charge battery and restart system");
|
||||||
|
getdisplay().nextPage(); // Partial update
|
||||||
|
getdisplay().powerOff(); // Display power off
|
||||||
|
setPortPin(OBP_POWER_EPD, false); // Power off ePaper display
|
||||||
|
setPortPin(OBP_POWER_SD, false); // Power off SD card
|
||||||
|
#else
|
||||||
|
// Switch off all power lines
|
||||||
|
setPortPin(OBP_BACKLIGHT_LED, false); // Backlight Off
|
||||||
|
setFlashLED(false); // Flash LED Off
|
||||||
|
buzzer(TONE4, 20); // Buzzer tone 4kHz 20ms
|
||||||
|
setPortPin(OBP_POWER_50, false); // Power rail 5.0V Off
|
||||||
|
// Shutdown EInk display
|
||||||
|
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||||
|
getdisplay().fillScreen(common.bgcolor);// Clear screen
|
||||||
|
getdisplay().setTextColor(common.fgcolor);
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold20pt7b);
|
||||||
|
getdisplay().setCursor(65, 150);
|
||||||
|
getdisplay().print("Undervoltage");
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||||
|
getdisplay().setCursor(65, 175);
|
||||||
|
getdisplay().print("To wake up repower system");
|
||||||
|
getdisplay().nextPage(); // Partial update
|
||||||
|
getdisplay().powerOff(); // Display power off
|
||||||
|
#endif
|
||||||
|
// Stop system
|
||||||
|
while(true){
|
||||||
|
esp_deep_sleep_start(); // Deep Sleep without weakup. Weakup only after power cycle (restart).
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OBP60 Task
|
||||||
|
//####################################################################################
|
||||||
|
void OBP60Task(GwApi *api){
|
||||||
|
// vTaskDelete(NULL);
|
||||||
|
// return;
|
||||||
|
GwLog *logger=api->getLogger();
|
||||||
|
GwConfigHandler *config=api->getConfig();
|
||||||
|
#ifdef HARDWARE_V21
|
||||||
|
startLedTask(api);
|
||||||
|
#endif
|
||||||
|
PageList allPages;
|
||||||
|
registerAllPages(allPages);
|
||||||
|
CommonData commonData;
|
||||||
|
commonData.logger=logger;
|
||||||
|
commonData.config=config;
|
||||||
|
|
||||||
|
#ifdef HARDWARE_V21
|
||||||
|
// Keyboard coordinates for page footer
|
||||||
|
initKeys(commonData);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tN2kMsg N2kMsg;
|
||||||
|
|
||||||
|
LOG_DEBUG(GwLog::LOG,"obp60task started");
|
||||||
|
for (auto it=allPages.pages.begin();it != allPages.pages.end();it++){
|
||||||
|
LOG_DEBUG(GwLog::LOG,"found registered page %s",(*it)->pageName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init E-Ink display
|
||||||
|
String displaymode = api->getConfig()->getConfigItem(api->getConfig()->display,true)->asString();
|
||||||
|
String displaycolor = api->getConfig()->getConfigItem(api->getConfig()->displaycolor,true)->asString();
|
||||||
|
if (displaycolor == "Normal") {
|
||||||
|
commonData.fgcolor = GxEPD_BLACK;
|
||||||
|
commonData.bgcolor = GxEPD_WHITE;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
commonData.fgcolor = GxEPD_WHITE;
|
||||||
|
commonData.bgcolor = GxEPD_BLACK;
|
||||||
|
}
|
||||||
|
String systemname = api->getConfig()->getConfigItem(api->getConfig()->systemName,true)->asString();
|
||||||
|
String wifipass = api->getConfig()->getConfigItem(api->getConfig()->apPassword,true)->asString();
|
||||||
|
bool refreshmode = api->getConfig()->getConfigItem(api->getConfig()->refresh,true)->asBoolean();
|
||||||
|
String fastrefresh = api->getConfig()->getConfigItem(api->getConfig()->fastRefresh,true)->asString();
|
||||||
|
uint fullrefreshtime = uint(api->getConfig()->getConfigItem(api->getConfig()->fullRefreshTime,true)->asInt());
|
||||||
|
#ifdef BOARD_OBP40S3
|
||||||
|
bool syspage_enabled = config->getBool(config->systemPage);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DISPLAY_GDEY042T81
|
||||||
|
getdisplay().init(115200, true, 2, false); // Use this for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||||
|
#else
|
||||||
|
getdisplay().init(115200); // Init for normal displays
|
||||||
|
#endif
|
||||||
|
|
||||||
|
getdisplay().setRotation(0); // Set display orientation (horizontal)
|
||||||
|
getdisplay().setFullWindow(); // Set full Refresh
|
||||||
|
getdisplay().firstPage(); // set first page
|
||||||
|
getdisplay().fillScreen(commonData.bgcolor);
|
||||||
|
getdisplay().setTextColor(commonData.fgcolor);
|
||||||
|
getdisplay().nextPage(); // Full Refresh
|
||||||
|
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||||
|
getdisplay().fillScreen(commonData.bgcolor);
|
||||||
|
getdisplay().nextPage(); // Fast Refresh
|
||||||
|
getdisplay().nextPage(); // Fast Refresh
|
||||||
|
if(String(displaymode) == "Logo + QR Code" || String(displaymode) == "Logo"){
|
||||||
|
getdisplay().fillScreen(commonData.bgcolor);
|
||||||
|
getdisplay().drawBitmap(0, 0, gImage_Logo_OBP_400x300_sw, getdisplay().width(), getdisplay().height(), commonData.fgcolor); // Draw start logo
|
||||||
|
getdisplay().nextPage(); // Fast Refresh
|
||||||
|
getdisplay().nextPage(); // Fast Refresh
|
||||||
|
delay(SHOW_TIME); // Logo show time
|
||||||
|
if(String(displaymode) == "Logo + QR Code"){
|
||||||
|
getdisplay().fillScreen(commonData.bgcolor);
|
||||||
|
qrWiFi(systemname, wifipass, commonData.fgcolor, commonData.bgcolor); // Show QR code for WiFi connection
|
||||||
|
getdisplay().nextPage(); // Fast Refresh
|
||||||
|
getdisplay().nextPage(); // Fast Refresh
|
||||||
|
delay(SHOW_TIME); // QR code show time
|
||||||
|
}
|
||||||
|
getdisplay().fillScreen(commonData.bgcolor);
|
||||||
|
getdisplay().nextPage(); // Fast Refresh
|
||||||
|
getdisplay().nextPage(); // Fast Refresh
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init pages
|
||||||
|
int numPages=1;
|
||||||
|
PageStruct pages[MAX_PAGE_NUMBER];
|
||||||
|
// Set start page
|
||||||
|
int pageNumber = int(api->getConfig()->getConfigItem(api->getConfig()->startPage,true)->asInt()) - 1;
|
||||||
|
|
||||||
|
LOG_DEBUG(GwLog::LOG,"Checking wakeup...");
|
||||||
|
#ifdef BOARD_OBP60S3
|
||||||
|
if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_TOUCHPAD) {
|
||||||
|
LOG_DEBUG(GwLog::LOG,"Wake up by touch pad %d",esp_sleep_get_touchpad_wakeup_status());
|
||||||
|
pageNumber = getLastPage();
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG(GwLog::LOG,"Other wakeup reason");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef BOARD_OBP40S3
|
||||||
|
if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_EXT0) {
|
||||||
|
LOG_DEBUG(GwLog::LOG,"Wake up by key");
|
||||||
|
pageNumber = getLastPage();
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG(GwLog::LOG,"Other wakeup reason");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
LOG_DEBUG(GwLog::LOG,"...done");
|
||||||
|
|
||||||
|
int lastPage=pageNumber;
|
||||||
|
|
||||||
|
BoatValueList boatValues; //all the boat values for the api query
|
||||||
|
//commonData.distanceformat=config->getString(xxx);
|
||||||
|
//add all necessary data to common data
|
||||||
|
|
||||||
|
//fill the page data from config
|
||||||
|
numPages=config->getInt(config->visiblePages,1);
|
||||||
|
if (numPages < 1) numPages=1;
|
||||||
|
if (numPages >= MAX_PAGE_NUMBER) numPages=MAX_PAGE_NUMBER;
|
||||||
|
LOG_DEBUG(GwLog::LOG,"Number of pages %d",numPages);
|
||||||
|
String configPrefix="page";
|
||||||
|
for (int i=0;i< numPages;i++){
|
||||||
|
String prefix=configPrefix+String(i+1); //e.g. page1
|
||||||
|
String configName=prefix+String("type");
|
||||||
|
LOG_DEBUG(GwLog::DEBUG,"asking for page config %s",configName.c_str());
|
||||||
|
String pageType=config->getString(configName,"");
|
||||||
|
PageDescription *description=allPages.find(pageType);
|
||||||
|
if (description == NULL){
|
||||||
|
LOG_DEBUG(GwLog::ERROR,"page description for %s not found",pageType.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pages[i].description=description;
|
||||||
|
pages[i].page=description->creator(commonData);
|
||||||
|
pages[i].parameters.pageName=pageType;
|
||||||
|
pages[i].parameters.pageNumber = i + 1;
|
||||||
|
LOG_DEBUG(GwLog::DEBUG,"found page %s for number %d",pageType.c_str(),i);
|
||||||
|
//fill in all the user defined parameters
|
||||||
|
for (int uid=0;uid<description->userParam;uid++){
|
||||||
|
String cfgName=prefix+String("value")+String(uid+1);
|
||||||
|
GwApi::BoatValue *value=boatValues.findValueOrCreate(config->getString(cfgName,""));
|
||||||
|
LOG_DEBUG(GwLog::DEBUG,"add user input cfg=%s,value=%s for page %d",
|
||||||
|
cfgName.c_str(),
|
||||||
|
value->getName().c_str(),
|
||||||
|
i
|
||||||
|
);
|
||||||
|
pages[i].parameters.values.push_back(value);
|
||||||
|
}
|
||||||
|
//now add the predefined values
|
||||||
|
for (auto it=description->fixedParam.begin();it != description->fixedParam.end();it++){
|
||||||
|
GwApi::BoatValue *value=boatValues.findValueOrCreate(*it);
|
||||||
|
LOG_DEBUG(GwLog::DEBUG,"added fixed value %s to page %d",value->getName().c_str(),i);
|
||||||
|
pages[i].parameters.values.push_back(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add out of band system page (always available)
|
||||||
|
Page *syspage = allPages.pages[0]->creator(commonData);
|
||||||
|
|
||||||
|
// Display screenshot handler for HTTP request
|
||||||
|
// http://192.168.15.1/api/user/OBP60Task/screenshot
|
||||||
|
api->registerRequestHandler("screenshot", [api, &pageNumber, pages](AsyncWebServerRequest *request) {
|
||||||
|
doImageRequest(api, &pageNumber, pages, request);
|
||||||
|
});
|
||||||
|
|
||||||
|
//now we have prepared the page data
|
||||||
|
//we start a separate task that will fetch our keys...
|
||||||
|
MyData allParameters;
|
||||||
|
allParameters.logger=api->getLogger();
|
||||||
|
allParameters.page0=3;
|
||||||
|
allParameters.queue=xQueueCreate(10,sizeof(int));
|
||||||
|
allParameters.sensitivity= api->getConfig()->getInt(GwConfigDefinitions::tSensitivity);
|
||||||
|
#ifdef BOARD_OBP40S3
|
||||||
|
allParameters.use_syspage = syspage_enabled;
|
||||||
|
#endif
|
||||||
|
xTaskCreate(keyboardTask,"keyboard",2000,&allParameters,configMAX_PRIORITIES-1,NULL);
|
||||||
|
SharedData *shared=new SharedData(api);
|
||||||
|
createSensorTask(shared);
|
||||||
|
|
||||||
|
// Task Loop
|
||||||
|
//####################################################################################
|
||||||
|
|
||||||
|
// Configuration values for main loop
|
||||||
|
String gpsFix = api->getConfig()->getConfigItem(api->getConfig()->flashLED,true)->asString();
|
||||||
|
String gpsOn=api->getConfig()->getConfigItem(api->getConfig()->useGPS,true)->asString();
|
||||||
|
float tz = api->getConfig()->getConfigItem(api->getConfig()->timeZone,true)->asFloat();
|
||||||
|
|
||||||
|
commonData.backlight.mode = backlightMapping(config->getConfigItem(config->backlight,true)->asString());
|
||||||
|
commonData.backlight.color = colorMapping(config->getConfigItem(config->blColor,true)->asString());
|
||||||
|
commonData.backlight.brightness = 2.55 * uint(config->getConfigItem(config->blBrightness,true)->asInt());
|
||||||
|
commonData.powermode = api->getConfig()->getConfigItem(api->getConfig()->powerMode,true)->asString();
|
||||||
|
|
||||||
|
bool uvoltage = api->getConfig()->getConfigItem(api->getConfig()->underVoltage,true)->asBoolean();
|
||||||
|
String cpuspeed = api->getConfig()->getConfigItem(api->getConfig()->cpuSpeed,true)->asString();
|
||||||
|
uint hdopAccuracy = uint(api->getConfig()->getConfigItem(api->getConfig()->hdopAccuracy,true)->asInt());
|
||||||
|
|
||||||
|
double homelat = commonData.config->getString(commonData.config->homeLAT).toDouble();
|
||||||
|
double homelon = commonData.config->getString(commonData.config->homeLON).toDouble();
|
||||||
|
bool homevalid = homelat >= -180.0 and homelat <= 180 and homelon >= -90.0 and homelon <= 90.0;
|
||||||
|
if (homevalid) {
|
||||||
|
LOG_DEBUG(GwLog::LOG, "Home location set to %f : %f", homelat, homelon);
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG(GwLog::LOG, "No valid home location found");
|
||||||
|
}
|
||||||
|
|
||||||
|
// refreshmode defined in init section
|
||||||
|
|
||||||
|
// Boat values for main loop
|
||||||
|
GwApi::BoatValue *date = boatValues.findValueOrCreate("GPSD"); // Load GpsDate
|
||||||
|
GwApi::BoatValue *time = boatValues.findValueOrCreate("GPST"); // Load GpsTime
|
||||||
|
GwApi::BoatValue *lat = boatValues.findValueOrCreate("LAT"); // Load GpsLatitude
|
||||||
|
GwApi::BoatValue *lon = boatValues.findValueOrCreate("LON"); // Load GpsLongitude
|
||||||
|
GwApi::BoatValue *hdop = boatValues.findValueOrCreate("HDOP"); // Load GpsHDOP
|
||||||
|
|
||||||
|
LOG_DEBUG(GwLog::LOG,"obp60task: start mainloop");
|
||||||
|
|
||||||
|
commonData.time = boatValues.findValueOrCreate("GPST"); // Load GpsTime
|
||||||
|
commonData.date = boatValues.findValueOrCreate("GPSD"); // Load GpsTime
|
||||||
|
bool delayedDisplayUpdate = false; // If select a new pages then make a delayed full display update
|
||||||
|
bool cpuspeedsetted = false; // Marker for change CPU speed
|
||||||
|
long firststart = millis(); // First start
|
||||||
|
long starttime0 = millis(); // Mainloop
|
||||||
|
long starttime1 = millis(); // Full display refresh for the first 5 min (more often as normal)
|
||||||
|
long starttime2 = millis(); // Full display refresh after 5 min
|
||||||
|
long starttime3 = millis(); // Display update all 1s
|
||||||
|
long starttime4 = millis(); // Delayed display update after 4s when select a new page
|
||||||
|
long starttime5 = millis(); // Calculate sunrise and sunset all 1s
|
||||||
|
|
||||||
|
pages[pageNumber].page->setupKeys(); // Initialize keys for first page
|
||||||
|
|
||||||
|
// Main loop runs with 100ms
|
||||||
|
//####################################################################################
|
||||||
|
|
||||||
|
bool systemPage = false;
|
||||||
|
Page *currentPage;
|
||||||
|
while (true){
|
||||||
|
delay(100); // Delay 100ms (loop time)
|
||||||
|
bool keypressed = false;
|
||||||
|
|
||||||
|
// Undervoltage detection
|
||||||
|
if(uvoltage == true){
|
||||||
|
underVoltageDetection(api, commonData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set CPU speed after boot after 1min
|
||||||
|
if(millis() > firststart + (1 * 60 * 1000) && cpuspeedsetted == false){
|
||||||
|
if(String(cpuspeed) == "80"){
|
||||||
|
setCpuFrequencyMhz(80);
|
||||||
|
}
|
||||||
|
if(String(cpuspeed) == "160"){
|
||||||
|
setCpuFrequencyMhz(160);
|
||||||
|
}
|
||||||
|
if(String(cpuspeed) == "240"){
|
||||||
|
setCpuFrequencyMhz(240);
|
||||||
|
}
|
||||||
|
int freq = getCpuFrequencyMhz();
|
||||||
|
api->getLogger()->logDebug(GwLog::LOG,"CPU speed: %i MHz", freq);
|
||||||
|
cpuspeedsetted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(millis() > starttime0 + 100){
|
||||||
|
starttime0 = millis();
|
||||||
|
commonData.data=shared->getSensorData();
|
||||||
|
commonData.data.actpage = pageNumber + 1;
|
||||||
|
commonData.data.maxpage = numPages;
|
||||||
|
|
||||||
|
// If GPS fix then LED off (HDOP)
|
||||||
|
if(String(gpsFix) == "GPS Fix Lost" && hdop->value <= hdopAccuracy && hdop->valid == true){
|
||||||
|
setFlashLED(false);
|
||||||
|
}
|
||||||
|
// If missing GPS fix then LED on
|
||||||
|
if((String(gpsFix) == "GPS Fix Lost" && hdop->value > hdopAccuracy && hdop->valid == true) || (String(gpsFix) == "GPS Fix Lost" && hdop->valid == false)){
|
||||||
|
setFlashLED(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the keyboard message
|
||||||
|
int keyboardMessage=0;
|
||||||
|
while (xQueueReceive(allParameters.queue,&keyboardMessage,0)){
|
||||||
|
LOG_DEBUG(GwLog::LOG,"new key from keyboard %d",keyboardMessage);
|
||||||
|
keypressed = true;
|
||||||
|
|
||||||
|
if (keyboardMessage == 12 and !systemPage) {
|
||||||
|
LOG_DEBUG(GwLog::LOG, "Calling system page");
|
||||||
|
systemPage = true; // System page is out of band
|
||||||
|
syspage->setupKeys();
|
||||||
|
keyboardMessage = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
currentPage = pages[pageNumber].page;
|
||||||
|
if (systemPage && keyboardMessage == 1) {
|
||||||
|
// exit system mode with exit key number 1
|
||||||
|
systemPage = false;
|
||||||
|
currentPage->setupKeys();
|
||||||
|
keyboardMessage = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (systemPage) {
|
||||||
|
keyboardMessage = syspage->handleKey(keyboardMessage);
|
||||||
|
} else if (currentPage) {
|
||||||
|
keyboardMessage = currentPage->handleKey(keyboardMessage);
|
||||||
|
}
|
||||||
|
if (keyboardMessage > 0) // not handled by page
|
||||||
|
{
|
||||||
|
// Decoding all key codes
|
||||||
|
// #6 Backlight on if key controled
|
||||||
|
if (commonData.backlight.mode == BacklightMode::KEY) {
|
||||||
|
// if(String(backlight) == "Control by Key"){
|
||||||
|
if(keyboardMessage == 6){
|
||||||
|
LOG_DEBUG(GwLog::LOG,"Toggle Backlight LED");
|
||||||
|
toggleBacklightLED(commonData.backlight.brightness, commonData.backlight.color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef BOARD_OBP40S3
|
||||||
|
// #3 Deep sleep mode for OBP40
|
||||||
|
if ((keyboardMessage == 3) and !syspage_enabled){
|
||||||
|
deepSleep(commonData);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// #9 Swipe right or #4 key right
|
||||||
|
if ((keyboardMessage == 9) or (keyboardMessage == 4))
|
||||||
|
{
|
||||||
|
pageNumber++;
|
||||||
|
if (pageNumber >= numPages){
|
||||||
|
pageNumber = 0;
|
||||||
|
}
|
||||||
|
commonData.data.actpage = pageNumber + 1;
|
||||||
|
commonData.data.maxpage = numPages;
|
||||||
|
}
|
||||||
|
// #10 Swipe left or #3 key left
|
||||||
|
if ((keyboardMessage == 10) or (keyboardMessage == 3))
|
||||||
|
{
|
||||||
|
pageNumber--;
|
||||||
|
if (pageNumber < 0){
|
||||||
|
pageNumber = numPages - 1;
|
||||||
|
}
|
||||||
|
commonData.data.actpage = pageNumber + 1;
|
||||||
|
commonData.data.maxpage = numPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #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)){
|
||||||
|
starttime4 = millis();
|
||||||
|
starttime2 = millis(); // Reset the timer for full display update
|
||||||
|
delayedDisplayUpdate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG_DEBUG(GwLog::LOG,"set pagenumber to %d",pageNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate sunrise, sunset and backlight control with sun status all 1s
|
||||||
|
if(millis() > starttime5 + 1000){
|
||||||
|
starttime5 = millis();
|
||||||
|
if(time->valid == true && date->valid == true && lat->valid == true && lon->valid == true){
|
||||||
|
// Provide sundata to all pages
|
||||||
|
commonData.sundata = calcSunsetSunrise(time->value , date->value, lat->value, lon->value, tz);
|
||||||
|
// Backlight with sun control
|
||||||
|
if (commonData.backlight.mode == BacklightMode::SUN) {
|
||||||
|
// if(String(backlight) == "Control by Sun"){
|
||||||
|
if(commonData.sundata.sunDown == true){
|
||||||
|
setBacklightLED(commonData.backlight.brightness, commonData.backlight.color);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
setBacklightLED(0, COLOR_BLUE); // Backlight LEDs off (blue without britghness)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (homevalid and commonData.data.rtcValid) {
|
||||||
|
// No gps fix but valid home location and time configured
|
||||||
|
commonData.sundata = calcSunsetSunriseRTC(&commonData.data.rtcTime, homelat, homelon, tz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Full display update afer a new selected page and 4s wait time
|
||||||
|
if(millis() > starttime4 + 4000 && delayedDisplayUpdate == true){
|
||||||
|
starttime1 = millis();
|
||||||
|
starttime2 = millis();
|
||||||
|
getdisplay().setFullWindow(); // Set full update
|
||||||
|
getdisplay().nextPage();
|
||||||
|
if(fastrefresh == "false"){
|
||||||
|
getdisplay().fillScreen(commonData.fgcolor); // Clear display
|
||||||
|
getdisplay().nextPage(); // Full update
|
||||||
|
getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||||
|
getdisplay().nextPage(); // Full update
|
||||||
|
}
|
||||||
|
delayedDisplayUpdate = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtask E-Ink full refresh all 1 min for the first 5 min after power on or restart
|
||||||
|
// This needs for a better display contrast after power on in cold or warm environments
|
||||||
|
if(millis() < firststart + (5 * 60 * 1000) && millis() > starttime1 + (60 * 1000)){
|
||||||
|
starttime1 = millis();
|
||||||
|
starttime2 = millis();
|
||||||
|
LOG_DEBUG(GwLog::DEBUG,"E-Ink full refresh first 5 min");
|
||||||
|
getdisplay().setFullWindow(); // Set full update
|
||||||
|
getdisplay().nextPage();
|
||||||
|
if(fastrefresh == "false"){
|
||||||
|
getdisplay().fillScreen(commonData.fgcolor); // Clear display
|
||||||
|
getdisplay().nextPage(); // Full update
|
||||||
|
getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||||
|
getdisplay().nextPage(); // Full update
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtask E-Ink full refresh
|
||||||
|
if(millis() > starttime2 + fullrefreshtime * 60 * 1000){
|
||||||
|
starttime2 = millis();
|
||||||
|
LOG_DEBUG(GwLog::DEBUG,"E-Ink full refresh");
|
||||||
|
getdisplay().setFullWindow(); // Set full update
|
||||||
|
getdisplay().nextPage();
|
||||||
|
if(fastrefresh == "false"){
|
||||||
|
getdisplay().fillScreen(commonData.fgcolor); // Clear display
|
||||||
|
getdisplay().nextPage(); // Full update
|
||||||
|
getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||||
|
getdisplay().nextPage(); // Full update
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh display data, default all 1s
|
||||||
|
currentPage = pages[pageNumber].page;
|
||||||
|
int pagetime = 1000;
|
||||||
|
if ((lastPage == pageNumber) and (!keypressed)) {
|
||||||
|
// same page we use page defined time
|
||||||
|
pagetime = currentPage->refreshtime;
|
||||||
|
}
|
||||||
|
if(millis() > starttime3 + pagetime){
|
||||||
|
LOG_DEBUG(GwLog::DEBUG,"Page with refreshtime=%d", pagetime);
|
||||||
|
starttime3 = millis();
|
||||||
|
|
||||||
|
//refresh data from api
|
||||||
|
api->getBoatDataValues(boatValues.numValues,boatValues.allBoatValues);
|
||||||
|
api->getStatus(commonData.status);
|
||||||
|
|
||||||
|
// Clear display
|
||||||
|
// getdisplay().fillRect(0, 0, getdisplay().width(), getdisplay().height(), commonData.bgcolor);
|
||||||
|
getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||||
|
|
||||||
|
// Show header if enabled
|
||||||
|
if (pages[pageNumber].description && pages[pageNumber].description->header or systemPage){
|
||||||
|
// build header using commonData
|
||||||
|
displayHeader(commonData, date, time, hdop); // Show page header
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the particular page
|
||||||
|
if (systemPage) {
|
||||||
|
displayFooter(commonData);
|
||||||
|
PageData sysparams; // empty
|
||||||
|
syspage->displayPage(sysparams);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (currentPage == NULL){
|
||||||
|
LOG_DEBUG(GwLog::ERROR,"page number %d not found", pageNumber);
|
||||||
|
// Error handling for missing page
|
||||||
|
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||||
|
getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||||
|
getdisplay().drawXBitmap(200 - unknown_width / 2, 150 - unknown_height / 2, unknown_bits, unknown_width, unknown_height, commonData.fgcolor);
|
||||||
|
getdisplay().setCursor(140, 250);
|
||||||
|
getdisplay().setFont(&Atari16px);
|
||||||
|
getdisplay().print("Here be dragons!");
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (lastPage != pageNumber){
|
||||||
|
if (hasFRAM) fram.write(FRAM_PAGE_NO, pageNumber); // remember page for device restart
|
||||||
|
currentPage->setupKeys();
|
||||||
|
currentPage->displayNew(pages[pageNumber].parameters);
|
||||||
|
lastPage=pageNumber;
|
||||||
|
}
|
||||||
|
//call the page code
|
||||||
|
LOG_DEBUG(GwLog::DEBUG,"calling page %d",pageNumber);
|
||||||
|
// Show footer if enabled (together with header)
|
||||||
|
if (pages[pageNumber].description && pages[pageNumber].description->header){
|
||||||
|
displayFooter(commonData);
|
||||||
|
}
|
||||||
|
currentPage->displayPage(pages[pageNumber].parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} // refresh display all 1s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue