buffer extension; still some errors

This commit is contained in:
Ulrich Meine 2025-06-14 02:19:52 +02:00
parent 13c85adad2
commit bd9741d851
1 changed files with 130 additions and 52 deletions

View File

@ -12,19 +12,24 @@ class wndHistory {
private:
int SIZE;
std::vector<int> buffer;
int first = 0; // points to the first valid element
int head = 0; // points to the next insertion index
int count = 0; // number of valid elements
int first; // points to the first (oldest) valid element
int last; // points to the last (newest) valid element
int head; // points to the next insertion index
int count; // number of valid elements
public:
bool begin(int size)
// specifies buffer size
// start buffer
{
if (size <= 0 || size > 10000) {
return false;
}
SIZE = size;
buffer.resize(size, INT_MIN); // allocate buffer
head = 0;
first = 0;
last = 0;
count = 0;
return true;
}
@ -32,6 +37,7 @@ public:
// Add a new value; store in [0..360 deg] format
{
buffer[head] = value;
last = head;
head = (head + 1) % SIZE;
if (count < SIZE) {
count++;
@ -80,7 +86,7 @@ public:
}
int getMin() const
// Get minimum value in the buffer
// Get minimum value of buffer
{
if (count == 0) {
return -1; // Buffer is empty
@ -95,8 +101,46 @@ public:
}
}
/* int getMin(int amount) const
// Get minimum value of the last <amount> values of buffer
{
if (count == 0 || amount <= 0) {
return -1;
} else if (amount > count) {
amount = count; // Limit to available values
}
if (last + amount <= SIZE) {
// No wrap-around
return *std::min_element(buffer.begin() + last, buffer.begin() + (last + amount));
} else {
// Wrap-around
int min1 = *std::min_element(buffer.begin() + ((last - amount) % last), buffer.begin() + last);
int min2 = *std::min_element(buffer.end() - (count - amount - last > 0 ? amount - last : 0), buffer.end());
return std::min(min1, min2);
}
} */
int getMin(int amount) const
// Get minimum value of the last <amount> values of buffer
{
if (count == 0 || amount <= 0)
return -1;
if (amount > count)
amount = count;
int minVal = INT_MAX;
// Start from the newest value (last) and go backwards x times
for (int i = 0; i < amount; ++i) {
int idx = (last - i + SIZE) % SIZE;
if (buffer[idx] < minVal)
minVal = buffer[idx];
}
return minVal;
}
int getMax() const
// Get maximum value in the buffer
// Get maximum value of buffer
{
if (count == 0) {
return -1; // Buffer is empty
@ -111,6 +155,44 @@ public:
}
}
int getMax(int amount) const
// Get minimum value of the last <amount> values of buffer
{
if (count == 0 || amount <= 0)
return -1;
if (amount > count)
amount = count;
int maxVal = INT_MIN;
// Start from the newest value (last) and go backwards x times
for (int i = 0; i < amount; ++i) {
int idx = (last - i + SIZE) % SIZE;
if (buffer[idx] > maxVal)
maxVal = buffer[idx];
}
return maxVal;
}
/* int getMax(int amount) const
// Get maximum value of the last <amount> values of buffer
{
if (count == 0 || amount <= 0) {
return -1;
} else if (amount > count) {
amount = count; // Limit to available values
}
if (first + count <= SIZE) {
// No wrap-around
return *std::max_element(buffer.begin() + last, buffer.begin() + (last + amount));
} else {
// Wrap-around
int max1 = *std::max_element(buffer.begin() + ((last - amount) % last), buffer.begin() + last);
int max2 = *std::max_element(buffer.end(), buffer.end() - (amount - last > 0 ? amount - last : 0);
return std::max(max1, max2);
}
} */
int getMid() const
// Get middle value in the buffer
{
@ -120,16 +202,15 @@ public:
return (getMin() + getMax()) / 2;
}
int getRng(int center)
// Get range of values in the buffer relative to a center value
int getRng(int center, int amount) const
// Get maximum difference of last <amount> of buffer values to center value
{
if (count == 0) {
return -1; // Buffer is empty
}
int min = getMin();
int max = getMax();
// int rng = std::max(abs((min - center + 540) % 360 - 180), abs((max - center + 540) % 360 - 180));
int min = getMin(amount);
int max = getMax(amount);
int rng = std::max(abs(min - center), abs(max - center));
if (rng > 180) { // should never happen, but just in case
rng = 180;
@ -145,6 +226,10 @@ public:
count -= start;
else
count = 0;
if (first == 0)
last = count;
else
last = first - 1;
}
// TWA, TWS, HDM, AWA, AWS, STW
@ -167,7 +252,7 @@ class PageWindPlot : public Page {
// int16_t lp = 80; // Pointer length
char chrtMode = 'D'; // Chart mode: 'D' for TWD, 'S' for TWS, 'B' for both06121990
int dataInterv = 1; // Update interval for wind history chart:
// (1)|(2)|(3)|(4) seconds for 4, 8, 12, 16 min. history chart
// (1)|(2)|(3)|(4) seconds for approx. 4, 8, 12, 16 min. history chart
bool showTWS = true; // Show TWS value in chart area
public:
@ -245,16 +330,18 @@ public:
String dataUnit[numCfgValues];
String dataSValueOld[numCfgValues];
String dataUnitOld[numCfgValues];
static const int bufMinutes = 16; // Buffer size in minutes for wind history chart
bool wndDataValid = false; // Flag to indicate if wind data is valid
bool simulation = false;
bool holdValues = false;
int width = getdisplay().width(); // Get screen width
int height = getdisplay().height(); // Get screen height
int xCenter = width / 2; // Center of screen in x direction
static const int yOffset = 48; // Offset for y coordinates of chart area
int cHeight = height - yOffset - 22; // height of chart area
int xCenter = width / 2; // Center of screen in x direction
static int bufSize = cHeight * 4; // Buffer size: 920 values for appox. 16 min. history chart
int intvBufSize; // Buffer size currently used for user selected time interval
int count; // current size of buffer
static const float radToDeg = 180.0 / M_PI; // Conversion factor from radians to degrees
static int wndCenter = INT_MIN; // chart wind center value position; init value indicates that wndCenter is not set yet
@ -272,32 +359,19 @@ public:
static float chrtScl; // Scale for wind values in pixels per degree
int chrtVal; // Current wind value
static int chrtPrevVal; // Last wind value in chart area for check if value crosses 180 degree line
int count; // index for next wind value in buffer
static int updCnt = 0; // update counter for wind history chart in seconds
bool isTimeforUpd = true; // Flag to indicate if it is time for chart update
int numWndValues; // number of wind values available for current interval selection
LOG_DEBUG(GwLog::LOG, "Display page WindPlot");
if (windDirHstry.getSize() == 0) {
// if (!windDirValues.begin(bufMinutes * 60)) {
if (!windDirHstry.begin(cHeight)) {
logger->logDebug(GwLog::ERROR, "Failed to initialize wind values buffer");
if (!windDirHstry.begin(bufSize)) {
logger->logDebug(GwLog::ERROR, "Failed to initialize wind direction history buffer");
return;
}
}
/* if (updCnt < updTime) {
// Next update interval not reached yet
updCnt++;
isTimeforUpd = false;
} else {
isTimeforUpd = true;
updCnt = 1; // Data update is now; reset counter
}
*/
// Get config data
String lengthformat = config->getString(config->lengthFormat);
// String lengthformat = config->getString(config->lengthFormat);
simulation = config->getBool(config->useSimuData);
holdValues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
@ -341,8 +415,10 @@ public:
windDirHstry.add(twdValue);
}
count = windDirHstry.getSize(); // Get number of valid elements in buffer; maximum is cHeight
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot: Data 0 valid - dataValue[0]: %f, TWD: %d, cnt: %d, valid0: %d", dataValue[0] * radToDeg, twdValue, count, dataValid[0]);
intvBufSize = cHeight * dataInterv; // Get buffer size for current interval selection
count = windDirHstry.getSize();
numWndValues = min(count, intvBufSize);
LOG_DEBUG(GwLog::ERROR, "PageWindPlot: User Interval: %d, intvBufSize: %d, count: %d, TWD: %d", dataInterv, intvBufSize, count, twdValue);
// Optical warning by limit violation (unused)
if (String(flashLED) == "Limit Violation") {
@ -358,14 +434,14 @@ public:
// initialize chart range values
if (wndCenter == INT_MIN) {
wndCenter = (windDirHstry.get(0) < 0 ? 0 : windDirHstry.get(0));
wndCenter = windDirHstry.get(count - intvBufSize < 0 ? 0 : count - intvBufSize);
wndCenter = int((wndCenter + (wndCenter >= 0 ? 5 : -5)) / 10) * 10; // Set new center value; round to nearest 10 degree value
diffRng = 30;
chrtRng = 30;
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot initialized. wndCenter: %d, chrtRng: %d ", wndCenter, chrtRng);
} else {
diffRng = windDirHstry.getRng(wndCenter);
diffRng = windDirHstry.getRng(wndCenter, numWndValues);
diffRng = (diffRng < 0 ? 0 : diffRng); // If no data in buffer, set range to 0
if (diffRng > chrtRng) {
chrtRng = int((diffRng + (diffRng >= 0 ? 9 : -1)) / 10) * 10; // Round up to next 10 degree value
@ -422,26 +498,27 @@ public:
// Draw wind values in chart
//***********************************************************
if (wndDataValid || holdValues || simulation) {
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Draw: prevX: %d, chrtPrevVal: %d, wndLeft: %d, chrtScl: %f, count: %d", prevX, chrtPrevVal, wndLeft, chrtScl, count);
int threshold = 90;
for (int i = 0; i < count; i++) {
chrtVal = windDirHstry.get(i);
// if (i == 0)
// chrtPrevVal = chrtVal;
for (int i = 0; i < numWndValues; i++) {
chrtVal = windDirHstry.get(count - numWndValues + (i * dataInterv));
if (i < 12)
LOG_DEBUG(GwLog::ERROR, "PageWindPlot Draw: i: %d, numWndValues: %d, chrtVal: %d, count: %d", i, numWndValues, chrtVal, count);
x = ((chrtVal - wndLeft + 360) % 360) * chrtScl;
y = yOffset + cHeight - i; // Position in chart area
if (i == 0) { // just a dot for 1st chart point
prevX = x;
prevY = y;
chrtPrevVal = chrtVal;
} else if (((chrtPrevVal >= wndLeft) && (chrtVal <= wndLeft)) || ((chrtPrevVal <= wndRight) && (chrtVal >= wndRight)) && !((chrtPrevVal < wndCenter && chrtVal >= wndCenter) || (chrtPrevVal >= wndCenter && chrtVal <= wndCenter))) {
} else if (((chrtPrevVal >= wndLeft) && (chrtVal <= wndLeft)) || ((chrtPrevVal <= wndRight) && (chrtVal >= wndRight))) {
// if (!((chrtPrevVal > 180) && (chrtVal < 180)) || ((chrtPrevVal < 180) && (chrtVal > 180))) {
if (!((chrtPrevVal >= 360 - threshold) && (chrtVal < threshold)) || ((chrtPrevVal < threshold) && (chrtVal >= 360 - threshold))) {
// If current value crosses chart edges, compared to previous value, and does not cross "0" line, draw a dot only, no line
prevX = x; // don't print connecting line to previous value
prevY = y;
LOG_DEBUG(GwLog::ERROR, "PageWindPlot Chart: chrtVal: %d, chrtPrevVal: %d, 0-Crossing: %d", chrtVal, chrtPrevVal, ((chrtPrevVal > 180 && chrtVal < 180) || (chrtPrevVal < 180 && chrtVal > 180)));
}
}
if ((chrtVal > 350 || chrtVal < 10) || (chrtVal > 170 && chrtVal < 190)) // data debugging
LOG_DEBUG(GwLog::ERROR, "PageWindPlot Chart: chrtVal: %d, x: %d, y: %d prevX: %d, prevY: %d, loop-Counter: %d, Flipped: %d", chrtVal, x, y, prevX, prevY, count, rngFlipped);
// Draw line with 2 pixels width + make sure vertical line are drawn correctly
getdisplay().drawLine(prevX, prevY, x, y, commonData->fgcolor);
@ -452,7 +529,7 @@ public:
if (i == (cHeight - 1)) { // Reaching chart area top end
windDirHstry.mvStart(40); // virtually delete 40 values from buffer
if ((windDirHstry.getMin() > wndCenter) || (windDirHstry.getMax() < wndCenter)) {
if ((windDirHstry.getMin(numWndValues) > wndCenter) || (windDirHstry.getMax(numWndValues) < wndCenter)) {
// Check if all wind value are left or right of center value -> optimize chart range
int mid = windDirHstry.getMid();
wndCenter = int((mid + (mid >= 0 ? 5 : -5)) / 10) * 10; // Set new center value; round to nearest 10 degree value
@ -478,11 +555,12 @@ public:
int xPosTws = flipTws ? 30 : width - 145;
static const int yPosTws = yOffset + 40;
int currentZone = (y > yPosTws - 36 && y < yPosTws) ? 1 : 0; // Define zone for TWS value
// int currentZone = (y > yPosTws - 36 && y < yPosTws) ? 1 : 0; // Define zone for TWS value
int currentZone = (x > xPosTws) && (x < (xPosTws + 145)) ? 1 : 0; // Define zone for TWS value
if (currentZone != lastZone) {
// Only flip when y moves to a different zone
if ((y > yPosTws - 36) && (y < yPosTws) && ((!flipTws && (x > xPosTws)) || (flipTws && (x > xPosTws) && (x < (xPosTws + 145))))) {
// if ((y > yPosTws - 36) && (y < yPosTws) && ((!flipTws && (x > xPosTws)) || (flipTws && (x > xPosTws) && (x < (xPosTws + 145))))) {
if ((y > yPosTws - 36) && (y < yPosTws) && (x > xPosTws) && (x < (xPosTws + 145))) {
flipTws = !flipTws;
xPosTws = flipTws ? 30 : width - 145;
}
@ -513,7 +591,7 @@ public:
for (int i = 3; i > 0; i--) {
yPos = yOffset + cHeight - (i * 60) + 14; // Y position for label
getdisplay().fillRect(0, yPos, width, 1, commonData->fgcolor);
getdisplay().fillRect(0, yPos - 6, 26, 15, commonData->bgcolor); // Clear small area to remove potential chart lines
getdisplay().fillRect(0, yPos - 9, 26, 16, commonData->bgcolor); // Clear small area to remove potential chart lines
getdisplay().fillRect(0, yPos, 8, 2, commonData->fgcolor);
getdisplay().setCursor(9, yPos + 4);
snprintf(sWndYAx, 4, "%2d", i * dataInterv);