diff --git a/companion/src/datamodels/compounditemmodels.cpp b/companion/src/datamodels/compounditemmodels.cpp index 8d462166e9a..7c680f4a926 100644 --- a/companion/src/datamodels/compounditemmodels.cpp +++ b/companion/src/datamodels/compounditemmodels.cpp @@ -481,22 +481,74 @@ TelemetrySourceItemModel::TelemetrySourceItemModel(const GeneralSettings * const if (!modelData) return; - setUpdateMask(IMUE_TeleSensors | IMUE_Modules); - const int count = firmware->getCapability(Sensors); + setUpdateMask(IMUE_TeleSensors | IMUE_Modules | IMUE_GVars); - for (int i = -count; i <= count; ++i) { + addItems(SOURCE_TYPE_GVAR, -firmware->getCapability(Gvars)); + addItems(SOURCE_TYPE_TELEMETRY, -firmware->getCapability(Sensors)); + addItems(SOURCE_TYPE_NONE, 1); + addItems(SOURCE_TYPE_TELEMETRY, firmware->getCapability(Sensors)); + addItems(SOURCE_TYPE_GVAR, firmware->getCapability(Gvars)); +} + +void TelemetrySourceItemModel::addItems(const RawSourceType & type, int count) +{ + int flags = 0; + + if (type == SOURCE_TYPE_GVAR) + flags = RawSource::GVarsGroup; + + int i = (count < 0 ? count : 1); + count = (i < 0 ? 0 : count + i); + + for ( ; i < count; ++i) { QStandardItem * modelItem = new QStandardItem(); - modelItem->setData(i, IMDR_Id); - modelItem->setData(i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None, IMDR_Flags); - setDynamicItemData(modelItem, i); + int id = i; + + if (type == SOURCE_TYPE_NONE) + id = 0; + + if (type != SOURCE_TYPE_GVAR) { + flags = (i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None); + } + else { + id = ((SENSOR_GVAR_START + 1) * (i < 0 ? -1 : 1)) - id; + } + + modelItem->setData(id, IMDR_Id); + modelItem->setData((int)type, IMDR_Type); + modelItem->setData(flags , IMDR_Flags); + setDynamicItemData(modelItem); appendRow(modelItem); } } -void TelemetrySourceItemModel::setDynamicItemData(QStandardItem * item, const int value) const +void TelemetrySourceItemModel::setDynamicItemData(QStandardItem * item) const { - item->setText(SensorData::sourceToString(modelData, value)); - item->setData(SensorData::isSourceAvailable(modelData, value), IMDR_Available); + const int type = item->data(IMDR_Type).toInt(); + int id = item->data(IMDR_Id).toInt(); + + switch (type) { + case SOURCE_TYPE_NONE: + { + const RawSource src = RawSource(id); + item->setText(src.toString()); + item->setData(true, IMDR_Available); + break; + } + case SOURCE_TYPE_TELEMETRY: + item->setText(SensorData::sourceToString(modelData, id)); + item->setData(SensorData::isSourceAvailable(modelData, id), IMDR_Available); + break; + case SOURCE_TYPE_GVAR: + { + int idx = SENSOR_GVAR_START - abs(id); + item->setText((id < 0 ? "-" : "") % modelData->gvarData[idx].nameToString(idx)); + item->setData(true, IMDR_Available); + break; + } + default: + break; + } } void TelemetrySourceItemModel::update(const int event) @@ -505,7 +557,7 @@ void TelemetrySourceItemModel::update(const int event) emit aboutToBeUpdated(); for (int i = 0; i < rowCount(); ++i) { - setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt()); + setDynamicItemData(item(i)); } emit updateComplete(); diff --git a/companion/src/datamodels/compounditemmodels.h b/companion/src/datamodels/compounditemmodels.h index ede23bb3420..d330f1ff215 100644 --- a/companion/src/datamodels/compounditemmodels.h +++ b/companion/src/datamodels/compounditemmodels.h @@ -303,7 +303,8 @@ class TelemetrySourceItemModel: public AbstractDynamicItemModel virtual void update(const int event = IMUE_SystemRefresh) override; protected: - virtual void setDynamicItemData(QStandardItem * item, const int value) const; + virtual void setDynamicItemData(QStandardItem * item) const; + void addItems(const RawSourceType & type, int count); }; class CurveRefTypeItemModel : public AbstractStaticItemModel diff --git a/companion/src/firmwares/sensordata.h b/companion/src/firmwares/sensordata.h index 948b1807d77..52ad40400d0 100644 --- a/companion/src/firmwares/sensordata.h +++ b/companion/src/firmwares/sensordata.h @@ -25,6 +25,7 @@ #include constexpr int SENSOR_LABEL_LEN { 4 }; +constexpr int SENSOR_GVAR_START { 127 }; constexpr int SENSOR_ISCONFIGURABLE { 1 << 1 }; constexpr int SENSOR_HAS_GPS { 1 << 2 }; diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index 6536f30f45d..8cc23a267c0 100644 --- a/radio/src/datastructs_private.h +++ b/radio/src/datastructs_private.h @@ -421,6 +421,7 @@ PACK(struct TelemetrySensor { void init(const char *label, uint8_t unit=UNIT_RAW, uint8_t prec=0); void init(uint16_t id); bool isAvailable() const; + bool isOfflineFresh() const; int32_t getValue(int32_t value, uint8_t unit, uint8_t prec) const; bool isConfigurable() const; bool isPrecConfigurable() const; diff --git a/radio/src/gui/128x64/model_telemetry_sensor.cpp b/radio/src/gui/128x64/model_telemetry_sensor.cpp index 1ce8173f400..ebec46c41f1 100644 --- a/radio/src/gui/128x64/model_telemetry_sensor.cpp +++ b/radio/src/gui/128x64/model_telemetry_sensor.cpp @@ -266,15 +266,46 @@ void menuModelSensor(event_t event) { drawStringWithIndex(0, y, STR_SOURCE, k-SENSOR_FIELD_PARAM1+1); int8_t * source = &sensor->calc.sources[k-SENSOR_FIELD_PARAM1]; + uint8_t delta = GV_GET_GV1_VALUE(-MAX_TELEMETRY_SENSORS, MAX_TELEMETRY_SENSORS); if (attr) { - *source = checkIncDec(event, *source, -MAX_TELEMETRY_SENSORS, MAX_TELEMETRY_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isSensorAvailable); - } - if (*source < 0) { - lcdDrawChar(SENSOR_2ND_COLUMN, y, '-', attr); - drawSource(lcdNextPos, y, MIXSRC_FIRST_TELEM+3*(-1-*source), attr); +#if defined(GVARS) + if (event == EVT_KEY_LONG(KEY_ENTER)) { + *source = (GV_IS_GV_VALUE(*source, -MAX_TELEMETRY_SENSORS, MAX_TELEMETRY_SENSORS) ? 0 : delta); + s_editMode = !s_editMode; + } + if(GV_IS_GV_VALUE(*source, -MAX_TELEMETRY_SENSORS, MAX_TELEMETRY_SENSORS)) { + int8_t idx = (int16_t)GV_INDEX_CALC_DELTA(*source, delta); + CHECK_INCDEC_MODELVAR(event, idx, -MAX_GVARS, MAX_GVARS-1); + if (idx < 0) { + *source = (int8_t)GV_CALC_VALUE_IDX_NEG(idx, delta); + } + else { + *source = (int8_t)GV_CALC_VALUE_IDX_POS(idx, delta); + } + } else { +#endif + *source = checkIncDec(event, *source, -MAX_TELEMETRY_SENSORS, MAX_TELEMETRY_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isSensorAvailable); + } +#if defined(GVARS) } - else { - drawSource(SENSOR_2ND_COLUMN, y, *source ? MIXSRC_FIRST_TELEM+3*(*source-1) : 0, attr); + if(GV_IS_GV_VALUE(*source, -MAX_TELEMETRY_SENSORS, MAX_TELEMETRY_SENSORS)) { + int8_t gvindex = GV_INDEX_CALC_DELTA(*source, delta); + if(gvindex<0 && sensor->formula == TELEM_FORMULA_MULTIPLY) { + lcdDrawChar(SENSOR_2ND_COLUMN, y, '/', attr); + drawGVarName(lcdNextPos, y, -gvindex-1, attr); + } else { + drawGVarName(SENSOR_2ND_COLUMN, y, gvindex, attr); + } + } else +#endif + { + if (*source < 0) { + lcdDrawChar(SENSOR_2ND_COLUMN, y, '-', attr); + drawSource(lcdNextPos, y, MIXSRC_FIRST_TELEM+3*(-1-*source), attr); + } + else { + drawSource(SENSOR_2ND_COLUMN, y, *source ? MIXSRC_FIRST_TELEM+3*(*source-1) : 0, attr); + } } break; } diff --git a/radio/src/gui/212x64/model_telemetry_sensor.cpp b/radio/src/gui/212x64/model_telemetry_sensor.cpp index 5135deb9249..62f4a9ebff6 100644 --- a/radio/src/gui/212x64/model_telemetry_sensor.cpp +++ b/radio/src/gui/212x64/model_telemetry_sensor.cpp @@ -280,15 +280,46 @@ void menuModelSensor(event_t event) { drawStringWithIndex(0, y, STR_SOURCE, k-SENSOR_FIELD_PARAM1+1); int8_t * source = &sensor->calc.sources[k-SENSOR_FIELD_PARAM1]; + uint8_t delta = GV_GET_GV1_VALUE(-MAX_TELEMETRY_SENSORS, MAX_TELEMETRY_SENSORS); if (attr) { +#if defined(GVARS) + if (event == EVT_KEY_LONG(KEY_ENTER)) { + *source = (GV_IS_GV_VALUE(*source, -MAX_TELEMETRY_SENSORS, MAX_TELEMETRY_SENSORS) ? 0 : delta); + s_editMode = !s_editMode; + } + if(GV_IS_GV_VALUE(*source, -MAX_TELEMETRY_SENSORS, MAX_TELEMETRY_SENSORS)) { + int8_t idx = (int16_t)GV_INDEX_CALC_DELTA(*source, delta); + CHECK_INCDEC_MODELVAR(event, idx, -MAX_GVARS, MAX_GVARS-1); + if (idx < 0) { + *source = (int8_t)GV_CALC_VALUE_IDX_NEG(idx, delta); + } + else { + *source = (int8_t)GV_CALC_VALUE_IDX_POS(idx, delta); + } + } else { +#endif *source = checkIncDec(event, *source, -MAX_TELEMETRY_SENSORS, MAX_TELEMETRY_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isSensorAvailable); } - if (*source < 0) { - lcdDrawChar(SENSOR_2ND_COLUMN, y, '-', attr); - drawSource(lcdNextPos, y, MIXSRC_FIRST_TELEM+3*(-1-*source), attr); +#if defined(GVARS) } - else { - drawSource(SENSOR_2ND_COLUMN, y, *source ? MIXSRC_FIRST_TELEM+3*(*source-1) : 0, attr); + if(GV_IS_GV_VALUE(*source, -MAX_TELEMETRY_SENSORS, MAX_TELEMETRY_SENSORS)) { + int8_t gvindex = GV_INDEX_CALC_DELTA(*source, delta); + if(gvindex<0 && sensor->formula == TELEM_FORMULA_MULTIPLY) { + lcdDrawChar(SENSOR_2ND_COLUMN, y, '/', attr); + drawGVarName(lcdNextPos, y, -gvindex-1, attr); + } else { + drawGVarName(SENSOR_2ND_COLUMN, y, gvindex, attr); + } + } else +#endif + { + if (*source < 0) { + lcdDrawChar(SENSOR_2ND_COLUMN, y, '-', attr); + drawSource(lcdNextPos, y, MIXSRC_FIRST_TELEM+3*(-1-*source), attr); + } + else { + drawSource(SENSOR_2ND_COLUMN, y, *source ? MIXSRC_FIRST_TELEM+3*(*source-1) : 0, attr); + } } break; } diff --git a/radio/src/gui/colorlcd/model_telemetry.cpp b/radio/src/gui/colorlcd/model_telemetry.cpp index a415202ccb2..583b733e727 100644 --- a/radio/src/gui/colorlcd/model_telemetry.cpp +++ b/radio/src/gui/colorlcd/model_telemetry.cpp @@ -341,27 +341,108 @@ class SensorButton : public Button { } }; -class SensorSourceChoice : public SourceChoice +class TelemetrySourceChoice : public Choice { - public: - SensorSourceChoice(Window *window, const rect_t &rect, uint8_t *source, - IsValueAvailable isValueAvailable) : - SourceChoice(window, rect, MIXSRC_NONE, MIXSRC_LAST_TELEM, - GET_DEFAULT(*source ? MIXSRC_FIRST_TELEM + 3 * (*source - 1) - : MIXSRC_NONE), - [=](uint16_t newValue) { - *source = newValue == MIXSRC_NONE - ? 0 - : (newValue - MIXSRC_FIRST_TELEM) / 3 + 1; - }) - { - setAvailableHandler([=](int16_t value) { - if (value == MIXSRC_NONE) return true; - if (value < MIXSRC_FIRST_TELEM) return false; - auto qr = div(value - MIXSRC_FIRST_TELEM, 3); - return qr.rem == 0 && isValueAvailable(qr.quot + 1); - }); - } +public: + TelemetrySourceChoice(Window *window, const rect_t &rect, uint8_t *source, IsValueAvailable isValueAvailable) : + Choice(window, rect, 0, 127, GET_DEFAULT(static_cast(*source)), [=](int16_t newValue){*source=newValue;}) + { + setAvailableHandler([=](int16_t value) -> bool { + if (value == 0) return true; + if (negativeGVarPrefix!=0){ + //gvars allowed + //negative values allowed + int8_t gvindex = static_cast(GV_INDEX_CALCULATION(value, -MAX_TELEMETRY_SENSORS, MAX_TELEMETRY_SENSORS)); + if(-MAX_GVARS <= gvindex && gvindex < MAX_GVARS) { + return true; + } + } + //not a gvar, negative can be allowed + int index = abs(value); + return index <= MAX_TELEMETRY_SENSORS && isValueAvailable(index); + }); + setTextHandler([=](int value) { + if(GV_IS_GV_VALUE(value, -MAX_TELEMETRY_SENSORS, MAX_TELEMETRY_SENSORS)) { + int index = GV_INDEX_CALCULATION(value, -MAX_TELEMETRY_SENSORS, MAX_TELEMETRY_SENSORS); + std::string ret(getGVarString(index)); + fprintf(stderr,">>>>>> GV %d %d %s\n",value,index,ret.c_str()); + if(value>0) { + ret[0] = negativeGVarPrefix; + } + return ret; + } else if (value == 0) { + return std::string(getSourceString(0)); + } else if (value < 0) { + std::string ret(getSourceString(MIXSRC_FIRST_TELEM+((-value)-1)*3)); + ret.insert(0, 1, '-'); + return ret; + } else { + return std::string(getSourceString(MIXSRC_FIRST_TELEM+(value-1)*3)); + } + }); + setRangeMapHandler([=](int n) { + // Map range of choice values so GVars are in correct order. + if (n <= -120) + n += GV1_SMALL * 2 - MAX_GVARS; + else if (n >= 119) + n -= GV1_SMALL * 2 - MAX_GVARS; + return n; + }); + } + + void setGVPrefix(char prefix) + { + if (modelGVEnabled()) { + negativeGVarPrefix = prefix; + setMin(negativeGVarPrefix != 0 ? -128 : 0); + if (getIntValue() < getMin()) + setValue(getMin()); + } + } + + protected: + char negativeGVarPrefix; +}; + +class SensorLiveValue: public Window { + public: + explicit SensorLiveValue(Window * parent, const rect_t & rect, int index): + Window(parent, rect, OPAQUE), + index(index) + { + } + + void checkEvents() override + { + uint32_t now = RTOS_GET_MS(); + if (now - lastRefresh >= 200) { + // update at least every 200ms + invalidate(); + } + + TelemetryItem & telemetryItem = telemetryItems[index]; + if (telemetryItem.isFresh()) { + invalidate(); + } + + Window::checkEvents(); + } + + void paint(BitmapBuffer * dc) override + { + TelemetryItem &telemetryItem = telemetryItems[index]; + + dc->drawSolidFilledRect(0, 0, width(), height(), COLOR_THEME_SECONDARY1); + if (telemetryItem.isAvailable()) { + LcdFlags color = telemetryItem.isOld() ? COLOR_THEME_WARNING : COLOR_THEME_PRIMARY2; + drawSensorCustomValue(dc, 0, 1, index, getValue(MIXSRC_FIRST_TELEM + 3 * index), LEFT | color); + } else { + dc->drawText(0, 1, "---", COLOR_THEME_PRIMARY2); + } + } + protected: + uint8_t index; + uint32_t lastRefresh = 0; }; class SensorEditWindow : public Page { @@ -406,6 +487,7 @@ class SensorEditWindow : public Page { }; FormWindow::Line* paramLines[P_COUNT] = {}; + TelemetrySourceChoice* calcSource[4] = {}; void buildHeader(Window * window) { @@ -443,6 +525,16 @@ class SensorEditWindow : public Page { } } + void setGVPrefix(int n, uint8_t formula) + { + if (formula == TELEM_FORMULA_MULTIPLY) + calcSource[n]->setGVPrefix('/'); + else if (formula < TELEM_FORMULA_MULTIPLY) + calcSource[n]->setGVPrefix('-'); + else + calcSource[n]->setGVPrefix(0); + } + void updateSensorParameters() { TelemetrySensor * sensor = &g_model.telemetrySensors[index]; @@ -486,6 +578,7 @@ class SensorEditWindow : public Page { } else { lv_obj_clear_flag(paramLines[P_CALC0]->getLvObj(), LV_OBJ_FLAG_HIDDEN); + setGVPrefix(0, sensor->formula); } } else { @@ -509,6 +602,7 @@ class SensorEditWindow : public Page { } else { lv_obj_clear_flag(paramLines[P_CALC1]->getLvObj(), LV_OBJ_FLAG_HIDDEN); + setGVPrefix(1, sensor->formula); } } else if (sensor->unit == UNIT_RPMS) { @@ -521,7 +615,9 @@ class SensorEditWindow : public Page { if ((sensor->type == TELEM_TYPE_CALCULATED && sensor->formula < TELEM_FORMULA_MULTIPLY)) { lv_obj_clear_flag(paramLines[P_CALC2]->getLvObj(), LV_OBJ_FLAG_HIDDEN); + setGVPrefix(2, sensor->formula); lv_obj_clear_flag(paramLines[P_CALC3]->getLvObj(), LV_OBJ_FLAG_HIDDEN); + setGVPrefix(3, sensor->formula); } // Auto Offset @@ -647,23 +743,23 @@ class SensorEditWindow : public Page { paramLines[P_CELLSENSOR] = form->newLine(&grid); new StaticText(paramLines[P_CELLSENSOR], rect_t{}, STR_CELLSENSOR, 0, COLOR_THEME_PRIMARY1); - new SensorSourceChoice(paramLines[P_CELLSENSOR], rect_t{}, &sensor->cell.source, isCellsSensor); + new TelemetrySourceChoice(paramLines[P_CELLSENSOR], rect_t{}, &sensor->cell.source, isCellsSensor); paramLines[P_GPSSENSOR] = form->newLine(&grid); new StaticText(paramLines[P_GPSSENSOR], rect_t{}, STR_GPSSENSOR, 0, COLOR_THEME_PRIMARY1); - new SensorSourceChoice(paramLines[P_GPSSENSOR], rect_t{}, &sensor->dist.gps, isGPSSensor); + new TelemetrySourceChoice(paramLines[P_GPSSENSOR], rect_t{}, &sensor->dist.gps, isGPSSensor); paramLines[P_CURRENTSENSOR] = form->newLine(&grid); new StaticText(paramLines[P_CURRENTSENSOR], rect_t{}, STR_CURRENTSENSOR, 0, COLOR_THEME_PRIMARY1); - new SensorSourceChoice(paramLines[P_CURRENTSENSOR], rect_t{}, &sensor->consumption.source, isSensorAvailable); + new TelemetrySourceChoice(paramLines[P_CURRENTSENSOR], rect_t{}, &sensor->consumption.source, isSensorAvailable); paramLines[P_CONSUMPTIONSOURCE] = form->newLine(&grid); new StaticText(paramLines[P_CONSUMPTIONSOURCE], rect_t{}, STR_SOURCE, 0, COLOR_THEME_PRIMARY1); - new SensorSourceChoice(paramLines[P_CONSUMPTIONSOURCE], rect_t{}, &sensor->consumption.source, isSensorAvailable); + new TelemetrySourceChoice(paramLines[P_CONSUMPTIONSOURCE], rect_t{}, &sensor->consumption.source, isSensorAvailable); paramLines[P_CALC0] = form->newLine(&grid); new StaticText(paramLines[P_CALC0], rect_t{}, STR_SOURCE + std::to_string(1), 0, COLOR_THEME_PRIMARY1); - new SensorSourceChoice(paramLines[P_CALC0], rect_t{}, (uint8_t *) &sensor->calc.sources[0], isSensorAvailable); + calcSource[0] = new TelemetrySourceChoice(paramLines[P_CALC0], rect_t{}, (uint8_t *) &sensor->calc.sources[0], isSensorAvailable); paramLines[P_BLADES] = form->newLine(&grid); new StaticText(paramLines[P_BLADES], rect_t{}, STR_BLADES, 0, COLOR_THEME_PRIMARY1); @@ -680,11 +776,11 @@ class SensorEditWindow : public Page { paramLines[P_ALTSENSOR] = form->newLine(&grid); new StaticText(paramLines[P_ALTSENSOR], rect_t{}, STR_ALTSENSOR, 0, COLOR_THEME_PRIMARY1); - new SensorSourceChoice(paramLines[P_ALTSENSOR], rect_t{}, &sensor->dist.alt, isAltSensor); + new TelemetrySourceChoice(paramLines[P_ALTSENSOR], rect_t{}, &sensor->dist.alt, isAltSensor); paramLines[P_CALC1] = form->newLine(&grid); new StaticText(paramLines[P_CALC1], rect_t{}, STR_SOURCE + std::to_string(2), 0, COLOR_THEME_PRIMARY1); - new SensorSourceChoice(paramLines[P_CALC1], rect_t{}, (uint8_t *) &sensor->calc.sources[1], isSensorAvailable); + calcSource[1] = new TelemetrySourceChoice(paramLines[P_CALC1], rect_t{}, (uint8_t *) &sensor->calc.sources[1], isSensorAvailable); paramLines[P_MULT] = form->newLine(&grid); new StaticText(paramLines[P_MULT], rect_t{}, STR_MULTIPLIER, 0, COLOR_THEME_PRIMARY1); @@ -697,11 +793,11 @@ class SensorEditWindow : public Page { paramLines[P_CALC2] = form->newLine(&grid); new StaticText(paramLines[P_CALC2], rect_t{}, STR_SOURCE + std::to_string(3), 0, COLOR_THEME_PRIMARY1); - new SensorSourceChoice(paramLines[P_CALC2], rect_t{}, (uint8_t *) &sensor->calc.sources[2], isSensorAvailable); + calcSource[2] = new TelemetrySourceChoice(paramLines[P_CALC2], rect_t{}, (uint8_t *) &sensor->calc.sources[2], isSensorAvailable); paramLines[P_CALC3] = form->newLine(&grid); new StaticText(paramLines[P_CALC3], rect_t{}, STR_SOURCE + std::to_string(4), 0, COLOR_THEME_PRIMARY1); - new SensorSourceChoice(paramLines[P_CALC3], rect_t{}, (uint8_t *) &sensor->calc.sources[3], isSensorAvailable); + calcSource[3] = new TelemetrySourceChoice(paramLines[P_CALC3], rect_t{}, (uint8_t *) &sensor->calc.sources[3], isSensorAvailable); paramLines[P_AUTOOFFSET] = form->newLine(&grid); new StaticText(paramLines[P_AUTOOFFSET], rect_t{}, STR_AUTOOFFSET, 0, COLOR_THEME_PRIMARY1); diff --git a/radio/src/gvars.cpp b/radio/src/gvars.cpp index b1dbc3d1d96..5d593fe6958 100644 --- a/radio/src/gvars.cpp +++ b/radio/src/gvars.cpp @@ -68,7 +68,7 @@ void setGVarValue(uint8_t gv, int16_t value, int8_t fm) int16_t getGVarFieldValue(int16_t val, int16_t min, int16_t max, int8_t fm) { if (GV_IS_GV_VALUE(val, min, max)) { - int8_t gv = GV_INDEX_CALCULATION(val, max); + int8_t gv = GV_INDEX_CALCULATION(val, min, max); val = getGVarValue(gv, fm); } return limit(min, val, max); @@ -77,7 +77,7 @@ int16_t getGVarFieldValue(int16_t val, int16_t min, int16_t max, int8_t fm) int32_t getGVarFieldValuePrec1(int16_t val, int16_t min, int16_t max, int8_t fm) { if (GV_IS_GV_VALUE(val, min, max)) { - int8_t gv = GV_INDEX_CALCULATION(val, max); + int8_t gv = GV_INDEX_CALCULATION(val, min, max); val = getGVarValuePrec1(gv, fm); } else { diff --git a/radio/src/gvars.h b/radio/src/gvars.h index ed3f1fa2a03..a167535df7e 100644 --- a/radio/src/gvars.h +++ b/radio/src/gvars.h @@ -50,7 +50,7 @@ #endif #define GV_GET_GV1_VALUE(vmin, vmax) ((vmax<=GV_RANGESMALL && vmin>=GV_RANGESMALL_NEG) ? GV1_SMALL : GV1_LARGE) -#define GV_INDEX_CALCULATION(x,max) ((max<=GV_RANGESMALL && min>=GV_RANGESMALL_NEG) ? (uint8_t) x-GV1_SMALL : ((x&(GV1_LARGE*2-1))-GV1_LARGE)) +#define GV_INDEX_CALCULATION(x,min,max) ((max<=GV_RANGESMALL && min>=GV_RANGESMALL_NEG) ? (uint8_t) x-GV1_SMALL : ((x&(GV1_LARGE*2-1))-GV1_LARGE)) #define GV_IS_GV_VALUE(x,min,max) ((max>GV1_SMALL || min<-GV1_SMALL) ? (x>GV_RANGELARGE || xmax) || (x0) { + //divide, actually + int32_t divisor = convertTelemetryValue(-gvarvalue, sensor.unit, 0, sensor.unit, 0); + if (divisor!=0) { + value = convertTelemetryValue(value, sensor.unit, mulprec, sensor.unit, mulprec+sensor.prec)/divisor; + } else { + value = 0; + } + } else { + value *= convertTelemetryValue(gvarvalue, sensor.unit, 0, sensor.unit, 0); + mulprec += sensor.prec; + } + } + else { + if (sensor.formula == TELEM_FORMULA_MIN) + value = (count==1 ? gvarvalue : min(value, gvarvalue)); + else if (sensor.formula == TELEM_FORMULA_MAX) + value = (count==1 ? gvarvalue : max(value, gvarvalue)); + else + value += gvarvalue; + } + count += 1; + + continue; + } +#endif if (source) { unsigned int index = abs(source)-1; TelemetrySensor & telemetrySensor = g_model.telemetrySensors[index]; @@ -641,6 +673,25 @@ bool TelemetrySensor::isAvailable() const return ZLEN(label) > 0; } +bool TelemetrySensor::isOfflineFresh() const +{ + if(type == TELEM_TYPE_CALCULATED && formula <= TELEM_FORMULA_MULTIPLY) { + int32_t maxitems = 4; + if(formula == TELEM_FORMULA_MULTIPLY) { + maxitems = 2; + } + for(int i=0; i handler) + { + rangeMapHandler = handler; + } + void setMenuTitle(std::string value) { menuTitle = std::move(value); } std::string getMenuTitle() const { return menuTitle; } @@ -192,6 +197,7 @@ class Choice : public ChoiceBase std::function _setValue; std::function isValueAvailable; std::function textHandler; + std::function rangeMapHandler; std::function fillMenuHandler; std::function beforeDisplayMenuHandler;