From 2e836bc7501ce7ee720c0e0d63e3494f7d837ff5 Mon Sep 17 00:00:00 2001 From: Ulrich Meine Date: Thu, 1 Jan 2026 22:52:33 +0100 Subject: [PATCH] added helper method for boat value conversion to OBP60Formatter; fixed range calculation for temperature and other value formats; fixed printing for names > len(3); show "mode" only for supported data types --- lib/obp60task/OBP60Formatter.cpp | 17 ++ lib/obp60task/OBPDataOperations.cpp | 20 +-- lib/obp60task/OBPDataOperations.h | 10 +- lib/obp60task/OBPcharts.cpp | 266 ++++++++++++++++------------ lib/obp60task/OBPcharts.h | 21 ++- lib/obp60task/PageOneValue.cpp | 72 ++++---- lib/obp60task/PageWindPlot.cpp | 15 +- lib/obp60task/Pagedata.h | 3 + 8 files changed, 246 insertions(+), 178 deletions(-) diff --git a/lib/obp60task/OBP60Formatter.cpp b/lib/obp60task/OBP60Formatter.cpp index 79bd16a..830a846 100644 --- a/lib/obp60task/OBP60Formatter.cpp +++ b/lib/obp60task/OBP60Formatter.cpp @@ -877,4 +877,21 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata){ return result; } +// Helper method for conversion of boat data values from SI to user defined format +double convertValue(const double &value, const String &format, CommonData &commondata) +{ + std::unique_ptr tmpBValue; // Temp variable to get converted data value from + double result; // data value converted to user defined target data format + + // prepare dummy BoatValue structure for use in + tmpBValue = std::unique_ptr(new GwApi::BoatValue("dummy")); // we don't need boat value name for pure value conversion + tmpBValue->setFormat(format); + tmpBValue->valid = true; + tmpBValue->value = value; + + result = formatValue(tmpBValue.get(), commondata).cvalue; // get value (converted) + + return result; +} + #endif diff --git a/lib/obp60task/OBPDataOperations.cpp b/lib/obp60task/OBPDataOperations.cpp index b966bf5..aae0040 100644 --- a/lib/obp60task/OBPDataOperations.cpp +++ b/lib/obp60task/OBPDataOperations.cpp @@ -31,11 +31,11 @@ void HstryBuf::add(double value) void HstryBuf::handle(bool useSimuData, CommonData& common) { - //GwApi::BoatValue* tmpBVal; + // GwApi::BoatValue* tmpBVal; std::unique_ptr tmpBVal; // Temp variable to get formatted and converted data value from OBP60Formatter // create temporary boat value for calibration purposes and retrieval of simulation value - //tmpBVal = new GwApi::BoatValue(boatDataName.c_str()); + // tmpBVal = new GwApi::BoatValue(boatDataName.c_str()); tmpBVal = std::unique_ptr(new GwApi::BoatValue(boatDataName)); tmpBVal->setFormat(boatValue->getFormat()); tmpBVal->value = boatValue->value; @@ -45,7 +45,7 @@ void HstryBuf::handle(bool useSimuData, CommonData& common) // Calibrate boat value before adding it to history buffer calibrationData.calibrateInstance(tmpBVal.get(), logger); add(tmpBVal->value); - + } else if (useSimuData) { // add simulated value to history buffer double simValue = formatValue(tmpBVal.get(), common).value; // simulated value is generated at add(simValue); @@ -78,6 +78,9 @@ void HstryBuffers::addBuffer(const String& name) if (HstryBuffers::getBuffer(name) != nullptr) { // buffer for this data type already exists return; } + if (bufferParams.find(name) == bufferParams.end()) { // requested boat data type is not supported in list of + return; + } hstryBuffers[name] = std::unique_ptr(new HstryBuf(name, size, boatValueList, logger)); @@ -93,13 +96,11 @@ void HstryBuffers::addBuffer(const String& name) LOG_DEBUG(GwLog::DEBUG, "HstryBuffers: new buffer added: name: %s, format: %s, multiplier: %d, min value: %.2f, max value: %.2f", name, valueFormat, mltplr, bufferMinVal, bufferMaxVal); } -// Handle history buffers +// Handle all registered history buffers void HstryBuffers::handleHstryBufs(bool useSimuData, CommonData& common) { - - // Handle all registered history buffers - for (auto& pair : hstryBuffers) { - auto& buf = pair.second; + for (auto& bufMap : hstryBuffers) { + auto& buf = bufMap.second; buf->handle(useSimuData, common); } } @@ -238,7 +239,6 @@ bool WindUtils::calcWinds(const double* awaVal, const double* awsVal, } // LOG_DEBUG(GwLog::DEBUG, "WindUtils:calcWinds: HDT: %.1f, CTW %.1f, STW %.1f", hdt, ctw, stw); - if ((*awaVal == DBL_MAX) || (*awsVal == DBL_MAX)) { // Cannot calculate true wind without valid AWA, AWS; other checks are done earlier return false; @@ -284,7 +284,7 @@ bool WindUtils::addWinds() twdBVal->value = twd; twdBVal->valid = true; } - + } else { // Calculate true winds and AWD; if true winds exist, use at least AWD calculation twCalculated = calcWinds(&awaVal, &awsVal, &cogVal, &stwVal, &sogVal, &hdtVal, &hdmVal, &varVal, &twd, &tws, &twa, &awd); diff --git a/lib/obp60task/OBPDataOperations.h b/lib/obp60task/OBPDataOperations.h index f8c9c6e..7cb4320 100644 --- a/lib/obp60task/OBPDataOperations.h +++ b/lib/obp60task/OBPDataOperations.h @@ -39,9 +39,9 @@ private: String format; }; - // Define buffer parameters for each boat data type + // Define buffer parameters for supported boat data type std::map bufferParams = { - {"AWA", {1000, 10000, -M_PI, M_PI, "formatWind"}}, + {"AWA", {1000, 10000, 0.0, M_TWOPI, "formatWind"}}, {"AWD", {1000, 10000, 0.0, M_TWOPI, "formatCourse"}}, {"AWS", {1000, 1000, 0.0, 65.0, "formatKnots"}}, {"COG", {1000, 10000, 0.0, M_TWOPI, "formatCourse"}}, @@ -50,13 +50,13 @@ private: {"DPT", {1000, 100, 0.0, 650.0, "formatDepth"}}, {"HDM", {1000, 10000, 0.0, M_TWOPI, "formatCourse"}}, {"HDT", {1000, 10000, 0.0, M_TWOPI, "formatCourse"}}, - {"ROT", {1000, 10000, -M_PI / 180.0 * 99.0, M_PI / 180.0 * 99.0, "formatRot"}}, // min/max is -/+ 99 degrees for rotational angle + {"ROT", {1000, 10000, -M_PI / 180.0 * 99.0, M_PI / 180.0 * 99.0, "formatRot"}}, // min/max is -/+ 99 degrees for "rate of turn" {"SOG", {1000, 1000, 0.0, 65.0, "formatKnots"}}, {"STW", {1000, 1000, 0.0, 65.0, "formatKnots"}}, - {"TWA", {1000, 10000, -M_PI, M_PI, "formatWind"}}, + {"TWA", {1000, 10000, 0.0, M_TWOPI, "formatWind"}}, {"TWD", {1000, 10000, 0.0, M_TWOPI, "formatCourse"}}, {"TWS", {1000, 1000, 0.0, 65.0, "formatKnots"}}, - {"WTemp", {1000, 100, 0.0, 650.0, "kelvinToC"}} + {"WTemp", {1000, 100, 233.0, 650.0, "kelvinToC"}} // [-50..376] °C }; public: diff --git a/lib/obp60task/OBPcharts.cpp b/lib/obp60task/OBPcharts.cpp index 0b00cb7..3143273 100644 --- a/lib/obp60task/OBPcharts.cpp +++ b/lib/obp60task/OBPcharts.cpp @@ -25,6 +25,17 @@ Chart::Chart(RingBuffer& dataBuf, char chrtDir, int8_t chrtSz, double dflt fgColor = commonData->fgcolor; bgColor = commonData->bgcolor; + // we need "0" value for any user defined temperature format + tempFormat = commonData->config->getString(commonData->config->tempFormat); // [K|°C|°F] + if (tempFormat == "K") { + zeroValue = 0.0; + } else if (tempFormat == "C") { + zeroValue = 273.15; + } else if (tempFormat == "F") { + zeroValue = 255.37; + } + // LOG_DEBUG(GwLog::DEBUG, "Chart-init: fgColor: %d, bgColor: %d, tempFormat: %s, zeroValue: %.1f, &commonData: %p", fgColor, bgColor, tempFormat, zeroValue, commonData); + // LOG_DEBUG(GwLog::DEBUG, "Chart Init: Chart::dataBuf: %p, passed dataBuf: %p", (void*)&this->dataBuf, (void*)&dataBuf); dWidth = getdisplay().width(); dHeight = getdisplay().height(); @@ -59,12 +70,10 @@ Chart::Chart(RingBuffer& dataBuf, char chrtDir, int8_t chrtSz, double dflt cStart = { 0, top - 1 }; break; case 1: - // valAxis = dWidth / 2 - vGap - 1; valAxis = dWidth / 2 - vGap; cStart = { 0, top - 1 }; break; case 2: - // valAxis = dWidth / 2 - vGap - 1; valAxis = dWidth / 2 - vGap; cStart = { dWidth / 2 + vGap - 1, top - 1 }; break; @@ -94,19 +103,22 @@ Chart::Chart(RingBuffer& dataBuf, char chrtDir, int8_t chrtSz, double dflt } else { if (dbFormat == "formatDepth") { chrtDataFmt = 'D'; // Chart ist showing data of format + } else if (dbFormat == "kelvinToC") { + chrtDataFmt = 'T'; // Chart ist showing data of format } else { - chrtDataFmt = 'S'; // Chart is showing any other data format than + chrtDataFmt = 'S'; // Chart is showing any other data format } - rngStep = 5.0; // +/- 10 for all other values (eg. m/s, m, K, mBar) + rngStep = 10.0; // +/- 10 for all other values (eg. m/s, m, K, mBar) } - chrtMin = 0; - chrtMax = 0; + chrtMin = dbMIN_VAL; + chrtMax = dbMAX_VAL; chrtMid = dbMAX_VAL; chrtRng = dfltRng; - recalcRngCntr = true; // initialize on first screen call + recalcRngCntr = true; // initialize and chart borders on first screen call - LOG_DEBUG(GwLog::DEBUG, "Chart Init: dWidth: %d, dHeight: %d, timAxis: %d, valAxis: %d, cStart {x,y}: %d, %d, dbname: %s, rngStep: %.4f", dWidth, dHeight, timAxis, valAxis, cStart.x, cStart.y, dbName, rngStep); + LOG_DEBUG(GwLog::DEBUG, "Chart Init: dWidth: %d, dHeight: %d, timAxis: %d, valAxis: %d, cStart {x,y}: %d, %d, dbname: %s, rngStep: %.4f, chrtDataFmt: %c", + dWidth, dHeight, timAxis, valAxis, cStart.x, cStart.y, dbName, rngStep, chrtDataFmt); }; template @@ -117,7 +129,7 @@ Chart::~Chart() // Perform all actions to draw chart // Parameters: chart time interval, current boat data value to be printed, current boat data shall be shown yes/no template -void Chart::showChrt(int8_t chrtIntv, GwApi::BoatValue currValue, bool showCurrValue) +void Chart::showChrt(GwApi::BoatValue currValue, int8_t chrtIntv, bool showCurrValue) { drawChrt(chrtIntv, currValue); drawChrtTimeAxis(chrtIntv); @@ -126,11 +138,10 @@ void Chart::showChrt(int8_t chrtIntv, GwApi::BoatValue currValue, bool showCu if (bufDataValid) { if (showCurrValue) { // uses BoatValue temp variable to format latest buffer value - // doesn't work unfortunately when 'simulation data' is active, because OBP60Formatter generates own simulation value in that case + // doesn't work unfortunately when 'simulation data' is active, because OBP60Formatter generates own simulation values in that case currValue.value = dataBuf.getLast(); currValue.valid = currValue.value != dbMAX_VAL; Chart::prntCurrValue(currValue); - LOG_DEBUG(GwLog::DEBUG, "OBPcharts showChrt: currValue-value: %.1f, Valid: %d, Name: %s, Address: %p", currValue.value, currValue.valid, currValue.getName(), (void*)&currValue); } } else { // No valid data available -> print message @@ -157,11 +168,8 @@ void Chart::drawChrt(int8_t chrtIntv, GwApi::BoatValue& currValue) { double chrtVal; // Current data value double chrtScl; // Scale for data values in pixels per value - static double chrtPrevVal; // Last data value in chart area - static int numNoData; // Counter for multiple invalid data values in a row int x, y; // x and y coordinates for drawing - static int prevX, prevY; // Last x and y coordinates for drawing // Identify buffer size and buffer start position for chart count = dataBuf.getCurrentSize(); @@ -183,10 +191,12 @@ void Chart::drawChrt(int8_t chrtIntv, GwApi::BoatValue& currValue) } } - calcChrtBorders(chrtMid, chrtMin, chrtMax, chrtRng); - LOG_DEBUG(GwLog::DEBUG, "calcChrtBorders: min: %.3f, mid: %.3f, max: %.3f, rng: %.3f", chrtMin, chrtMid, chrtMax, chrtRng); + // LOG_DEBUG(GwLog::DEBUG, "PageOneValue:drawChart: min: %.1f, mid: %.1f, max: %.1f, rng: %.1f", chrtMin, chrtMid, chrtMax, chrtRng); + calcChrtBorders(chrtMin, chrtMid, chrtMax, chrtRng); + LOG_DEBUG(GwLog::DEBUG, "PageOneValue:drawChart2: min: %.1f, mid: %.1f, max: %.1f, rng: %.1f", chrtMin, chrtMid, chrtMax, chrtRng); - chrtScl = double(valAxis) / chrtRng; // Chart scale: pixels per value step + // Chart scale: pixels per value step + chrtScl = double(valAxis) / chrtRng; // Do we have valid buffer data? if (dataBuf.getMax() == dbMAX_VAL) { // only values in buffer -> no valid wind data available @@ -214,8 +224,7 @@ void Chart::drawChrt(int8_t chrtIntv, GwApi::BoatValue& currValue) if (chrtDir == 'H') { // horizontal chart x = cStart.x + i; // Position in chart area - if (chrtDataFmt == 'S') { // speed data format -> print low values at bottom - // y = cStart.y + static_cast(((chrtVal - chrtMin) * chrtScl) + 0.5); // calculate chart point and round + if (chrtDataFmt == 'S' or chrtDataFmt == 'T') { // speed data format -> print low values at bottom y = cStart.y + valAxis - static_cast(((chrtVal - chrtMin) * chrtScl) + 0.5); // calculate chart point and round } else if (chrtDataFmt == 'D') { y = cStart.y + static_cast(((chrtVal - chrtMin) * chrtScl) + 0.5); // calculate chart point and round @@ -226,7 +235,7 @@ void Chart::drawChrt(int8_t chrtIntv, GwApi::BoatValue& currValue) } else { // vertical chart y = cStart.y + timAxis - i; // Position in chart area - if (chrtDataFmt == 'S' || chrtDataFmt == 'D') { + if (chrtDataFmt == 'S' || chrtDataFmt == 'D' || chrtDataFmt == 'T') { x = cStart.x + static_cast(((chrtVal - chrtMin) * chrtScl) + 0.5); // calculate chart point and round } else { // degree type value x = cStart.x + static_cast((WindUtils::to2PI(chrtVal - chrtMin) * chrtScl) + 0.5); // calculate chart point and round @@ -234,7 +243,7 @@ void Chart::drawChrt(int8_t chrtIntv, GwApi::BoatValue& currValue) } // if (i >= (numBufVals / chrtIntv) - 5) // log chart data of 1 line (adjust for test purposes) - // LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Chart: i: %d, chrtVal: %.4f, {x,y} {%d,%d}", i, chrtVal, x, y); + // LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Chart: i: %d, chrtVal: %.2f, chrtMin: %.2f, {x,y} {%d,%d}", i, chrtVal, chrtMin, x, y); if ((i == 0) || (chrtPrevVal == dbMAX_VAL)) { // just a dot for 1st chart point or after some invalid values @@ -304,45 +313,9 @@ void Chart::drawChrt(int8_t chrtIntv, GwApi::BoatValue& currValue) } } -// Get maximum difference of last of dataBuf ringbuffer values to center chart -template -double Chart::getRng(double center, size_t amount) -{ - size_t count = dataBuf.getCurrentSize(); - - if (dataBuf.isEmpty() || amount <= 0) { - return dbMAX_VAL; - } - if (amount > count) - amount = count; - - double value = 0; - double range = 0; - double maxRng = dbMIN_VAL; - - // Start from the newest value (last) and go backwards x times - for (size_t i = 0; i < amount; i++) { - value = dataBuf.get(count - 1 - i); - - if (value == dbMAX_VAL) { - continue; // ignore invalid values - } - - range = abs(fmod((value - center + (M_TWOPI + M_PI)), M_TWOPI) - M_PI); - if (range > maxRng) - maxRng = range; - } - - if (maxRng > M_PI) { - maxRng = M_PI; - } - - return (maxRng != dbMIN_VAL ? maxRng : dbMAX_VAL); // Return range from to -} - // check and adjust chart range and set range borders and range middle template -void Chart::calcChrtBorders(double& rngMid, double& rngMin, double& rngMax, double& rng) +void Chart::calcChrtBorders(double& rngMin, double& rngMid, double& rngMax, double& rng) { if (chrtDataFmt == 'W' || chrtDataFmt == 'R') { // Chart data is of type 'course', 'wind' or 'rot' @@ -372,7 +345,7 @@ void Chart::calcChrtBorders(double& rngMid, double& rngMin, double& rngMax, d } } recalcRngCntr = false; // Reset flag for determination - LOG_DEBUG(GwLog::DEBUG, "calcChrtRange1b: rngMid: %.1f°, rngMin: %.1f°, rngMax: %.1f°, rng: %.1f°, rngStep: %.1f°", rngMid * RAD_TO_DEG, rngMin * RAD_TO_DEG, rngMax * RAD_TO_DEG, + LOG_DEBUG(GwLog::DEBUG, "calcChrtRange: rngMid: %.1f°, rngMin: %.1f°, rngMax: %.1f°, rng: %.1f°, rngStep: %.1f°", rngMid * RAD_TO_DEG, rngMin * RAD_TO_DEG, rngMax * RAD_TO_DEG, rng * RAD_TO_DEG, rngStep * RAD_TO_DEG); } @@ -383,10 +356,9 @@ void Chart::calcChrtBorders(double& rngMid, double& rngMin, double& rngMax, d // check and adjust range between left, center, and right chart limit double halfRng = rng / 2.0; // we calculate with range between and edges - double diffRng = getRng(rngMid, numBufVals); - // LOG_DEBUG(GwLog::DEBUG, "calcChrtRange2: diffRng: %.1f°, halfRng: %.1f°", diffRng * RAD_TO_DEG, halfRng * RAD_TO_DEG); + double diffRng = getAngleRng(rngMid, numBufVals); diffRng = (diffRng == dbMAX_VAL ? 0 : std::ceil(diffRng / rngStep) * rngStep); - // LOG_DEBUG(GwLog::DEBUG, "calcChrtRange2: diffRng: %.1f°, halfRng: %.1f°", diffRng * RAD_TO_DEG, halfRng * RAD_TO_DEG); + // LOG_DEBUG(GwLog::DEBUG, "calcChrtBorders: diffRng: %.1f°, halfRng: %.1f°", diffRng * RAD_TO_DEG, halfRng * RAD_TO_DEG); if (diffRng > halfRng) { halfRng = diffRng; // round to next value @@ -397,41 +369,47 @@ void Chart::calcChrtBorders(double& rngMid, double& rngMin, double& rngMax, d rngMin = WindUtils::to2PI(rngMid - halfRng); rngMax = (halfRng < M_PI ? rngMid + halfRng : rngMid + halfRng - (M_TWOPI / 360)); // if chart range is 360°, then make 1° smaller than rngMax = WindUtils::to2PI(rngMax); - // LOG_DEBUG(GwLog::DEBUG, "calcChrtRange2: diffRng: %.1f°, halfRng: %.1f°", diffRng * RAD_TO_DEG, halfRng * RAD_TO_DEG); rng = halfRng * 2.0; - // LOG_DEBUG(GwLog::DEBUG, "calcChrtRange2b: rngMid: %.1f°, rngMin: %.1f°, rngMax: %.1f°, diffRng: %.1f°, rng: %.1f°, rngStep: %.1f°", rngMid * RAD_TO_DEG, rngMin * RAD_TO_DEG, rngMax * RAD_TO_DEG, - // diffRng * RAD_TO_DEG, rng * RAD_TO_DEG, rngStep * RAD_TO_DEG); + LOG_DEBUG(GwLog::DEBUG, "calcChrtBorders: rngMid: %.1f°, rngMin: %.1f°, rngMax: %.1f°, diffRng: %.1f°, rng: %.1f°, rngStep: %.1f°", rngMid * RAD_TO_DEG, rngMin * RAD_TO_DEG, rngMax * RAD_TO_DEG, + diffRng * RAD_TO_DEG, rng * RAD_TO_DEG, rngStep * RAD_TO_DEG); + + } else { // chart data is of any other type - } else { double oldRngMin = rngMin; double oldRngMax = rngMax; - // Chart starts at lowest range value, but at least '0' or includes even negative values + // calculate low end range value double currMinVal = dataBuf.getMin(numBufVals); - // LOG_DEBUG(GwLog::DEBUG, "calcChrtRange0a: currMinVal: %.1f, currMaxVal: %.1f, rngMin: %.1f, rngMid: %.1f, rngMax: %.1f, rng: %.1f, rngStep: %.1f, oldRngMin: %.1f, oldRngMax: %.1f, dfltRng: %.1f, numBufVals: %d", - // currMinVal, dataBuf.getMax(numBufVals), rngMin, rngMid, rngMax, rng, rngStep, oldRngMin, oldRngMax, dfltRng, numBufVals); + LOG_DEBUG(GwLog::DEBUG, "calcChrtBorders: currMinVal: %.1f, currMaxVal: %.1f, rngMin: %.1f, rngMid: %.1f, rngMax: %.1f, rng: %.1f, rngStep: %.1f, zeroValue: %.1f, oldRngMin: %.1f, oldRngMax: %.1f, dfltRng: %.1f, dbMIN_VAL: %.1f", + currMinVal, dataBuf.getMax(numBufVals), rngMin, rngMid, rngMax, rng, rngStep, zeroValue, oldRngMin, oldRngMax, dfltRng, dbMIN_VAL); if (currMinVal != dbMAX_VAL) { // current min value is valid - if (currMinVal > 0 && dbMIN_VAL == 0) { // Chart range starts at least at '0' or includes negative values - rngMin = 0; - } else if (currMinVal < oldRngMin || (oldRngMin < 0 && (currMinVal > (oldRngMin + rngStep)))) { // decrease rngMin if required or increase if lowest value is higher than old rngMin - rngMin = std::floor(currMinVal / rngStep) * rngStep; + + if (currMinVal < oldRngMin || (currMinVal > (oldRngMin + rngStep))) { // recalculate rngMin if required or increase if lowest value is higher than old rngMin + // rngMin = std::floor(currMinVal / rngStep) * rngStep; // align low range to lowest buffer value and nearest range interval + rngMin = currMinVal; + LOG_DEBUG(GwLog::DEBUG, "calcChrtBorders2: currMinVal: %.1f, rngMin: %.1f, oldRngMin: %.1f, zeroValue: %.1f", currMinVal, rngMin, oldRngMin, zeroValue); + } + if (rngMin > zeroValue && dbMIN_VAL <= zeroValue) { // Chart range starts at least at '0' if minimum data value allows it + rngMin = zeroValue; + LOG_DEBUG(GwLog::DEBUG, "calcChrtBorders3: currMinVal: %.1f, rngMin: %.1f, oldRngMin: %.1f, zeroValue: %.1f", currMinVal, rngMin, oldRngMin, zeroValue); } } // otherwise keep rngMin unchanged double currMaxVal = dataBuf.getMax(numBufVals); if (currMaxVal != dbMAX_VAL) { // current max value is valid if ((currMaxVal > oldRngMax) || (currMaxVal < (oldRngMax - rngStep))) { // increase rngMax if required or decrease if lowest value is lower than old rngMax - rngMax = std::ceil(currMaxVal / rngStep) * rngStep; + // rngMax = std::ceil(currMaxVal / rngStep) * rngStep; + rngMax = currMaxVal; rngMax = std::max(rngMax, rngMin + dfltRng); // keep at least default chart range } } // otherwise keep rngMax unchanged rngMid = (rngMin + rngMax) / 2.0; rng = rngMax - rngMin; - // LOG_DEBUG(GwLog::DEBUG, "calcChrtRange1a: currMinVal: %.1f, currMaxVal: %.1f, rngMin: %.1f, rngMid: %.1f, rngMax: %.1f, rng: %.1f, rngStep: %.1f, oldRngMin: %.1f, oldRngMax: %.1f, dfltRng: %.1f, numBufVals: %d", - // currMinVal, currMaxVal, rngMin, rngMid, rngMax, rng, rngStep, oldRngMin, oldRngMax, dfltRng, numBufVals); + // LOG_DEBUG(GwLog::DEBUG, "calcChrtRange-end: currMinVal: %.1f, currMaxVal: %.1f, rngMin: %.1f, rngMid: %.1f, rngMax: %.1f, rng: %.1f, rngStep: %.1f, oldRngMin: %.1f, oldRngMax: %.1f, dfltRng: %.1f, numBufVals: %d", + // currMinVal, currMaxVal, rngMin, rngMid, rngMax, rng, rngStep, oldRngMin, oldRngMax, dfltRng, numBufVals); } } @@ -492,30 +470,39 @@ void Chart::drawChrtValAxis() { double slots; int i, intv; - double cVal, cChrtRng, crngMin; + double cVal, cChrtRng; char sVal[6]; int sLen; - std::unique_ptr tmpBVal; // Temp variable to get formatted and converted data value from OBP60Formatter - tmpBVal = std::unique_ptr(new GwApi::BoatValue(dataBuf.getName())); - tmpBVal->setFormat(dataBuf.getFormat()); - tmpBVal->valid = true; if (chrtDir == 'H') { - slots = valAxis / 60.0; // number of axis labels - tmpBVal->value = chrtRng; - cChrtRng = formatValue(tmpBVal.get(), *commonData).cvalue; // value (converted) - if (useSimuData) { - // cannot use in this case, because that would change the range value to some random data - cChrtRng = tmpBVal->value; // take SI value in this case -> need to be improved - } - intv = static_cast(round(cChrtRng / slots)); - i = intv; - if (chrtSz == 0) { // full size chart -> print multiple value lines + // adjust value range to user defined data format + if (chrtDataFmt == 'T') { + if (tempFormat == "F") { + cChrtRng = chrtRng * (9 / 5); + } else { + // data steps for Kelvin and Celsius are identical and '1' + cChrtRng = chrtRng; + } + } else { + // any other data format can be converted with standard rules + cChrtRng = convertValue(chrtRng, dataBuf.getFormat(), *commonData); + } + if (useSimuData) { + // cannot use in this case, because that would change the range value to some random data + cChrtRng = chrtRng; // take SI value in this case -> need to be improved + } + + slots = valAxis / 60.0; // number of axis labels + intv = static_cast(round(cChrtRng / slots)); + i = static_cast(convertValue(chrtMin, dataBuf.getFormat(), *commonData) + intv + 0.5); // convert and round lower chart value end + LOG_DEBUG(GwLog::DEBUG, "Chart::drawChrtValAxis: chrtRng: %.2f, cChrtRng: %.2f, slots: %.2f, intv: %d, chrtMin: %.2f, chrtMid: %.2f, chrtMax: %.2f", chrtRng, cChrtRng, slots, intv, chrtMin, chrtMid, chrtMax); + + if (chrtSz == 0 && chrtDataFmt != 'W') { // full size chart -> print multiple value lines getdisplay().setFont(&Ubuntu_Bold12pt8b); int loopStrt, loopEnd, loopStp; - if (chrtDataFmt == 'S') { + if (chrtDataFmt == 'S' || chrtDataFmt == 'T') { loopStrt = valAxis - 60; loopEnd = 30; loopStp = -60; @@ -535,23 +522,27 @@ void Chart::drawChrtValAxis() i += intv; } - } else { // half size chart -> print just edge values + middle chart line + + } else { // half size chart or degree values -> print just edge values + middle chart line + LOG_DEBUG(GwLog::DEBUG, "Chart::drawChrtValAxis: chrtDataFmt: %c, chrtMin: %.2f, chrtMid: %.2f, chrtMax: %.2f", chrtDataFmt, chrtMin, chrtMid, chrtMax); getdisplay().setFont(&Ubuntu_Bold10pt8b); - tmpBVal->value = (chrtDataFmt == 'D') ? chrtMin : chrtMax; - cVal = formatValue(tmpBVal.get(), *commonData).cvalue; // value (converted) + // cVal = (chrtDataFmt == 'D') ? chrtMin : chrtMax; + cVal = (chrtDataFmt == 'S' || chrtDataFmt == 'T') ? chrtMax : chrtMin; + cVal = convertValue(cVal, dataBuf.getFormat(), *commonData); // value (converted) if (useSimuData) { // dirty fix for problem that OBP60Formatter can only be used without data simulation -> returns random values in simulation mode - cVal = tmpBVal->value; // no value conversion here + // cVal = (chrtDataFmt == 'D') ? chrtMin : chrtMax; // no value conversion + cVal = (chrtDataFmt == 'S' || chrtDataFmt == 'T') ? chrtMax : chrtMin; // no value conversion } sLen = snprintf(sVal, sizeof(sVal), "%.0f", round(cVal)); getdisplay().fillRect(cStart.x, cStart.y + 2, 42, 16, bgColor); // Clear small area to remove potential chart lines getdisplay().setCursor(cStart.x + ((3 - sLen) * 10), cStart.y + 16); getdisplay().printf("%s", sVal); // Range low end - tmpBVal->value = chrtMid; - cVal = formatValue(tmpBVal.get(), *commonData).cvalue; // value (converted) + cVal = chrtMid; + cVal = convertValue(cVal, dataBuf.getFormat(), *commonData); // value (converted) if (useSimuData) { // dirty fix for problem that OBP60Formatter can only be used without data simulation -> returns random values in simulation mode - cVal = tmpBVal->value; // no value conversion here + cVal = chrtMid; // no value conversion } sLen = snprintf(sVal, sizeof(sVal), "%.0f", round(cVal)); getdisplay().fillRect(cStart.x, cStart.y + (valAxis / 2) - 9, 42, 16, bgColor); // Clear small area to remove potential chart lines @@ -559,10 +550,12 @@ void Chart::drawChrtValAxis() getdisplay().printf("%s", sVal); // Range mid value getdisplay().drawLine(cStart.x + 43, cStart.y + (valAxis / 2), cStart.x + timAxis, cStart.y + (valAxis / 2), fgColor); - tmpBVal->value = (chrtDataFmt == 'D') ? chrtMax : chrtMin; - cVal = formatValue(tmpBVal.get(), *commonData).cvalue; // value (converted) + // cVal = (chrtDataFmt == 'D') ? chrtMax : chrtMin; + cVal = (chrtDataFmt == 'S' || chrtDataFmt == 'T') ? chrtMin : chrtMax; + cVal = convertValue(cVal, dataBuf.getFormat(), *commonData); // value (converted) if (useSimuData) { // dirty fix for problem that OBP60Formatter can only be used without data simulation -> returns random values in simulation mode - cVal = tmpBVal->value; // no value conversion here + // cVal = (chrtDataFmt == 'D') ? chrtMax : chrtMin; // no value conversion + cVal = (chrtDataFmt == 'S' || chrtDataFmt == 'T') ? chrtMax : chrtMin; // no value conversion } sLen = snprintf(sVal, sizeof(sVal), "%.0f", round(cVal)); getdisplay().fillRect(cStart.x, cStart.y + valAxis - 16, 42, 16, bgColor); // Clear small area to remove potential chart lines @@ -572,42 +565,43 @@ void Chart::drawChrtValAxis() } getdisplay().setFont(&Ubuntu_Bold12pt8b); - drawTextRalign(cStart.x + timAxis, cStart.y - 3, dbName); // buffer data name + drawTextRalign(cStart.x + timAxis, cStart.y - 3, dbName.substring(0, 4)); // buffer data name (max. size 4 characters) } else { // vertical chart if (chrtSz == 0) { // full size chart -> use larger font getdisplay().setFont(&Ubuntu_Bold12pt8b); - drawTextCenter(cStart.x + (valAxis / 4) + 25, cStart.y - 10, dbName); // buffer data name + drawTextRalign(cStart.x + (valAxis * 0.42), cStart.y - 2, dbName.substring(0, 6)); // buffer data name (max. size 5 characters) } else { getdisplay().setFont(&Ubuntu_Bold10pt8b); } getdisplay().fillRect(cStart.x, cStart.y, valAxis, 2, fgColor); // top chart line - tmpBVal->value = chrtMin; - cVal = formatValue(tmpBVal.get(), *commonData).cvalue; // value (converted) + cVal = chrtMin; + cVal = convertValue(cVal, dataBuf.getFormat(), *commonData); if (useSimuData) { // dirty fix for problem that OBP60Formatter can only be used without data simulation -> returns random values in simulation mode - cVal = tmpBVal->value; // no value conversion here + cVal = chrtMin; // no value conversion } snprintf(sVal, sizeof(sVal), "%.0f", round(cVal)); getdisplay().setCursor(cStart.x, cStart.y - 2); getdisplay().printf("%s", sVal); // Range low end - tmpBVal->value = chrtMid; - cVal = formatValue(tmpBVal.get(), *commonData).cvalue; // value (converted) + cVal = chrtMid; + cVal = convertValue(cVal, dataBuf.getFormat(), *commonData); if (useSimuData) { // dirty fix for problem that OBP60Formatter can only be used without data simulation -> returns random values in simulation mode - cVal = tmpBVal->value; // no value conversion here + cVal = chrtMid; // no value conversion } snprintf(sVal, sizeof(sVal), "%.0f", round(cVal)); - drawTextCenter(cStart.x + (valAxis / 2), cStart.y - 10, sVal); // Range mid end + drawTextCenter(cStart.x + (valAxis / 2), cStart.y - 9, sVal); // Range mid end - tmpBVal->value = chrtMax; - cVal = formatValue(tmpBVal.get(), *commonData).cvalue; // value (converted) + cVal = chrtMax; + cVal = convertValue(cVal, dataBuf.getFormat(), *commonData); if (useSimuData) { // dirty fix for problem that OBP60Formatter can only be used without data simulation -> returns random values in simulation mode - cVal = tmpBVal->value; // no value conversion here + cVal = chrtMax; // no value conversion } snprintf(sVal, sizeof(sVal), "%.0f", round(cVal)); drawTextRalign(cStart.x + valAxis - 2, cStart.y - 2, sVal); // Range high end + // draw vertical grid lines for each axis label for (int j = 0; j <= valAxis; j += (valAxis / 2)) { getdisplay().drawLine(cStart.x + j, cStart.y, cStart.x + j, cStart.y + timAxis, fgColor); } @@ -623,25 +617,61 @@ void Chart::prntCurrValue(GwApi::BoatValue& currValue) FormattedData frmtDbData = formatValue(&currValue, *commonData); String sdbValue = frmtDbData.svalue; // value as formatted string - String dbUnit = frmtDbData.unit; // Unit of value + String dbUnit = frmtDbData.unit; // Unit of value; limit length to 3 characters // LOG_DEBUG(GwLog::DEBUG, "Chart CurrValue: dbValue: %.2f, sdbValue: %s, dbFormat: %s, dbUnit: %s, Valid: %d, Name: %s, Address: %p", currValue.value, sdbValue, - // currValue.getFormat(), dbUnit, currValue.valid, currValue.getName(), currValue); + // currValue.getFormat(), dbUnit, currValue.valid, currValue.getName(), currValue); getdisplay().fillRect(xPosVal - 1, yPosVal - 35, 128, 41, bgColor); // Clear area for TWS value getdisplay().drawRect(xPosVal, yPosVal - 34, 126, 40, fgColor); // Draw box for TWS value getdisplay().setFont(&DSEG7Classic_BoldItalic16pt7b); getdisplay().setCursor(xPosVal + 1, yPosVal); - getdisplay().print(sdbValue); // alue + getdisplay().print(sdbValue); // value getdisplay().setFont(&Ubuntu_Bold10pt8b); getdisplay().setCursor(xPosVal + 76, yPosVal - 17); - getdisplay().print(dbName); // Name + getdisplay().print(dbName.substring(0, 3)); // Name, limited to 3 characters getdisplay().setFont(&Ubuntu_Bold8pt8b); getdisplay().setCursor(xPosVal + 76, yPosVal + 0); getdisplay().print(dbUnit); // Unit } +// Get maximum difference of last of dataBuf ringbuffer values to center chart; for angle data only +template +double Chart::getAngleRng(double center, size_t amount) +{ + size_t count = dataBuf.getCurrentSize(); + + if (dataBuf.isEmpty() || amount <= 0) { + return dbMAX_VAL; + } + if (amount > count) + amount = count; + + double value = 0; + double range = 0; + double maxRng = dbMIN_VAL; + + // Start from the newest value (last) and go backwards x times + for (size_t i = 0; i < amount; i++) { + value = dataBuf.get(count - 1 - i); + + if (value == dbMAX_VAL) { + continue; // ignore invalid values + } + + range = abs(fmod((value - center + (M_TWOPI + M_PI)), M_TWOPI) - M_PI); + if (range > maxRng) + maxRng = range; + } + + if (maxRng > M_PI) { + maxRng = M_PI; + } + + return (maxRng != dbMIN_VAL ? maxRng : dbMAX_VAL); // Return range from to +} + // Explicitly instantiate class with required data types to avoid linker errors template class Chart; // --- Class Chart --------------- diff --git a/lib/obp60task/OBPcharts.h b/lib/obp60task/OBPcharts.h index 7740f91..9ce3017 100644 --- a/lib/obp60task/OBPcharts.h +++ b/lib/obp60task/OBPcharts.h @@ -22,6 +22,8 @@ protected: uint16_t fgColor; // color code for any screen writing uint16_t bgColor; // color code for screen background bool useSimuData; // flag to indicate if simulation data is active + String tempFormat; // user defined format for temperature + double zeroValue; // "0" SI value for temperature int top = 44; // chart gap at top of display (25 lines for standard gap + 19 lines for axis labels) int bottom = 25; // chart gap at bottom of display to keep space for status line @@ -50,30 +52,35 @@ protected: size_t currIdx; // Current index in TWD history buffer size_t lastIdx; // Last index of TWD history buffer size_t lastAddedIdx = 0; // Last index of TWD history buffer when new data was added + int numNoData; // Counter for multiple invalid data values in a row bool bufDataValid = false; // Flag to indicate if buffer data is valid int oldChrtIntv = 0; // remember recent user selection of data interval + double chrtPrevVal; // Last data value in chart area + int x, y; // x and y coordinates for drawing + int prevX, prevY; // Last x and y coordinates for drawing + void drawChrt(int8_t chrtIntv, GwApi::BoatValue& currValue); // Draw chart line - double getRng(double center, size_t amount); // Calculate range between chart center and edges - void calcChrtBorders(double& rngMid, double& rngMin, double& rngMax, double& rng); // Calculate chart points for value axis and return range between and + void calcChrtBorders(double& rngMin, double& rngMid, double& rngMax, double& rng); // Calculate chart points for value axis and return range between and void drawChrtTimeAxis(int8_t chrtIntv); // Draw time axis of chart, value and lines void drawChrtValAxis(); // Draw value axis of chart, value and lines void prntCurrValue(GwApi::BoatValue& currValue); // Add current boat data value to chart + double getAngleRng(double center, size_t amount); // Calculate range between chart center and edges public: // Define default chart range for each boat data type - static std::map dfltChartRng; + static std::map dfltChrtRng; Chart(RingBuffer& dataBuf, char chrtDir, int8_t chrtSz, double dfltRng, CommonData& common, bool useSimuData); // Chart object of data chart ~Chart(); - void showChrt(int8_t chrtIntv, GwApi::BoatValue currValue, bool showCurrValue); // Perform all actions to draw chart + void showChrt(GwApi::BoatValue currValue, int8_t chrtIntv, bool showCurrValue); // Perform all actions to draw chart }; template -std::map Chart::dfltChartRng = { +std::map Chart::dfltChrtRng = { { "formatWind", 60.0 * DEG_TO_RAD }, // default course range 60 degrees { "formatCourse", 60.0 * DEG_TO_RAD }, // default course range 60 degrees { "formatKnots", 5.1 }, // default speed range in m/s - { "formatDepth", 15 }, // default depth range in m - { "kelvinToC", 30 } // default temp range in °C/K + { "formatDepth", 15.0 }, // default depth range in m + { "kelvinToC", 30.0 } // default temp range in °C/K }; \ No newline at end of file diff --git a/lib/obp60task/PageOneValue.cpp b/lib/obp60task/PageOneValue.cpp index 8f1cc19..a9ce6ff 100644 --- a/lib/obp60task/PageOneValue.cpp +++ b/lib/obp60task/PageOneValue.cpp @@ -18,11 +18,12 @@ private: int dataIntv = 1; // Update interval for wind history chart: // (1)|(2)|(3)|(4)|(8) x 240 seconds for 4, 8, 12, 16, 32 min. history chart - String lengthformat; + //String lengthformat; bool useSimuData; bool holdValues; String flashLED; String backlightMode; + String tempFormat; // Old values for hold function String sValue1Old = ""; @@ -51,14 +52,14 @@ private: valueFnt3 = &DSEG7Classic_BoldItalic60pt7b; } else { // half size data and chart display nameXoff = 105; - nameYoff = -40; + nameYoff = -35; nameFnt = &Ubuntu_Bold20pt8b; - unitXoff = -33; - unitYoff = -40; + unitXoff = -35; + unitYoff = -102; unitFnt = &Ubuntu_Bold12pt8b; valueFnt1 = &Ubuntu_Bold12pt8b; value1Xoff = 105; - value1Yoff = -105; + value1Yoff = -102; valueFnt2 = &Ubuntu_Bold20pt8b; valueFnt3 = &DSEG7Classic_BoldItalic30pt7b; } @@ -79,11 +80,12 @@ private: // Show unit getdisplay().setFont(unitFnt); - getdisplay().setCursor(270 + unitXoff, 100 + unitYoff); + getdisplay().setCursor(305 + unitXoff, 240 + unitYoff); + if (holdValues) { - drawTextRalign(298 + unitXoff, 100 + unitYoff, unit1Old); + getdisplay().print(unit1Old); // name } else { - drawTextRalign(298 + unitXoff, 100 + unitYoff, unit1); // Unit + getdisplay().print(unit1); // name } // Switch font depending on value format and adjust position @@ -122,17 +124,23 @@ public: height = getdisplay().height(); // Screen height // Get config data - lengthformat = common.config->getString(common.config->lengthFormat); - useSimuData = common.config->getBool(common.config->useSimuData); - holdValues = common.config->getBool(common.config->holdvalues); - flashLED = common.config->getString(common.config->flashLED); - backlightMode = common.config->getString(common.config->backlight); + //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] } virtual void setupKeys() { Page::setupKeys(); - commonData->keydata[0].label = "MODE"; + + if (dataHstryBuf) { // show "Mode" key only if chart supported boat data type is available + commonData->keydata[0].label = "MODE"; + } else { + commonData->keydata[0].label = ""; + } #if defined BOARD_OBP60S3 commonData->keydata[4].label = "ZOOM"; #elif defined BOARD_OBP40S3 @@ -192,8 +200,8 @@ public: setFlashLED(false); } #endif - // buffer initialization cannot be performed here, because is not executed at system start for default page - /* if (!dataFlChart) { // Create chart objects if they don't exist + // buffer initialization will fail, if page is default page, because is not executed at system start for default page + if (!dataFlChart) { // Create chart objects if they don't exist GwApi::BoatValue* bValue1 = pageData.values[0]; // Page boat data element String bValName1 = bValue1->getName(); // Value name String bValFormat = bValue1->getFormat(); // Value format @@ -201,21 +209,23 @@ public: dataHstryBuf = pageData.hstryBuffers->getBuffer(bValName1); if (dataHstryBuf) { - dataFlChart.reset(new Chart(*dataHstryBuf, 'H', 0, Chart::dfltChartRng[bValFormat], *commonData, useSimuData)); - dataHfChart.reset(new Chart(*dataHstryBuf, 'H', 2, Chart::dfltChartRng[bValFormat], *commonData, useSimuData)); + dataFlChart.reset(new Chart(*dataHstryBuf, 'H', 0, Chart::dfltChrtRng[bValFormat], *commonData, useSimuData)); + dataHfChart.reset(new Chart(*dataHstryBuf, 'H', 2, Chart::dfltChrtRng[bValFormat], *commonData, useSimuData)); LOG_DEBUG(GwLog::DEBUG, "PageOneValue: Created chart objects for %s", bValName1); } else { LOG_DEBUG(GwLog::DEBUG, "PageOneValue: No chart objects available for %s", bValName1); } - } */ + } + + setupKeys(); // adjust key depending on chart supported boat data type } int displayPage(PageData& pageData) { LOG_DEBUG(GwLog::LOG, "Display PageOneValue"); - GwConfigHandler* config = commonData->config; - GwLog* logger = commonData->logger; + //GwConfigHandler* config = commonData->config; + //GwLog* logger = commonData->logger; // Get boat value for page GwApi::BoatValue* bValue1 = pageData.values[0]; // Page boat data element @@ -226,7 +236,7 @@ public: setFlashLED(false); } - if (!dataFlChart) { // Create chart objects if they don't exist +/* if (!dataFlChart) { // Create chart objects if they don't exist GwApi::BoatValue* bValue1 = pageData.values[0]; // Page boat data element String bValName1 = bValue1->getName(); // Value name String bValFormat = bValue1->getFormat(); // Value format @@ -234,37 +244,37 @@ public: dataHstryBuf = pageData.hstryBuffers->getBuffer(bValName1); if (dataHstryBuf) { - dataFlChart.reset(new Chart(*dataHstryBuf, 'H', 0, Chart::dfltChartRng[bValFormat], *commonData, useSimuData)); - dataHfChart.reset(new Chart(*dataHstryBuf, 'H', 2, Chart::dfltChartRng[bValFormat], *commonData, useSimuData)); + dataFlChart.reset(new Chart(*dataHstryBuf, 'H', 0, Chart::dfltChrtRng[bValFormat], *commonData, useSimuData)); + dataHfChart.reset(new Chart(*dataHstryBuf, 'H', 2, Chart::dfltChrtRng[bValFormat], *commonData, useSimuData)); LOG_DEBUG(GwLog::DEBUG, "PageOneValue: Created chart objects for %s", bValName1); } else { LOG_DEBUG(GwLog::DEBUG, "PageOneValue: No chart objects available for %s", bValName1); } - } + } */ - // Logging boat values if (bValue1 == NULL) - return PAGE_OK; // WTF why this statement? + return PAGE_OK; // no data, no display of page - LOG_DEBUG(GwLog::DEBUG, "Drawing at PageOneValue, %s, %.3f", bValue1->getName().c_str(), bValue1->value); + LOG_DEBUG(GwLog::DEBUG, "PageOneValue: printing %s, %.3f", bValue1->getName().c_str(), bValue1->value); // Draw page //*********************************************************** getdisplay().setPartialWindow(0, 0, width, height); // Set partial update - if (pageMode == 'V') { // show only data value + if (pageMode == 'V' || dataHstryBuf == nullptr) { + // show only data value; ignore other pageMode options if no chart supported boat data history buffer is available showData(bValue1, 'F'); } else if (pageMode == 'C') { // show only data chart if (dataFlChart) { - dataFlChart->showChrt(dataIntv, *bValue1, true); + dataFlChart->showChrt(*bValue1, dataIntv, true); } } else if (pageMode == 'B') { // show data value and chart showData(bValue1, 'H'); if (dataHfChart) { - dataHfChart->showChrt(dataIntv, *bValue1, false); + dataHfChart->showChrt(*bValue1, dataIntv, false); } } diff --git a/lib/obp60task/PageWindPlot.cpp b/lib/obp60task/PageWindPlot.cpp index 088be08..50da88f 100644 --- a/lib/obp60task/PageWindPlot.cpp +++ b/lib/obp60task/PageWindPlot.cpp @@ -22,7 +22,7 @@ private: int dataIntv = 1; // Update interval for wind history chart: // (1)|(2)|(3)|(4)|(8) x 240 seconds for 4, 8, 12, 16, 32 min. history chart bool useSimuData; - //bool holdValues; + // bool holdValues; String flashLED; String backlightMode; @@ -65,7 +65,7 @@ public: // Get config data useSimuData = common.config->getBool(common.config->useSimuData); - //holdValues = common.config->getBool(common.config->holdvalues); + // holdValues = common.config->getBool(common.config->holdvalues); flashLED = common.config->getString(common.config->flashLED); backlightMode = common.config->getString(common.config->backlight); @@ -143,6 +143,7 @@ public: } #endif #ifdef BOARD_OBP40S3 + // we can only initialize user defined wind source here, because "pageData" is not available at object instantiation wndSrc = commonData->config->getString("page" + String(pageData.pageNumber) + "wndsrc"); if (wndSrc == "True wind") { showTruW = true; @@ -151,8 +152,8 @@ public: } oldShowTruW = !showTruW; // Force chart update in displayPage #endif - // buffer initialization cannot be performed here, because is not executed at system start for default page + // buffer initialization cannot be performed here, because is not executed at system start for default page /* if (!twdFlChart) { // Create true wind charts if they don't exist twdHstry = pageData.hstryBuffers->getBuffer("TWD"); twsHstry = pageData.hstryBuffers->getBuffer("TWS"); @@ -257,20 +258,20 @@ public: if (chrtMode == 'D') { if (wdFlChart) { - wdFlChart->showChrt(dataIntv, *wdBVal, true); + wdFlChart->showChrt(*wdBVal, dataIntv, true); } } else if (chrtMode == 'S') { if (wsFlChart) { - wsFlChart->showChrt(dataIntv, *wsBVal, true); + wsFlChart->showChrt(*wsBVal, dataIntv, true); } } else if (chrtMode == 'B') { if (wdHfChart) { - wdHfChart->showChrt(dataIntv, *wdBVal, true); + wdHfChart->showChrt(*wdBVal, dataIntv, true); } if (wsHfChart) { - wsHfChart->showChrt(dataIntv, *wsBVal, true); + wsHfChart->showChrt(*wsBVal, dataIntv, true); } } diff --git a/lib/obp60task/Pagedata.h b/lib/obp60task/Pagedata.h index 103082f..d6f342e 100644 --- a/lib/obp60task/Pagedata.h +++ b/lib/obp60task/Pagedata.h @@ -204,3 +204,6 @@ typedef struct{ // Formatter for boat values FormattedData formatValue(GwApi::BoatValue *value, 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);