Convert invalid marker of ringbuffer to MAX_VAL -> required for unsigned types

This commit is contained in:
Ulrich Meine 2025-08-23 13:43:02 +02:00
parent c6c2ad537a
commit 851149bae6
5 changed files with 67 additions and 67 deletions

View File

@ -16,7 +16,7 @@ void HstryBuf::init(BoatValueList* boatValues, GwLog *log) {
twsHstryMin = hstryMinVal; twsHstryMin = hstryMinVal;
awdHstryMin = hstryMinVal; awdHstryMin = hstryMinVal;
awsHstryMin = hstryMinVal; awsHstryMin = hstryMinVal;
const double DBL_MIN = std::numeric_limits<double>::lowest(); const double DBL_MAX = std::numeric_limits<double>::max();
// Initialize history buffers with meta data // Initialize history buffers with meta data
hstryBufList.twdHstry->setMetaData("TWD", "formatCourse", hstryUpdFreq, hstryMinVal, twdHstryMax); hstryBufList.twdHstry->setMetaData("TWD", "formatCourse", hstryUpdFreq, hstryMinVal, twdHstryMax);
@ -33,7 +33,7 @@ void HstryBuf::init(BoatValueList* boatValues, GwLog *log) {
if (!awdBVal->valid) { // AWD usually does not exist if (!awdBVal->valid) { // AWD usually does not exist
awdBVal->setFormat(hstryBufList.awdHstry->getFormat()); awdBVal->setFormat(hstryBufList.awdHstry->getFormat());
awdBVal->value = DBL_MIN; awdBVal->value = DBL_MAX;
} }
// collect boat values for true wind calculation // collect boat values for true wind calculation
@ -221,15 +221,14 @@ double WindUtils::calcHDT(const double* hdmVal, const double* varVal, const doub
{ {
double hdt; double hdt;
double minSogVal = 0.1; // SOG below this value (m/s) is assumed to be data noise from GPS sensor double minSogVal = 0.1; // SOG below this value (m/s) is assumed to be data noise from GPS sensor
static const double DBL_MIN = std::numeric_limits<double>::lowest();
if (*hdmVal != DBL_MIN) { if (*hdmVal != DBL_MAX) {
hdt = *hdmVal + (*varVal != DBL_MIN ? *varVal : 0.0); // Use corrected HDM if HDT is not available (or just HDM if VAR is not available) hdt = *hdmVal + (*varVal != DBL_MAX ? *varVal : 0.0); // Use corrected HDM if HDT is not available (or just HDM if VAR is not available)
hdt = to2PI(hdt); hdt = to2PI(hdt);
} else if (*cogVal != DBL_MIN && *sogVal >= minSogVal) { } else if (*cogVal != DBL_MAX && *sogVal >= minSogVal) {
hdt = *cogVal; // Use COG as fallback if HDT and HDM are not available, and SOG is not data noise hdt = *cogVal; // Use COG as fallback if HDT and HDM are not available, and SOG is not data noise
} else { } else {
hdt = DBL_MIN; // Cannot calculate HDT without valid HDM or HDM+VAR or COG hdt = DBL_MAX; // Cannot calculate HDT without valid HDM or HDM+VAR or COG
} }
return hdt; return hdt;
@ -242,24 +241,23 @@ bool WindUtils::calcTrueWind(const double* awaVal, const double* awsVal,
double stw, hdt, ctw; double stw, hdt, ctw;
double twd, tws, twa; double twd, tws, twa;
double minSogVal = 0.1; // SOG below this value (m/s) is assumed to be data noise from GPS sensor double minSogVal = 0.1; // SOG below this value (m/s) is assumed to be data noise from GPS sensor
static const double DBL_MIN = std::numeric_limits<double>::lowest();
if (*hdtVal != DBL_MIN) { if (*hdtVal != DBL_MAX) {
hdt = *hdtVal; // Use HDT if available hdt = *hdtVal; // Use HDT if available
} else { } else {
hdt = calcHDT(hdmVal, varVal, cogVal, sogVal); hdt = calcHDT(hdmVal, varVal, cogVal, sogVal);
} }
if (*cogVal != DBL_MIN && *sogVal >= minSogVal) { // if SOG is data noise, we don't trust COG if (*cogVal != DBL_MAX && *sogVal >= minSogVal) { // if SOG is data noise, we don't trust COG
ctw = *cogVal; // Use COG for CTW if available ctw = *cogVal; // Use COG for CTW if available
} else { } else {
ctw = hdt; // 2nd approximation for CTW; hdt must exist if we reach this part of the code ctw = hdt; // 2nd approximation for CTW; hdt must exist if we reach this part of the code
} }
if (*stwVal != DBL_MIN) { if (*stwVal != DBL_MAX) {
stw = *stwVal; // Use STW if available stw = *stwVal; // Use STW if available
} else if (*sogVal != DBL_MIN) { } else if (*sogVal != DBL_MAX) {
stw = *sogVal; stw = *sogVal;
} else { } else {
// If STW and SOG are not available, we cannot calculate true wind // If STW and SOG are not available, we cannot calculate true wind
@ -267,7 +265,7 @@ bool WindUtils::calcTrueWind(const double* awaVal, const double* awsVal,
} }
// Serial.println("\ncalcTrueWind: HDT: " + String(hdt) + ", CTW: " + String(ctw) + ", STW: " + String(stw)); // Serial.println("\ncalcTrueWind: HDT: " + String(hdt) + ", CTW: " + String(ctw) + ", STW: " + String(stw));
if ((*awaVal == DBL_MIN) || (*awsVal == DBL_MIN)) { if ((*awaVal == DBL_MAX) || (*awsVal == DBL_MAX)) {
// Cannot calculate true wind without valid AWA, AWS; other checks are done earlier // Cannot calculate true wind without valid AWA, AWS; other checks are done earlier
return false; return false;
} else { } else {
@ -288,16 +286,15 @@ bool WindUtils::addTrueWind(GwApi* api, BoatValueList* boatValues, GwLog* log) {
double awaVal, awsVal, cogVal, stwVal, sogVal, hdtVal, hdmVal, varVal; double awaVal, awsVal, cogVal, stwVal, sogVal, hdtVal, hdmVal, varVal;
double twd, tws, twa; double twd, tws, twa;
bool isCalculated = false; bool isCalculated = false;
const double DBL_MIN = std::numeric_limits<double>::lowest();
awaVal = awaBVal->valid ? awaBVal->value : DBL_MIN; awaVal = awaBVal->valid ? awaBVal->value : DBL_MAX;
awsVal = awsBVal->valid ? awsBVal->value : DBL_MIN; awsVal = awsBVal->valid ? awsBVal->value : DBL_MAX;
cogVal = cogBVal->valid ? cogBVal->value : DBL_MIN; cogVal = cogBVal->valid ? cogBVal->value : DBL_MAX;
stwVal = stwBVal->valid ? stwBVal->value : DBL_MIN; stwVal = stwBVal->valid ? stwBVal->value : DBL_MAX;
sogVal = sogBVal->valid ? sogBVal->value : DBL_MIN; sogVal = sogBVal->valid ? sogBVal->value : DBL_MAX;
hdtVal = hdtBVal->valid ? hdtBVal->value : DBL_MIN; hdtVal = hdtBVal->valid ? hdtBVal->value : DBL_MAX;
hdmVal = hdmBVal->valid ? hdmBVal->value : DBL_MIN; hdmVal = hdmBVal->valid ? hdmBVal->value : DBL_MAX;
varVal = varBVal->valid ? varBVal->value : DBL_MIN; varVal = varBVal->valid ? varBVal->value : DBL_MAX;
LOG_DEBUG(GwLog::DEBUG,"obp60task addTrueWind: AWA %.1f, AWS %.1f, COG %.1f, STW %.1f, SOG %.2f, HDT %.1f, HDM %.1f, VAR %.1f", awaBVal->value * RAD_TO_DEG, awsBVal->value * 3.6 / 1.852, LOG_DEBUG(GwLog::DEBUG,"obp60task addTrueWind: AWA %.1f, AWS %.1f, COG %.1f, STW %.1f, SOG %.2f, HDT %.1f, HDM %.1f, VAR %.1f", awaBVal->value * RAD_TO_DEG, awsBVal->value * 3.6 / 1.852,
cogBVal->value * RAD_TO_DEG, stwBVal->value * 3.6 / 1.852, sogBVal->value * 3.6 / 1.852, hdtBVal->value * RAD_TO_DEG, hdmBVal->value * RAD_TO_DEG, varBVal->value * RAD_TO_DEG); cogBVal->value * RAD_TO_DEG, stwBVal->value * 3.6 / 1.852, sogBVal->value * 3.6 / 1.852, hdtBVal->value * RAD_TO_DEG, hdmBVal->value * RAD_TO_DEG, varBVal->value * RAD_TO_DEG);

View File

@ -54,6 +54,7 @@ class WindUtils {
private: private:
GwApi::BoatValue *twdBVal, *twsBVal, *twaBVal; GwApi::BoatValue *twdBVal, *twsBVal, *twaBVal;
GwApi::BoatValue *awaBVal, *awsBVal, *cogBVal, *stwBVal, *sogBVal, *hdtBVal, *hdmBVal, *varBVal; GwApi::BoatValue *awaBVal, *awsBVal, *cogBVal, *stwBVal, *sogBVal, *hdtBVal, *hdmBVal, *varBVal;
static constexpr double DBL_MAX = std::numeric_limits<double>::max();
public: public:
WindUtils(BoatValueList* boatValues){ WindUtils(BoatValueList* boatValues){

View File

@ -16,16 +16,16 @@ private:
size_t last; // Points to the last (newest) valid element size_t last; // Points to the last (newest) valid element
size_t count; // Number of valid elements currently in buffer size_t count; // Number of valid elements currently in buffer
bool is_Full; // Indicates that all buffer elements are used and ringing is in use bool is_Full; // Indicates that all buffer elements are used and ringing is in use
T MIN_VAL; // lowest possible value of buffer T MIN_VAL; // lowest possible value of buffer of type <T>
T MAX_VAL; // highest possible value of buffer of type <T> T MAX_VAL; // highest possible value of buffer of type <T> -> indicates invalid value in buffer
mutable SemaphoreHandle_t bufLocker; mutable SemaphoreHandle_t bufLocker;
// metadata for buffer // metadata for buffer
String dataName; // Name of boat data in buffer String dataName; // Name of boat data in buffer
String dataFmt; // Format of boat data in buffer String dataFmt; // Format of boat data in buffer
int updFreq; // Update frequency in milliseconds int updFreq; // Update frequency in milliseconds
T smallest; // Value range of buffer: smallest value T smallest; // Value range of buffer: smallest value; needs to be => MIN_VAL
T largest; // Value range of buffer: biggest value T largest; // Value range of buffer: biggest value; needs to be < MAX_VAL, since MAX_VAL indicates invalid entries
void initCommon(); void initCommon();
@ -55,8 +55,8 @@ public:
size_t getLastIdx() const; // Get the index of newest value in buffer size_t getLastIdx() const; // Get the index of newest value in buffer
bool isEmpty() const; // Check if buffer is empty bool isEmpty() const; // Check if buffer is empty
bool isFull() const; // Check if buffer is full bool isFull() const; // Check if buffer is full
T getMinVal() const; // Get lowest possible value for buffer; used for initialized buffer data T getMinVal() const; // Get lowest possible value for buffer
T getMaxVal() const; // Get highest possible value for buffer T getMaxVal() const; // Get highest possible value for buffer; used for unset/invalid buffer data
void clear(); // Clear buffer void clear(); // Clear buffer
void resize(size_t size); // Delete buffer and set new size void resize(size_t size); // Delete buffer and set new size
T operator[](size_t index) const; // Operator[] for convenient access (same as get()) T operator[](size_t index) const; // Operator[] for convenient access (same as get())

View File

@ -35,7 +35,7 @@ RingBuffer<T>::RingBuffer(size_t size)
, is_Full(false) , is_Full(false)
{ {
initCommon(); initCommon();
buffer.resize(size, MIN_VAL); buffer.resize(size, MAX_VAL); // MAX_VAL indicate invalid values
} }
// Specify meta data of buffer content // Specify meta data of buffer content
@ -101,7 +101,7 @@ void RingBuffer<T>::add(const T& value)
{ {
GWSYNCHRONIZED(&bufLocker); GWSYNCHRONIZED(&bufLocker);
if (value < smallest || value > largest) { if (value < smallest || value > largest) {
buffer[head] = MIN_VAL; // Store MIN_VAL if value is out of range buffer[head] = MAX_VAL; // Store MAX_VAL if value is out of range
} else { } else {
buffer[head] = value; buffer[head] = value;
} }
@ -125,7 +125,7 @@ T RingBuffer<T>::get(size_t index) const
{ {
GWSYNCHRONIZED(&bufLocker); GWSYNCHRONIZED(&bufLocker);
if (isEmpty() || index < 0 || index >= count) { if (isEmpty() || index < 0 || index >= count) {
return MIN_VAL; return MAX_VAL;
} }
size_t realIndex = (first + index) % capacity; size_t realIndex = (first + index) % capacity;
@ -144,7 +144,7 @@ template <typename T>
T RingBuffer<T>::getFirst() const T RingBuffer<T>::getFirst() const
{ {
if (isEmpty()) { if (isEmpty()) {
return MIN_VAL; return MAX_VAL;
} }
return get(0); return get(0);
} }
@ -154,7 +154,7 @@ template <typename T>
T RingBuffer<T>::getLast() const T RingBuffer<T>::getLast() const
{ {
if (isEmpty()) { if (isEmpty()) {
return MIN_VAL; return MAX_VAL;
} }
return get(count - 1); return get(count - 1);
} }
@ -164,14 +164,14 @@ template <typename T>
T RingBuffer<T>::getMin() const T RingBuffer<T>::getMin() const
{ {
if (isEmpty()) { if (isEmpty()) {
return MIN_VAL; return MAX_VAL;
} }
T minVal = MAX_VAL; T minVal = MAX_VAL;
T value; T value;
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
value = get(i); value = get(i);
if (value < minVal && value != MIN_VAL) { if (value < minVal && value != MAX_VAL) {
minVal = value; minVal = value;
} }
} }
@ -183,7 +183,7 @@ template <typename T>
T RingBuffer<T>::getMin(size_t amount) const T RingBuffer<T>::getMin(size_t amount) const
{ {
if (isEmpty() || amount <= 0) { if (isEmpty() || amount <= 0) {
return MIN_VAL; return MAX_VAL;
} }
if (amount > count) if (amount > count)
amount = count; amount = count;
@ -192,7 +192,7 @@ T RingBuffer<T>::getMin(size_t amount) const
T value; T value;
for (size_t i = 0; i < amount; i++) { for (size_t i = 0; i < amount; i++) {
value = get(count - 1 - i); value = get(count - 1 - i);
if (value < minVal && value != MIN_VAL) { if (value < minVal && value != MAX_VAL) {
minVal = value; minVal = value;
} }
} }
@ -204,14 +204,14 @@ template <typename T>
T RingBuffer<T>::getMax() const T RingBuffer<T>::getMax() const
{ {
if (isEmpty()) { if (isEmpty()) {
return MIN_VAL; return MAX_VAL;
} }
T maxVal = MIN_VAL; T maxVal = MIN_VAL;
T value; T value;
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
value = get(i); value = get(i);
if (value > maxVal && value != MIN_VAL) { if (value > maxVal && value != MAX_VAL) {
maxVal = value; maxVal = value;
} }
} }
@ -223,7 +223,7 @@ template <typename T>
T RingBuffer<T>::getMax(size_t amount) const T RingBuffer<T>::getMax(size_t amount) const
{ {
if (isEmpty() || amount <= 0) { if (isEmpty() || amount <= 0) {
return MIN_VAL; return MAX_VAL;
} }
if (amount > count) if (amount > count)
amount = count; amount = count;
@ -232,7 +232,7 @@ T RingBuffer<T>::getMax(size_t amount) const
T value; T value;
for (size_t i = 0; i < amount; i++) { for (size_t i = 0; i < amount; i++) {
value = get(count - 1 - i); value = get(count - 1 - i);
if (value > maxVal && value != MIN_VAL) { if (value > maxVal && value != MAX_VAL) {
maxVal = value; maxVal = value;
} }
} }
@ -244,7 +244,7 @@ template <typename T>
T RingBuffer<T>::getMid() const T RingBuffer<T>::getMid() const
{ {
if (isEmpty()) { if (isEmpty()) {
return MIN_VAL; return MAX_VAL;
} }
return (getMin() + getMax()) / static_cast<T>(2); return (getMin() + getMax()) / static_cast<T>(2);
@ -255,7 +255,7 @@ template <typename T>
T RingBuffer<T>::getMid(size_t amount) const T RingBuffer<T>::getMid(size_t amount) const
{ {
if (isEmpty() || amount <= 0) { if (isEmpty() || amount <= 0) {
return MIN_VAL; return MAX_VAL;
} }
if (amount > count) if (amount > count)
@ -269,7 +269,7 @@ template <typename T>
T RingBuffer<T>::getMedian() const T RingBuffer<T>::getMedian() const
{ {
if (isEmpty()) { if (isEmpty()) {
return MIN_VAL; return MAX_VAL;
} }
// Create a temporary vector with current valid elements // Create a temporary vector with current valid elements
@ -298,7 +298,7 @@ template <typename T>
T RingBuffer<T>::getMedian(size_t amount) const T RingBuffer<T>::getMedian(size_t amount) const
{ {
if (isEmpty() || amount <= 0) { if (isEmpty() || amount <= 0) {
return MIN_VAL; return MAX_VAL;
} }
if (amount > count) if (amount > count)
amount = count; amount = count;
@ -366,14 +366,14 @@ bool RingBuffer<T>::isFull() const
return is_Full; return is_Full;
} }
// Get lowest possible value for buffer; used for non-set buffer data // Get lowest possible value for buffer
template <typename T> template <typename T>
T RingBuffer<T>::getMinVal() const T RingBuffer<T>::getMinVal() const
{ {
return MIN_VAL; return MIN_VAL;
} }
// Get highest possible value for buffer // Get highest possible value for buffer; used for unset/invalid buffer data
template <typename T> template <typename T>
T RingBuffer<T>::getMaxVal() const T RingBuffer<T>::getMaxVal() const
{ {
@ -405,7 +405,7 @@ void RingBuffer<T>::resize(size_t newSize)
is_Full = false; is_Full = false;
buffer.clear(); buffer.clear();
buffer.resize(newSize, MIN_VAL); buffer.resize(newSize, MAX_VAL);
} }
// Get all current values as a vector // Get all current values as a vector

View File

@ -12,7 +12,7 @@ static const double radToDeg = 180.0 / M_PI; // Conversion factor from radians t
// Get maximum difference of last <amount> of TWD ringbuffer values to center chart; returns "0" if data is not valid // Get maximum difference of last <amount> of TWD ringbuffer values to center chart; returns "0" if data is not valid
int getCntr(const RingBuffer<int16_t>& windDirHstry, size_t amount) int getCntr(const RingBuffer<int16_t>& windDirHstry, size_t amount)
{ {
int minVal = windDirHstry.getMinVal(); const int MAX_VAL = windDirHstry.getMaxVal();
size_t count = windDirHstry.getCurrentSize(); size_t count = windDirHstry.getCurrentSize();
if (windDirHstry.isEmpty() || amount <= 0) { if (windDirHstry.isEmpty() || amount <= 0) {
@ -25,7 +25,7 @@ int getCntr(const RingBuffer<int16_t>& windDirHstry, size_t amount)
int wndCenter = 0; int wndCenter = 0;
midWndDir = windDirHstry.getMid(amount); midWndDir = windDirHstry.getMid(amount);
if (midWndDir != INT16_MIN) { if (midWndDir != MAX_VAL) {
midWndDir = midWndDir / 1000.0 * radToDeg; midWndDir = midWndDir / 1000.0 * radToDeg;
wndCenter = int((midWndDir + (midWndDir >= 0 ? 5 : -5)) / 10) * 10; // Set new center value; round to nearest 10 degree value wndCenter = int((midWndDir + (midWndDir >= 0 ? 5 : -5)) / 10) * 10; // Set new center value; round to nearest 10 degree value
minWndDir = windDirHstry.getMin(amount) / 1000.0 * radToDeg; minWndDir = windDirHstry.getMin(amount) / 1000.0 * radToDeg;
@ -42,10 +42,11 @@ int getCntr(const RingBuffer<int16_t>& windDirHstry, size_t amount)
int getRng(const RingBuffer<int16_t>& windDirHstry, int center, size_t amount) int getRng(const RingBuffer<int16_t>& windDirHstry, int center, size_t amount)
{ {
int minVal = windDirHstry.getMinVal(); int minVal = windDirHstry.getMinVal();
const int MAX_VAL = windDirHstry.getMaxVal();
size_t count = windDirHstry.getCurrentSize(); size_t count = windDirHstry.getCurrentSize();
if (windDirHstry.isEmpty() || amount <= 0) { if (windDirHstry.isEmpty() || amount <= 0) {
return minVal; return MAX_VAL;
} }
if (amount > count) if (amount > count)
amount = count; amount = count;
@ -57,8 +58,8 @@ int getRng(const RingBuffer<int16_t>& windDirHstry, int center, size_t amount)
for (size_t i = 0; i < amount; i++) { for (size_t i = 0; i < amount; i++) {
value = windDirHstry.get(count - 1 - i); value = windDirHstry.get(count - 1 - i);
if (value == minVal) { if (value == MAX_VAL) {
continue; continue; // ignore invalid values
} }
value = value / 1000.0 * radToDeg; value = value / 1000.0 * radToDeg;
@ -70,7 +71,7 @@ int getRng(const RingBuffer<int16_t>& windDirHstry, int center, size_t amount)
maxRng = 180; maxRng = 180;
} }
return maxRng; return (maxRng != minVal ? maxRng : MAX_VAL);
} }
// **************************************************************** // ****************************************************************
@ -104,7 +105,7 @@ public:
virtual void setupKeys() virtual void setupKeys()
{ {
Page::setupKeys(); Page::setupKeys();
// commonData->keydata[0].label = "MODE"; // commonData->keydata[0].label = "MODE";
#if defined BOARD_OBP60S3 #if defined BOARD_OBP60S3
commonData->keydata[1].label = "SRC"; commonData->keydata[1].label = "SRC";
commonData->keydata[4].label = "INTV"; commonData->keydata[4].label = "INTV";
@ -184,6 +185,7 @@ public:
static RingBuffer<uint16_t>* wsHstry; // Wind speed data buffer static RingBuffer<uint16_t>* wsHstry; // Wind speed data buffer
static String wdName, wdFormat; // Wind direction name and format static String wdName, wdFormat; // Wind direction name and format
static String wsName, wsFormat; // Wind speed name and format static String wsName, wsFormat; // Wind speed name and format
static int16_t wdMAX_VAL; // Max. value of wd history buffer, indicating invalid values
float wsValue; // Wind speed value in chart area float wsValue; // Wind speed value in chart area
String wsUnit; // Wind speed unit in chart area String wsUnit; // Wind speed unit in chart area
static GwApi::BoatValue* wsBVal = new GwApi::BoatValue("TWS"); // temp BoatValue for wind speed unit identification; required by OBP60Formater static GwApi::BoatValue* wsBVal = new GwApi::BoatValue("TWS"); // temp BoatValue for wind speed unit identification; required by OBP60Formater
@ -240,7 +242,7 @@ public:
oldDataIntv = 0; oldDataIntv = 0;
wsValue = 0; wsValue = 0;
numAddedBufVals, currIdx, lastIdx = 0; numAddedBufVals, currIdx, lastIdx = 0;
wndCenter = INT_MIN; wndCenter = INT_MAX;
midWndDir = 0; midWndDir = 0;
diffRng = dfltRng; diffRng = dfltRng;
chrtRng = dfltRng; chrtRng = dfltRng;
@ -270,6 +272,7 @@ public:
} }
wdHstry->getMetaData(wdName, wdFormat); wdHstry->getMetaData(wdName, wdFormat);
wsHstry->getMetaData(wsName, wsFormat); wsHstry->getMetaData(wsName, wsFormat);
wdMAX_VAL = wdHstry->getMaxVal();
bufSize = wdHstry->getCapacity(); bufSize = wdHstry->getCapacity();
wsBVal->setFormat(wsHstry->getFormat()); wsBVal->setFormat(wsHstry->getFormat());
lastAddedIdx = wdHstry->getLastIdx(); lastAddedIdx = wdHstry->getLastIdx();
@ -300,14 +303,14 @@ public:
showTruW ? "True" : "App"); showTruW ? "True" : "App");
// Set wndCenter from 1st real buffer value // Set wndCenter from 1st real buffer value
if (wndCenter == INT_MIN || (wndCenter == 0 && count == 1)) { if (wndCenter == INT_MAX || (wndCenter == 0 && count == 1)) {
wndCenter = getCntr(*wdHstry, numWndVals); wndCenter = getCntr(*wdHstry, numWndVals);
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Range Init: count: %d, xWD: %.1f, wndCenter: %d, diffRng: %d, chrtRng: %d, Min: %.0f, Max: %.0f", count, wdHstry->getLast() / 10000.0 * radToDeg, LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Range Init: count: %d, xWD: %.1f, wndCenter: %d, diffRng: %d, chrtRng: %d, Min: %.0f, Max: %.0f", count, wdHstry->getLast() / 1000.0 * radToDeg,
wndCenter, diffRng, chrtRng, wdHstry->getMin(numWndVals) / 10000.0 * radToDeg, wdHstry->getMax(numWndVals) / 10000.0 * radToDeg); wndCenter, diffRng, chrtRng, wdHstry->getMin(numWndVals) / 1000.0 * radToDeg, wdHstry->getMax(numWndVals) / 1000.0 * radToDeg);
} else { } else {
// check and adjust range between left, center, and right chart limit // check and adjust range between left, center, and right chart limit
diffRng = getRng(*wdHstry, wndCenter, numWndVals); diffRng = getRng(*wdHstry, wndCenter, numWndVals);
diffRng = (diffRng == INT16_MIN ? 0 : diffRng); diffRng = (diffRng == wdMAX_VAL ? 0 : diffRng);
if (diffRng > chrtRng) { if (diffRng > chrtRng) {
chrtRng = int((diffRng + (diffRng >= 0 ? 9 : -1)) / 10) * 10; // Round up to next 10 degree value chrtRng = int((diffRng + (diffRng >= 0 ? 9 : -1)) / 10) * 10; // Round up to next 10 degree value
} else if (diffRng + 10 < chrtRng) { // Reduce chart range for higher resolution if possible } else if (diffRng + 10 < chrtRng) { // Reduce chart range for higher resolution if possible
@ -355,11 +358,11 @@ public:
getdisplay().drawCircle(width - 5, yOffset - 17, 2, commonData->fgcolor); // <degree> symbol getdisplay().drawCircle(width - 5, yOffset - 17, 2, commonData->fgcolor); // <degree> symbol
getdisplay().drawCircle(width - 5, yOffset - 17, 3, commonData->fgcolor); // <degree> symbol getdisplay().drawCircle(width - 5, yOffset - 17, 3, commonData->fgcolor); // <degree> symbol
if (wdHstry->getMax() == wdHstry->getMinVal()) { if (wdHstry->getMax() == wdMAX_VAL) {
// only <INT16_MIN> values in buffer -> no valid wind data available // only <MAX_VAL> values in buffer -> no valid wind data available
wndDataValid = false; wndDataValid = false;
} else if (!BDataValid[0] && !useSimuData) { } else if (!BDataValid[0] && !useSimuData) {
// currently no valid TWD data available and no simulation mode // currently no valid xWD data available and no simulation mode
numNoData++; numNoData++;
wndDataValid = true; wndDataValid = true;
if (numNoData > 3) { if (numNoData > 3) {
@ -375,8 +378,8 @@ public:
if (wndDataValid) { if (wndDataValid) {
for (int i = 0; i < (numWndVals / dataIntv); i++) { for (int i = 0; i < (numWndVals / dataIntv); i++) {
chrtVal = static_cast<int>(wdHstry->get(bufStart + (i * dataIntv))); // show the latest wind values in buffer; keep 1st value constant in a rolling buffer chrtVal = static_cast<int>(wdHstry->get(bufStart + (i * dataIntv))); // show the latest wind values in buffer; keep 1st value constant in a rolling buffer
if (chrtVal == INT16_MIN) { if (chrtVal == wdMAX_VAL) {
chrtPrevVal = INT16_MIN; chrtPrevVal = wdMAX_VAL;
} else { } else {
chrtVal = static_cast<int>((chrtVal / 1000.0 * radToDeg) + 0.5); // Convert to degrees and round chrtVal = static_cast<int>((chrtVal / 1000.0 * radToDeg) + 0.5); // Convert to degrees and round
x = ((chrtVal - wndLeft + 360) % 360) * chrtScl; x = ((chrtVal - wndLeft + 360) % 360) * chrtScl;
@ -385,7 +388,7 @@ public:
if (i >= (numWndVals / dataIntv) - 1) // log chart data of 1 line (adjust for test purposes) if (i >= (numWndVals / dataIntv) - 1) // log chart data of 1 line (adjust for test purposes)
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Chart: i: %d, chrtVal: %d, bufStart: %d, count: %d, linesToShow: %d", i, chrtVal, bufStart, count, (numWndVals / dataIntv)); LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Chart: i: %d, chrtVal: %d, bufStart: %d, count: %d, linesToShow: %d", i, chrtVal, bufStart, count, (numWndVals / dataIntv));
if ((i == 0) || (chrtPrevVal == INT16_MIN)) { if ((i == 0) || (chrtPrevVal == wdMAX_VAL)) {
// just a dot for 1st chart point or after some invalid values // just a dot for 1st chart point or after some invalid values
prevX = x; prevX = x;
prevY = y; prevY = y;
@ -517,7 +520,6 @@ PageDescription registerPageWindPlot(
"WindPlot", // Page name "WindPlot", // Page name
createPage, // Action createPage, // Action
0, // Number of bus values depends on selection in Web configuration 0, // Number of bus values depends on selection in Web configuration
// { "TWD", "TWS", "AWD", "AWS" }, // Bus values we need in the page
{ "TWD", "AWD" }, // Bus values we need in the page { "TWD", "AWD" }, // Bus values we need in the page
true // Show display header on/off true // Show display header on/off
); );