diff --git a/lib/obp60task/OBPRingBuffer.h b/lib/obp60task/OBPRingBuffer.h index c458e34..332dddc 100644 --- a/lib/obp60task/OBPRingBuffer.h +++ b/lib/obp60task/OBPRingBuffer.h @@ -45,9 +45,9 @@ private: size_t last; // Points to the last (newest) valid element 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 - T MIN_VAL; // lowest possible value of buffer of type - T MAX_VAL; // highest possible value of buffer of type -> indicates invalid value in buffer - double dblMIN_VAL, dblMAX_VAL; // MIN_VAL, MAX_VAL in double format + T NUMLIMIT_LOW; // internally lowest possible value of buffer of type + T NUMLIMIT_HIGH; // internally highest possible value of buffer of type + double BUFMIN_VAL, BUFMAX_VAL; // lowest/highest possible buffer value considering multiplier -> externally used mutable SemaphoreHandle_t bufLocker; // metadata for buffer @@ -55,8 +55,8 @@ private: String dataFmt; // Format of boat data in buffer int updFreq; // Update frequency in milliseconds double mltplr; // Multiplier which transforms original value into buffer type format - double smallest; // Value range of buffer: smallest value; needs to be => MIN_VAL - double largest; // Value range of buffer: biggest value; needs to be < MAX_VAL, since MAX_VAL indicates invalid entries + double lowest; // low value range for boat data in this buffer; needs to be => BUFMIN_VAL + double highest; // high value range for boat data in this buffer; needs to be < BUFMAX_VAL, since BUFMAX_VAL indicates invalid entries void initCommon(); diff --git a/lib/obp60task/OBPRingBuffer.tpp b/lib/obp60task/OBPRingBuffer.tpp index dd256b1..1b88498 100644 --- a/lib/obp60task/OBPRingBuffer.tpp +++ b/lib/obp60task/OBPRingBuffer.tpp @@ -6,16 +6,16 @@ template void RingBuffer::initCommon() { - MIN_VAL = std::numeric_limits::lowest(); - MAX_VAL = std::numeric_limits::max(); - dblMIN_VAL = static_cast(MIN_VAL); - dblMAX_VAL = static_cast(MAX_VAL); + NUMLIMIT_LOW = std::numeric_limits::lowest(); + NUMLIMIT_HIGH = std::numeric_limits::max(); dataName = ""; dataFmt = ""; updFreq = -1; mltplr = 1; - smallest = dblMIN_VAL; - largest = dblMAX_VAL; + BUFMIN_VAL = static_cast(NUMLIMIT_LOW); + BUFMAX_VAL = static_cast(NUMLIMIT_HIGH); + lowest = BUFMIN_VAL; + highest = BUFMAX_VAL; bufLocker = xSemaphoreCreateMutex(); } @@ -44,7 +44,7 @@ RingBuffer::RingBuffer(size_t size) initCommon(); buffer.reserve(size); - buffer.resize(size, MAX_VAL); // MAX_VAL indicate invalid values + buffer.resize(size, NUMLIMIT_HIGH); // NUMLIMIT_HIGH indicate invalid values } // Specify meta data of buffer content @@ -56,8 +56,10 @@ void RingBuffer::setMetaData(String name, String format, int updateFrequency, dataFmt = format; updFreq = updateFrequency; mltplr = multiplier; - smallest = std::max(dblMIN_VAL, minValue); - largest = std::min(dblMAX_VAL, maxValue); + BUFMIN_VAL = static_cast(NUMLIMIT_LOW) / mltplr; // lowest possible buffer value; converted to external view + BUFMAX_VAL = static_cast(NUMLIMIT_HIGH) / mltplr; // highest possible buffer value; converted to external view + lowest = std::max(BUFMIN_VAL, minValue); // low value range, set by user + highest = std::min(std::nextafter(BUFMAX_VAL, -std::numeric_limits::infinity()), maxValue); // high value range, set by user; max. is 1 tick smaller than BUFMAX_VAL } // Specify format of buffer content @@ -81,8 +83,8 @@ bool RingBuffer::getMetaData(String& name, String& format, int& updateFrequen format = dataFmt; updateFrequency = updFreq; multiplier = mltplr; - minValue = smallest; - maxValue = largest; + minValue = lowest; + maxValue = highest; return true; } @@ -126,8 +128,8 @@ template void RingBuffer::add(const double& value) { GWSYNCHRONIZED(&bufLocker); - if (value < smallest || value > largest) { - buffer[head] = MAX_VAL; // Store MAX_VAL if value is out of range + if (value < lowest || value > highest) { + buffer[head] = NUMLIMIT_HIGH; // Store maximum buffer value if data value is out of range } else { buffer[head] = static_cast(std::round(value * mltplr)); } @@ -151,11 +153,11 @@ double RingBuffer::get(size_t index) const { GWSYNCHRONIZED(&bufLocker); if (isEmpty() || index < 0 || index >= count) { - return dblMAX_VAL; + return BUFMAX_VAL; } size_t realIndex = (first + index) % capacity; - return static_cast(buffer[realIndex] / mltplr); + return static_cast(buffer[realIndex] / mltplr); // is BUFMAX_VAL if value is invalid } // Operator[] for convenient access (same as get()) @@ -170,7 +172,7 @@ template double RingBuffer::getFirst() const { if (isEmpty()) { - return dblMAX_VAL; + return BUFMAX_VAL; } return get(0); } @@ -180,7 +182,7 @@ template double RingBuffer::getLast() const { if (isEmpty()) { - return dblMAX_VAL; + return BUFMAX_VAL; } return get(count - 1); } @@ -189,19 +191,7 @@ double RingBuffer::getLast() const template double RingBuffer::getMin() const { - if (isEmpty()) { - return dblMAX_VAL; - } - - double minVal = dblMAX_VAL; - double value; - for (size_t i = 0; i < count; i++) { - value = get(i); - if (value < minVal && value != dblMAX_VAL) { - minVal = value; - } - } - return minVal; + return getMin(getCurrentSize()); } // Get minimum value of the last values of buffer @@ -209,16 +199,16 @@ template double RingBuffer::getMin(size_t amount) const { if (isEmpty() || amount <= 0) { - return dblMAX_VAL; + return BUFMAX_VAL; } if (amount > count) amount = count; - double minVal = dblMAX_VAL; + double minVal = BUFMAX_VAL; double value; for (size_t i = 0; i < amount; i++) { value = get(count - 1 - i); - if (value < minVal && value != dblMAX_VAL) { + if (value < minVal && value != BUFMAX_VAL) { minVal = value; } } @@ -229,22 +219,7 @@ double RingBuffer::getMin(size_t amount) const template double RingBuffer::getMax() const { - if (isEmpty()) { - return dblMAX_VAL; - } - - double maxVal = dblMIN_VAL; - double value; - for (size_t i = 0; i < count; i++) { - value = get(i); - if (value > maxVal && value != dblMAX_VAL) { - maxVal = value; - } - } - if (maxVal == dblMIN_VAL) { // no change of initial value -> buffer has only invalid values (MAX_VAL) - maxVal = dblMAX_VAL; - } - return maxVal; + return getMax(getCurrentSize()); } // Get maximum value of the last values of buffer @@ -252,21 +227,21 @@ template double RingBuffer::getMax(size_t amount) const { if (isEmpty() || amount <= 0) { - return dblMAX_VAL; + return BUFMAX_VAL; } if (amount > count) amount = count; - double maxVal = dblMIN_VAL; + double maxVal = BUFMIN_VAL; double value; for (size_t i = 0; i < amount; i++) { value = get(count - 1 - i); - if (value > maxVal && value != dblMAX_VAL) { + if (value > maxVal && value != BUFMAX_VAL) { maxVal = value; } } - if (maxVal == dblMIN_VAL) { // no change of initial value -> buffer has only invalid values (MAX_VAL) - maxVal = dblMAX_VAL; + if (maxVal == BUFMIN_VAL) { // no change of initial value -> buffer has only invalid values (BUFMAX_VAL) + maxVal = BUFMAX_VAL; } return maxVal; } @@ -275,11 +250,7 @@ double RingBuffer::getMax(size_t amount) const template double RingBuffer::getMid() const { - if (isEmpty()) { - return dblMAX_VAL; - } - - return (getMin() + getMax()) / 2; + return getMid(getCurrentSize()); } // Get mid value between and value of the last values of buffer @@ -287,7 +258,7 @@ template double RingBuffer::getMid(size_t amount) const { if (isEmpty() || amount <= 0) { - return dblMAX_VAL; + return BUFMAX_VAL; } if (amount > count) @@ -300,29 +271,7 @@ double RingBuffer::getMid(size_t amount) const template double RingBuffer::getMedian() const { - if (isEmpty()) { - return dblMAX_VAL; - } - - // Create a temporary vector with current valid elements - std::vector temp; - temp.reserve(count); - - for (size_t i = 0; i < count; i++) { - temp.push_back(get(i)); - } - - // Sort to find median - std::sort(temp.begin(), temp.end()); - - if (count % 2 == 1) { - // Odd number of elements - return static_cast(temp[count / 2]); - } else { - // Even number of elements - return average of middle two - // Note: For integer types, this truncates. For floating point, it's exact. - return static_cast((temp[count / 2 - 1] + temp[count / 2]) / 2); - } + return getMedian(getCurrentSize()); } // Get the median value of the last values of buffer @@ -330,7 +279,7 @@ template double RingBuffer::getMedian(size_t amount) const { if (isEmpty() || amount <= 0) { - return dblMAX_VAL; + return BUFMAX_VAL; } if (amount > count) amount = count; @@ -402,14 +351,14 @@ bool RingBuffer::isFull() const template double RingBuffer::getMinVal() const { - return dblMIN_VAL; + return BUFMIN_VAL; } // Get highest possible value for buffer; used for unset/invalid buffer data template double RingBuffer::getMaxVal() const { - return dblMAX_VAL; + return BUFMAX_VAL; } // Clear buffer @@ -438,21 +387,14 @@ void RingBuffer::resize(size_t newSize) buffer.clear(); buffer.reserve(newSize); - buffer.resize(newSize, MAX_VAL); + buffer.resize(newSize, NUMLIMIT_HIGH); } // Get all current values in native buffer format as a vector template std::vector RingBuffer::getAllValues() const { - std::vector result; - result.reserve(count); - - for (size_t i = 0; i < count; i++) { - result.push_back(get(i)); - } - - return result; + return getAllValues(getCurrentSize()); } // Get last values in native buffer format as a vector