diff --git a/lib/obp60task/OBP60Extensions.cpp b/lib/obp60task/OBP60Extensions.cpp index ccbf343..2da55da 100644 --- a/lib/obp60task/OBP60Extensions.cpp +++ b/lib/obp60task/OBP60Extensions.cpp @@ -11,6 +11,8 @@ #include "imglib.h" // Character sets +#include "fonts/DSEG7Classic-BoldItalic10pt7b.h" +#include "fonts/DSEG7Classic-BoldItalic12pt7b.h" #include "fonts/DSEG7Classic-BoldItalic16pt7b.h" #include "fonts/DSEG7Classic-BoldItalic20pt7b.h" #include "fonts/DSEG7Classic-BoldItalic26pt7b.h" @@ -539,17 +541,21 @@ std::vector wordwrap(String &line, uint16_t maxwidth) { } // Draw centered text -void drawTextCenter(int16_t cx, int16_t cy, String text) { +// bool dsegAdjust = false - optional, for adjustment of DSEG italic font +// returns left edge of printed string +int16_t drawTextCenter(int16_t cx, int16_t cy, String text, bool dsegAdjust) { int16_t x1, y1; uint16_t w, h; - displayGetTextBounds(text, 0, 0, &x1, &y1, &w, &h); + displayGetTextBounds(text, 0, 0, &x1, &y1, &w, &h, dsegAdjust); int16_t cursorX = cx - (x1 + static_cast(w / 2)); int16_t cursorY = cy - (y1 + static_cast(h / 2)); getdisplay().setCursor(cursorX, cursorY); getdisplay().print(text); + + return cursorX; } -// Draw centered botton with centered text +// Draw centered button with centered text void drawButtonCenter(int16_t cx, int16_t cy, int8_t sx, int8_t sy, String text, uint16_t fg, uint16_t bg, bool inverted) { int16_t x1, y1; uint16_t w, h; @@ -572,17 +578,155 @@ void drawButtonCenter(int16_t cx, int16_t cy, int8_t sx, int8_t sy, String text, } // Draw right aligned text -void drawTextRalign(int16_t x, int16_t y, String text) { - int16_t x1, y1; - uint16_t w, h; -#ifdef TFT_DISPLAY - w = getdisplay().textWidth(text); - h = getdisplay().fontHeight(); -#else - getdisplay().getTextBounds(text, 0, 150, &x1, &y1, &w, &h); -#endif - getdisplay().setCursor(x - w - 1, y); // '-1' required since some strings wrap around w/o it +// int16_t x - upper right x position for text to start printing +// int16_t y - upper right y position for text to start printing +// const String& text - text to be printed +// bool dsegAdjust = false - optional, for adjustment of DSEG italic font +// returns left edge of printed string +int16_t drawTextRalign(int16_t x, int16_t y, const String& text, bool dsegAdjust) { + int16_t x1 = 0, y1 = 0; + uint16_t w = 0, h = 0; + + displayGetTextBounds(text, 0, y, &x1, &y1, &w, &h, dsegAdjust); + int16_t cursorX = x - x1 - w; + getdisplay().setCursor(cursorX, y); getdisplay().print(text); + + return cursorX; // currently visible left edge +} + +// Implementation of ; does the actual printing +static void printBoatValueImpl(const String &sBoatValue, const int16_t x, const int16_t y, + const int8_t align, const int8_t fontSize, bool smallDecs) { + const GFXfont *mainFont = nullptr; + const GFXfont *decimalFont = nullptr; + constexpr bool dsegAdjust = true; + + String integerPart = ""; + String decimalPart = ""; + int16_t dot = 0; + + uint16_t intW = 0, decW = 0; + int16_t decimalLeftX = 0; + + // ----------------------------------------------------------------- + // Font selection + // ----------------------------------------------------------------- + if (sBoatValue.indexOf('"') != -1) + { + // LAT/LON values + if (fontSize <= 12) + mainFont = &Ubuntu_Bold12pt8b; + else if (fontSize <= 16) + mainFont = &Ubuntu_Bold16pt8b; + else if (fontSize <= 20) + mainFont = &Ubuntu_Bold20pt8b; + else + mainFont = &Ubuntu_Bold32pt8b; + + smallDecs = false; // disable small decimals for LAT/LON in any case + } + else if (fontSize <= 12) { + mainFont = &DSEG7Classic_BoldItalic12pt7b; + decimalFont = &DSEG7Classic_BoldItalic10pt7b; + } else if (fontSize <= 16) { + mainFont = &DSEG7Classic_BoldItalic16pt7b; + decimalFont = &DSEG7Classic_BoldItalic12pt7b; + } else if (fontSize <= 20) { + mainFont = &DSEG7Classic_BoldItalic20pt7b; + decimalFont = &DSEG7Classic_BoldItalic16pt7b; + } else if (fontSize <= 26) { + mainFont = &DSEG7Classic_BoldItalic26pt7b; + decimalFont = &DSEG7Classic_BoldItalic20pt7b; + } else if (fontSize <= 30) { + mainFont = &DSEG7Classic_BoldItalic30pt7b; + decimalFont = &DSEG7Classic_BoldItalic26pt7b; + } else if (fontSize <= 42) { + mainFont = &DSEG7Classic_BoldItalic42pt7b; + decimalFont = &DSEG7Classic_BoldItalic30pt7b; + } else { + mainFont = &DSEG7Classic_BoldItalic60pt7b; + decimalFont = &DSEG7Classic_BoldItalic42pt7b; + } + + // separate integer and decimal part of the value + dot = sBoatValue.indexOf('.'); + if (dot == -1) { // no decimal point found + integerPart = sBoatValue; + decimalPart = ""; + smallDecs = false; // print only integer part + } else { + integerPart = sBoatValue.substring(0, dot + 1); // keep decimal point + decimalPart = sBoatValue.substring(dot + 1); + } + + // Measure integer part + int16_t ix1, iy1; + uint16_t iw, ih; + display.setFont(mainFont); + displayGetTextBounds(integerPart, 0, 0, &ix1, &iy1, &iw, &ih, dsegAdjust); + intW = ix1 + iw; + + // Measure decimal part only if one actually exists + decW = 0; + if (dot != -1 && decimalPart.length() > 0) { + int16_t dx1, dy1; + uint16_t dw, dh; + display.setFont(smallDecs ? decimalFont : mainFont); + displayGetTextBounds(decimalPart, 0, 0, &dx1, &dy1, &dw, &dh, dsegAdjust); + decW = dx1 + dw; + } + + const int16_t totalWidth = intW + decW; + int16_t startX; + switch (align) { + case 0: // LEFT + startX = x; + break; + case 1: // CENTER + startX = x - totalWidth / 2; + break; + case 2: // RIGHT + default: + startX = x - totalWidth; + break; + } + decimalLeftX = startX + intW; + + // Draw integer part + display.setFont(mainFont); + getdisplay().setCursor(startX, y); + getdisplay().print(integerPart); + + // Draw decimal part only when present + if (dot != -1 && decimalPart.length() > 0) { + display.setFont(smallDecs ? decimalFont : mainFont); + getdisplay().setCursor(decimalLeftX, y); + getdisplay().print(decimalPart); + } +} + +// Print boat data value at x,y position with selectable alignment +// Version with ; formats the boat data value and then prints the formatted value +// GwApi::BoatValue *bValue - boat value to print +// CommonData &commondata - required for function +// int16_t x - upper left/right x position for text to start printing +// int16_t y - upper left/right y position for text to start printing +// int8_t align - alignment [0,1,2] of the value: 0 = left, 1 = center, 2 = right +// int8_t fontSize - font size for integer part of number or for full value, if is /not set +// bool smallDecs - flag specifies if decimals will be printed in smaller fontsize [default = false] +void printBoatValue(GwApi::BoatValue *bValue, CommonData &commondata, const int16_t x, const int16_t y, + const int8_t align, const int8_t fontSize, const bool smallDecs) +{ + String sBoatValue = formatValue(bValue, commondata).svalue; + printBoatValueImpl(sBoatValue, x, y, align, fontSize, smallDecs); +} + +// Print boat data value at x,y position with selectable alignment; oerload with ready-to-print ; omits boat data value formatting +void printBoatValue(const String &sBoatValue, const int16_t x, const int16_t y, + const int8_t align, const int8_t fontSize, const bool smallDecs) +{ + printBoatValueImpl(sBoatValue, x, y, align, fontSize, smallDecs); } // Draw text inside box, normal or inverted diff --git a/lib/obp60task/OBP60Extensions.h b/lib/obp60task/OBP60Extensions.h index 9e2bc99..3129d50 100644 --- a/lib/obp60task/OBP60Extensions.h +++ b/lib/obp60task/OBP60Extensions.h @@ -56,6 +56,8 @@ extern sdmmc_card_t *sdcard; #endif // Fonts declarations for display (#includes see OBP60Extensions.cpp) +extern const GFXfont DSEG7Classic_BoldItalic10pt7b; +extern const GFXfont DSEG7Classic_BoldItalic12pt7b; extern const GFXfont DSEG7Classic_BoldItalic16pt7b; extern const GFXfont DSEG7Classic_BoldItalic20pt7b; extern const GFXfont DSEG7Classic_BoldItalic26pt7b; @@ -695,11 +697,17 @@ inline void displaySetFullWindow() { // replacement for getTextBounds that works with both EPD and TFT inline void displayGetTextBounds(const String &txt, int16_t x, int16_t y, int16_t *x0, int16_t *y0, - uint16_t *w, uint16_t *h) { + uint16_t *w, uint16_t *h, const bool dsegAdjust = false) { +String str = txt; +// make sure that we always have a char with max size at last position for boundary test +// for monotype italic DSEG7 font to avoid text wobbling +if (dsegAdjust && str.length() > 0 && isDigit(str[str.length() - 1])) { + str.setCharAt(str.length() - 1, '8'); +} #ifdef TFT_DISPLAY - getdisplay().getTextBounds(txt, x, y, x0, y0, w, h); + getdisplay().getTextBounds(str, x, y, x0, y0, w, h); #else - getdisplay().getTextBounds(txt, x, y, x0, y0, w, h); + getdisplay().getTextBounds(str, x, y, x0, y0, w, h); #endif } @@ -732,10 +740,12 @@ void setBuzzerPower(uint power); // Set buzzer power String xdrDelete(String input); // Delete xdr prefix from string -void drawTextCenter(int16_t cx, int16_t cy, String text); +int16_t drawTextCenter(int16_t cx, int16_t cy, String text, bool dsegAdjust = false); void drawButtonCenter(int16_t cx, int16_t cy, int8_t sx, int8_t sy, String text, uint16_t fg, uint16_t bg, bool inverted); -void drawTextRalign(int16_t x, int16_t y, String text); +int16_t drawTextRalign(int16_t x, int16_t y, const String& text, bool dsegAdjust = false); void drawTextBoxed(Rect box, String text, uint16_t fg, uint16_t bg, bool inverted, bool border); +void printBoatValue(GwApi::BoatValue *bValue, CommonData &commondata, const int16_t x, const int16_t y, const int8_t align, const int8_t fontSize, const bool smallDecs = false); +void printBoatValue(const String &sBoatValue, const int16_t x, const int16_t y, const int8_t align, const int8_t fontSize, const bool smallDecs = false); 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); diff --git a/lib/obp60task/OBP60Formatter.cpp b/lib/obp60task/OBP60Formatter.cpp index 18cff2f..c6ddda2 100644 --- a/lib/obp60task/OBP60Formatter.cpp +++ b/lib/obp60task/OBP60Formatter.cpp @@ -3,6 +3,7 @@ #include #include "GwApi.h" #include "Pagedata.h" +#include "OBPDataOperations.h" // ToDo // simulation data @@ -49,15 +50,10 @@ String formatLongitude(double lon) { return String(degree, 0) + "\x90 " + String(minute, 4) + "' " + ((lon > 0) ? "E" : "W"); } -// Convert and format boat value from SI to user defined format (definition for compatibility purposes) -FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata) { - - return formatValue(value, commondata, false); // call with standard handling of user setting for simulation data -} - // Convert and format boat value from SI to user defined format -// generate random simulation data; can be deselected to use conversion+formatting function even in simulation mode -FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool ignoreSimuDataSetting){ +// generates random simulation data; can be deselected to use conversion+formatting function even in simulation mode +// String setPrecision - overrides precision setting from config; if not set, use config setting +FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool ignoreSimuDataSetting, String setPrecision) { GwLog *logger = commondata.logger; FormattedData result; static int dayoffset = 0; @@ -75,12 +71,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool String tempFormat = commondata.config->getString(commondata.config->tempFormat); // [K|°C|°F] String dateFormat = commondata.config->getString(commondata.config->dateFormat); // [DE|GB|US] String precision = commondata.config->getString(commondata.config->valueprecision); // [1|2] + bool usesimudata = commondata.config->getBool(commondata.config->useSimuData); // [on|off] - bool usesimudata; + if (setPrecision == "1" || setPrecision == "2") { + precision = setPrecision; // override precision setting from config + } if (ignoreSimuDataSetting){ usesimudata = false; // ignore user setting for simulation data; we want to format the boat value passed to this function - } else { - usesimudata = commondata.config->getBool(commondata.config->useSimuData); // [on|off] } // If boat value not valid @@ -95,21 +92,20 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool double limit_dec_10; double limit_dec_100; if (precision == "1") { - // - //All values are displayed using a DSEG7* font. In this font, ' ' is a very short space, and '.' takes up no space at all. - //For a space that is as long as a number, '!' is used. For details see https://www.keshikan.net/fonts-e.html - // - fmt_dec_1 = "!%1.1f"; //insert a blank digit and then display a two-digit number - fmt_dec_10 = "!%2.0f"; //insert a blank digit and then display a two-digit number - fmt_dec_100 = "%3.0f"; //dispay a three digit number - limit_dec_10=9.95; // use fmt_dec_1 below this number to avoid formatting 9.96 as 10.0 instead of 10 - limit_dec_100=99.5; + //All values are displayed using a DSEG7* font. In this font, ' ' is a very short space, and '.' takes up no space at all. + //For a space that is as long as a number, '!' is used. For details see https://www.keshikan.net/fonts-e.html + + fmt_dec_1 = "!%1.1f"; // blank digit + 2 digit number, incl. 1 decimal + fmt_dec_10 = "%3.1f"; // 3 digit number, incl. 1 decimal + fmt_dec_100 = "%3.0f"; // 3 digit number, no decimal + limit_dec_10=9.95; // use fmt_dec_1 below this number to avoid formatting 9.96 as 10.0 instead of 10 + limit_dec_100=99.5; } else { fmt_dec_1 = "%3.2f"; fmt_dec_10 = "%3.1f"; fmt_dec_100 = "%3.0f"; - limit_dec_10=9.995; - limit_dec_100=99.95; + limit_dec_10=9.995; + limit_dec_100=99.95; } // LOG_DEBUG(GwLog::DEBUG,"formatValue init: getFormat: %s date->value: %f time->value: %f", value->getFormat(), commondata.date->value, commondata.time->value); @@ -216,10 +212,10 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool rawvalue = value->value; } else { - course = M_PI_2 + float(random(-17, 17) / 100.0); // create random course/wind values with 90° +/- 10° + course = M_PI_2 + float(random(-26, 26) / 100.0); // create random course/wind values with 90° +/- 15° rawvalue = course; } - course = course * RAD_TO_DEG; // Unit conversion form rad to deg + course = WindUtils::to360(course * RAD_TO_DEG); // Unit conversion form rad to deg // Format 3 numbers with prefix zero snprintf(buffer,bsize,"%03.0f",course); @@ -908,6 +904,40 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool return result; } +// Convert and format boat value from SI to user defined format +FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata) { + + return formatValue(value, commondata, false, String("-1")); // call with standard setting for simulation data and precision setting from config +} + +// Convert and format boat value from SI to user defined format with simulation data setting and precision setting from config +FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool ignoreSimuDataSetting) { + + return formatValue(value, commondata, ignoreSimuDataSetting, String("-1")); +} + +// Convert and format boat value from SI to user defined format with standard setting for simulation data and specified precision +FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, String setPrecision) { + + return formatValue(value, commondata, false, setPrecision); +} + +// Format double value from SI to user defined format and convert to string user defined precision setting +String formatValue(const double &value, const String &vFormat, CommonData &commondata) +{ + GwApi::BoatValue tmpBVal("dummy"); // temporary boat value for string formatter + String sVal; + + tmpBVal.setFormat(vFormat); + tmpBVal.valid = true; + tmpBVal.value = value; + sVal = formatValue(&tmpBVal, commondata, false, String("-1")).svalue; // Formatted value as string including unit conversion and switching decimal places + if (sVal.length() > 0 && sVal[0] == '!') { + sVal = sVal.substring(1); // cut leading "!" created at OBPFormatter; doesn't work for other fonts than 7SEG + } + return sVal; +} + // Helper method for conversion of any data value from SI to user defined format double convertValue(const double &value, const String &name, const String &format, CommonData &commondata) { diff --git a/lib/obp60task/OBPcharts.cpp b/lib/obp60task/OBPcharts.cpp index ae9a7b6..efb18ca 100644 --- a/lib/obp60task/OBPcharts.cpp +++ b/lib/obp60task/OBPcharts.cpp @@ -581,6 +581,11 @@ void Chart::drawChrtValAxis(const ChrtDir chrtDir, const ChrtSize chrtSz, const // Print current data value void Chart::prntCurrValue(const ChrtDir chrtDir, GwApi::BoatValue& currValue) { + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; + static constexpr bool smallDecimals = true; // print data value always with small decimals + const int xPosVal = (chrtDir == HORIZONTAL) ? cRoot.x + (timAxis / 2) - 74 : cRoot.x + 31; const int yPosVal = (chrtDir == HORIZONTAL) ? cRoot.y + valAxis : cRoot.y + timAxis; @@ -593,19 +598,20 @@ void Chart::prntCurrValue(const ChrtDir chrtDir, GwApi::BoatValue& currValue) getdisplay().drawRect(xPosVal, yPosVal - 39, 146, 37, fgColor); // Draw box for value // value - getdisplay().setFont(&DSEG7Classic_BoldItalic16pt7b); - getdisplay().setCursor(xPosVal + 1, yPosVal - 6); - getdisplay().print(sdbValue); + printBoatValue(sdbValue, xPosVal + 93, yPosVal - 6, RIGHT, 16, smallDecimals); +// getdisplay().setFont(&DSEG7Classic_BoldItalic16pt7b); +// getdisplay().setCursor(xPosVal + 1, yPosVal - 6); +// getdisplay().print(sdbValue); // name getdisplay().setFont(&Ubuntu_Bold10pt8b); - getdisplay().setCursor(xPosVal + 100, yPosVal - 23); + getdisplay().setCursor(xPosVal + 97, yPosVal - 23); String name = xdrDelete(dbName); getdisplay().print(name.substring(0, 3)); // Name, limited to 3 characters // unit getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().setCursor(xPosVal + 101, yPosVal - 8); + getdisplay().setCursor(xPosVal + 98, yPosVal - 8); getdisplay().print(dbUnit); } diff --git a/lib/obp60task/PageAutopilot.cpp b/lib/obp60task/PageAutopilot.cpp index b57c159..4671938 100644 --- a/lib/obp60task/PageAutopilot.cpp +++ b/lib/obp60task/PageAutopilot.cpp @@ -31,6 +31,10 @@ const float Compass_LineDelta = 8.0;// Compass band: 1deg = 5 Pixels, 10deg = 50 class PageAutopilot : public Page { + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; + int WhichDataCompass = ShowHDM; // Start value int WhichDataDisplay = ShowHDM; // Start value @@ -85,6 +89,7 @@ class PageAutopilot : public Page bool holdvalues = config->getBool(config->holdvalues); String flashLED = config->getString(config->flashLED); String backlightMode = config->getString(config->backlight); + bool smallDecimals = config->getBool(config->smallDecimals); GwApi::BoatValue *bvalue; String DataName[HowManyValues]; @@ -130,14 +135,12 @@ class PageAutopilot : public Page getdisplay().setFont(&Ubuntu_Bold12pt8b); getdisplay().setCursor(10, 120); getdisplay().print(DataUnits[WhichDataDisplay]); - getdisplay().setCursor(190, 120); - getdisplay().setFont(&DSEG7Classic_BoldItalic42pt7b); - + if(holdvalues == false){ - getdisplay().print(DataText[WhichDataDisplay]); // Real value as formated string + printBoatValue(DataText[WhichDataDisplay], 190, 120, LEFT, 42, smallDecimals); // Real value as formated string } else{ - getdisplay().print(OldDataText[WhichDataDisplay]); // Old value as formated string + printBoatValue(OldDataText[WhichDataDisplay], 190, 120, LEFT, 42, smallDecimals); // Old value as formated string } if(DataValid[WhichDataDisplay] == true){ OldDataText[WhichDataDisplay] = DataText[WhichDataDisplay]; // Save the old value diff --git a/lib/obp60task/PageBME280.cpp b/lib/obp60task/PageBME280.cpp index e54b629..a82bc91 100644 --- a/lib/obp60task/PageBME280.cpp +++ b/lib/obp60task/PageBME280.cpp @@ -5,6 +5,10 @@ class PageBME280 : public Page { + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; + public: PageBME280(CommonData &common){ commonData = &common; @@ -37,6 +41,7 @@ class PageBME280 : public Page String flashLED = config->getString(config->flashLED); String backlightMode = config->getString(config->backlight); String useenvsensor = config->getString(config->useEnvSensor); + bool smallDecimals = config->getBool(config->smallDecimals); // Get sensor values #1 String name1 = "Temp"; // Value name @@ -121,12 +126,8 @@ class PageBME280 : public Page getdisplay().setCursor(20, 90); getdisplay().print(unit1); // Unit - // Switch font if format for any values - getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b); - getdisplay().setCursor(180, 90); - // Show bus data - getdisplay().print(svalue1); // Real value as formated string + printBoatValue(svalue1, 380, 90, RIGHT, 30, smallDecimals); // Real value as formated string // ############### Horizontal Line ################ @@ -145,12 +146,8 @@ class PageBME280 : public Page getdisplay().setCursor(20, 180); getdisplay().print(unit2); // Unit - // Switch font if format for any values - getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b); - getdisplay().setCursor(180, 180); - // Show bus data - getdisplay().print(svalue2); // Real value as formated string + printBoatValue(svalue2, 380, 180, RIGHT, 30, smallDecimals); // Real value as formated string // ############### Horizontal Line ################ @@ -169,12 +166,8 @@ class PageBME280 : public Page getdisplay().setCursor(20, 270); getdisplay().print(unit3); // Unit - // Switch font if format for any values - getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b); - getdisplay().setCursor(140, 270); - // Show bus data - getdisplay().print(svalue3); // Real value as formated string + printBoatValue(svalue3, 380, 270, RIGHT, 30, smallDecimals); // Real value as formated string return PAGE_UPDATE; }; diff --git a/lib/obp60task/PageBattery.cpp b/lib/obp60task/PageBattery.cpp index e53f12f..e5951c1 100644 --- a/lib/obp60task/PageBattery.cpp +++ b/lib/obp60task/PageBattery.cpp @@ -5,6 +5,10 @@ class PageBattery : public Page { + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; + int average = 0; // Average type [0...3], 0=off, 1=10s, 2=60s, 3=300s public: @@ -56,6 +60,7 @@ class PageBattery : public Page String backlightMode = config->getString(config->backlight); String powsensor1 = config->getString(config->usePowSensor1); bool simulation = config->getBool(config->useSimuData); + bool smallDecimals = config->getBool(config->smallDecimals); // Get voltage value String name1 = "VBat"; // Value name @@ -218,17 +223,13 @@ class PageBattery : public Page getdisplay().setCursor(20, 90); getdisplay().print(unit1); // Unit - // Show value - getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b); - getdisplay().setCursor(180, 90); - - // Show bus data + // Show bus value if(String(powsensor1) != "off"){ - getdisplay().print(value1,2); // Real value as formated string - } - else{ - getdisplay().print("---"); // No sensor data (sensor is off) + svalue1 = formatValue(value1, String("formatXdr:U:V"), *commonData); + } else{ + svalue1 = "---"; } + printBoatValue(svalue1, 380, 90, RIGHT, 30, smallDecimals); // Real value as formated string // ############### Horizontal Line ################ @@ -247,17 +248,13 @@ class PageBattery : public Page getdisplay().setCursor(20, 180); getdisplay().print(unit2); // Unit - // Show value - getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b); - getdisplay().setCursor(180, 180); - - // Show bus data + // Show bus value if(String(powsensor1) != "off"){ - getdisplay().print(value2,1); // Real value as formated string - } - else{ - getdisplay().print("---"); // No sensor data (sensor is off) + svalue2 = formatValue(value2, String("formatXdr:U:V"), *commonData); + } else{ + svalue2 = "---"; } + printBoatValue(svalue2, 380, 180, RIGHT, 30, smallDecimals); // Real value as formated string // ############### Horizontal Line ################ @@ -276,17 +273,13 @@ class PageBattery : public Page getdisplay().setCursor(20, 270); getdisplay().print(unit3); // Unit - // Show value - getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b); - getdisplay().setCursor(180, 270); - - // Show bus data + // Show bus value if(String(powsensor1) != "off"){ - getdisplay().print(value3,1); // Real value as formated string - } - else{ - getdisplay().print("---"); // No sensor data (sensor is off) + svalue3 = formatValue(value3, String("formatXdr:U:V"), *commonData); + } else{ + svalue3 = "---"; } + printBoatValue(svalue3, 380, 270, RIGHT, 30, smallDecimals); // Real value as formated string return PAGE_UPDATE; }; diff --git a/lib/obp60task/PageBattery2.cpp b/lib/obp60task/PageBattery2.cpp index b691c30..d78e237 100644 --- a/lib/obp60task/PageBattery2.cpp +++ b/lib/obp60task/PageBattery2.cpp @@ -5,6 +5,10 @@ class PageBattery2 : public Page { +static constexpr int8_t LEFT = 0; +static constexpr int8_t CENTER = 1; +static constexpr int8_t RIGHT = 2; + bool init = false; // Marker for init done int 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 @@ -65,6 +69,7 @@ public: String batType = config->getString(config->batteryType); String backlightMode = config->getString(config->backlight); String powerSensor = config->getString(config->usePowSensor1); + bool smallDecimals = config->getBool(config->smallDecimals); double value1 = 0; // Battery voltage double value2 = 0; // Battery current @@ -198,20 +203,16 @@ public: getdisplay().print(batType); // Show voltage type - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(10, 140); int bvoltage = 0; if(String(batVoltage) == "12V") bvoltage = 12; else bvoltage = 24; - getdisplay().print(bvoltage); + printBoatValue(String(bvoltage), 10, 140, LEFT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("V"); // Show battery capacity - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(10, 200); - if(batCapacity <= 999) getdisplay().print(batCapacity, 0); - if(batCapacity > 999) getdisplay().print(float(batCapacity/1000.0), 1); + String svalueCapacity = (batCapacity <= 999) ? String(batCapacity) : String(float(batCapacity/1000.0), 1); + printBoatValue(svalueCapacity, 10, 200, LEFT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); if(batCapacity <= 999) getdisplay().print("Ah"); if(batCapacity > 999) getdisplay().print("kAh"); @@ -248,20 +249,19 @@ public: } // Show fill level in percent - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(150, 200); - getdisplay().print(batPercentage); + printBoatValue(String(batPercentage), 150, 200, LEFT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("%"); // Show time to full discharge - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(150, 260); + String svalueRange; if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){ - if(batRange < 9.9) getdisplay().print(batRange, 1); - else getdisplay().print(batRange, 0); + svalueRange = (batRange < 9.9) ? String(batRange, 1) : String(batRange, 0); } - else getdisplay().print("--"); + else{ + svalueRange = "--"; + } + printBoatValue(svalueRange, 150, 260, LEFT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("h"); @@ -282,54 +282,38 @@ public: getdisplay().print("Sensor Modul"); // Reading bus data or using simulation data - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(260, 140); - if(simulation == true){ - if(batVoltage == "12V"){ - value1 = 12.0; - } - if(batVoltage == "24V"){ - value1 = 24.0; - } - value1 += float(random(0, 5)) / 10; // Simulation data - getdisplay().print(value1,1); - } - else{ - // Check for valid real data, display also if hold values activated - if(valid1 == true || holdvalues == true){ - // Resolution switching - if(value1 <= 9.9) getdisplay().print(value1, 2); - if(value1 > 9.9 && value1 <= 99.9)getdisplay().print(value1, 1); - if(value1 > 99.9) getdisplay().print(value1, 0); - } - else{ - getdisplay().print("---"); // Missing bus data - } + String svalue1; + // Check for valid real data, display also if hold values activated + if(valid1 == true || holdvalues == true){ + svalue1 = formatValue(value1, String("formatXdr:U:V"), *commonData); + } else { + svalue1 = "---"; // Missing bus data } + printBoatValue(svalue1, 355, 140, RIGHT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("V"); // Show actual current in A - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(260, 200); + String svalue2; if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){ - if(value2 <= 9.9) getdisplay().print(value2, 2); - if(value2 > 9.9 && value2 <= 99.9)getdisplay().print(value2, 1); - if(value2 > 99.9) getdisplay().print(value2, 0); + svalue2 = formatValue(value2, String("formatXdr:I:A"), *commonData); } - else getdisplay().print("---"); + else{ + svalue2 = "---"; + } + printBoatValue(svalue2, 355, 200, RIGHT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("A"); // Show actual consumption in W - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(260, 260); + String svalue3; if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){ - if(value3 <= 9.9) getdisplay().print(value3, 2); - if(value3 > 9.9 && value3 <= 99.9)getdisplay().print(value3, 1); - if(value3 > 99.9) getdisplay().print(value3, 0); + svalue3 = formatValue(value3, String("formatXdr:G:"), *commonData); } - else getdisplay().print("---"); + else{ + svalue3 = "---"; + } + printBoatValue(svalue3, 355, 260, RIGHT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("W"); diff --git a/lib/obp60task/PageCompass.cpp b/lib/obp60task/PageCompass.cpp index f5e14b5..45e5edf 100644 --- a/lib/obp60task/PageCompass.cpp +++ b/lib/obp60task/PageCompass.cpp @@ -24,6 +24,10 @@ const float Compass_LineDelta = 8.0;// Compass band: 1deg = 5 Pixels, 10deg = 50 class PageCompass : public Page { + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; + int WhichDataCompass = ShowHDM; int WhichDataDisplay = ShowHDM; @@ -75,6 +79,7 @@ class PageCompass : public Page bool holdvalues = config->getBool(config->holdvalues); String flashLED = config->getString(config->flashLED); String backlightMode = config->getString(config->backlight); + bool smallDecimals = config->getBool(config->smallDecimals); GwApi::BoatValue *bvalue; String DataName[HowManyValues]; @@ -122,14 +127,12 @@ class PageCompass : public Page getdisplay().setFont(&Ubuntu_Bold12pt8b); getdisplay().setCursor(10, 120); getdisplay().print(DataUnits[WhichDataDisplay]); - getdisplay().setCursor(190, 120); - getdisplay().setFont(&DSEG7Classic_BoldItalic42pt7b); - + if(holdvalues == false){ - getdisplay().print(DataText[WhichDataDisplay]); // Real value as formated string + printBoatValue(DataText[WhichDataDisplay], 190, 120, LEFT, 42, smallDecimals); // Real value as formated string } else{ - getdisplay().print(OldDataText[WhichDataDisplay]); // Old value as formated string + printBoatValue(OldDataText[WhichDataDisplay], 190, 120, LEFT, 42, smallDecimals); // Old value as formated string } if(DataValid[WhichDataDisplay] == true){ OldDataText[WhichDataDisplay] = DataText[WhichDataDisplay]; // Save the old value diff --git a/lib/obp60task/PageCurrent.cpp b/lib/obp60task/PageCurrent.cpp index 2c34e8a..5b1e3f1 100644 --- a/lib/obp60task/PageCurrent.cpp +++ b/lib/obp60task/PageCurrent.cpp @@ -16,7 +16,7 @@ static const std::unordered_map leeKMap = { { "Multihull Fixed Keel [16]", 16 } }; -enum bValIdx { +enum bValueIdx { ROLL = 0, SET, DFT, @@ -30,7 +30,7 @@ enum bValIdx { NUM_VALS }; -// Screen coordinates for boat values +// Screen coordinates for boat value, name, unit struct Points { int16_t x1, y1; int16_t x2, y2; @@ -39,10 +39,10 @@ struct Points { // Screen coordinates for four boat data values (top-left, bottom-left, top-right, bottom-right) static constexpr Points POS[] = { - { 10, 65, 10, 95, 10, 115 }, // Position top left for value, name, unit - { 10, 270, 10, 220, 10, 190 }, // Position bottom left - { 295, 65, 390, 95, 390, 115 }, // Position top right - { 295, 270, 390, 220, 390, 190 } // Position bottom right + { 101, 65, 10, 95, 10, 115 }, // Position top left for value, name, unit + { 101, 270, 10, 220, 10, 190 }, // Position bottom left + { 395, 65, 390, 95, 390, 115 }, // Position top right + { 395, 270, 390, 220, 390, 190 } // Position bottom right }; // Define wave visual (XBM Format) @@ -75,6 +75,10 @@ static const uint8_t wave_bitmap[] PROGMEM = { class PageCurrent : public Page { private: + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; + GwLog* logger; int width; // Screen width @@ -86,8 +90,11 @@ private: bool holdValues; String flashLED; String backlightMode; + bool smallDecimals; String leeKStd; double leeK; + movingAvgAngle SetAvg {8}; // Store average of the last 8 values of SET angle values + movingAvg DftAvg {8}; // Store average of the last 8 values of DFT speed value // Old values for hold function String sValueOld[NUM_VALS] = { "", "", "", "", "", "", "", "", "", "" }; @@ -104,12 +111,15 @@ private: double stw // speed through water (m/s) ) { - if (stw == 0) { - return 0; + static constexpr double MINSTW = 0.5; // minimum speed (m/s) for leeway calculation to prevent math explosion + static constexpr double MAXLAY = 30.0 * DEG_TO_RAD; // cap leeway at this level of degree; + + if (stw < MINSTW) { + return 0; } double lay = leeK * roll / (stw * stw); - return lay; + return std::min(lay, MAXLAY); } double calcCTW( @@ -121,9 +131,9 @@ private: double ctw; // course through water (rad true) if (awa >= M_PI) { // apparent wind > 180° -> comes from port - ctw = hdt + lay; + ctw = WindUtils::to2PI(hdt + lay); } else { // wind comes from starboard - ctw = hdt - lay; + ctw = WindUtils::to2PI(hdt - lay); } return ctw; @@ -226,7 +236,9 @@ private: float direction // angle the arrow is pointing to [0..2PI] ) { - if (size < 0.05) { // no arrow for current set below 0.05 m/s + static constexpr double MINSIZE = 0.05; // minimum current set (size) (m/s) for arrow size + + if (size < MINSIZE) { // no arrow for current set below 0.05 m/s return; } @@ -310,6 +322,7 @@ public: holdValues = commonData->config->getBool(commonData->config->holdvalues); flashLED = commonData->config->getString(commonData->config->flashLED); backlightMode = commonData->config->getString(commonData->config->backlight); + smallDecimals = commonData->config->getBool(commonData->config->smallDecimals); leeKStd = commonData->config->getString(commonData->config->leeKStd); auto it = leeKMap.find(leeKStd.c_str()); @@ -319,6 +332,10 @@ public: leeK = (commonData->config->getString(commonData->config->leeK)).toDouble(); } LOG_DEBUG(GwLog::DEBUG, "PageCurrent: leeKStd: %s, leeK: %.3f", leeKStd.c_str(), leeK); + + // Initialize average buffer for SET and DFT + SetAvg.begin(); + DftAvg.begin(); } virtual int handleKey(int key) @@ -358,22 +375,23 @@ public: bValue[DFT]->getName().c_str(), bValue[DFT]->value, bValue[DFT]->valid, bValue[HDT]->getName().c_str(), bValue[HDT]->value, bValue[HDT]->valid, bValue[STW]->getName().c_str(), bValue[STW]->value, bValue[STW]->valid); - // Calculate current data + // Calculate current //*********************************************************** if (!bValue[SET]->valid || !bValue[DFT]->valid) { // If SET or DRIFT not available, try to calculate them - if (bValue[SOG]->valid && bValue[COG]->valid && bValue[STW]->valid && bValue[AWA]->valid) { // calculate current only if all required values are available + if (bValue[SOG]->valid && bValue[COG]->valid && bValue[STW]->valid) { + // calculate current only if all required values are available; we accept missing AWA, because this is only required for leeway adjustment if (!bValue[HDT]->valid) { // HDT not available if (bValue[HDM]->valid) { if (bValue[VAR]->valid) { bValue[HDT]->value = bValue[HDM]->value + bValue[VAR]->value; // Use corrected HDM if HDT is not available bValue[HDT]->value = WindUtils::to2PI(bValue[HDT]->value); - bValue[HDT]->valid = true; } else { // if HDT cannot be fully substituted by HDM+VAR, continue with HDM only bValue[HDT] = bValue[HDM]; } + bValue[HDT]->valid = true; } } @@ -386,7 +404,8 @@ public: lay = calcLeeway(leeK, bValue[ROLL]->value, bValue[STW]->value); if (bValue[HDT]->valid) { // That's either HDT or HDM - current = calcSetAndDrift(lay, bValue[SOG]->value, bValue[COG]->value, bValue[STW]->value, bValue[HDT]->value, bValue[AWA]->value); + double awaVal = (bValue[AWA]->valid ? bValue[AWA]->value : 0.0); // catch potentially missing AWA + current = calcSetAndDrift(lay, bValue[SOG]->value, bValue[COG]->value, bValue[STW]->value, bValue[HDT]->value, awaVal); bValue[SET]->value = current.set; bValue[SET]->setFormat("formatCourse"); bValue[SET]->valid = true; @@ -397,6 +416,12 @@ public: } } + // averaging current for smoother output + if (bValue[SET]->valid && bValue[DFT]->valid) { // Are SET and DRIFT now available? + bValue[SET]->value = SetAvg.reading(bValue[SET]->value); + bValue[DFT]->value = DftAvg.reading(bValue[DFT]->value); + } + LOG_DEBUG(GwLog::DEBUG, "PageCurrent: leeKStd: %s, leeK: %.3f, lay: %.3f, roll: %.3f, stw: %.3f, awa: %.3f, hdt: %.3f, cog: %.3f, sog: %.3f, set: %.3f, dft: %.3f", leeKStd.c_str(), leeK, lay, bValue[ROLL]->value, bValue[STW]->value, bValue[AWA]->value, bValue[HDT]->value, bValue[COG]->value, bValue[SOG]->value, bValue[SET]->value, bValue[DFT]->value); @@ -416,12 +441,10 @@ public: unit = unit.substring(0, 6); // String length limit for value unit // Show boat data value - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(POS[i].x1, POS[i].y1); if (!holdValues || useSimuData) { - getdisplay().print(sValue); + printBoatValue(sValue, POS[i].x1, POS[i].y1, RIGHT, 20, smallDecimals); } else { - getdisplay().print(sValueOld[i]); + printBoatValue(sValueOld[i], POS[i].x1, POS[i].y1, RIGHT, 20, smallDecimals); } // Show name diff --git a/lib/obp60task/PageDST810.cpp b/lib/obp60task/PageDST810.cpp index 93021c2..8a52460 100644 --- a/lib/obp60task/PageDST810.cpp +++ b/lib/obp60task/PageDST810.cpp @@ -5,6 +5,11 @@ class PageDST810 : public Page { + private: + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; + public: PageDST810(CommonData &common){ commonData = &common; @@ -24,6 +29,9 @@ public: GwConfigHandler *config = commonData->config; GwLog *logger = commonData->logger; + int valueX, valueY; + int DsegFontSize; + // Old values for hold function static String svalue1old = ""; static String unit1old = ""; @@ -40,6 +48,7 @@ public: bool holdvalues = config->getBool(config->holdvalues); String flashLED = config->getString(config->flashLED); String backlightMode = config->getString(config->backlight); + bool smallDecimals = config->getBool(config->smallDecimals); // Get boat values #1 GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue) @@ -100,7 +109,8 @@ public: // Show name getdisplay().setFont(&Ubuntu_Bold20pt8b); getdisplay().setCursor(20, 55); - getdisplay().print("Depth"); // Page name +// getdisplay().print("Depth"); // Page name + getdisplay().print(name1); // Page name // Show unit getdisplay().setFont(&Ubuntu_Bold12pt8b); @@ -112,16 +122,15 @@ public: getdisplay().print(unit1old); } - // Set font - getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b); - getdisplay().setCursor(180, 90); - // Show bus data + valueX = 380; + valueY = 90; + DsegFontSize = 30; if(holdvalues == false){ - getdisplay().print(svalue1); // Real value as formated string + printBoatValue(svalue1, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } else{ - getdisplay().print(svalue1old); // Old value as formated string + printBoatValue(svalue1old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string } if(valid1 == true){ svalue1old = svalue1; // Save the old value @@ -138,7 +147,8 @@ public: // Show name getdisplay().setFont(&Ubuntu_Bold20pt8b); getdisplay().setCursor(20, 145); - getdisplay().print("Speed"); // Page name +// getdisplay().print("Speed"); // Page name + getdisplay().print(name2); // Page name // Show unit getdisplay().setFont(&Ubuntu_Bold12pt8b); @@ -150,16 +160,15 @@ public: getdisplay().print(unit2old); } - // Setfont - getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b); - getdisplay().setCursor(180, 180); - // Show bus data + valueX = 380; + valueY = 180; + DsegFontSize = 30; if(holdvalues == false){ - getdisplay().print(svalue2); // Real value as formated string + printBoatValue(svalue2, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } else{ - getdisplay().print(svalue2old); // Old value as formated string + printBoatValue(svalue2old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string } if(valid2 == true){ svalue2old = svalue2; // Save the old value @@ -176,7 +185,8 @@ public: // Show name getdisplay().setFont(&Ubuntu_Bold12pt8b); getdisplay().setCursor(20, 220); - getdisplay().print("Log"); // Page name +// getdisplay().print("Log"); // Page name + getdisplay().print(name3); // Page name // Show unit getdisplay().setFont(&Ubuntu_Bold8pt8b); @@ -188,16 +198,15 @@ public: getdisplay().print(unit3old); } - // Set font - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(80, 270); - // Show bus data + valueX = 190; + valueY = 270; + DsegFontSize = 20; if(holdvalues == false){ - getdisplay().print(svalue3); // Real value as formated string + printBoatValue(svalue3, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } else{ - getdisplay().print(svalue3old); // Old value as formated string + printBoatValue(svalue3old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string } if(valid3 == true){ svalue3old = svalue3; // Save the old value @@ -214,7 +223,8 @@ public: // Show name getdisplay().setFont(&Ubuntu_Bold12pt8b); getdisplay().setCursor(220, 220); - getdisplay().print("Temp"); // Page name +// getdisplay().print("Temp"); // Page name + getdisplay().print(name4); // Page name // Show unit getdisplay().setFont(&Ubuntu_Bold8pt8b); @@ -226,16 +236,15 @@ public: getdisplay().print(unit4old); } - // Set font - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(280, 270); - // Show bus data + valueX = 390; + valueY = 270; + DsegFontSize = 20; if(holdvalues == false){ - getdisplay().print(svalue4); // Real value as formated string + printBoatValue(svalue4, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } else{ - getdisplay().print(svalue4old); // Old value as formated string + printBoatValue(svalue4old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string } if(valid4 == true){ svalue4old = svalue4; // Save the old value diff --git a/lib/obp60task/PageFourValues.cpp b/lib/obp60task/PageFourValues.cpp index 5797f55..b2d5e3a 100644 --- a/lib/obp60task/PageFourValues.cpp +++ b/lib/obp60task/PageFourValues.cpp @@ -5,6 +5,11 @@ class PageFourValues : public Page { + private: + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; + public: PageFourValues(CommonData &common){ commonData = &common; @@ -24,6 +29,9 @@ class PageFourValues : public Page GwConfigHandler *config = commonData->config; GwLog *logger = commonData->logger; + int valueX, valueY; + int DsegFontSize; + // Old values for hold function static String svalue1old = ""; static String unit1old = ""; @@ -35,11 +43,9 @@ class PageFourValues : public Page static String unit4old = ""; // Get config data - String lengthformat = config->getString(config->lengthFormat); - // bool simulation = config->getBool(config->useSimuData); bool holdvalues = config->getBool(config->holdvalues); String flashLED = config->getString(config->flashLED); - String backlightMode = config->getString(config->backlight); + bool smallDecimals = config->getBool(config->smallDecimals); // Get boat values #1 GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue) @@ -104,7 +110,7 @@ class PageFourValues : public Page // Show unit getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().setCursor(20, 65); + getdisplay().setCursor(20, 67); if(holdvalues == false){ getdisplay().print(unit1); // Unit } @@ -113,25 +119,26 @@ class PageFourValues : public Page } // Switch font if format for any values + valueX = 380; if(bvalue1->getFormat() == "formatLatitude" || bvalue1->getFormat() == "formatLongitude"){ - getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(120, 55); + valueY = 55; + DsegFontSize = 12; } else if(bvalue1->getFormat() == "formatTime" || bvalue1->getFormat() == "formatDate"){ - getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(150, 58); + valueY = 67; + DsegFontSize = 20; } else{ - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(180, 65); + valueY = 67; + DsegFontSize = 20; } // Show bus data if(holdvalues == false){ - getdisplay().print(svalue1); // Real value as formated string + printBoatValue(svalue1, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } else{ - getdisplay().print(svalue1old); // Old value as formated string + printBoatValue(svalue1old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string } if(valid1 == true){ svalue1old = svalue1; // Save the old value @@ -152,7 +159,7 @@ class PageFourValues : public Page // Show unit getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().setCursor(20, 133); + getdisplay().setCursor(20, 135); if(holdvalues == false){ getdisplay().print(unit2); // Unit } @@ -162,24 +169,24 @@ class PageFourValues : public Page // Switch font if format for any values if(bvalue2->getFormat() == "formatLatitude" || bvalue2->getFormat() == "formatLongitude"){ - getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(120, 123); + valueY = 123; + DsegFontSize = 12; } else if(bvalue2->getFormat() == "formatTime" || bvalue2->getFormat() == "formatDate"){ - getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(150, 123); + valueY = 135; + DsegFontSize = 20; } else{ - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(180, 133); + valueY = 135; + DsegFontSize = 20; } // Show bus data if(holdvalues == false){ - getdisplay().print(svalue2); // Real value as formated string + printBoatValue(svalue2, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } else{ - getdisplay().print(svalue2old); // Old value as formated string + printBoatValue(svalue2old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string } if(valid2 == true){ svalue2old = svalue2; // Save the old value @@ -200,7 +207,7 @@ class PageFourValues : public Page // Show unit getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().setCursor(20, 201); + getdisplay().setCursor(20, 203); if(holdvalues == false){ getdisplay().print(unit3); // Unit } @@ -210,24 +217,24 @@ class PageFourValues : public Page // Switch font if format for any values if(bvalue3->getFormat() == "formatLatitude" || bvalue3->getFormat() == "formatLongitude"){ - getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(120, 191); + valueY = 191; + DsegFontSize = 16; } else if(bvalue3->getFormat() == "formatTime" || bvalue3->getFormat() == "formatDate"){ - getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(150, 191); + valueY = 203; + DsegFontSize = 20; } else{ - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(180, 201); + valueY = 203; + DsegFontSize = 20; } // Show bus data if(holdvalues == false){ - getdisplay().print(svalue3); // Real value as formated string + printBoatValue(svalue3, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } else{ - getdisplay().print(svalue3old); // Old value as formated string + printBoatValue(svalue3old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string } if(valid3 == true){ svalue3old = svalue3; // Save the old value @@ -248,7 +255,7 @@ class PageFourValues : public Page // Show unit getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().setCursor(20, 269); + getdisplay().setCursor(20, 271); if(holdvalues == false){ getdisplay().print(unit4); // Unit } @@ -258,24 +265,24 @@ class PageFourValues : public Page // Switch font if format for any values if(bvalue4->getFormat() == "formatLatitude" || bvalue4->getFormat() == "formatLongitude"){ - getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(120, 259); + valueY = 271; + DsegFontSize = 16; } else if(bvalue4->getFormat() == "formatTime" || bvalue4->getFormat() == "formatDate"){ - getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(150, 259); + valueY = 271; + DsegFontSize = 20; } else{ - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(180, 269); + valueY = 271; + DsegFontSize = 20; } // Show bus data if(holdvalues == false){ - getdisplay().print(svalue4); // Real value as formated string + printBoatValue(svalue4, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } else{ - getdisplay().print(svalue4old); // Old value as formated string + printBoatValue(svalue4old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string } if(valid4 == true){ svalue4old = svalue4; // Save the old value diff --git a/lib/obp60task/PageFourValues2.cpp b/lib/obp60task/PageFourValues2.cpp index 63b0045..e34cc34 100644 --- a/lib/obp60task/PageFourValues2.cpp +++ b/lib/obp60task/PageFourValues2.cpp @@ -5,6 +5,11 @@ class PageFourValues2 : public Page { + private: + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; + public: PageFourValues2(CommonData &common){ commonData = &common; @@ -24,6 +29,9 @@ class PageFourValues2 : public Page GwConfigHandler *config = commonData->config; GwLog *logger = commonData->logger; + int valueX, valueY; + int DsegFontSize; + // Old values for hold function static String svalue1old = ""; static String unit1old = ""; @@ -35,11 +43,9 @@ class PageFourValues2 : public Page static String unit4old = ""; // Get config data - String lengthformat = config->getString(config->lengthFormat); - // bool simulation = config->getBool(config->useSimuData); bool holdvalues = config->getBool(config->holdvalues); String flashLED = config->getString(config->flashLED); - String backlightMode = config->getString(config->backlight); + bool smallDecimals = config->getBool(config->smallDecimals); // Get boat values #1 GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue) @@ -113,25 +119,26 @@ class PageFourValues2 : public Page } // Switch font if format for any values + valueX = 380; if(bvalue1->getFormat() == "formatLatitude" || bvalue1->getFormat() == "formatLongitude"){ - getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(100, 90); + valueY = 90; + DsegFontSize = 20; } else if(bvalue1->getFormat() == "formatTime" || bvalue1->getFormat() == "formatDate"){ - getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(180, 77); + valueY = 80; + DsegFontSize = 20; } else{ - getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b); - getdisplay().setCursor(180, 90); + valueY = 90; + DsegFontSize = 30; } // Show bus data if(holdvalues == false){ - getdisplay().print(svalue1); // Real value as formated string + printBoatValue(svalue1, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } else{ - getdisplay().print(svalue1old); // Old value as formated string + printBoatValue(svalue1old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string } if(valid1 == true){ svalue1old = svalue1; // Save the old value @@ -162,24 +169,24 @@ class PageFourValues2 : public Page // Switch font if format for any values if(bvalue2->getFormat() == "formatLatitude" || bvalue2->getFormat() == "formatLongitude"){ - getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(100, 180); + valueY = 180; + DsegFontSize = 20; } else if(bvalue2->getFormat() == "formatTime" || bvalue2->getFormat() == "formatDate"){ - getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(180, 158); + valueY = 170; + DsegFontSize = 20; } else{ - getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b); - getdisplay().setCursor(180, 180); + valueY = 180; + DsegFontSize = 30; } // Show bus data if(holdvalues == false){ - getdisplay().print(svalue2); // Real value as formated string + printBoatValue(svalue2, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } else{ - getdisplay().print(svalue2old); // Old value as formated string + printBoatValue(svalue2old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string } if(valid2 == true){ svalue2old = svalue2; // Save the old value @@ -194,13 +201,13 @@ class PageFourValues2 : public Page // ############### Value 3 ################ // Show name - getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(20, 220); + getdisplay().setFont(&Ubuntu_Bold16pt8b); + getdisplay().setCursor(20, 223); getdisplay().print(name3); // Page name // Show unit - getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().setCursor(20, 240); + getdisplay().setFont(&Ubuntu_Bold10pt8b); + getdisplay().setCursor(20, 270); if(holdvalues == false){ getdisplay().print(unit3); // Unit } @@ -209,25 +216,26 @@ class PageFourValues2 : public Page } // Switch font if format for any values + valueX = 190; if(bvalue3->getFormat() == "formatLatitude" || bvalue3->getFormat() == "formatLongitude"){ - getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().setCursor(50, 240); + valueY = 250; + DsegFontSize = 10; } else if(bvalue3->getFormat() == "formatTime" || bvalue3->getFormat() == "formatDate"){ - getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().setCursor(100, 240); + valueY = 253; + DsegFontSize = 10; } else{ - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(80, 270); + valueY = 270; + DsegFontSize = 20; } // Show bus data if(holdvalues == false){ - getdisplay().print(svalue3); // Real value as formated string + printBoatValue(svalue3, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } else{ - getdisplay().print(svalue3old); // Old value as formated string + printBoatValue(svalue3old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string } if(valid3 == true){ svalue3old = svalue3; // Save the old value @@ -242,13 +250,13 @@ class PageFourValues2 : public Page // ############### Value 4 ################ // Show name - getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(220, 220); + getdisplay().setFont(&Ubuntu_Bold16pt8b); + getdisplay().setCursor(220, 223); getdisplay().print(name4); // Page name // Show unit - getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().setCursor(220, 240); + getdisplay().setFont(&Ubuntu_Bold10pt8b); + getdisplay().setCursor(220, 270); if(holdvalues == false){ getdisplay().print(unit4); // Unit } @@ -257,25 +265,26 @@ class PageFourValues2 : public Page } // Switch font if format for any values + valueX = 390; if(bvalue4->getFormat() == "formatLatitude" || bvalue4->getFormat() == "formatLongitude"){ - getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().setCursor(250, 240); + valueY = 250; + DsegFontSize = 10; } else if(bvalue4->getFormat() == "formatTime" || bvalue4->getFormat() == "formatDate"){ - getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().setCursor(300, 240); + valueY = 253; + DsegFontSize = 10; } else{ - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(280, 270); + valueY = 270; + DsegFontSize = 20; } // Show bus data if(holdvalues == false){ - getdisplay().print(svalue4); // Real value as formated string + printBoatValue(svalue4, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } else{ - getdisplay().print(svalue4old); // Old value as formated string + printBoatValue(svalue4old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string } if(valid4 == true){ svalue4old = svalue4; // Save the old value diff --git a/lib/obp60task/PageGenerator.cpp b/lib/obp60task/PageGenerator.cpp index 9f0b93e..8135193 100644 --- a/lib/obp60task/PageGenerator.cpp +++ b/lib/obp60task/PageGenerator.cpp @@ -5,6 +5,10 @@ class PageGenerator : public Page { + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; + public: PageGenerator(CommonData &common){ commonData = &common; @@ -32,6 +36,7 @@ public: int genPower = config->getInt(config->genPower); String backlightMode = config->getString(config->backlight); String powerSensor = config->getString(config->usePowSensor3); + bool smallDecimals = config->getBool(config->smallDecimals); double value1 = 0; // Solar voltage double value2 = 0; // Solar current @@ -95,20 +100,16 @@ public: getdisplay().print("Generator"); // Show voltage type - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(10, 140); int bvoltage = 0; if(String(batVoltage) == "12V") bvoltage = 12; else bvoltage = 24; - getdisplay().print(bvoltage); + printBoatValue(String(bvoltage), 10, 140, LEFT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("V"); // Show solar power - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(10, 200); - if(genPower <= 999) getdisplay().print(genPower, 0); - if(genPower > 999) getdisplay().print(float(genPower/1000.0), 1); + String svalueGenPower = (genPower <= 999) ? String(genPower) : String(float(genPower/1000.0), 1); + printBoatValue(svalueGenPower, 10, 200, LEFT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); if(genPower <= 999) getdisplay().print("W"); if(genPower > 999) getdisplay().print("kW"); @@ -124,9 +125,7 @@ public: generatorGraphic(200, 95, commonData->fgcolor, commonData->bgcolor); // Show load level in percent - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(150, 200); - getdisplay().print(genPercentage); + printBoatValue(String(genPercentage), 150, 200, LEFT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("%"); getdisplay().setFont(&Ubuntu_Bold8pt8b); @@ -151,54 +150,37 @@ public: getdisplay().print("Sensor Modul"); // Reading bus data or using simulation data - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(260, 140); - if(simulation == true){ - if(batVoltage == "12V"){ - value1 = 12.0; - } - if(batVoltage == "24V"){ - value1 = 24.0; - } - value1 += float(random(0, 5)) / 10; // Simulation data - getdisplay().print(value1,1); - } - else{ - // Check for valid real data, display also if hold values activated - if(valid1 == true || holdvalues == true){ - // Resolution switching - if(value1 <= 9.9) getdisplay().print(value1, 2); - if(value1 > 9.9 && value1 <= 99.9)getdisplay().print(value1, 1); - if(value1 > 99.9) getdisplay().print(value1, 0); - } - else{ - getdisplay().print("---"); // Missing bus data - } + String svalue1; + if(valid1 == true || holdvalues == true){ + svalue1 = formatValue(value1, String("formatXdr:U:V"), *commonData); + } else { + svalue1 = "---"; // Missing bus data } + printBoatValue(svalue1, 355, 140, RIGHT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("V"); // Show actual current in A - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(260, 200); + String svalue2; if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){ - if(value2 <= 9.9) getdisplay().print(value2, 2); - if(value2 > 9.9 && value2 <= 99.9)getdisplay().print(value2, 1); - if(value2 > 99.9) getdisplay().print(value2, 0); + svalue2 = formatValue(value2, String("formatXdr:I:A"), *commonData); } - else getdisplay().print("---"); + else{ + svalue2 = "---"; + } + printBoatValue(svalue2, 355, 200, RIGHT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("A"); // Show actual consumption in W - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(260, 260); + String svalue3; if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){ - if(value3 <= 9.9) getdisplay().print(value3, 2); - if(value3 > 9.9 && value3 <= 99.9)getdisplay().print(value3, 1); - if(value3 > 99.9) getdisplay().print(value3, 0); + svalue3 = formatValue(value3, String("formatXdr:G:"), *commonData); } - else getdisplay().print("---"); + else{ + svalue3 = "---"; + } + printBoatValue(svalue3, 355, 260, RIGHT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("W"); diff --git a/lib/obp60task/PageOneValue.cpp b/lib/obp60task/PageOneValue.cpp index fe47a94..73e8dbc 100644 --- a/lib/obp60task/PageOneValue.cpp +++ b/lib/obp60task/PageOneValue.cpp @@ -31,8 +31,11 @@ private: bool useSimuData; bool holdValues; String flashLED; - String backlightMode; - String tempFormat; + bool smallDecimals; + + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; // Old values for hold function String sValue1Old = ""; @@ -40,38 +43,41 @@ private: // Data buffer pointer (owned by HstryBuffers) RingBuffer* dataHstryBuf = nullptr; - std::unique_ptr dataChart; // Chart object + std::unique_ptr dataChart = nullptr; // Chart object // display data value in display [FULL|HALF] void showData(GwApi::BoatValue* bValue1, DisplayMode mode) { - int nameXoff, nameYoff, unitXoff, unitYoff, value1Xoff, value1Yoff; - const GFXfont *nameFnt, *unitFnt, *valueFnt1, *valueFnt2, *valueFnt3; + int nameXoff, nameYoff, unitX, unitY, unitXoff, unitYoff, valueX, valueY, valueXoff, valueYoff; + const GFXfont *nameFnt, *unitFnt; + int valueFontSize1, valueFontSize2, valueFontSize3, DsegFontSize; if (mode == FULL) { // full size data display nameXoff = 0; nameYoff = 0; nameFnt = &Ubuntu_Bold32pt8b; + unitX = 380; + unitY = 100; unitXoff = 0; unitYoff = 0; unitFnt = &Ubuntu_Bold20pt8b; - value1Xoff = 0; - value1Yoff = 0; - valueFnt1 = &Ubuntu_Bold20pt8b; - valueFnt2 = &Ubuntu_Bold32pt8b; - valueFnt3 = &DSEG7Classic_BoldItalic60pt7b; + valueXoff = 0; + valueYoff = 0; + valueFontSize1 = 20; + valueFontSize2 = 30; + valueFontSize3 = 60; } else { // half size data and chart display nameXoff = -10; nameYoff = -34; nameFnt = &Ubuntu_Bold20pt8b; - unitXoff = -295; - unitYoff = 21; + unitX = 10; + unitY = 121; unitFnt = &Ubuntu_Bold12pt8b; - valueFnt1 = &Ubuntu_Bold12pt8b; - value1Xoff = 111; - value1Yoff = -119; - valueFnt2 = &Ubuntu_Bold20pt8b; - valueFnt3 = &DSEG7Classic_BoldItalic42pt7b; + valueXoff = 0; + valueYoff = -119; + valueFontSize1 = 12; + valueFontSize2 = 20; + valueFontSize3 = 42; } String name1 = xdrDelete(bValue1->getName()); // Value name @@ -88,32 +94,38 @@ private: getdisplay().print(name1); // name // Show unit + String unitName; getdisplay().setFont(unitFnt); - getdisplay().setCursor(305 + unitXoff, 100 + unitYoff); - if (holdValues) { - getdisplay().print(unit1Old); // name + unitName = unit1Old; } else { - getdisplay().print(unit1); // name + unitName = unit1; } + if (mode == FULL) { + drawTextRalign(unitX, unitY, unitName); + } else { + getdisplay().setCursor(unitX, unitY); + getdisplay().print(unitName); + } // Switch font depending on value format and adjust position + valueX = 380 + valueXoff; if (bValue1->getFormat() == "formatLatitude" || bValue1->getFormat() == "formatLongitude") { - getdisplay().setFont(valueFnt1); - getdisplay().setCursor(20 + value1Xoff, 180 + value1Yoff); + valueY = 180 + valueYoff; + DsegFontSize = valueFontSize1; } else if (bValue1->getFormat() == "formatTime" || bValue1->getFormat() == "formatDate") { - getdisplay().setFont(valueFnt2); - getdisplay().setCursor(20 + value1Xoff, 200 + value1Yoff); + valueY = 200 + valueYoff; + DsegFontSize = valueFontSize2; } else { - getdisplay().setFont(valueFnt3); - getdisplay().setCursor(20 + value1Xoff, 240 + value1Yoff); + valueY = 240 + valueYoff; + DsegFontSize = valueFontSize3; } // Show bus data if (!holdValues || useSimuData) { - getdisplay().print(sValue1); // Real value as formated string + printBoatValue(sValue1, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); } else { - getdisplay().print(sValue1Old); // Old value as formated string + printBoatValue(sValue1Old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); } if (valid1 == true) { @@ -127,18 +139,19 @@ public: { commonData = &common; logger = commonData->logger; + GwConfigHandler *config = commonData->config; + LOG_DEBUG(GwLog::LOG, "Instantiate PageOneValue"); width = getdisplay().width(); // Screen width height = getdisplay().height(); // Screen height + getdisplay().setTextWrap(false); // Get config data - // lengthformat = commonData->config->getString(commonData->config->lengthFormat); - useSimuData = commonData->config->getBool(commonData->config->useSimuData); + useSimuData = config->getBool(config->useSimuData); holdValues = commonData->config->getBool(commonData->config->holdvalues); flashLED = commonData->config->getString(commonData->config->flashLED); - backlightMode = commonData->config->getString(commonData->config->backlight); - tempFormat = commonData->config->getString(commonData->config->tempFormat); // [K|°C|°F] + smallDecimals = commonData->config->getBool(commonData->config->smallDecimals); } virtual void setupKeys() @@ -233,9 +246,9 @@ public: if (dataHstryBuf) { dataChart.reset(new Chart(*dataHstryBuf, *commonData, useSimuData)); - LOG_DEBUG(GwLog::DEBUG, "PageOneValue: Created chart objects for %s", bValName1); + LOG_DEBUG(GwLog::DEBUG, "PageOneValue: Created chart object for %s", bValName1); } else { - LOG_DEBUG(GwLog::DEBUG, "PageOneValue: No chart objects available for %s", bValName1); + LOG_DEBUG(GwLog::DEBUG, "PageOneValue: No chart object available for %s", bValName1); } } @@ -249,12 +262,13 @@ public: // Get boat value for page GwApi::BoatValue* bValue1 = pageData.values[0]; // Page boat data element +#ifdef BOARD_OBP60S3 // Optical warning by limit violation (unused) if (String(flashLED) == "Limit Violation") { setBlinkingLED(false); setFlashLED(false); } - +#endif if (bValue1 == NULL) return PAGE_OK; // no data, no page to display @@ -265,11 +279,13 @@ public: displaySetPartialWindow(0, 0, width, height); // Set partial update - if (!dataChart->isValid()) { - dataChart->init(); // try late initialization if chart object could not be properly initialized earlier due to missing boat data + if (dataChart) { // Check only if dataChart object exists at all + if (!dataChart->isValid()) { + dataChart->init(); // try late initialization if chart object could not be properly initialized earlier due to missing boat data + } } - if (pageMode == VALUE || dataHstryBuf == nullptr) { + if (pageMode == VALUE || dataChart == nullptr) { // show only data value; ignore other pageMode options if no chart supported boat data history buffer is available showData(bValue1, FULL); diff --git a/lib/obp60task/PageRollPitch.cpp b/lib/obp60task/PageRollPitch.cpp index 59c79dc..ff999ff 100644 --- a/lib/obp60task/PageRollPitch.cpp +++ b/lib/obp60task/PageRollPitch.cpp @@ -5,6 +5,10 @@ class PageRollPitch : public Page { + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; + public: PageRollPitch(CommonData &common){ commonData = &common; @@ -44,12 +48,15 @@ public: double rolloffset = roffset.toFloat()/360*(2*M_PI); String poffset = config->getString(config->pitchOffset); double pitchoffset = poffset.toFloat()/360*(2*M_PI); + bool smallDecimals = config->getBool(config->smallDecimals); // Get boat values for roll GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (xdrRoll) String name1 = xdrDelete(bvalue1->getName()); // Value name - name1 = name1.substring(0, 6); // String length limit for value name + name1 = name1.substring(0, 5); // String length limit for value name bool valid1 = bvalue1->valid; // Valid information + String unit1 = formatValue(bvalue1, *commonData).unit; // Unit of value + unit1 = unit1.substring(0, 4); // String length limit for value unit if(valid1 == true){ value1 = bvalue1->value + rolloffset; // Raw value for pitch } @@ -73,8 +80,10 @@ public: // Get boat values for pitch GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list (xdrPitch) String name2 = xdrDelete(bvalue2->getName()); // Value name - name2 = name2.substring(0, 6); // String length limit for value name + name2 = name2.substring(0, 5); // String length limit for value name bool valid2 = bvalue2->valid; // Valid information + String unit2 = formatValue(bvalue2, *commonData).unit; // Unit of value + unit2 = unit2.substring(0, 4); // String length limit for value unit if(valid2 == true){ value2 = bvalue2->value + pitchoffset; // Raw value for pitch } @@ -86,7 +95,7 @@ public: value2 = 0; } } - if(value2/(2*PI)*360 > -10 && value2/(2*M_PI)*360 < 10){ + if(value2/(2*M_PI)*360 > -10 && value2/(2*M_PI)*360 < 10){ svalue2 = String(value2/(2*M_PI)*360,1); // Convert raw value to string } else{ @@ -121,53 +130,44 @@ public: getdisplay().setTextColor(commonData->fgcolor); // Show roll limit - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(10, 65); - getdisplay().print(rolllimit); // Value - //getdisplay().print(svalue1); // Value + printBoatValue(String(rolllimit), 10, 65, LEFT, 20, smallDecimals); // Value getdisplay().setFont(&Ubuntu_Bold12pt8b); getdisplay().setCursor(10, 95); getdisplay().print("Limit"); // Name getdisplay().setFont(&Ubuntu_Bold8pt8b); getdisplay().setCursor(10, 115); - getdisplay().print("DEG"); + getdisplay().print("Deg"); // Horizintal separator left getdisplay().fillRect(0, 149, 60, 3, commonData->fgcolor); // Show roll value - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(10, 270); - if(holdvalues == false) getdisplay().print(svalue1); // Value - else getdisplay().print(svalue1old); + if(holdvalues == false) printBoatValue(svalue1, 101, 270, RIGHT, 20, smallDecimals); // Value + else printBoatValue(svalue1old, 101, 270, RIGHT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold12pt8b); getdisplay().setCursor(10, 220); getdisplay().print(name1); // Name getdisplay().setFont(&Ubuntu_Bold8pt8b); getdisplay().setCursor(10, 190); - getdisplay().print("Deg"); + getdisplay().print(unit1); // Unit // Horizintal separator right getdisplay().fillRect(340, 149, 80, 3, commonData->fgcolor); // Show pitch value - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(295, 270); - if(holdvalues == false) getdisplay().print(svalue2); // Value - else getdisplay().print(svalue2old); + if(holdvalues == false) printBoatValue(svalue2, 395, 270, RIGHT, 20, smallDecimals); // Value + else printBoatValue(svalue2old, 395, 270, RIGHT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(335, 220); - getdisplay().print(name2); // Name + drawTextRalign(395, 220, name2); // Name getdisplay().setFont(&Ubuntu_Bold8pt8b); getdisplay().setCursor(335, 190); - getdisplay().print("Deg"); + getdisplay().print(unit2); // Unit //******************************************************************************************* // Draw instrument int rInstrument = 100; // Radius of instrument - float pi = 3.141592; getdisplay().fillCircle(200, 150, rInstrument + 10, commonData->fgcolor); // Outer circle getdisplay().fillCircle(200, 150, rInstrument + 7, commonData->bgcolor); // Outer circle @@ -264,11 +264,11 @@ public: int y0 = 150; int x1 = x0 + 50*cos(value1); int y1 = y0 + 50*sin(value1); - int x2 = x0 + 50*cos(value1 - pi/2); - int y2 = y0 + 50*sin(value1 - pi/2); + int x2 = x0 + 50*cos(value1 - M_PI/2); + int y2 = y0 + 50*sin(value1 - M_PI/2); getdisplay().fillTriangle(x0, y0, x1, y1, x2, y2, commonData->bgcolor); // Clear half top side of boat circle (right triangle) - x1 = x0 + 50*cos(value1 + pi); - y1 = y0 + 50*sin(value1 + pi); + x1 = x0 + 50*cos(value1 + M_PI); + y1 = y0 + 50*sin(value1 + M_PI); getdisplay().fillTriangle(x0, y0, x1, y1, x2, y2, commonData->bgcolor); // Clear half top side of boat circle (left triangle) getdisplay().fillRect(150, 160, 100, 4, commonData->fgcolor); // Water line diff --git a/lib/obp60task/PageSixValues.cpp b/lib/obp60task/PageSixValues.cpp index fd409dc..d8ad885 100644 --- a/lib/obp60task/PageSixValues.cpp +++ b/lib/obp60task/PageSixValues.cpp @@ -3,168 +3,168 @@ #include "Pagedata.h" #include "OBP60Extensions.h" -const int SixValues_x1 = 5; -const int SixValues_DeltaX = 200; +class PageSixValues : public Page { +private: + GwLog* logger; + GwConfigHandler* config; -// const int SixValues_y1 = 23; -const int SixValues_y1 = 22; -const int SixValues_DeltaY = 83; + bool holdValues; + String flashLED; + String backlightMode; + bool smallDecimals; -const int HowManyValues = 6; + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; -class PageSixValues : public Page -{ - public: - PageSixValues(CommonData &common){ + static constexpr int SixValues_x1 = 5; + static constexpr int SixValues_DeltaX = 200; + static constexpr int SixValues_y1 = 22; + static constexpr int SixValues_DeltaY = 83; + + static constexpr int HowManyValues = 6; + // Old values for hold function + String OldDataText[HowManyValues] = { "", "", "", "", "", "" }; + String OldDataUnit[HowManyValues] = { "", "", "", "", "", "" }; + +public: + PageSixValues(CommonData& common) + { commonData = &common; - common.logger->logDebug(GwLog::LOG,"Instantiate PageSixValues"); + config = commonData->config; + logger = commonData->logger; + LOG_DEBUG(GwLog::LOG, "Instantiate PageSixValues"); + + // Get config data + holdValues = config->getBool(config->holdvalues); + flashLED = config->getString(config->flashLED); + backlightMode = config->getString(config->backlight); + smallDecimals = config->getBool(config->smallDecimals); } - virtual int handleKey(int key){ + virtual int handleKey(int key) + { // Code for keylock - if(key == 11){ + if (key == 11) { commonData->keylock = !commonData->keylock; - return 0; // Commit the key + return 0; // Commit the key } return key; } - int displayPage(PageData &pageData){ - GwConfigHandler *config = commonData->config; - GwLog *logger = commonData->logger; + int displayPage(PageData& pageData) + { + GwApi::BoatValue* bvalue; + String DataName[HowManyValues]; + double DataValue[HowManyValues]; + bool DataValid[HowManyValues]; + String DataText[HowManyValues]; + String DataUnit[HowManyValues]; + String DataFormat[HowManyValues]; + int8_t DsegFontSize = 0; - - // Old values for hold function - static String OldDataText[HowManyValues] = {"", "", "", "", "", ""}; - static String OldDataUnits[HowManyValues] = {"", "", "", "", "", ""}; - - // Get config data - String lengthformat = config->getString(config->lengthFormat); - // bool simulation = config->getBool(config->useSimuData); - bool holdvalues = config->getBool(config->holdvalues); - String flashLED = config->getString(config->flashLED); - String backlightMode = config->getString(config->backlight); - - GwApi::BoatValue *bvalue; - String DataName[HowManyValues]; - double DataValue[HowManyValues]; - bool DataValid[HowManyValues]; - String DataText[HowManyValues]; - String DataUnits[HowManyValues]; - String DataFormat[HowManyValues]; - - for (int i = 0; i < HowManyValues; i++){ - bvalue = pageData.values[i]; - DataName[i] = xdrDelete(bvalue->getName()); - DataName[i] = DataName[i].substring(0, 6); // String length limit for value name - DataValue[i] = bvalue->value; // Value as double in SI unit - DataValid[i] = bvalue->valid; - DataText[i] = formatValue(bvalue, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places - DataUnits[i] = formatValue(bvalue, *commonData).unit; - DataFormat[i] = bvalue->getFormat(); // Unit of value - } - - // Optical warning by limit violation (unused) - if(String(flashLED) == "Limit Violation"){ - setBlinkingLED(false); - setFlashLED(false); - } - - if (bvalue == NULL) return PAGE_OK; // WTF why this statement? - - // Draw page - //*********************************************************** - - // Set display in partial refresh mode - displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update - getdisplay().setTextColor(commonData->fgcolor); + for (int i = 0; i < HowManyValues; i++) { + bvalue = pageData.values[i]; + DataName[i] = xdrDelete(bvalue->getName()); + DataName[i] = DataName[i].substring(0, 6); // String length limit for value name + DataValue[i] = bvalue->value; // Value as double in SI unit + DataValid[i] = bvalue->valid; + DataText[i] = formatValue(bvalue, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places + DataUnit[i] = formatValue(bvalue, *commonData).unit; + DataFormat[i] = bvalue->getFormat(); // Unit of value + } - for (int i = 0; i < ( HowManyValues / 2 ); i++){ - if (i < (HowManyValues / 2) - 1) { // Don't draw horizontal line after last line of values -> standard design - // Horizontal line 3 pix - getdisplay().fillRect(0, SixValues_y1+(i+1)*SixValues_DeltaY, 400, 3, commonData->fgcolor); - } - for (int j = 0; j < 2; j++){ - int ValueIndex = i * 2 + j; - int x0 = SixValues_x1 + j * SixValues_DeltaX; - int y0 = SixValues_y1 + i * SixValues_DeltaY; - LOG_DEBUG(GwLog::LOG,"Drawing at PageSixValue: %d %s %f %s", ValueIndex, DataName[ValueIndex], DataValue[ValueIndex], DataFormat[ValueIndex] ); - - // Show name - getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(x0, y0+25); - getdisplay().print(DataName[ValueIndex]); // Page name - - // Show unit - getdisplay().setFont(&Ubuntu_Bold8pt8b); - if(holdvalues == false){ - drawTextRalign(x0+187, y0+19, DataUnits[ValueIndex]); // Unit - } - else{ - drawTextRalign(x0+187, y0+19, OldDataUnits[ValueIndex]); - } - - // Switch font depending on data type - if(DataFormat[ValueIndex] == "formatLatitude" || DataFormat[ValueIndex] == "formatLongitude"){ - getdisplay().setFont(&Ubuntu_Bold12pt8b); - getdisplay().setCursor(x0+21, y0+60); - } - else if(DataFormat[ValueIndex] == "formatTime" || DataFormat[ValueIndex] == "formatDate"){ - getdisplay().setFont(&Ubuntu_Bold16pt8b); - getdisplay().setCursor(x0+23,y0+55); - } - // pressure in hPa - else if(DataFormat[ValueIndex] == "formatXdr:P:P"){ - getdisplay().setFont(&DSEG7Classic_BoldItalic26pt7b); - getdisplay().setCursor(x0+23, y0+79); - } - // RPM - else if(DataFormat[ValueIndex] == "formatXdr:T:R"){ - getdisplay().setFont(&DSEG7Classic_BoldItalic16pt7b); - getdisplay().setCursor(x0+23, y0+79); - } - else{ - getdisplay().setFont(&DSEG7Classic_BoldItalic26pt7b); - if ( DataText[ValueIndex][0] == '-' ) - getdisplay().setCursor(x0+23, y0+79); - else - getdisplay().setCursor(x0+65, y0+79); - } - - // Show bus data - if(holdvalues == false){ - getdisplay().print(DataText[ValueIndex]); // Real value as formated string - } - else{ - getdisplay().print(OldDataText[ValueIndex]); // Old value as formated string - } - if(DataValid[ValueIndex] == true){ - OldDataText[ValueIndex] = DataText[ValueIndex]; // Save the old value - OldDataUnits[ValueIndex] = DataUnits[ValueIndex]; // Save the old unit - } - } - // Vertical line 3 pix - getdisplay().fillRect(SixValues_x1+SixValues_DeltaX-8, SixValues_y1+i*SixValues_DeltaY, 3, SixValues_DeltaY, commonData->fgcolor); +#ifdef BOARD_OBP60S3 + // Optical warning by limit violation (unused) + if (String(flashLED) == "Limit Violation") { + setBlinkingLED(false); + setFlashLED(false); + } +#endif + if (bvalue == NULL) + return PAGE_OK; + + // Draw page + //*********************************************************** + + // Set display in partial refresh mode + displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update + getdisplay().setTextWrap(false); + getdisplay().setTextColor(commonData->fgcolor); + + for (int i = 0; i < (HowManyValues / 2); i++) { + if (i < (HowManyValues / 2) - 1) { // Don't draw horizontal line after last line of values + // Horizontal line 3 px + getdisplay().fillRect(0, SixValues_y1 + (i + 1) * SixValues_DeltaY, 400, 3, commonData->fgcolor); } - - return PAGE_UPDATE; - }; - + + for (int j = 0; j < 2; j++) { + int ValueIndex = i * 2 + j; + int x0 = SixValues_x1 + j * SixValues_DeltaX; + int y0 = SixValues_y1 + i * SixValues_DeltaY; + //LOG_DEBUG(GwLog::DEBUG, "Drawing at PageSixValue: %d %s %f %s %s", ValueIndex, DataName[ValueIndex], + // DataValue[ValueIndex], DataUnit[ValueIndex], DataFormat[ValueIndex]); + + // Show name + getdisplay().setFont(&Ubuntu_Bold12pt8b); + getdisplay().setCursor(x0, y0 + 25); + getdisplay().print(DataName[ValueIndex]); // Page name + + // Show unit + getdisplay().setFont(&Ubuntu_Bold8pt8b); + if (holdValues == false) { + drawTextRalign(x0 + 187, y0 + 19, DataUnit[ValueIndex]); // Unit + } else { + drawTextRalign(x0 + 187, y0 + 19, OldDataUnit[ValueIndex]); + } + + // Set font size depending on data type + if (DataFormat[ValueIndex] == "formatLatitude" || DataFormat[ValueIndex] == "formatLongitude") { + DsegFontSize = 12; + } else if (DataFormat[ValueIndex] == "formatTime" || DataFormat[ValueIndex] == "formatDate") { + DsegFontSize = 16; + } + else if (DataFormat[ValueIndex] == "formatXdr:T:R") { // RPM + DsegFontSize = 20; + } + else { + DsegFontSize = 26; + } + + // Show bus data value + if (holdValues == false) { + printBoatValue(DataText[ValueIndex], x0 + 187, y0 + 79, RIGHT, DsegFontSize, smallDecimals); + } else { + printBoatValue(OldDataText[ValueIndex], x0 + 187, y0 + 79, RIGHT, DsegFontSize, smallDecimals); + } + + if (DataValid[ValueIndex] == true) { + OldDataText[ValueIndex] = DataText[ValueIndex]; // Save the old value + OldDataUnit[ValueIndex] = DataUnit[ValueIndex]; // Save the old unit + } + } + // Vertical line 3 px + getdisplay().fillRect(SixValues_x1 + SixValues_DeltaX - 8, SixValues_y1 + i * SixValues_DeltaY, 3, SixValues_DeltaY, commonData->fgcolor); + } + + return PAGE_UPDATE; }; -static Page *createPage(CommonData &common){ +}; +static Page* createPage(CommonData& common) +{ return new PageSixValues(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 - */ +} /** + * 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 registerPageSixValues( - "SixValues", // Page name - createPage, // Action - 6, // Number of bus values depends on selection in Web configuration - true // Show display header on/off + "SixValues", // Page name + createPage, // Action + 6, // Number of bus values depends on selection in Web configuration + true // Show display header on/off ); #endif diff --git a/lib/obp60task/PageSolar.cpp b/lib/obp60task/PageSolar.cpp index 4fd20a5..5120ea6 100644 --- a/lib/obp60task/PageSolar.cpp +++ b/lib/obp60task/PageSolar.cpp @@ -5,6 +5,10 @@ class PageSolar : public Page { + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; + public: PageSolar(CommonData &common){ commonData = &common; @@ -31,6 +35,7 @@ public: int solPower = config->getInt(config->solarPower); String backlightMode = config->getString(config->backlight); String powerSensor = config->getString(config->usePowSensor2); + bool smallDecimals = config->getBool(config->smallDecimals); double value1 = 0; // Solar voltage double value2 = 0; // Solar current @@ -91,20 +96,16 @@ public: getdisplay().print("Solar"); // Show voltage type - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(10, 140); int bvoltage = 0; if(String(batVoltage) == "12V") bvoltage = 12; else bvoltage = 24; - getdisplay().print(bvoltage); + printBoatValue(String(bvoltage), 10, 140, LEFT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("V"); // Show solar power - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(10, 200); - if(solPower <= 999) getdisplay().print(solPower, 0); - if(solPower > 999) getdisplay().print(float(solPower/1000.0), 1); + String svalueSolPower = (solPower <= 999) ? String(solPower) : String(float(solPower/1000.0), 1); + printBoatValue(svalueSolPower, 10, 200, LEFT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); if(solPower <= 999) getdisplay().print("W"); if(solPower > 999) getdisplay().print("kW"); @@ -120,9 +121,7 @@ public: solarGraphic(150, 45, commonData->fgcolor, commonData->bgcolor); // Show load level in percent - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(150, 200); - getdisplay().print(solPercentage); + printBoatValue(String(solPercentage), 150, 200, LEFT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("%"); getdisplay().setFont(&Ubuntu_Bold8pt8b); @@ -147,54 +146,37 @@ public: getdisplay().print("Sensor Modul"); // Reading bus data or using simulation data - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(260, 140); - if(simulation == true){ - if(batVoltage == "12V"){ - value1 = 12.0; - } - if(batVoltage == "24V"){ - value1 = 24.0; - } - value1 += float(random(0, 5)) / 10; // Simulation data - getdisplay().print(value1,1); - } - else{ - // Check for valid real data, display also if hold values activated - if(valid1 == true || holdvalues == true){ - // Resolution switching - if(value1 <= 9.9) getdisplay().print(value1, 2); - if(value1 > 9.9 && value1 <= 99.9)getdisplay().print(value1, 1); - if(value1 > 99.9) getdisplay().print(value1, 0); - } - else{ - getdisplay().print("---"); // Missing bus data - } + String svalue1; + if(valid1 == true || holdvalues == true){ + svalue1 = formatValue(value1, String("formatXdr:U:V"), *commonData); + } else { + svalue1 = "---"; // Missing bus data } + printBoatValue(svalue1, 355, 140, RIGHT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("V"); // Show actual current in A - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(260, 200); + String svalue2; if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){ - if(value2 <= 9.9) getdisplay().print(value2, 2); - if(value2 > 9.9 && value2 <= 99.9)getdisplay().print(value2, 1); - if(value2 > 99.9) getdisplay().print(value2, 0); + svalue2 = formatValue(value2, String("formatXdr:I:A"), *commonData); } - else getdisplay().print("---"); + else{ + svalue2 = "---"; + } + printBoatValue(svalue2, 355, 200, RIGHT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("A"); // Show actual consumption in W - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(260, 260); + String svalue3; if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){ - if(value3 <= 9.9) getdisplay().print(value3, 2); - if(value3 > 9.9 && value3 <= 99.9)getdisplay().print(value3, 1); - if(value3 > 99.9) getdisplay().print(value3, 0); + svalue3 = formatValue(value3, String("formatXdr:G:"), *commonData); } - else getdisplay().print("---"); + else{ + svalue3 = "---"; + } + printBoatValue(svalue3, 355, 260, RIGHT, 20, smallDecimals); getdisplay().setFont(&Ubuntu_Bold16pt8b); getdisplay().print("W"); diff --git a/lib/obp60task/PageThreeValues.cpp b/lib/obp60task/PageThreeValues.cpp index 404015b..6099977 100644 --- a/lib/obp60task/PageThreeValues.cpp +++ b/lib/obp60task/PageThreeValues.cpp @@ -5,6 +5,11 @@ class PageThreeValues : public Page { + private: + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; + public: PageThreeValues(CommonData &common){ commonData = &common; @@ -24,6 +29,9 @@ class PageThreeValues : public Page GwConfigHandler *config = commonData->config; GwLog *logger = commonData->logger; + int valueX, valueY; + int DsegFontSize; + // Old values for hold function static String svalue1old = ""; static String unit1old = ""; @@ -33,11 +41,10 @@ class PageThreeValues : public Page static String unit3old = ""; // Get config data - String lengthformat = config->getString(config->lengthFormat); // bool simulation = config->getBool(config->useSimuData); bool holdvalues = config->getBool(config->holdvalues); String flashLED = config->getString(config->flashLED); - String backlightMode = config->getString(config->backlight); + bool smallDecimals = config->getBool(config->smallDecimals); // Get boat values #1 GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue) @@ -101,25 +108,26 @@ class PageThreeValues : public Page } // Switch font if format for any values + valueX = 380; if(bvalue1->getFormat() == "formatLatitude" || bvalue1->getFormat() == "formatLongitude"){ - getdisplay().setFont(&Ubuntu_Bold20pt8b); - getdisplay().setCursor(50, 90); + valueY = 90; + DsegFontSize = 20; } else if(bvalue1->getFormat() == "formatTime" || bvalue1->getFormat() == "formatDate"){ - getdisplay().setFont(&Ubuntu_Bold20pt8b); - getdisplay().setCursor(170, 68); + valueY = 80; + DsegFontSize = 20; } else{ - getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b); - getdisplay().setCursor(180, 90); + valueY = 90; + DsegFontSize = 30; } // Show bus data if(holdvalues == false){ - getdisplay().print(svalue1); // Real value as formated string + printBoatValue(svalue1, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } else{ - getdisplay().print(svalue1old); // Old value as formated string + printBoatValue(svalue1old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string } if(valid1 == true){ svalue1old = svalue1; // Save the old value @@ -150,24 +158,30 @@ class PageThreeValues : public Page // Switch font if format for any values if(bvalue2->getFormat() == "formatLatitude" || bvalue2->getFormat() == "formatLongitude"){ + valueY = 180; + DsegFontSize = 20; getdisplay().setFont(&Ubuntu_Bold20pt8b); getdisplay().setCursor(50, 180); } else if(bvalue2->getFormat() == "formatTime" || bvalue2->getFormat() == "formatDate"){ + valueY = 170; + DsegFontSize = 20; getdisplay().setFont(&Ubuntu_Bold20pt8b); getdisplay().setCursor(170, 158); } else{ + valueY = 180; + DsegFontSize = 30; getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b); getdisplay().setCursor(180, 180); } // Show bus data if(holdvalues == false){ - getdisplay().print(svalue2); // Real value as formated string + printBoatValue(svalue2, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } else{ - getdisplay().print(svalue2old); // Old value as formated string + printBoatValue(svalue2old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } if(valid2 == true){ svalue2old = svalue2; // Save the old value @@ -198,24 +212,24 @@ class PageThreeValues : public Page // Switch font if format for any values if(bvalue3->getFormat() == "formatLatitude" || bvalue3->getFormat() == "formatLongitude"){ - getdisplay().setFont(&Ubuntu_Bold20pt8b); - getdisplay().setCursor(50, 270); + valueY = 270; + DsegFontSize = 20; } else if(bvalue3->getFormat() == "formatTime" || bvalue3->getFormat() == "formatDate"){ - getdisplay().setFont(&Ubuntu_Bold20pt8b); - getdisplay().setCursor(170, 248); + valueY = 260; + DsegFontSize = 20; } else{ - getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b); - getdisplay().setCursor(180, 270); + valueY = 270; + DsegFontSize = 30; } // Show bus data if(holdvalues == false){ - getdisplay().print(svalue3); // Real value as formated string + printBoatValue(svalue3, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } else{ - getdisplay().print(svalue3old); // Old value as formated string + printBoatValue(svalue3old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } if(valid3 == true){ svalue3old = svalue3; // Save the old value diff --git a/lib/obp60task/PageTwoValues.cpp b/lib/obp60task/PageTwoValues.cpp index bc580e0..815e988 100644 --- a/lib/obp60task/PageTwoValues.cpp +++ b/lib/obp60task/PageTwoValues.cpp @@ -34,8 +34,11 @@ private: bool useSimuData; bool holdValues; String flashLED; - String backlightMode; - String tempFormat; + bool smallDecimals; + + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; // Data buffer pointer (owned by HstryBuffers) static constexpr int NUMVALUES = 2; // two data values in this page @@ -49,8 +52,10 @@ private: // display data values in display [FULL|HALF] void showData(const std::vector& bValue, DisplayMode mode) { - getdisplay().setTextColor(commonData->fgcolor); + int valueX, valueY; + int DsegFontSize; + getdisplay().setTextColor(commonData->fgcolor); int numValues = bValue.size(); // do we have to handle 1 or 2 values? for (int i = 0; i < numValues; i++) { @@ -78,22 +83,23 @@ private: } // Switch font depending on value format and adjust position + valueX = 380; if (bValue[i]->getFormat() == "formatLatitude" || bValue[i]->getFormat() == "formatLongitude") { - getdisplay().setFont(&Ubuntu_Bold20pt8b); - getdisplay().setCursor(50, 125 + yOffset); + valueY = 125 + yOffset; + DsegFontSize = 20; } else if (bValue[i]->getFormat() == "formatTime" || bValue[i]->getFormat() == "formatDate") { - getdisplay().setFont(&Ubuntu_Bold20pt8b); - getdisplay().setCursor(170, 105 + yOffset); + valueY = 105 + yOffset; + DsegFontSize = 20; } else { // Default font for other formats - getdisplay().setFont(&DSEG7Classic_BoldItalic42pt7b); - getdisplay().setCursor(180, 125 + yOffset); + valueY = 125 + yOffset; + DsegFontSize = 42; } // Show bus data if (!holdValues || useSimuData) { - getdisplay().print(sValue); // Real value as formated string + printBoatValue(sValue, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); } else { - getdisplay().print(sValueOld[i]); // Old value as formated string + printBoatValue(sValueOld[i], valueX, valueY, RIGHT, DsegFontSize, smallDecimals); } if (valid == true) { @@ -116,14 +122,13 @@ public: width = getdisplay().width(); // Screen width height = getdisplay().height(); // Screen height + getdisplay().setTextWrap(false); // Get config data - // lengthformat = commonData->config->getString(commonData->config->lengthFormat); useSimuData = commonData->config->getBool(commonData->config->useSimuData); holdValues = commonData->config->getBool(commonData->config->holdvalues); flashLED = commonData->config->getString(commonData->config->flashLED); - backlightMode = commonData->config->getString(commonData->config->backlight); - tempFormat = commonData->config->getString(commonData->config->tempFormat); // [K|°C|°F] + smallDecimals = commonData->config->getBool(commonData->config->smallDecimals); } virtual void setupKeys() @@ -255,12 +260,13 @@ public: bValue.push_back(pageData.values[0]); // Page boat data element 1 bValue.push_back(pageData.values[1]); // Page boat data element 2 +#ifdef BOARD_OBP60S3 // Optical warning by limit violation (unused) if (String(flashLED) == "Limit Violation") { setBlinkingLED(false); setFlashLED(false); } - +#endif if (bValue[0] == NULL && bValue[1] == NULL) return PAGE_OK; // no data, no page to display @@ -273,12 +279,14 @@ public: displaySetPartialWindow(0, 0, width, height); // Set partial update for (int i = 0; i < NUMVALUES; i++) { - if (!dataChart[i]->isValid()) { - dataChart[i]->init(); // try late initialization if chart object could not be properly initialized earlier due to missing boat data + if (dataChart[i]) { // Check only if dataChart object exists at all + if (!dataChart[i]->isValid()) { + dataChart[i]->init(); // try late initialization if chart object could not be properly initialized earlier due to missing boat data + } } } - - if (pageMode == VALUES || (dataHstryBuf[0] == nullptr && dataHstryBuf[1] == nullptr)) { + + if (pageMode == VALUES || (dataChart[0] == nullptr && dataChart[1] == nullptr)) { // show only data value; ignore other pageMode options if no chart supported boat data history buffer is available showData(bValue, FULL); diff --git a/lib/obp60task/PageVoltage.cpp b/lib/obp60task/PageVoltage.cpp index de467ba..2f3a033 100644 --- a/lib/obp60task/PageVoltage.cpp +++ b/lib/obp60task/PageVoltage.cpp @@ -5,11 +5,15 @@ class PageVoltage : public Page { -bool init = false; // Marker for init done -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 -double raw = 0; -char mode = 'D'; // display mode (A)nalog | (D)igital + bool init = false; // Marker for init done + 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 + double raw = 0; + char mode = 'D'; // display mode (A)nalog | (D)igital + + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; public: PageVoltage(CommonData &common){ @@ -110,8 +114,10 @@ public: String batVoltage = config->getString(config->batteryVoltage); String batType = config->getString(config->batteryType); String backlightMode = config->getString(config->backlight); + bool smallDecimals = config->getBool(config->smallDecimals); double value1 = 0; + String svalue = "---"; double valueTrend = 0; // Average over 10 values // Get voltage value @@ -234,36 +240,12 @@ public: printAvg(average, 320, 84, true); // Reading bus data or using simulation data - getdisplay().setFont(&DSEG7Classic_BoldItalic60pt7b); - getdisplay().setCursor(20, 240); - if(simulation == true){ - if(batVoltage == "12V"){ - value1 = 12.0; - } - if(batVoltage == "24V"){ - value1 = 24.0; - } - value1 += float(random(0, 5)) / 10; // Simulation data - getdisplay().print(value1,1); - } - else{ - // Check for valid real data, display also if hold values activated - if(valid1 == true || holdvalues == true){ - // Resolution switching - if(value1 < 10){ - getdisplay().print(value1,2); - } - if(value1 >= 10 && value1 < 100){ - getdisplay().print(value1,1); - } - if(value1 >= 100){ - getdisplay().print(value1,0); - } - } - else{ - getdisplay().print("---"); // Missing bus data - } + if(valid1 == true || holdvalues == true){ + svalue = formatValue(value1, String("formatXdr:U:V"), *commonData); + } else { + svalue = "---"; // Missing bus data } + printBoatValue(svalue, 300, 240, RIGHT, 60, smallDecimals); // Show trend indicator if(trend == true){ diff --git a/lib/obp60task/PageWeather.cpp b/lib/obp60task/PageWeather.cpp index c33a88c..12ba66e 100644 --- a/lib/obp60task/PageWeather.cpp +++ b/lib/obp60task/PageWeather.cpp @@ -14,6 +14,10 @@ private: CHART }; + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; + static constexpr int XOFFSET = 133; // x offset for display of boat values int width; // Screen width @@ -28,8 +32,7 @@ private: bool useSimuData; bool holdValues; String flashLED; - String backlightMode; - String tempFormat; + bool smallDecimals; static constexpr int NUMVALUES = 4; // number of boat values used on this page static constexpr int NUMCHARTS = 1; // one data buffer used on this page @@ -74,16 +77,13 @@ private: } // Print value - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - if (bValue[i]->getFormat() == "formatXdr:P:P" || bValue[i]->getFormat() == "formatXdr:P:B") { - getdisplay().setCursor(6 + xOffset, 275); // pressure format is always 4 digits when all other boat data has 3 digit format - } else { - getdisplay().setCursor(37 + xOffset, 275); - } + int valueX = XOFFSET * i - 5; + int valueY = 275; + int DsegFontSize = 20; if (!holdValues || useSimuData) { - getdisplay().print(sValue); // Real value as formated string + printBoatValue(sValue, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string } else { - getdisplay().print(sValueOld[i]); // Old value as formated string + printBoatValue(sValueOld[i], valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string } if (valid) { // Save value for hold function @@ -112,8 +112,7 @@ public: useSimuData = commonData->config->getBool(commonData->config->useSimuData); holdValues = commonData->config->getBool(commonData->config->holdvalues); flashLED = commonData->config->getString(commonData->config->flashLED); - backlightMode = commonData->config->getString(commonData->config->backlight); - tempFormat = commonData->config->getString(commonData->config->tempFormat); // [K|°C|°F] + smallDecimals = commonData->config->getBool(commonData->config->smallDecimals); } virtual void setupKeys() @@ -223,14 +222,12 @@ public: bValue.push_back(pageData.values[i]); } - // Optical warning by limit violation (unused) - if (String(flashLED) == "Limit Violation") { - setBlinkingLED(false); - setFlashLED(false); - } - - if (bValue[0] == NULL && bValue[1] == NULL && bValue[2] == NULL && bValue[3] == NULL) + if (bValue[0] == NULL && bValue[1] == NULL && bValue[2] == NULL && bValue[3] == NULL) { return PAGE_OK; // no data, no page to display + } + if (dataHstryBuf == nullptr) { // no buffer for main boat data item, no page display + return PAGE_OK; + } LOG_DEBUG(GwLog::DEBUG, "PageWeather: printing #1: %s, %.3f, %s, #2: %s, %.3f, %s, #3: %s, %.3f, %s, #4: %s, %.3f, %s", bValue[0]->getName().c_str(), bValue[0]->value, bValue[0]->getFormat().c_str(), bValue[1]->getName().c_str(), bValue[1]->value, bValue[1]->getFormat().c_str(), @@ -241,11 +238,10 @@ public: displaySetPartialWindow(0, 0, width, height); // Set partial update - if (dataHstryBuf == nullptr) { // no buffer for main boat data item, no page display - return PAGE_UPDATE; - } - if (!dataChart[0]->isValid()) { - dataChart[0]->init(); // try late initialization if chart object could not be properly initialized earlier due to missing boat data + if (dataChart[0]) { // Check only if dataChart object exists at all + if (!dataChart[0]->isValid()) { + dataChart[0]->init(); // try late initialization if chart object could not be properly initialized earlier due to missing boat data + } } if (pageMode == VAL_CHART) { @@ -281,5 +277,4 @@ PageDescription registerPageWeather( { }, // Bus values we need in the page true // Show display header on/off ); - -#endif +#endif \ No newline at end of file diff --git a/lib/obp60task/PageWind.cpp b/lib/obp60task/PageWind.cpp index 084651b..ddd5869 100644 --- a/lib/obp60task/PageWind.cpp +++ b/lib/obp60task/PageWind.cpp @@ -213,6 +213,10 @@ static unsigned char front_bits[] PROGMEM = { class PageWind : public Page { +static constexpr int8_t LEFT = 0; +static constexpr int8_t CENTER = 1; +static constexpr int8_t RIGHT = 2; + bool keylock = false; // Keylock int8_t lp = 80; // Pointer length char mode = 'N'; // page mode (N)ormal | (L)ens | e(X)ample @@ -306,11 +310,10 @@ public: static String unit2old = ""; // Get config data - String lengthformat = config->getString(config->lengthFormat); bool simulation = config->getBool(config->useSimuData); bool holdvalues = config->getBool(config->holdvalues); String flashLED = config->getString(config->flashLED); - String backlightMode = config->getString(config->backlight); + bool smallDecimals = config->getBool(config->smallDecimals); GwApi::BoatValue *bvalue1; // Value 1 for speed on top GwApi::BoatValue *bvalue2; // Value 2 for angle on bottom @@ -512,17 +515,14 @@ public: } // Wind speed as decimal number - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(150, 250); if (holdvalues == false) { - getdisplay().print(svalue1); + printBoatValue(svalue1, 260, 250, RIGHT, 26, smallDecimals); } else { - getdisplay().print(svalue1old); + printBoatValue(svalue1old, 260, 250, RIGHT, 26, smallDecimals); } // unit getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().setCursor(220, 265); - getdisplay().print("kts"); + drawTextRalign(260, 265, unit1); } else { // Normal mode @@ -584,17 +584,14 @@ public: } // Wind speed as decimal number - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(150, 250); if (holdvalues == false) { - getdisplay().print(svalue1); + printBoatValue(svalue1, 260, 250, RIGHT, 26, smallDecimals); } else { - getdisplay().print(svalue1old); + printBoatValue(svalue1old, 260, 250, RIGHT, 26, smallDecimals); } // unit getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().setCursor(220, 265); - getdisplay().print("kts"); + drawTextRalign(260, 265, unit1); // Wind pointer (angle) if (bvalue2->valid or simulation) { diff --git a/lib/obp60task/PageWindRose.cpp b/lib/obp60task/PageWindRose.cpp index 75f9ab1..5f9ccb3 100644 --- a/lib/obp60task/PageWindRose.cpp +++ b/lib/obp60task/PageWindRose.cpp @@ -5,7 +5,10 @@ class PageWindRose : public Page { -int16_t lp = 80; // Pointer length +private: + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; public: PageWindRose(CommonData &common){ @@ -27,6 +30,9 @@ public: GwConfigHandler *config = commonData->config; GwLog *logger = commonData->logger; + int valueX, valueY; + int DsegFontSize; + static String svalue1old = ""; static String unit1old = ""; static String svalue2old = ""; @@ -41,19 +47,18 @@ public: static String unit6old = ""; // Get config data - String lengthformat = config->getString(config->lengthFormat); bool simulation = config->getBool(config->useSimuData); bool holdvalues = config->getBool(config->holdvalues); String flashLED = config->getString(config->flashLED); - String backlightMode = config->getString(config->backlight); + bool smallDecimals = config->getBool(config->smallDecimals); // Get boat value for AWA GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue) String name1 = xdrDelete(bvalue1->getName()); // Value name name1 = name1.substring(0, 6); // String length limit for value name double value1 = bvalue1->value; // Value as double in SI unit - bool valid1 = bvalue1->valid; // Valid information value1 = formatValue(bvalue1, *commonData).value;// Format only nesaccery for simulation data for pointer + bool valid1 = bvalue1->valid; // Valid information String svalue1 = formatValue(bvalue1, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places String unit1 = formatValue(bvalue1, *commonData).unit; // Unit of value if(valid1 == true){ @@ -141,13 +146,10 @@ public: // Set display in partial refresh mode displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update - getdisplay().setTextColor(commonData->fgcolor); // Show values AWA - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(10, 65); - getdisplay().print(svalue1); // Value + printBoatValue(svalue1, 101, 65, RIGHT, 20, smallDecimals); // value getdisplay().setFont(&Ubuntu_Bold12pt8b); getdisplay().setCursor(10, 95); getdisplay().print(name1); // Name @@ -161,13 +163,11 @@ public: getdisplay().print(unit1old); // Unit } - // Horizintal separator left + // Horizontal separator left getdisplay().fillRect(0, 149, 60, 3, commonData->fgcolor); // Show values AWS - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(10, 270); - getdisplay().print(svalue2); // Value + printBoatValue(svalue2, 101, 270, RIGHT, 20, smallDecimals); // value getdisplay().setFont(&Ubuntu_Bold12pt8b); getdisplay().setCursor(10, 220); getdisplay().print(name2); // Name @@ -182,14 +182,7 @@ public: } // Show values TWD - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(295, 65); - if(valid3 == true){ - getdisplay().print(abs(value3 * 180 / PI), 0); // Value - } - else{ - getdisplay().print("---"); // Value - } + printBoatValue(svalue3, 391, 65, RIGHT, 20, smallDecimals); // value getdisplay().setFont(&Ubuntu_Bold12pt8b); getdisplay().setCursor(335, 95); getdisplay().print(name3); // Name @@ -207,9 +200,7 @@ public: getdisplay().fillRect(340, 149, 80, 3, commonData->fgcolor); // Show values TWS - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(295, 270); - getdisplay().print(svalue4); // Value + printBoatValue(svalue4, 391, 270, RIGHT, 20, smallDecimals); // value getdisplay().setFont(&Ubuntu_Bold12pt8b); getdisplay().setCursor(335, 220); getdisplay().print(name4); // Name @@ -227,7 +218,7 @@ public: // Draw wind rose int rInstrument = 110; // Radius of grafic instrument - float pi = 3.141592; + String sDegree; getdisplay().fillCircle(200, 150, rInstrument + 10, commonData->fgcolor); // Outer circle getdisplay().fillCircle(200, 150, rInstrument + 7, commonData->bgcolor); // Outer circle @@ -237,56 +228,38 @@ public: for(int i=0; i<360; i=i+10) { // Scaling values - float x = 200 + (rInstrument-30)*sin(i/180.0*pi); // x-coordinate dots - float y = 150 - (rInstrument-30)*cos(i/180.0*pi); // y-coordinate cots - const char *ii = ""; - switch (i) -{ - case 0: ii="0"; break; - case 30 : ii="30"; break; - case 60 : ii="60"; break; - case 90 : ii="90"; break; - case 120 : ii="120"; break; - case 150 : ii="150"; break; - case 180 : ii="180"; break; - case 210 : ii="210"; break; - case 240 : ii="240"; break; - case 270 : ii="270"; break; - case 300 : ii="300"; break; - case 330 : ii="330"; break; - default: break; - } + float x = 200 + (rInstrument-30)*sin(i/180.0*M_PI); // x-coordinate dots + float y = 150 - (rInstrument-30)*cos(i/180.0*M_PI); // y-coordinate cots - // Print text centered on position x, y - int16_t x1, y1; // Return values of getTextBounds - uint16_t w, h; // Return values of getTextBounds - displayGetTextBounds(ii, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string - getdisplay().setCursor(x-w/2, y+h/2); if(i % 30 == 0){ + // Print text centered on position x, y + int16_t x1, y1; // Return values of getTextBounds + uint16_t w, h; // Return values of getTextBounds + sDegree = String(i); getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().print(ii); - } + displayGetTextBounds(sDegree, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string + getdisplay().setCursor(x-w/2, y+h/2); + getdisplay().print(sDegree); - // Draw sub scale with dots - float x1c = 200 + rInstrument*sin(i/180.0*pi); - float y1c = 150 - rInstrument*cos(i/180.0*pi); - getdisplay().fillCircle((int)x1c, (int)y1c, 2, commonData->fgcolor); - float sinx=sin(i/180.0*pi); - float cosx=cos(i/180.0*pi); - - // Draw sub scale with lines (two triangles) - if(i % 30 == 0){ + // Draw sub scale with lines (two triangles) float dx=2; // Line thickness = 2*dx+1 float xx1 = -dx; float xx2 = +dx; float yy1 = -(rInstrument-10); float yy2 = -(rInstrument+10); + float sinx = sin(i/180.0*M_PI); + float cosx = cos(i/180.0*M_PI); getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1), 200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1), 200+(int)(cosx*xx1-sinx*yy2),150+(int)(sinx*xx1+cosx*yy2),commonData->fgcolor); getdisplay().fillTriangle(200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1), 200+(int)(cosx*xx1-sinx*yy2),150+(int)(sinx*xx1+cosx*yy2), 200+(int)(cosx*xx2-sinx*yy2),150+(int)(sinx*xx2+cosx*yy2),commonData->fgcolor); + } else { + // Draw sub scale with dots + float x1c = 200 + rInstrument*sin(i/180.0*M_PI); + float y1c = 150 - rInstrument*cos(i/180.0*M_PI); + getdisplay().fillCircle((int)x1c, (int)y1c, 2, commonData->fgcolor); } } @@ -323,9 +296,7 @@ public: //******************************************************************************************* // Show values DBT - getdisplay().setFont(&DSEG7Classic_BoldItalic16pt7b); - getdisplay().setCursor(160, 200); - getdisplay().print(svalue5); // Value + printBoatValue(svalue5, 200, 200, CENTER, 16, smallDecimals); // value getdisplay().setFont(&Ubuntu_Bold8pt8b); getdisplay().setCursor(190, 215); getdisplay().print(" "); @@ -337,9 +308,7 @@ public: } // Show values STW - getdisplay().setFont(&DSEG7Classic_BoldItalic16pt7b); - getdisplay().setCursor(160, 130); - getdisplay().print(svalue6); // Value + printBoatValue(svalue6, 200, 130, CENTER, 16, smallDecimals); // value getdisplay().setFont(&Ubuntu_Bold8pt8b); getdisplay().setCursor(190, 90); getdisplay().print(" "); diff --git a/lib/obp60task/PageWindRoseFlex.cpp b/lib/obp60task/PageWindRoseFlex.cpp index 2b71328..340d38d 100644 --- a/lib/obp60task/PageWindRoseFlex.cpp +++ b/lib/obp60task/PageWindRoseFlex.cpp @@ -5,8 +5,11 @@ class PageWindRoseFlex : public Page { -int16_t lp = 80; // Pointer length -char source = 'A'; // data source (A)pparent | (T)rue +private: + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; + char source = 'A'; // data source (A)pparent | (T)rue public: PageWindRoseFlex(CommonData &common){ @@ -42,6 +45,9 @@ public: GwConfigHandler *config = commonData->config; GwLog *logger = commonData->logger; + int valueX, valueY; + int DsegFontSize; + static String svalue1old = ""; static String unit1old = ""; static String svalue2old = ""; @@ -61,11 +67,10 @@ public: // Get config data - String lengthformat = config->getString(config->lengthFormat); bool simulation = config->getBool(config->useSimuData); bool holdvalues = config->getBool(config->holdvalues); String flashLED = config->getString(config->flashLED); - String backlightMode = config->getString(config->backlight); + bool smallDecimals = config->getBool(config->smallDecimals); GwApi::BoatValue *bvalue1; // Value 1 for angle GwApi::BoatValue *bvalue2; // Value 2 for speed @@ -79,10 +84,11 @@ public: String name1 = bvalue1->getName().c_str(); // Value name name1 = name1.substring(0, 6); // String length limit for value name double value1 = bvalue1->value; // Value as double in SI unit + value1 = formatValue(bvalue1, *commonData).value;// Format only nesaccery for simulation data for pointer bool valid1 = bvalue1->valid; // Valid information String svalue1 = formatValue(bvalue1, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places String unit1 = formatValue(bvalue1, *commonData).unit; // Unit of value - if(valid1 == true){ + if(valid1 == true){ svalue1old = svalue1; // Save old value unit1old = unit1; // Save old unit } @@ -97,12 +103,9 @@ public: name2 = name2.substring(0, 6); // String length limit for value name double value2 = bvalue2->value; // Value as double in SI unit bool valid2 = bvalue2->valid; // Valid information - if (simulation) { - value2 = 0.62731; // some random value - } String svalue2 = formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places String unit2 = formatValue(bvalue2, *commonData).unit; // Unit of value - if(valid2 == true){ + if(valid2 == true){ svalue2old = svalue2; // Save old value unit2old = unit2; // Save old unit } @@ -185,7 +188,6 @@ public: unit6old = unit6; // Save old unit } - // Optical warning by limit violation (unused) if(String(flashLED) == "Limit Violation"){ setBlinkingLED(false); @@ -201,13 +203,10 @@ public: // Set display in partial refresh mode displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update - getdisplay().setTextColor(commonData->fgcolor); // Show AWS or TWS top left - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(10, 65); - getdisplay().print(svalue2); // Value + printBoatValue(svalue2, 101, 65, RIGHT, 20, smallDecimals); // value getdisplay().setFont(&Ubuntu_Bold12pt8b); getdisplay().setCursor(10, 95); getdisplay().print(name2); // Name @@ -225,9 +224,7 @@ public: getdisplay().fillRect(0, 149, 60, 3, commonData->fgcolor); // Show value 3 (=first user-configured parameter) at bottom left - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(10, 270); - getdisplay().print(svalue3); // Value + printBoatValue(svalue3, 101, 270, RIGHT, 20, smallDecimals); // value getdisplay().setFont(&name3font); getdisplay().setCursor(10, 220); getdisplay().print(name3); // Name @@ -242,9 +239,7 @@ public: } // Show value 4 (=second user-configured parameter) at top right - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(295, 65); - getdisplay().print(svalue4); // Value + printBoatValue(svalue4, 395, 65, RIGHT, 20, smallDecimals); // value getdisplay().setFont(&name4font); getdisplay().setCursor(325, 95); getdisplay().print(name4); // Name @@ -258,13 +253,11 @@ public: getdisplay().print(unit4old); // Unit } - // Horizintal separator right + // Horizontal separator right getdisplay().fillRect(340, 149, 80, 3, commonData->fgcolor); // Show value 5 (=third user-configured parameter) at bottom right - getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b); - getdisplay().setCursor(295, 270); - getdisplay().print(svalue5); // Value + printBoatValue(svalue5, 395, 270, RIGHT, 20, smallDecimals); // value getdisplay().setFont(&name5font); getdisplay().setCursor(325, 220); getdisplay().print(name5); // Name @@ -283,6 +276,7 @@ public: // Draw wind rose int rInstrument = 110; // Radius of grafic instrument + String sDegree; getdisplay().fillCircle(200, 150, rInstrument + 10, commonData->fgcolor); // Outer circle getdisplay().fillCircle(200, 150, rInstrument + 7, commonData->bgcolor); // Outer circle @@ -294,53 +288,36 @@ public: // Scaling values float x = 200 + (rInstrument-30)*sin(i/180.0*M_PI); // x-coordinate dots float y = 150 - (rInstrument-30)*cos(i/180.0*M_PI); // y-coordinate dots - const char *ii = ""; - switch (i) { - case 0: ii="0"; break; - case 30 : ii="30"; break; - case 60 : ii="60"; break; - case 90 : ii="90"; break; - case 120 : ii="120"; break; - case 150 : ii="150"; break; - case 180 : ii="180"; break; - case 210 : ii="210"; break; - case 240 : ii="240"; break; - case 270 : ii="270"; break; - case 300 : ii="300"; break; - case 330 : ii="330"; break; - default: break; - } - // Print text centered on position x, y - int16_t x1, y1; // Return values of getTextBounds - uint16_t w, h; // Return values of getTextBounds - displayGetTextBounds(ii, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string - getdisplay().setCursor(x-w/2, y+h/2); if(i % 30 == 0){ + // Print text centered on position x, y + int16_t x1, y1; // Return values of getTextBounds + uint16_t w, h; // Return values of getTextBounds + sDegree = String(i); getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().print(ii); - } + displayGetTextBounds(sDegree, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string + getdisplay().setCursor(x-w/2, y+h/2); + getdisplay().print(sDegree); - // Draw sub scale with dots - float x1c = 200 + rInstrument*sin(i/180.0*M_PI); - float y1c = 150 - rInstrument*cos(i/180.0*M_PI); - getdisplay().fillCircle((int)x1c, (int)y1c, 2, commonData->fgcolor); - float sinx=sin(i/180.0*M_PI); - float cosx=cos(i/180.0*M_PI); - - // Draw sub scale with lines (two triangles) - if(i % 30 == 0){ + // Draw sub scale with lines (two triangles) float dx=2; // Line thickness = 2*dx+1 float xx1 = -dx; float xx2 = +dx; float yy1 = -(rInstrument-10); float yy2 = -(rInstrument+10); + float sinx = sin(i/180.0*M_PI); + float cosx = cos(i/180.0*M_PI); getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1), 200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1), 200+(int)(cosx*xx1-sinx*yy2),150+(int)(sinx*xx1+cosx*yy2),commonData->fgcolor); getdisplay().fillTriangle(200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1), 200+(int)(cosx*xx1-sinx*yy2),150+(int)(sinx*xx1+cosx*yy2), 200+(int)(cosx*xx2-sinx*yy2),150+(int)(sinx*xx2+cosx*yy2),commonData->fgcolor); + } else { + // Draw sub scale with dots + float x1c = 200 + rInstrument*sin(i/180.0*M_PI); + float y1c = 150 - rInstrument*cos(i/180.0*M_PI); + getdisplay().fillCircle((int)x1c, (int)y1c, 2, commonData->fgcolor); } } @@ -376,47 +353,42 @@ public: getdisplay().fillCircle(200, 150, startwidth + 4, commonData->bgcolor); getdisplay().setFont(&Ubuntu_Bold10pt8b); if (source=='A'){ - getdisplay().setCursor(193, 155); - } - else { - getdisplay().setCursor(195, 156); - } + getdisplay().setCursor(193, 155); + } + else { + getdisplay().setCursor(195, 156); + } getdisplay().print({source}); - //******************************************************************************************* - // Show value6 (=fourth user-configured parameter) -if ( cos(value1) > 0){ - //pointer points upwards - getdisplay().setFont(&DSEG7Classic_BoldItalic16pt7b); - getdisplay().setCursor(160, 200); - getdisplay().print(svalue6); // Value - getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().setCursor(190, 215); - getdisplay().print(" "); - if(holdvalues == false){ - getdisplay().print(unit6); // Unit - } - else{ - getdisplay().print(unit6old); // Unit - } -} -else{ - // pointer points downwards - getdisplay().setFont(&DSEG7Classic_BoldItalic16pt7b); - getdisplay().setCursor(160, 130); - getdisplay().print(svalue6); // Value - getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().setCursor(190, 90); - getdisplay().print(" "); - if(holdvalues == false){ - getdisplay().print(unit6); // Unit - } - else{ - getdisplay().print(unit6old); // Unit - } -} + // Show value6 (=fourth user-configured parameter) + if ( cos(value1) > 0){ + //pointer points upwards + printBoatValue(svalue6, 200, 200, CENTER, 16, smallDecimals); // value + getdisplay().setFont(&Ubuntu_Bold8pt8b); + getdisplay().setCursor(190, 215); + getdisplay().print(" "); + if(holdvalues == false){ + getdisplay().print(unit6); // Unit + } + else{ + getdisplay().print(unit6old); // Unit + } + } + else{ + // pointer points downwards + printBoatValue(svalue6, 200, 130, CENTER, 16, smallDecimals); // value + getdisplay().setFont(&Ubuntu_Bold8pt8b); + getdisplay().setCursor(190, 90); + getdisplay().print(" "); + if(holdvalues == false){ + getdisplay().print(unit6); // Unit + } + else{ + getdisplay().print(unit6old); // Unit + } + } return PAGE_UPDATE; }; diff --git a/lib/obp60task/PageXTETrack.cpp b/lib/obp60task/PageXTETrack.cpp index ce404a9..253058b 100644 --- a/lib/obp60task/PageXTETrack.cpp +++ b/lib/obp60task/PageXTETrack.cpp @@ -28,8 +28,13 @@ static unsigned char ship_bits[] PROGMEM = { class PageXTETrack : public Page { + static constexpr int8_t LEFT = 0; + static constexpr int8_t CENTER = 1; + static constexpr int8_t RIGHT = 2; + bool simulation = false; bool holdvalues = false; + bool smallDecimals = false; public: PageXTETrack(CommonData &common){ @@ -37,6 +42,7 @@ class PageXTETrack : public Page common.logger->logDebug(GwLog::LOG,"Instantiate PageXTETrack"); simulation = common.config->getBool(common.config->useSimuData); holdvalues = common.config->getBool(common.config->holdvalues); + smallDecimals = common.config->getBool(common.config->smallDecimals); } void drawSegment(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, @@ -95,44 +101,33 @@ class PageXTETrack : public Page // descriptions getdisplay().setFont(&Ubuntu_Bold8pt8b); - getdisplay().setCursor(50, 188); + getdisplay().setCursor(30, 188); getdisplay().print("Cross-track error"); getdisplay().setCursor(270, 188); getdisplay().print("Track"); - getdisplay().setCursor(45, 275); + getdisplay().setCursor(25, 275); getdisplay().print("Distance to waypoint"); - getdisplay().setCursor(260, 275); + getdisplay().setCursor(280, 275); getdisplay().print("Bearing"); // values - getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b); - - int16_t x, y; - uint16_t w, h; - GwApi::BoatValue *bv_xte = pageData.values[0]; // XTE String sval_xte = formatValue(bv_xte, *commonData).svalue; - displayGetTextBounds(sval_xte, 0, 0, &x, &y, &w, &h); - getdisplay().setCursor(160-w, 170); - getdisplay().print(sval_xte); +// printBoatValue(sval_xte, 160, 170, RIGHT, 30, smallDecimals); + printBoatValue(sval_xte, 180, 170, RIGHT, 30, smallDecimals); GwApi::BoatValue *bv_cog = pageData.values[1]; // COG String sval_cog = formatValue(bv_cog, *commonData).svalue; - displayGetTextBounds(sval_cog, 0, 0, &x, &y, &w, &h); - getdisplay().setCursor(360-w, 170); - getdisplay().print(sval_cog); + printBoatValue(sval_cog, 360, 170, RIGHT, 30, smallDecimals); GwApi::BoatValue *bv_dtw = pageData.values[2]; // DTW String sval_dtw = formatValue(bv_dtw, *commonData).svalue; - displayGetTextBounds(sval_dtw, 0, 0, &x, &y, &w, &h); - getdisplay().setCursor(160-w, 257); - getdisplay().print(sval_dtw); +// printBoatValue(sval_dtw, 160, 257, RIGHT, 30, smallDecimals); + printBoatValue(sval_dtw, 160, 257, RIGHT, 30, smallDecimals); GwApi::BoatValue *bv_btw = pageData.values[3]; // BTW String sval_btw = formatValue(bv_btw, *commonData).svalue; - displayGetTextBounds(sval_btw, 0, 0, &x, &y, &w, &h); - getdisplay().setCursor(360-w, 257); - getdisplay().print(sval_btw); + printBoatValue(sval_btw, 368, 257, RIGHT, 30, smallDecimals); bool valid = bv_cog->valid && bv_btw->valid; @@ -148,6 +143,9 @@ class PageXTETrack : public Page sval_wpname = "Tonne 122"; } + int16_t x, y; + uint16_t w, h; + getdisplay().setFont(&Ubuntu_Bold10pt8b); displayGetTextBounds(sval_wpname, 0, 150, &x, &y, &w, &h); // TODO if text don't fix use smaller font size. diff --git a/lib/obp60task/Pagedata.h b/lib/obp60task/Pagedata.h index 0fcb304..aa096df 100644 --- a/lib/obp60task/Pagedata.h +++ b/lib/obp60task/Pagedata.h @@ -205,6 +205,8 @@ typedef struct{ // Formatter for boat values FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata); FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool ignoreSimuDataSetting); +FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, String setPrecision); +String formatValue(const double &value, const String &vFormat, CommonData &commondata); // Helper method for conversion of any data value from SI to user defined format (defined in OBP60Formatter) double convertValue(const double &value, const String &format, CommonData &commondata); diff --git a/lib/obp60task/config_obp40.json b/lib/obp60task/config_obp40.json index e73f545..af535af 100644 --- a/lib/obp60task/config_obp40.json +++ b/lib/obp60task/config_obp40.json @@ -1355,10 +1355,10 @@ }, { "name": "valueprecision", - "label": "Display value precision", + "label": "Value precision", "type": "list", "default": "2", - "description": "Maximum number of decimal places to display [1|2]", + "description": "Number of decimal precision on display: [1|2] decimals", "list": [ "1", "2" @@ -1368,6 +1368,17 @@ "obp40":"true" } }, + { + "name": "smallDecimals", + "label": "Display small decimals", + "type": "boolean", + "default": "true", + "description": "Show decimals of values in smaller size [on|off]", + "category": "OBP40 Display", + "capabilities": { + "obp40": "true" + } + }, { "name": "backlight", "label": "Backlight Mode", diff --git a/lib/obp60task/config_obp60.json b/lib/obp60task/config_obp60.json index fdf48d9..653cd6d 100644 --- a/lib/obp60task/config_obp60.json +++ b/lib/obp60task/config_obp60.json @@ -1344,10 +1344,10 @@ }, { "name": "valueprecision", - "label": "Display value precision", + "label": "Value precision", "type": "list", "default": "2", - "description": "Maximum number of decimal places to display [1|2]", + "description": "Number of decimal precision on display: [1|2] decimals", "list": [ "1", "2" @@ -1357,6 +1357,17 @@ "obp60":"true" } }, + { + "name": "smallDecimals", + "label": "Display small decimals", + "type": "boolean", + "default": "true", + "description": "Show decimals of values in smaller size [on|off]", + "category": "OBP60 Display", + "capabilities": { + "obp60": "true" + } + }, { "name": "backlight", "label": "Backlight Mode", diff --git a/lib/obp60task/config_obp70.json b/lib/obp60task/config_obp70.json index 3fd704a..ffb3d88 100644 --- a/lib/obp60task/config_obp70.json +++ b/lib/obp60task/config_obp70.json @@ -1298,10 +1298,10 @@ }, { "name": "valueprecision", - "label": "Display value precision", + "label": "Value precision", "type": "list", "default": "2", - "description": "Maximum number of decimal places to display [1|2]", + "description": "Number of decimal precision on display: [1|2] decimals", "list": [ "1", "2" @@ -1311,6 +1311,17 @@ "obp70":"true" } }, + { + "name": "smallDecimals", + "label": "Display small decimals", + "type": "boolean", + "default": "true", + "description": "Show decimals of values in smaller size [on|off]", + "category": "OBP70 Display", + "capabilities": { + "obp70": "true" + } + }, { "name": "backlight", "label": "Backlight Mode", diff --git a/lib/obp60task/fonts/DSEG7Classic-BoldItalic10pt7b.h b/lib/obp60task/fonts/DSEG7Classic-BoldItalic10pt7b.h new file mode 100644 index 0000000..a384536 --- /dev/null +++ b/lib/obp60task/fonts/DSEG7Classic-BoldItalic10pt7b.h @@ -0,0 +1,278 @@ +const uint8_t DSEG7Classic_BoldItalic10pt7bBitmaps[] PROGMEM = { + 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, + 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, + 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, + 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, + 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, + 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, + 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, + 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, + 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, + 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, + 0xF0, 0xFF, 0x7F, 0x80, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, + 0x18, 0x61, 0x87, 0xF0, 0x1F, 0xF8, 0xBF, 0xD3, 0x00, 0xCC, 0x07, 0x70, + 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x07, 0x70, 0x19, 0x00, 0x24, 0x00, 0x98, + 0x06, 0x60, 0x19, 0x80, 0x66, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEB, + 0xFF, 0x9F, 0xF8, 0x13, 0x77, 0x77, 0x76, 0x22, 0x66, 0x6E, 0xEE, 0xE6, + 0x1F, 0xF8, 0x3F, 0xD0, 0x00, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, + 0xC0, 0x07, 0x00, 0x18, 0x7F, 0xA5, 0xFE, 0x18, 0x00, 0x60, 0x01, 0x80, + 0x06, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0B, 0xFE, 0x1F, 0xF8, 0x3F, + 0xF0, 0xFF, 0x40, 0x06, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, + 0x00, 0x31, 0xFE, 0x8F, 0xF4, 0x00, 0x60, 0x03, 0x00, 0x18, 0x01, 0xC0, + 0x0E, 0x00, 0x70, 0x03, 0x9F, 0xFD, 0xFF, 0x80, 0x40, 0x0B, 0x00, 0xD8, + 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x06, 0xBF, 0xD1, 0xFE, + 0x80, 0x0C, 0x00, 0x60, 0x03, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, + 0x01, 0x80, 0x3F, 0xF5, 0xFE, 0x60, 0x06, 0x00, 0xE0, 0x0E, 0x00, 0xE0, + 0x0E, 0x00, 0xE0, 0x0B, 0xFC, 0x3F, 0xD0, 0x03, 0x00, 0x30, 0x03, 0x00, + 0x70, 0x07, 0x00, 0x70, 0x07, 0x7F, 0xFF, 0xFC, 0x1F, 0xF9, 0x7F, 0x8C, + 0x00, 0x60, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x02, 0xFF, + 0x17, 0xFA, 0xC0, 0x36, 0x01, 0xB0, 0x0D, 0x80, 0xFC, 0x07, 0xE0, 0x3F, + 0x01, 0xEF, 0xFE, 0xFF, 0xC0, 0x3F, 0xF2, 0xFF, 0x58, 0x06, 0xC0, 0x7E, + 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x34, 0x00, 0x80, 0x04, 0x00, + 0x60, 0x03, 0x00, 0x18, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x0C, + 0x1F, 0xF8, 0xBF, 0xD3, 0x00, 0xCC, 0x07, 0x70, 0x1D, 0xC0, 0x77, 0x01, + 0xDC, 0x07, 0x70, 0x19, 0x7F, 0xA5, 0xFE, 0x98, 0x06, 0x60, 0x19, 0x80, + 0x66, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEB, 0xFF, 0x9F, 0xF8, 0x3F, + 0xF2, 0xFF, 0x58, 0x06, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, + 0xE0, 0x35, 0xFE, 0x8F, 0xF4, 0x00, 0x60, 0x03, 0x00, 0x18, 0x01, 0xC0, + 0x0E, 0x00, 0x70, 0x03, 0x9F, 0xFD, 0xFF, 0x80, 0x67, 0x00, 0x00, 0x00, + 0x4E, 0x40, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, + 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, + 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, + 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, + 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, + 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0x1F, 0xF8, 0xBF, 0xD3, + 0x00, 0xCC, 0x07, 0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x07, 0x70, 0x19, + 0x7F, 0xA5, 0xFE, 0x98, 0x06, 0x60, 0x19, 0x80, 0x66, 0x03, 0xB8, 0x0E, + 0xE0, 0x3B, 0x80, 0xE8, 0x01, 0x80, 0x20, 0x01, 0x80, 0x0C, 0x00, 0xE0, + 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x5F, 0xE2, 0xFF, 0x58, 0x06, + 0xC0, 0x36, 0x01, 0xB0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3D, 0xFF, 0xDF, + 0xF8, 0x1F, 0xE5, 0xFE, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0xE0, 0x0E, + 0x00, 0xE0, 0x0B, 0xFE, 0x7F, 0xE0, 0x00, 0x04, 0x00, 0x30, 0x01, 0xC0, + 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x06, 0x1F, 0xE9, 0x7F, 0xA6, + 0x01, 0x98, 0x06, 0x60, 0x19, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3A, + 0xFF, 0xE7, 0xFE, 0x00, 0x1F, 0xF9, 0x7F, 0x8C, 0x00, 0x60, 0x07, 0x00, + 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x02, 0xFF, 0x17, 0xF8, 0xC0, 0x06, + 0x00, 0x30, 0x01, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x2F, 0xF8, 0xFF, + 0xC0, 0x1F, 0xF9, 0x7F, 0x8C, 0x00, 0x60, 0x07, 0x00, 0x38, 0x01, 0xC0, + 0x0E, 0x00, 0x70, 0x02, 0xFF, 0x17, 0xF8, 0xC0, 0x06, 0x00, 0x30, 0x01, + 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x20, 0x00, 0x1F, 0xF9, 0x7F, 0x8C, + 0x00, 0x60, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x02, 0x00, + 0x10, 0x02, 0xC0, 0x36, 0x01, 0xB0, 0x0D, 0x80, 0xFC, 0x07, 0xE0, 0x3F, + 0x01, 0xEF, 0xFE, 0xFF, 0xC0, 0x20, 0x01, 0x80, 0x0C, 0x00, 0xE0, 0x07, + 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x5F, 0xE2, 0xFF, 0x58, 0x06, 0xC0, + 0x36, 0x01, 0xB0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3C, 0x00, 0xC0, 0x2D, + 0xBF, 0xFF, 0x60, 0x00, 0x04, 0x00, 0x30, 0x01, 0xC0, 0x07, 0x00, 0x1C, + 0x00, 0x70, 0x01, 0xC0, 0x06, 0x00, 0x09, 0x00, 0x26, 0x01, 0x98, 0x06, + 0x60, 0x19, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3A, 0xFF, 0xE7, 0xFE, + 0x00, 0x1F, 0xF9, 0x7F, 0x8C, 0x00, 0x60, 0x07, 0x00, 0x38, 0x01, 0xC0, + 0x0E, 0x00, 0x70, 0x02, 0xFF, 0x17, 0xFA, 0xC0, 0x36, 0x01, 0xB0, 0x0D, + 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xE0, 0x06, 0x20, 0x03, 0x00, 0x30, + 0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0x00, 0x40, 0x04, 0x00, 0x60, + 0x06, 0x00, 0x60, 0x06, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0B, 0xFE, 0x7F, + 0xE0, 0x1F, 0xF8, 0xBF, 0xD3, 0x00, 0xCC, 0x07, 0x70, 0x1D, 0xC0, 0x77, + 0x01, 0xDC, 0x07, 0x70, 0x19, 0x00, 0x24, 0x00, 0x98, 0x06, 0x60, 0x19, + 0x80, 0x66, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xE8, 0x01, 0x80, 0x1F, + 0xE2, 0xFF, 0x58, 0x06, 0xC0, 0x36, 0x01, 0xB0, 0x1F, 0x80, 0xFC, 0x07, + 0xE0, 0x3C, 0x00, 0xC0, 0x1F, 0xE2, 0xFF, 0x58, 0x06, 0xC0, 0x36, 0x01, + 0xB0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3D, 0xFF, 0xDF, 0xF8, 0x1F, 0xF8, + 0xBF, 0xD3, 0x00, 0xCC, 0x07, 0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x07, + 0x70, 0x19, 0x7F, 0xA5, 0xFE, 0x18, 0x00, 0x60, 0x01, 0x80, 0x06, 0x00, + 0x38, 0x00, 0xE0, 0x03, 0x80, 0x08, 0x00, 0x00, 0x3F, 0xF2, 0xFF, 0x58, + 0x06, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x35, 0xFE, + 0x8F, 0xF4, 0x00, 0x60, 0x03, 0x00, 0x18, 0x01, 0xC0, 0x0E, 0x00, 0x70, + 0x03, 0x80, 0x0C, 0x1F, 0xE5, 0xFE, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, + 0xE0, 0x0E, 0x00, 0xE0, 0x08, 0x00, 0x40, 0x06, 0x00, 0x60, 0x0E, 0x00, + 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xBF, 0xC3, 0xFD, 0x00, 0x30, 0x03, + 0x00, 0x30, 0x07, 0x00, 0x70, 0x07, 0x00, 0x77, 0xFF, 0xFF, 0xC0, 0x20, + 0x03, 0x00, 0x30, 0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0x00, 0x5F, + 0xE5, 0xFE, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0xE0, 0x0E, 0x00, 0xE0, + 0x0B, 0xFE, 0x7F, 0xE0, 0x40, 0x0B, 0x00, 0xD8, 0x06, 0xC0, 0x36, 0x03, + 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xBF, 0xFB, 0xFF, 0x00, 0x20, 0x04, 0xC0, + 0x33, 0x01, 0xDC, 0x07, 0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x06, 0x40, + 0x09, 0x00, 0x26, 0x01, 0x98, 0x06, 0x60, 0x19, 0x80, 0xEE, 0x03, 0xB8, + 0x0E, 0xE0, 0x3A, 0xFF, 0xE7, 0xFE, 0x00, 0x20, 0x04, 0xC0, 0x33, 0x01, + 0xDC, 0x07, 0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x06, 0x5F, 0xE9, 0x7F, + 0xA6, 0x01, 0x98, 0x06, 0x60, 0x19, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, + 0x3A, 0xFF, 0xE7, 0xFE, 0x00, 0x20, 0x04, 0xC0, 0x33, 0x01, 0xDC, 0x07, + 0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x06, 0x5F, 0xE9, 0x7F, 0xA6, 0x01, + 0x98, 0x06, 0x60, 0x19, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3A, 0x00, + 0x60, 0x40, 0x0B, 0x00, 0xD8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, + 0xFC, 0x06, 0xBF, 0xD1, 0xFE, 0x80, 0x0C, 0x00, 0x60, 0x03, 0x00, 0x38, + 0x01, 0xC0, 0x0E, 0x00, 0x73, 0xFF, 0xBF, 0xF0, 0x1F, 0xF8, 0x3F, 0xD0, + 0x00, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x18, + 0x00, 0x24, 0x00, 0x18, 0x00, 0x60, 0x01, 0x80, 0x06, 0x00, 0x38, 0x00, + 0xE0, 0x03, 0x80, 0x0B, 0xFE, 0x1F, 0xF8, 0xFE, 0x18, 0x61, 0x86, 0x18, + 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, + 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, + 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, + 0x61, 0x87, 0xF0, 0x7F, 0xDF, 0xF8, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, + 0x86, 0x18, 0x61, 0x87, 0xF0, 0x1F, 0xF8, 0xBF, 0xD3, 0x00, 0xCC, 0x07, + 0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x07, 0x70, 0x19, 0x7F, 0xA5, 0xFE, + 0x98, 0x06, 0x60, 0x19, 0x80, 0x66, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, + 0xE8, 0x01, 0x80, 0x20, 0x01, 0x80, 0x0C, 0x00, 0xE0, 0x07, 0x00, 0x38, + 0x01, 0xC0, 0x0E, 0x00, 0x5F, 0xE2, 0xFF, 0x58, 0x06, 0xC0, 0x36, 0x01, + 0xB0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3D, 0xFF, 0xDF, 0xF8, 0x1F, 0xE5, + 0xFE, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0B, + 0xFE, 0x7F, 0xE0, 0x00, 0x04, 0x00, 0x30, 0x01, 0xC0, 0x07, 0x00, 0x1C, + 0x00, 0x70, 0x01, 0xC0, 0x06, 0x1F, 0xE9, 0x7F, 0xA6, 0x01, 0x98, 0x06, + 0x60, 0x19, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3A, 0xFF, 0xE7, 0xFE, + 0x00, 0x1F, 0xF9, 0x7F, 0x8C, 0x00, 0x60, 0x07, 0x00, 0x38, 0x01, 0xC0, + 0x0E, 0x00, 0x70, 0x02, 0xFF, 0x17, 0xF8, 0xC0, 0x06, 0x00, 0x30, 0x01, + 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x2F, 0xF8, 0xFF, 0xC0, 0x1F, 0xF9, + 0x7F, 0x8C, 0x00, 0x60, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, + 0x02, 0xFF, 0x17, 0xF8, 0xC0, 0x06, 0x00, 0x30, 0x01, 0x80, 0x1C, 0x00, + 0xE0, 0x07, 0x00, 0x20, 0x00, 0x1F, 0xF9, 0x7F, 0x8C, 0x00, 0x60, 0x07, + 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x02, 0x00, 0x10, 0x02, 0xC0, + 0x36, 0x01, 0xB0, 0x0D, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xEF, 0xFE, + 0xFF, 0xC0, 0x20, 0x01, 0x80, 0x0C, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x01, + 0xC0, 0x0E, 0x00, 0x5F, 0xE2, 0xFF, 0x58, 0x06, 0xC0, 0x36, 0x01, 0xB0, + 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3C, 0x00, 0xC0, 0x2D, 0xBF, 0xFF, 0x60, + 0x00, 0x04, 0x00, 0x30, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, + 0xC0, 0x06, 0x00, 0x09, 0x00, 0x26, 0x01, 0x98, 0x06, 0x60, 0x19, 0x80, + 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3A, 0xFF, 0xE7, 0xFE, 0x00, 0x1F, 0xF9, + 0x7F, 0x8C, 0x00, 0x60, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, + 0x02, 0xFF, 0x17, 0xFA, 0xC0, 0x36, 0x01, 0xB0, 0x0D, 0x80, 0xFC, 0x07, + 0xE0, 0x3F, 0x01, 0xE0, 0x06, 0x20, 0x03, 0x00, 0x30, 0x07, 0x00, 0x70, + 0x07, 0x00, 0x70, 0x07, 0x00, 0x40, 0x04, 0x00, 0x60, 0x06, 0x00, 0x60, + 0x06, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0B, 0xFE, 0x7F, 0xE0, 0x1F, 0xF8, + 0xBF, 0xD3, 0x00, 0xCC, 0x07, 0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x07, + 0x70, 0x19, 0x00, 0x24, 0x00, 0x98, 0x06, 0x60, 0x19, 0x80, 0x66, 0x03, + 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xE8, 0x01, 0x80, 0x1F, 0xE2, 0xFF, 0x58, + 0x06, 0xC0, 0x36, 0x01, 0xB0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3C, 0x00, + 0xC0, 0x1F, 0xE2, 0xFF, 0x58, 0x06, 0xC0, 0x36, 0x01, 0xB0, 0x1F, 0x80, + 0xFC, 0x07, 0xE0, 0x3D, 0xFF, 0xDF, 0xF8, 0x1F, 0xF8, 0xBF, 0xD3, 0x00, + 0xCC, 0x07, 0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x07, 0x70, 0x19, 0x7F, + 0xA5, 0xFE, 0x18, 0x00, 0x60, 0x01, 0x80, 0x06, 0x00, 0x38, 0x00, 0xE0, + 0x03, 0x80, 0x08, 0x00, 0x00, 0x3F, 0xF2, 0xFF, 0x58, 0x06, 0xC0, 0x7E, + 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x35, 0xFE, 0x8F, 0xF4, 0x00, + 0x60, 0x03, 0x00, 0x18, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x0C, + 0x1F, 0xE5, 0xFE, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0xE0, 0x0E, 0x00, + 0xE0, 0x08, 0x00, 0x40, 0x06, 0x00, 0x60, 0x0E, 0x00, 0xE0, 0x0E, 0x00, + 0xE0, 0x0E, 0x00, 0xBF, 0xC3, 0xFD, 0x00, 0x30, 0x03, 0x00, 0x30, 0x07, + 0x00, 0x70, 0x07, 0x00, 0x77, 0xFF, 0xFF, 0xC0, 0x20, 0x03, 0x00, 0x30, + 0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0x00, 0x5F, 0xE5, 0xFE, 0x60, + 0x06, 0x00, 0x60, 0x06, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0B, 0xFE, 0x7F, + 0xE0, 0x40, 0x0B, 0x00, 0xD8, 0x06, 0xC0, 0x36, 0x03, 0xF0, 0x1F, 0x80, + 0xFC, 0x07, 0xBF, 0xFB, 0xFF, 0x00, 0x20, 0x04, 0xC0, 0x33, 0x01, 0xDC, + 0x07, 0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x06, 0x40, 0x09, 0x00, 0x26, + 0x01, 0x98, 0x06, 0x60, 0x19, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3A, + 0xFF, 0xE7, 0xFE, 0x00, 0x20, 0x04, 0xC0, 0x33, 0x01, 0xDC, 0x07, 0x70, + 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x06, 0x5F, 0xE9, 0x7F, 0xA6, 0x01, 0x98, + 0x06, 0x60, 0x19, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3A, 0xFF, 0xE7, + 0xFE, 0x00, 0x20, 0x04, 0xC0, 0x33, 0x01, 0xDC, 0x07, 0x70, 0x1D, 0xC0, + 0x77, 0x01, 0xDC, 0x06, 0x5F, 0xE9, 0x7F, 0xA6, 0x01, 0x98, 0x06, 0x60, + 0x19, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3A, 0x00, 0x60, 0x40, 0x0B, + 0x00, 0xD8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x06, 0xBF, + 0xD1, 0xFE, 0x80, 0x0C, 0x00, 0x60, 0x03, 0x00, 0x38, 0x01, 0xC0, 0x0E, + 0x00, 0x73, 0xFF, 0xBF, 0xF0, 0x1F, 0xF8, 0x3F, 0xD0, 0x00, 0xC0, 0x07, + 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x18, 0x00, 0x24, 0x00, + 0x18, 0x00, 0x60, 0x01, 0x80, 0x06, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, + 0x0B, 0xFE, 0x1F, 0xF8, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, + 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, + 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, + 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0 }; + +const GFXglyph DSEG7Classic_BoldItalic10pt7bGlyphs[] PROGMEM = { + { 0, 0, 0, 4, 0, 1 }, // 0x20 ' ' + { 0, 0, 0, 16, 0, 1 }, // 0x21 '!' + { 0, 6, 14, 7, 1, -13 }, // 0x22 '"' + { 11, 6, 14, 7, 1, -13 }, // 0x23 '#' + { 22, 6, 14, 7, 1, -13 }, // 0x24 '$' + { 33, 6, 14, 7, 1, -13 }, // 0x25 '%' + { 44, 6, 14, 7, 1, -13 }, // 0x26 '&' + { 55, 6, 14, 7, 1, -13 }, // 0x27 ''' + { 66, 6, 14, 7, 1, -13 }, // 0x28 '(' + { 77, 6, 14, 7, 1, -13 }, // 0x29 ')' + { 88, 6, 14, 7, 1, -13 }, // 0x2A '*' + { 99, 6, 14, 7, 1, -13 }, // 0x2B '+' + { 110, 6, 14, 7, 1, -13 }, // 0x2C ',' + { 121, 9, 2, 16, 4, -10 }, // 0x2D '-' + { 124, 2, 2, 0, -2, -1 }, // 0x2E '.' + { 125, 6, 14, 7, 1, -13 }, // 0x2F '/' + { 136, 14, 20, 16, 1, -19 }, // 0x30 '0' + { 171, 4, 18, 16, 11, -18 }, // 0x31 '1' + { 180, 14, 20, 16, 1, -19 }, // 0x32 '2' + { 215, 13, 20, 16, 2, -19 }, // 0x33 '3' + { 248, 13, 18, 16, 2, -18 }, // 0x34 '4' + { 278, 12, 20, 16, 2, -19 }, // 0x35 '5' + { 308, 13, 20, 16, 1, -19 }, // 0x36 '6' + { 341, 13, 19, 16, 2, -19 }, // 0x37 '7' + { 372, 14, 20, 16, 1, -19 }, // 0x38 '8' + { 407, 13, 20, 16, 2, -19 }, // 0x39 '9' + { 440, 4, 11, 4, 0, -14 }, // 0x3A ':' + { 446, 6, 14, 7, 1, -13 }, // 0x3B ';' + { 457, 6, 14, 7, 1, -13 }, // 0x3C '<' + { 468, 6, 14, 7, 1, -13 }, // 0x3D '=' + { 479, 6, 14, 7, 1, -13 }, // 0x3E '>' + { 490, 6, 14, 7, 1, -13 }, // 0x3F '?' + { 501, 6, 14, 7, 1, -13 }, // 0x40 '@' + { 512, 14, 19, 16, 1, -19 }, // 0x41 'A' + { 546, 13, 19, 16, 1, -18 }, // 0x42 'B' + { 577, 12, 11, 16, 1, -10 }, // 0x43 'C' + { 594, 14, 19, 16, 1, -18 }, // 0x44 'D' + { 628, 13, 20, 16, 1, -19 }, // 0x45 'E' + { 661, 13, 19, 16, 1, -19 }, // 0x46 'F' + { 692, 13, 20, 16, 1, -19 }, // 0x47 'G' + { 725, 13, 18, 16, 1, -18 }, // 0x48 'H' + { 755, 3, 9, 16, 11, -9 }, // 0x49 'I' + { 759, 14, 19, 16, 1, -18 }, // 0x4A 'J' + { 793, 13, 19, 16, 1, -19 }, // 0x4B 'K' + { 824, 12, 19, 16, 1, -18 }, // 0x4C 'L' + { 853, 14, 19, 16, 1, -19 }, // 0x4D 'M' + { 887, 13, 10, 16, 1, -10 }, // 0x4E 'N' + { 904, 13, 11, 16, 1, -10 }, // 0x4F 'O' + { 922, 14, 19, 16, 1, -19 }, // 0x50 'P' + { 956, 13, 19, 16, 2, -19 }, // 0x51 'Q' + { 987, 12, 10, 16, 1, -10 }, // 0x52 'R' + { 1002, 12, 19, 16, 2, -18 }, // 0x53 'S' + { 1031, 12, 19, 16, 1, -18 }, // 0x54 'T' + { 1060, 13, 10, 16, 1, -9 }, // 0x55 'U' + { 1077, 14, 19, 16, 1, -18 }, // 0x56 'V' + { 1111, 14, 19, 16, 1, -18 }, // 0x57 'W' + { 1145, 14, 18, 16, 1, -18 }, // 0x58 'X' + { 1177, 13, 19, 16, 2, -18 }, // 0x59 'Y' + { 1208, 14, 20, 16, 1, -19 }, // 0x5A 'Z' + { 1243, 6, 14, 7, 1, -13 }, // 0x5B '[' + { 1254, 6, 14, 7, 1, -13 }, // 0x5C '\' + { 1265, 6, 14, 7, 1, -13 }, // 0x5D ']' + { 1276, 6, 14, 7, 1, -13 }, // 0x5E '^' + { 1287, 11, 2, 16, 2, -1 }, // 0x5F '_' + { 1290, 6, 14, 7, 1, -13 }, // 0x60 '`' + { 1301, 14, 19, 16, 1, -19 }, // 0x61 'a' + { 1335, 13, 19, 16, 1, -18 }, // 0x62 'b' + { 1366, 12, 11, 16, 1, -10 }, // 0x63 'c' + { 1383, 14, 19, 16, 1, -18 }, // 0x64 'd' + { 1417, 13, 20, 16, 1, -19 }, // 0x65 'e' + { 1450, 13, 19, 16, 1, -19 }, // 0x66 'f' + { 1481, 13, 20, 16, 1, -19 }, // 0x67 'g' + { 1514, 13, 18, 16, 1, -18 }, // 0x68 'h' + { 1544, 3, 9, 16, 11, -9 }, // 0x69 'i' + { 1548, 14, 19, 16, 1, -18 }, // 0x6A 'j' + { 1582, 13, 19, 16, 1, -19 }, // 0x6B 'k' + { 1613, 12, 19, 16, 1, -18 }, // 0x6C 'l' + { 1642, 14, 19, 16, 1, -19 }, // 0x6D 'm' + { 1676, 13, 10, 16, 1, -10 }, // 0x6E 'n' + { 1693, 13, 11, 16, 1, -10 }, // 0x6F 'o' + { 1711, 14, 19, 16, 1, -19 }, // 0x70 'p' + { 1745, 13, 19, 16, 2, -19 }, // 0x71 'q' + { 1776, 12, 10, 16, 1, -10 }, // 0x72 'r' + { 1791, 12, 19, 16, 2, -18 }, // 0x73 's' + { 1820, 12, 19, 16, 1, -18 }, // 0x74 't' + { 1849, 13, 10, 16, 1, -9 }, // 0x75 'u' + { 1866, 14, 19, 16, 1, -18 }, // 0x76 'v' + { 1900, 14, 19, 16, 1, -18 }, // 0x77 'w' + { 1934, 14, 18, 16, 1, -18 }, // 0x78 'x' + { 1966, 13, 19, 16, 2, -18 }, // 0x79 'y' + { 1997, 14, 20, 16, 1, -19 }, // 0x7A 'z' + { 2032, 6, 14, 7, 1, -13 }, // 0x7B '{' + { 2043, 6, 14, 7, 1, -13 }, // 0x7C '|' + { 2054, 6, 14, 7, 1, -13 }, // 0x7D '}' + { 2065, 6, 14, 7, 1, -13 } }; // 0x7E '~' + +const GFXfont DSEG7Classic_BoldItalic10pt7b PROGMEM = { + (uint8_t *)DSEG7Classic_BoldItalic10pt7bBitmaps, + (GFXglyph *)DSEG7Classic_BoldItalic10pt7bGlyphs, + 0x20, 0x7E, 22 }; + +// Approx. 2748 bytes diff --git a/lib/obp60task/fonts/DSEG7Classic-BoldItalic12pt7b.h b/lib/obp60task/fonts/DSEG7Classic-BoldItalic12pt7b.h new file mode 100644 index 0000000..e8d2a84 --- /dev/null +++ b/lib/obp60task/fonts/DSEG7Classic-BoldItalic12pt7b.h @@ -0,0 +1,352 @@ +const uint8_t DSEG7Classic_BoldItalic12pt7bBitmaps[] PROGMEM = { + 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, + 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, + 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, + 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, + 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, + 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, + 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, + 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, + 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, + 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, + 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0x7F, 0xEF, + 0xFC, 0x7D, 0x80, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, + 0x0C, 0x18, 0x30, 0x60, 0xFF, 0x0F, 0xFF, 0x07, 0xFF, 0x4D, 0xFF, 0x67, + 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, + 0x9C, 0x03, 0x9C, 0x00, 0xCC, 0x00, 0x26, 0x00, 0x13, 0x80, 0x39, 0xC0, + 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x00, 0xE7, + 0x00, 0xE3, 0xFF, 0xF1, 0xFF, 0xE8, 0x7F, 0xF8, 0x08, 0xCE, 0x73, 0x9C, + 0xE7, 0x71, 0x84, 0x27, 0x39, 0xCE, 0x73, 0x9D, 0xC6, 0x10, 0x0F, 0xFF, + 0x07, 0xFF, 0x41, 0xFF, 0x60, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, + 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x03, 0x80, 0x00, 0xC1, 0xFF, 0xA6, + 0xFF, 0xC3, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, + 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0xFF, 0xC1, 0xFF, 0xE0, 0x7F, + 0xF8, 0x1F, 0xFE, 0x1F, 0xFD, 0x0F, 0xFB, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x0E, 0x00, 0x06, 0x1F, + 0xFA, 0x1F, 0xFA, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, + 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x1C, 0x3F, 0xFC, 0x7F, 0xF4, 0x7F, + 0xF8, 0x00, 0x01, 0x60, 0x03, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, + 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0xE0, 0x06, 0xDF, 0xFA, 0x1F, + 0xFA, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, + 0x0E, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x0C, 0x00, 0x04, 0x1F, 0xFE, 0x3F, + 0xF9, 0xBF, 0xE3, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, + 0x70, 0x00, 0xE0, 0x03, 0x80, 0x06, 0xFF, 0xC1, 0xFF, 0xA0, 0x01, 0xC0, + 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x01, + 0xC7, 0xFF, 0x9F, 0xFD, 0x3F, 0xFC, 0x0F, 0xFF, 0x0F, 0xFE, 0x37, 0xFC, + 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, + 0x38, 0x00, 0x70, 0x00, 0x6F, 0xFC, 0x6F, 0xFD, 0x70, 0x07, 0x70, 0x07, + 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, + 0x7F, 0xFE, 0x7F, 0xFA, 0x3F, 0xFC, 0x1F, 0xFE, 0x1F, 0xFD, 0x6F, 0xFB, + 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, + 0x70, 0x0E, 0xE0, 0x06, 0xC0, 0x02, 0x00, 0x02, 0x00, 0x0E, 0x00, 0x0E, + 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x1C, + 0x00, 0x0C, 0x00, 0x04, 0x0F, 0xFF, 0x07, 0xFF, 0x4D, 0xFF, 0x67, 0x00, + 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, + 0x03, 0x9C, 0x00, 0xCD, 0xFF, 0xA6, 0xFF, 0xD3, 0x80, 0x39, 0xC0, 0x1C, + 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x00, 0xE7, 0x00, + 0xE3, 0xFF, 0xF1, 0xFF, 0xE8, 0x7F, 0xF8, 0x1F, 0xFE, 0x1F, 0xFD, 0x6F, + 0xFB, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, + 0x07, 0x70, 0x0E, 0xE0, 0x06, 0xDF, 0xFA, 0x1F, 0xFA, 0x00, 0x0E, 0x00, + 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, + 0x1C, 0x3F, 0xFC, 0x7F, 0xF4, 0x7F, 0xF8, 0x37, 0x30, 0x00, 0x00, 0x00, + 0x6E, 0x60, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, + 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, + 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, + 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, + 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, + 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, + 0x60, 0xFF, 0x0F, 0xFF, 0x07, 0xFF, 0x4D, 0xFF, 0x67, 0x00, 0x73, 0x80, + 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x03, 0x9C, + 0x00, 0xCD, 0xFF, 0xA6, 0xFF, 0xD3, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, + 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x00, 0xE7, 0x00, 0xE3, 0x00, + 0x31, 0x00, 0x08, 0x00, 0x00, 0x30, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, + 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x6F, + 0xFC, 0x6F, 0xFD, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, + 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0x7F, 0xFE, 0x7F, 0xFA, 0x3F, + 0xFC, 0x0F, 0xFD, 0xBF, 0xF7, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, + 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0xFF, 0x9F, 0xFE, 0x3F, 0xFC, + 0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, + 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x07, 0x00, 0x01, 0x83, 0xFF, 0x4D, + 0xFF, 0xA7, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, + 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x01, 0xC7, 0xFF, 0xE3, 0xFF, 0xD0, 0xFF, + 0xF0, 0x0F, 0xFF, 0x0F, 0xFE, 0x37, 0xFC, 0x38, 0x00, 0x38, 0x00, 0x38, + 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x6F, + 0xFC, 0x6F, 0xFC, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, + 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x7F, 0xF8, 0x7F, 0xF8, 0x3F, + 0xFC, 0x0F, 0xFF, 0x0F, 0xFE, 0x37, 0xFC, 0x38, 0x00, 0x38, 0x00, 0x38, + 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x6F, + 0xFC, 0x6F, 0xFC, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, + 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x60, 0x00, 0x40, 0x00, 0x0F, + 0xFF, 0x0F, 0xFE, 0x37, 0xFC, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, + 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x60, 0x00, 0x60, + 0x01, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, + 0x07, 0x70, 0x07, 0x70, 0x0E, 0x7F, 0xFE, 0x7F, 0xFA, 0x3F, 0xFC, 0x00, + 0x00, 0x30, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, + 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x6F, 0xFC, 0x6F, 0xFD, 0x70, + 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, + 0x07, 0x70, 0x0E, 0x60, 0x06, 0x40, 0x02, 0x17, 0x77, 0x77, 0x77, 0xE6, + 0x20, 0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, + 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x07, 0x00, 0x01, 0x80, 0x00, + 0x4C, 0x00, 0x27, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, + 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x01, 0xC7, 0xFF, 0xE3, 0xFF, 0xD0, + 0xFF, 0xF0, 0x0F, 0xFF, 0x0F, 0xFE, 0x37, 0xFC, 0x38, 0x00, 0x38, 0x00, + 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, + 0x6F, 0xFC, 0x6F, 0xFD, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, + 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0x60, 0x06, 0x40, 0x02, + 0x00, 0x00, 0xC0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, + 0x0E, 0x00, 0x38, 0x01, 0xC0, 0x06, 0x00, 0x18, 0x00, 0x70, 0x01, 0xC0, + 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x7F, + 0xF9, 0xFF, 0xE3, 0xFF, 0xC0, 0x0F, 0xFF, 0x07, 0xFF, 0x4D, 0xFF, 0x67, + 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, + 0x9C, 0x03, 0x9C, 0x00, 0xCC, 0x00, 0x26, 0x00, 0x13, 0x80, 0x39, 0xC0, + 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x00, 0xE7, + 0x00, 0xE3, 0x00, 0x31, 0x00, 0x08, 0x0F, 0xFC, 0x6F, 0xFD, 0x70, 0x07, + 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, + 0x70, 0x0E, 0x60, 0x06, 0x40, 0x02, 0x0F, 0xFC, 0x6F, 0xFD, 0x70, 0x07, + 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, + 0x70, 0x0E, 0x7F, 0xFE, 0x7F, 0xFA, 0x3F, 0xFC, 0x0F, 0xFF, 0x07, 0xFF, + 0x4D, 0xFF, 0x67, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, + 0x07, 0x38, 0x03, 0x9C, 0x03, 0x9C, 0x00, 0xCD, 0xFF, 0xA6, 0xFF, 0xC3, + 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, + 0x0E, 0x00, 0x07, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x1F, 0xFE, 0x1F, + 0xFD, 0x6F, 0xFB, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, + 0x07, 0x70, 0x07, 0x70, 0x0E, 0xE0, 0x06, 0xDF, 0xFA, 0x1F, 0xFA, 0x00, + 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, + 0x0E, 0x00, 0x1C, 0x00, 0x0C, 0x00, 0x04, 0x0F, 0xFD, 0xBF, 0xF7, 0x00, + 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, + 0x06, 0x00, 0x10, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xC0, 0x03, 0x80, 0x07, + 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x01, 0xC0, 0x03, 0x7F, + 0xE0, 0xFF, 0xD0, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, + 0x00, 0x1C, 0x00, 0x38, 0x00, 0xE3, 0xFF, 0xCF, 0xFE, 0x9F, 0xFE, 0x00, + 0x00, 0x00, 0xC0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, + 0x0E, 0x00, 0x38, 0x01, 0xC0, 0x06, 0xFF, 0xDB, 0xFF, 0x70, 0x01, 0xC0, + 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x7F, + 0xF9, 0xFF, 0xE3, 0xFF, 0xC0, 0x60, 0x01, 0x70, 0x07, 0x70, 0x07, 0x70, + 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0x7F, + 0xFE, 0x7F, 0xFA, 0x3F, 0xFC, 0x00, 0x00, 0x98, 0x00, 0xCE, 0x00, 0xE7, + 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x07, + 0x38, 0x01, 0x98, 0x00, 0x4C, 0x00, 0x27, 0x00, 0x73, 0x80, 0x39, 0xC0, + 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x01, 0xC7, + 0xFF, 0xE3, 0xFF, 0xD0, 0xFF, 0xF0, 0x00, 0x00, 0x98, 0x00, 0xCE, 0x00, + 0xE7, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, + 0x07, 0x38, 0x01, 0x9B, 0xFF, 0x4D, 0xFF, 0xA7, 0x00, 0x73, 0x80, 0x39, + 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x01, + 0xC7, 0xFF, 0xE3, 0xFF, 0xD0, 0xFF, 0xF0, 0x00, 0x00, 0x98, 0x00, 0xCE, + 0x00, 0xE7, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, + 0x38, 0x07, 0x38, 0x01, 0x9B, 0xFF, 0x4D, 0xFF, 0xA7, 0x00, 0x73, 0x80, + 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, + 0x01, 0xC6, 0x00, 0x62, 0x00, 0x10, 0x00, 0x01, 0x60, 0x03, 0x70, 0x07, + 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, + 0xE0, 0x06, 0xDF, 0xFA, 0x1F, 0xFA, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, + 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x1C, 0x3F, 0xFC, + 0x7F, 0xF4, 0x7F, 0xF8, 0x0F, 0xFF, 0x07, 0xFF, 0x41, 0xFF, 0x60, 0x00, + 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, + 0x03, 0x80, 0x00, 0xC0, 0x00, 0x26, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, + 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, + 0x03, 0xFF, 0xC1, 0xFF, 0xE0, 0x7F, 0xF8, 0xFF, 0x06, 0x0C, 0x18, 0x30, + 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, + 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, + 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, + 0x30, 0x60, 0xFF, 0x3F, 0xF3, 0xFF, 0x9F, 0xFE, 0xFF, 0x06, 0x0C, 0x18, + 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0x0F, 0xFF, + 0x07, 0xFF, 0x4D, 0xFF, 0x67, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, + 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x03, 0x9C, 0x00, 0xCD, 0xFF, 0xA6, + 0xFF, 0xD3, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, + 0x9C, 0x01, 0xCE, 0x00, 0xE7, 0x00, 0xE3, 0x00, 0x31, 0x00, 0x08, 0x00, + 0x00, 0x30, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, + 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x6F, 0xFC, 0x6F, 0xFD, 0x70, + 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, + 0x07, 0x70, 0x0E, 0x7F, 0xFE, 0x7F, 0xFA, 0x3F, 0xFC, 0x0F, 0xFD, 0xBF, + 0xF7, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, + 0x01, 0xC0, 0x07, 0xFF, 0x9F, 0xFE, 0x3F, 0xFC, 0x00, 0x00, 0x80, 0x00, + 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00, + 0x07, 0x00, 0x07, 0x00, 0x01, 0x83, 0xFF, 0x4D, 0xFF, 0xA7, 0x00, 0x73, + 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, + 0xCE, 0x01, 0xC7, 0xFF, 0xE3, 0xFF, 0xD0, 0xFF, 0xF0, 0x0F, 0xFF, 0x0F, + 0xFE, 0x37, 0xFC, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, + 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x6F, 0xFC, 0x6F, 0xFC, 0x70, + 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, + 0x00, 0x70, 0x00, 0x7F, 0xF8, 0x7F, 0xF8, 0x3F, 0xFC, 0x0F, 0xFF, 0x0F, + 0xFE, 0x37, 0xFC, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, + 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x6F, 0xFC, 0x6F, 0xFC, 0x70, + 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, + 0x00, 0x70, 0x00, 0x60, 0x00, 0x40, 0x00, 0x0F, 0xFF, 0x0F, 0xFE, 0x37, + 0xFC, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, + 0x00, 0x38, 0x00, 0x70, 0x00, 0x60, 0x00, 0x60, 0x01, 0x70, 0x07, 0x70, + 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, + 0x0E, 0x7F, 0xFE, 0x7F, 0xFA, 0x3F, 0xFC, 0x00, 0x00, 0x30, 0x00, 0x38, + 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, + 0x00, 0x70, 0x00, 0x6F, 0xFC, 0x6F, 0xFD, 0x70, 0x07, 0x70, 0x07, 0x70, + 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0x60, + 0x06, 0x40, 0x02, 0x17, 0x77, 0x77, 0x77, 0xE6, 0x20, 0x00, 0x00, 0x80, + 0x00, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, + 0x00, 0x07, 0x00, 0x07, 0x00, 0x01, 0x80, 0x00, 0x4C, 0x00, 0x27, 0x00, + 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, + 0x01, 0xCE, 0x01, 0xC7, 0xFF, 0xE3, 0xFF, 0xD0, 0xFF, 0xF0, 0x0F, 0xFF, + 0x0F, 0xFE, 0x37, 0xFC, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, + 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x6F, 0xFC, 0x6F, 0xFD, + 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, + 0x70, 0x07, 0x70, 0x0E, 0x60, 0x06, 0x40, 0x02, 0x00, 0x00, 0xC0, 0x03, + 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x01, + 0xC0, 0x06, 0x00, 0x18, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, + 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x7F, 0xF9, 0xFF, 0xE3, 0xFF, + 0xC0, 0x0F, 0xFF, 0x07, 0xFF, 0x4D, 0xFF, 0x67, 0x00, 0x73, 0x80, 0x39, + 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x03, 0x9C, 0x00, + 0xCC, 0x00, 0x26, 0x00, 0x13, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, + 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x00, 0xE7, 0x00, 0xE3, 0x00, 0x31, + 0x00, 0x08, 0x0F, 0xFC, 0x6F, 0xFD, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, + 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0x60, 0x06, + 0x40, 0x02, 0x0F, 0xFC, 0x6F, 0xFD, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, + 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0x7F, 0xFE, + 0x7F, 0xFA, 0x3F, 0xFC, 0x0F, 0xFF, 0x07, 0xFF, 0x4D, 0xFF, 0x67, 0x00, + 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, + 0x03, 0x9C, 0x00, 0xCD, 0xFF, 0xA6, 0xFF, 0xC3, 0x80, 0x01, 0xC0, 0x00, + 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x00, 0x1F, 0xFE, 0x1F, 0xFD, 0x6F, 0xFB, 0x70, + 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, + 0x0E, 0xE0, 0x06, 0xDF, 0xFA, 0x1F, 0xFA, 0x00, 0x0E, 0x00, 0x0E, 0x00, + 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x1C, 0x00, + 0x0C, 0x00, 0x04, 0x0F, 0xFD, 0xBF, 0xF7, 0x00, 0x1C, 0x00, 0x70, 0x01, + 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x06, 0x00, 0x10, 0x00, + 0x00, 0x00, 0xC0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, + 0x00, 0x38, 0x00, 0x70, 0x01, 0xC0, 0x03, 0x7F, 0xE0, 0xFF, 0xD0, 0x00, + 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, + 0x00, 0xE3, 0xFF, 0xCF, 0xFE, 0x9F, 0xFE, 0x00, 0x00, 0x00, 0xC0, 0x03, + 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x01, + 0xC0, 0x06, 0xFF, 0xDB, 0xFF, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, + 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x7F, 0xF9, 0xFF, 0xE3, 0xFF, + 0xC0, 0x60, 0x01, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, + 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0x7F, 0xFE, 0x7F, 0xFA, 0x3F, + 0xFC, 0x00, 0x00, 0x98, 0x00, 0xCE, 0x00, 0xE7, 0x00, 0x73, 0x80, 0x39, + 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x07, 0x38, 0x01, 0x98, 0x00, + 0x4C, 0x00, 0x27, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, + 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x01, 0xC7, 0xFF, 0xE3, 0xFF, 0xD0, + 0xFF, 0xF0, 0x00, 0x00, 0x98, 0x00, 0xCE, 0x00, 0xE7, 0x00, 0x73, 0x80, + 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x07, 0x38, 0x01, 0x9B, + 0xFF, 0x4D, 0xFF, 0xA7, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, + 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x01, 0xC7, 0xFF, 0xE3, 0xFF, + 0xD0, 0xFF, 0xF0, 0x00, 0x00, 0x98, 0x00, 0xCE, 0x00, 0xE7, 0x00, 0x73, + 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x07, 0x38, 0x01, + 0x9B, 0xFF, 0x4D, 0xFF, 0xA7, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, + 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x01, 0xC6, 0x00, 0x62, + 0x00, 0x10, 0x00, 0x01, 0x60, 0x03, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, + 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0xE0, 0x06, 0xDF, 0xFA, + 0x1F, 0xFA, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, + 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x1C, 0x3F, 0xFC, 0x7F, 0xF4, 0x7F, 0xF8, + 0x0F, 0xFF, 0x07, 0xFF, 0x41, 0xFF, 0x60, 0x00, 0x70, 0x00, 0x38, 0x00, + 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x03, 0x80, 0x00, 0xC0, + 0x00, 0x26, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, + 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0xFF, 0xC1, 0xFF, + 0xE0, 0x7F, 0xF8, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, + 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, + 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, + 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, + 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF }; + +const GFXglyph DSEG7Classic_BoldItalic12pt7bGlyphs[] PROGMEM = { + { 0, 0, 0, 5, 0, 1 }, // 0x20 ' ' + { 0, 0, 0, 20, 0, 1 }, // 0x21 '!' + { 0, 7, 16, 9, 1, -15 }, // 0x22 '"' + { 14, 7, 16, 9, 1, -15 }, // 0x23 '#' + { 28, 7, 16, 9, 1, -15 }, // 0x24 '$' + { 42, 7, 16, 9, 1, -15 }, // 0x25 '%' + { 56, 7, 16, 9, 1, -15 }, // 0x26 '&' + { 70, 7, 16, 9, 1, -15 }, // 0x27 ''' + { 84, 7, 16, 9, 1, -15 }, // 0x28 '(' + { 98, 7, 16, 9, 1, -15 }, // 0x29 ')' + { 112, 7, 16, 9, 1, -15 }, // 0x2A '*' + { 126, 7, 16, 9, 1, -15 }, // 0x2B '+' + { 140, 7, 16, 9, 1, -15 }, // 0x2C ',' + { 154, 11, 2, 20, 4, -12 }, // 0x2D '-' + { 157, 3, 3, 0, -3, -2 }, // 0x2E '.' + { 159, 7, 16, 9, 1, -15 }, // 0x2F '/' + { 173, 17, 24, 20, 1, -23 }, // 0x30 '0' + { 224, 5, 22, 20, 13, -22 }, // 0x31 '1' + { 238, 17, 24, 20, 1, -23 }, // 0x32 '2' + { 289, 16, 24, 20, 2, -23 }, // 0x33 '3' + { 337, 16, 22, 20, 2, -22 }, // 0x34 '4' + { 381, 15, 24, 20, 2, -23 }, // 0x35 '5' + { 426, 16, 24, 20, 1, -23 }, // 0x36 '6' + { 474, 16, 23, 20, 2, -23 }, // 0x37 '7' + { 520, 17, 24, 20, 1, -23 }, // 0x38 '8' + { 571, 16, 24, 20, 2, -23 }, // 0x39 '9' + { 619, 4, 13, 5, 0, -17 }, // 0x3A ':' + { 626, 7, 16, 9, 1, -15 }, // 0x3B ';' + { 640, 7, 16, 9, 1, -15 }, // 0x3C '<' + { 654, 7, 16, 9, 1, -15 }, // 0x3D '=' + { 668, 7, 16, 9, 1, -15 }, // 0x3E '>' + { 682, 7, 16, 9, 1, -15 }, // 0x3F '?' + { 696, 7, 16, 9, 1, -15 }, // 0x40 '@' + { 710, 17, 23, 20, 1, -23 }, // 0x41 'A' + { 759, 16, 23, 20, 1, -22 }, // 0x42 'B' + { 805, 14, 13, 20, 1, -12 }, // 0x43 'C' + { 828, 17, 23, 20, 1, -22 }, // 0x44 'D' + { 877, 16, 24, 20, 1, -23 }, // 0x45 'E' + { 925, 16, 23, 20, 1, -23 }, // 0x46 'F' + { 971, 16, 24, 20, 1, -23 }, // 0x47 'G' + { 1019, 16, 22, 20, 1, -22 }, // 0x48 'H' + { 1063, 4, 11, 20, 13, -11 }, // 0x49 'I' + { 1069, 17, 23, 20, 1, -22 }, // 0x4A 'J' + { 1118, 16, 23, 20, 1, -23 }, // 0x4B 'K' + { 1164, 14, 23, 20, 1, -22 }, // 0x4C 'L' + { 1205, 17, 23, 20, 1, -23 }, // 0x4D 'M' + { 1254, 16, 12, 20, 1, -12 }, // 0x4E 'N' + { 1278, 16, 13, 20, 1, -12 }, // 0x4F 'O' + { 1304, 17, 23, 20, 1, -23 }, // 0x50 'P' + { 1353, 16, 23, 20, 2, -23 }, // 0x51 'Q' + { 1399, 14, 12, 20, 1, -12 }, // 0x52 'R' + { 1420, 15, 23, 20, 2, -22 }, // 0x53 'S' + { 1464, 14, 23, 20, 1, -22 }, // 0x54 'T' + { 1505, 16, 12, 20, 1, -11 }, // 0x55 'U' + { 1529, 17, 23, 20, 1, -22 }, // 0x56 'V' + { 1578, 17, 23, 20, 1, -22 }, // 0x57 'W' + { 1627, 17, 22, 20, 1, -22 }, // 0x58 'X' + { 1674, 16, 23, 20, 2, -22 }, // 0x59 'Y' + { 1720, 17, 24, 20, 1, -23 }, // 0x5A 'Z' + { 1771, 7, 16, 9, 1, -15 }, // 0x5B '[' + { 1785, 7, 16, 9, 1, -15 }, // 0x5C '\' + { 1799, 7, 16, 9, 1, -15 }, // 0x5D ']' + { 1813, 7, 16, 9, 1, -15 }, // 0x5E '^' + { 1827, 13, 3, 20, 2, -2 }, // 0x5F '_' + { 1832, 7, 16, 9, 1, -15 }, // 0x60 '`' + { 1846, 17, 23, 20, 1, -23 }, // 0x61 'a' + { 1895, 16, 23, 20, 1, -22 }, // 0x62 'b' + { 1941, 14, 13, 20, 1, -12 }, // 0x63 'c' + { 1964, 17, 23, 20, 1, -22 }, // 0x64 'd' + { 2013, 16, 24, 20, 1, -23 }, // 0x65 'e' + { 2061, 16, 23, 20, 1, -23 }, // 0x66 'f' + { 2107, 16, 24, 20, 1, -23 }, // 0x67 'g' + { 2155, 16, 22, 20, 1, -22 }, // 0x68 'h' + { 2199, 4, 11, 20, 13, -11 }, // 0x69 'i' + { 2205, 17, 23, 20, 1, -22 }, // 0x6A 'j' + { 2254, 16, 23, 20, 1, -23 }, // 0x6B 'k' + { 2300, 14, 23, 20, 1, -22 }, // 0x6C 'l' + { 2341, 17, 23, 20, 1, -23 }, // 0x6D 'm' + { 2390, 16, 12, 20, 1, -12 }, // 0x6E 'n' + { 2414, 16, 13, 20, 1, -12 }, // 0x6F 'o' + { 2440, 17, 23, 20, 1, -23 }, // 0x70 'p' + { 2489, 16, 23, 20, 2, -23 }, // 0x71 'q' + { 2535, 14, 12, 20, 1, -12 }, // 0x72 'r' + { 2556, 15, 23, 20, 2, -22 }, // 0x73 's' + { 2600, 14, 23, 20, 1, -22 }, // 0x74 't' + { 2641, 16, 12, 20, 1, -11 }, // 0x75 'u' + { 2665, 17, 23, 20, 1, -22 }, // 0x76 'v' + { 2714, 17, 23, 20, 1, -22 }, // 0x77 'w' + { 2763, 17, 22, 20, 1, -22 }, // 0x78 'x' + { 2810, 16, 23, 20, 2, -22 }, // 0x79 'y' + { 2856, 17, 24, 20, 1, -23 }, // 0x7A 'z' + { 2907, 7, 16, 9, 1, -15 }, // 0x7B '{' + { 2921, 7, 16, 9, 1, -15 }, // 0x7C '|' + { 2935, 7, 16, 9, 1, -15 }, // 0x7D '}' + { 2949, 7, 16, 9, 1, -15 } }; // 0x7E '~' + +const GFXfont DSEG7Classic_BoldItalic12pt7b PROGMEM = { + (uint8_t *)DSEG7Classic_BoldItalic12pt7bBitmaps, + (GFXglyph *)DSEG7Classic_BoldItalic12pt7bGlyphs, + 0x20, 0x7E, 26 }; + +// Approx. 3635 bytes