diff --git a/radio/src/gui/colorlcd/draw_functions.cpp b/radio/src/gui/colorlcd/draw_functions.cpp index 122c0ac91..0b2ca84f3 100644 --- a/radio/src/gui/colorlcd/draw_functions.cpp +++ b/radio/src/gui/colorlcd/draw_functions.cpp @@ -317,19 +317,23 @@ coord_t drawGPSCoord(BitmapBuffer * dc, coord_t x, coord_t y, int32_t value, con } *tmp++ = direction[value>=0 ? 0 : 1]; *tmp = '\0'; - dc->drawText(x, y, s, flags); + x = dc->drawText(x, y, s, flags); return x; } void drawGPSPosition(BitmapBuffer * dc, coord_t x, coord_t y, int32_t longitude, int32_t latitude, LcdFlags flags) { - if (flags & EXPANDED) { - drawGPSCoord(dc, x, y, latitude, "NS", flags, true); - drawGPSCoord(dc, x, y + FH, longitude, "EW", flags, true); - } - else { - x = drawGPSCoord(dc, x, y, latitude, "NS", flags, false); - drawGPSCoord(dc, x + 5, y, longitude, "EW", flags, false); + if (flags & PREC1) { + drawGPSCoord(dc, x, y, latitude, "NS", flags, false); + drawGPSCoord(dc, x, y + FH, longitude, "EW", flags, false); + } else { + if (flags & RIGHT) { + x = drawGPSCoord(dc, x, y, longitude, "EW", flags, false); + drawGPSCoord(dc, x - 5, y, latitude, "NS", flags, false); + } else { + x = drawGPSCoord(dc, x, y, latitude, "NS", flags, false); + drawGPSCoord(dc, x + 5, y, longitude, "EW", flags, false); + } } } diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index 10cdf1a96..862168d1f 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -123,8 +123,6 @@ void loadCustomScreens() } auto topbar = viewMain->getTopbar(); - - // TODO: how to reload this guy? topbar->load(); viewMain->setCurrentMainView(0); diff --git a/radio/src/gui/colorlcd/model_select.cpp b/radio/src/gui/colorlcd/model_select.cpp index 9a4a0115b..04e08f621 100644 --- a/radio/src/gui/colorlcd/model_select.cpp +++ b/radio/src/gui/colorlcd/model_select.cpp @@ -108,15 +108,30 @@ class ModelButton : public Button if (strncmp(modelCell->modelFilename, g_eeGeneral.currModelFilename, LEN_MODEL_FILENAME) == 0) { memcpy(&partialModel.header, &g_model.header, sizeof(partialModel)); + version = EEPROM_VER; } else { error = readModel(modelCell->modelFilename, (uint8_t *)&partialModel.header, sizeof(partialModel), &version); - if (!error) { - if (modelCell->modelName[0] == '\0' && - partialModel.header.name[0] != '\0') { - modelCell->setModelName(partialModel.header.name); + } + + if (!error) { + if (modelCell->modelName[0] == '\0' && + partialModel.header.name[0] != '\0') { + + if (version == 219) { + size_t len = sizeof(partialModel.header.name); + char* str = partialModel.header.name; + for (int i=0; i < len; i++) { + str[i] = zchar2char(str[i]); + } + // Trim string + while(len > 0 && str[len-1]) { + if (str[len - 1] != ' ' && str[len - 1] != '\0') break; + str[--len] = '\0'; + } } + modelCell->setModelName(partialModel.header.name); } } diff --git a/radio/src/gui/colorlcd/special_functions.cpp b/radio/src/gui/colorlcd/special_functions.cpp index 5c79687e0..3faf9d9ad 100644 --- a/radio/src/gui/colorlcd/special_functions.cpp +++ b/radio/src/gui/colorlcd/special_functions.cpp @@ -250,6 +250,92 @@ class SpecialFunctionEditPage : public Page }); break; } + + case FUNC_ADJUST_GVAR: { + + new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), + STR_GLOBALVAR); + auto gvarchoice = + new Choice(specialFunctionOneWindow, grid.getFieldSlot(), 0, + MAX_GVARS - 1, GET_SET_DEFAULT(CFN_GVAR_INDEX(cfn))); + gvarchoice->setTextHandler([](int32_t value) { + return std::string(STR_GV) + std::to_string(value + 1); + }); + grid.nextLine(); + + new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), + STR_MODE); + auto modechoice = + new Choice(specialFunctionOneWindow, grid.getFieldSlot(), + FUNC_ADJUST_GVAR_CONSTANT, FUNC_ADJUST_GVAR_INCDEC, + GET_DEFAULT(CFN_GVAR_MODE(cfn)), nullptr); + grid.nextLine(); + + modechoice->setTextHandler([](int32_t value) { + switch (value) { + case FUNC_ADJUST_GVAR_CONSTANT: + return std::string(STR_CONSTANT); + case FUNC_ADJUST_GVAR_SOURCE: + return std::string(STR_MIXSOURCE); + case FUNC_ADJUST_GVAR_GVAR: + return std::string(STR_GLOBALVAR); + case FUNC_ADJUST_GVAR_INCDEC: + return std::string(STR_INCDEC); + } + return std::string("---"); + }); + + modechoice->setSetValueHandler([=](int32_t newValue) { + CFN_GVAR_MODE(cfn) = newValue; + CFN_PARAM(cfn) = 0; + SET_DIRTY(); + updateSpecialFunctionOneWindow(); + }); + + switch (CFN_GVAR_MODE(cfn)) { + case FUNC_ADJUST_GVAR_CONSTANT: { + //TODO: label + int16_t val_min, val_max; + getMixSrcRange(CFN_GVAR_INDEX(cfn) + MIXSRC_FIRST_GVAR, val_min, + val_max); + new NumberEdit(specialFunctionOneWindow, grid.getFieldSlot(), + val_min, val_max, GET_SET_DEFAULT(CFN_PARAM(cfn))); + break; + } + case FUNC_ADJUST_GVAR_SOURCE: + //TODO: label + new SourceChoice(specialFunctionOneWindow, grid.getFieldSlot(), + 0, MIXSRC_LAST_CH, GET_SET_DEFAULT(CFN_PARAM(cfn))); + break; + case FUNC_ADJUST_GVAR_GVAR: { + auto gvarchoice = + new Choice(specialFunctionOneWindow, grid.getFieldSlot(), 0, + MAX_GVARS - 1, GET_SET_DEFAULT(CFN_PARAM(cfn))); + gvarchoice->setTextHandler([](int32_t value) { + return std::string(STR_GV) + std::to_string(value + 1); + }); + gvarchoice->setAvailableHandler([=](int value) { + return CFN_GVAR_INDEX(cfn) != value; + }); + break; + } + case FUNC_ADJUST_GVAR_INCDEC: { + int16_t val_min, val_max; + getMixSrcRange(CFN_GVAR_INDEX(cfn) + MIXSRC_FIRST_GVAR, val_min, val_max); + getGVarIncDecRange(val_min, val_max); + auto numedit = new NumberEdit(specialFunctionOneWindow, + grid.getFieldSlot(), val_min, val_max, + GET_SET_DEFAULT(CFN_PARAM(cfn))); + numedit->setDisplayHandler( + [](BitmapBuffer *dc, LcdFlags flags, int value) { + dc->drawNumber(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, abs(value), + flags, 0, value >= 0 ? "+= " : "-= ", nullptr); + }); + break; + } + } + grid.nextLine(); + } } if (HAS_ENABLE_PARAM(func)) { @@ -390,12 +476,18 @@ class SpecialFunctionButton : public Button dc->drawNumber(col2, line2, CFN_PARAM(cfn)); break; - case FUNC_TRAINER: - drawSource( - dc, col1, line2, - CFN_CH_INDEX(cfn) == 0 ? 0 : MIXSRC_Rud + CFN_CH_INDEX(cfn) - 1); + case FUNC_TRAINER: { + std::string text; + int16_t value = CFN_CH_INDEX(cfn); + if (value == 0) + text = std::string(STR_STICKS); + else if (value == NUM_STICKS + 1) + text = std::string(STR_CHANS); + else + text = TEXT_AT_INDEX(STR_VSRCRAW, value); + dc->drawText(col1, line2, text.c_str(), 0); break; - + } case FUNC_RESET: if (CFN_PARAM(cfn) < FUNC_RESET_PARAM_FIRST_TELEM) { dc->drawTextAtIndex(col1, line2, STR_VFSWRESET, CFN_PARAM(cfn)); @@ -450,6 +542,26 @@ class SpecialFunctionButton : public Button dc->drawNumber(col3, line1, CFN_PARAM(cfn), PREC1, sizeof(CFN_PARAM(cfn)), nullptr, "s"); break; + + case FUNC_ADJUST_GVAR: + switch(CFN_GVAR_MODE(cfn)) { + case FUNC_ADJUST_GVAR_CONSTANT: + dc->drawNumber(col1, line2, CFN_PARAM(cfn), 0); + break; + case FUNC_ADJUST_GVAR_SOURCE: + drawSource(dc, col1, line2, CFN_PARAM(cfn), 0); + break; + case FUNC_ADJUST_GVAR_GVAR: + drawSource(dc, col1, line2, CFN_PARAM(cfn) + MIXSRC_FIRST_GVAR, 0); + break; + case FUNC_ADJUST_GVAR_INCDEC: { + int16_t value = CFN_PARAM(cfn); + std::string text(value >= 0 ? "+= " : "-= "); + text += std::to_string(abs(value)); + dc->drawText(col1, line2, text.c_str()); + break; + } + } } if (HAS_ENABLE_PARAM(func)) { theme->drawCheckBox(dc, CFN_ACTIVE(cfn), col3, line2); diff --git a/radio/src/gui/colorlcd/widgets/modelbmp.cpp b/radio/src/gui/colorlcd/widgets/modelbmp.cpp index daf5977f7..3eee954d0 100644 --- a/radio/src/gui/colorlcd/widgets/modelbmp.cpp +++ b/radio/src/gui/colorlcd/widgets/modelbmp.cpp @@ -97,7 +97,12 @@ class ModelBitmapWidget: public Widget TRACE("could not load bitmap '%s'", filename.c_str()); return; } - buffer->drawScaledBitmap(bitmap.get(), 0, 38, width(), height() - 38); + + if (rect.h >= 96 && rect.w >= 120) { + buffer->drawScaledBitmap(bitmap.get(), 0, 38, width(), height() - 38); + } else { + buffer->drawScaledBitmap(bitmap.get(), 0, 0, width(), height()); + } } } }; diff --git a/radio/src/gui/colorlcd/widgets/value.cpp b/radio/src/gui/colorlcd/widgets/value.cpp index b79a19d89..6c8821a2a 100644 --- a/radio/src/gui/colorlcd/widgets/value.cpp +++ b/radio/src/gui/colorlcd/widgets/value.cpp @@ -26,10 +26,11 @@ const coord_t NUMBERS_PADDING = 4; class ValueWidget: public Widget { public: - ValueWidget(const WidgetFactory * factory, FormGroup * parent, const rect_t & rect, Widget::PersistentData * persistentData): - Widget(factory, parent, rect, persistentData) - { - } + ValueWidget(const WidgetFactory* factory, FormGroup* parent, + const rect_t& rect, Widget::PersistentData* persistentData) : + Widget(factory, parent, rect, persistentData) + { + } void refresh(BitmapBuffer * dc) override { @@ -37,7 +38,7 @@ class ValueWidget: public Widget mixsrc_t field = persistentData->options[0].value.unsignedValue; // get color from options[1] - lcdSetColor(persistentData->options[1].value.unsignedValue); + LcdFlags color = COLOR2FLAGS(persistentData->options[1].value.unsignedValue); coord_t xValue, yValue, xLabel, yLabel; LcdFlags attrValue, attrLabel = 0; @@ -55,7 +56,7 @@ class ValueWidget: public Widget yValue = -2; xLabel = NUMBERS_PADDING; yLabel = +2; - attrValue = RIGHT | NO_UNIT | FONT(XL); + attrValue = RIGHT | NO_UNIT | FONT(L); } else { xValue = NUMBERS_PADDING; @@ -64,7 +65,7 @@ class ValueWidget: public Widget yLabel = 2; if (field >= MIXSRC_FIRST_TELEM) { if (isGPSSensor(1 + (field - MIXSRC_FIRST_TELEM) / 3)) { - attrValue = LEFT | FONT(L) | EXPANDED; + attrValue = LEFT | FONT(L) | PREC1; } else { attrValue = LEFT | FONT(XL); @@ -72,7 +73,7 @@ class ValueWidget: public Widget } #if defined(INTERNAL_GPS) else if (field == MIXSRC_TX_GPS) { - attrValue = LEFT | FONT(L) | EXPANDED; + attrValue = LEFT | FONT(L) | PREC1; } #endif else { @@ -83,27 +84,32 @@ class ValueWidget: public Widget if (field >= MIXSRC_FIRST_TIMER && field <= MIXSRC_LAST_TIMER) { TimerState & timerState = timersStates[field - MIXSRC_FIRST_TIMER]; if (timerState.val < 0) { - lcdSetColor(lcdColorTable[ALARM_COLOR_INDEX]); + color = ALARM_COLOR; } - drawSource(dc, NUMBERS_PADDING, 2, field, CUSTOM_COLOR); - drawSource(dc, NUMBERS_PADDING + 1, 3, field, BLACK); - drawTimer(dc, xValue, yValue, abs(timerState.val), attrValue | FONT(XL) | CUSTOM_COLOR); + drawSource(dc, NUMBERS_PADDING, 2, field, color); + drawSource(dc, NUMBERS_PADDING + 1, 3, field, COLOR2FLAGS(BLACK)); + drawTimer(dc, xValue, yValue, abs(timerState.val), attrValue | FONT(XL) | color); } + if (field == MIXSRC_TX_TIME) { + drawTimer(dc, xValue, yValue, getValue(MIXSRC_TX_TIME), + attrValue | FONT(XL) | color); + } + if (field >= MIXSRC_FIRST_TELEM) { - TelemetryItem & telemetryItem = telemetryItems[(field - MIXSRC_FIRST_TELEM) / 3]; // TODO macro to convert a source to a telemetry index + TelemetryItem & telemetryItem = telemetryItems[(field - MIXSRC_FIRST_TELEM) / 3]; if (!telemetryItem.isAvailable() || telemetryItem.isOld()) { - lcdSetColor(lcdColorTable[TEXT_DISABLE_COLOR_INDEX]); + color = TEXT_DISABLE_COLOR; } } if (persistentData->options[2].value.boolValue) { - drawSource(dc,xLabel + 1, yLabel + 1, field, attrLabel | BLACK); - drawSourceValue(dc, xValue + 1, yValue + 1, field, attrValue | BLACK); + drawSource(dc,xLabel + 1, yLabel + 1, field, attrLabel | COLOR2FLAGS(BLACK)); + drawSourceValue(dc, xValue + 1, yValue + 1, field, attrValue | COLOR2FLAGS(BLACK)); } - drawSource(dc, xLabel, yLabel, field, attrLabel | CUSTOM_COLOR); - drawSourceValue(dc, xValue, yValue, field, attrValue | CUSTOM_COLOR); + drawSource(dc, xLabel, yLabel, field, attrLabel | color); + drawSourceValue(dc, xValue, yValue, field, attrValue | color); } void checkEvents() override diff --git a/radio/src/gui/colorlcd/widgets/widgets_container_impl.h b/radio/src/gui/colorlcd/widgets/widgets_container_impl.h index 0fb615c3a..9d2836781 100644 --- a/radio/src/gui/colorlcd/widgets/widgets_container_impl.h +++ b/radio/src/gui/colorlcd/widgets/widgets_container_impl.h @@ -43,10 +43,12 @@ class WidgetsContainerImpl: public WidgetsContainer // remove old one if existing removeWidget(index); - Widget * widget = nullptr; + Widget* widget = nullptr; if (factory) { - strncpy(persistentData->zones[index].widgetName, factory->getName(), sizeof(ZonePersistentData::widgetName)); - widget = factory->create(this, getZone(index), &persistentData->zones[index].widgetData); + strncpy(persistentData->zones[index].widgetName, factory->getName(), + sizeof(ZonePersistentData::widgetName)); + widget = factory->create(this, getZone(index), + &persistentData->zones[index].widgetData); } widgets[index] = widget; @@ -61,12 +63,16 @@ class WidgetsContainerImpl: public WidgetsContainer if (index >= N) return; - if (widgets[index]) + if (widgets[index]) { + removeField(widgets[index]); widgets[index]->deleteLater(); + } widgets[index] = nullptr; - memset(persistentData->zones[index].widgetName, 0, sizeof(ZonePersistentData::widgetName)); - memset(&persistentData->zones[index].widgetData, 0, sizeof(Widget::PersistentData)); + memset(persistentData->zones[index].widgetName, 0, + sizeof(ZonePersistentData::widgetName)); + memset(&persistentData->zones[index].widgetData, 0, + sizeof(Widget::PersistentData)); } Widget * getWidget(unsigned int index) override @@ -89,6 +95,7 @@ class WidgetsContainerImpl: public WidgetsContainer // remove old widget if (widgets[i]) { + removeField(widgets[i]); widgets[i]->deleteLater(); widgets[i] = nullptr; } diff --git a/radio/src/storage/conversions/conversions.cpp b/radio/src/storage/conversions/conversions.cpp index 7071b7540..0e474d1c4 100644 --- a/radio/src/storage/conversions/conversions.cpp +++ b/radio/src/storage/conversions/conversions.cpp @@ -59,6 +59,9 @@ void convertRadioData(int version) RAISE_ALERT(STR_STORAGE_WARNING, STR_SDCARD_CONVERSION_REQUIRE, NULL, AU_NONE); + // Load models list before converting + modelslist.load(); + unsigned converted = 0; auto to_convert = modelslist.getModelsCount() + 1; @@ -68,6 +71,8 @@ void convertRadioData(int version) #if STORAGE_CONVERSIONS < 220 if (version == 219) { convertRadioData_219_to_220(g_eeGeneral); + storageDirty(EE_GENERAL); + storageCheck(true); } #endif converted++; @@ -76,9 +81,6 @@ void convertRadioData(int version) RTOS_WAIT_MS(200); #endif - // Load models list before converting - modelslist.load(); - const char* error = nullptr; for (auto category_ptr : modelslist.getCategories()) { for (auto model_ptr : *category_ptr) { diff --git a/radio/src/storage/conversions/conversions_219_220.cpp b/radio/src/storage/conversions/conversions_219_220.cpp index 8c6d841f1..9fb21e390 100644 --- a/radio/src/storage/conversions/conversions_219_220.cpp +++ b/radio/src/storage/conversions/conversions_219_220.cpp @@ -109,7 +109,7 @@ void convertModelData_219_to_220(ModelData &model) convertToStr(model.header.name, LEN_MODEL_NAME_219); for (uint8_t i=0; i