feat(color,cpn): Updates to the model telemetry page, sensor ID consistency (#3401)

* Add 'Show Instance ID' button to telemetry page to show/hide sensor instance number (default is hidden).
Fix issues with page refresh when all sensors deleted.
Select closest sensor when a single sensor is deleted.
On change, only refresh the sensor list instead of the whole page.
The 'showInstanceIds' property is saved to the model file.
Update Companion to save/load 'showInstanceIds' in model YAML file. Add checkbox to telemetry edit page.

* Update all radio specific files.

* Keep focus on 'Discover/Stop' button when searching for new sensors.
Start sensor ID index at 1 to match B&W radios.
Keep focus on changed parameter when editing sensor, don't rebuild entire parameter list on change.

* Display actual 'instance' ID instead of 'instance' + 1.

* Fix incorrect ID when reloading simulator data.

* Fix incorrect ID when reloading simulator data on B&W radios.
This commit is contained in:
philmoz
2023-04-17 18:44:44 +10:00
committed by GitHub
parent 7bf6dbba0f
commit 6985d3f24b
49 changed files with 559 additions and 345 deletions
@@ -811,6 +811,7 @@ Node convert<ModelData>::encode(const ModelData& rhs)
node["trimInc"] = rhs.trimInc;
node["displayTrims"] = rhs.trimsDisplay;
node["ignoreSensorIds"] = (int)rhs.frsky.ignoreSensorIds;
node["showInstanceIds"] = (int)rhs.showInstanceIds;
node["disableThrottleWarning"] = (int)rhs.disableThrottleWarning;
node["enableCustomThrottleWarning"] = (int)rhs.enableCustomThrottleWarning;
node["customThrottleWarningPosition"] = (int)rhs.customThrottleWarningPosition;
@@ -1058,6 +1059,7 @@ bool convert<ModelData>::decode(const Node& node, ModelData& rhs)
node["trimInc"] >> rhs.trimInc;
node["displayTrims"] >> rhs.trimsDisplay;
node["ignoreSensorIds"] >> rhs.frsky.ignoreSensorIds;
node["showInstanceIds"] >> rhs.showInstanceIds;
node["disableThrottleWarning"] >> rhs.disableThrottleWarning;
node["enableCustomThrottleWarning"] >> rhs.enableCustomThrottleWarning;
node["customThrottleWarningPosition"] >> rhs.customThrottleWarningPosition;
@@ -49,12 +49,7 @@ Node convert<SensorData>::encode(const SensorData& rhs)
node["id1"]["id"] = rhs.id;
node["subId"] = rhs.subid;
unsigned int instance = rhs.instance;
if (instance != 0) {
instance =
((instance - 1) & 0x1F) | (rhs.rxIdx << 5) | (rhs.moduleIdx << 7);
}
node["id2"]["instance"] = instance;
node["id2"]["instance"] = rhs.instance;
cfg["custom"]["ratio"] = rhs.ratio;
cfg["custom"]["offset"] = rhs.offset;
} else {
@@ -132,7 +127,6 @@ bool convert<SensorData>::decode(const Node& node, SensorData& rhs)
if (rhs.type == SensorData::TELEM_TYPE_CUSTOM) {
rhs.rxIdx = (rhs.instance >> 5) & 0x03; // 2 bits Rx idx
rhs.moduleIdx = (rhs.instance >> 7) & 0x1; // 1 bit module idx
rhs.instance = (rhs.instance & 0x1F) + 1; // 5 bits instance
}
node["label"] >> rhs.label;
+1
View File
@@ -171,6 +171,7 @@ class ModelData {
FrSkyData frsky;
unsigned int rssiSource;
RSSIAlarmData rssiAlarms;
bool showInstanceIds;
char bitmap[CPN_MAX_BITMAP_LEN + 1];
+1
View File
@@ -516,6 +516,7 @@ void TelemetryPanel::setup()
}
ui->telemetryProtocol->setCurrentIndex(model->telemetryProtocol);
ui->ignoreSensorIds->setField(model->frsky.ignoreSensorIds, this);
ui->showInstanceIds->setField(model->showInstanceIds, this);
ui->disableTelemetryAlarms->setField(model->rssiAlarms.disabled);
ui->rssiAlarmWarningSB->setRange(0, 127);
+8 -1
View File
@@ -963,7 +963,7 @@
<property name="flat">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="sensorsLayout" columnstretch="0">
<layout class="QGridLayout" name="sensorsLayout" columnstretch="0,0">
<property name="leftMargin">
<number>4</number>
</property>
@@ -996,6 +996,13 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="AutoCheckBox" name="showInstanceIds">
<property name="text">
<string>Show Instance IDs</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
+1
View File
@@ -820,6 +820,7 @@ QString MultiModelPrinter::printTelemetry()
}
ROWLABELCOMPARECELL(tr("Multi sensors"), 0, modelPrinter->printIgnoreSensorIds(!model->frsky.ignoreSensorIds), 0);
ROWLABELCOMPARECELL(tr("Show Instance IDs"), 0, modelPrinter->printIgnoreSensorIds(!model->showInstanceIds), 0);
// Various
columns.appendTableEnd();
+28 -28
View File
@@ -126,7 +126,7 @@ void TelemetrySimulator::stopTelemetry()
return;
uint8_t buffer[FRSKY_SPORT_PACKET_SIZE] = {0};
generateSportPacket(buffer, id - 1, DATA_FRAME, RSSI_ID, 0);
generateSportPacket(buffer, id, DATA_FRAME, RSSI_ID, 0);
emit telemetryDataChanged(QByteArray((char *)buffer, FRSKY_SPORT_PACKET_SIZE));
}
@@ -261,7 +261,7 @@ void TelemetrySimulator::onReplayRateChanged(int value)
}
}
#define SET_INSTANCE(control, id, def) ui->control->setText(QString::number(simulator->getSensorInstance(id, ((def) & 0x1F) + 1)))
#define SET_INSTANCE(control, id, def) ui->control->setText(QString::number(simulator->getSensorInstance(id, ((def) & 0x1F))))
void TelemetrySimulator::setupDataFields()
{
@@ -359,78 +359,78 @@ void TelemetrySimulator::generateTelemetryFrame()
case 1:
if (ui->rxbt->text().length()) {
generateSportPacket(buffer, ui->rxbt_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, BATT_ID, LIMIT<uint32_t>(0, ui->rxbt->value() * 255.0 / ui->rxbt_ratio->value(), 0xFFFFFFFF));
generateSportPacket(buffer, ui->rxbt_inst->text().toInt(&ok, 0), DATA_FRAME, BATT_ID, LIMIT<uint32_t>(0, ui->rxbt->value() * 255.0 / ui->rxbt_ratio->value(), 0xFFFFFFFF));
}
break;
case 2:
if (ui->Rssi->text().length())
generateSportPacket(buffer, ui->rssi_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, RSSI_ID, LIMIT<uint32_t>(0, ui->Rssi->text().toInt(&ok, 0), 0xFF));
generateSportPacket(buffer, ui->rssi_inst->text().toInt(&ok, 0), DATA_FRAME, RSSI_ID, LIMIT<uint32_t>(0, ui->Rssi->text().toInt(&ok, 0), 0xFF));
break;
case 3:
if (ui->Swr->text().length())
generateSportPacket(buffer, ui->swr_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, RAS_ID, LIMIT<uint32_t>(0, ui->Swr->text().toInt(&ok, 0), 0xFFFF));
generateSportPacket(buffer, ui->swr_inst->text().toInt(&ok, 0), DATA_FRAME, RAS_ID, LIMIT<uint32_t>(0, ui->Swr->text().toInt(&ok, 0), 0xFFFF));
break;
case 4:
if (ui->A1->value() > 0)
generateSportPacket(buffer, ui->a1_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ADC1_ID, LIMIT<uint32_t>(0, ui->A1->value() * 255.0 / ui->A1_ratio->value(), 0xFF));
generateSportPacket(buffer, ui->a1_inst->text().toInt(&ok, 0), DATA_FRAME, ADC1_ID, LIMIT<uint32_t>(0, ui->A1->value() * 255.0 / ui->A1_ratio->value(), 0xFF));
break;
case 5:
if (ui->A2->value() > 0)
generateSportPacket(buffer, ui->a2_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ADC2_ID, LIMIT<uint32_t>(0, ui->A2->value() * 255.0 / ui->A2_ratio->value(), 0xFF));
generateSportPacket(buffer, ui->a2_inst->text().toInt(&ok, 0), DATA_FRAME, ADC2_ID, LIMIT<uint32_t>(0, ui->A2->value() * 255.0 / ui->A2_ratio->value(), 0xFF));
break;
case 6:
if (ui->A3->value() != 0)
generateSportPacket(buffer, ui->a3_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, A3_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->A3->value() * 100.0, 0x7FFFFFFF));
generateSportPacket(buffer, ui->a3_inst->text().toInt(&ok, 0), DATA_FRAME, A3_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->A3->value() * 100.0, 0x7FFFFFFF));
break;
case 7:
if (ui->A4->value() != 0)
generateSportPacket(buffer, ui->a4_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, A4_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->A4->value() * 100.0, 0x7FFFFFFF));
generateSportPacket(buffer, ui->a4_inst->text().toInt(&ok, 0), DATA_FRAME, A4_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->A4->value() * 100.0, 0x7FFFFFFF));
break;
case 8:
if (ui->T1->value() != 0)
generateSportPacket(buffer, ui->t1_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, T1_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->T1->value(), 0x7FFFFFFF));
generateSportPacket(buffer, ui->t1_inst->text().toInt(&ok, 0), DATA_FRAME, T1_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->T1->value(), 0x7FFFFFFF));
break;
case 9:
if (ui->T2->value() != 0)
generateSportPacket(buffer, ui->t2_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, T2_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->T2->value(), 0x7FFFFFFF));
generateSportPacket(buffer, ui->t2_inst->text().toInt(&ok, 0), DATA_FRAME, T2_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->T2->value(), 0x7FFFFFFF));
break;
case 10:
if (ui->rpm->value() > 0)
generateSportPacket(buffer, ui->rpm_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, RPM_FIRST_ID, LIMIT<uint32_t>(0, ui->rpm->value(), 0x7FFFFFFF));
generateSportPacket(buffer, ui->rpm_inst->text().toInt(&ok, 0), DATA_FRAME, RPM_FIRST_ID, LIMIT<uint32_t>(0, ui->rpm->value(), 0x7FFFFFFF));
break;
case 11:
if (ui->fuel->value() > 0)
generateSportPacket(buffer, ui->fuel_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, FUEL_FIRST_ID, LIMIT<uint32_t>(0, ui->fuel->value(), 0xFFFF));
generateSportPacket(buffer, ui->fuel_inst->text().toInt(&ok, 0), DATA_FRAME, FUEL_FIRST_ID, LIMIT<uint32_t>(0, ui->fuel->value(), 0xFFFF));
break;
case 12:
if (ui->vspeed->value() != 0)
generateSportPacket(buffer, ui->vvspd_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, VARIO_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->vspeed->value() * 100.0, 0x7FFFFFFF));
generateSportPacket(buffer, ui->vvspd_inst->text().toInt(&ok, 0), DATA_FRAME, VARIO_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->vspeed->value() * 100.0, 0x7FFFFFFF));
break;
case 13:
if (ui->valt->value() != 0)
generateSportPacket(buffer, ui->valt_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ALT_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->valt->value() * 100.0, 0x7FFFFFFF));
generateSportPacket(buffer, ui->valt_inst->text().toInt(&ok, 0), DATA_FRAME, ALT_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->valt->value() * 100.0, 0x7FFFFFFF));
break;
case 14:
if (ui->vfas->value() != 0)
generateSportPacket(buffer, ui->fasv_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, VFAS_FIRST_ID, LIMIT<uint32_t>(0, ui->vfas->value() * 100.0, 0xFFFFFFFF));
generateSportPacket(buffer, ui->fasv_inst->text().toInt(&ok, 0), DATA_FRAME, VFAS_FIRST_ID, LIMIT<uint32_t>(0, ui->vfas->value() * 100.0, 0xFFFFFFFF));
break;
case 15:
if (ui->curr->value() != 0)
generateSportPacket(buffer, ui->fasc_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, CURR_FIRST_ID, LIMIT<uint32_t>(0, ui->curr->value() * 10.0, 0xFFFFFFFF));
generateSportPacket(buffer, ui->fasc_inst->text().toInt(&ok, 0), DATA_FRAME, CURR_FIRST_ID, LIMIT<uint32_t>(0, ui->curr->value() * 10.0, 0xFFFFFFFF));
break;
case 16:
@@ -444,7 +444,7 @@ void TelemetrySimulator::generateTelemetryFrame()
cellValues[5] = ui->cell6->value();
cellValues[6] = ui->cell7->value();
cellValues[7] = ui->cell8->value();
generateSportPacket(buffer, ui->cells_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, CELLS_FIRST_ID, flvss->setAllCells_GetNextPair(cellValues));
generateSportPacket(buffer, ui->cells_inst->text().toInt(&ok, 0), DATA_FRAME, CELLS_FIRST_ID, flvss->setAllCells_GetNextPair(cellValues));
}
else {
cellValues[0] = 0;
@@ -454,62 +454,62 @@ void TelemetrySimulator::generateTelemetryFrame()
case 17:
if (ui->aspeed->value() > 0)
generateSportPacket(buffer, ui->aspd_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, AIR_SPEED_FIRST_ID, LIMIT<uint32_t>(0, ui->aspeed->value() * 5.39957, 0xFFFFFFFF));
generateSportPacket(buffer, ui->aspd_inst->text().toInt(&ok, 0), DATA_FRAME, AIR_SPEED_FIRST_ID, LIMIT<uint32_t>(0, ui->aspeed->value() * 5.39957, 0xFFFFFFFF));
break;
case 18:
if (ui->gps_alt->value() != 0) {
gps->setGPSAltitude(ui->gps_alt->value());
generateSportPacket(buffer, ui->gpsa_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, GPS_ALT_FIRST_ID, gps->getNextPacketData(GPS_ALT_FIRST_ID));
generateSportPacket(buffer, ui->gpsa_inst->text().toInt(&ok, 0), DATA_FRAME, GPS_ALT_FIRST_ID, gps->getNextPacketData(GPS_ALT_FIRST_ID));
}
break;
case 19:
if (ui->gps_speed->value() > 0) {
gps->setGPSSpeedKMH(ui->gps_speed->value());
generateSportPacket(buffer, ui->gpss_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, GPS_SPEED_FIRST_ID, gps->getNextPacketData(GPS_SPEED_FIRST_ID));
generateSportPacket(buffer, ui->gpss_inst->text().toInt(&ok, 0), DATA_FRAME, GPS_SPEED_FIRST_ID, gps->getNextPacketData(GPS_SPEED_FIRST_ID));
}
break;
case 20:
if (ui->gps_course->value() != 0) {
gps->setGPSCourse(ui->gps_course->value());
generateSportPacket(buffer, ui->gpsc_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, GPS_COURS_FIRST_ID, gps->getNextPacketData(GPS_COURS_FIRST_ID));
generateSportPacket(buffer, ui->gpsc_inst->text().toInt(&ok, 0), DATA_FRAME, GPS_COURS_FIRST_ID, gps->getNextPacketData(GPS_COURS_FIRST_ID));
}
break;
case 21:
if (ui->gps_time->text().length()) {
gps->setGPSDateTime(ui->gps_time->text());
generateSportPacket(buffer, ui->gpst_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, GPS_TIME_DATE_FIRST_ID, gps->getNextPacketData(GPS_TIME_DATE_FIRST_ID));
generateSportPacket(buffer, ui->gpst_inst->text().toInt(&ok, 0), DATA_FRAME, GPS_TIME_DATE_FIRST_ID, gps->getNextPacketData(GPS_TIME_DATE_FIRST_ID));
}
break;
case 22:
if (ui->gps_latlon->text().length()) {
gps->setGPSLatLon(ui->gps_latlon->text());
generateSportPacket(buffer, ui->gpsll_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, GPS_LONG_LATI_FIRST_ID, gps->getNextPacketData(GPS_LONG_LATI_FIRST_ID));
generateSportPacket(buffer, ui->gpsll_inst->text().toInt(&ok, 0), DATA_FRAME, GPS_LONG_LATI_FIRST_ID, gps->getNextPacketData(GPS_LONG_LATI_FIRST_ID));
}
break;
case 23:
if (ui->accx->value() != 0)
generateSportPacket(buffer, ui->accx_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ACCX_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accx->value() * 100.0, 0x7FFFFFFF));
generateSportPacket(buffer, ui->accx_inst->text().toInt(&ok, 0), DATA_FRAME, ACCX_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accx->value() * 100.0, 0x7FFFFFFF));
break;
case 24:
if (ui->accy->value() != 0)
generateSportPacket(buffer, ui->accy_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ACCY_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accy->value() * 100.0, 0x7FFFFFFF));
generateSportPacket(buffer, ui->accy_inst->text().toInt(&ok, 0), DATA_FRAME, ACCY_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accy->value() * 100.0, 0x7FFFFFFF));
break;
case 25:
if (ui->accz->value() != 0)
generateSportPacket(buffer, ui->accz_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ACCZ_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accz->value() * 100.0, 0x7FFFFFFF));
generateSportPacket(buffer, ui->accz_inst->text().toInt(&ok, 0), DATA_FRAME, ACCZ_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accz->value() * 100.0, 0x7FFFFFFF));
break;
case 26:
if (ui->fuel_qty->value() > 0)
generateSportPacket(buffer, ui->fuel_qty_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, FUEL_QTY_FIRST_ID, LIMIT<uint32_t>(0, ui->fuel_qty->value() * 100.0, 0xFFFFFF));
generateSportPacket(buffer, ui->fuel_qty_inst->text().toInt(&ok, 0), DATA_FRAME, FUEL_QTY_FIRST_ID, LIMIT<uint32_t>(0, ui->fuel_qty->value() * 100.0, 0xFFFFFF));
break;
default:
+2 -1
View File
@@ -672,7 +672,8 @@ PACK(struct ModelData {
uint8_t throttleReversed:1;
uint8_t enableCustomThrottleWarning:1;
uint8_t disableTelemetryWarning:1;
uint8_t spare3:6 SKIP;
uint8_t showInstanceIds:1;
uint8_t spare3:5 SKIP;
int8_t customThrottleWarningPosition;
BeepANACenter beepANACenter;
MixData mixData[MAX_MIXERS] NO_IDX;
@@ -108,7 +108,7 @@ void menuModelSensor(event_t event)
if (sensor->type == TELEM_TYPE_CUSTOM) {
lcdDrawTextAlignedLeft(y, STR_ID);
lcdDrawHexNumber(SENSOR_2ND_COLUMN, y, sensor->id, LEFT|(menuHorizontalPosition==0 ? attr : 0));
lcdDrawNumber(SENSOR_3RD_COLUMN, y, (sensor->instance & 0x1F) + 1, LEFT|(menuHorizontalPosition==1 ? attr : 0));
lcdDrawNumber(SENSOR_3RD_COLUMN, y, sensor->instance & 0x1F, LEFT|(menuHorizontalPosition==1 ? attr : 0));
if (attr && s_editMode > 0) {
switch (menuHorizontalPosition) {
case 0:
@@ -118,7 +118,7 @@ void menuModelSensor(event_t event)
if (sensor->type == TELEM_TYPE_CUSTOM) {
lcdDrawTextAlignedLeft(y, STR_ID);
lcdDrawHexNumber(SENSOR_2ND_COLUMN, y, sensor->id, LEFT|(menuHorizontalPosition==0 ? attr : 0));
lcdDrawNumber(SENSOR_3RD_COLUMN, y, (sensor->instance & 0x1F) + 1, LEFT|(menuHorizontalPosition==1 ? attr : 0));
lcdDrawNumber(SENSOR_3RD_COLUMN, y, sensor->instance & 0x1F, LEFT|(menuHorizontalPosition==1 ? attr : 0));
if (attr) {
switch (menuHorizontalPosition) {
case 0:
+452 -279
View File
@@ -39,15 +39,6 @@ std::string getSensorCustomValue(uint8_t sensor, int32_t value, LcdFlags flags);
// Overview grid variants
static const lv_coord_t col_dsc[] = {LV_GRID_FR(14), LV_GRID_FR(6),
LV_GRID_TEMPLATE_LAST};
#if LCD_W > LCD_H
static const lv_coord_t col_dsc2[] = {LV_GRID_FR(3), LV_GRID_FR(3), 8, LV_GRID_FR(8), LV_GRID_FR(2),
LV_GRID_TEMPLATE_LAST};
#else
static const lv_coord_t col_dsc2[] = {28, 56, 8, LV_GRID_FR(1), 32,
LV_GRID_TEMPLATE_LAST};
#endif
static const lv_coord_t col_dsc3[] = {LCD_W - 12,
LV_GRID_TEMPLATE_LAST};
#if TWOCOLBUTTONS
static const lv_coord_t col_dsc4[] = {LV_GRID_FR(1), LV_GRID_FR(1),
LV_GRID_TEMPLATE_LAST};
@@ -67,59 +58,117 @@ static const lv_coord_t e_col_dsc2[] = {LV_GRID_FR(4), LV_GRID_FR(3), LV_GRID_FR
static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT,
LV_GRID_TEMPLATE_LAST};
// Sensor value label that updates current value display
class SensorValueLabel : public StaticText {
#define BTN_H 32
#define NUM_W 36
#define NAME_W 56
class TSStyle
{
public:
SensorValueLabel(Window * parent, const rect_t &rect, uint8_t index) :
StaticText(parent, rect, ""),
index(index)
TSStyle() {}
void init()
{
padLeft(10);
}
if (!styleInitDone)
{
styleInitDone = true;
void checkEvents() override
{
uint32_t now = RTOS_GET_MS();
TelemetryItem & telemetryItem = telemetryItems[index];
lv_style_init(&tsContStyle);
lv_style_set_pad_all(&tsContStyle, 0);
lv_style_set_width(&tsContStyle, NUM_W);
lv_style_set_height(&tsContStyle, BTN_H-4);
if ((now - lastRefresh >= 200) || telemetryItem.isFresh()) {
// update at least every 200ms
lastRefresh = now;
lv_style_init(&tsNumStyle);
lv_style_set_text_font(&tsNumStyle, getFont(FONT(STD)));
lv_style_set_text_color(&tsNumStyle, makeLvColor(COLOR_THEME_SECONDARY1));
lv_style_set_text_align(&tsNumStyle, LV_TEXT_ALIGN_CENTER);
lv_style_set_width(&tsNumStyle, NUM_W);
std::string s;
LcdFlags color = COLOR_THEME_SECONDARY1;
lv_style_init(&tsNameStyle);
lv_style_set_text_font(&tsNameStyle, getFont(FONT(STD)));
lv_style_set_text_color(&tsNameStyle, makeLvColor(COLOR_THEME_SECONDARY1));
lv_style_set_text_align(&tsNameStyle, LV_TEXT_ALIGN_LEFT);
lv_style_set_width(&tsNameStyle, NAME_W);
if (telemetryItem.isAvailable()) {
color = telemetryItem.isOld() ? COLOR_THEME_WARNING : color;
s = getSensorCustomValue(index, getValue(MIXSRC_FIRST_TELEM + 3 * index), LEFT);
} else {
s = "---";
}
lv_style_init(&tsFreshStyle);
lv_style_set_text_color(&tsFreshStyle, makeLvColor(COLOR_THEME_SECONDARY1));
lv_style_set_width(&tsFreshStyle, 8);
lv_style_set_height(&tsFreshStyle, 8);
lv_style_set_img_recolor(&tsFreshStyle, makeLvColor(COLOR_THEME_SECONDARY1));
lv_style_set_img_recolor_opa(&tsFreshStyle, LV_OPA_COVER);
#if LCD_H > LCD_W
if (s.size() >= 20) {
setFont(FONT(XS));
} else {
setFont(FONT(STD));
}
#endif
lv_obj_set_style_text_color(lvobj, makeLvColor(color), 0);
setText(s);
lv_style_init(&tsValueStyle);
lv_style_set_text_font(&tsValueStyle, getFont(FONT(STD)));
lv_style_set_text_color(&tsValueStyle, makeLvColor(COLOR_THEME_SECONDARY1));
lv_style_set_text_align(&tsValueStyle, LV_TEXT_ALIGN_LEFT);
lv_style_set_width(&tsValueStyle, LV_SIZE_CONTENT);
lv_style_init(&tsIdStyle);
lv_style_set_text_font(&tsIdStyle, getFont(FONT(XXS)));
lv_style_set_text_color(&tsIdStyle, makeLvColor(COLOR_THEME_SECONDARY1));
lv_style_set_text_align(&tsIdStyle, LV_TEXT_ALIGN_CENTER);
lv_style_set_width(&tsIdStyle, NUM_W);
lv_style_set_height(&tsIdStyle, 11);
}
}
void paint(BitmapBuffer * dc) override
void setContStyle(lv_obj_t* obj)
{
TelemetryItem &telemetryItem = telemetryItems[index];
// Draw a 'fresh' marker
if (telemetryItem.isFresh())
dc->drawFilledCircle(5, 10, 4, COLOR_THEME_SECONDARY1);
init();
lv_obj_add_style(obj, &tsContStyle, LV_PART_MAIN);
}
protected:
uint8_t index;
uint32_t lastRefresh = 0;
void setNumStyle(lv_obj_t* obj)
{
init();
lv_obj_add_style(obj, &tsNumStyle, LV_PART_MAIN);
}
void setNameStyle(lv_obj_t* obj)
{
init();
lv_obj_add_style(obj, &tsNameStyle, LV_PART_MAIN);
}
void setValueStyle(lv_obj_t* obj)
{
init();
lv_obj_add_style(obj, &tsValueStyle, LV_PART_MAIN);
}
void setFreshStyle(lv_obj_t* obj)
{
init();
lv_obj_add_style(obj, &tsFreshStyle, LV_PART_MAIN);
}
void setIdStyle(lv_obj_t* obj)
{
init();
lv_obj_add_style(obj, &tsIdStyle, LV_PART_MAIN);
}
private:
lv_style_t tsContStyle;
lv_style_t tsNumStyle;
lv_style_t tsNameStyle;
lv_style_t tsValueStyle;
lv_style_t tsIdStyle;
lv_style_t tsFreshStyle;
bool styleInitDone;
};
static TSStyle tsStyle;
static uint8_t freshBitmap[] = {
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
};
class SensorButton : public Button {
@@ -128,27 +177,29 @@ class SensorButton : public Button {
Button(parent, rect, nullptr, 0, 0, input_mix_line_create),
index(index)
{
padAll(0);
lv_obj_set_layout(lvobj, LV_LAYOUT_GRID);
lv_obj_set_grid_dsc_array(lvobj, col_dsc2, row_dsc);
lv_obj_set_style_pad_row(lvobj, 0, 0);
lv_obj_set_style_pad_column(lvobj, 4, 0);
padTop(0);
padBottom(0);
padLeft(3);
padRight(3);
setHeight(BTN_H);
lv_obj_set_flex_flow(lvobj, LV_FLEX_FLOW_ROW);
lv_obj_set_style_pad_all(lvobj, 0, 0);
lv_obj_set_flex_align(lvobj, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_AROUND);
check(isActive());
lv_obj_update_layout(parent->getLvObj());
if(lv_obj_is_visible(lvobj)) delayed_init(nullptr);
lv_obj_add_event_cb(lvobj, SensorButton::on_draw, LV_EVENT_DRAW_MAIN_BEGIN, nullptr);
}
protected:
bool init = false;
bool hideId = false;
bool showId = false;
lv_obj_t* numLabel = nullptr;
lv_obj_t* idLabel = nullptr;
uint8_t index;
lv_obj_t* valLabel = nullptr;
lv_obj_t* fresh = nullptr;
uint32_t lastRefresh = 0;
uint8_t index;
static void on_draw(lv_event_t * e)
{
@@ -164,61 +215,74 @@ class SensorButton : public Button {
bool isActive() const
{
TelemetryItem & telemetryItem = telemetryItems[index];
return telemetryItem.isAvailable();
return telemetryItems[index].isAvailable();
}
void setNumIdState()
{
showId = g_model.showInstanceIds;
if (showId) {
lv_obj_clear_flag(idLabel, LV_OBJ_FLAG_HIDDEN);
lv_obj_set_style_text_font(numLabel, getFont(FONT(XS)), 0);
lv_obj_set_height(numLabel, 14);
} else {
lv_obj_add_flag(idLabel, LV_OBJ_FLAG_HIDDEN);
lv_obj_set_style_text_font(numLabel, getFont(FONT(STD)), 0);
lv_obj_set_height(numLabel, 22);
}
}
void checkEvents() override
{
Button::checkEvents();
check(isActive());
if (hideId != g_model.ignoreSensorIds) {
hideId = g_model.ignoreSensorIds;
if (hideId)
lv_obj_add_flag(idLabel, LV_OBJ_FLAG_HIDDEN);
else
lv_obj_clear_flag(idLabel, LV_OBJ_FLAG_HIDDEN);
}
refresh();
}
void delayed_init(lv_event_t* e)
{
char s[20];
auto lbl = lv_label_create(lvobj);
lv_obj_set_style_text_align(lbl, LV_TEXT_ALIGN_CENTER, 0);
lv_obj_set_grid_cell(lbl, LV_GRID_ALIGN_CENTER, 0, 1, LV_GRID_ALIGN_CENTER, 0, 1);
auto box = lv_obj_create(lvobj);
tsStyle.setContStyle(box);
lv_obj_set_flex_flow(box, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(box, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_AROUND);
lv_label_set_text(lbl, std::to_string(index).c_str());
numLabel = lv_label_create(box);
tsStyle.setNumStyle(numLabel);
lbl = lv_label_create(lvobj);
lv_obj_set_style_text_align(lbl, LV_TEXT_ALIGN_LEFT, 0);
lv_obj_set_grid_cell(lbl, LV_GRID_ALIGN_START, 1, 1, LV_GRID_ALIGN_CENTER, 0, 1);
lv_label_set_text(numLabel, std::to_string(index+1).c_str());
strAppend(s, g_model.telemetrySensors[index].label, TELEM_LABEL_LEN);
lv_label_set_text(lbl, s);
auto v = new SensorValueLabel(this, rect_t{}, index);
lv_obj_set_grid_cell(v->getLvObj(), LV_GRID_ALIGN_STRETCH, 2, 2, LV_GRID_ALIGN_CENTER, 0, 1);
idLabel = lv_label_create(box);
tsStyle.setIdStyle(idLabel);
TelemetrySensor * sensor = & g_model.telemetrySensors[index];
if (sensor->type == TELEM_TYPE_CUSTOM) {
sprintf(s, "%d", sensor->instance);
sprintf(s, "ID: %d", sensor->instance);
} else {
s[0] = 0;
}
hideId = g_model.ignoreSensorIds;
idLabel = lv_label_create(lvobj);
lv_obj_set_style_text_align(idLabel, LV_TEXT_ALIGN_LEFT, 0);
lv_obj_set_grid_cell(idLabel, LV_GRID_ALIGN_START, 4, 1, LV_GRID_ALIGN_CENTER, 0, 1);
lv_label_set_text(idLabel, s);
setNumIdState();
if (hideId)
lv_obj_add_flag(idLabel, LV_OBJ_FLAG_HIDDEN);
auto lbl = lv_label_create(lvobj);
tsStyle.setNameStyle(lbl);
strAppend(s, g_model.telemetrySensors[index].label, TELEM_LABEL_LEN);
lv_label_set_text(lbl, s);
box = lv_obj_create(lvobj);
tsStyle.setFreshStyle(box);
fresh = lv_canvas_create(box);
tsStyle.setFreshStyle(fresh);
lv_canvas_set_buffer(fresh, freshBitmap, 8, 8, LV_IMG_CF_ALPHA_8BIT);
lv_obj_add_flag(fresh, LV_OBJ_FLAG_HIDDEN);
valLabel = lv_label_create(lvobj);
tsStyle.setValueStyle(valLabel);
lv_label_set_text(valLabel, "");
init = true;
refresh();
@@ -232,6 +296,38 @@ class SensorButton : public Button {
void refresh()
{
if (!init) return;
if (showId != g_model.showInstanceIds)
setNumIdState();
// Draw a 'fresh' marker
if (telemetryItems[index].isFresh())
lv_obj_clear_flag(fresh, LV_OBJ_FLAG_HIDDEN);
else
lv_obj_add_flag(fresh, LV_OBJ_FLAG_HIDDEN);
uint32_t now = RTOS_GET_MS();
TelemetryItem & telemetryItem = telemetryItems[index];
// Update value
if ((now - lastRefresh >= 200) || telemetryItem.isFresh()) {
// update at least every 200ms
lastRefresh = now;
std::string s;
LcdFlags color = COLOR_THEME_SECONDARY1;
if (telemetryItem.isAvailable()) {
color = telemetryItem.isOld() ? COLOR_THEME_WARNING : color;
s = getSensorCustomValue(index, getValue(MIXSRC_FIRST_TELEM + 3 * index), LEFT);
} else {
s = "---";
}
lv_obj_set_style_text_color(valLabel, makeLvColor(color), 0);
lv_label_set_text(valLabel, s.c_str());
}
}
};
@@ -271,9 +367,36 @@ class SensorEditWindow : public Page {
protected:
uint8_t index;
uint32_t lastRefresh = 0;
FormWindow * sensorParametersWindow = nullptr;
StaticText * headerValue = nullptr;
enum ParamTypes {
P_FORMULA = 0,
P_ID,
P_UNIT,
P_PREC,
P_CELLSENSOR,
P_GPSSENSOR,
P_CURRENTSENSOR,
P_CONSUMPTIONSOURCE,
P_CALC0,
P_BLADES,
P_RATIO,
P_CELLINDEX,
P_ALTSENSOR,
P_CALC1,
P_MULT,
P_OFFSET,
P_CALC2,
P_CALC3,
P_AUTOOFFSET,
P_ONLYPOS,
P_FILTER,
P_PERSISTENT,
P_COUNT,
};
FormWindow::Line* paramLines[P_COUNT] = {};
void buildHeader(Window * window)
{
std::string title2 = STR_SENSOR + std::to_string(index + 1) + " = " + STR_NA;
@@ -310,197 +433,102 @@ class SensorEditWindow : public Page {
}
}
void updateSensorParametersWindow()
void updateSensorParameters()
{
// Sensor variable part
sensorParametersWindow->clear();
sensorParametersWindow->setFlexLayout();
FlexGridLayout grid(e_col_dsc, row_dsc, 2);
FlexGridLayout grid2(e_col_dsc2, row_dsc, 2);
TelemetrySensor * sensor = &g_model.telemetrySensors[index];
FormWindow::Line* line;
for (int i = P_FORMULA; i < P_COUNT; i += 1) {
lv_obj_add_flag(paramLines[i]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
if (sensor->type == TELEM_TYPE_CALCULATED) {
// Formula
line = sensorParametersWindow->newLine(&grid);
new StaticText(line, rect_t{}, STR_FORMULA, 0, COLOR_THEME_PRIMARY1);
new Choice(line, rect_t{}, STR_VFORMULAS, 0, TELEM_FORMULA_LAST, GET_DEFAULT(sensor->formula),
[=](uint8_t newValue) {
sensor->formula = newValue;
sensor->param = 0;
if (sensor->formula == TELEM_FORMULA_CELL) {
sensor->unit = UNIT_VOLTS;
sensor->prec = 2;
}
else if (sensor->formula == TELEM_FORMULA_DIST) {
sensor->unit = UNIT_DIST;
sensor->prec = 0;
}
else if (sensor->formula == TELEM_FORMULA_CONSUMPTION) {
sensor->unit = UNIT_MAH;
sensor->prec = 0;
}
SET_DIRTY();
telemetryItems[index].clear();
updateSensorParametersWindow();
});
lv_obj_clear_flag(paramLines[P_FORMULA]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
else {
line = sensorParametersWindow->newLine(&grid2);
new StaticText(line, rect_t{}, STR_ID, 0, COLOR_THEME_PRIMARY1);
auto hex = new NumberEdit(line, rect_t{}, 0, 0xFFFF, GET_SET_DEFAULT(sensor->id));
hex->setDisplayHandler([](int32_t value) {
std::stringstream stream;
stream << std::hex << value;
return stream.str();
});
new NumberEdit(line, rect_t{}, 0, 0xff, GET_SET_DEFAULT(sensor->instance));
lv_obj_clear_flag(paramLines[P_ID]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
// Unit
if ((sensor->type == TELEM_TYPE_CALCULATED && (sensor->formula == TELEM_FORMULA_DIST)) || sensor->isConfigurable()) {
line = sensorParametersWindow->newLine(&grid);
new StaticText(line, rect_t{}, STR_UNIT, 0, COLOR_THEME_PRIMARY1);
new Choice(line, rect_t{}, STR_VTELEMUNIT, 0, UNIT_MAX, GET_DEFAULT(sensor->unit),
[=](uint8_t newValue) {
sensor->unit = newValue;
if (sensor->unit == UNIT_FAHRENHEIT) {
sensor->prec = 0;
}
SET_DIRTY();
telemetryItems[index].clear();
updateSensorParametersWindow();
});
lv_obj_clear_flag(paramLines[P_UNIT]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
// Precision
if (sensor->isPrecConfigurable() && sensor->unit != UNIT_FAHRENHEIT) {
line = sensorParametersWindow->newLine(&grid);
new StaticText(line, rect_t{}, STR_PRECISION, 0, COLOR_THEME_PRIMARY1);
new Choice(line, rect_t{}, STR_VPREC, 0, 2, GET_DEFAULT(sensor->prec),
[=](uint8_t newValue) {
sensor->prec = newValue;
SET_DIRTY();
telemetryItems[index].clear();
updateSensorParametersWindow();
});
lv_obj_clear_flag(paramLines[P_PREC]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
// Params
if (sensor->unit < UNIT_FIRST_VIRTUAL) {
line = sensorParametersWindow->newLine(&grid);
if (sensor->type == TELEM_TYPE_CALCULATED) {
if (sensor->formula == TELEM_FORMULA_CELL) {
new StaticText(line, rect_t{}, STR_CELLSENSOR, 0, COLOR_THEME_PRIMARY1);
new SensorSourceChoice(line, rect_t{}, &sensor->cell.source, isCellsSensor);
lv_obj_clear_flag(paramLines[P_CELLSENSOR]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
else if (sensor->formula == TELEM_FORMULA_DIST) {
new StaticText(line, rect_t{}, STR_GPSSENSOR, 0, COLOR_THEME_PRIMARY1);
new SensorSourceChoice(line, rect_t{}, &sensor->dist.gps, isGPSSensor);
lv_obj_clear_flag(paramLines[P_GPSSENSOR]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
else if (sensor->formula == TELEM_FORMULA_CONSUMPTION) {
new StaticText(line, rect_t{}, STR_CURRENTSENSOR, 0, COLOR_THEME_PRIMARY1);
new SensorSourceChoice(line, rect_t{}, &sensor->consumption.source, isSensorAvailable);
lv_obj_clear_flag(paramLines[P_CURRENTSENSOR]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
else if (sensor->formula == TELEM_FORMULA_TOTALIZE) {
new StaticText(line, rect_t{}, STR_SOURCE, 0, COLOR_THEME_PRIMARY1);
new SensorSourceChoice(line, rect_t{}, &sensor->consumption.source, isSensorAvailable);
lv_obj_clear_flag(paramLines[P_CONSUMPTIONSOURCE]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
else {
new StaticText(line, rect_t{}, STR_SOURCE + std::to_string(1), 0, COLOR_THEME_PRIMARY1);
new SensorSourceChoice(line, rect_t{}, (uint8_t *) &sensor->calc.sources[0], isSensorAvailable);
lv_obj_clear_flag(paramLines[P_CALC0]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
}
else {
if (sensor->unit == UNIT_RPMS) {
new StaticText(line, rect_t{}, STR_BLADES, 0, COLOR_THEME_PRIMARY1);
new NumberEdit(line, rect_t{}, 1, 30000, GET_SET_DEFAULT(sensor->custom.ratio));
lv_obj_clear_flag(paramLines[P_BLADES]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
else {
new StaticText(line, rect_t{}, STR_RATIO, 0, COLOR_THEME_PRIMARY1);
auto edit = new NumberEdit(line, rect_t{}, 0, 30000, GET_SET_DEFAULT(sensor->custom.ratio));
edit->setZeroText("-");
lv_obj_clear_flag(paramLines[P_RATIO]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
}
}
if (!(sensor->unit == UNIT_GPS || sensor->unit == UNIT_DATETIME || sensor->unit == UNIT_CELLS ||
(sensor->type == TELEM_TYPE_CALCULATED && (sensor->formula == TELEM_FORMULA_CONSUMPTION || sensor->formula == TELEM_FORMULA_TOTALIZE)))) {
line = sensorParametersWindow->newLine(&grid);
if (sensor->type == TELEM_TYPE_CALCULATED) {
if (sensor->formula == TELEM_FORMULA_CELL) {
new StaticText(line, rect_t{}, STR_CELLINDEX, 0, COLOR_THEME_PRIMARY1);
new Choice(line, rect_t{}, STR_VCELLINDEX, TELEM_CELL_INDEX_LOWEST, TELEM_CELL_INDEX_LAST, GET_SET_DEFAULT(sensor->cell.index));
lv_obj_clear_flag(paramLines[P_CELLINDEX]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
else if (sensor->formula == TELEM_FORMULA_DIST) {
new StaticText(line, rect_t{}, STR_ALTSENSOR, 0, COLOR_THEME_PRIMARY1);
new SensorSourceChoice(line, rect_t{}, &sensor->dist.alt, isAltSensor);
lv_obj_clear_flag(paramLines[P_ALTSENSOR]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
else {
new StaticText(line, rect_t{}, STR_SOURCE + std::to_string(2), 0, COLOR_THEME_PRIMARY1);
new SensorSourceChoice(line, rect_t{}, (uint8_t *) &sensor->calc.sources[1], isSensorAvailable);
lv_obj_clear_flag(paramLines[P_CALC1]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
}
else if (sensor->unit == UNIT_RPMS) {
new StaticText(line, rect_t{}, STR_MULTIPLIER, 0, COLOR_THEME_PRIMARY1);
new NumberEdit(line, rect_t{}, 1, 30000, GET_SET_DEFAULT(sensor->custom.offset));
lv_obj_clear_flag(paramLines[P_MULT]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
else {
new StaticText(line, rect_t{}, STR_OFFSET, 0, COLOR_THEME_PRIMARY1);
new NumberEdit(line, rect_t{}, -30000, 30000, GET_SET_DEFAULT(sensor->custom.offset),
0, (sensor->prec > 0) ? (sensor->prec == 2 ? PREC2 : PREC1) : 0);
lv_obj_clear_flag(paramLines[P_OFFSET]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
}
if ((sensor->type == TELEM_TYPE_CALCULATED && sensor->formula < TELEM_FORMULA_MULTIPLY)) {
line = sensorParametersWindow->newLine(&grid);
new StaticText(line, rect_t{}, STR_SOURCE + std::to_string(3), 0, COLOR_THEME_PRIMARY1);
new SensorSourceChoice(line, rect_t{}, (uint8_t *) &sensor->calc.sources[2], isSensorAvailable);
line = sensorParametersWindow->newLine(&grid);
new StaticText(line, rect_t{}, STR_SOURCE + std::to_string(4), 0, COLOR_THEME_PRIMARY1);
new SensorSourceChoice(line, rect_t{}, (uint8_t *) &sensor->calc.sources[3], isSensorAvailable);
lv_obj_clear_flag(paramLines[P_CALC2]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
lv_obj_clear_flag(paramLines[P_CALC3]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
// Auto Offset
if (sensor->unit != UNIT_RPMS && sensor->isConfigurable()) {
line = sensorParametersWindow->newLine(&grid);
new StaticText(line, rect_t{}, STR_AUTOOFFSET, 0, COLOR_THEME_PRIMARY1);
new CheckBox(line, rect_t{}, GET_SET_DEFAULT(sensor->autoOffset));
lv_obj_clear_flag(paramLines[P_AUTOOFFSET]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
if (sensor->isConfigurable()) {
// Only positive
line = sensorParametersWindow->newLine(&grid);
new StaticText(line, rect_t{}, STR_ONLYPOSITIVE, 0, COLOR_THEME_PRIMARY1);
new CheckBox(line, rect_t{}, GET_SET_DEFAULT(sensor->onlyPositive));
lv_obj_clear_flag(paramLines[P_ONLYPOS]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
// Filter
line = sensorParametersWindow->newLine(&grid);
new StaticText(line, rect_t{}, STR_FILTER, 0, COLOR_THEME_PRIMARY1);
new CheckBox(line, rect_t{}, GET_SET_DEFAULT(sensor->filter));
lv_obj_clear_flag(paramLines[P_FILTER]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
if (sensor->type == TELEM_TYPE_CALCULATED) {
line = sensorParametersWindow->newLine(&grid);
new StaticText(line, rect_t{}, STR_PERSISTENT, 0, COLOR_THEME_PRIMARY1);
new CheckBox(line, rect_t{}, GET_DEFAULT(sensor->persistent), [=](int32_t newValue) {
sensor->persistent = newValue;
if (!sensor->persistent)
sensor->persistentValue = 0;
SET_DIRTY();
});
lv_obj_clear_flag(paramLines[P_PERSISTENT]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
line = sensorParametersWindow->newLine(&grid);
new StaticText(line, rect_t{}, STR_LOGS, 0, COLOR_THEME_PRIMARY1);
new CheckBox(line, rect_t{}, GET_DEFAULT(sensor->logs), [=](int32_t newValue) {
sensor->logs = newValue;
logsClose();
SET_DIRTY();
});
}
void buildBody(FormWindow * window)
@@ -514,6 +542,7 @@ class SensorEditWindow : public Page {
form->padAll(4);
FlexGridLayout grid(e_col_dsc, row_dsc, 2);
FlexGridLayout grid2(e_col_dsc2, row_dsc, 2);
TelemetrySensor * sensor = &g_model.telemetrySensors[index];
@@ -535,11 +564,155 @@ class SensorEditWindow : public Page {
sensor->autoOffset = 0;
}
SET_DIRTY();
updateSensorParametersWindow();
updateSensorParameters();
});
sensorParametersWindow = new FormWindow(form, rect_t{});
updateSensorParametersWindow();
// Parameters
paramLines[P_FORMULA] = form->newLine(&grid);
new StaticText(paramLines[P_FORMULA], rect_t{}, STR_FORMULA, 0, COLOR_THEME_PRIMARY1);
new Choice(paramLines[P_FORMULA], rect_t{}, STR_VFORMULAS, 0, TELEM_FORMULA_LAST, GET_DEFAULT(sensor->formula),
[=](uint8_t newValue) {
sensor->formula = newValue;
sensor->param = 0;
if (sensor->formula == TELEM_FORMULA_CELL) {
sensor->unit = UNIT_VOLTS;
sensor->prec = 2;
}
else if (sensor->formula == TELEM_FORMULA_DIST) {
sensor->unit = UNIT_DIST;
sensor->prec = 0;
}
else if (sensor->formula == TELEM_FORMULA_CONSUMPTION) {
sensor->unit = UNIT_MAH;
sensor->prec = 0;
}
SET_DIRTY();
telemetryItems[index].clear();
updateSensorParameters();
});
paramLines[P_ID] = form->newLine(&grid2);
new StaticText(paramLines[P_ID], rect_t{}, STR_ID, 0, COLOR_THEME_PRIMARY1);
auto hex = new NumberEdit(paramLines[P_ID], rect_t{}, 0, 0xFFFF, GET_SET_DEFAULT(sensor->id));
hex->setDisplayHandler([](int32_t value) {
std::stringstream stream;
stream << std::hex << value;
return stream.str();
});
new NumberEdit(paramLines[P_ID], rect_t{}, 0, 0xff, GET_SET_DEFAULT(sensor->instance));
paramLines[P_UNIT] = form->newLine(&grid);
new StaticText(paramLines[P_UNIT], rect_t{}, STR_UNIT, 0, COLOR_THEME_PRIMARY1);
new Choice(paramLines[P_UNIT], rect_t{}, STR_VTELEMUNIT, 0, UNIT_MAX, GET_DEFAULT(sensor->unit),
[=](uint8_t newValue) {
sensor->unit = newValue;
if (sensor->unit == UNIT_FAHRENHEIT) {
sensor->prec = 0;
}
SET_DIRTY();
telemetryItems[index].clear();
updateSensorParameters();
});
paramLines[P_PREC] = form->newLine(&grid);
new StaticText(paramLines[P_PREC], rect_t{}, STR_PRECISION, 0, COLOR_THEME_PRIMARY1);
new Choice(paramLines[P_PREC], rect_t{}, STR_VPREC, 0, 2, GET_DEFAULT(sensor->prec),
[=](uint8_t newValue) {
sensor->prec = newValue;
SET_DIRTY();
telemetryItems[index].clear();
updateSensorParameters();
});
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);
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);
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);
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);
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);
paramLines[P_BLADES] = form->newLine(&grid);
new StaticText(paramLines[P_BLADES], rect_t{}, STR_BLADES, 0, COLOR_THEME_PRIMARY1);
new NumberEdit(paramLines[P_BLADES], rect_t{}, 1, 30000, GET_SET_DEFAULT(sensor->custom.ratio));
paramLines[P_RATIO] = form->newLine(&grid);
new StaticText(paramLines[P_RATIO], rect_t{}, STR_RATIO, 0, COLOR_THEME_PRIMARY1);
auto edit = new NumberEdit(paramLines[P_RATIO], rect_t{}, 0, 30000, GET_SET_DEFAULT(sensor->custom.ratio));
edit->setZeroText("-");
paramLines[P_CELLINDEX] = form->newLine(&grid);
new StaticText(paramLines[P_CELLINDEX], rect_t{}, STR_CELLINDEX, 0, COLOR_THEME_PRIMARY1);
new Choice(paramLines[P_CELLINDEX], rect_t{}, STR_VCELLINDEX, TELEM_CELL_INDEX_LOWEST, TELEM_CELL_INDEX_LAST, GET_SET_DEFAULT(sensor->cell.index));
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);
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);
paramLines[P_MULT] = form->newLine(&grid);
new StaticText(paramLines[P_MULT], rect_t{}, STR_MULTIPLIER, 0, COLOR_THEME_PRIMARY1);
new NumberEdit(paramLines[P_MULT], rect_t{}, 1, 30000, GET_SET_DEFAULT(sensor->custom.offset));
paramLines[P_OFFSET] = form->newLine(&grid);
new StaticText(paramLines[P_OFFSET], rect_t{}, STR_OFFSET, 0, COLOR_THEME_PRIMARY1);
new NumberEdit(paramLines[P_OFFSET], rect_t{}, -30000, 30000, GET_SET_DEFAULT(sensor->custom.offset),
0, (sensor->prec > 0) ? (sensor->prec == 2 ? PREC2 : PREC1) : 0);
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);
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);
paramLines[P_AUTOOFFSET] = form->newLine(&grid);
new StaticText(paramLines[P_AUTOOFFSET], rect_t{}, STR_AUTOOFFSET, 0, COLOR_THEME_PRIMARY1);
new CheckBox(paramLines[P_AUTOOFFSET], rect_t{}, GET_SET_DEFAULT(sensor->autoOffset));
paramLines[P_ONLYPOS] = form->newLine(&grid);
new StaticText(paramLines[P_ONLYPOS], rect_t{}, STR_ONLYPOSITIVE, 0, COLOR_THEME_PRIMARY1);
new CheckBox(paramLines[P_ONLYPOS], rect_t{}, GET_SET_DEFAULT(sensor->onlyPositive));
paramLines[P_FILTER] = form->newLine(&grid);
new StaticText(paramLines[P_FILTER], rect_t{}, STR_FILTER, 0, COLOR_THEME_PRIMARY1);
new CheckBox(paramLines[P_FILTER], rect_t{}, GET_SET_DEFAULT(sensor->filter));
paramLines[P_PERSISTENT] = form->newLine(&grid);
new StaticText(paramLines[P_PERSISTENT], rect_t{}, STR_PERSISTENT, 0, COLOR_THEME_PRIMARY1);
new CheckBox(paramLines[P_PERSISTENT], rect_t{}, GET_DEFAULT(sensor->persistent), [=](int32_t newValue) {
sensor->persistent = newValue;
if (!sensor->persistent)
sensor->persistentValue = 0;
SET_DIRTY();
});
// Logs
line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_LOGS, 0, COLOR_THEME_PRIMARY1);
new CheckBox(line, rect_t{}, GET_DEFAULT(sensor->logs), [=](int32_t newValue) {
sensor->logs = newValue;
logsClose();
SET_DIRTY();
});
updateSensorParameters();
}
};
@@ -562,10 +735,7 @@ void ModelTelemetryPage::checkEvents()
void ModelTelemetryPage::rebuild(FormWindow * window, int8_t focusSensorIndex)
{
auto scroll_y = lv_obj_get_scroll_y(window->getLvObj());
window->clear();
build(window, focusSensorIndex);
lv_obj_scroll_to_y(window->getLvObj(), scroll_y, LV_ANIM_OFF);
buildSensorList(focusSensorIndex);
lastKnownIndex = availableTelemetryIndex();
}
@@ -579,53 +749,18 @@ void ModelTelemetryPage::editSensor(FormWindow * window, uint8_t index)
});
}
#if LCD_W > LCD_H
#define B_HEIGHT 32
#else
#define B_HEIGHT 44
#endif
void ModelTelemetryPage::build(FormWindow * window, int8_t focusSensorIndex)
void ModelTelemetryPage::buildSensorList(int8_t focusSensorIndex)
{
window->padAll(4);
window->setFlexLayout(LV_FLEX_FLOW_COLUMN, 0);
bool didFocus = false;
SensorButton* first = nullptr;
this->window = window;
sensorWindow->clear();
FlexGridLayout grid(col_dsc, row_dsc, 2);
FlexGridLayout grid2(col_dsc2, row_dsc, 2);
// Sensors
auto line = window->newLine(&grid2);
lv_obj_set_style_pad_row(line->getLvObj(), 0, 0);
lv_obj_set_style_pad_column(line->getLvObj(), 4, 0);
auto subttl = new Subtitle(line, rect_t{}, STR_TELEMETRY_SENSORS, 0, COLOR_THEME_PRIMARY1);
#if LCD_H > LCD_W
lv_obj_set_grid_cell(subttl->getLvObj(), LV_GRID_ALIGN_START, 0, 3, LV_GRID_ALIGN_CENTER, 0, 1);
line = window->newLine(&grid2);
lv_obj_set_style_pad_row(line->getLvObj(), 0, 0);
lv_obj_set_style_pad_column(line->getLvObj(), 4, 0);
grid2.nextCell();
#endif
// Sensors columns titles
uint8_t sensorsCount = getTelemetrySensorsCount();
if (sensorsCount > 0) {
new StaticText(line, rect_t{}, STR_NAME, 0, FONT(XS) | COLOR_THEME_PRIMARY1);
grid2.nextCell();
new StaticText(line, rect_t{}, STR_VALUE, 0, FONT(XS) | COLOR_THEME_PRIMARY1);
idLabel = new StaticText(line, rect_t{}, STR_ID, 0, FONT(XS) | COLOR_THEME_PRIMARY1);
if (g_model.ignoreSensorIds)
lv_obj_add_flag(idLabel->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
FlexGridLayout grid3(col_dsc3, row_dsc, 2);
for (uint8_t idx = 0; idx < MAX_TELEMETRY_SENSORS; idx++) {
if (g_model.telemetrySensors[idx].isAvailable()) {
line = window->newLine(&grid3);
auto button = new SensorButton(line, rect_t{0, 0, LCD_W-12, 25}, idx);
auto button = new SensorButton(sensorWindow, rect_t{}, idx);
if (!first) first = button;
button->setPressHandler([=]() -> uint8_t {
Menu * menu = new Menu(window);
@@ -650,21 +785,56 @@ void ModelTelemetryPage::build(FormWindow * window, int8_t focusSensorIndex)
});
menu->addLine(STR_DELETE, [=]() {
delTelemetryIndex(idx); // calls setDirty internally
rebuild(window);
for (uint8_t i = idx + 1; i < MAX_TELEMETRY_SENSORS; i += 1) {
if (g_model.telemetrySensors[i].isAvailable()) {
rebuild(window, i);
return;
}
}
for (uint8_t i = idx - 1; i >= 0; i -= 1) {
if (g_model.telemetrySensors[i].isAvailable()) {
rebuild(window, i);
return;
}
}
rebuild(window,-1);
});
return 0;
});
if (focusSensorIndex == idx) {
lv_group_focus_obj(button->getLvObj());
didFocus = true;
}
}
}
if (!didFocus) {
if (first && !allowNewSensors)
lv_group_focus_obj(first->getLvObj());
else
lv_group_focus_obj(discover->getLvObj());
}
}
void ModelTelemetryPage::build(FormWindow * window)
{
window->padAll(4);
window->setFlexLayout(LV_FLEX_FLOW_COLUMN, 0);
this->window = window;
// Sensors
new Subtitle(window, rect_t{}, STR_TELEMETRY_SENSORS, 0, COLOR_THEME_PRIMARY1);
sensorWindow = new FormWindow(window, rect_t{});
sensorWindow->padAll(0);
sensorWindow->setFlexLayout(LV_FLEX_FLOW_COLUMN, 4);
FlexGridLayout grid4(col_dsc4, row_dsc, 4);
// Autodiscover button
line = window->newLine(&grid4);
auto discover = new TextButton(line, rect_t{}, (allowNewSensors) ? STR_STOP_DISCOVER_SENSORS : STR_DISCOVER_SENSORS);
auto line = window->newLine(&grid4);
discover = new TextButton(line, rect_t{}, (allowNewSensors) ? STR_STOP_DISCOVER_SENSORS : STR_DISCOVER_SENSORS);
discover->setPressHandler([=]() {
allowNewSensors = !allowNewSensors;
if (allowNewSensors) {
@@ -690,14 +860,15 @@ void ModelTelemetryPage::build(FormWindow * window, int8_t focusSensorIndex)
});
lv_obj_set_grid_cell(b->getLvObj(), LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_CENTER, 0, 1);
uint8_t sensorsCount = getTelemetrySensorsCount();
if (sensorsCount > 0) {
#if TWOCOLBUTTONS
line = window->newLine(&grid4);
#endif
// Delete all sensors button
b = new TextButton(line, rect_t{}, STR_DELETE_ALL_SENSORS,
[]() -> uint8_t {
new FullScreenDialog(WARNING_TYPE_CONFIRM, STR_CONFIRMDELETE, "", "", [=]() {
[=]() -> uint8_t {
new ConfirmDialog(window, STR_DELETE_ALL_SENSORS, STR_CONFIRMDELETE, [=]() {
for (int i = 0; i < MAX_TELEMETRY_SENSORS; i++) {
delTelemetryIndex(i);
}
@@ -712,22 +883,22 @@ void ModelTelemetryPage::build(FormWindow * window, int8_t focusSensorIndex)
#endif
}
FlexGridLayout grid(col_dsc, row_dsc, 2);
// Show instance IDs button
line = window->newLine(&grid);
line->padLeft(10);
new StaticText(line, rect_t{}, STR_SHOW_INSTANCE_ID, 0, COLOR_THEME_PRIMARY1);
new CheckBox(line, rect_t{}, GET_SET_DEFAULT(g_model.showInstanceIds));
// Ignore instance button
line = window->newLine(&grid);
line->padLeft(10);
new StaticText(line, rect_t{}, STR_IGNORE_INSTANCE, 0, COLOR_THEME_PRIMARY1);
new CheckBox(line, rect_t{}, GET_DEFAULT(g_model.ignoreSensorIds),
[=](bool newValue) {
g_model.ignoreSensorIds = newValue;
if (newValue)
lv_obj_add_flag(idLabel->getLvObj(), LV_OBJ_FLAG_HIDDEN);
else
lv_obj_clear_flag(idLabel->getLvObj(), LV_OBJ_FLAG_HIDDEN);
});
new CheckBox(line, rect_t{}, GET_SET_DEFAULT(g_model.ignoreSensorIds));
// RSSI
line = window->newLine(&grid);
new Subtitle(line, rect_t{}, getRssiLabel(), 0, COLOR_THEME_PRIMARY1);
new Subtitle(window, rect_t{}, getRssiLabel(), 0, COLOR_THEME_PRIMARY1);
line = window->newLine(&grid);
line->padLeft(10);
@@ -745,8 +916,7 @@ void ModelTelemetryPage::build(FormWindow * window, int8_t focusSensorIndex)
new CheckBox(line, rect_t{}, GET_SET_DEFAULT(g_model.disableTelemetryWarning));
// Vario
line = window->newLine(&grid);
new Subtitle(line, rect_t{}, STR_VARIO, 0, COLOR_THEME_PRIMARY1);
new Subtitle(window, rect_t{}, STR_VARIO, 0, COLOR_THEME_PRIMARY1);
FlexGridLayout grid5(col_dsc5, row_dsc, 4);
@@ -786,6 +956,9 @@ void ModelTelemetryPage::build(FormWindow * window, int8_t focusSensorIndex)
cMax->setAvailableHandler([](int val) { return g_model.varioData.centerMin - 5 < val; });
new Choice(line, rect_t{}, STR_VVARIOCENTER, 0, 1, GET_SET_DEFAULT(g_model.varioData.centerSilent));
// Don't call this before the 'discover' button has been created
buildSensorList(-1);
}
+5 -7
View File
@@ -28,21 +28,19 @@ class ModelTelemetryPage: public PageTab {
public:
ModelTelemetryPage();
void build(FormWindow * window) override
{
build(window, -1);
}
void build(FormWindow * window) override;
void checkEvents() override;
protected:
int lastKnownIndex = 0;
FormWindow * window = nullptr;
Window* idLabel = nullptr;
FormWindow* window = nullptr;
FormWindow* sensorWindow = nullptr;
TextButton* discover = nullptr;
void editSensor(FormWindow * window, uint8_t index);
void build(FormWindow * window, int8_t focusSensorIndex=-1);
void rebuild(FormWindow * window, int8_t focusSensorIndex=-1);
void buildSensorList(int8_t focusSensorIndex=-1);
};
#endif //_MODEL_TELEMETRY_H
@@ -851,7 +851,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -850,7 +850,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -882,7 +882,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -850,7 +850,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -850,7 +850,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -850,7 +850,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -856,7 +856,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -850,7 +850,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -850,7 +850,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -913,7 +913,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -911,7 +911,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -850,7 +850,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -863,7 +863,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -902,7 +902,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -835,7 +835,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -845,7 +845,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -842,7 +842,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -846,7 +846,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
@@ -850,7 +850,8 @@ static const struct YamlNode struct_ModelData[] = {
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_PADDING( 5 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
+1 -1
View File
@@ -407,7 +407,7 @@ uint8_t OpenTxSimulator::getSensorInstance(uint16_t id, uint8_t defaultValue)
if (isTelemetryFieldAvailable(i)) {
TelemetrySensor * sensor = &g_model.telemetrySensors[i];
if (sensor->id == id) {
return sensor->frskyInstance.physID + 1;
return sensor->frskyInstance.physID;
}
}
}
+1
View File
@@ -607,6 +607,7 @@ const char STR_FILTER[] = TR_FILTER;
const char STR_TELEMETRYFULL[] = TR_TELEMETRYFULL;
const char STR_INVERTED_SERIAL[] = TR_INVERTED_SERIAL;
const char STR_IGNORE_INSTANCE[] = TR_IGNORE_INSTANCE;
const char STR_SHOW_INSTANCE_ID[] = TR_SHOW_INSTANCE_ID;
const char STR_DISCOVER_SENSORS[] = TR_DISCOVER_SENSORS;
const char STR_STOP_DISCOVER_SENSORS[] = TR_STOP_DISCOVER_SENSORS;
const char STR_DELETE_ALL_SENSORS[] = TR_DELETE_ALL_SENSORS;
+1
View File
@@ -990,6 +990,7 @@ extern const char STR_FILTER[];
extern const char STR_TELEMETRYFULL[];
extern const char STR_INVERTED_SERIAL[];
extern const char STR_IGNORE_INSTANCE[];
extern const char STR_SHOW_INSTANCE_ID[];
extern const char STR_DISCOVER_SENSORS[];
extern const char STR_STOP_DISCOVER_SENSORS[];
extern const char STR_DELETE_ALL_SENSORS[];
+1
View File
@@ -1153,6 +1153,7 @@
#define TR_TELEMETRYFULL TR("项目已满!", "回传项目已满!")
#define TR_INVERTED_SERIAL INDENT "反向"
#define TR_IGNORE_INSTANCE TR(INDENT "忽略ID", INDENT "忽略ID鉴别")
#define TR_SHOW_INSTANCE_ID "Show instance ID"
#define TR_DISCOVER_SENSORS "扫描新的回传项目"
#define TR_STOP_DISCOVER_SENSORS "停止扫描"
#define TR_DELETE_ALL_SENSORS "删除所有回传项目"
+1
View File
@@ -1157,6 +1157,7 @@
#define TR_TELEMETRYFULL "Všechny sloty jsou plné!"
#define TR_INVERTED_SERIAL INDENT "Invert"
#define TR_IGNORE_INSTANCE TR(INDENT "Chybné ID", INDENT "Ignoruj chyby ID")
#define TR_SHOW_INSTANCE_ID "Show instance ID"
#define TR_DISCOVER_SENSORS "Detekovat nové senzory"
#define TR_STOP_DISCOVER_SENSORS "Zastavit autodetekci"
#define TR_DELETE_ALL_SENSORS "Odebrat všechny senzory"
+1
View File
@@ -1158,6 +1158,7 @@
#define TR_TELEMETRYFULL TR("Alle slots fulde!", "Alle telemetri slots fulde!")
#define TR_INVERTED_SERIAL INDENT "Invers"
#define TR_IGNORE_INSTANCE TR(INDENT "Ingen inst.", INDENT "Ignorer instans")
#define TR_SHOW_INSTANCE_ID "Show instance ID"
#define TR_DISCOVER_SENSORS "Søg efter nye"
#define TR_STOP_DISCOVER_SENSORS "Stop"
#define TR_DELETE_ALL_SENSORS "Slet alle"
+1
View File
@@ -1156,6 +1156,7 @@
#define TR_TELEMETRYFULL TR("Telem voll!", "Telemetriezeilen voll!")
#define TR_INVERTED_SERIAL INDENT "Invert."
#define TR_IGNORE_INSTANCE TR(INDENT "No Inst.", INDENT "Ignor. Instanzen")
#define TR_SHOW_INSTANCE_ID "Show instance ID"
#define TR_DISCOVER_SENSORS "Start Sensorsuche"
#define TR_STOP_DISCOVER_SENSORS "Stop Sensorsuche"
#define TR_DELETE_ALL_SENSORS "Lösche alle Sensoren"
+1
View File
@@ -1150,6 +1150,7 @@
#define TR_TELEMETRYFULL TR("All slots full!", "All telemetry slots full!")
#define TR_INVERTED_SERIAL INDENT "Invert"
#define TR_IGNORE_INSTANCE TR(INDENT "No inst.", INDENT "Ignore instances")
#define TR_SHOW_INSTANCE_ID "Show instance ID"
#define TR_DISCOVER_SENSORS "Discover new"
#define TR_STOP_DISCOVER_SENSORS "Stop"
#define TR_DELETE_ALL_SENSORS "Delete all"
+1
View File
@@ -1158,6 +1158,7 @@
#define TR_TELEMETRYFULL TR("Telem. llena!", "Todas las entradas de telemetría llenas!")
#define TR_INVERTED_SERIAL INDENT "Invertir"
#define TR_IGNORE_INSTANCE TR(INDENT "No inst.", INDENT "Ignora instancias")
#define TR_SHOW_INSTANCE_ID "Show instance ID"
#define TR_DISCOVER_SENSORS "Buscar sensores"
#define TR_STOP_DISCOVER_SENSORS "Parar busqueda"
#define TR_DELETE_ALL_SENSORS "Borrar sensores"
+1
View File
@@ -1168,6 +1168,7 @@
#define TR_TELEMETRYFULL TR("All slots full!", "All telemetry slots full!")
#define TR_INVERTED_SERIAL INDENT "Invert"
#define TR_IGNORE_INSTANCE INDENT "Ignore instance"
#define TR_SHOW_INSTANCE_ID "Show instance ID"
#define TR_DISCOVER_SENSORS "Discover new sensors"
#define TR_STOP_DISCOVER_SENSORS "Stop discovery"
#define TR_DELETE_ALL_SENSORS "Delete all"
+1
View File
@@ -1173,6 +1173,7 @@
#define TR_TELEMETRYFULL "Plus de capteurs libres!"
#define TR_INVERTED_SERIAL INDENT "Inversé"
#define TR_IGNORE_INSTANCE TR(INDENT "Ign. inst", INDENT "Ignorer instance")
#define TR_SHOW_INSTANCE_ID "Show instance ID"
#define TR_DISCOVER_SENSORS "Découvrir capteurs"
#define TR_STOP_DISCOVER_SENSORS "Terminer découverte"
#define TR_DELETE_ALL_SENSORS TR("Suppr. tous capteurs", "Supprimer tous capteurs")
+1
View File
@@ -1160,6 +1160,7 @@
//TODO: translation
#define TR_INVERTED_SERIAL INDENT "Invert."
#define TR_IGNORE_INSTANCE TR(INDENT "No inst.", INDENT "Ignora instanza")
#define TR_SHOW_INSTANCE_ID "Show instance ID"
#define TR_DISCOVER_SENSORS "Cerca nuovi sensori"
#define TR_STOP_DISCOVER_SENSORS "Ferma ricerca"
#define TR_DELETE_ALL_SENSORS "Elimina tutti i sensori"
+1
View File
@@ -1151,6 +1151,7 @@
#define TR_TELEMETRYFULL TR("All slots full!", "テレメトリー枠はすべて埋まりました!!")
#define TR_INVERTED_SERIAL INDENT "リバース"
#define TR_IGNORE_INSTANCE TR(INDENT "No inst.", INDENT "ID識別を無視")
#define TR_SHOW_INSTANCE_ID "Show instance ID"
#define TR_DISCOVER_SENSORS "新規検索"
#define TR_STOP_DISCOVER_SENSORS "停止"
#define TR_DELETE_ALL_SENSORS "すべて削除"
+1
View File
@@ -1167,6 +1167,7 @@
//TODO: translation
#define TR_INVERTED_SERIAL INDENT "Invert"
#define TR_IGNORE_INSTANCE TR(INDENT "Neg. ID ","Negeer ID's")
#define TR_SHOW_INSTANCE_ID "Show instance ID"
#define TR_DISCOVER_SENSORS "Ontdek nieuwe sensors"
#define TR_STOP_DISCOVER_SENSORS "Stop ontdekking"
#define TR_DELETE_ALL_SENSORS "Wis alle sensors"
+1
View File
@@ -1154,6 +1154,7 @@
//TODO: translation
#define TR_INVERTED_SERIAL INDENT "Odwróć"
#define TR_IGNORE_INSTANCE INDENT "Ignoruj przypadek"
#define TR_SHOW_INSTANCE_ID "Show instance ID"
#define TR_DISCOVER_SENSORS "Znajdź nowe czujniki"
#define TR_STOP_DISCOVER_SENSORS "Szukanie STOP "
#define TR_DELETE_ALL_SENSORS "Usuń czujniki "
+1
View File
@@ -1161,6 +1161,7 @@
#define TR_TELEMETRYFULL TR("All slots full!", "All telemetry slots full!")
#define TR_INVERTED_SERIAL INDENT "Invert"
#define TR_IGNORE_INSTANCE INDENT "Ignore instance"
#define TR_SHOW_INSTANCE_ID "Show instance ID"
#define TR_DISCOVER_SENSORS "Discover new"
#define TR_STOP_DISCOVER_SENSORS "Stop discovery"
#define TR_DELETE_ALL_SENSORS "Delete all"
+1
View File
@@ -1186,6 +1186,7 @@
#define TR_INVERTED_SERIAL INDENT "Inverterad"
#define TR_IGNORE_INSTANCE TR(INDENT "Ej inst.", INDENT "Ignorera instansfel")
#define TR_SHOW_INSTANCE_ID "Show instance ID"
#define TR_DISCOVER_SENSORS "Sök nya"
#define TR_STOP_DISCOVER_SENSORS "Avbryt sökning"
#define TR_DELETE_ALL_SENSORS "Ta bort alla sensorer"
+1
View File
@@ -1151,6 +1151,7 @@
#define TR_TELEMETRYFULL TR("項目已滿!", "回傳項目已滿!")
#define TR_INVERTED_SERIAL INDENT "反向"
#define TR_IGNORE_INSTANCE TR(INDENT "忽略ID", INDENT "忽略ID鑑別")
#define TR_SHOW_INSTANCE_ID "Show instance ID"
#define TR_DISCOVER_SENSORS "掃描新的回傳項目"
#define TR_STOP_DISCOVER_SENSORS "停止掃描"
#define TR_DELETE_ALL_SENSORS "刪除所有回傳項目"