1
0
mirror of https://github.com/thooge/esp32-nmea2000-obp60.git synced 2025-12-28 13:13:07 +01:00

18 Commits

Author SHA1 Message Date
39966098cc Switched obp60task.cpp to epd pointer 2025-08-04 21:25:01 +02:00
11a061d5a2 Consolidating development hints in README file 2025-08-04 21:13:40 +02:00
4600cb7228 Start switching from getdisplay to epd pointer 2025-08-04 20:57:50 +02:00
e89d1ac62e Merge branch 'clock' into extended 2025-08-04 15:35:13 +02:00
6fb5e01969 Preparation for new anchor page 2025-08-04 15:28:49 +02:00
5c731bc662 Fixed config.json 2025-08-04 14:36:41 +02:00
25c2742f5b Merge branch 'symbols' into extended 2025-08-04 14:14:27 +02:00
6479c7d711 Fixed SkyView: return value needed, enabled for OBP40 2025-08-04 13:47:50 +02:00
e287bfa72e Merge branch 'skyview' into extended 2025-08-04 13:16:57 +02:00
5a652e2c19 Merge branch 'precision' into extended 2025-08-04 12:58:42 +02:00
5081f3a684 Merge branch 'scripts' into extended 2025-08-04 12:57:57 +02:00
7de226b447 Merge branch 'system' into extended 2025-08-04 12:39:54 +02:00
f6e2fa7806 Mark extended firmware and prepare for getdisplay() replacement 2025-08-04 12:37:50 +02:00
28a7e58e27 Automate gen_set.py with page detection and command line parameters 2025-08-01 11:01:23 +02:00
eb51092b23 Added config option for display precision and formatter code improvements 2025-07-31 12:31:57 +02:00
08cd2ad4b1 Some work on page clock concerning default time source 2025-07-09 15:07:52 +02:00
b50d82eff0 Header switcheable between text and symbol view, symbols added 2025-02-06 17:51:26 +01:00
6ae4e195d6 First template for sky view page 2025-01-21 20:48:43 +01:00
18 changed files with 1533 additions and 607 deletions

View File

@@ -501,7 +501,7 @@ def prebuild(env):
genereateUserTasks(os.path.join(outPath(), TASK_INCLUDE)) genereateUserTasks(os.path.join(outPath(), TASK_INCLUDE))
generateFile(os.path.join(basePath(),XDR_FILE),os.path.join(outPath(),XDR_INCLUDE),generateXdrMappings) generateFile(os.path.join(basePath(),XDR_FILE),os.path.join(outPath(),XDR_INCLUDE),generateXdrMappings)
generateFile(os.path.join(basePath(),GROVE_CONFIG_IN),os.path.join(outPath(),GROVE_CONFIG),generateGroveDefs,inMode='r') generateFile(os.path.join(basePath(),GROVE_CONFIG_IN),os.path.join(outPath(),GROVE_CONFIG),generateGroveDefs,inMode='r')
version="dev"+datetime.now().strftime("%Y%m%d") version = "dev{}{}".format(datetime.now().strftime("%Y%m%d"), "-ext")
env.Append(CPPDEFINES=[('GWDEVVERSION',version)]) env.Append(CPPDEFINES=[('GWDEVVERSION',version)])
def cleangenerated(source, target, env): def cleangenerated(source, target, env):

View File

@@ -1,6 +0,0 @@
Craete new page for OBP60
1. Create page under /lib/obp60task/PageXXXX.cpp
2. Set page name in PageXXXX.cpp on file name
3. Register new page in /lib/obp60task/obp60task.cpp line 242 (registerAllPages)
4. Add new page in /lib/obp60task/config.json for each page type or add new page to gen_set.py and run it to auto-generate the relevant section of config.json

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3 #if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include <Arduino.h> #include <Arduino.h>
@@ -33,28 +34,32 @@
// Set display type and SPI pins for display // Set display type and SPI pins for display
GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST, OBP_SPI_BUSY)); // GDEW042T2 400x300, UC8176 (IL0398) GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST, OBP_SPI_BUSY)); // GDEW042T2 400x300, UC8176 (IL0398)
// Export display in new funktion // Export display in new funktion
GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> & getdisplay(){return display;} GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> & getdisplay(){return display;} // DEPRECATED
gxepd2display *epd = &display;
#endif #endif
#ifdef DISPLAY_GDEY042T81 #ifdef DISPLAY_GDEY042T81
// Set display type and SPI pins for display // Set display type and SPI pins for display
GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> display(GxEPD2_420_GDEY042T81(OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST, OBP_SPI_BUSY)); // GDEW042T2 400x300, UC8176 (IL0398) GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> display(GxEPD2_420_GDEY042T81(OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST, OBP_SPI_BUSY)); // GDEW042T2 400x300, UC8176 (IL0398)
// Export display in new funktion // Export display in new funktion
GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> & getdisplay(){return display;} GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> & getdisplay(){return display;} // DEPRECATED
gxepd2display *epd = &display;
#endif #endif
#ifdef DISPLAY_GYE042A87 #ifdef DISPLAY_GYE042A87
// Set display type and SPI pins for display // Set display type and SPI pins for display
GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> display(GxEPD2_420_GYE042A87(OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST, OBP_SPI_BUSY)); // GDEW042T2 400x300, UC8176 (IL0398) GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> display(GxEPD2_420_GYE042A87(OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST, OBP_SPI_BUSY)); // GDEW042T2 400x300, UC8176 (IL0398)
// Export display in new funktion // Export display in new funktion
GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay(){return display;} GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay(){return display;} // DEPRECATED
gxepd2display *epd = &display;
#endif #endif
#ifdef DISPLAY_SE0420NQ04 #ifdef DISPLAY_SE0420NQ04
// Set display type and SPI pins for display // Set display type and SPI pins for display
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> display(GxEPD2_420_SE0420NQ04(OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST, OBP_SPI_BUSY)); // GDEW042T2 400x300, UC8176 (IL0398) GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> display(GxEPD2_420_SE0420NQ04(OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST, OBP_SPI_BUSY)); // GDEW042T2 400x300, UC8176 (IL0398)
// Export display in new funktion // Export display in new funktion
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay(){return display;} GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay(){return display;} // DEPRECATED
gxepd2display *epd = &display;
#endif #endif
// Horter I2C moduls // Horter I2C moduls
@@ -401,7 +406,7 @@ void displayTrendLow(int16_t x, int16_t y, uint16_t size, uint16_t color){
} }
// Show header informations // Show header informations
void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatValue *time, GwApi::BoatValue *hdop){ void displayHeader(CommonData &commonData, bool symbolmode, GwApi::BoatValue *date, GwApi::BoatValue *time, GwApi::BoatValue *hdop){
static bool heartbeat = false; static bool heartbeat = false;
static unsigned long usbRxOld = 0; static unsigned long usbRxOld = 0;
@@ -415,32 +420,71 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa
static unsigned long n2kRxOld = 0; static unsigned long n2kRxOld = 0;
static unsigned long n2kTxOld = 0; static unsigned long n2kTxOld = 0;
uint16_t symbol_x = 2;
static const uint16_t symbol_offset = 20;
if(commonData.config->getBool(commonData.config->statusLine) == true){ if(commonData.config->getBool(commonData.config->statusLine) == true){
if (symbolmode) {
commonData.logger->logDebug(GwLog::LOG,"Header: Symbolmode");
} else {
commonData.logger->logDebug(GwLog::LOG,"Header: Textmode");
}
// Show status info // Show status info
getdisplay().setTextColor(commonData.fgcolor); getdisplay().setTextColor(commonData.fgcolor);
getdisplay().setFont(&Ubuntu_Bold8pt8b); getdisplay().setFont(&Ubuntu_Bold8pt8b);
getdisplay().setCursor(0, 15); getdisplay().setCursor(0, 15);
if (commonData.status.wifiApOn) { if (commonData.status.wifiApOn) {
if (symbolmode) {
getdisplay().drawXBitmap(symbol_x, 1, iconmap["AP"], icon_width, icon_height, commonData.fgcolor);
symbol_x += symbol_offset;
} else {
getdisplay().print(" AP "); getdisplay().print(" AP ");
} }
}
// If receive new telegram data then display bus name // If receive new telegram data then display bus name
if(commonData.status.tcpClRx != tcpClRxOld || commonData.status.tcpClTx != tcpClTxOld || commonData.status.tcpSerRx != tcpSerRxOld || commonData.status.tcpSerTx != tcpSerTxOld){ if(commonData.status.tcpClRx != tcpClRxOld || commonData.status.tcpClTx != tcpClTxOld || commonData.status.tcpSerRx != tcpSerRxOld || commonData.status.tcpSerTx != tcpSerTxOld){
if (symbolmode) {
getdisplay().drawXBitmap(symbol_x, 1, iconmap["TCP"], icon_width, icon_height, commonData.fgcolor);
symbol_x += symbol_offset;
} else {
getdisplay().print("TCP "); getdisplay().print("TCP ");
} }
}
if(commonData.status.n2kRx != n2kRxOld || commonData.status.n2kTx != n2kTxOld){ if(commonData.status.n2kRx != n2kRxOld || commonData.status.n2kTx != n2kTxOld){
if (symbolmode) {
getdisplay().drawXBitmap(symbol_x, 1, iconmap["N2K"], icon_width, icon_height, commonData.fgcolor);
symbol_x += symbol_offset;
} else {
getdisplay().print("N2K "); getdisplay().print("N2K ");
} }
}
if(commonData.status.serRx != serRxOld || commonData.status.serTx != serTxOld){ if(commonData.status.serRx != serRxOld || commonData.status.serTx != serTxOld){
if (symbolmode) {
getdisplay().drawXBitmap(symbol_x, 1, iconmap["0183"], icon_width, icon_height, commonData.fgcolor);
symbol_x += symbol_offset;
} else {
getdisplay().print("183 "); getdisplay().print("183 ");
} }
}
if(commonData.status.usbRx != usbRxOld || commonData.status.usbTx != usbTxOld){ if(commonData.status.usbRx != usbRxOld || commonData.status.usbTx != usbTxOld){
if (symbolmode) {
getdisplay().drawXBitmap(symbol_x, 1, iconmap["USB"], icon_width, icon_height, commonData.fgcolor);
symbol_x += symbol_offset;
} else {
getdisplay().print("USB "); getdisplay().print("USB ");
} }
}
double gpshdop = formatValue(hdop, commonData).value; double gpshdop = formatValue(hdop, commonData).value;
if(commonData.config->getString(commonData.config->useGPS) != "off" && gpshdop <= commonData.config->getInt(commonData.config->hdopAccuracy) && hdop->valid == true){ if(commonData.config->getString(commonData.config->useGPS) != "off" && gpshdop <= commonData.config->getInt(commonData.config->hdopAccuracy) && hdop->valid == true){
if (symbolmode) {
getdisplay().drawXBitmap(symbol_x, 1, iconmap["GPS"], icon_width, icon_height, commonData.fgcolor);
symbol_x += symbol_offset;
} else {
getdisplay().print("GPS"); getdisplay().print("GPS");
} }
}
// Save old telegram counter // Save old telegram counter
tcpClRxOld = commonData.status.tcpClRx; tcpClRxOld = commonData.status.tcpClRx;
tcpClTxOld = commonData.status.tcpClTx; tcpClTxOld = commonData.status.tcpClTx;
@@ -456,26 +500,26 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa
#ifdef HARDWARE_V21 #ifdef HARDWARE_V21
// Display key lock status // Display key lock status
if (commonData.keylock) { if (commonData.keylock) {
getdisplay().drawXBitmap(170, 1, lock_bits, icon_width, icon_height, commonData.fgcolor); epd->drawXBitmap(170, 1, lock_bits, icon_width, icon_height, commonData.fgcolor);
} else { } else {
getdisplay().drawXBitmap(166, 1, swipe_bits, swipe_width, swipe_height, commonData.fgcolor); epd->drawXBitmap(166, 1, swipe_bits, swipe_width, swipe_height, commonData.fgcolor);
} }
#endif #endif
#ifdef LIPO_ACCU_1200 #ifdef LIPO_ACCU_1200
if (commonData.data.BatteryChargeStatus == 1) { if (commonData.data.BatteryChargeStatus == 1) {
getdisplay().drawXBitmap(170, 1, battery_loading_bits, battery_width, battery_height, commonData.fgcolor); epd->drawXBitmap(170, 1, battery_loading_bits, battery_width, battery_height, commonData.fgcolor);
} else { } else {
#ifdef VOLTAGE_SENSOR #ifdef VOLTAGE_SENSOR
if (commonData.data.batteryLevelLiPo < 10) { if (commonData.data.batteryLevelLiPo < 10) {
getdisplay().drawXBitmap(170, 1, battery_0_bits, battery_width, battery_height, commonData.fgcolor); epd->drawXBitmap(170, 1, battery_0_bits, battery_width, battery_height, commonData.fgcolor);
} else if (commonData.data.batteryLevelLiPo < 25) { } else if (commonData.data.batteryLevelLiPo < 25) {
getdisplay().drawXBitmap(170, 1, battery_25_bits, battery_width, battery_height, commonData.fgcolor); epd->drawXBitmap(170, 1, battery_25_bits, battery_width, battery_height, commonData.fgcolor);
} else if (commonData.data.batteryLevelLiPo < 50) { } else if (commonData.data.batteryLevelLiPo < 50) {
getdisplay().drawXBitmap(170, 1, battery_50_bits, battery_width, battery_height, commonData.fgcolor); epd->drawXBitmap(170, 1, battery_50_bits, battery_width, battery_height, commonData.fgcolor);
} else if (commonData.data.batteryLevelLiPo < 75) { } else if (commonData.data.batteryLevelLiPo < 75) {
getdisplay().drawXBitmap(170, 1, battery_75_bits, battery_width, battery_height, commonData.fgcolor); epd->drawXBitmap(170, 1, battery_75_bits, battery_width, battery_height, commonData.fgcolor);
} else { } else {
getdisplay().drawXBitmap(170, 1, battery_100_bits, battery_width, battery_height, commonData.fgcolor); epd->drawXBitmap(170, 1, battery_100_bits, battery_width, battery_height, commonData.fgcolor);
} }
#endif // VOLTAGE_SENSOR #endif // VOLTAGE_SENSOR
} }
@@ -483,13 +527,13 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa
// Heartbeat as page number // Heartbeat as page number
if (heartbeat) { if (heartbeat) {
getdisplay().setTextColor(commonData.bgcolor); epd->setTextColor(commonData.bgcolor);
getdisplay().fillRect(201, 0, 23, 19, commonData.fgcolor); epd->fillRect(201, 0, 23, 19, commonData.fgcolor);
} else { } else {
getdisplay().setTextColor(commonData.fgcolor); epd->setTextColor(commonData.fgcolor);
getdisplay().drawRect(201, 0, 23, 19, commonData.fgcolor); epd->drawRect(201, 0, 23, 19, commonData.fgcolor);
} }
getdisplay().setFont(&Ubuntu_Bold8pt8b); epd->setFont(&Ubuntu_Bold8pt8b);
drawTextCenter(211, 9, String(commonData.data.actpage)); drawTextCenter(211, 9, String(commonData.data.actpage));
heartbeat = !heartbeat; heartbeat = !heartbeat;
@@ -497,19 +541,19 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa
String fmttype = commonData.config->getString(commonData.config->dateFormat); String fmttype = commonData.config->getString(commonData.config->dateFormat);
String timesource = commonData.config->getString(commonData.config->timeSource); String timesource = commonData.config->getString(commonData.config->timeSource);
double tz = commonData.config->getString(commonData.config->timeZone).toDouble(); double tz = commonData.config->getString(commonData.config->timeZone).toDouble();
getdisplay().setTextColor(commonData.fgcolor); epd->setTextColor(commonData.fgcolor);
getdisplay().setFont(&Ubuntu_Bold8pt8b); epd->setFont(&Ubuntu_Bold8pt8b);
getdisplay().setCursor(230, 15); epd->setCursor(230, 15);
if (timesource == "RTC" or timesource == "iRTC") { if (timesource == "RTC" or timesource == "iRTC") {
// TODO take DST into account // TODO take DST into account
if (commonData.data.rtcValid) { if (commonData.data.rtcValid) {
time_t tv = mktime(&commonData.data.rtcTime) + (int)(tz * 3600); time_t tv = mktime(&commonData.data.rtcTime) + (int)(tz * 3600);
struct tm *local_tm = localtime(&tv); struct tm *local_tm = localtime(&tv);
getdisplay().print(formatTime('m', local_tm->tm_hour, local_tm->tm_min, 0)); epd->print(formatTime('m', local_tm->tm_hour, local_tm->tm_min, 0));
getdisplay().print(" "); epd->print(" ");
getdisplay().print(formatDate(fmttype, local_tm->tm_year + 1900, local_tm->tm_mon + 1, local_tm->tm_mday)); epd->print(formatDate(fmttype, local_tm->tm_year + 1900, local_tm->tm_mon + 1, local_tm->tm_mday));
getdisplay().print(" "); epd->print(" ");
getdisplay().print(tz == 0 ? "UTC" : "LOT"); epd->print(tz == 0 ? "UTC" : "LOT");
} else { } else {
drawTextRalign(396, 15, "RTC invalid"); drawTextRalign(396, 15, "RTC invalid");
} }
@@ -520,15 +564,15 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa
String acttime = formatValue(time, commonData).svalue; String acttime = formatValue(time, commonData).svalue;
acttime = acttime.substring(0, 5); acttime = acttime.substring(0, 5);
String actdate = formatValue(date, commonData).svalue; String actdate = formatValue(date, commonData).svalue;
getdisplay().print(acttime); epd->print(acttime);
getdisplay().print(" "); epd->print(" ");
getdisplay().print(actdate); epd->print(actdate);
getdisplay().print(" "); epd->print(" ");
getdisplay().print(tz == 0 ? "UTC" : "LOT"); epd->print(tz == 0 ? "UTC" : "LOT");
} }
else{ else{
if(commonData.config->getBool(commonData.config->useSimuData) == true){ if(commonData.config->getBool(commonData.config->useSimuData) == true){
getdisplay().print("12:00 01.01.2024 LOT"); epd->print("12:00 01.01.2024 LOT");
} }
else{ else{
drawTextRalign(396, 15, "No GPS data"); drawTextRalign(396, 15, "No GPS data");
@@ -536,15 +580,15 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa
} }
} // timesource == "GPS" } // timesource == "GPS"
else { else {
getdisplay().print("No time source"); epd->print("No time source");
} }
} }
} }
void displayFooter(CommonData &commonData) { void displayFooter(CommonData &commonData) {
getdisplay().setFont(&Atari16px); epd->setFont(&Atari16px);
getdisplay().setTextColor(commonData.fgcolor); epd->setTextColor(commonData.fgcolor);
#ifdef HARDWARE_V21 #ifdef HARDWARE_V21
// Frame around key icon area // Frame around key icon area
@@ -553,14 +597,14 @@ void displayFooter(CommonData &commonData) {
const uint16_t top = 280; const uint16_t top = 280;
const uint16_t bottom = 299; const uint16_t bottom = 299;
// horizontal stub lines // horizontal stub lines
getdisplay().drawLine(commonData.keydata[0].x, top, commonData.keydata[0].x+10, top, commonData.fgcolor); epd->drawLine(commonData.keydata[0].x, top, commonData.keydata[0].x+10, top, commonData.fgcolor);
for (int i = 1; i <= 5; i++) { for (int i = 1; i <= 5; i++) {
getdisplay().drawLine(commonData.keydata[i].x-10, top, commonData.keydata[i].x+10, top, commonData.fgcolor); epd->drawLine(commonData.keydata[i].x-10, top, commonData.keydata[i].x+10, top, commonData.fgcolor);
} }
getdisplay().drawLine(commonData.keydata[5].x + commonData.keydata[5].w - 10, top, commonData.keydata[5].x + commonData.keydata[5].w + 1, top, commonData.fgcolor); epd->drawLine(commonData.keydata[5].x + commonData.keydata[5].w - 10, top, commonData.keydata[5].x + commonData.keydata[5].w + 1, top, commonData.fgcolor);
// vertical key separators // vertical key separators
for (int i = 0; i <= 4; i++) { for (int i = 0; i <= 4; i++) {
getdisplay().drawLine(commonData.keydata[i].x + commonData.keydata[i].w, top, commonData.keydata[i].x + commonData.keydata[i].w, bottom, commonData.fgcolor); epd->drawLine(commonData.keydata[i].x + commonData.keydata[i].w, top, commonData.keydata[i].x + commonData.keydata[i].w, bottom, commonData.fgcolor);
} }
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
uint16_t x, y; uint16_t x, y;
@@ -571,7 +615,7 @@ void displayFooter(CommonData &commonData) {
if (iconmap.find(icon_name) != iconmap.end()) { if (iconmap.find(icon_name) != iconmap.end()) {
x = commonData.keydata[i].x + (commonData.keydata[i].w - icon_width) / 2; x = commonData.keydata[i].x + (commonData.keydata[i].w - icon_width) / 2;
y = commonData.keydata[i].y + (commonData.keydata[i].h - icon_height) / 2; y = commonData.keydata[i].y + (commonData.keydata[i].h - icon_height) / 2;
getdisplay().drawXBitmap(x, y, iconmap[icon_name], icon_width, icon_height, commonData.fgcolor); epd->drawXBitmap(x, y, iconmap[icon_name], icon_width, icon_height, commonData.fgcolor);
} else { } else {
// icon is missing, use name instead // icon is missing, use name instead
x = commonData.keydata[i].x + commonData.keydata[i].w / 2; x = commonData.keydata[i].x + commonData.keydata[i].w / 2;
@@ -586,8 +630,8 @@ void displayFooter(CommonData &commonData) {
} }
} }
} else { } else {
getdisplay().setCursor(65, 295); epd->setCursor(65, 295);
getdisplay().print("Press 1 and 6 fast to unlock keys"); epd->print("Press 1 and 6 fast to unlock keys");
} }
#endif #endif
#ifdef BOARD_OBP40S3 #ifdef BOARD_OBP40S3
@@ -598,21 +642,21 @@ void displayFooter(CommonData &commonData) {
uint16_t x0 = (GxEPD_WIDTH - w) / 2 + r * 2; uint16_t x0 = (GxEPD_WIDTH - w) / 2 + r * 2;
for (int i = 0; i < commonData.data.maxpage; i++) { for (int i = 0; i < commonData.data.maxpage; i++) {
if (i == (commonData.data.actpage - 1)) { if (i == (commonData.data.actpage - 1)) {
getdisplay().fillCircle(x0 + i * (r * 2 + space), 290, r, commonData.fgcolor); epd->fillCircle(x0 + i * (r * 2 + space), 290, r, commonData.fgcolor);
} else { } else {
getdisplay().drawCircle(x0 + i * (r * 2 + space), 290, r, commonData.fgcolor); epd->drawCircle(x0 + i * (r * 2 + space), 290, r, commonData.fgcolor);
} }
} }
// key indicators // key indicators
// left side = top key "menu" // left side = top key "menu"
getdisplay().drawLine(0, 280, 10, 280, commonData.fgcolor); epd->drawLine(0, 280, 10, 280, commonData.fgcolor);
getdisplay().drawLine(55, 280, 65, 280, commonData.fgcolor); epd->drawLine(55, 280, 65, 280, commonData.fgcolor);
getdisplay().drawLine(65, 280, 65, 299, commonData.fgcolor); epd->drawLine(65, 280, 65, 299, commonData.fgcolor);
drawTextCenter(33, 291, commonData.keydata[0].label); drawTextCenter(33, 291, commonData.keydata[0].label);
// right side = bottom key "exit" // right side = bottom key "exit"
getdisplay().drawLine(390, 280, 399, 280, commonData.fgcolor); epd->drawLine(390, 280, 399, 280, commonData.fgcolor);
getdisplay().drawLine(335, 280, 345, 280, commonData.fgcolor); epd->drawLine(335, 280, 345, 280, commonData.fgcolor);
getdisplay().drawLine(335, 280, 335, 399, commonData.fgcolor); epd->drawLine(335, 280, 335, 399, commonData.fgcolor);
drawTextCenter(366, 291, commonData.keydata[1].label); drawTextCenter(366, 291, commonData.keydata[1].label);
#endif #endif
} }
@@ -625,31 +669,31 @@ void displayAlarm(CommonData &commonData) {
const uint16_t w = 300; const uint16_t w = 300;
const uint16_t h = 150; const uint16_t h = 150;
getdisplay().setFont(&Atari16px); epd->setFont(&Atari16px);
getdisplay().setTextColor(commonData.fgcolor); epd->setTextColor(commonData.fgcolor);
// overlay // overlay
getdisplay().drawRect(x, y, w, h, commonData.fgcolor); epd->drawRect(x, y, w, h, commonData.fgcolor);
getdisplay().fillRect(x + 1, y + 1, w - 1, h - 1, commonData.bgcolor); epd->fillRect(x + 1, y + 1, w - 1, h - 1, commonData.bgcolor);
getdisplay().drawRect(x + 3, y + 3, w - 5, h - 5, commonData.fgcolor); epd->drawRect(x + 3, y + 3, w - 5, h - 5, commonData.fgcolor);
// exclamation icon in left top corner // exclamation icon in left top corner
getdisplay().drawXBitmap(x + 16, y + 16, exclamation_bits, exclamation_width, exclamation_height, commonData.fgcolor); epd->drawXBitmap(x + 16, y + 16, exclamation_bits, exclamation_width, exclamation_height, commonData.fgcolor);
// title // title
getdisplay().setCursor(x + 64, y + 30); epd->setCursor(x + 64, y + 30);
getdisplay().print("A L A R M"); epd->print("A L A R M");
getdisplay().setCursor(x + 64, y + 48); epd->setCursor(x + 64, y + 48);
getdisplay().print("#" + commonData.alarm.id); epd->print("#" + commonData.alarm.id);
getdisplay().print(" from "); epd->print(" from ");
getdisplay().print(commonData.alarm.source); epd->print(commonData.alarm.source);
// message, but maximum 4 lines // message, but maximum 4 lines
std::vector<String> lines = wordwrap (commonData.alarm.message, w - 16 - 8 / 8); std::vector<String> lines = wordwrap (commonData.alarm.message, w - 16 - 8 / 8);
int n = 0; int n = 0;
for (const auto& l : lines) { for (const auto& l : lines) {
getdisplay().setCursor(x + 16, y + 80 + n); epd->setCursor(x + 16, y + 80 + n);
getdisplay().print(l); epd->print(l);
n += 16; n += 16;
if (n > 64) { if (n > 64) {
break; break;
@@ -742,20 +786,20 @@ void batteryGraphic(uint x, uint y, float percent, int pcolor, int bcolor){
} }
// Battery corpus 100x80 with fill level // Battery corpus 100x80 with fill level
int level = int((100.0 - percent) * (80-(2*t)) / 100.0); int level = int((100.0 - percent) * (80-(2*t)) / 100.0);
getdisplay().fillRect(xb, yb, 100, 80, pcolor); epd->fillRect(xb, yb, 100, 80, pcolor);
if(percent < 99){ if(percent < 99){
getdisplay().fillRect(xb+t, yb+t, 100-(2*t), level, bcolor); epd->fillRect(xb+t, yb+t, 100-(2*t), level, bcolor);
} }
// Plus pol 20x15 // Plus pol 20x15
int xp = xb + 20; int xp = xb + 20;
int yp = yb - 15 + t; int yp = yb - 15 + t;
getdisplay().fillRect(xp, yp, 20, 15, pcolor); epd->fillRect(xp, yp, 20, 15, pcolor);
getdisplay().fillRect(xp+t, yp+t, 20-(2*t), 15-(2*t), bcolor); epd->fillRect(xp+t, yp+t, 20-(2*t), 15-(2*t), bcolor);
// Minus pol 20x15 // Minus pol 20x15
int xm = xb + 60; int xm = xb + 60;
int ym = yb -15 + t; int ym = yb -15 + t;
getdisplay().fillRect(xm, ym, 20, 15, pcolor); epd->fillRect(xm, ym, 20, 15, pcolor);
getdisplay().fillRect(xm+t, ym+t, 20-(2*t), 15-(2*t), bcolor); epd->fillRect(xm+t, ym+t, 20-(2*t), 15-(2*t), bcolor);
} }
// Solar graphic with fill level // Solar graphic with fill level
@@ -767,17 +811,17 @@ void solarGraphic(uint x, uint y, int pcolor, int bcolor){
int percent = 0; int percent = 0;
// Solar corpus 100x80 // Solar corpus 100x80
int level = int((100.0 - percent) * (80-(2*t)) / 100.0); int level = int((100.0 - percent) * (80-(2*t)) / 100.0);
getdisplay().fillRect(xb, yb, 100, 80, pcolor); epd->fillRect(xb, yb, 100, 80, pcolor);
if(percent < 99){ if(percent < 99){
getdisplay().fillRect(xb+t, yb+t, 100-(2*t), level, bcolor); epd->fillRect(xb+t, yb+t, 100-(2*t), level, bcolor);
} }
// Draw horizontel lines // Draw horizontel lines
getdisplay().fillRect(xb, yb+28-t, 100, t, pcolor); epd->fillRect(xb, yb+28-t, 100, t, pcolor);
getdisplay().fillRect(xb, yb+54-t, 100, t, pcolor); epd->fillRect(xb, yb+54-t, 100, t, pcolor);
// Draw vertical lines // Draw vertical lines
getdisplay().fillRect(xb+19+t, yb, t, 80, pcolor); epd->fillRect(xb+19+t, yb, t, 80, pcolor);
getdisplay().fillRect(xb+39+2*t, yb, t, 80, pcolor); epd->fillRect(xb+39+2*t, yb, t, 80, pcolor);
getdisplay().fillRect(xb+59+3*t, yb, t, 80, pcolor); epd->fillRect(xb+59+3*t, yb, t, 80, pcolor);
} }
@@ -789,13 +833,13 @@ void generatorGraphic(uint x, uint y, int pcolor, int bcolor){
int t = 4; // Line thickness int t = 4; // Line thickness
// Generator corpus with radius 45 // Generator corpus with radius 45
getdisplay().fillCircle(xb, yb, 45, pcolor); epd->fillCircle(xb, yb, 45, pcolor);
getdisplay().fillCircle(xb, yb, 41, bcolor); epd->fillCircle(xb, yb, 41, bcolor);
// Insert G // Insert G
getdisplay().setTextColor(pcolor); epd->setTextColor(pcolor);
getdisplay().setFont(&Ubuntu_Bold32pt8b); epd->setFont(&Ubuntu_Bold32pt8b);
getdisplay().setCursor(xb-22, yb+20); epd->setCursor(xb-22, yb+20);
getdisplay().print("G"); epd->print("G");
} }
// Function to handle HTTP image request // Function to handle HTTP image request
@@ -809,7 +853,7 @@ void doImageRequest(GwApi *api, int *pageno, const PageStruct pages[MAX_PAGE_NUM
logger->logDebug(GwLog::LOG,"handle image request [%s]: %s", imgformat, filename); logger->logDebug(GwLog::LOG,"handle image request [%s]: %s", imgformat, filename);
uint8_t *fb = getdisplay().getBuffer(); // EPD framebuffer uint8_t *fb = epd->getBuffer(); // EPD framebuffer
std::vector<uint8_t> imageBuffer; // image in webserver transferbuffer std::vector<uint8_t> imageBuffer; // image in webserver transferbuffer
String mimetype; String mimetype;

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef _OBP60EXTENSIONPORT_H #ifndef _OBP60EXTENSIONPORT_H
#define _OBP60EXTENSIONPORT_H #define _OBP60EXTENSIONPORT_H
@@ -43,19 +44,27 @@ extern const GFXfont Atari16px;
// Global functions // Global functions
#ifdef DISPLAY_GDEW042T2 #ifdef DISPLAY_GDEW042T2
GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> & getdisplay(); GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> & getdisplay(); // DEPRECATED
typedef GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> gxepd2display;
extern gxepd2display *epd;
#endif #endif
#ifdef DISPLAY_GDEY042T81 #ifdef DISPLAY_GDEY042T81
GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> & getdisplay(); GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> & getdisplay(); // DEPRECATED
typedef GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> gxepd2display;
extern gxepd2display *epd;
#endif #endif
#ifdef DISPLAY_GYE042A87 #ifdef DISPLAY_GYE042A87
GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay(); GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay(); // DEPRECATED
typedef GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> gxepd2display;
extern gxepd2display *epd;
#endif #endif
#ifdef DISPLAY_SE0420NQ04 #ifdef DISPLAY_SE0420NQ04
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay(); GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay(); // DEPRECATED
typedef GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> gxepd2display;
extern gxepd2display *epd;
#endif #endif
// Page display return values // Page display return values
@@ -98,7 +107,7 @@ void drawTextBoxed(Rect box, String text, uint16_t fg, uint16_t bg, bool inverte
void displayTrendHigh(int16_t x, int16_t y, uint16_t size, uint16_t color); void displayTrendHigh(int16_t x, int16_t y, uint16_t size, uint16_t color);
void displayTrendLow(int16_t x, int16_t y, uint16_t size, uint16_t color); void displayTrendLow(int16_t x, int16_t y, uint16_t size, uint16_t color);
void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatValue *time, GwApi::BoatValue *hdop); // Draw display header void displayHeader(CommonData &commonData, bool symbolmode, GwApi::BoatValue *date, GwApi::BoatValue *time, GwApi::BoatValue *hdop); // Draw display header
void displayFooter(CommonData &commonData); void displayFooter(CommonData &commonData);
void displayAlarm(CommonData &commonData); void displayAlarm(CommonData &commonData);
@@ -146,24 +155,62 @@ static unsigned char fram_bits[] PROGMEM = {
0xff, 0xff, 0xf8, 0x1f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf8, 0x1f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f,
0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f }; 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f };
// Header symbols
static unsigned char ap_bits[] PROGMEM= { static unsigned char ap_bits[] PROGMEM= {
0xe0, 0x03, 0x18, 0x0c, 0x04, 0x10, 0xc2, 0x21, 0x30, 0x06, 0x08, 0x08, 0xe0, 0x03, 0x18, 0x0c, 0x04, 0x10, 0xc2, 0x21, 0x30, 0x06, 0x08, 0x08,
0xc0, 0x01, 0x20, 0x02, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0x20, 0x02, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x01, 0xc0, 0x01,
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
static unsigned char dish_bits[] PROGMEM = { static unsigned char gps_bits[] PROGMEM = {
0x3c, 0x00, 0x42, 0x18, 0xfa, 0x1b, 0x02, 0x04, 0x02, 0x0a, 0x02, 0x09, 0x3c, 0x00, 0x42, 0x18, 0xfa, 0x1b, 0x02, 0x04, 0x02, 0x0a, 0x02, 0x09,
0x82, 0x08, 0x06, 0x0a, 0x0e, 0x1b, 0x9c, 0x2b, 0x38, 0x2b, 0x74, 0x20, 0x82, 0x08, 0x06, 0x0a, 0x0e, 0x1b, 0x9c, 0x2b, 0x38, 0x2b, 0x74, 0x20,
0xec, 0x1f, 0x1c, 0x00, 0xf4, 0x00, 0xfe, 0x03 }; 0xec, 0x1f, 0x1c, 0x00, 0xf4, 0x00, 0xfe, 0x03 };
static unsigned char nmea_bits[] PROGMEM = {
0x00, 0x00, 0x22, 0x21, 0x26, 0x33, 0x26, 0x33, 0x2a, 0x2d, 0x32, 0x2d,
0x32, 0x21, 0x22, 0x21, 0x00, 0x00, 0x3c, 0x0c, 0x04, 0x0c, 0x04, 0x12,
0x3c, 0x12, 0x04, 0x1e, 0x04, 0x21, 0x3c, 0x21 };
static unsigned char n2k_bits[] PROGMEM = {
0xe0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x02, 0x40, 0x32, 0x4c, 0x31, 0x8c,
0x01, 0x80, 0x81, 0x81, 0x81, 0x81, 0x01, 0x80, 0x31, 0x8c, 0x32, 0x4c,
0x02, 0x40, 0x04, 0x20, 0x98, 0x19, 0xe0, 0x07 };
static unsigned char tcp_bits[] PROGMEM = {
0x00, 0x00, 0xe0, 0x03, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0xe0, 0x03,
0x80, 0x00, 0x80, 0x00, 0xff, 0xff, 0x08, 0x10, 0x08, 0x10, 0x3e, 0x7c,
0x22, 0x44, 0x22, 0x44, 0x22, 0x44, 0x3e, 0x7c };
static unsigned char usb_bits[] PROGMEM = {
0x00, 0x00, 0x92, 0x39, 0x52, 0x4a, 0x52, 0x48, 0x92, 0x39, 0x12, 0x4a,
0x52, 0x4a, 0x8c, 0x39, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x04, 0x20,
0xf4, 0x2f, 0x04, 0x20, 0xf8, 0x1f, 0x00, 0x00 };
static unsigned char sdcard_bits[] PROGMEM = {
0xf8, 0x07, 0x0c, 0x08, 0x04, 0x08, 0xc4, 0x09, 0x24, 0x1a, 0xe4, 0x13,
0x04, 0x20, 0x24, 0x21, 0xa4, 0x12, 0x44, 0x12, 0x04, 0x20, 0x04, 0x20,
0xc4, 0x23, 0x34, 0x2c, 0xd8, 0x1b, 0x00, 0x00 };
static unsigned char bluetooth_bits[] PROGMEM = {
0x00, 0x00, 0x22, 0x21, 0x26, 0x33, 0x26, 0x33, 0x2a, 0x2d, 0x32, 0x2d,
0x32, 0x21, 0x22, 0x21, 0x00, 0x00, 0x3c, 0x0c, 0x04, 0x0c, 0x04, 0x12,
0x3c, 0x12, 0x04, 0x1e, 0x04, 0x21, 0x3c, 0x21 };
static std::map<String, unsigned char *> iconmap = { static std::map<String, unsigned char *> iconmap = {
{"LEFT", left_bits}, {"LEFT", left_bits},
{"RIGHT", right_bits}, {"RIGHT", right_bits},
{"LOCK", lock_bits}, {"LOCK", lock_bits},
{"PLUS", plus_bits}, {"PLUS", plus_bits},
{"MINUS", minus_bits}, {"MINUS", minus_bits},
{"DISH", dish_bits}, {"GPS", gps_bits},
{"AP", ap_bits} {"AP", ap_bits},
{"0183", nmea_bits},
{"N2K", n2k_bits},
{"TCP", tcp_bits},
{"USB", usb_bits},
{"SDCARD", sdcard_bits},
{"BLUE", bluetooth_bits}
}; };
// Battery // Battery

View File

@@ -65,6 +65,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
String tempFormat = commondata.config->getString(commondata.config->tempFormat); // [K|°C|°F] String tempFormat = commondata.config->getString(commondata.config->tempFormat); // [K|°C|°F]
String dateFormat = commondata.config->getString(commondata.config->dateFormat); // [DE|GB|US] String dateFormat = commondata.config->getString(commondata.config->dateFormat); // [DE|GB|US]
bool usesimudata = commondata.config->getBool(commondata.config->useSimuData); // [on|off] bool usesimudata = commondata.config->getBool(commondata.config->useSimuData); // [on|off]
String precision = commondata.config->getString(commondata.config->valueprecision); // [1|2]
// If boat value not valid // If boat value not valid
if (! value->valid && !usesimudata){ if (! value->valid && !usesimudata){
@@ -72,6 +73,19 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
return result; return result;
} }
const char* fmt_dec_1;
const char* fmt_dec_10;
const char* fmt_dec_100;
if (precision == "1") {
fmt_dec_1 = "%3.1f";
fmt_dec_10 = "%3.0f";
fmt_dec_100 = "%3.0f";
} else {
fmt_dec_1 = "%3.2f";
fmt_dec_10 = "%3.1f";
fmt_dec_100 = "%3.0f";
}
// LOG_DEBUG(GwLog::DEBUG,"formatValue init: getFormat: %s date->value: %f time->value: %f", value->getFormat(), commondata.date->value, commondata.time->value); // LOG_DEBUG(GwLog::DEBUG,"formatValue init: getFormat: %s date->value: %f time->value: %f", value->getFormat(), commondata.date->value, commondata.time->value);
static const int bsize = 30; static const int bsize = 30;
char buffer[bsize+1]; char buffer[bsize+1];
@@ -206,13 +220,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
result.unit = "m/s"; result.unit = "m/s";
} }
if(speed < 10) { if(speed < 10) {
snprintf(buffer,bsize,"%3.2f",speed); snprintf(buffer, bsize, fmt_dec_1, speed);
} }
if(speed >= 10 && speed < 100){ else if (speed < 100) {
snprintf(buffer,bsize,"%3.1f",speed); snprintf(buffer, bsize, fmt_dec_10, speed);
} }
if(speed >= 100){ else {
snprintf(buffer,bsize,"%3.0f",speed); snprintf(buffer, bsize, fmt_dec_100, speed);
} }
} }
//######################################################## //########################################################
@@ -238,40 +252,40 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
if (speed < 0.3) { if (speed < 0.3) {
speed = 0; speed = 0;
} }
if(speed >=0.3 && speed < 1.5){ else if (speed < 1.5) {
speed = 1; speed = 1;
} }
if(speed >=1.5 && speed < 3.3){ else if (speed < 3.3) {
speed = 2; speed = 2;
} }
if(speed >=3.3 && speed < 5.4){ else if (speed < 5.4) {
speed = 3; speed = 3;
} }
if(speed >=5.4 && speed < 7.9){ else if (speed < 7.9) {
speed = 4; speed = 4;
} }
if(speed >=7.9 && speed < 10.7){ else if (speed < 10.7) {
speed = 5; speed = 5;
} }
if(speed >=10.7 && speed < 13.8){ else if (speed < 13.8) {
speed = 6; speed = 6;
} }
if(speed >=13.8 && speed < 17.1){ else if (speed < 17.1) {
speed = 7; speed = 7;
} }
if(speed >=17.1 && speed < 20.7){ else if (speed < 20.7) {
speed = 8; speed = 8;
} }
if(speed >=20.7 && speed < 24.4){ else if (speed < 24.4) {
speed = 9; speed = 9;
} }
if(speed >=24.4 && speed < 28.4){ else if (speed < 28.4) {
speed = 10; speed = 10;
} }
if(speed >=28.4 && speed < 32.6){ else if (speed < 32.6) {
speed = 11; speed = 11;
} }
if(speed >=32.6){ else {
speed = 12; speed = 12;
} }
result.unit = "bft"; result.unit = "bft";
@@ -285,13 +299,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
} }
else{ else{
if (speed < 10){ if (speed < 10){
snprintf(buffer,bsize,"%3.2f",speed); snprintf(buffer, bsize, fmt_dec_1, speed);
} }
if(speed >= 10 && speed < 100){ else if (speed < 100){
snprintf(buffer,bsize,"%3.1f",speed); snprintf(buffer, bsize, fmt_dec_10, speed);
} }
if(speed >= 100){ else {
snprintf(buffer,bsize,"%3.0f",speed); snprintf(buffer, bsize, fmt_dec_100, speed);
} }
} }
} }
@@ -337,10 +351,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
dop = 99.9; dop = 99.9;
} }
if (dop < 10){ if (dop < 10){
snprintf(buffer,bsize,"%3.2f",dop); snprintf(buffer, bsize, fmt_dec_1, dop);
} }
if(dop >= 10 && dop < 100){ else if(dop < 100){
snprintf(buffer,bsize,"%3.1f",dop); snprintf(buffer, bsize, fmt_dec_10, dop);
}
else {
snprintf(buffer, bsize, fmt_dec_100, dop);
} }
} }
//######################################################## //########################################################
@@ -410,13 +427,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
result.unit = "m"; result.unit = "m";
} }
if (depth < 10) { if (depth < 10) {
snprintf(buffer,bsize,"%3.2f",depth); snprintf(buffer, bsize, fmt_dec_1, depth);
} }
if(depth >= 10 && depth < 100){ else if (depth < 100){
snprintf(buffer,bsize,"%3.1f",depth); snprintf(buffer, bsize, fmt_dec_10, depth);
} }
if(depth >= 100){ else {
snprintf(buffer,bsize,"%3.0f",depth); snprintf(buffer, bsize, fmt_dec_100, depth);
} }
} }
//######################################################## //########################################################
@@ -430,11 +447,11 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
xte = rawvalue; xte = rawvalue;
} }
if (xte >= 100) { if (xte >= 100) {
snprintf(buffer,bsize,"%3.0f",value->value); snprintf(buffer, bsize, fmt_dec_100, value->value);
} else if (xte >= 10) { } else if (xte >= 10) {
snprintf(buffer,bsize,"%3.1f",value->value); snprintf(buffer, bsize, fmt_dec_10, value->value);
} else { } else {
snprintf(buffer,bsize,"%3.2f",value->value); snprintf(buffer, bsize, fmt_dec_1, value->value);
} }
result.unit = "nm"; result.unit = "nm";
} }
@@ -461,13 +478,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
result.unit = "K"; result.unit = "K";
} }
if(temp < 10) { if(temp < 10) {
snprintf(buffer,bsize,"%3.2f",temp); snprintf(buffer, bsize, fmt_dec_1, temp);
} }
if(temp >= 10 && temp < 100){ else if (temp < 100) {
snprintf(buffer,bsize,"%3.1f",temp); snprintf(buffer, bsize, fmt_dec_10, temp);
} }
if(temp >= 100){ else {
snprintf(buffer,bsize,"%3.0f",temp); snprintf(buffer, bsize, fmt_dec_100, temp);
} }
} }
//######################################################## //########################################################
@@ -489,17 +506,17 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
distance = distance * 0.000539957; distance = distance * 0.000539957;
result.unit = "nm"; result.unit = "nm";
} }
else{; else {
result.unit = "m"; result.unit = "m";
} }
if (distance < 10){ if (distance < 10){
snprintf(buffer,bsize,"%3.2f",distance); snprintf(buffer, bsize, fmt_dec_1, distance);
} }
if(distance >= 10 && distance < 100){ else if (distance < 100){
snprintf(buffer,bsize,"%3.1f",distance); snprintf(buffer, bsize, fmt_dec_10, distance);
} }
if(distance >= 100){ else {
snprintf(buffer,bsize,"%3.0f",distance); snprintf(buffer, bsize, fmt_dec_100, distance);
} }
} }
//######################################################## //########################################################
@@ -547,10 +564,10 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
voltage = rawvalue; voltage = rawvalue;
} }
if (voltage < 10) { if (voltage < 10) {
snprintf(buffer,bsize,"%3.2f",voltage); snprintf(buffer, bsize, fmt_dec_1, voltage);
} }
else { else {
snprintf(buffer,bsize,"%3.1f",voltage); snprintf(buffer, bsize, fmt_dec_10, voltage);
} }
result.unit = "V"; result.unit = "V";
} }
@@ -566,13 +583,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
current = rawvalue; current = rawvalue;
} }
if (current < 10) { if (current < 10) {
snprintf(buffer,bsize,"%3.2f",current); snprintf(buffer, bsize, fmt_dec_1, current);
} }
if(current >= 10 && current < 100){ else if(current < 100) {
snprintf(buffer,bsize,"%3.1f",current); snprintf(buffer, bsize, fmt_dec_10, current);
} }
if(current >= 100){ else {
snprintf(buffer,bsize,"%3.0f",current); snprintf(buffer, bsize, fmt_dec_100, current);
} }
result.unit = "A"; result.unit = "A";
} }
@@ -588,13 +605,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
temperature = rawvalue; temperature = rawvalue;
} }
if (temperature < 10) { if (temperature < 10) {
snprintf(buffer,bsize,"%3.2f",temperature); snprintf(buffer, bsize, fmt_dec_1, temperature);
} }
if(temperature >= 10 && temperature < 100){ else if (temperature < 100) {
snprintf(buffer,bsize,"%3.1f",temperature); snprintf(buffer, bsize, fmt_dec_10, temperature);
} }
if(temperature >= 100){ else {
snprintf(buffer,bsize,"%3.0f",temperature); snprintf(buffer, bsize, fmt_dec_100, temperature);
} }
result.unit = "Deg C"; result.unit = "Deg C";
} }
@@ -610,13 +627,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
temperature = rawvalue; temperature = rawvalue;
} }
if (temperature < 10) { if (temperature < 10) {
snprintf(buffer,bsize,"%3.2f",temperature); snprintf(buffer, bsize, fmt_dec_1, temperature);
} }
if(temperature >= 10 && temperature < 100){ else if(temperature < 100) {
snprintf(buffer,bsize,"%3.1f",temperature); snprintf(buffer, bsize, fmt_dec_10, temperature);
} }
if(temperature >= 100){ else {
snprintf(buffer,bsize,"%3.0f",temperature); snprintf(buffer, bsize, fmt_dec_100, temperature);
} }
result.unit = "Deg C"; result.unit = "Deg C";
} }
@@ -632,13 +649,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
humidity = rawvalue; humidity = rawvalue;
} }
if (humidity < 10) { if (humidity < 10) {
snprintf(buffer,bsize,"%3.2f",humidity); snprintf(buffer, bsize, fmt_dec_1, humidity);
} }
if(humidity >= 10 && humidity < 100){ else if(humidity < 100) {
snprintf(buffer,bsize,"%3.1f",humidity); snprintf(buffer, bsize, fmt_dec_10, humidity);
} }
if(humidity >= 100){ else {
snprintf(buffer,bsize,"%3.0f",humidity); snprintf(buffer, bsize, fmt_dec_100, humidity);
} }
result.unit = "%"; result.unit = "%";
} }
@@ -654,13 +671,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
volume = rawvalue; volume = rawvalue;
} }
if (volume < 10) { if (volume < 10) {
snprintf(buffer,bsize,"%3.2f",volume); snprintf(buffer, bsize, fmt_dec_1, volume);
} }
if(volume >= 10 && volume < 100){ else if (volume < 100) {
snprintf(buffer,bsize,"%3.1f",volume); snprintf(buffer, bsize, fmt_dec_10, volume);
} }
if(volume >= 100){ else if (volume >= 100) {
snprintf(buffer,bsize,"%3.0f",volume); snprintf(buffer, bsize, fmt_dec_100, volume);
} }
result.unit = "%"; result.unit = "%";
} }
@@ -676,13 +693,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
volume = rawvalue; volume = rawvalue;
} }
if (volume < 10) { if (volume < 10) {
snprintf(buffer,bsize,"%3.2f",volume); snprintf(buffer, bsize, fmt_dec_1, volume);
} }
if(volume >= 10 && volume < 100){ else if (volume < 100) {
snprintf(buffer,bsize,"%3.1f",volume); snprintf(buffer, bsize, fmt_dec_10, volume);
} }
if(volume >= 100){ else {
snprintf(buffer,bsize,"%3.0f",volume); snprintf(buffer, bsize, fmt_dec_100, volume);
} }
result.unit = "l"; result.unit = "l";
} }
@@ -698,13 +715,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
flow = rawvalue; flow = rawvalue;
} }
if (flow < 10) { if (flow < 10) {
snprintf(buffer,bsize,"%3.2f",flow); snprintf(buffer, bsize, fmt_dec_1, flow);
} }
if(flow >= 10 && flow < 100){ else if (flow < 100) {
snprintf(buffer,bsize,"%3.1f",flow); snprintf(buffer, bsize, fmt_dec_10, flow);
} }
if(flow >= 100){ else {
snprintf(buffer,bsize,"%3.0f",flow); snprintf(buffer, bsize, fmt_dec_100, flow);
} }
result.unit = "l/min"; result.unit = "l/min";
} }
@@ -712,7 +729,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
else if (value->getFormat() == "formatXdr:G:"){ else if (value->getFormat() == "formatXdr:G:"){
double generic = 0; double generic = 0;
if (usesimudata == false) { if (usesimudata == false) {
generic = value->value; // Value in l/min generic = value->value;
rawvalue = value->value; rawvalue = value->value;
} }
else { else {
@@ -720,13 +737,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
generic = rawvalue; generic = rawvalue;
} }
if (generic < 10) { if (generic < 10) {
snprintf(buffer,bsize,"%3.2f",generic); snprintf(buffer, bsize, fmt_dec_1, generic);
} }
if(generic >= 10 && generic < 100){ else if (generic < 100) {
snprintf(buffer,bsize,"%3.1f",generic); snprintf(buffer, bsize, fmt_dec_10, generic);
} }
if(generic >= 100){ else {
snprintf(buffer,bsize,"%3.0f",generic); snprintf(buffer, bsize, fmt_dec_100, generic);
} }
result.unit = ""; result.unit = "";
} }
@@ -742,13 +759,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
dplace = rawvalue; dplace = rawvalue;
} }
if (dplace < 10) { if (dplace < 10) {
snprintf(buffer,bsize,"%3.2f",dplace); snprintf(buffer, bsize, fmt_dec_1, dplace);
} }
if(dplace >= 10 && dplace < 100){ else if (dplace < 100) {
snprintf(buffer,bsize,"%3.1f",dplace); snprintf(buffer, bsize, fmt_dec_10, dplace);
} }
if(dplace >= 100){ else {
snprintf(buffer,bsize,"%3.0f",dplace); snprintf(buffer, bsize, fmt_dec_100, dplace);
} }
result.unit = "%"; result.unit = "%";
} }
@@ -784,13 +801,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
rpm = rawvalue; rpm = rawvalue;
} }
if (rpm < 10) { if (rpm < 10) {
snprintf(buffer,bsize,"%3.2f",rpm); snprintf(buffer, bsize, fmt_dec_1, rpm);
} }
if(rpm >= 10 && rpm < 100){ else if (rpm < 100) {
snprintf(buffer,bsize,"%3.1f",rpm); snprintf(buffer, bsize, fmt_dec_10, rpm);
} }
if(rpm >= 100){ else {
snprintf(buffer,bsize,"%3.0f",rpm); snprintf(buffer, bsize, fmt_dec_100, rpm);
} }
result.unit = "rpm"; result.unit = "rpm";
} }
@@ -799,13 +816,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
//######################################################## //########################################################
else { else {
if (value->value < 10) { if (value->value < 10) {
snprintf(buffer,bsize,"%3.2f",value->value); snprintf(buffer, bsize, fmt_dec_1, value->value);
} }
if(value->value >= 10 && value->value < 100){ else if (value->value < 100) {
snprintf(buffer,bsize,"%3.1f",value->value); snprintf(buffer, bsize, fmt_dec_10, value->value);
} }
if(value->value >= 100){ else {
snprintf(buffer,bsize,"%3.0f",value->value); snprintf(buffer, bsize, fmt_dec_100, value->value);
} }
result.unit = ""; result.unit = "";
} }

View File

@@ -0,0 +1,433 @@
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
#include "ConfigMenu.h"
/*
Anchor overview with additional associated data
This page is in experimental stage so be warned!
North is up.
Boatdata used
DBS - Water depth
HDT - Boat heading
AWS - Wind strength; Boat not moving so we assume AWS=TWS and AWD=TWD
AWD - Wind direction
LAT/LON - Boat position, current
HDOP - Position error
This is the fist page to contain a configuration page with
data entry option.
Also it will make use of the new alarm function.
Data
Anchor position lat/lon
Depth at anchor position
Chain length used
Boat position current
Depth at boat position
Boat heading
Wind direction
Wind strength
Alarm j/n
Alarm radius
GPS position error
Timestamp while dropping anchor
Drop / raise function in device OBP40 has to be done inside
config mode because of limited number of buttons.
*/
#define anchor_width 16
#define anchor_height 16
static unsigned char anchor_bits[] = {
0x80, 0x01, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, 0xf0, 0x0f, 0x80, 0x01,
0x80, 0x01, 0x88, 0x11, 0x8c, 0x31, 0x8e, 0x71, 0x84, 0x21, 0x86, 0x61,
0x86, 0x61, 0xfc, 0x3f, 0xf8, 0x1f, 0x80, 0x01 };
class PageAnchor : public Page
{
private:
GwConfigHandler *config;
GwLog *logger;
bool simulation = false;
bool holdvalues = false;
String flashLED;
String backlightMode;
String lengthformat;
int scale = 50; // Radius of display circle in meter
bool alarm = false;
bool alarm_enabled = false;
uint8_t alarm_range;
uint8_t chain_length;
uint8_t chain;
bool anchor_set = false;
double anchor_lat;
double anchor_lon;
double anchor_depth;
int anchor_ts; // time stamp anchor dropped
char mode = 'N'; // (N)ormal, (C)onfig
int8_t editmode = -1; // marker for menu/edit/set function
ConfigMenu *menu;
void displayModeNormal(PageData &pageData) {
// Boatvalues: DBS, HDT, AWS, AWD, LAT, LON, HDOP
GwApi::BoatValue *bv_dbs = pageData.values[0]; // DBS
String sval_dbs = formatValue(bv_dbs, *commonData).svalue;
String sunit_dbs = formatValue(bv_dbs, *commonData).unit;
GwApi::BoatValue *bv_hdt = pageData.values[1]; // HDT
String sval_hdt = formatValue(bv_hdt, *commonData).svalue;
GwApi::BoatValue *bv_aws = pageData.values[2]; // AWS
String sval_aws = formatValue(bv_aws, *commonData).svalue;
String sunit_aws = formatValue(bv_aws, *commonData).unit;
GwApi::BoatValue *bv_awd = pageData.values[3]; // AWD
String sval_awd = formatValue(bv_awd, *commonData).svalue;
GwApi::BoatValue *bv_lat = pageData.values[4]; // LAT
String sval_lat = formatValue(bv_lat, *commonData).svalue;
GwApi::BoatValue *bv_lon = pageData.values[5]; // LON
String sval_lon = formatValue(bv_lon, *commonData).svalue;
GwApi::BoatValue *bv_hdop = pageData.values[6]; // HDOP
String sval_hdop = formatValue(bv_hdop, *commonData).svalue;
String sunit_hdop = formatValue(bv_hdop, *commonData).unit;
LOG_DEBUG(GwLog::DEBUG,"Drawing at PageAnchor; DBS=%f, HDT=%f, AWS=%f", bv_dbs->value, bv_hdt->value, bv_aws->value);
Point c = {200, 150}; // center = anchor position
uint16_t r = 125;
Point b = {200, 180}; // boat position while dropping anchor
const std::vector<Point> pts_boat = { // polygon lines
{b.x - 5, b.y},
{b.x - 5, b.y - 10},
{b.x, b.y - 16},
{b.x + 5, b.y - 10},
{b.x + 5, b.y}
};
//rotatePoints und dann Linien zeichnen
// TODO rotate boat according to current heading
//drawPoly(rotatePoints(c, pts, RadToDeg(value2)), commonData->fgcolor);
drawPoly(pts_boat, commonData->fgcolor);
// Draw wind arrow
const std::vector<Point> pts_wind = {
{c.x, c.y - r + 25},
{c.x - 12, c.y - r - 4},
{c.x, c.y - r + 6},
{c.x + 12, c.y - r - 4}
};
if (bv_awd->valid) {
fillPoly4(rotatePoints(c, pts_wind, bv_awd->value), commonData->fgcolor);
}
// Title and corner value headings
getdisplay().setTextColor(commonData->fgcolor);
getdisplay().setFont(&Ubuntu_Bold12pt8b);
getdisplay().setCursor(8, 48);
getdisplay().print("Anchor");
getdisplay().setFont(&Ubuntu_Bold10pt8b);
getdisplay().setCursor(8, 200);
getdisplay().print("Depth");
drawTextRalign(392, 38, "Chain");
drawTextRalign(392, 200, "Wind");
// Units
getdisplay().setCursor(8, 272);
getdisplay().print(sunit_dbs);
drawTextRalign(392, 272, sunit_aws);
drawTextRalign(392, 100, lengthformat); // chain unit not implemented
// Corner values
getdisplay().setFont(&Ubuntu_Bold8pt8b);
getdisplay().setCursor(8, 70);
getdisplay().print("Alarm: ");
getdisplay().print(alarm_enabled ? "On" : "Off");
getdisplay().setCursor(8, 90);
getdisplay().print("HDOP");
getdisplay().setCursor(8, 106);
if (bv_hdop->valid) {
getdisplay().print(round(bv_hdop->value), 0);
getdisplay().print(sunit_hdop);
} else {
getdisplay().print("n/a");
}
// Values
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
// Current chain used
getdisplay().setCursor(328, 85);
getdisplay().print("27");
// Depth
getdisplay().setCursor(8, 250);
getdisplay().print(sval_dbs);
// Wind
getdisplay().setCursor(328, 250);
getdisplay().print(sval_aws);
getdisplay().drawCircle(c.x, c.y, r, commonData->fgcolor);
getdisplay().drawCircle(c.x, c.y, r + 1, commonData->fgcolor);
// zoom scale
getdisplay().drawLine(c.x + 10, c.y, c.x + r - 4, c.y, commonData->fgcolor);
// arrow left
getdisplay().drawLine(c.x + 10, c.y, c.x + 16, c.y - 4, commonData->fgcolor);
getdisplay().drawLine(c.x + 10, c.y, c.x + 16, c.y + 4, commonData->fgcolor);
// arrow right
getdisplay().drawLine(c.x + r - 4, c.y, c.x + r - 10, c.y - 4, commonData->fgcolor);
getdisplay().drawLine(c.x + r - 4, c.y, c.x + r - 10, c.y + 4, commonData->fgcolor);
getdisplay().setFont(&Ubuntu_Bold8pt8b);
drawTextCenter(c.x + r / 2, c.y + 8, String(scale) + "m");
// alarm range circle
if (alarm_enabled) {
// alarm range in meter has to be smaller than the scale in meter
// r and r_range are pixel values
uint16_t r_range = int(alarm_range * r / scale);
LOG_DEBUG(GwLog::LOG,"Drawing at PageAnchor; Alarm range = %d", r_range);
getdisplay().drawCircle(c.x, c.y, r_range, commonData->fgcolor);
}
// draw anchor symbol (as bitmap)
getdisplay().drawXBitmap(c.x - anchor_width / 2, c.y - anchor_height / 2,
anchor_bits, anchor_width, anchor_height, commonData->fgcolor);
}
void displayModeConfig() {
getdisplay().setTextColor(commonData->fgcolor);
getdisplay().setFont(&Ubuntu_Bold12pt8b);
getdisplay().setCursor(8, 48);
getdisplay().print("Anchor configuration");
// TODO
// show lat/lon for anchor pos
// show lat/lon for boat pos
// show distance anchor <-> boat
getdisplay().setFont(&Ubuntu_Bold8pt8b);
for (int i = 0 ; i < menu->getItemCount(); i++) {
ConfigMenuItem *itm = menu->getItemByIndex(i);
if (!itm) {
LOG_DEBUG(GwLog::ERROR, "Menu item not found: %d", i);
} else {
Rect r = menu->getItemRect(i);
bool inverted = (i == menu->getActiveIndex());
drawTextBoxed(r, itm->getLabel(), commonData->fgcolor, commonData->bgcolor, inverted, false);
if (inverted and editmode > 0) {
// triangle as edit marker
getdisplay().fillTriangle(r.x + r.w + 20, r.y, r.x + r.w + 30, r.y + r.h / 2, r.x + r.w + 20, r.y + r.h, commonData->fgcolor);
}
getdisplay().setCursor(r.x + r.w + 40, r.y + r.h - 4);
if (itm->getType() == "int") {
getdisplay().print(itm->getValue());
getdisplay().print(itm->getUnit());
} else {
getdisplay().print(itm->getValue() == 0 ? "No" : "Yes");
}
}
}
}
public:
PageAnchor(CommonData &common)
{
commonData = &common;
config = commonData->config;
logger = commonData->logger;
logger->logDebug(GwLog::LOG,"Instantiate PageAnchor");
// preload configuration data
simulation = config->getBool(config->useSimuData);
holdvalues = config->getBool(config->holdvalues);
flashLED = config->getString(config->flashLED);
backlightMode = config->getString(config->backlight);
lengthformat = config->getString(config->lengthFormat);
chain_length = config->getInt(config->chainLength);
chain = 0;
anchor_set = false;
alarm_range = 30;
// Initialize config menu
menu = new ConfigMenu("Options", 40, 80);
menu->setItemDimension(150, 20);
ConfigMenuItem *newitem;
newitem = menu->addItem("chain", "Chain out", "int", 0, "m");
if (! newitem) {
// Demo: in case of failure exit here, should never be happen
logger->logDebug(GwLog::ERROR,"Menu item creation failed");
return;
}
newitem->setRange(0, 200, {1, 5, 10});
newitem = menu->addItem("chainmax", "Chain max", "int", chain_length, "m");
newitem->setRange(0, 200, {1, 5, 10});
newitem = menu->addItem("zoom", "Zoom", "int", 50, "m");
newitem->setRange(0, 200, {1, });
newitem = menu->addItem("range", "Alarm range", "int", 40, "m");
newitem->setRange(0, 200, {1, 5, 10});
newitem = menu->addItem("alat", "Adjust anchor lat.", "int", 0, "m");
newitem->setRange(0, 200, {1, 5, 10});
newitem = menu->addItem("alon", "Adjust anchor lon.", "int", 0, "m");
newitem->setRange(0, 200, {1, 5, 10});
#ifdef BOARD_OBP40S3
// Intodruced here because of missing keys for OBP40
newitem = menu->addItem("anchor", "Anchor down", "bool", 0, "");
#endif
menu->setItemActive("zoom");
}
void setupKeys(){
Page::setupKeys();
commonData->keydata[0].label = "MODE";
commonData->keydata[1].label = "ALARM";
}
#ifdef BOARD_OBP60S3
int handleKey(int key){
if (key == 1) { // Switch between normal and config mode
if (mode == 'N') {
mode = 'C';
} else {
mode = 'N';
}
return 0;
}
if (mode == 'N') {
if (key == 2) { // Toggle alarm
alarm_enabled = !alarm_enabled;
return 0;
}
} else { // Config mode
if (key == 3) {
// menu down
menu->goNext();
return 0;
}
if (key == 4) {
// menu up
menu->goPrev();
return 0;
}
}
if (key == 11) { // Code for keylock
commonData->keylock = !commonData->keylock;
return 0;
}
return key;
}
#endif
#ifdef BOARD_OBP40S3
int handleKey(int key){
if (key == 1) { // Switch between normal and config mode
if (mode == 'N') {
mode = 'C';
commonData->keydata[1].label = "EDIT";
} else {
mode = 'N';
commonData->keydata[1].label = "ALARM";
}
return 0;
}
if (mode == 'N') {
if (key == 2) { // Toggle alarm
alarm_enabled = !alarm_enabled;
return 0;
}
} else { // Config mode
// TODO different code for OBP40 / OBP60
if (key == 9) {
// menu down
if (editmode > 0) {
// decrease item value
menu->getActiveItem()->decValue();
} else {
menu->goNext();
}
return 0;
}
if (key == 10) {
// menu up or value up
if (editmode > 0) {
// increase item value
menu->getActiveItem()->incValue();
} else {
menu->goPrev();
}
return 0;
}
if (key == 2) {
// enter / leave edit mode for current menu item
if (editmode > 0) {
commonData->keydata[1].label = "EDIT";
editmode = 0;
} else {
commonData->keydata[1].label = "SET";
editmode = 1;
}
return 0;
}
}
if (key == 11) { // Code for keylock
commonData->keylock = !commonData->keylock;
return 0;
}
return key;
}
#endif
void displayNew(PageData &pageData){
};
int displayPage(PageData &pageData){
// Logging boat values
LOG_DEBUG(GwLog::LOG,"Drawing at PageAnchor; Mode=%c", mode);
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
if (mode == 'N') {
displayModeNormal(pageData);
} else if (mode == 'C') {
displayModeConfig();
}
return PAGE_UPDATE;
};
};
static Page *createPage(CommonData &common){
return new PageAnchor(common);
}
/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect
* this will be number of BoatValue pointers in pageData.values
*/
PageDescription registerPageAnchor(
"Anchor", // Page name
createPage, // Action
0, // Number of bus values depends on selection in Web configuration
{"DBS", "HDT", "AWS", "AWD", "LAT", "LON", "HDOP"}, // Names of bus values undepends on selection in Web configuration (refer GwBoatData.h)
true // Show display header on/off
);
#endif

View File

@@ -31,6 +31,15 @@ bool homevalid = false; // homelat and homelon are valid
PageClock(CommonData &common){ PageClock(CommonData &common){
commonData = &common; commonData = &common;
common.logger->logDebug(GwLog::LOG,"Instantiate PageClock"); common.logger->logDebug(GwLog::LOG,"Instantiate PageClock");
// WIP time source
#ifdef BOARD_OBP60S3
String use_rtc = common.config->getString(common.config->useRTC);
if (use_rtc == "off") {
source = 'G';
}
#endif
simulation = common.config->getBool(common.config->useSimuData); simulation = common.config->getBool(common.config->useSimuData);
timezone = common.config->getString(common.config->timeZone).toDouble(); timezone = common.config->getString(common.config->timeZone).toDouble();
homelat = common.config->getString(common.config->homeLAT).toDouble(); homelat = common.config->getString(common.config->homeLAT).toDouble();
@@ -100,9 +109,10 @@ bool homevalid = false; // homelat and homelon are valid
static String svalue5old = ""; static String svalue5old = "";
static String svalue6old = ""; static String svalue6old = "";
double value1 = 0; double value1 = 0; // GPS time
double value2 = 0; double value2 = 0; // GPS date FIXME date defined as uint32_t!
double value3 = 0; double value3 = 0; // HDOP
bool gpsvalid = false;
// Get config data // Get config data
String lengthformat = config->getString(config->lengthFormat); String lengthformat = config->getString(config->lengthFormat);
@@ -155,6 +165,9 @@ bool homevalid = false; // homelat and homelon are valid
unit3old = unit3; // Save old unit unit3old = unit3; // Save old unit
} }
// GPS date and time are valid and can be used
gpsvalid = (valid1 && valid2 && valid3);
// Optical warning by limit violation (unused) // Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){ if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false); setBlinkingLED(false);
@@ -163,7 +176,7 @@ bool homevalid = false; // homelat and homelon are valid
// Logging boat values // Logging boat values
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement? if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
LOG_DEBUG(GwLog::LOG,"Drawing at PageClock, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2); LOG_DEBUG(GwLog::LOG,"Drawing at PageClock, %s:%f, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3);
// Draw page // Draw page
//*********************************************************** //***********************************************************
@@ -231,7 +244,7 @@ bool homevalid = false; // homelat and homelon are valid
// Show values sunrise // Show values sunrise
String sunrise = "---"; String sunrise = "---";
if ((valid1 and valid2 and valid3 == true) or (homevalid and commonData->data.rtcValid)) { if (((source == 'G') and gpsvalid) or (homevalid and commonData->data.rtcValid)) {
sunrise = String(commonData->sundata.sunriseHour) + ":" + String(commonData->sundata.sunriseMinute + 100).substring(1); sunrise = String(commonData->sundata.sunriseHour) + ":" + String(commonData->sundata.sunriseMinute + 100).substring(1);
svalue5old = sunrise; svalue5old = sunrise;
} else if (simulation) { } else if (simulation) {
@@ -251,7 +264,7 @@ bool homevalid = false; // homelat and homelon are valid
// Show values sunset // Show values sunset
String sunset = "---"; String sunset = "---";
if ((valid1 and valid2 and valid3 == true) or (homevalid and commonData->data.rtcValid)) { if (((source == 'G') and gpsvalid) or (homevalid and commonData->data.rtcValid)) {
sunset = String(commonData->sundata.sunsetHour) + ":" + String(commonData->sundata.sunsetMinute + 100).substring(1); sunset = String(commonData->sundata.sunsetHour) + ":" + String(commonData->sundata.sunsetMinute + 100).substring(1);
svalue6old = sunset; svalue6old = sunset;
} else if (simulation) { } else if (simulation) {

View File

@@ -0,0 +1,153 @@
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
/*
* SkyView / Satellites
*/
class PageSkyView : public Page
{
public:
PageSkyView(CommonData &common){
commonData = &common;
common.logger->logDebug(GwLog::LOG,"Show PageSkyView");
}
int handleKey(int key){
// Code for keylock
if(key == 11){
commonData->keylock = !commonData->keylock;
return 0; // Commit the key
}
return key;
}
int displayPage(PageData &pageData) {
GwConfigHandler *config = commonData->config;
GwLog *logger = commonData->logger;
// Get config data
String flashLED = config->getString(config->flashLED);
String displaycolor = config->getString(config->displaycolor);
String backlightMode = config->getString(config->backlight);
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false);
setFlashLED(false);
}
// Logging boat values
LOG_DEBUG(GwLog::LOG,"Drawing at PageSkyView");
// Draw page
//***********************************************************
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// current position
getdisplay().setFont(&Ubuntu_Bold8pt8b);
GwApi::BoatValue *bv_lat = pageData.values[0];
String sv_lat = formatValue(bv_lat, *commonData).svalue;
//getdisplay().setCursor(300, 40);
//getdisplay().print(sv_lat);
GwApi::BoatValue *bv_lon = pageData.values[1];
String sv_lon = formatValue(bv_lon, *commonData).svalue;
//getdisplay().setCursor(300, 60);
//getdisplay().print(sv_lon);
GwApi::BoatValue *bv_hdop = pageData.values[2];
String sv_hdop = formatValue(bv_hdop, *commonData).svalue;
//getdisplay().setCursor(300, 80);
//getdisplay().print(sv_hdop);
// sky view
Point c = {130, 148};
uint16_t r = 125;
uint16_t r1 = r / 2;
getdisplay().fillCircle(c.x, c.y, r, commonData->bgcolor);
getdisplay().drawCircle(c.x, c.y, r + 1, commonData->fgcolor);
getdisplay().drawCircle(c.x, c.y, r + 2, commonData->fgcolor);
getdisplay().drawCircle(c.x, c.y, r1, commonData->fgcolor);
// separation lines
getdisplay().drawLine(c.x - r, c.y, c.x + r, c.y, commonData->fgcolor);
getdisplay().drawLine(c.x, c.y - r, c.x, c.y + r, commonData->fgcolor);
Point p = {c.x, c.y - r};
Point p1, p2;
p1 = rotatePoint(c, p, 45);
p2 = rotatePoint(c, p, 45 + 180);
getdisplay().drawLine(p1.x, p1.y, p2.x, p2.y, commonData->fgcolor);
p1 = rotatePoint(c, p, -45);
p2 = rotatePoint(c, p, -45 + 180);
getdisplay().drawLine(p1.x, p1.y, p2.x, p2.y, commonData->fgcolor);
// directions
int16_t x1, y1;
uint16_t w, h;
getdisplay().setFont(&Ubuntu_Bold12pt8b);
getdisplay().getTextBounds("N", 0, 150, &x1, &y1, &w, &h);
getdisplay().setCursor(c.x - w / 2, c.y - r + h + 2);
getdisplay().print("N");
getdisplay().getTextBounds("S", 0, 150, &x1, &y1, &w, &h);
getdisplay().setCursor(c.x - w / 2, c.y + r - 2);
getdisplay().print("S");
getdisplay().getTextBounds("E", 0, 150, &x1, &y1, &w, &h);
getdisplay().setCursor(c.x + r - w - 2, c.y + h / 2);
getdisplay().print("E");
getdisplay().getTextBounds("W", 0, 150, &x1, &y1, &w, &h);
getdisplay().setCursor(c.x - r + 2 , c.y + h / 2);
getdisplay().print("W");
// satellites
// Signal / Noise bars
getdisplay().setFont(&Ubuntu_Bold8pt8b);
getdisplay().setCursor(325, 34);
getdisplay().print("SNR");
getdisplay().drawRect(270, 20, 125, 257, commonData->fgcolor);
for (int i = 0; i < 12; i++) {
uint16_t y = 29 + (i + 1) * 20;
getdisplay().setCursor(276, y);
char buffer[3];
snprintf(buffer, 3, "%02d", i+1);
getdisplay().print(String(buffer));
getdisplay().drawRect(305, y-12, 85, 14, commonData->fgcolor);
}
return PAGE_UPDATE;
};
};
static Page* createPage(CommonData &common){
return new PageSkyView(common);
}
/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect
* this will be number of BoatValue pointers in pageData.values
*/
PageDescription registerPageSkyView(
"SkyView", // Page name
createPage, // Action
0, // Number of bus values depends on selection in Web configuration
{"LAT", "LON", "HDOP"}, // Bus values we need in the page
true // Show display header on/off
);
#endif

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3 #if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h" #include "Pagedata.h"
@@ -6,6 +7,7 @@
class PageVoltage : public Page class PageVoltage : public Page
{ {
private:
bool init = false; // Marker for init done bool init = false; // Marker for init done
uint8_t average = 0; // Average type [0...3], 0=off, 1=10s, 2=60s, 3=300s uint8_t average = 0; // Average type [0...3], 0=off, 1=10s, 2=60s, 3=300s
bool trend = true; // Trend indicator [0|1], 0=off, 1=on bool trend = true; // Trend indicator [0|1], 0=off, 1=on
@@ -15,7 +17,10 @@ char mode = 'D'; // display mode (A)nalog | (D)igital
public: public:
PageVoltage(CommonData &common){ PageVoltage(CommonData &common){
commonData = &common; commonData = &common;
common.logger->logDebug(GwLog::LOG,"Instantiate PageVoltage"); config = commonData->config;
logger = commonData->logger;
logger->logDebug(GwLog::LOG,"Instantiate PageVoltage");
if (hasFRAM) { if (hasFRAM) {
average = fram.read(FRAM_VOLTAGE_AVG); average = fram.read(FRAM_VOLTAGE_AVG);
trend = fram.read(FRAM_VOLTAGE_TREND); trend = fram.read(FRAM_VOLTAGE_TREND);
@@ -23,6 +28,10 @@ public:
} }
} }
~PageVoltage(){
logger->logDebug(GwLog::LOG,"Destroy PageVoltage");
}
virtual void setupKeys(){ virtual void setupKeys(){
Page::setupKeys(); Page::setupKeys();
commonData->keydata[0].label = "AVG"; commonData->keydata[0].label = "AVG";

View File

@@ -1,3 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
#include <Arduino.h> #include <Arduino.h>
#include "GwApi.h" #include "GwApi.h"
@@ -98,6 +100,10 @@ typedef struct{
uint8_t length_sec; // seconds until alarm disappeares without user interaction uint8_t length_sec; // seconds until alarm disappeares without user interaction
} AlarmData; } AlarmData;
typedef struct{
int voltage = 0;
} AvgData;
typedef struct{ typedef struct{
GwApi::Status status; GwApi::Status status;
GwLog *logger=NULL; GwLog *logger=NULL;
@@ -107,6 +113,7 @@ typedef struct{
TouchKeyData keydata[6]; TouchKeyData keydata[6];
BacklightData backlight; BacklightData backlight;
AlarmData alarm; AlarmData alarm;
AvgData avgdata;
GwApi::BoatValue *time=NULL; GwApi::BoatValue *time=NULL;
GwApi::BoatValue *date=NULL; GwApi::BoatValue *date=NULL;
uint16_t fgcolor; uint16_t fgcolor;
@@ -119,6 +126,8 @@ typedef struct{
class Page{ class Page{
protected: protected:
CommonData *commonData; CommonData *commonData;
GwConfigHandler *config;
GwLog *logger;
public: public:
int refreshtime = 1000; int refreshtime = 1000;
virtual int displayPage(PageData &pageData)=0; virtual int displayPage(PageData &pageData)=0;

82
lib/obp60task/README Normal file
View File

@@ -0,0 +1,82 @@
Development information
=======================
This file contains some hints concerning building the firmware as well as
developing and debugging it.
Git commands
------------
Some useful commands are
git status
git fetch upstream
git diff --name-status upstream/master
git checkout upstream/master platformio.ini
# how to reset my Repo to match norbert's status
git remote add upstream https://github.com/norbert-walter/esp32-nmea2000-obp60
git fetch upstream
git checkout master
git reset --hard upstream/master
git push origin master --force
New pages
---------
To create a new page for OBP60 the following steps are necessary:
1. Create a page under /lib/obp60task/PageXXXX.cpp
2. Set page name in PageXXXX.cpp on file name
3. Register new page in /lib/obp60task/obp60task.cpp in function
'registerAllPages'
4. Add new page in /lib/obp60task/config.json for each page type or add
new page to gen_set.py and run it to auto-generate the relevant
section of config.json
5. Copy the changes in config.json to config_obp40.json and rename
strings accordingly. E.g. obp60 to obp40.
Using Gitpod
------------
Open web page:
https://gitpod.io/#https://github.com/norbert-walter/esp32-nmea2000-obp60/tree/master/lib/obp60task
Input in terminal:
cd /workspace/esp32-nmea2000-obp60
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run_installing_tools
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run_obp60_s3
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run_obp40_s3
Compile result for OBP60:
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/bootloader.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/firmware.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/partitions.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-all.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-dev<yyyymmdd>-all.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-dev<yyyymmdd>-update.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-all.bin, ready to flash to offset 0x0000
Compile result for OBP40 (CrowPanel 4.2):
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/bootloader.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/firmware.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/partitions.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-all.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-dev<yyyymmdd>-all.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-dev<yyyymmdd>-update.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-all.bin, ready to flash to offset 0x0000
Debugging tool
--------------
log.txt = text file with error messages from terminal console
tools/decoder.py -p ESP32S3 -t ~/.platformio/packages/toolchain-xtensa-esp32s3/ -e .pio/build/obp60_s3/firmware.elf log.txt

View File

@@ -1,38 +0,0 @@
Using Gitpod
############
Open web page:
https://gitpod.io/#https://github.com/norbert-walter/esp32-nmea2000-obp60/tree/master/lib/obp60task
Input in terminal:
cd /workspace/esp32-nmea2000-obp60
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run_installing_tools
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run_obp60_s3
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run_obp40_s3
Compile result for OBP60
########################
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/bootloader.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/firmware.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/partitions.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-all.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-dev20231220-all.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-dev20231220-update.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-all.bin, ready to flash to offset 0x0000
Compile result for OBP40 (CrowPanel 4.2)
########################################
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/bootloader.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/firmware.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/partitions.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-all.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-dev20231220-all.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-dev20231220-update.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-all.bin, ready to flash to offset 0x0000

View File

@@ -75,6 +75,20 @@
"obp60":"true" "obp60":"true"
} }
}, },
{
"name": "chainLength",
"label": "Anchor Chain Length [m]",
"type": "number",
"default": "0",
"check": "checkMinMax",
"min": 0,
"max": 255,
"description": "The length of the anchor chain [0...255m]",
"category": "OBP60 Settings",
"capabilities": {
"obp60":"true"
}
},
{ {
"name": "fuelTank", "name": "fuelTank",
"label": "Fuel Tank [l]", "label": "Fuel Tank [l]",
@@ -1117,6 +1131,36 @@
"obp60":"true" "obp60":"true"
} }
}, },
{
"name": "valueprecision",
"label": "Display value precision",
"type": "list",
"default": "2",
"description": "Maximum number of decimal places to display [1|2]",
"list": [
"1",
"2"
],
"category": "OBP60 Display",
"capabilities": {
"obp60":"true"
}
},
{
"name": "headerFormat",
"label": "Header Format",
"type": "list",
"default":"TEXT",
"description": "Header format: Text or Symbols",
"list": [
{"l":"Text","v":"TEXT"},
{"l":"Symbols","v":"ICON"}
],
"category":"OBP60 Pages",
"capabilities": {
"obp60":"true"
}
},
{ {
"name": "backlight", "name": "backlight",
"label": "Backlight Mode", "label": "Backlight Mode",
@@ -1303,6 +1347,7 @@
"default": "Voltage", "default": "Voltage",
"description": "Type of page for page 1", "description": "Type of page for page 1",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -1318,6 +1363,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -1584,6 +1630,7 @@
"default": "WindRose", "default": "WindRose",
"description": "Type of page for page 2", "description": "Type of page for page 2",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -1599,6 +1646,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -1862,6 +1910,7 @@
"default": "OneValue", "default": "OneValue",
"description": "Type of page for page 3", "description": "Type of page for page 3",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -1877,6 +1926,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -2137,6 +2187,7 @@
"default": "TwoValues", "default": "TwoValues",
"description": "Type of page for page 4", "description": "Type of page for page 4",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -2152,6 +2203,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -2409,6 +2461,7 @@
"default": "ThreeValues", "default": "ThreeValues",
"description": "Type of page for page 5", "description": "Type of page for page 5",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -2424,6 +2477,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -2678,6 +2732,7 @@
"default": "FourValues", "default": "FourValues",
"description": "Type of page for page 6", "description": "Type of page for page 6",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -2693,6 +2748,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -2944,6 +3000,7 @@
"default": "FourValues2", "default": "FourValues2",
"description": "Type of page for page 7", "description": "Type of page for page 7",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -2959,6 +3016,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -3207,6 +3265,7 @@
"default": "Clock", "default": "Clock",
"description": "Type of page for page 8", "description": "Type of page for page 8",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -3222,6 +3281,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -3467,6 +3527,7 @@
"default": "RollPitch", "default": "RollPitch",
"description": "Type of page for page 9", "description": "Type of page for page 9",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -3482,6 +3543,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -3724,6 +3786,7 @@
"default": "Battery2", "default": "Battery2",
"description": "Type of page for page 10", "description": "Type of page for page 10",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -3739,6 +3802,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",

View File

@@ -75,6 +75,20 @@
"obp40": "true" "obp40": "true"
} }
}, },
{
"name": "chainLength",
"label": "Anchor Chain Length [m]",
"type": "number",
"default": "0",
"check": "checkMinMax",
"min": 0,
"max": 255,
"description": "The length of the anchor chain [0...255m]",
"category": "OBP40 Settings",
"capabilities": {
"obp40":"true"
}
},
{ {
"name": "fuelTank", "name": "fuelTank",
"label": "Fuel Tank [l]", "label": "Fuel Tank [l]",
@@ -348,7 +362,7 @@
"label": "RTC Modul", "label": "RTC Modul",
"type": "list", "type": "list",
"default": "off", "default": "off",
"description": "Use internal RTC module type [off|DS1388]", "description": "Use RTC module type [off|DS1388]",
"list": [ "list": [
"off", "off",
"DS1388" "DS1388"
@@ -1129,6 +1143,36 @@
"obp40": "true" "obp40": "true"
} }
}, },
{
"name": "valueprecision",
"label": "Display value precision",
"type": "list",
"default": "2",
"description": "Maximum number of decimal places to display [1|2]",
"list": [
"1",
"2"
],
"category": "OBP40 Display",
"capabilities": {
"obp40":"true"
}
},
{
"name": "headerFormat",
"label": "Header Format",
"type": "list",
"default":"TEXT",
"description": "Header format: Text or Symbols",
"list": [
{"l":"Text","v":"TEXT"},
{"l":"Symbols","v":"ICON"}
],
"category":"OBP40 Display",
"capabilities": {
"obp40":"true"
}
},
{ {
"name": "backlight", "name": "backlight",
"label": "Backlight Mode", "label": "Backlight Mode",
@@ -1326,6 +1370,7 @@
"default": "Clock", "default": "Clock",
"description": "Type of page for page 1", "description": "Type of page for page 1",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -1341,6 +1386,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -1607,6 +1653,7 @@
"default": "Wind", "default": "Wind",
"description": "Type of page for page 2", "description": "Type of page for page 2",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -1622,6 +1669,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -1885,6 +1933,7 @@
"default": "OneValue", "default": "OneValue",
"description": "Type of page for page 3", "description": "Type of page for page 3",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -1900,6 +1949,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -2160,6 +2210,7 @@
"default": "TwoValues", "default": "TwoValues",
"description": "Type of page for page 4", "description": "Type of page for page 4",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -2175,6 +2226,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -2432,6 +2484,7 @@
"default": "ThreeValues", "default": "ThreeValues",
"description": "Type of page for page 5", "description": "Type of page for page 5",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -2447,6 +2500,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -2701,6 +2755,7 @@
"default": "FourValues", "default": "FourValues",
"description": "Type of page for page 6", "description": "Type of page for page 6",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -2716,6 +2771,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -2967,6 +3023,7 @@
"default": "FourValues2", "default": "FourValues2",
"description": "Type of page for page 7", "description": "Type of page for page 7",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -2982,6 +3039,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -3230,6 +3288,7 @@
"default": "Fluid", "default": "Fluid",
"description": "Type of page for page 8", "description": "Type of page for page 8",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -3245,6 +3304,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -3490,6 +3550,7 @@
"default": "RollPitch", "default": "RollPitch",
"description": "Type of page for page 9", "description": "Type of page for page 9",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -3505,6 +3566,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",
@@ -3747,6 +3809,7 @@
"default": "Battery2", "default": "Battery2",
"description": "Type of page for page 10", "description": "Type of page for page 10",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -3762,6 +3825,7 @@
"RollPitch", "RollPitch",
"RudderPosition", "RudderPosition",
"SixValues", "SixValues",
"SkyView",
"Solar", "Solar",
"ThreeValues", "ThreeValues",
"TwoValues", "TwoValues",

View File

@@ -1,6 +0,0 @@
Debugging tool
##############
log.txt = text file with error messages from terminal console
tools/decoder.py -p ESP32S3 -t ~/.platformio/packages/toolchain-xtensa-esp32s3/ -e .pio/build/obp60_s3/firmware.elf log.txt

View File

@@ -1,46 +1,55 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# A tool to generate that part of config.json that deals with pages and fields.
#
#Usage: 1. modify this script (e.g.add a page, change number of fields, etc.)
# 2. Delete all lines from config.json from the curly backet before "name": "page1type" to o the end of the file (as of today, delete from line 917 to the end of the File)
# 3. run ./gen_set.py >> config.json
"""
A tool to generate that part of config.json that deals with pages and fields.
Usage example:
1. Delete all lines from config.json from the curly backet before
"name": "page1type" to the end of the file
2. run ./gen_set.py -d obp60 -p 10 >> config.json
TODO Better handling of default pages
"""
import os
import sys
import getopt
import re
import json import json
# List of all pages and the number of parameters they expect. __version__ = "0.2"
no_of_fields_per_page = {
"Wind": 0,
"XTETrack": 0,
"Battery2": 0,
"Battery": 0,
"BME280": 0,
"Clock": 0,
"Compass" : 0,
"DST810": 0,
"Fluid": 1,
"FourValues2": 4,
"FourValues": 4,
"Generator": 0,
"KeelPosition": 0,
"OneValue": 1,
"RollPitch": 2,
"RudderPosition": 0,
"SixValues" : 6,
"Solar": 0,
"ThreeValues": 3,
"TwoValues": 2,
"Voltage": 0,
"WhitePage": 0,
"WindPlot": 0,
"WindRose": 0,
"WindRoseFlex": 6,
}
# No changes needed beyond this point def detect_pages(filename):
# max number of pages supported by OBP60 # returns a dictionary with page name and the number of gui fields
no_of_pages = 10 pagefiles = []
with open(filename, 'r') as fh:
pattern = r'extern PageDescription\s*register(Page[^;\s]*)'
for line in fh:
if "extern PageDescription" in line:
match = re.search(pattern, line)
if match:
pagefiles.append(match.group(1))
try:
pagefiles.remove('PageSystem')
except ValueError:
pass
pagedata = {}
for pf in pagefiles:
filename = pf + ".cpp"
with open(filename, 'r') as fh:
content = fh.read()
pattern = r'PageDescription\s*?register' + pf + r'\s*\(\s*"([^"]+)".*?\n\s*(\d+)'
match = re.search(pattern, content, re.DOTALL)
if match:
pagedata[match.group(1)] = int(match.group(2))
return pagedata
def get_default_page(pageno):
# Default selection for each page # Default selection for each page
default_pages = [ default_pages = (
"Voltage", "Voltage",
"WindRose", "WindRose",
"OneValue", "OneValue",
@@ -50,22 +59,30 @@ default_pages = [
"FourValues2", "FourValues2",
"Clock", "Clock",
"RollPitch", "RollPitch",
"Battery2", "Battery2"
] )
numbers = [ if pageno > len(default_pages):
"one", return "OneValue"
"two", return default_pages[pageno - 1]
"three",
"four", def number_to_text(number):
"five", if number < 0 or number > 99:
"six", raise ValueError("Only numbers from 0 to 99 are allowed.")
"seven", numbers = ("zero", "one", "two", "three", "four", "five", "six", "seven",
"eight", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
"nine", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen")
"ten", tens = ("", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy",
] "eighty", "ninety")
pages = sorted(no_of_fields_per_page.keys()) if number < 20:
max_no_of_fields_per_page = max(no_of_fields_per_page.values()) return numbers[number]
else:
q, r = divmod(number, 10)
return tens[q] + numbers[r]
def create_json(device, no_of_pages, pagedata):
pages = sorted(pagedata.keys())
max_no_of_fields_per_page = max(pagedata.values())
output = [] output = []
@@ -74,11 +91,11 @@ for page_no in range(1, no_of_pages + 1):
"name": f"page{page_no}type", "name": f"page{page_no}type",
"label": "Type", "label": "Type",
"type": "list", "type": "list",
"default": default_pages[page_no - 1], "default": get_default_page(page_no),
"description": f"Type of page for page {page_no}", "description": f"Type of page for page {page_no}",
"list": pages, "list": pages,
"category": f"OBP60 Page {page_no}", "category": f"{device.upper()} Page {page_no}",
"capabilities": {"obp60": "true"}, "capabilities": {device.lower(): "true"},
"condition": [{"visiblePages": vp} for vp in range(page_no, no_of_pages + 1)], "condition": [{"visiblePages": vp} for vp in range(page_no, no_of_pages + 1)],
#"fields": [], #"fields": [],
} }
@@ -90,13 +107,13 @@ for page_no in range(1, no_of_pages + 1):
"label": f"Field {field_no}", "label": f"Field {field_no}",
"type": "boatData", "type": "boatData",
"default": "", "default": "",
"description": f"The display for field {numbers[field_no - 1]}", "description": "The display for field {}".format(number_to_text(field_no)),
"category": f"OBP60 Page {page_no}", "category": f"{device.upper()} Page {page_no}",
"capabilities": {"obp60": "true"}, "capabilities": {device.lower(): "true"},
"condition": [ "condition": [
{f"page{page_no}type": page} {f"page{page_no}type": page}
for page in pages for page in pages
if no_of_fields_per_page[page] >= field_no if pagedata[page] >= field_no
], ],
} }
output.append(field_data) output.append(field_data)
@@ -116,17 +133,47 @@ for page_no in range(1, no_of_pages + 1):
{"l":"Fuel Gasoline (6)","v":"6"} {"l":"Fuel Gasoline (6)","v":"6"}
], ],
"description": "Fluid type in tank", "description": "Fluid type in tank",
"category": f"OBP60 Page {page_no}", "category": f"{device.upper()} Page {page_no}",
"capabilities": { "capabilities": {
"obp60":"true" device.lower(): "true"
}, },
"condition":[{f"page{page_no}type":"Fluid"}] "condition":[{f"page{page_no}type":"Fluid"}]
} }
output.append(fluid_data) output.append(fluid_data)
json_output = json.dumps(output, indent=4) return json.dumps(output, indent=4)
# print omitting first and last line containing [ ] of JSON array
#print(json_output[1:-1]) def usage():
print("{} v{}".format(os.path.basename(__file__), __version__))
print()
print("Command line options")
print(" -d --device device name to use e.g. obp60")
print(" -p --pages number of pages to create")
print(" -h show this help")
print()
if __name__ == '__main__':
try:
options, remainder = getopt.getopt(sys.argv[1:], 'd:p:', ['device=','--pages='])
except getopt.GetoptError as err:
print(err)
usage()
sys.exit(2)
device = "obp60"
no_of_pages = 10
for opt, arg in options:
if opt in ('-d', '--device'):
device = arg
elif opt in ('-p', '--pages'):
no_of_pages = int(arg)
elif opt == '-h':
usage()
sys.exit(0)
# automatic detect pages and number of fields from sourcecode
pagedata = detect_pages("obp60task.cpp")
json_output = create_json(device, no_of_pages, pagedata)
# print omitting first line containing [ of JSON array # print omitting first line containing [ of JSON array
print(json_output[1:]) print(json_output[1:])
# print(",")

View File

@@ -1,12 +0,0 @@
git status
git fetch upstream
git diff --name-status upstream/master
git checkout upstream/master platformio.ini
# how to reset my Repo to match norbert'status
git remote add upstream https://github.com/norbert-walter/esp32-nmea2000-obp60
git fetch upstream
git checkout master
git reset --hard upstream/master
git push origin master --force

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3 #if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "obp60task.h" #include "obp60task.h"
#include "Pagedata.h" // Data exchange for pages #include "Pagedata.h" // Data exchange for pages
@@ -295,6 +296,10 @@ void registerAllPages(PageList &list){
list.add(&registerPageXTETrack); list.add(&registerPageXTETrack);
extern PageDescription registerPageFluid; extern PageDescription registerPageFluid;
list.add(&registerPageFluid); list.add(&registerPageFluid);
extern PageDescription registerPageSkyView;
list.add(&registerPageSkyView);
extern PageDescription registerPageAnchor;
list.add(&registerPageAnchor);
} }
// Undervoltage detection for shutdown display // Undervoltage detection for shutdown display
@@ -318,18 +323,18 @@ void underVoltageDetection(GwApi *api, CommonData &common){
setFlashLED(false); // Flash LED Off setFlashLED(false); // Flash LED Off
buzzer(TONE4, 20); // Buzzer tone 4kHz 20ms buzzer(TONE4, 20); // Buzzer tone 4kHz 20ms
// Shutdown EInk display // Shutdown EInk display
getdisplay().setFullWindow(); // Set full Refresh epd->setFullWindow(); // Set full Refresh
//getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update //epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
getdisplay().fillScreen(common.bgcolor);// Clear screen epd->fillScreen(common.bgcolor);// Clear screen
getdisplay().setTextColor(common.fgcolor); epd->setTextColor(common.fgcolor);
getdisplay().setFont(&Ubuntu_Bold20pt8b); epd->setFont(&Ubuntu_Bold20pt8b);
getdisplay().setCursor(65, 150); epd->setCursor(65, 150);
getdisplay().print("Undervoltage"); epd->print("Undervoltage");
getdisplay().setFont(&Ubuntu_Bold8pt8b); epd->setFont(&Ubuntu_Bold8pt8b);
getdisplay().setCursor(65, 175); epd->setCursor(65, 175);
getdisplay().print("Charge battery and restart system"); epd->print("Charge battery and restart system");
getdisplay().nextPage(); // Partial update epd->nextPage(); // Partial update
getdisplay().powerOff(); // Display power off epd->powerOff(); // Display power off
setPortPin(OBP_POWER_EPD, false); // Power off ePaper display setPortPin(OBP_POWER_EPD, false); // Power off ePaper display
setPortPin(OBP_POWER_SD, false); // Power off SD card setPortPin(OBP_POWER_SD, false); // Power off SD card
#else #else
@@ -339,17 +344,17 @@ void underVoltageDetection(GwApi *api, CommonData &common){
buzzer(TONE4, 20); // Buzzer tone 4kHz 20ms buzzer(TONE4, 20); // Buzzer tone 4kHz 20ms
setPortPin(OBP_POWER_50, false); // Power rail 5.0V Off setPortPin(OBP_POWER_50, false); // Power rail 5.0V Off
// Shutdown EInk display // Shutdown EInk display
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
getdisplay().fillScreen(common.bgcolor);// Clear screen epd->fillScreen(common.bgcolor);// Clear screen
getdisplay().setTextColor(common.fgcolor); epd->setTextColor(common.fgcolor);
getdisplay().setFont(&Ubuntu_Bold20pt8b); epd->setFont(&Ubuntu_Bold20pt8b);
getdisplay().setCursor(65, 150); epd->setCursor(65, 150);
getdisplay().print("Undervoltage"); epd->print("Undervoltage");
getdisplay().setFont(&Ubuntu_Bold8pt8b); epd->setFont(&Ubuntu_Bold8pt8b);
getdisplay().setCursor(65, 175); epd->setCursor(65, 175);
getdisplay().print("To wake up repower system"); epd->print("To wake up repower system");
getdisplay().nextPage(); // Partial update epd->nextPage(); // Partial update
getdisplay().powerOff(); // Display power off epd->powerOff(); // Display power off
#endif #endif
// Stop system // Stop system
while(true){ while(true){
@@ -518,6 +523,7 @@ void OBP60Task(GwApi *api){
String systemname = api->getConfig()->getConfigItem(api->getConfig()->systemName,true)->asString(); String systemname = api->getConfig()->getConfigItem(api->getConfig()->systemName,true)->asString();
String wifipass = api->getConfig()->getConfigItem(api->getConfig()->apPassword,true)->asString(); String wifipass = api->getConfig()->getConfigItem(api->getConfig()->apPassword,true)->asString();
bool refreshmode = api->getConfig()->getConfigItem(api->getConfig()->refresh,true)->asBoolean(); bool refreshmode = api->getConfig()->getConfigItem(api->getConfig()->refresh,true)->asBoolean();
bool symbolmode = (config->getString(config->headerFormat) == "ICON");
String fastrefresh = api->getConfig()->getConfigItem(api->getConfig()->fastRefresh,true)->asString(); String fastrefresh = api->getConfig()->getConfigItem(api->getConfig()->fastRefresh,true)->asString();
uint fullrefreshtime = uint(api->getConfig()->getConfigItem(api->getConfig()->fullRefreshTime,true)->asInt()); uint fullrefreshtime = uint(api->getConfig()->getConfigItem(api->getConfig()->fullRefreshTime,true)->asInt());
#ifdef BOARD_OBP40S3 #ifdef BOARD_OBP40S3
@@ -525,37 +531,37 @@ void OBP60Task(GwApi *api){
#endif #endif
#ifdef DISPLAY_GDEY042T81 #ifdef DISPLAY_GDEY042T81
getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse epd->init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
#else #else
getdisplay().init(115200); // Init for normal displays epd->init(115200); // Init for normal displays
#endif #endif
getdisplay().setRotation(0); // Set display orientation (horizontal) epd->setRotation(0); // Set display orientation (horizontal)
getdisplay().setFullWindow(); // Set full Refresh epd->setFullWindow(); // Set full Refresh
getdisplay().firstPage(); // set first page epd->firstPage(); // set first page
getdisplay().fillScreen(commonData.bgcolor); epd->fillScreen(commonData.bgcolor);
getdisplay().setTextColor(commonData.fgcolor); epd->setTextColor(commonData.fgcolor);
getdisplay().nextPage(); // Full Refresh epd->nextPage(); // Full Refresh
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
getdisplay().fillScreen(commonData.bgcolor); epd->fillScreen(commonData.bgcolor);
getdisplay().nextPage(); // Fast Refresh epd->nextPage(); // Fast Refresh
getdisplay().nextPage(); // Fast Refresh epd->nextPage(); // Fast Refresh
if(String(displaymode) == "Logo + QR Code" || String(displaymode) == "Logo"){ if(String(displaymode) == "Logo + QR Code" || String(displaymode) == "Logo"){
getdisplay().fillScreen(commonData.bgcolor); epd->fillScreen(commonData.bgcolor);
getdisplay().drawBitmap(0, 0, gImage_Logo_OBP_400x300_sw, getdisplay().width(), getdisplay().height(), commonData.fgcolor); // Draw start logo epd->drawBitmap(0, 0, gImage_Logo_OBP_400x300_sw, epd->width(), epd->height(), commonData.fgcolor); // Draw start logo
getdisplay().nextPage(); // Fast Refresh epd->nextPage(); // Fast Refresh
getdisplay().nextPage(); // Fast Refresh epd->nextPage(); // Fast Refresh
delay(SHOW_TIME); // Logo show time delay(SHOW_TIME); // Logo show time
if(String(displaymode) == "Logo + QR Code"){ if(String(displaymode) == "Logo + QR Code"){
getdisplay().fillScreen(commonData.bgcolor); epd->fillScreen(commonData.bgcolor);
qrWiFi(systemname, wifipass, commonData.fgcolor, commonData.bgcolor); // Show QR code for WiFi connection qrWiFi(systemname, wifipass, commonData.fgcolor, commonData.bgcolor); // Show QR code for WiFi connection
getdisplay().nextPage(); // Fast Refresh epd->nextPage(); // Fast Refresh
getdisplay().nextPage(); // Fast Refresh epd->nextPage(); // Fast Refresh
delay(SHOW_TIME); // QR code show time delay(SHOW_TIME); // QR code show time
} }
getdisplay().fillScreen(commonData.bgcolor); epd->fillScreen(commonData.bgcolor);
getdisplay().nextPage(); // Fast Refresh epd->nextPage(); // Fast Refresh
getdisplay().nextPage(); // Fast Refresh epd->nextPage(); // Fast Refresh
} }
// Init pages // Init pages
@@ -866,23 +872,23 @@ void OBP60Task(GwApi *api){
if(millis() > starttime4 + 4000 && delayedDisplayUpdate == true){ if(millis() > starttime4 + 4000 && delayedDisplayUpdate == true){
starttime1 = millis(); starttime1 = millis();
starttime2 = millis(); starttime2 = millis();
getdisplay().setFullWindow(); // Set full update epd->setFullWindow(); // Set full update
if(fastrefresh == "true"){ if(fastrefresh == "true"){
getdisplay().nextPage(); // Full update epd->nextPage(); // Full update
} }
else{ else{
getdisplay().fillScreen(commonData.fgcolor); // Clear display epd->fillScreen(commonData.fgcolor); // Clear display
#ifdef DISPLAY_GDEY042T81 #ifdef DISPLAY_GDEY042T81
getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse epd->init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
#else #else
getdisplay().init(115200); // Init for normal displays epd->init(115200); // Init for normal displays
#endif #endif
getdisplay().firstPage(); // Full update epd->firstPage(); // Full update
getdisplay().nextPage(); // Full update epd->nextPage(); // Full update
// getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update // epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
// getdisplay().fillScreen(commonData.bgcolor); // Clear display // epd->fillScreen(commonData.bgcolor); // Clear display
// getdisplay().nextPage(); // Partial update // epd->nextPage(); // Partial update
// getdisplay().nextPage(); // Partial update // epd->nextPage(); // Partial update
} }
delayedDisplayUpdate = false; delayedDisplayUpdate = false;
} }
@@ -893,23 +899,23 @@ void OBP60Task(GwApi *api){
starttime1 = millis(); starttime1 = millis();
starttime2 = millis(); starttime2 = millis();
LOG_DEBUG(GwLog::DEBUG,"E-Ink full refresh first 5 min"); LOG_DEBUG(GwLog::DEBUG,"E-Ink full refresh first 5 min");
getdisplay().setFullWindow(); // Set full update epd->setFullWindow(); // Set full update
if(fastrefresh == "true"){ if(fastrefresh == "true"){
getdisplay().nextPage(); // Full update epd->nextPage(); // Full update
} }
else{ else{
getdisplay().fillScreen(commonData.fgcolor); // Clear display epd->fillScreen(commonData.fgcolor); // Clear display
#ifdef DISPLAY_GDEY042T81 #ifdef DISPLAY_GDEY042T81
getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse epd->init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
#else #else
getdisplay().init(115200); // Init for normal displays epd->init(115200); // Init for normal displays
#endif #endif
getdisplay().firstPage(); // Full update epd->firstPage(); // Full update
getdisplay().nextPage(); // Full update epd->nextPage(); // Full update
// getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update // epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
// getdisplay().fillScreen(commonData.bgcolor); // Clear display // epd->fillScreen(commonData.bgcolor); // Clear display
// getdisplay().nextPage(); // Partial update // epd->nextPage(); // Partial update
// getdisplay().nextPage(); // Partial update // epd->nextPage(); // Partial update
} }
} }
@@ -917,23 +923,23 @@ void OBP60Task(GwApi *api){
if(millis() > starttime2 + fullrefreshtime * 60 * 1000){ if(millis() > starttime2 + fullrefreshtime * 60 * 1000){
starttime2 = millis(); starttime2 = millis();
LOG_DEBUG(GwLog::DEBUG,"E-Ink full refresh"); LOG_DEBUG(GwLog::DEBUG,"E-Ink full refresh");
getdisplay().setFullWindow(); // Set full update epd->setFullWindow(); // Set full update
if(fastrefresh == "true"){ if(fastrefresh == "true"){
getdisplay().nextPage(); // Full update epd->nextPage(); // Full update
} }
else{ else{
getdisplay().fillScreen(commonData.fgcolor); // Clear display epd->fillScreen(commonData.fgcolor); // Clear display
#ifdef DISPLAY_GDEY042T81 #ifdef DISPLAY_GDEY042T81
getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse epd->init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
#else #else
getdisplay().init(115200); // Init for normal displays epd->init(115200); // Init for normal displays
#endif #endif
getdisplay().firstPage(); // Full update epd->firstPage(); // Full update
getdisplay().nextPage(); // Full update epd->nextPage(); // Full update
// getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update // epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
// getdisplay().fillScreen(commonData.bgcolor); // Clear display // epd->fillScreen(commonData.bgcolor); // Clear display
// getdisplay().nextPage(); // Partial update // epd->nextPage(); // Partial update
// getdisplay().nextPage(); // Partial update // epd->nextPage(); // Partial update
} }
} }
@@ -959,13 +965,13 @@ void OBP60Task(GwApi *api){
handleHstryBuf(api, &boatValues, hstryBufList); handleHstryBuf(api, &boatValues, hstryBufList);
// Clear display // Clear display
// getdisplay().fillRect(0, 0, getdisplay().width(), getdisplay().height(), commonData.bgcolor); // epd->fillRect(0, 0, epd->width(), epd->height(), commonData.bgcolor);
getdisplay().fillScreen(commonData.bgcolor); // Clear display epd->fillScreen(commonData.bgcolor); // Clear display
// Show header if enabled // Show header if enabled
if (pages[pageNumber].description && pages[pageNumber].description->header or systemPage){ if (pages[pageNumber].description && pages[pageNumber].description->header or systemPage){
// build header using commonData // build header using commonData
displayHeader(commonData, date, time, hdop); // Show page header displayHeader(commonData, symbolmode, date, time, hdop); // Show page header
} }
// Call the particular page // Call the particular page
@@ -978,13 +984,13 @@ void OBP60Task(GwApi *api){
if (currentPage == NULL){ if (currentPage == NULL){
LOG_DEBUG(GwLog::ERROR,"page number %d not found", pageNumber); LOG_DEBUG(GwLog::ERROR,"page number %d not found", pageNumber);
// Error handling for missing page // Error handling for missing page
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
getdisplay().fillScreen(commonData.bgcolor); // Clear display epd->fillScreen(commonData.bgcolor); // Clear display
getdisplay().drawXBitmap(200 - unknown_width / 2, 150 - unknown_height / 2, unknown_bits, unknown_width, unknown_height, commonData.fgcolor); epd->drawXBitmap(200 - unknown_width / 2, 150 - unknown_height / 2, unknown_bits, unknown_width, unknown_height, commonData.fgcolor);
getdisplay().setCursor(140, 250); epd->setCursor(140, 250);
getdisplay().setFont(&Atari16px); epd->setFont(&Atari16px);
getdisplay().print("Here be dragons!"); epd->print("Here be dragons!");
getdisplay().nextPage(); // Partial update (fast) epd->nextPage(); // Partial update (fast)
} }
else{ else{
if (lastPage != pageNumber){ if (lastPage != pageNumber){
@@ -1004,10 +1010,10 @@ void OBP60Task(GwApi *api){
displayAlarm(commonData); displayAlarm(commonData);
} }
if (ret & PAGE_UPDATE) { if (ret & PAGE_UPDATE) {
getdisplay().nextPage(); // Partial update (fast) epd->nextPage(); // Partial update (fast)
} }
if (ret & PAGE_HIBERNATE) { if (ret & PAGE_HIBERNATE) {
getdisplay().hibernate(); epd->hibernate();
} }
} }