Compare commits

..

No commits in common. "39966098cc5c903a7df674164d502974a92c588d" and "e89d1ac62ee6c077a14620a204bab2fea9c033fb" have entirely different histories.

8 changed files with 236 additions and 265 deletions

View File

@ -0,0 +1,6 @@
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

@ -34,8 +34,7 @@
// 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;} // DEPRECATED GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> & getdisplay(){return display;}
gxepd2display *epd = &display;
#endif #endif
#ifdef DISPLAY_GDEY042T81 #ifdef DISPLAY_GDEY042T81
@ -50,16 +49,14 @@ gxepd2display *epd = &display;
// 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;} // DEPRECATED GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay(){return display;}
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;} // DEPRECATED GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay(){return display;}
gxepd2display *epd = &display;
#endif #endif
// Horter I2C moduls // Horter I2C moduls
@ -500,26 +497,26 @@ void displayHeader(CommonData &commonData, bool symbolmode, GwApi::BoatValue *da
#ifdef HARDWARE_V21 #ifdef HARDWARE_V21
// Display key lock status // Display key lock status
if (commonData.keylock) { if (commonData.keylock) {
epd->drawXBitmap(170, 1, lock_bits, icon_width, icon_height, commonData.fgcolor); getdisplay().drawXBitmap(170, 1, lock_bits, icon_width, icon_height, commonData.fgcolor);
} else { } else {
epd->drawXBitmap(166, 1, swipe_bits, swipe_width, swipe_height, commonData.fgcolor); getdisplay().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) {
epd->drawXBitmap(170, 1, battery_loading_bits, battery_width, battery_height, commonData.fgcolor); getdisplay().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) {
epd->drawXBitmap(170, 1, battery_0_bits, battery_width, battery_height, commonData.fgcolor); getdisplay().drawXBitmap(170, 1, battery_0_bits, battery_width, battery_height, commonData.fgcolor);
} else if (commonData.data.batteryLevelLiPo < 25) { } else if (commonData.data.batteryLevelLiPo < 25) {
epd->drawXBitmap(170, 1, battery_25_bits, battery_width, battery_height, commonData.fgcolor); getdisplay().drawXBitmap(170, 1, battery_25_bits, battery_width, battery_height, commonData.fgcolor);
} else if (commonData.data.batteryLevelLiPo < 50) { } else if (commonData.data.batteryLevelLiPo < 50) {
epd->drawXBitmap(170, 1, battery_50_bits, battery_width, battery_height, commonData.fgcolor); getdisplay().drawXBitmap(170, 1, battery_50_bits, battery_width, battery_height, commonData.fgcolor);
} else if (commonData.data.batteryLevelLiPo < 75) { } else if (commonData.data.batteryLevelLiPo < 75) {
epd->drawXBitmap(170, 1, battery_75_bits, battery_width, battery_height, commonData.fgcolor); getdisplay().drawXBitmap(170, 1, battery_75_bits, battery_width, battery_height, commonData.fgcolor);
} else { } else {
epd->drawXBitmap(170, 1, battery_100_bits, battery_width, battery_height, commonData.fgcolor); getdisplay().drawXBitmap(170, 1, battery_100_bits, battery_width, battery_height, commonData.fgcolor);
} }
#endif // VOLTAGE_SENSOR #endif // VOLTAGE_SENSOR
} }
@ -527,13 +524,13 @@ void displayHeader(CommonData &commonData, bool symbolmode, GwApi::BoatValue *da
// Heartbeat as page number // Heartbeat as page number
if (heartbeat) { if (heartbeat) {
epd->setTextColor(commonData.bgcolor); getdisplay().setTextColor(commonData.bgcolor);
epd->fillRect(201, 0, 23, 19, commonData.fgcolor); getdisplay().fillRect(201, 0, 23, 19, commonData.fgcolor);
} else { } else {
epd->setTextColor(commonData.fgcolor); getdisplay().setTextColor(commonData.fgcolor);
epd->drawRect(201, 0, 23, 19, commonData.fgcolor); getdisplay().drawRect(201, 0, 23, 19, commonData.fgcolor);
} }
epd->setFont(&Ubuntu_Bold8pt8b); getdisplay().setFont(&Ubuntu_Bold8pt8b);
drawTextCenter(211, 9, String(commonData.data.actpage)); drawTextCenter(211, 9, String(commonData.data.actpage));
heartbeat = !heartbeat; heartbeat = !heartbeat;
@ -541,19 +538,19 @@ void displayHeader(CommonData &commonData, bool symbolmode, GwApi::BoatValue *da
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();
epd->setTextColor(commonData.fgcolor); getdisplay().setTextColor(commonData.fgcolor);
epd->setFont(&Ubuntu_Bold8pt8b); getdisplay().setFont(&Ubuntu_Bold8pt8b);
epd->setCursor(230, 15); getdisplay().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);
epd->print(formatTime('m', local_tm->tm_hour, local_tm->tm_min, 0)); getdisplay().print(formatTime('m', local_tm->tm_hour, local_tm->tm_min, 0));
epd->print(" "); getdisplay().print(" ");
epd->print(formatDate(fmttype, local_tm->tm_year + 1900, local_tm->tm_mon + 1, local_tm->tm_mday)); getdisplay().print(formatDate(fmttype, local_tm->tm_year + 1900, local_tm->tm_mon + 1, local_tm->tm_mday));
epd->print(" "); getdisplay().print(" ");
epd->print(tz == 0 ? "UTC" : "LOT"); getdisplay().print(tz == 0 ? "UTC" : "LOT");
} else { } else {
drawTextRalign(396, 15, "RTC invalid"); drawTextRalign(396, 15, "RTC invalid");
} }
@ -564,15 +561,15 @@ void displayHeader(CommonData &commonData, bool symbolmode, GwApi::BoatValue *da
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;
epd->print(acttime); getdisplay().print(acttime);
epd->print(" "); getdisplay().print(" ");
epd->print(actdate); getdisplay().print(actdate);
epd->print(" "); getdisplay().print(" ");
epd->print(tz == 0 ? "UTC" : "LOT"); getdisplay().print(tz == 0 ? "UTC" : "LOT");
} }
else{ else{
if(commonData.config->getBool(commonData.config->useSimuData) == true){ if(commonData.config->getBool(commonData.config->useSimuData) == true){
epd->print("12:00 01.01.2024 LOT"); getdisplay().print("12:00 01.01.2024 LOT");
} }
else{ else{
drawTextRalign(396, 15, "No GPS data"); drawTextRalign(396, 15, "No GPS data");
@ -580,15 +577,15 @@ void displayHeader(CommonData &commonData, bool symbolmode, GwApi::BoatValue *da
} }
} // timesource == "GPS" } // timesource == "GPS"
else { else {
epd->print("No time source"); getdisplay().print("No time source");
} }
} }
} }
void displayFooter(CommonData &commonData) { void displayFooter(CommonData &commonData) {
epd->setFont(&Atari16px); getdisplay().setFont(&Atari16px);
epd->setTextColor(commonData.fgcolor); getdisplay().setTextColor(commonData.fgcolor);
#ifdef HARDWARE_V21 #ifdef HARDWARE_V21
// Frame around key icon area // Frame around key icon area
@ -597,14 +594,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
epd->drawLine(commonData.keydata[0].x, top, commonData.keydata[0].x+10, top, commonData.fgcolor); getdisplay().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++) {
epd->drawLine(commonData.keydata[i].x-10, top, commonData.keydata[i].x+10, top, commonData.fgcolor); getdisplay().drawLine(commonData.keydata[i].x-10, top, commonData.keydata[i].x+10, 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); getdisplay().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++) {
epd->drawLine(commonData.keydata[i].x + commonData.keydata[i].w, top, commonData.keydata[i].x + commonData.keydata[i].w, bottom, commonData.fgcolor); getdisplay().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;
@ -615,7 +612,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;
epd->drawXBitmap(x, y, iconmap[icon_name], icon_width, icon_height, commonData.fgcolor); getdisplay().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;
@ -630,8 +627,8 @@ void displayFooter(CommonData &commonData) {
} }
} }
} else { } else {
epd->setCursor(65, 295); getdisplay().setCursor(65, 295);
epd->print("Press 1 and 6 fast to unlock keys"); getdisplay().print("Press 1 and 6 fast to unlock keys");
} }
#endif #endif
#ifdef BOARD_OBP40S3 #ifdef BOARD_OBP40S3
@ -642,21 +639,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)) {
epd->fillCircle(x0 + i * (r * 2 + space), 290, r, commonData.fgcolor); getdisplay().fillCircle(x0 + i * (r * 2 + space), 290, r, commonData.fgcolor);
} else { } else {
epd->drawCircle(x0 + i * (r * 2 + space), 290, r, commonData.fgcolor); getdisplay().drawCircle(x0 + i * (r * 2 + space), 290, r, commonData.fgcolor);
} }
} }
// key indicators // key indicators
// left side = top key "menu" // left side = top key "menu"
epd->drawLine(0, 280, 10, 280, commonData.fgcolor); getdisplay().drawLine(0, 280, 10, 280, commonData.fgcolor);
epd->drawLine(55, 280, 65, 280, commonData.fgcolor); getdisplay().drawLine(55, 280, 65, 280, commonData.fgcolor);
epd->drawLine(65, 280, 65, 299, commonData.fgcolor); getdisplay().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"
epd->drawLine(390, 280, 399, 280, commonData.fgcolor); getdisplay().drawLine(390, 280, 399, 280, commonData.fgcolor);
epd->drawLine(335, 280, 345, 280, commonData.fgcolor); getdisplay().drawLine(335, 280, 345, 280, commonData.fgcolor);
epd->drawLine(335, 280, 335, 399, commonData.fgcolor); getdisplay().drawLine(335, 280, 335, 399, commonData.fgcolor);
drawTextCenter(366, 291, commonData.keydata[1].label); drawTextCenter(366, 291, commonData.keydata[1].label);
#endif #endif
} }
@ -669,31 +666,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;
epd->setFont(&Atari16px); getdisplay().setFont(&Atari16px);
epd->setTextColor(commonData.fgcolor); getdisplay().setTextColor(commonData.fgcolor);
// overlay // overlay
epd->drawRect(x, y, w, h, commonData.fgcolor); getdisplay().drawRect(x, y, w, h, commonData.fgcolor);
epd->fillRect(x + 1, y + 1, w - 1, h - 1, commonData.bgcolor); getdisplay().fillRect(x + 1, y + 1, w - 1, h - 1, commonData.bgcolor);
epd->drawRect(x + 3, y + 3, w - 5, h - 5, commonData.fgcolor); getdisplay().drawRect(x + 3, y + 3, w - 5, h - 5, commonData.fgcolor);
// exclamation icon in left top corner // exclamation icon in left top corner
epd->drawXBitmap(x + 16, y + 16, exclamation_bits, exclamation_width, exclamation_height, commonData.fgcolor); getdisplay().drawXBitmap(x + 16, y + 16, exclamation_bits, exclamation_width, exclamation_height, commonData.fgcolor);
// title // title
epd->setCursor(x + 64, y + 30); getdisplay().setCursor(x + 64, y + 30);
epd->print("A L A R M"); getdisplay().print("A L A R M");
epd->setCursor(x + 64, y + 48); getdisplay().setCursor(x + 64, y + 48);
epd->print("#" + commonData.alarm.id); getdisplay().print("#" + commonData.alarm.id);
epd->print(" from "); getdisplay().print(" from ");
epd->print(commonData.alarm.source); getdisplay().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) {
epd->setCursor(x + 16, y + 80 + n); getdisplay().setCursor(x + 16, y + 80 + n);
epd->print(l); getdisplay().print(l);
n += 16; n += 16;
if (n > 64) { if (n > 64) {
break; break;
@ -786,20 +783,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);
epd->fillRect(xb, yb, 100, 80, pcolor); getdisplay().fillRect(xb, yb, 100, 80, pcolor);
if(percent < 99){ if(percent < 99){
epd->fillRect(xb+t, yb+t, 100-(2*t), level, bcolor); getdisplay().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;
epd->fillRect(xp, yp, 20, 15, pcolor); getdisplay().fillRect(xp, yp, 20, 15, pcolor);
epd->fillRect(xp+t, yp+t, 20-(2*t), 15-(2*t), bcolor); getdisplay().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;
epd->fillRect(xm, ym, 20, 15, pcolor); getdisplay().fillRect(xm, ym, 20, 15, pcolor);
epd->fillRect(xm+t, ym+t, 20-(2*t), 15-(2*t), bcolor); getdisplay().fillRect(xm+t, ym+t, 20-(2*t), 15-(2*t), bcolor);
} }
// Solar graphic with fill level // Solar graphic with fill level
@ -811,17 +808,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);
epd->fillRect(xb, yb, 100, 80, pcolor); getdisplay().fillRect(xb, yb, 100, 80, pcolor);
if(percent < 99){ if(percent < 99){
epd->fillRect(xb+t, yb+t, 100-(2*t), level, bcolor); getdisplay().fillRect(xb+t, yb+t, 100-(2*t), level, bcolor);
} }
// Draw horizontel lines // Draw horizontel lines
epd->fillRect(xb, yb+28-t, 100, t, pcolor); getdisplay().fillRect(xb, yb+28-t, 100, t, pcolor);
epd->fillRect(xb, yb+54-t, 100, t, pcolor); getdisplay().fillRect(xb, yb+54-t, 100, t, pcolor);
// Draw vertical lines // Draw vertical lines
epd->fillRect(xb+19+t, yb, t, 80, pcolor); getdisplay().fillRect(xb+19+t, yb, t, 80, pcolor);
epd->fillRect(xb+39+2*t, yb, t, 80, pcolor); getdisplay().fillRect(xb+39+2*t, yb, t, 80, pcolor);
epd->fillRect(xb+59+3*t, yb, t, 80, pcolor); getdisplay().fillRect(xb+59+3*t, yb, t, 80, pcolor);
} }
@ -833,13 +830,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
epd->fillCircle(xb, yb, 45, pcolor); getdisplay().fillCircle(xb, yb, 45, pcolor);
epd->fillCircle(xb, yb, 41, bcolor); getdisplay().fillCircle(xb, yb, 41, bcolor);
// Insert G // Insert G
epd->setTextColor(pcolor); getdisplay().setTextColor(pcolor);
epd->setFont(&Ubuntu_Bold32pt8b); getdisplay().setFont(&Ubuntu_Bold32pt8b);
epd->setCursor(xb-22, yb+20); getdisplay().setCursor(xb-22, yb+20);
epd->print("G"); getdisplay().print("G");
} }
// Function to handle HTTP image request // Function to handle HTTP image request
@ -853,7 +850,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 = epd->getBuffer(); // EPD framebuffer uint8_t *fb = getdisplay().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

@ -44,9 +44,7 @@ extern const GFXfont Atari16px;
// Global functions // Global functions
#ifdef DISPLAY_GDEW042T2 #ifdef DISPLAY_GDEW042T2
GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> & getdisplay(); // DEPRECATED GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> & getdisplay();
typedef GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> gxepd2display;
extern gxepd2display *epd;
#endif #endif
#ifdef DISPLAY_GDEY042T81 #ifdef DISPLAY_GDEY042T81
@ -56,15 +54,11 @@ extern gxepd2display *epd;
#endif #endif
#ifdef DISPLAY_GYE042A87 #ifdef DISPLAY_GYE042A87
GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay(); // DEPRECATED GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay();
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(); // DEPRECATED GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay();
typedef GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> gxepd2display;
extern gxepd2display *epd;
#endif #endif
// Page display return values // Page display return values

View File

@ -1,82 +0,0 @@
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

@ -0,0 +1,38 @@
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

@ -0,0 +1,6 @@
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

@ -0,0 +1,12 @@
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

@ -323,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
epd->setFullWindow(); // Set full Refresh getdisplay().setFullWindow(); // Set full Refresh
//epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update //getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
epd->fillScreen(common.bgcolor);// Clear screen getdisplay().fillScreen(common.bgcolor);// Clear screen
epd->setTextColor(common.fgcolor); getdisplay().setTextColor(common.fgcolor);
epd->setFont(&Ubuntu_Bold20pt8b); getdisplay().setFont(&Ubuntu_Bold20pt8b);
epd->setCursor(65, 150); getdisplay().setCursor(65, 150);
epd->print("Undervoltage"); getdisplay().print("Undervoltage");
epd->setFont(&Ubuntu_Bold8pt8b); getdisplay().setFont(&Ubuntu_Bold8pt8b);
epd->setCursor(65, 175); getdisplay().setCursor(65, 175);
epd->print("Charge battery and restart system"); getdisplay().print("Charge battery and restart system");
epd->nextPage(); // Partial update getdisplay().nextPage(); // Partial update
epd->powerOff(); // Display power off getdisplay().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
@ -344,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
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
epd->fillScreen(common.bgcolor);// Clear screen getdisplay().fillScreen(common.bgcolor);// Clear screen
epd->setTextColor(common.fgcolor); getdisplay().setTextColor(common.fgcolor);
epd->setFont(&Ubuntu_Bold20pt8b); getdisplay().setFont(&Ubuntu_Bold20pt8b);
epd->setCursor(65, 150); getdisplay().setCursor(65, 150);
epd->print("Undervoltage"); getdisplay().print("Undervoltage");
epd->setFont(&Ubuntu_Bold8pt8b); getdisplay().setFont(&Ubuntu_Bold8pt8b);
epd->setCursor(65, 175); getdisplay().setCursor(65, 175);
epd->print("To wake up repower system"); getdisplay().print("To wake up repower system");
epd->nextPage(); // Partial update getdisplay().nextPage(); // Partial update
epd->powerOff(); // Display power off getdisplay().powerOff(); // Display power off
#endif #endif
// Stop system // Stop system
while(true){ while(true){
@ -531,37 +531,37 @@ void OBP60Task(GwApi *api){
#endif #endif
#ifdef DISPLAY_GDEY042T81 #ifdef DISPLAY_GDEY042T81
epd->init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
#else #else
epd->init(115200); // Init for normal displays getdisplay().init(115200); // Init for normal displays
#endif #endif
epd->setRotation(0); // Set display orientation (horizontal) getdisplay().setRotation(0); // Set display orientation (horizontal)
epd->setFullWindow(); // Set full Refresh getdisplay().setFullWindow(); // Set full Refresh
epd->firstPage(); // set first page getdisplay().firstPage(); // set first page
epd->fillScreen(commonData.bgcolor); getdisplay().fillScreen(commonData.bgcolor);
epd->setTextColor(commonData.fgcolor); getdisplay().setTextColor(commonData.fgcolor);
epd->nextPage(); // Full Refresh getdisplay().nextPage(); // Full Refresh
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
epd->fillScreen(commonData.bgcolor); getdisplay().fillScreen(commonData.bgcolor);
epd->nextPage(); // Fast Refresh getdisplay().nextPage(); // Fast Refresh
epd->nextPage(); // Fast Refresh getdisplay().nextPage(); // Fast Refresh
if(String(displaymode) == "Logo + QR Code" || String(displaymode) == "Logo"){ if(String(displaymode) == "Logo + QR Code" || String(displaymode) == "Logo"){
epd->fillScreen(commonData.bgcolor); getdisplay().fillScreen(commonData.bgcolor);
epd->drawBitmap(0, 0, gImage_Logo_OBP_400x300_sw, epd->width(), epd->height(), commonData.fgcolor); // Draw start logo getdisplay().drawBitmap(0, 0, gImage_Logo_OBP_400x300_sw, getdisplay().width(), getdisplay().height(), commonData.fgcolor); // Draw start logo
epd->nextPage(); // Fast Refresh getdisplay().nextPage(); // Fast Refresh
epd->nextPage(); // Fast Refresh getdisplay().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"){
epd->fillScreen(commonData.bgcolor); getdisplay().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
epd->nextPage(); // Fast Refresh getdisplay().nextPage(); // Fast Refresh
epd->nextPage(); // Fast Refresh getdisplay().nextPage(); // Fast Refresh
delay(SHOW_TIME); // QR code show time delay(SHOW_TIME); // QR code show time
} }
epd->fillScreen(commonData.bgcolor); getdisplay().fillScreen(commonData.bgcolor);
epd->nextPage(); // Fast Refresh getdisplay().nextPage(); // Fast Refresh
epd->nextPage(); // Fast Refresh getdisplay().nextPage(); // Fast Refresh
} }
// Init pages // Init pages
@ -872,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();
epd->setFullWindow(); // Set full update getdisplay().setFullWindow(); // Set full update
if(fastrefresh == "true"){ if(fastrefresh == "true"){
epd->nextPage(); // Full update getdisplay().nextPage(); // Full update
} }
else{ else{
epd->fillScreen(commonData.fgcolor); // Clear display getdisplay().fillScreen(commonData.fgcolor); // Clear display
#ifdef DISPLAY_GDEY042T81 #ifdef DISPLAY_GDEY042T81
epd->init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
#else #else
epd->init(115200); // Init for normal displays getdisplay().init(115200); // Init for normal displays
#endif #endif
epd->firstPage(); // Full update getdisplay().firstPage(); // Full update
epd->nextPage(); // Full update getdisplay().nextPage(); // Full update
// epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update // getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// epd->fillScreen(commonData.bgcolor); // Clear display // getdisplay().fillScreen(commonData.bgcolor); // Clear display
// epd->nextPage(); // Partial update // getdisplay().nextPage(); // Partial update
// epd->nextPage(); // Partial update // getdisplay().nextPage(); // Partial update
} }
delayedDisplayUpdate = false; delayedDisplayUpdate = false;
} }
@ -899,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");
epd->setFullWindow(); // Set full update getdisplay().setFullWindow(); // Set full update
if(fastrefresh == "true"){ if(fastrefresh == "true"){
epd->nextPage(); // Full update getdisplay().nextPage(); // Full update
} }
else{ else{
epd->fillScreen(commonData.fgcolor); // Clear display getdisplay().fillScreen(commonData.fgcolor); // Clear display
#ifdef DISPLAY_GDEY042T81 #ifdef DISPLAY_GDEY042T81
epd->init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
#else #else
epd->init(115200); // Init for normal displays getdisplay().init(115200); // Init for normal displays
#endif #endif
epd->firstPage(); // Full update getdisplay().firstPage(); // Full update
epd->nextPage(); // Full update getdisplay().nextPage(); // Full update
// epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update // getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// epd->fillScreen(commonData.bgcolor); // Clear display // getdisplay().fillScreen(commonData.bgcolor); // Clear display
// epd->nextPage(); // Partial update // getdisplay().nextPage(); // Partial update
// epd->nextPage(); // Partial update // getdisplay().nextPage(); // Partial update
} }
} }
@ -923,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");
epd->setFullWindow(); // Set full update getdisplay().setFullWindow(); // Set full update
if(fastrefresh == "true"){ if(fastrefresh == "true"){
epd->nextPage(); // Full update getdisplay().nextPage(); // Full update
} }
else{ else{
epd->fillScreen(commonData.fgcolor); // Clear display getdisplay().fillScreen(commonData.fgcolor); // Clear display
#ifdef DISPLAY_GDEY042T81 #ifdef DISPLAY_GDEY042T81
epd->init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
#else #else
epd->init(115200); // Init for normal displays getdisplay().init(115200); // Init for normal displays
#endif #endif
epd->firstPage(); // Full update getdisplay().firstPage(); // Full update
epd->nextPage(); // Full update getdisplay().nextPage(); // Full update
// epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update // getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// epd->fillScreen(commonData.bgcolor); // Clear display // getdisplay().fillScreen(commonData.bgcolor); // Clear display
// epd->nextPage(); // Partial update // getdisplay().nextPage(); // Partial update
// epd->nextPage(); // Partial update // getdisplay().nextPage(); // Partial update
} }
} }
@ -965,8 +965,8 @@ void OBP60Task(GwApi *api){
handleHstryBuf(api, &boatValues, hstryBufList); handleHstryBuf(api, &boatValues, hstryBufList);
// Clear display // Clear display
// epd->fillRect(0, 0, epd->width(), epd->height(), commonData.bgcolor); // getdisplay().fillRect(0, 0, getdisplay().width(), getdisplay().height(), commonData.bgcolor);
epd->fillScreen(commonData.bgcolor); // Clear display getdisplay().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){
@ -984,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
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
epd->fillScreen(commonData.bgcolor); // Clear display getdisplay().fillScreen(commonData.bgcolor); // Clear display
epd->drawXBitmap(200 - unknown_width / 2, 150 - unknown_height / 2, unknown_bits, unknown_width, unknown_height, commonData.fgcolor); getdisplay().drawXBitmap(200 - unknown_width / 2, 150 - unknown_height / 2, unknown_bits, unknown_width, unknown_height, commonData.fgcolor);
epd->setCursor(140, 250); getdisplay().setCursor(140, 250);
epd->setFont(&Atari16px); getdisplay().setFont(&Atari16px);
epd->print("Here be dragons!"); getdisplay().print("Here be dragons!");
epd->nextPage(); // Partial update (fast) getdisplay().nextPage(); // Partial update (fast)
} }
else{ else{
if (lastPage != pageNumber){ if (lastPage != pageNumber){
@ -1010,10 +1010,10 @@ void OBP60Task(GwApi *api){
displayAlarm(commonData); displayAlarm(commonData);
} }
if (ret & PAGE_UPDATE) { if (ret & PAGE_UPDATE) {
epd->nextPage(); // Partial update (fast) getdisplay().nextPage(); // Partial update (fast)
} }
if (ret & PAGE_HIBERNATE) { if (ret & PAGE_HIBERNATE) {
epd->hibernate(); getdisplay().hibernate();
} }
} }