Compare commits

...

3 Commits

8 changed files with 265 additions and 236 deletions

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

@ -34,7 +34,8 @@
// 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
@ -49,14 +50,16 @@ 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;} 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
@ -497,26 +500,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) {
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
} }
@ -524,13 +527,13 @@ void displayHeader(CommonData &commonData, bool symbolmode, GwApi::BoatValue *da
// 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;
@ -538,19 +541,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();
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");
} }
@ -561,15 +564,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;
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");
@ -577,15 +580,15 @@ void displayHeader(CommonData &commonData, bool symbolmode, GwApi::BoatValue *da
} }
} // 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
@ -594,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;
@ -612,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;
@ -627,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
@ -639,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
} }
@ -666,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;
@ -783,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
@ -808,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);
} }
@ -830,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
@ -850,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

@ -44,7 +44,9 @@ 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
@ -54,11 +56,15 @@ 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

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

@ -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,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

@ -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
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
@ -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
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){
@ -531,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
@ -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();
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;
} }
@ -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");
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
} }
} }
@ -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");
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
} }
} }
@ -965,8 +965,8 @@ 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){
@ -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
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){
@ -1010,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();
} }
} }